整型FFT

引用自:http://blog.csdn.net/s3c44b0x/article/details/5667619

FFT计算比较费时,这是由于计算过程中使用浮点数以及需要大量计算sin、cos函数。常规方法实现FFT的C代码如下(参见数值计算与信号处理,输入为实数序列): 

#include "math.h" 

void rfftd(double *x, int n) 

    int i, j, k, m, i1, i2, i3, i4, n1, n2, n4; 
    double a, e, cc, ss, xt, t1, t2; 
    for(j = 1, i = 1; i < 16; i ++) 
    { 
        m = i; 
        j = 2 * j; 
        if(j == n) 
            break; 
    } 
    n1 = n - 1; 
    for(j = 0, i = 0; i < n1; i ++) 
    { 
        if(i < j) 
        { 
            xt = x[j]; 
            x[j] = x[i]; 
            x[i] = xt; 
        } 
        k = n / 2; 
        while(k < (j + 1)) 
        { 
            j -= k; 
            k /= 2; 
        } 
        j += k; 
    } 
    for(i = 0; i < n; i += 2) 
    { 
        xt = x[i]; 
        x[i] += x[i + 1]; 
        x[i + 1] = xt - x[i + 1]; 
    } 
    n2 = 1; 
    for(k = 2; k <= m; k ++) 
    { 
        n4 = n2; 
        n2 = 2 * n4; 
        n1 = 2 * n2; 
        e = 6.28318530718 / n1; 
        for(i = 0; i < n; i += n1) 
        { 
            xt = x[i]; 
            x[i] += x[i + n2]; 
            x[i + n2] = xt - x[i + n2]; 
            x[i + n2 + n4] = -x[i + n2 + n4]; 
            a = e; 
            for(j = 1; j <= (n4 - 1); j ++) 
            { 
                i1 = i + j; 
                i2 = i - j + n2; 
                i3 = i + j + n2; 
                i4 = i - j + n1; 
                cc = cos(a); 
                ss = sin(a); 
                a += e; 
                t1 = cc * x[i3] + ss * x[i4]; 
                t2 = ss * x[i3] - cc * x[i4]; 
                x[i4] = x[i2] - t2; 
                x[i3] = -x[i2] - t2; 
                x[i2] = x[i1] - t1; 
                x[i1] = x[i1] +t1; 
            } 
        } 
    } 


参数x为要变换的数据的指针,n为数据的个数(必须为2的整数次幂),变换后的结果从x中输出(只存放前n/2+1个值),存储顺序为[Re0, Re1, …, Ren/2, Imn/2-1, …, Im1](Re和Im分别为实部和虚部)。 

把这段代码转换成整型运算,可用的方法是:1、把所有浮点数乘以2的N次幂,例如256,取整成整型数;2、sin和cos函数采用查表法实现。修改后的整型FFT运算代码如下: 

long SIN_TABLE256[91] = {0, 4, 9, 13, 18, 22, 27, 31, 36, 40, 
                         44, 49, 53, 58, 62, 66, 71, 75, 79, 83, 
                         88, 92, 96, 100, 104, 108, 112, 116, 120, 124, 
                         128, 132, 136, 139, 143, 147, 150, 154, 158, 161, 
                         165, 168, 171, 175, 178, 181, 184, 187, 190, 193, 
                         196, 199, 202, 204, 207, 210, 212, 215, 217, 219, 
                         222, 224, 226, 228, 230, 232, 234, 236, 237, 239, 
                         241, 242, 243, 245, 246, 247, 248, 249, 250, 251, 
                         252, 253, 254, 254, 255, 255, 255, 256, 256, 256, 
                         256}; 

long fastsin256(long degree) 

    long result, neg = 0; 
    if(degree < 0) 
        degree = -degree + 180; 
    if(degree>= 360) 
        degree %= 360; 
    if(degree>= 180) 
    { 
        degree -= 180; 
        neg = 1; 
    } 
    if((degree>= 0) && (degree <= 90)) 
        result = SIN_TABLE256[degree]; 
    else 
        result = SIN_TABLE256[180 - degree]; 
    if(!neg) 
        return result; 
    else 
        return -result; 


__inline long faSTCos256(long degree) 

    return fastsin256(degree + 90); 


void rfftl(long *x, int n) 

    int i, j, k, m, i1, i2, i3, i4, n1, n2, n4; 
    long a, e, cc, ss, xt, t1, t2; 
    for(j = 1, i = 1; i < 16; i ++) 
    { 
        m = i; 
        j = (j << 1); 
        if(j == n) 
            break; 
    } 
    n1 = n - 1; 
    for(j = 0, i = 0; i < n1; i ++) 
    { 
        if(i < j) 
        { 
            xt = x[j]; 
            x[j] = x[i]; 
            x[i] = xt; 
        } 
        k = (n>> 1); 
        while(k < (j + 1)) 
        { 
            j -= k; 
            k = (k>> 1); 
        } 
        j += k; 
    } 
    for(i = 0; i < n; i += 2) 
    { 
        xt = x[i]; 
        x[i] += x[i + 1]; 
        x[i + 1] = xt - x[i + 1]; 
    } 
    n2 = 1; 
    for(k = 2; k <= m; k ++) 
    { 
        n4 = n2; 
        n2 = (n4 << 1); 
        n1 = (n2 << 1); 
        e = 360 / n1; 
        for(i = 0; i < n; i += n1) 
        { 
            xt = x[i]; 
            x[i] += x[i + n2]; 
            x[i + n2] = xt - x[i + n2]; 
            x[i + n2 + n4] = -x[i + n2 + n4]; 
            a = e; 
            for(j = 1; j <= (n4 - 1); j ++) 
            { 
                i1 = i + j; 
                i2 = i - j + n2; 
                i3 = i + j + n2; 
                i4 = i - j + n1; 
                cc = faSTCos256(a); 
                ss = fastsin256(a); 
                a += e; 
                t1 = cc * x[i3] + ss * x[i4]; 
                t2 = ss * x[i3] - cc * x[i4]; 
                t1 = (t1>> 8); 
                t2 = (t2>> 8); 
                x[i4] = x[i2] - t2; 
                x[i3] = -x[i2] - t2; 
                x[i2] = x[i1] - t1; 
                x[i1] = x[i1] + t1; 
            } 
        } 
    } 


运算过程中所有浮点数都乘以256并取整,输入和输出数据也是乘以256之后的整型数据。sin和cos采用查表实现,精确到1度。程序适用于对精度要求不高的FFT计算,例如音频播放器的频谱显示等。采用更大的取整系数(例如65536)并增加sin、cos表的精度可以提高这个整型FFT计算的精度。 

应用转化成整型计算的FFT需要注意的问题是,整型FFT的动态范围会比较小,这是由定点数的性质决定的,因此如果计算对在很大的动态范围内的精度有要求,则整型FFT不适用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值