利用傅里叶变换求得音频数据的频率,根据音高频率对照表,可测试出吉他每根弦与标准音的差值,实现调音器效果。
目录
- 程序效果
- 实现过程
- 样例代码
- 测试用例
- 参考资料
程序效果
截图1:程序效果
输入需要调整的弦,即开始录音,弹对应的弦即可,录音时间大约10秒,10秒后短暂计算处理后会显示结果。
实现过程
截图2:流程图
主要步骤如上,需要注意的细节有:
1.如何获取有效的4096个采样数据点
截图3:有效数据前的杂音及静音数据
本程序强行跳过前8000个采样数据点,并且用600进行边界判定,从第一个大于600的点开始采集。这要求使用的环境很安静才行,如果有其他声音干扰,对结果有较大影响。
2.6弦的特殊情况 :1-5弦使用正常时,6弦的频率值一直为正常值的2倍,无法定位问题情况下,强行将结果除以2,保证功能可以正常使用。
样例代码
1.下载链接:https://download.youkuaiyun.com/download/u013025955/11190369
部分主要代码
//傅里叶变换
void getFFTEnergy(double *data)
{
double pr[DATASIZE], pi[DATASIZE], fr[DATASIZE], fi[DATASIZE];
int i=0;
//原始数据作为实部,虚部填0.0
for (i=0; i<DATASIZE; i++)
{
pr[i] = *(data+i);
pi[i] = 0.0;
}
/*
入参解释:
pr:采样数据的实部,对应PCM数据,返回傅里叶变换的模(能量)
pi:采样数据的虚部,填0.0,返回傅里叶变换的幅角,本程序不使用
DATASIZE:采样点数,这里对应4096
12:采样点数4096对应是2的12次方
fr:傅里叶变换后的实部
fi:傅里叶变换后的虚部
0:使用傅里叶变换功能,1为逆变换
1:计算模和幅角,0的话不会计算,这里要注意
*/
//调用FFT快速离散傅里叶变换函数
kfft(pr, pi, DATASIZE, 12, fr, fi, 0, 1);
//模(能量)返回
for (i=0; i<DATASIZE; i++)
{
*(data+i) = pr[i];
}
}
//换算频率
double getFrequence(double *data, int chooseStr)
{
int locate; //能量值对应的横坐标
int i;
double frequence; //频率
double max; //能量最大值
max = *data;
//求能量最大值对应的横坐标
for (i=0; i<(DATASIZE/2); i++)
{
if (*(data+i) > max)
{
max = *(data+i);
locate = i;
}
}
//计算频率,频率=横坐标*(采样率/采样点数)
frequence = locate*(8000.0/DATASIZE);
//6弦的特殊处理,除以2
if (chooseStr == 6)
{
frequence = frequence/2.0;
}
return frequence;
}
测试用例
截图4:测试用例
参考资料
1.《常用算法程序集(C语言描述)》FFT快速离散傅里叶变换例程
2.深入浅出解释FFT(一)——用fft求频谱
https://blog.youkuaiyun.com/wordwarwordwar/article/details/68951388
3.fseek()用法 设定文件的当前读写位置
https://blog.youkuaiyun.com/Tian_fourpieces/article/details/79970098