DSP浮点数和定点数笔记

参考文章

Introduction to Fixed Point Number Representation
tas5751m
原码
补码

定点数存储

定点数是以补码方式存储。原码与补码的概念请移步参考文章。
+1的原码为00000001,-1的原码就是10000001。
-1的补码:

1 1111110 // 除符号位,全部取反
1 1111111 // 加1,进位不能进给符号位,例如1 1111111 + 1应为1 0000000,
          // 得到的便是最终补码

注意,正数的补码等于原码。

实验

#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>

int main(int argc, char *argv[])
{
    union {
        unsigned char   uc;
        signed char     sc;
    } num;

    num.sc = -128;
    printf("%+4d:%02x\n", num.sc, num.uc);
    num.sc = +127;
    printf("%+4d:%02x\n", num.sc, num.uc);

    num.sc = -1;
    printf("%+4d:%02x\n", num.sc, num.uc);
    num.sc = +1;
    printf("%+4d:%02x\n", num.sc, num.uc);

    return 0;
}

运行结果

-128:80
+127:7f
  -1:ff
  +1:01

浮点数存储

符号位指数位小数位指数偏移量
单精度浮点数1位[31]8位[30 ~ 23]23位[22 ~ 00]127
双精度浮点数1位[63]11位[62 ~ 52]52位[51 ~ 00]1023

举例

浮点数式:+27.5
二进制为:11011.1
指数式为:1.10111*2^4

尾数(小数点后的数):10111,补够23位 1011 1000 0000 0000 0000 000
指数:4,加上指数偏移量 127,等于131,二进制1000 0011

组合: (符号数位1位)0 (指数位8位)1000 0011 (尾数位23位)1011 1000 0000 0000 0000 000
即:0100 0001 1101 1100 0000 0000 0000 0000
16进制:41 DC 00 00

实验

#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>

static bool ls_cpu_little_endian(void)
{
    union __TENDIAN{
        int a;
        char b;
    } tend;
     
    tend.a = 1;
    if(tend.b == 1) {
        return true;
    } else {
        return false;
    }
}

int main(int argc, char *argv[])
{
    union {
        uint8_t c[4];
        float f;
    } num = { .f = +27.5 };

    printf("sizeof(float) = %d\n", sizeof(float));

    if (ls_cpu_little_endian()) {
        printf("%02x%02x%02x%02x:%+f\n",
               num.c[3], num.c[2], num.c[1], num.c[0], num.f);
    } else {
        printf("%02x%02x%02x%02x:%+f\n",
               num.c[0], num.c[1], num.c[2], num.c[3], num.f);
    }

    return 0;
}

运行结果

sizeof(float) = 4
41dc0000:+27.500000

其他例子

sizeof(double) = 8
403b800000000000:+27.500000
c03b800000000000:-27.500000

3.23

TAS5751m滤波器参数采用的是3.23格式存储方式。类似的格式还有1.31,9.23等等。
在这里插入图片描述实验
在这里插入图片描述导出滤波器参数

0x00,0x82,0x7b,0x2e
0x07,0x03,0xd7,0x2b
0x00,0x7b,0xda,0xad
0x00,0xfc,0x28,0xd5
0x07,0x81,0xaa,0x25

代码

static double fixed2double(uint32_t fixed, uint32_t format)
{
    double d    = 0.0;
    uint32_t n  = 0;

    switch (format) {
    case 323:
        if (fixed & 0x02000000) {
            fixed = ~fixed;
            fixed = fixed & 0x01ffffff;
            fixed = fixed + 1;
            d += (double)(fixed) / ( 1 << 23);
            d *= (-1);
        } else {
            d += (double)(fixed) / ( 1 << 23);
        }
        break;
    default:
        break;
    }

    return d;
}

转换成浮点数

> ./Math.exe fixed2float -f 323 -v 00827b2e
323(00827b2e) = +1.019384
> ./Math.exe fixed2float -f 323 -v 0703d72b
323(0703d72b) = -1.969996
> ./Math.exe fixed2float -f 323 -v 007bdaad
323(007bdaad) = +0.967611
> ./Math.exe fixed2float -f 323 -v 00fc28d5
323(00fc28d5) = +1.969996
> ./Math.exe fixed2float -f 323 -v 0781aa25
323(0781aa25) = -0.986995

注意DSP习惯采用的传递函数与Octave等数学工具的a1, a2的符号取反。

[a0, -a1, -a2];
[b0, +b1, +b2]; 

所以Octave参数应为:

BIQUAD_1_A = [+1.000000, -1.969996, +0.986995];
BIQUAD_1_B = [+1.019384, -1.969996, +0.967611];

代码

% Loader Octave packages
pkg load signal

% Sample Rate
Fs = 48000;

BIQUAD_1_A = [+1.000000, -1.969996, +0.986995];
BIQUAD_1_B = [+1.019384, -1.969996, +0.967611];

[H_BIQUAD_1, w_BIQUAD_1] = freqz(BIQUAD_1_B, BIQUAD_1_A, Fs);


% Transfer from Rad to Hz.
F_BIQUAD_1 = (w_BIQUAD_1 / (2 * pi)) * Fs;

% Transfer from Magnitude to DB
Hf_BIQUAD_1 = mag2db(abs(H_BIQUAD_1));
Hx_BIQUAD_1 = rad2deg(angle(H_BIQUAD_1));

clear figure
clf;
figure(1);

% Plot Magnitude VS Frequency
% Range: 1 ~ Fs / 2 = 1 ~ 24000
% Because Freqz only return half result (1, +pi) rather than (-pi, +pi),
% So divided by 2.
warning ("off", "Octave:negative-data-log-axis");

subplot(1, 2, 1);
semilogx(F_BIQUAD_1(1:Fs, 1), Hf_BIQUAD_1(1:Fs, 1), "linewidth", 3.0);
axis([10, 24000]);
xlabel('Frequency(Hz)');
ylabel('Amplitude(DB)');

subplot(1, 2, 2);
plot(F_BIQUAD_1(1:Fs, 1), Hx_BIQUAD_1(1:Fs, 1), "linewidth", 3.0);
xlabel('Frequency(Hz)');
ylabel('Phase(Degree)');

运行结果
在这里插入图片描述可以看到频响是一致的。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值