2013-02-19 53 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