问题描述
我使用一个树莓派的node.js引导一些仪器。我想有一个特定信号的话筒听,说,在500 Hz的音调,当它听到触发一个事件。
I'm using node.js on a Raspberry Pi to steer some instruments. I would like to have a mic listening for a specific signal, say a tone at 500 Hz, and trigger an event when it is heard.
说完看着多的Node.js库,节点核心音频()是最接近的一个,但它编译失败。
Having looked at multiple node.js libraries, node-core-audio (https://www.npmjs.com/package/node-core-audio) is the one that comes closest, but it fails on compilation.
任何人都可以推荐一个好办法做到这一点?
Can anybody recommend a good way to do this?
推荐答案
只是用傅立叶的某些部分变换你感兴趣的频率。
Just use some parts of the Fourier transform for the frequency you are interested in.
标量具有两个500赫兹音调乘以你输入信号偏移四分之一波长和总均方根(RMS)的一个,这意味着,在缩放具有n ^矢量-½。
Scalar multiply your input signal with two 500 Hz tones shifted one quarter of a wavelength and with a total root mean square (RMS) of one, which means that you scale the vector with 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);
}
标量乘的信号输入与两个矢量。
Scalar multiply the signal input with the two vectors.
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);
}
您可以将此值与噪音,否则也可以用findTone()被检测到的信号(取所有样本在区间的RMS)的总幅度进行比较。
You may want to compare this value with the total amplitude of the signal (take the RMS of all samples in the interval) otherwise noise can also be detected with 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)。
So the detection you want is probably some minimum value of the quota findTone(inputSamples)/noiseLevel(inputSamples).
如果你使用太多的样本算法会非常precise,也许更多的precise比你想,如果你有一个偏见或嘈杂的500 Hz的输入信号。然后带通滤波器是一种替代
If you use too many samples the algorithm will be very precise and maybe more precise than you wish if you have a biased or noisy 500 Hz input signal. Then a band pass filter is an alternative.
这是CPU周期的浪费使用FFT,如果你只想要一个或光谱的一些少数部分和FFT既允许任意频率,也不随意抽样集。
It is a waste of CPU cycles to use FFT if you only want one or some few parts of a spectrum and FFT neither allows arbitrary frequencies nor arbitrary sampling sets.
这篇关于从node.js的麦克风检测音频的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!