2013-02-19 119 views
2

我正在尝试为HTML5音频创建一个图形均衡器类型可视化 - Chrome仅在此时使用webkitAudioContext。HTML5音频API - “AudioContext构造不可用的音频资源”

当我尝试更改音频的来源即播放不同的歌曲时,我发现了不寻常的和不可预知的行为。我读的地方,我应该等到音频的“canplay”事件将其连接到上下文/分析仪之前触发:

var context, sourceNode, analyser, javascriptNode, audio; 

var ctx = $("#songcanvas").get()[0].getContext("2d");  


function loadSong(url) { 
    if (audio!=undefined) { audio.pause(); } 
    audio = new Audio(); 
    audio.src = url; 
    audio.addEventListener("canplay", function(e) { 
     setupAudioNodes(); 
    }, false); 
} 

function setupAudioNodes() { 
     context = new webkitAudioContext(); 
     javascriptNode = context.createJavaScriptNode(2048, 1, 1); 
     javascriptNode.connect(context.destination); 

     analyser = context.createAnalyser(); 
     analyser.smoothingTimeConstant = 0.3; 
     analyser.fftSize = 512; 

     sourceNode = context.createMediaElementSource(audio); 
     sourceNode.connect(analyser); 
     analyser.connect(javascriptNode); 

     sourceNode.connect(context.destination); 

     javascriptNode.onaudioprocess = function() { 
      var array = new Uint8Array(analyser.frequencyBinCount); 
      analyser.getByteFrequencyData(array); 
      ctx.clearRect(0, 0, 1000, 325); 
      ctx.fillStyle="rgba(32, 45, 21,1)"; 
      drawSpectrum(array); 
     } 
     audio.play(); 
} 

function drawSpectrum(array) { 
    for (var i = 0; i < (array.length); i++){ 
     var value = array[i]; 
     ctx.fillRect(i*5,325-value,3,325); 
    } 
}; 

前三四次我更改信号源,它的工作原理,然后最终失败与“未捕获的SyntaxError:为AudioContext建设不可用音频资源”

这里充分http://jsfiddle.net/eAgQN/

回答

7

演示中,我建议你从创建JavaScriptNode如果你只是简单的将要绘图光谱避而远之。相反,请尝试使用​​方法,因为它可以节省CPU周期,并使您更接近恒定的60fps(如果您的窗口/选项卡位于后台,则特别有用,因为包装在​​中的任何函数都将等待窗口再次对焦在射击之前)。

您可能得到该错误的原因是因为A)每个窗口只能创建一个单独的AudioContext B)当您完成使用时,您应该断开MediaElementSource C)您也应该也删除实际的Audio元素。

下面是与我上面列出的变化您的演示:http://jsbin.com/acolet/1/

window.AudioContext = window.AudioContext || window.webkitAudioContext; 
 
var context = new AudioContext(), 
 
    audioAnimation, sourceNode, analyser, audio, 
 
    songs = document.getElementById('songs'), 
 
    canvas = document.getElementById('songcanvas'), 
 
    WIDTH = canvas.width, 
 
    HEIGHT = canvas.height, 
 
    // get the context from the canvas to draw on 
 
    ctx = canvas.getContext('2d'), 
 
    gradient = ctx.createLinearGradient(0, 0, 0, HEIGHT), 
 
    bar = { width: 2, gap: 2, ratio: HEIGHT/256 }; 
 

 
gradient.addColorStop(1.00,'#000000'); 
 
gradient.addColorStop(0.75,'#ff0000'); 
 
gradient.addColorStop(0.25,'#ffff00'); 
 
gradient.addColorStop(0.00,'#ffff00'); 
 
ctx.fillStyle = gradient; 
 

 
songs.addEventListener('click', loadSong, false); 
 

 
function loadSong(e) { 
 
    e.preventDefault(); 
 
    var url = e.target.href; 
 
    if (!url) return false; 
 
    if (audio) audio.remove(); 
 
    if (sourceNode) sourceNode.disconnect(); 
 
    cancelAnimationFrame(audioAnimation); 
 
    audio = new Audio(); 
 
    audio.src = url; 
 
    audio.addEventListener('canplay', setupAudioNodes, false); 
 
} 
 

 
function setupAudioNodes() { 
 
    analyser = (analyser || context.createAnalyser()); 
 
    analyser.smoothingTimeConstant = 0.8; 
 
    analyser.fftSize = 512; 
 

 
    sourceNode = context.createMediaElementSource(audio); 
 
    sourceNode.connect(analyser); 
 
    sourceNode.connect(context.destination); 
 
    
 
    audio.play(); 
 
    drawSpectrum(); 
 
} 
 

 
function drawSpectrum() { 
 
    var freq = new Uint8Array(analyser.frequencyBinCount); 
 
    analyser.getByteFrequencyData(freq); 
 
    ctx.clearRect(0, 0, WIDTH, HEIGHT); 
 
    audioAnimation = requestAnimationFrame(drawSpectrum); 
 
    for (var i = freq.length - 1; i >= 0 ; i--){ 
 
    var x = i * (bar.width + bar.gap); 
 
    var y = HEIGHT - (freq[i] * bar.ratio); 
 
    ctx.fillRect(x, y, bar.width, HEIGHT); 
 
    } 
 
}
body { font-family: sans-serif; background-color: #000; } 
 
a { color: #fff; text-decoration: none; } 
 
ul { padding: 20px 0; width: 100px; } 
 
ul, canvas { float: left; }
<ul id="songs"> 
 
    <li><a class="song" href="http://upload.wikimedia.org/wikipedia/en/4/45/ACDC_-_Back_In_Black-sample.ogg">ACDC</a></li> 
 
    <li><a class="song" href="http://upload.wikimedia.org/wikipedia/en/9/9f/Sample_of_%22Another_Day_in_Paradise%22.ogg">Phil Collins</a></li> 
 
    <li><a class="song" href="http://upload.wikimedia.org/wikipedia/en/1/1f/%22Layla%22%2C_Derek_and_the_Dominos_song_%28sample%29.ogg">Clapton</a></li> 
 
</ul> 
 
<canvas id="songcanvas" width="400" height="128"></canvas>

+0

伟大的工作。谢谢。 – user888734 2013-02-19 17:23:28