要检测声卡是否发出“嘟”这个声音,我有们这个声音的波形(比如440HZ,持续0.1s),而且也已经得到了声卡出来的数据。现在的问题是:如果对捕捉到的声卡数据进行分析??
在网上翻了一下,好像是要对得到的声卡数据进行FFT,得到声音波形的频谱。但我不知道这个到底该怎么来实现,还请各位DX指点指点。
对这个问题,现存在下面两个疑问:
问题1:如何对现有数据进行FFT变换,得到相应的频谱数据
问题2:如何对得到的频谱数据进行分析,检测其是否匹配(是否为440HZ,持续0.1s
10 个解决方案
#1
up
#2
http://www.codeproject.com/audio/waveInFFT.asp
#3
TO:Zhymax(蓝点)
那第二个问题又如何来解决呢!!
如何进行匹配
那第二个问题又如何来解决呢!!
如何进行匹配
#4
呵呵,从你的问题来看,你要解决这个问题关键还在于基础知识
不论你是通过何种方法进行分析都需要针对数据的某个特征,即使是频谱特征你也需要明确你自己的目标,你有一个样本,你取出来的特征和样本特征要如何比较或运算才能达到匹配,这是从代码中找不出来的,建议多用 google
不论你是通过何种方法进行分析都需要针对数据的某个特征,即使是频谱特征你也需要明确你自己的目标,你有一个样本,你取出来的特征和样本特征要如何比较或运算才能达到匹配,这是从代码中找不出来的,建议多用 google
#5
对FFT不大明白
根据网上的算法,经过FFT后得到两组数据Real[]、Img[].
这两组数据都表示着什么呢
在我的匹配中,只要能取到在440HZ频率下持续0.1s的声音波形,这又该如何做呢??
用得到的两组数据,如何来画出一个频谱图呢??
请指教....
根据网上的算法,经过FFT后得到两组数据Real[]、Img[].
这两组数据都表示着什么呢
在我的匹配中,只要能取到在440HZ频率下持续0.1s的声音波形,这又该如何做呢??
用得到的两组数据,如何来画出一个频谱图呢??
请指教....
#6
其实第二个问题是比较简单的信号检测匹配问题.
以http://www.codeproject.com/audio/waveInFFT.asp的FFT算法说明:
参数说明:
FFT_LEN FFT的长度 这里假定为512点
p_nSamples(Hz/s) 声卡采样速率 这里假定为11025Hz/s
FFT频域分辨率(Hz/点): Freq=p_nSamples/FFT_LEN
FFT时域分辨率(s):Timeq=FFT_LEN/p_nSamples;表示一次FFT所代表的时间长度
从这里看出FFT的时域和频域分辨率成反比,也就是说如果要得到较好的频域分辨效果就要增大
FFT点数,但会导致时域分辨率下降,反之亦然。
原理说明:
FFT算法是将信号从时域变化到频域的一种算法
输出值分为虚部foutimg和实部fout,
foutimg和fout的平方和代表一个频率的功率
某一频率出是否有信号的判断:
该例中,频域分辨率为(11025/512)Hz=21.5Hz;
FFT频域分辨率也就代表了FFT输出的相邻一对虚部和实部值表示的频率间的差值
第i对FFT输出值所代表的频率:Fre[i]=(p_nSamples/FFT_LEN)*i;//i=0...FFT_LEN/2-1;
440Hz所在的点为:440/Freq=440/21.5=20.4,也就是说第20和21点处的值就代表了440Hz,
所以只需将第20和21点处的功率值与其他点的功率值相比就可以判断当前在440Hz处是否有信号。
持续时间的判断:
时域分辨率Timeq=512/11025=0.046s=46ms
例:若判断持续时间为0.1s,那么只需判断0.1/0.046=2次就可以了
注意:以上算法仅适用于简单的频谱估计,如果要求比较精确,那么可以采用短时FFT算法或者时域滤波法会更精确
不过时域滤波算法设计数字滤波器和相关匹配等专业知识,这里就不多说了,有兴趣的可以和我联系。
int frec=0;
DWORD nCount = 0;
for (DWORD dw = 0; dw < FFT_LEN; dw++)
{
{
//将声卡数据拷贝到FFT算法缓冲区
finleft[nCount++] = (double)((short*)pwh->lpData)[dw++];
}
}
//左声道的512点FFT
fft_double(FFT_LEN/2,0,finleft,NULL,fout,foutimg);
//输出值分为虚部foutimg和实部fout,
float re,im;
float power0=0,power;
int fremax;
//检测16到25点(244Hz----537Hz)处的最大频率点
for(int i=16;i < 25;i++)
{
re = fout[i];//实部
im = foutimg[i];//虚部
//get frequency intensity and scale to 0..256 range
power=GetFrequencyIntensity(re,im);
if(power>power0) fremax=i;
}
//判断440Hz处是否有信号
if(fremax==20 || fremax==21) frec++;
if(frec>=2)
{
//持续时间>=0.1s
............
}
以http://www.codeproject.com/audio/waveInFFT.asp的FFT算法说明:
参数说明:
FFT_LEN FFT的长度 这里假定为512点
p_nSamples(Hz/s) 声卡采样速率 这里假定为11025Hz/s
FFT频域分辨率(Hz/点): Freq=p_nSamples/FFT_LEN
FFT时域分辨率(s):Timeq=FFT_LEN/p_nSamples;表示一次FFT所代表的时间长度
从这里看出FFT的时域和频域分辨率成反比,也就是说如果要得到较好的频域分辨效果就要增大
FFT点数,但会导致时域分辨率下降,反之亦然。
原理说明:
FFT算法是将信号从时域变化到频域的一种算法
输出值分为虚部foutimg和实部fout,
foutimg和fout的平方和代表一个频率的功率
某一频率出是否有信号的判断:
该例中,频域分辨率为(11025/512)Hz=21.5Hz;
FFT频域分辨率也就代表了FFT输出的相邻一对虚部和实部值表示的频率间的差值
第i对FFT输出值所代表的频率:Fre[i]=(p_nSamples/FFT_LEN)*i;//i=0...FFT_LEN/2-1;
440Hz所在的点为:440/Freq=440/21.5=20.4,也就是说第20和21点处的值就代表了440Hz,
所以只需将第20和21点处的功率值与其他点的功率值相比就可以判断当前在440Hz处是否有信号。
持续时间的判断:
时域分辨率Timeq=512/11025=0.046s=46ms
例:若判断持续时间为0.1s,那么只需判断0.1/0.046=2次就可以了
注意:以上算法仅适用于简单的频谱估计,如果要求比较精确,那么可以采用短时FFT算法或者时域滤波法会更精确
不过时域滤波算法设计数字滤波器和相关匹配等专业知识,这里就不多说了,有兴趣的可以和我联系。
int frec=0;
DWORD nCount = 0;
for (DWORD dw = 0; dw < FFT_LEN; dw++)
{
{
//将声卡数据拷贝到FFT算法缓冲区
finleft[nCount++] = (double)((short*)pwh->lpData)[dw++];
}
}
//左声道的512点FFT
fft_double(FFT_LEN/2,0,finleft,NULL,fout,foutimg);
//输出值分为虚部foutimg和实部fout,
float re,im;
float power0=0,power;
int fremax;
//检测16到25点(244Hz----537Hz)处的最大频率点
for(int i=16;i < 25;i++)
{
re = fout[i];//实部
im = foutimg[i];//虚部
//get frequency intensity and scale to 0..256 range
power=GetFrequencyIntensity(re,im);
if(power>power0) fremax=i;
}
//判断440Hz处是否有信号
if(fremax==20 || fremax==21) frec++;
if(frec>=2)
{
//持续时间>=0.1s
............
}
#7
补充一点:
在检测时,不要把检测范围设的太大,否则容易误判,具体设置要在实际测试中设置
//检测16到25点(244Hz----537Hz)处的最大频率点
for(int i=16;i < 25;i++)
{
re = fout[i];//实部
im = foutimg[i];//虚部
//get frequency intensity and scale to 0..256 range
power=GetFrequencyIntensity(re,im);
if(power>power0) fremax=i;
}
在检测时,不要把检测范围设的太大,否则容易误判,具体设置要在实际测试中设置
//检测16到25点(244Hz----537Hz)处的最大频率点
for(int i=16;i < 25;i++)
{
re = fout[i];//实部
im = foutimg[i];//虚部
//get frequency intensity and scale to 0..256 range
power=GetFrequencyIntensity(re,im);
if(power>power0) fremax=i;
}
#8
TO: bbbleo()
能给我发一份相关的材料吗??谢谢
ww51xh@163.com
能给我发一份相关的材料吗??谢谢
ww51xh@163.com
#9
TO: bbbleo()
画出来的频谱好像不对!!
for (DWORD i=0; i<FFT_LEN/2;i++)
{
LineTo(i, GetFrequencyIntensity(re, im);
}
当我用一个恒定频率的声音时,其产生的频谱并不能在这一频率上固定,而是在周围不停地跳跃的。
画出来的频谱好像不对!!
for (DWORD i=0; i<FFT_LEN/2;i++)
{
LineTo(i, GetFrequencyIntensity(re, im);
}
当我用一个恒定频率的声音时,其产生的频谱并不能在这一频率上固定,而是在周围不停地跳跃的。
#10
怎么我做完FFT后,得到的频率的值猣峰值达到了3万多,这符合吗??
而且当产生一固定频率的声音的时候,频谱图并不稳定,
而且当产生一固定频率的声音的时候,频谱图并不稳定,
#1
up
#2
http://www.codeproject.com/audio/waveInFFT.asp
#3
TO:Zhymax(蓝点)
那第二个问题又如何来解决呢!!
如何进行匹配
那第二个问题又如何来解决呢!!
如何进行匹配
#4
呵呵,从你的问题来看,你要解决这个问题关键还在于基础知识
不论你是通过何种方法进行分析都需要针对数据的某个特征,即使是频谱特征你也需要明确你自己的目标,你有一个样本,你取出来的特征和样本特征要如何比较或运算才能达到匹配,这是从代码中找不出来的,建议多用 google
不论你是通过何种方法进行分析都需要针对数据的某个特征,即使是频谱特征你也需要明确你自己的目标,你有一个样本,你取出来的特征和样本特征要如何比较或运算才能达到匹配,这是从代码中找不出来的,建议多用 google
#5
对FFT不大明白
根据网上的算法,经过FFT后得到两组数据Real[]、Img[].
这两组数据都表示着什么呢
在我的匹配中,只要能取到在440HZ频率下持续0.1s的声音波形,这又该如何做呢??
用得到的两组数据,如何来画出一个频谱图呢??
请指教....
根据网上的算法,经过FFT后得到两组数据Real[]、Img[].
这两组数据都表示着什么呢
在我的匹配中,只要能取到在440HZ频率下持续0.1s的声音波形,这又该如何做呢??
用得到的两组数据,如何来画出一个频谱图呢??
请指教....
#6
其实第二个问题是比较简单的信号检测匹配问题.
以http://www.codeproject.com/audio/waveInFFT.asp的FFT算法说明:
参数说明:
FFT_LEN FFT的长度 这里假定为512点
p_nSamples(Hz/s) 声卡采样速率 这里假定为11025Hz/s
FFT频域分辨率(Hz/点): Freq=p_nSamples/FFT_LEN
FFT时域分辨率(s):Timeq=FFT_LEN/p_nSamples;表示一次FFT所代表的时间长度
从这里看出FFT的时域和频域分辨率成反比,也就是说如果要得到较好的频域分辨效果就要增大
FFT点数,但会导致时域分辨率下降,反之亦然。
原理说明:
FFT算法是将信号从时域变化到频域的一种算法
输出值分为虚部foutimg和实部fout,
foutimg和fout的平方和代表一个频率的功率
某一频率出是否有信号的判断:
该例中,频域分辨率为(11025/512)Hz=21.5Hz;
FFT频域分辨率也就代表了FFT输出的相邻一对虚部和实部值表示的频率间的差值
第i对FFT输出值所代表的频率:Fre[i]=(p_nSamples/FFT_LEN)*i;//i=0...FFT_LEN/2-1;
440Hz所在的点为:440/Freq=440/21.5=20.4,也就是说第20和21点处的值就代表了440Hz,
所以只需将第20和21点处的功率值与其他点的功率值相比就可以判断当前在440Hz处是否有信号。
持续时间的判断:
时域分辨率Timeq=512/11025=0.046s=46ms
例:若判断持续时间为0.1s,那么只需判断0.1/0.046=2次就可以了
注意:以上算法仅适用于简单的频谱估计,如果要求比较精确,那么可以采用短时FFT算法或者时域滤波法会更精确
不过时域滤波算法设计数字滤波器和相关匹配等专业知识,这里就不多说了,有兴趣的可以和我联系。
int frec=0;
DWORD nCount = 0;
for (DWORD dw = 0; dw < FFT_LEN; dw++)
{
{
//将声卡数据拷贝到FFT算法缓冲区
finleft[nCount++] = (double)((short*)pwh->lpData)[dw++];
}
}
//左声道的512点FFT
fft_double(FFT_LEN/2,0,finleft,NULL,fout,foutimg);
//输出值分为虚部foutimg和实部fout,
float re,im;
float power0=0,power;
int fremax;
//检测16到25点(244Hz----537Hz)处的最大频率点
for(int i=16;i < 25;i++)
{
re = fout[i];//实部
im = foutimg[i];//虚部
//get frequency intensity and scale to 0..256 range
power=GetFrequencyIntensity(re,im);
if(power>power0) fremax=i;
}
//判断440Hz处是否有信号
if(fremax==20 || fremax==21) frec++;
if(frec>=2)
{
//持续时间>=0.1s
............
}
以http://www.codeproject.com/audio/waveInFFT.asp的FFT算法说明:
参数说明:
FFT_LEN FFT的长度 这里假定为512点
p_nSamples(Hz/s) 声卡采样速率 这里假定为11025Hz/s
FFT频域分辨率(Hz/点): Freq=p_nSamples/FFT_LEN
FFT时域分辨率(s):Timeq=FFT_LEN/p_nSamples;表示一次FFT所代表的时间长度
从这里看出FFT的时域和频域分辨率成反比,也就是说如果要得到较好的频域分辨效果就要增大
FFT点数,但会导致时域分辨率下降,反之亦然。
原理说明:
FFT算法是将信号从时域变化到频域的一种算法
输出值分为虚部foutimg和实部fout,
foutimg和fout的平方和代表一个频率的功率
某一频率出是否有信号的判断:
该例中,频域分辨率为(11025/512)Hz=21.5Hz;
FFT频域分辨率也就代表了FFT输出的相邻一对虚部和实部值表示的频率间的差值
第i对FFT输出值所代表的频率:Fre[i]=(p_nSamples/FFT_LEN)*i;//i=0...FFT_LEN/2-1;
440Hz所在的点为:440/Freq=440/21.5=20.4,也就是说第20和21点处的值就代表了440Hz,
所以只需将第20和21点处的功率值与其他点的功率值相比就可以判断当前在440Hz处是否有信号。
持续时间的判断:
时域分辨率Timeq=512/11025=0.046s=46ms
例:若判断持续时间为0.1s,那么只需判断0.1/0.046=2次就可以了
注意:以上算法仅适用于简单的频谱估计,如果要求比较精确,那么可以采用短时FFT算法或者时域滤波法会更精确
不过时域滤波算法设计数字滤波器和相关匹配等专业知识,这里就不多说了,有兴趣的可以和我联系。
int frec=0;
DWORD nCount = 0;
for (DWORD dw = 0; dw < FFT_LEN; dw++)
{
{
//将声卡数据拷贝到FFT算法缓冲区
finleft[nCount++] = (double)((short*)pwh->lpData)[dw++];
}
}
//左声道的512点FFT
fft_double(FFT_LEN/2,0,finleft,NULL,fout,foutimg);
//输出值分为虚部foutimg和实部fout,
float re,im;
float power0=0,power;
int fremax;
//检测16到25点(244Hz----537Hz)处的最大频率点
for(int i=16;i < 25;i++)
{
re = fout[i];//实部
im = foutimg[i];//虚部
//get frequency intensity and scale to 0..256 range
power=GetFrequencyIntensity(re,im);
if(power>power0) fremax=i;
}
//判断440Hz处是否有信号
if(fremax==20 || fremax==21) frec++;
if(frec>=2)
{
//持续时间>=0.1s
............
}
#7
补充一点:
在检测时,不要把检测范围设的太大,否则容易误判,具体设置要在实际测试中设置
//检测16到25点(244Hz----537Hz)处的最大频率点
for(int i=16;i < 25;i++)
{
re = fout[i];//实部
im = foutimg[i];//虚部
//get frequency intensity and scale to 0..256 range
power=GetFrequencyIntensity(re,im);
if(power>power0) fremax=i;
}
在检测时,不要把检测范围设的太大,否则容易误判,具体设置要在实际测试中设置
//检测16到25点(244Hz----537Hz)处的最大频率点
for(int i=16;i < 25;i++)
{
re = fout[i];//实部
im = foutimg[i];//虚部
//get frequency intensity and scale to 0..256 range
power=GetFrequencyIntensity(re,im);
if(power>power0) fremax=i;
}
#8
TO: bbbleo()
能给我发一份相关的材料吗??谢谢
ww51xh@163.com
能给我发一份相关的材料吗??谢谢
ww51xh@163.com
#9
TO: bbbleo()
画出来的频谱好像不对!!
for (DWORD i=0; i<FFT_LEN/2;i++)
{
LineTo(i, GetFrequencyIntensity(re, im);
}
当我用一个恒定频率的声音时,其产生的频谱并不能在这一频率上固定,而是在周围不停地跳跃的。
画出来的频谱好像不对!!
for (DWORD i=0; i<FFT_LEN/2;i++)
{
LineTo(i, GetFrequencyIntensity(re, im);
}
当我用一个恒定频率的声音时,其产生的频谱并不能在这一频率上固定,而是在周围不停地跳跃的。
#10
怎么我做完FFT后,得到的频率的值猣峰值达到了3万多,这符合吗??
而且当产生一固定频率的声音的时候,频谱图并不稳定,
而且当产生一固定频率的声音的时候,频谱图并不稳定,