2013-01-05 14 views
25

L'API Web Audio ha un nodo dell'analizzatore che consente di ottenere dati FFT sull'audio con cui si sta lavorando e ha modi byte e variabili per ottenere i dati. La versione di byte ha un po 'di senso, restituendo quello che sembra uno spettro di intensità normalizzato (in base ai valori di decibel minimo e massimo) con 0 che non è un componente dell'audio in uno specifico scomparto di frequenza e 255 è il massimo.Interpretazione dei risultati FFT dell'API Web

Ma mi piacerebbe un po 'più di dettaglio di 8 bit, tuttavia la versione float fornisce risultati strani.

freqData = new Float32Array(analyser.frequencyBinCount); 
analyser.getFloatFrequencyData(freqData); 

Questo mi dà valori compresi tra -891,048828125 e 0. -891 si presenta corrispondente al silenzio, quindi è in qualche modo il valore minimo, mentre io sto indovinando 0 è equivalente al valore massimo.

Cosa sta succedendo? Perché è significativo il -891.048828125? Perché un grande negativo è il silenzio e lo zero è massimo? Sto usando il FloatArray sbagliato o c'è una configurazione errata? Float64 fornisce 0 valori.

risposta

29

Dal momento sembra che ci sia la documentazione a zero su ciò che rappresenta in realtà i dati, ho guardato nel codice sorgente rilevante di WebKit: RealtimeAnalyser.cpp

Risposta breve: sottrarre analyser.minDecibels da ogni valore della Float32Array per ottenere numeri positivi e moltiplicare con (analyser.maxDecibels - analyser.minDecibels) per ottenere una rappresentazione simile a getByteFrequencyData, solo con più risoluzione.

Risposta lunga:

Sia getByteFrequencyData e getFloatFrequencyData ti danno la grandezza in decibel. E 'solo in scala in modo diverso e per getByteFrequencyData una costante minDecibels viene sottratto:

relativo codice in WebKit per getByteFrequencyData:

const double rangeScaleFactor = m_maxDecibels == m_minDecibels ? 1 : 1/(m_maxDecibels - m_minDecibels); 
float linearValue = source[i]; 
double dbMag = !linearValue ? minDecibels : AudioUtilities::linearToDecibels(linearValue); 

// The range m_minDecibels to m_maxDecibels will be scaled to byte values from 0 to UCHAR_MAX. 
double scaledValue = UCHAR_MAX * (dbMag - minDecibels) * rangeScaleFactor; 

relativo codice in WebKit per getFloatFrequencyData:

float linearValue = source[i]; 
double dbMag = !linearValue ? minDecibels : AudioUtilities::linearToDecibels(linearValue); 
destination[i] = float(dbMag); 

Quindi, per ottenere positivi valori, puoi semplicemente sottrarre minDecibels te stesso, che viene esposto nello analyzer node:

//The minimum power value in the scaling range for the FFT analysis data for conversion to unsigned byte values. 
attribute double minDecibels; 

Un altro dettaglio è che per impostazione predefinita, il nodo dell'analizzatore esegue il livellamento del tempo, che può essere disabilitato impostando smoothingTimeConstant su zero.

I valori standard webkit sono:

const double RealtimeAnalyser::DefaultSmoothingTimeConstant = 0.8; 
const double RealtimeAnalyser::DefaultMinDecibels = -100; 
const double RealtimeAnalyser::DefaultMaxDecibels = -30; 

Purtroppo, anche se il nodo analizzatore calcola una FFT complessa, che non consente l'accesso alle rappresentazioni complesse, solo le grandezze di esso.

+1

Sottraendo minDecibels dal valore float, a volte non ottengo numeri positivi. L'impostazione del valore minDecibels in realtà non limita nulla nel mio caso, continuo a ottenere valori più piccoli. qualche idea? – nevos

2

Si sta utilizzando correttamente un Float32Array. Ho trovato un interessante tutorial sull'utilizzo dell'API Audio Data, che sebbene sia diverso dall'API Web Audio, mi ha fornito alcune informazioni utili su cosa stai cercando di fare here. Ho avuto una rapida occhiata per vedere perché i numeri sono negativi e non ho notato nulla di ovvio, ma mi sono chiesto se questi numeri potrebbero essere in decibel, dB, che comunemente è dato in numeri negativi, e zero è il picco. L'unico problema con questa teoria è che -891 sembra essere un numero veramente piccolo per dB.

+1

Quel tutorial è per l'implementazione di Moz deprecata prima che venisse fuori lo standard, provato anche a guardarlo! Penso che tu abbia ragione in realtà. I float possono diventare molto piccoli e -891 è abbastanza vicino a 2^-128 in db che sembra giusto per ciò che i float possono memorizzare. – Newmu

+0

If I do ln (2^-128), ottengo -88.7 su un calcolatore HP15c (emulato sul mio mac). Non riesco a immaginare nessuna apparecchiatura audio in grado di avere il minimo rumore (-891 db). Hmmm –

+0

È digitale, quindi il rumore di fondo può essere difficile 0 e non avere il rumore analogico che lo mantiene più alto, immagino. Db è 10 * ln (x) non ln (x). È molto più esattamente 2^-128,55. Convertendo di nuovo i valori decimali assumendo che fosse db mi ha dato dati sensibili come quelli che ho visto da fft prima, se solo ridimensionati in modo diverso. – Newmu

2

Corretto su entrambi i punti nella risposta e nei commenti precedenti: i numeri sono in decibel, quindi 0 è max e -infinity è min (silenzio assoluto). -891.0 ... è, credo, solo una stranezza di conversione in virgola mobile.