2012-12-05 6 views

Antwort

12

Dieser Ansatz in Chrome/Safari funktioniert:

+function(){ 
 
    
 
    var ctx = new AudioContext() 
 
    , url = 'https://cf-media.sndcdn.com/OfjMZo27DlvH.128.mp3?Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiKjovL2NmLW1lZGlhLnNuZGNkbi5jb20vT2ZqTVpvMjdEbHZILjEyOC5tcDMiLCJDb25kaXRpb24iOnsiRGF0ZUxlc3NUaGFuIjp7IkFXUzpFcG9jaFRpbWUiOjE1MTUwNDM5Njd9fX1dfQ__&Signature=FfmL2qUssAKs3Z7EPoYo0Yq8-SAg8rKLPs65EasXwuVkfsOB4joFqeCvVR2elpaG-lJaV4hXpXFiRCDWXNOYyAtO4Oz~sexiPwIoSk8-jWiVbGQRS8TMmUmj7TJzxemMOIj7ugWJKk6PHsrUdgqs9woDpHzxmkGCzk6sfqJEIsdeZJ4rWUFAh4iGWn9M6b0xfzTgndAJmytkNj9raCpWCBVmdr5u-r9nt~q5uF1easNSW9oaFilM4s1Hq2ei~VJye8zW9bzvrGm8idVdy-tiPeMWAKcE8J2VuaS1Ret6jRTRaHTDuiNgA5sZvgTzNpEpKtWI7UmAWI5TrqNVSlxpgQ__&Key-Pair-Id=APKAJAGZ7VMH2PFPW6UQ' 
 
    , audio = new Audio(url) 
 
    // 2048 sample buffer, 1 channel in, 1 channel out 
 
    , processor = ctx.createScriptProcessor(2048, 1, 1) 
 
    , meter = document.getElementById('meter') 
 
    , source 
 
    
 
    audio.crossOrigin = 'anonymous' 
 

 
    audio.addEventListener('canplaythrough', function(){ 
 
    source = ctx.createMediaElementSource(audio) 
 
    source.connect(processor) 
 
    source.connect(ctx.destination) 
 
    processor.connect(ctx.destination) 
 
    audio.play() 
 
    }, false); 
 
    
 
    // loop through PCM data and calculate average 
 
    // volume for a given 2048 sample buffer 
 
    processor.onaudioprocess = function(evt){ 
 
    var input = evt.inputBuffer.getChannelData(0) 
 
     , len = input.length 
 
     , total = i = 0 
 
     , rms 
 
    while (i < len) total += Math.abs(input[i++]) 
 
    rms = Math.sqrt(total/len) 
 
    meter.style.width = (rms * 100) + '%' 
 
    } 
 
    
 
}()
#meter { 
 
    width: 0%; 
 
    height: 15px; 
 
    margin: 2px 0; 
 
    background: green; 
 
    -webkit-transition: width .05s; 
 
}
<div id="meter"></div>

Das wichtige Zeug passiert hier:

processor.onaudioprocess = function(evt){ 
    var input = evt.inputBuffer.getChannelData(0) 
    , len = input.length 
    , total = i = 0 
    , rms 
    while (i < len) total += Math.abs(input[i++]) 
    rms = Math.sqrt(total/len) 
    meter.style.width = (rms * 100) + '%' 
} 

Basic Sie greifen die rohen PCM-Daten (Werte von -1 bis 1) alle 2048 Samples auf und durchlaufen diese, um den durchschnittlichen Signalpegel über den gegebenen Zeitraum zu berechnen.

Sie können diesen Wert dann für Ihre Animationen verwenden.

Bearbeiten: Aktualisiert, um RMS zu verwenden, die wie Jason hingewiesen hat, ist eine aussagekräftigere Messung.

+0

ich einige Probleme, zu verstehen, wie das funktioniert. Ich verwende page-player.js und soundmanager2.js -> www.wave.cat – coiso

+0

Wäre kein [AnalysatorNode] (https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode) Sei viel besser für diese Aufgabe? –

+0

Vielleicht? Sie können es sicherlich profilieren und herausfinden. Zumindest ist es wahrscheinlich erwähnenswert, dass seit diesem Post der 'ScriptProcessorNode' zugunsten des' AudioWorkerNode' veraltet ist. –

9

Ja, Sie müssen die rohen PCM-Proben greifen (wie Kennis erwähnt). Um jedoch die Gesamtlautstärke zu berechnen, möchten Sie den RMS (Root Mean Square) der Werte ermitteln. Außerdem sollten Sie auf alle Kanäle im Stream achten, nicht nur auf den ersten Kanal (damit Sie beispielsweise den Lautstärkepegel für einen Stereo-Stream genau wiedergeben können).

Es gibt einige Tricks (stellen Sie sicher, dass Sie die Multiplikation der gleichen Samples über die Kanäle hinweg verwenden, nicht die Addition). Dann werden Sie sie alle zusammen hinzufügen (wieder wie Kennis). Wenn Sie eine tatsächliche Dezibel haben möchten, ist auch ein Protokollschritt erforderlich.

Es gibt ein Beispiel als answer to this other question.

Relevante Code:

var rms = Math.sqrt(sum/(_buffer.length/2)); 
var decibel = 20 * (Math.log(rms)/Math.log(10)); 
+0

Danke Jason. Sie haben völlig Recht mit RMS. Ich war faul. FWIW, mein Beispiel summiert tatsächlich den linken und rechten Kanal am Prozessorknoten (es sei denn, ich habe die Spezifikation falsch verstanden) - also sollten beide in der Summe dargestellt werden. –

+0

Ah cool! Danke Kevin :). Ich habe mir die Spezifikation nicht angesehen, also wäre ich nicht überrascht :). –