Java—基频估计的几个问题
我试图从一个.wav文件中估计基频,该文件包含一个单词的语音记录 我试着用audioInputStream读取文件。格式为PCM_签名44100.0 Hz,16位,立体声,4字节/帧,小端 因此,我制作了一个新的缓冲区,只包含一个通道。该准则实现了以下目标:Java—基频估计的几个问题,java,signal-processing,fft,wav,Java,Signal Processing,Fft,Wav,我试图从一个.wav文件中估计基频,该文件包含一个单词的语音记录 我试着用audioInputStream读取文件。格式为PCM_签名44100.0 Hz,16位,立体声,4字节/帧,小端 因此,我制作了一个新的缓冲区,只包含一个通道。该准则实现了以下目标: double [] audioRight = new double[audioBytes.length/2]; for(int i = 0, k = 0; i <= audioBytes.length-1; i+=4, k+=2){
double [] audioRight = new double[audioBytes.length/2];
for(int i = 0, k = 0; i <= audioBytes.length-1; i+=4, k+=2){
audioRight[k]=audioBytes[i];
audioRight[k+1]=audioBytes[i+1];
}
double[]audioRight=新的双精度[audioBytes.length/2];
对于(inti=0,k=0;i一些一般提示:
你说你试图估计一个口语单词的基本频率。一个“单词”由几个辅音和元音组成(或更好)。每个“元音”都有不同的基本频率,在大多数情况下,频率甚至会在一个元音内发生变化(这会产生我们句子的“旋律”).Thius的意思是你应该估计很短的语音间隔的基频/基音,并确保你看到的是元音(辅音是某种形式的噪音,具有循环成分)
因此,第一个sterp应该是生成单词的光谱图
然后,您可以计算感兴趣部分的短期FFT,并进行谐波求和
不过,使用短期自相关函数会得到更好的结果
其他需要研究的东西:基音检测,倒谱16位是2个字节。你在哪里把小尾端的2个字节转换成1个双倍值?谢谢你的回答。我没有这样做。这样做的目的是什么?你对如何在java中实现这一点有什么建议吗?@hotpaw2我编辑了原始帖子,试图用appl正如你所建议的。这就是你的意思吗?如果我做得正确的话,它似乎不能解决我的问题。事实证明,使用ByteBuffer.wrap修复了我的问题,所以感谢你为我指明了方向。在使用ByteBuffer并专注于缓冲区中的前1000个值之后,我现在可以估计.wav f的基本频率演讲的时间间隔。结果符合每个性别基频的预期间隔。如果有人正在阅读这篇文章,寻找关于谐波频谱求和基频估计的答案,那么就去问吧,我会把我用过的所有代码都扔掉。我知道要找到关于基频估计的好信息有多难主题(:立体声,16位->4字节。一个示例小Endiannes:WavSample=(int)((字节[1]))
DoubleFFT_1D fftDo= new DoubleFFT_1D(audioLeft.length);
double[] fftBuffer = new double [audioLeft.length*2];
for (int i = 0; i < audioLeft.length; i++){
fftBuffer[i] = audioLeft[i];
}
fftDo.realForwardFull(fftBuffer);
double top_sum = 0;
double first_index = 0;
double sum = 0;
double f_0 = 0;
double FR = audioInputStream.getFormat().getSampleRate()/2/ampBuffer.length;
for (int i = 50; i <= ampBuffer.length/4-1; i++){
sum = ampBuffer[i]+ampBuffer[i*2]+ampBuffer[i*3]+ampBuffer[i*4];
if (top_sum < sum){
top_sum=sum;
first_index = i;
ByteBuffer buf = ByteBuffer.wrap(audioBytes);
buf.order(ByteOrder.LITTLE_ENDIAN);
double[] audio = new double[audioBytes.length/2];
for(int i = 0; i < audioBytes.length/2; i++) {
short s = buf.getShort();
double mono = (double) s;
double mono_norm = mono / 32768.0;
audio[i]=mono_norm;
}