赞
踩
之前写的那一篇打算重写。因为自己又看出了眉目。
代码需要弄懂逻辑,因为编程永远都是需要逻辑的,首先还是分析一下需求:我们要产生一个DTMF音信号,就是两个不同频率正弦波相加组合而成。就有个公式DTMFout = sine(360*f1*T + phase1) + alpha*sine(360*f2*T + phase2)
。至于这里为什么只有第二个sine有α,下一篇再说。
这里有一个思想,DTMF有8个频率,那么用什么来表示呢,当然有各自的f1,f2.但是函数的相位需要自己想办法,而且,我们需要的是定点数,而不是浮点数,所以所得到的这8个偏移相位,分别乘上1024,也就是2^10.得到的新的8个频率,后面要用到。
DTMF_coef1 = 1024为控制产生的DTMF音的输出幅度。
这里的belta = 1004,就是0.9801,不知道什么意思。
门限需要设定好,用宏定义就是为了可以及时修改,因为门限会因为信号而变化。
定义cos,sin(int carrierDeg),就是为了得到sin函数值,或者cos函数值。
key_convert(unsigned char key),你键入一个键,就要识别是什么数。
算法函数后面再说。
long int delta_phase[],里面每两个数为一组,分别是上面乘上1024后的偏移相位,就代表了8个频率,两两组合就成为了16个键。0-9,ABCD,*,#.
有一个1/4sin函数表,就是90度以内的sin和cos互换的,也就是诱导公式的一个系数数组。有92个。0-91.
主要是要看后面用到的函数需要怎么使用。
之后就是进入主程序部分,首先产生DTMF信号,保存在数组DTMF_Buf[160]中。每调用一次,生成160个样值。输入的参数:presskey是要产生的DTMF音对应的键值,ASCII码表示法。
long int phaseL_step,phaseH_step,long int long_temp1;
long int其实是32位,比int的16位更高,注意,一个字节占八位,所以我们说的一个符号就是占一个字节,8位,那么一个汉字就占2个字节,16位。
有个initflag,取值不为0时,复位高音和低音相位(全局变量),为0时,相位在原来基础上叠加。叠加说明要有循环啊,看下面。
key_convert(presskey)把所按的键值变成ASCII码值,假如按得是“A”,converted_key = key - 0x37,这里16进制表示成10进制就是65-55 = 10,就代表A就是在第10个位置,0-9,之后就是A。好,把10给temp1之后,向左移动一位。phaseL_step = delta_phase[temp1],这里就从里面找,注意c语言是从0开始的,所以找到的20就是实打实的20,就是第21个。temp1++,知道就是后一个相位偏移,就代表着频率。这两个频率合成就是A的DTMF频率对应。
生成信号最重要的就是后面的循环,循环次数是160,i=0时,由于一开始什么都没有,所以phaseL_step假设是32118就给了DTMF_phaseL,同理55711。那么i = 1时,向右移位10位,就是32118要除以1024,就变成我们一开始定义的这8个原始偏移相位,31.365.那么,sine(31.365)这个函数是这么算的。
利用前面的90度的sin函数表,获得0-359度范围内的sine值。注意,参数就是31.365,那么就在sinecoscoeff[]里面寻找对应的系数值——527,同理,phaseH也是一样找系数,最后把这两个系数相加得到temp3.乘上幅度限制1024,再向右移动8位得到temp1,赋给Buf[1]中。
之后继续32118+32118,赋给phaseL。。。呢么角度也就变成原来的两倍,找的系数又不一样了。因此存在Buf[]里面的数据都是两个sincoscoeff数组里面的系数在乘上一个幅度限制,再向右移动8位(也就是除以256)之后的值。
循环下去,叠加,一直到phaseL/H>368640的话,就让phaseL/H减去368640.这是是由360左移10位得来。有点不理解。。。
生成了信号,该检测了。这里用到了goertzel算法,需要好好说。
没有检测到DTMF音,函数就输出为0,否则为对应DTMF音对应的ASCII码键值。
这里有两个循环,一个循环152次,之前缓存的Buf[i],给rxsample,算法这里不写公式,可以看我上一篇文章。这152次循环,就是为了得到递归的中间Vk[n],这时候还没有得到幅度值。最后i=152~160之间就计算了平方幅值。因为这里有延迟器,所以需要有两个w1,w2这种表示延迟的N-2,N-1的情况。
最后选出4个低频音和高频音,确定从DTMF原始表中得到真的频率。然后再让高低频音检测值都大于门限,输出对应的DTMF音的ASCII码值,否则输出0.
要问导师的问题:
α为什么只有在第二个sine有?
belta 0.9801 1004是什么
为什么选取的是这8个相位偏移。
为什么要用相位这种表示方法来表示DTMF频率。
Buf[160]为什么缓存组是160个
sin函数表怎么来的,具体怎么用。sinecoscoeff[]
160次循环这里还有点模糊(移动8位,360移位相减)
循环152次,152~160
采样频率问题
goertzel_freq_FL问题,还有0.99,0.9801问题。
goertzel算法中的为什么一起还要向右移10位。然后为什么整体向右移动7位,幅度算法中的移位问题。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。