AnalyserNode.getFloatFrequencyData () возвращает отрицательные значения. - PullRequest
0 голосов
/ 29 мая 2020

Я пытаюсь получить громкость микрофонного входа с помощью API веб-аудио, используя AnalyserNode.getFloatFrequencyData().

spe c утверждает, что «каждый элемент в массиве представляет значение в децибелах для определенной c частоты», но возвращает только отрицательные значения, хотя они выглядят так, как будто они реагируют на уровень звука. - свисток вернет значение около -23 и тишина около -80 (значения в dataArray также все отрицательные, поэтому я не думаю, что это связано с тем, как я их сложил). Тот же код дает значения, которые я ожидал (положительные) с AnalyserNode.getByeFrequencyData(), но возвращенные значения в децибелах были нормализованы между 0–255, поэтому сложнее сложить для определения общей громкости.

Почему я не получаю ожидаемые значения? И / или это, возможно, не лучший способ получить громкость микрофонного входа в первую очередь?

function getVolume(analyser) {
  analyser.fftSize = 32; 
  let bufferLength = analyser.frequencyBinCount;
  let dataArray = new Float32Array(bufferLength);
  analyser.getFloatFrequencyData(dataArray);
  let totalAntilogAmplitude = 0;
  for (let i = 0; i < bufferLength; i++) {
    let thisAmp = dataArray[i]; // amplitude of current bin
      let thisAmpAntilog = Math.pow(10, (thisAmp / 10)) // antilog amplitude for adding
      totalAntilogAmplitude = totalAntilogAmplitude + thisAmpAntilog; 
  }
  let amplitude = 10 * Math.log10(totalAntilogAmplitude);
  return amplitude;
}

1 Ответ

0 голосов
/ 29 мая 2020

Ваш код выглядит правильно. Но без примера трудно сказать, дает ли он ожидаемые вами значения. Кроме того, поскольку вы просто вычисляете (в основном) сумму всех значений коэффициентов преобразования, вы только что выполнили более дорогую версию суммирования квадратов сигнала временной области.

Еще одна альтернатива возводит сигнал в квадрат, немного фильтрует его для сглаживания вариаций и получает выходное значение в разное время. Что-то вроде следующего, где s - это узел, имеющий интересующий вас сигнал.

let g = new GainNode(context, {gain: 0});
s.connect(g);
s.connect(g.gain);
// Output of g is now the square of s

let f = new BiquadFilterNode(context, {frequency: 10});
// May want to adjust the frequency some to other value for your needs.
// I arbitrarily chose 10 Hz.
g.connect(f).connect(analyser)

// Now get the time-domain value from the analyser and just take the first 
// value from the signal.  This is the energy of the signal and represents 
// the volume.
...