web audio,createMediaElementSource变量源

时间:2014-03-09 15:33:40

标签: javascript html5 audio web-audio

让我说我不想拥有一个具有可变音频源的应用程序作为音频标签,如下所示:

<audio preload="auto" src="1.mp3" controls="" class="muzz"></audio>
<audio preload="auto" src="track.mp3" controls="" class="muzz"></audio>

根据播放的内容,应将其传递给createMediaElementSource,然后将声音发送到分析器,并使用它完成各种操作,但不起作用:

var trackName;
//get the source of clicked track
$(".muzz").on("play", function(){
    trackName = $(this).attr("src");
    console.log("got a source: ", trackName);
    audio = new Audio();
    audio.src=trackName;




    context = new AudioContext();
    analyser = context.createAnalyser();
    source = context.createMediaElementSource(audio);
    source.connect(analyser);
    analyser.connect(context.destination); 

    letsDraw();


});

控制台日志显示正确的源名称,letsDraw()方法应该绘制音频播放的频谱图:

function letsDraw(){
console.log("draw called");
window.requestAnimationFrame(letsDraw);
fbc_array = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(fbc_array); //get frequency from the analyser node
ctx.clearRect(0, 0, canvas.width, canvas.height);

ctx.fillStyle="white";
ctx.font = "bold 12px Arial";
ctx.fillText("currently playing:" + trackName, 10, 20);//this works

bars =  150;
for(var i = 0; i < analyser.frequencyBinCount; i++){ //but this doesn't


    /*fill the canvas*/
    x = i *2;
    barWidth = 1;
    barHeight = -(fbc_array[i]/1.8); 

    //colours react to the  frequency loudness
        hue = parseInt(500 * (1 - (barHeight / 200)), 10); 
            ctx.fillStyle = 'hsl(' + hue + ',75%,50%)';

    ctx.fillRect(x, canvas.height, barWidth, barHeight);

}

}

它可以正常使用一套音频源,但是因为可变来源而失败,任何想法都会非常受欢迎。

当然,控制台中根本没有任何错误。

2 个答案:

答案 0 :(得分:3)

在第一个代码块的顶部,试试这个:

var trackName,
  context = new AudioContext();

从点击处理程序中删除context = new AudioContext();

页面应该只有一个AudioContext。

答案 1 :(得分:3)

我没有得到的是为什么你把src放在一个新的Audio对象中,就像你已经拥有它们一样。

<audio>个标记创建源代码也更好。您只需创建一个在页面加载时运行的函数(因此,当页面上的所有内容都准备就绪时,您将无法获得有关尚未存在的元素的任何错误等。)

在我开始编写一段代码之前,您期望发生什么?是否可以同时播放两个标签,或者如果单击另一个播放则应该停止播放?如果它不应该同时播放,你最好制作一个<audio>标签并创建两个按钮,每个按钮设置标签的src。

您的代码的另一个问题是您已经拥有<audio>元素,并且当您希望它们播放时,您只需创建一个新的音频元素并将src附加到它。这背后的逻辑是什么?

编辑:

Here is an example使用只有一个<audio>元素的多个来源。

HTML代码应如下所示:

<audio id="player" src="" autoplay="" controls=""></audio>
<div id="buttons">
    <!--The javascript code will generate buttons with which you can play the audio-->
</div>

然后你使用这个JS代码:

onload = function () { //this will be executed when the page is ready
    window.audioFiles = ['track1.mp3', 'track2.mp3']; //this is gonna be the array with all file names
    window.player = document.getElementById('player');
    window.AudioContext = window.AudioContext || window.webkitAudioContext;
    context = new AudioContext();
    source = context.createMediaElementSource(player);
    analyser = context.createAnalyser();
    source.connect(analyser);
    analyser.connect(context.destination);

    //now we take all the files and create a button for every file
    for (var x in audioFiles) {
        var btn = document.createElement('button');
        btn.innerHTML = audioFiles[x];
        btn.onclick = function () {
            player.src = audioFiles[x];
            //so when the user clicks the button, the new source gets appended to the audio element
        }
        document.getElementById('buttons').appendChild(btn);
    }

}

希望评论解释得足够好

EDIT2:

您想知道如何为多个元素执行此操作。您要做的是在页面加载时创建所有音频元素,并为其创建所有源。这将减少开始播放音频时的混乱。代码为here

你需要做的就是拥有为你拥有的每个媒体文件运行的for循环,它将为相应的源创建一个音频元素,然后为它创建一个sourcenode(createMediaElementSource),并将该sourcenode连接到分析器。

我还想谈谈你的可视化代码。如果不覆盖字体,颜色或任何内容,则不需要执行每个动画帧。一旦初始化就足够了。