【发布时间】:2014-08-30 09:29:39
【问题描述】:
我正在使用录音机来录制声音并在安卓手机上进行一些伪实时处理。 我面临着 FFT 和音频信号卷积之间的问题: 我对已知信号(正弦波形)执行 FFT,通过使用 FFT,我总是正确地找到其中包含的单音。
现在我想通过使用卷积来做同样的事情(这是一个练习):我使用 5000 个过滤器对该信号执行 5000 次卷积。每个滤波器都是 0 到 5000 Hz 之间不同频率的正弦波形。 然后,我搜索每个卷积输出的峰值。通过这种方式,当我使用信号中包含相同音调的滤波器时,我应该找到最大峰值。
事实上,对于 2kHz 的音调,我可以使用 2kHz 滤波器找到最大值。
问题是,当我收到 4kHz 音调时,我发现使用 4200Hz 滤波器的卷积最大(而 FFT 总是可以正常工作) 物质上可能吗? 我的卷积有什么问题?
这是我写的卷积函数:
//i do the convolution and return the max
//IN is the array with the signal
//DATASIZE is the size of the array IN
//KERNEL is the filter containing the sine at the selected frequency
int convolveAndGetPeak(short[] in,int dataSize, double[] kernel) {
//per non rischiare l'overflow, il kernel deve avere un ampiezza massima pari a 1/10 del max
int i, j, k;
int kernelSize=kernel.length;
int tmpSignalAfterFilter=0;
double out;
// convolution from out[0] to out[kernelSize-2]
//iniziamo
for(i=0; i < kernelSize - 1; ++i)
{
out = 0; // init to 0 before sum
for(j = i, k = 0; j >= 0; --j, ++k)
out += in[j] * kernel[k];
if (Math.abs((int) out)>tmpSignalAfterFilter ){
tmpSignalAfterFilter=Math.abs((int) out);
}
}
// start convolution from out[kernelSize-1] to out[dataSize-1] (last)
//iniziamo da dove eravamo arrivati
for( ; i < dataSize; ++i)
{
out = 0; // initialize to 0 before accumulate
for(j = i, k = 0; k < kernelSize; --j, ++k)
out += in[j] * kernel[k];
if (Math.abs((int) out)>tmpSignalAfterFilter ){
tmpSignalAfterFilter=Math.abs((int) out);
}
}
return tmpSignalAfterFilter;
}
用作过滤器的内核是这样生成的:
//curFreq is the frequency of the filter in Hz
//kernelSamplesSize is the desired length of the filter (number of samples), for time precision reasons i'm using 20 samples length.
//sampleRate is the sampling frequency
double[] generateKernel(int curFreq,int kernelSamplesSize,int sampleRate){
double[] curKernel= new double[kernelSamplesSize] ;
for (int kernelIndex=0;kernelIndex<curKernel.length;kernelIndex++){
curKernel[kernelIndex]=Math.sin( (double)kernelIndex * ((double)(2*Math.PI) * (double)curFreq / (double)sampleRate)); //the part that makes this a sine wave....
}
return curKernel;
}
如果要尝试卷积,IN数组中包含的数据如下: http://www.tr3ma.com/Dati/signal.txt
注1:采样频率为44100Hz
注意 2:信号中包含的音调是单个 4kHz 音调(即使卷积具有 4200Hz 滤波器的最大峰值。
编辑:我还在 Excel 表上重复了测试。结果是相同的(当然,我使用的是相同的算法)并且算法在我看来是正确的...... 这是我准备的 excel 表,如果您喜欢使用 excel:http://www.tr3ma.com/Dati/convolutions.xlsm
【问题讨论】:
标签: android processing audio-recording convolution