2015-08-07 28 views
6

Próbuję zmierzyć różnicę między dwoma dźwiękami za pomocą węzła analizatora i getByteFrequencyData(). Pomyślałem, że podsumowując różnicę w każdym polu częstotliwości, wymyślę jedną liczbę, która będzie reprezentować, jak różne są te dwa dźwięki. Wtedy będę w stanie zmienić dźwięki i zmierzyć liczby ponownie, aby sprawdzić, czy nowy dźwięk był mniej lub bardziej inny niż wcześniej.Jak mierzyć różnicę między dwoma dźwiękami za pomocą interfejsu Web Audio API?

Czy funkcja getByteFrequencyData() w pełni obejmuje reprezentację dźwięku lub czy muszę uwzględnić inne fragmenty danych, aby zakwalifikować dźwięk?

Oto kod używam:

var Spectrogram = (function(){ 
    function Spectrogram(ctx) { 
     this.analyser = ctx.createAnalyser(); 
     this.analyser.fftSize = 2048; 
     this.sampleRate = 512; 

     this.scriptNode = ctx.createScriptProcessor(this.sampleRate, 1, 1); 
     this.scriptNode.onaudioprocess = this.process.bind(this); 

     this.analyser.connect(this.scriptNode); 

     this.startNode = this.analyser; 
     this.endNode = this.scriptNode; 

     this.data = []; 
    } 

    Spectrogram.prototype.process = function(e) { 
     var d = new Uint8Array(this.analyser.frequencyBinCount); 
     this.analyser.getByteFrequencyData(d); 
     this.data.push(d); 

     var inputBuffer = e.inputBuffer; 
     var outputBuffer = e.outputBuffer; 
     for(var channel = 0; channel < outputBuffer.numberOfChannels; channel++) { 
      var inputData = inputBuffer.getChannelData(channel); 
      var outputData = outputBuffer.getChannelData(channel); 
      for(var sample = 0; sample < inputBuffer.length; sample++) { 
       outputData[sample] = inputData[sample]; 
      } 
     } 
    }; 

    Spectrogram.prototype.compare = function(other) { 
     var fitness = 0; 
     for(var i=0; i<this.data.length; i++) { 
      if(other.data[i]) { 
       for(var k=0; k<this.data[i].length; k++) { 
        fitness += Math.abs(this.data[i][k] - other.data[i][k]); 
       } 
      } 
     } 
     return fitness; 
    } 

    return Spectrogram; 
})(); 
+1

Musisz zastanowić się, co to dla Ciebie oznacza, aby dźwięki były inne. Z pewnością 'getByteFrequencyData' reprezentuje dźwięk w pewien sposób, ale nie wiem, czy przechwytuje to, co chcesz. Zastanów się, czy masz dźwięk. Teraz zmniejsz amplitudę o współczynnik 2. Czy dźwięki są takie same? Czy powinny być uważane za te same dźwięki? Musisz zdefiniować, co to znaczy być "tym samym", zanim będziesz mógł wymyślić algorytm, który ci powiem. –

+0

Domyślam się, że dźwięki brzmią tak samo, jak w ludzkim uchu. Tak więc amplituda byłaby częścią równania. Na węzłach analizatora istnieje również getByteTimeDomainData(), który opis to "aktualna domena czasu lub kształt fali", która obejmowałaby amplitudę? – zorqy

+0

Tak, zawiera informacje o amplitudzie. Ale prawdopodobnie chcesz użyć 'getFloatTimeDomainData' zamiast' getByteTimeDomainData'. –

Odpowiedz

1

Można użyć funkcji spectralFlux dostarczone przez pakiet Meyda porównanie dwóch sygnałów. Przepływ spektralny jest, zgodnie z wikipedią, "zwykle obliczany jako 2-norma (znana również jako odległość euklidesowa) pomiędzy dwoma znormalizowanymi widmami".

Po runninng npm install --save meyda, byś zrobił coś takiego:

const spectralFlux = require('meyda/src/extractors/spectralFlux'); 

const difference = spectralFlux({ 
    signal: [your first signal], 
    previousSignal: [your second signal] 
}); 

Zapraszam po prostu skopiować kod z here tak, że nie trzeba obsłużyć zależność, kodzie jest odpowiednio licencjonowany.

Powoduje zwrócenie współczynnika "dźwięków" obu sygnałów. Możesz to zrobić w dziedzinie czasu lub w dziedzinie częstotliwości. Dostaniesz różne liczby, ale oba będą korelować z tym, jak "różne" dźwięki są od siebie nawzajem.

Ale "różnica" może nie opisywać różnic wystarczająco dokładnie dla twojego przypadku użycia. Na przykład, możesz bardzo dbać o różnice w objętości, a nie o różnice między kolorami, ale metryka strumienia spektralnego nie bierze tego pod uwagę. Możesz najpierw uruchomić każdy sygnał za pomocą ekstraktorów elementów, znaleźć inne statystyki dotyczące ich właściwości, takie jak ich objętość percepcyjna, jasność itp., A następnie wziąć ważoną odległość euklidesową między tymi danymi, co zapewni bardziej dopasowaną metrykę "różnicową". do tego, czego potrzebujesz do swojego celu.

Zadowoleni z dalszego opracowania, ale jest to już dość długo na odpowiedź WR.

+0

Dzięki za wskazanie twojego projektu na github! Wygląda naprawdę użytecznie. Czy planujesz dodać więcej narzędzi do porównywania dźwięku? –

+0

@JustusRomijn Cieszę się, że mogę dodać cokolwiek, co byłoby przydatne :) –