Подтвердить что ты не робот

Интерпретация результатов веб-аудио API FFT

В Web Audio API есть анализатор node, который позволяет вам получать данные FFT на аудио, с которым вы работаете, и имеет байты и плавающие способы получения данных. Байт-версия имеет немного смысл, возвращая то, что выглядит как нормализованный (в зависимости от значений min и max decibel) спектр интенсивности, при котором 0 не является компонентом звука в конкретном ящике частоты, а 255 - максимальным.

Но я хотел бы получить более подробную информацию, чем 8 бит, но с использованием версии с плавающей запятой дает странные результаты.

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

Это дает мне значения между -891.048828125 и 0. -891, что соответствует тишине, поэтому оно как-то минимальное значение, пока я угадываю 0, эквивалентно максимальному значению.

Что происходит? Почему -891.048828125 значителен? Почему большой отрицательный тишина и нуль являются максимальными? Я использую неправильный FloatArray или есть неправильная конфигурация? Float64 дает 0 значений.

4b9b3361

Ответ 1

Поскольку, как представляется, существует нулевая документация по фактическим представлениям данных, я просмотрел соответствующий исходный код webkit: RealtimeAnalyser.cpp

Короткий ответ: subtract analyser.minDecibels от каждого значения Float32Array для получения положительных чисел и умножения с (analyser.maxDecibels - analyser.minDecibels), чтобы получить аналогичное представление, как с getByteFrequencyData, только с больше разрешения.

Длинный ответ:

Оба метода getByteFrequencyData и getFloatFrequencyData дают вам величину в децибелах. Он просто масштабируется по-разному, и для getByteFrequencyData вычитается константа minDecibels:

Соответствующий код в webkit для 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;

Соответствующий код в webkit для getFloatFrequencyData:

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

Итак, чтобы получить положительные значения, вы можете просто вычесть minDecibels самостоятельно, который отображается в анализаторе node:

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

Еще одна деталь заключается в том, что по умолчанию анализатор node выполняет сглаживание времени, что можно отключить, установив сглаживаниеTimeConstant в ноль.

Значения по умолчанию в webkit:

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

К сожалению, хотя анализатор node вычисляет комплекс fft, он не дает доступа к комплексным представлениям, а только его значениям.

Ответ 2

Вы правильно используете Float32Array. Я нашел интересный учебник по использованию API аудиоданных, который, хотя он отличается от API веб-аудио, дал мне некоторое полезное представление о том, что вы пытаетесь сделать . Я быстро посмотрел, почему цифры отрицательные, и не заметил ничего очевидного, но я задавался вопросом, могут ли эти цифры быть в децибелах, dB, которое обычно дается в отрицательных числах, а ноль - пик. Единственная проблема с этой теорией заключается в том, что -891, по-видимому, действительно небольшое число для дБ.

Ответ 3

Исправьте обе точки в предыдущем ответе и комментариях - числа в децибелах, поэтому 0 - макс, а -infinity - min (абсолютная тишина). -891.0... это, я считаю, просто странность с плавающей точкой.