所以,我不知道我是否错误地实现了这个,或者它是否是这种过滤器的一个特征;但是,我一直在尝试对音频信号应用峰值滤波器,但它并没有工作。 一些测试显示它没有过滤我选择的频率;但附近的值,其中一些是2的幂,因此,例如,过滤4KHz实际上过滤4096Hz。 这是过滤器(它来自http://dspguide.com/ch19/3.htm): SAMPLE_RATE是88 * 1024
class Coefficients {
double a0=0;
double a1=0;
double a2=0;
double twoCos2piFreq=0;
double b1=0;
double b2=0;
double K=0;
double R=0;
double rSquared=0;
public Coefficients(double freq, double bandwidth)
{
twoCos2piFreq=2*Math.cos(2*Math.PI*freq);
R=1-(3*bandwidth);
rSquared=R*R;
K=(1-(R*twoCos2piFreq)+rSquared)/(2-twoCos2piFreq);
b1=R*twoCos2piFreq;
b2=-rSquared;
}
// ----------------------------------------------------------------
// Source x, result y
// y[i]=a0*x[i] + a1*x[i-1] + a2*x[i-2] + b1*y[i-1] + b2*y[i-2]
private void recursiveFilter(float[] x, float[] y)
{
double x_2 = 0.0f; // delayed x, y samples
double x_1 = 0.0f;
double y_2 = 0.0f;
double y_1 = 0.0f;
for (int i = 0; i < x.length; ++i){
double xi=x[i];
double yi=a0*xi + a1*x_1 + a2*x_2 + b1*y_1 + b2*y_2;
x_2 = x_1; // shift delayed x, y samples
y_2 = y_1;
x_1 = xi;
y_1 = yi;
y[i] = (float)yi;
}
}
// ------------------------------------------------------------
public float[] filtered(float[] signal)
{
float[] result=new float[signal.length];
recursiveFilter(signal,result);
return result;
}
}
// ----------------------------------------------------------------
class BandPassCoefficients extends Coefficients
{
public BandPassCoefficients(double freq, double bandwidth)
{
super(freq/(double)SAMPLE_RATE,bandwidth/(double)SAMPLE_RATE);
a0=1-K;
a1=(K-R)*twoCos2piFreq;
a2=rSquared-K;
}
}
为了测试它,我用一个频率范围的正弦波填充缓冲区,一次一个,应用滤波器并测量结果中的最高振幅。 相当明显的代码,但在这里:
// ----------------------------------------------------------------
private void genTestSignal(float freq)
{
float[] leftSignal=createSinWaveBuffer(freq,ONE_SECOND);
float[] rightSignal=createSinWaveBuffer(freq,ONE_SECOND);
denormalise( leftSignal ,inputSignal, LEFT_CHANNEL);
denormalise(rightSignal,inputSignal,RIGHT_CHANNEL);
}
denormalise和normalize函数只是将交错的带符号16位值转换为单通道浮点数。 这样可以对信号的开始进行采样,以找到最大的绝对值:
private void findOptimalFreq(float[] signal, float freq)
{
float maxAmplitude=0;
int peak=0;
for(int i=(int)freq/2; i<(int)freq*3/2; i+=2){
BandPassCoefficients signalFilter=new BandPassCoefficients(i,10);
float[] normalised=signalFilter.filtered(signal);
float loudest=0;
// only scan the first part, since it's all the same
for(int j=1; j<10000; ++j){
float s=Math.abs(normalised[j]);
if(s>loudest) loudest=s;
}
if(loudest>maxAmplitude){
maxAmplitude=loudest;
peak=i;
}
}
log("freq,"+freq+","+peak);
}
并且,为了完成,跨越音频范围的代码,测试每个频率。
for(workingFreq=100; workingFreq<20000; workingFreq+=100){
genTestSignal(workingFreq);
inputShorts=new short[inputSignal.length/2];
ByteBuffer.wrap(inputSignal).order(bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(inputShorts);
findOptimalFreq(normalised(inputShorts,RIGHT_CHANNEL),workingFreq);
}
输出记录到System.out,并复制到电子表格,因为它是CSV格式。 其中一部分,左边是目标频率,右边是峰值的实际频率:
6200,6436
6300,6436
6400,6436
6500,6932
6600,6932
6700,6932
6800,6932
6900,6932
7000,7510
7100,7510
7200,7510
7300,7510
7400,7510
7500,7510
7600,8192
7700,8192
7800,8192
7900,8192
8000,8192
8100,8192
8200,9012
8300,9012
有什么想法? 我一遍又一遍地浏览过滤器代码,我确信它是正确的;但是,我在任何地方都没有提及过这种&#34;功能&#34;,所以我不知道下一步该怎么做。
答案 0 :(得分:0)
没有解决问题;但是能够用这个站点的BiQuadratic过滤器替换它:BiQuadDesigner
指向java source的链接:
HTH其他任何人都在努力解决这个问题。