我正在尝试从wav文件中提取频率,但看起来出现了问题。
首先,我从文件中提取字节,然后在其上应用FFT,最后找到幅度。
似乎我做错了,因为输出不接近实际价值。 以下是代码。
try{
File log = new File("files/log.txt");
if(!log.exists()) log.createNewFile();
PrintStream ps = new PrintStream(log);
File f = new File("files/5000.wav");
FileInputStream fis = new FileInputStream(f);
int length = (int)f.length();
length = (int)nearestPow2(length);
double[] ibr = new double[length]; //== real
double[] ibi = new double[length]; //== imaginary
int i = 0;
int l=0;
//fis.skip(44);
byte[] b = new byte[1024];
while((l=fis.read(b))!=-1){
try{
for(int j=0; j<1024; j++){
ibr[i] = b[j];
ibi[i] = 0;
i++;
}
}catch(Exception e){}
}
double[] ftb = FFTBase.fft(ibr, ibi, true);
double[] mag = new double[ftb.length/2];
double mxMag = 0;
long avgMg = 0;
int reqIndex = 512; //== no need to go till end
for(i=1;i<ibi.length; i++){
ibr[i] = ftb[i*2];
ibi[i] = ftb[i*2+1];
mag[i] = Math.sqrt(ibr[i]*ibr[i]+ibi[i]*ibi[i]);
avgMg += mag[i];
if(mag[i]>mxMag) mxMag = mag[i];
ps.println(mag[i]);
}
avgMg = avgMg/ibi.length;
ps.println("MAx===="+mxMag);
ps.println("Average===="+avgMg);
}catch(Exception e){e.printStackTrace();}
当我为5KHZ文件运行此代码时,这些是我得到的值。 https://pastebin.com/R3V0QU4G
这不是完整的输出,但有点类似。
由于
答案 0 :(得分:1)
仅仅通过执行fft并搜索“最响亮”的频率或类似的东西,不可能提取频率或“音调”。至少如果你试图从音乐信号中提取它。
还有不同种类的音调。很大一部分乐器(即吉他或我们的声音)产生的谐音包含几个遵循某种模式的频率。
但也有一些只有一个峰值/频率(即鸣笛)的音调
此外,您通常必须处理完全没有音调的信号中的噪音。这可能是背景噪音,或者这可能是仪器本身产生的。例如,吉他在攻击阶段具有非常大的噪声部分。
你可以使用不同的方法,这意味着不同的算法可以根据类型找到这些信号的音高。
如果我们停留在频域(fft)并假设我们想要分析谐波声音,那么例如two way mismatch algorithm
使用统计模式匹配来查找谐波并猜测fundamental frequency
,这是被我们的耳朵感知为音调的频率。
可以在此处找到示例实现:https://github.com/ausmauricio/audio_dsp此回购是课程中音频信号处理完整课程的一部分,也许这很有用。