2012-12-05 7 views

Odpowiedz

12

Podejście to będzie działać w Chrome/Safari:

+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>

Ważne informacje:

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) + '%' 
} 

Podstawowy sprzymierzając się, pobierasz nieprzetworzone dane PCM (wartości od -1 do 1) co 2048 próbek i przeglądasz je, obliczając średni poziom sygnału w danym okresie czasu.

Możesz następnie użyć tej wartości do animacji.

Edytuj:Zaktualizowany do użycia RMS, który, jak wskazał Jason, jest bardziej znaczącym pomiarem.

+0

Mam pewne kłopoty ze zrozumieniem, jak to działa. Używam page-player.js i soundmanager2.js -> www.wave.cat – coiso

+0

Nie byłby to [AnalyserNode] (https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode) być znacznie lepszym do tego zadania? –

+0

Może? Z pewnością możesz go profilować i dowiedzieć się na pewno. Przynajmniej warto wspomnieć, że od tego wpisu 'ScriptProcessorNode' został przestarzały na rzecz' AudioWorkerNode'. –

9

Tak, musisz pobrać surowe próbki PCM (jak wspomina Kennis). Jednak, aby obliczyć całkowity poziom głośności, chcesz pobrać RMS (główny średni kwadrat) wartości. Ponadto prawdopodobnie będziesz chciał zwrócić uwagę na wszystkie kanały w strumieniu, a nie tylko na pierwszy kanał (możesz więc dokładnie odzwierciedlić poziom głośności dla strumienia stereo na przykład).

Istnieje kilka trików (upewnij się, że używasz mnożenia tych samych próbek w różnych kanałach, a nie dodawania). Wtedy dodamy je wszystkie razem (tak jak robi to Kennis). Jeśli chcesz mieć rzeczywisty decybel, wymagany jest również krok logowania.

Istnieje przykład jako answer to this other question.

odpowiedni kod:

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

Dzięki Jason. Masz całkowitą rację, jeśli chodzi o używanie RMS. Byłem leniwy. FWIW, mój przykład faktycznie sumuje lewy i prawy kanał w węźle procesora (chyba że źle zrozumiałem specyfikację) - więc oba powinny być reprezentowane w sumie. –

+0

Ah cool! Dzięki Kevin :). Nie patrzyłem na specyfikację, więc nie byłbym zaskoczony :). –

Powiązane problemy