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

时间:2015-03-23 16:34:46

标签: javascript node.js audio fft

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

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

有人可以推荐一个好方法吗?

2 个答案:

答案 0 :(得分: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); 
}

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

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); 
}

您可能希望将此值与信号的总振幅进行比较(取区间内所有采样的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); 
}

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

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

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

答案 1 :(得分:1)

只是一个单挑,我也遇到过这个问题,但无法找到答案。我继续制作2个NPM模块,1个包装&#34; sndpeek&#34; (一个开源音频分析库)和另一个用该包装模块检测音调的音频; https://www.npmjs.com/package/whistle-detection

太糟糕了,我无法让sndpeek应用程序在我的覆盆子pi上运行,但这些节点应用程序在我的Linux(ubuntu 15.04)和Windows 7机器上运行良好。