gpt4 book ai didi

android - 音频信号的卷积

转载 作者:行者123 更新时间:2023-11-29 00:17:31 24 4
gpt4 key购买 nike

我正在使用 audiorecorder 来录制声音并在 Android 手机上以伪实时方式进行一些处理。我面临 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

最佳答案

您通过两个因素改变带宽:

a) 内核的长度(例如,5ms 的长度 t 产生 f >= 200Hz 的粗略带宽,估计为 1/0.005,因为 Δt·Δf >= 1,参见“Heisenberg”),以及

b) 窗口函数(你绝对应该实现它以使你的算法在实际应用中工作,否则在某些情况下某些滤波器输出的旁瓣可能产生比预期滤波器输出的主瓣更多的能量)。

但您还有另一个问题:您需要与由余弦波组成的第二个内核进行卷积(这意味着您需要与第一个内核相同的波,但偏移了 90 度)。这是为什么?因为仅使用正弦核,您可以获得滤波器输出的相位相关调制(例如,如果输入信号与具有相同频率的核波之间的相位差为 90 度,您将获得振幅 0)。

最后,您将两个内核的输出与毕达哥拉斯结合起来。

关于android - 音频信号的卷积,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25580934/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com