使用node.js从麦克风检测音频

Mor*_*ten 3 javascript audio fft node.js

我在Raspberry Pi上使用node.js来控制一些乐器.我想要一个麦克风听一个特定的信号,比如一个500赫兹的音调,并在听到它时触发一个事件.

在查看了多个node.js库之后,node-core-audio(https://www.npmjs.com/package/node-core-audio)是最接近的库,但在编译时失败了.

任何人都可以推荐一个好方法吗?

Dav*_*son 5

只需使用傅里叶变换的某些部分即可获得您感兴趣的频率.

标量将输入信号乘以四个波长四分之一的500 Hz音调,总均方根(RMS)为1,这意味着您可以使用n ^-½缩放矢量.

var sampleSize = 2000;
var sampleRate = 44100; // Or whatever in use (Hz)
var tone = 500; // tone to detect in Hz
var sin500Hz = Array(sampleSize);
var cos500Hz = Array(sampleSize);
for (var i = 0; i < sampleSize; i++) {
  sin500Hz[i] = Math.sin(2*Math.PI*tone/sampleRate*i)/Math.sqrt(sampleSize); 
  cos500Hz[i] = Math.cos(2*Math.PI*tone/sampleRate*i)/Math.sqrt(sampleSize); 
}
Run Code Online (Sandbox Code Playgroud)

标量将信号输入与两个向量相乘.

function findTone(inputSamples) {
  var amplitudeSin = 0;
  var amplitudeCos = 0;
  for (var i = 0; i < sampleSize; i++) {
    amplitudeSin += inputSamples[i]*sin500Hz[i]; 
    amplitudeCos += inputSamples[i]*cos500Hz[i]; 
  }
  return Math.sqrt(amplitudeSin*amplitudeSin + amplitudeCos*amplitudeCos); 
}
Run Code Online (Sandbox Code Playgroud)

您可能希望将此值与信号的总振幅进行比较(获取区间中所有采样的RMS),否则也可以使用findTone()检测噪声.

function noiseLevel(inputSamples) {
  var power = 0;
  var average = 0;
  for (var i = 0; i < sampleSize; i++) {
    average += inputSamples[i]; 
  }
  average /= sampleSize;
  for (var i = 0; i < sampleSize; i++) {
    power += Math.pow(inputSamples[i] - average, 2); 
  }
  return Math.sqrt(power); 
}
Run Code Online (Sandbox Code Playgroud)

因此,您想要的检测可能是配额findTone(inputSamples)/ noiseLevel(inputSamples)的最小值.

如果您使用太多样本,则算法将非常精确,并且如果您具有偏置或嘈杂的500 Hz输入信号,则可能比您希望的更精确.然后带通滤波器是另一种选择.

如果您只需要频谱的一个或几个部分,并且FFT既不允许任意频率也不允许任意采样集,则使用FFT会浪费CPU周期.