batcd 发表于 2025-12-27 09:23:10

batcd 发表于 2025-12-27 09:05
不知道什么原因最后的时候会有杂音
找到了原因extern const unsigned char song;
长度和song文件的设置不一致导致的

attach://126483.mp4

health 发表于 2025-12-29 21:46:40

batcd 发表于 2025-12-27 09:23
找到了原因extern const unsigned char song;
长度和song文件的设置不一致导致的



你这个是用C版本播的还是汇编播的?

batcd 发表于 2025-12-30 04:45:50

health 发表于 2025-12-29 21:46
你这个是用C版本播的还是汇编播的?

汇编的C的卡的有点严重

health 发表于 2026-1-3 17:35:26

minimp3针对STC MCU和C251继续优化。
先找出性能瓶颈,再针对性重点处理。


keil软仿真下的性能分析,各函数执行时间占比。
虽然指令周期与STC硬件不完全相同,还有FPU硬件加速器的参与,绝对的执行时间并不符合真实硬件,但是比较各函数的相对比例还是有参考意义的。

由上图可见,mp3d_synth函数占据了大部分的执行时间。
因此,先拿mp3d_synth函数下手。

health 发表于 2026-1-3 18:16:09

mp3d_synth源码不大,没多少行,但都是大量的浮点运算。
尤其是那一行宏,展开后是循环中大量计算。
另外,此函数对单声道和双声道没有区分,对于单声道来说,多算了一倍的计算量。
这一点可以简单的将for (j = 0; j < 4; j++)改为for (j = 0; j < 4; j+=2)来减少一半计算。

原始程序

static void mp3d_synth(float *xl, mp3d_sample_t *dstl, int nch, float *lins)
{
    int i;
    float *xr = xl + 576*(nch - 1);
    mp3d_sample_t *dstr = dstl + (nch - 1);

    static const float g_win[] = {
      -1,26,-31,208,218,401,-519,2063,2000,4788,-5517,7134,5959,35640,-39336,74992,
      -1,24,-35,202,222,347,-581,2080,1952,4425,-5879,7640,5288,33791,-41176,74856,
      -1,21,-38,196,225,294,-645,2087,1893,4063,-6237,8092,4561,31947,-43006,74630,
      -1,19,-41,190,227,244,-711,2085,1822,3705,-6589,8492,3776,30112,-44821,74313,
      -1,17,-45,183,228,197,-779,2075,1739,3351,-6935,8840,2935,28289,-46617,73908,
      -1,16,-49,176,228,153,-848,2057,1644,3004,-7271,9139,2037,26482,-48390,73415,
      -2,14,-53,169,227,111,-919,2032,1535,2663,-7597,9389,1082,24694,-50137,72835,
      -2,13,-58,161,224,72,-991,2001,1414,2330,-7910,9592,70,22929,-51853,72169,
      -2,11,-63,154,221,36,-1064,1962,1280,2006,-8209,9750,-998,21189,-53534,71420,
      -2,10,-68,147,215,2,-1137,1919,1131,1692,-8491,9863,-2122,19478,-55178,70590,
      -3,9,-73,139,208,-29,-1210,1870,970,1388,-8755,9935,-3300,17799,-56778,69679,
      -3,8,-79,132,200,-57,-1283,1817,794,1095,-8998,9966,-4533,16155,-58333,68692,
      -4,7,-85,125,189,-83,-1356,1759,605,814,-9219,9959,-5818,14548,-59838,67629,
      -4,7,-91,117,177,-106,-1428,1698,402,545,-9416,9916,-7154,12980,-61289,66494,
      -5,6,-97,111,163,-127,-1498,1634,185,288,-9585,9838,-8540,11455,-62684,65290
    };
    float *zlin = lins + 15*64;
    const float *w = g_win;

    zlin   = xl;
    zlin = xr;
    zlin = xl;
    zlin = xr;

    zlin   = xl;
    zlin = xr;
    zlin = xl;
    zlin = xr;

    mp3d_synth_pair(dstr, nch, lins + 4*15 + 1);
    mp3d_synth_pair(dstr + 32*nch, nch, lins + 4*15 + 64 + 1);
    mp3d_synth_pair(dstl, nch, lins + 4*15);
    mp3d_synth_pair(dstl + 32*nch, nch, lins + 4*15 + 64);

    for (i = 14; i >= 0; i--)
    {
#define LOAD(k) float w0 = *w++; float w1 = *w++; float *vz = &zlin; float *vy = &zlin;               
#define S0(k) { uint16_t j; LOAD(k); for (j = 0; j < 4; j++) b= vz*w1 + vy*w0, a= vz*w0 - vy*w1; }       
#define S1(k) { uint16_t j; LOAD(k); for (j = 0; j < 4; j++) b += vz*w1 + vy*w0, a += vz*w0 - vy*w1; }       
#define S2(k) { uint16_t j; LOAD(k); for (j = 0; j < 4; j++) b += vz*w1 + vy*w0, a += vy*w1 - vz*w0; }

      float a, b;

      zlin   = xl;
      zlin = xr;
      zlin = xl;
      zlin = xr;
      zlin   = xl;
      zlin = xr;
      zlin = xl;
      zlin = xr;

      S0(0) S2(1) S1(2) S2(3) S1(4) S2(5) S1(6) S2(7)
                dstr[(15 - i)*nch] = mp3d_scale_pcm(a);
                dstr[(17 + i)*nch] = mp3d_scale_pcm(b);
      dstl[(15 - i)*nch] = mp3d_scale_pcm(a);
      dstl[(17 + i)*nch] = mp3d_scale_pcm(b);
                dstr[(47 - i)*nch] = mp3d_scale_pcm(a);
                dstr[(49 + i)*nch] = mp3d_scale_pcm(b);
      dstl[(47 - i)*nch] = mp3d_scale_pcm(a);
      dstl[(49 + i)*nch] = mp3d_scale_pcm(b);
    }
}

经循环展开,增加中间变量,保存临时计算结果,避免重复计算。
改进后的源码如下
static void mp3d_synth(float *xl, int16_t *dstl, int nch, float *lins)
{
    int i;       
//    float *xr = xl;
//    int16_t *dstr = dstl;

    static const float g_win[] = {
      -1,26,-31,208,218,401,-519,2063,2000,4788,-5517,7134,5959,35640,-39336,74992,
      -1,24,-35,202,222,347,-581,2080,1952,4425,-5879,7640,5288,33791,-41176,74856,
      -1,21,-38,196,225,294,-645,2087,1893,4063,-6237,8092,4561,31947,-43006,74630,
      -1,19,-41,190,227,244,-711,2085,1822,3705,-6589,8492,3776,30112,-44821,74313,
      -1,17,-45,183,228,197,-779,2075,1739,3351,-6935,8840,2935,28289,-46617,73908,
      -1,16,-49,176,228,153,-848,2057,1644,3004,-7271,9139,2037,26482,-48390,73415,
      -2,14,-53,169,227,111,-919,2032,1535,2663,-7597,9389,1082,24694,-50137,72835,
      -2,13,-58,161,224,72,-991,2001,1414,2330,-7910,9592,70,22929,-51853,72169,
      -2,11,-63,154,221,36,-1064,1962,1280,2006,-8209,9750,-998,21189,-53534,71420,
      -2,10,-68,147,215,2,-1137,1919,1131,1692,-8491,9863,-2122,19478,-55178,70590,
      -3,9,-73,139,208,-29,-1210,1870,970,1388,-8755,9935,-3300,17799,-56778,69679,
      -3,8,-79,132,200,-57,-1283,1817,794,1095,-8998,9966,-4533,16155,-58333,68692,
      -4,7,-85,125,189,-83,-1356,1759,605,814,-9219,9959,-5818,14548,-59838,67629,
      -4,7,-91,117,177,-106,-1428,1698,402,545,-9416,9916,-7154,12980,-61289,66494,
      -5,6,-97,111,163,-127,-1498,1634,185,288,-9585,9838,-8540,11455,-62684,65290
    };

    float *zlin = lins + 15*64;
    const float *w = g_win;
       
    zlin   = xl;
//    zlin = xr;
    zlin = xl;
//    zlin = xr;

    zlin   = xl;
//    zlin = xr;
    zlin = xl;
//    zlin = xr;

//    mp3d_synth_pair(dstr, 1, lins + 4*15 + 1);
//    mp3d_synth_pair(dstr + 32, 1, lins + 4*15 + 64 + 1);
    mp3d_synth_pair(dstl, 1, lins + 4*15);
    mp3d_synth_pair(dstl + 32, 1, lins + 4*15 + 64);

    for (i = 14; i >= 0; i--)
    {
#define LOAD(k) float w0 = *w++; float w1 = *w++; float*vz = &zlin; float*vy = &zlin; float vzz = *vz; float vyy = *vy;
#define S0(k) {LOAD(k); b0= vzz*w1 + vyy*w0; a0= vzz*w0 - vyy*w1; vzz = vz; vyy = vy; b2= vzz*w1 + vyy*w0; a2= vzz*w0 - vyy*w1;}
#define S1(k) {LOAD(k); b0 += vzz*w1 + vyy*w0, a0 += vzz*w0 - vyy*w1; vzz = vz; vyy = vy; b2 += vzz*w1 + vyy*w0, a2 += vzz*w0 - vyy*w1;}
#define S2(k) {LOAD(k); b0 += vzz*w1 + vyy*w0, a0 += vyy*w1 - vzz*w0; vzz = vz; vyy = vy; b2 += vzz*w1 + vyy*w0, a2 += vyy*w1 - vzz*w0;}
                float a0, a2, b0, b2;

      zlin   = xl;
//      zlin = xr;
      zlin = xl;
//      zlin = xr;
      zlin   = xl;
//      zlin = xr;
      zlin = xl;
//      zlin = xr;
       
      S0(0) S2(1) S1(2) S2(3) S1(4) S2(5) S1(6) S2(7)
       
      dstl = mp3d_scale_pcm(a0);
      dstl = mp3d_scale_pcm(b0);
      dstl = mp3d_scale_pcm(a2);
      dstl = mp3d_scale_pcm(b2);
    }
}

health 发表于 2026-1-3 21:46:30

音频数据输出范围判断及浮点转整数
int16_t mp3d_scale_pcm(float sample)
高频调用,每个输出数据都要经过此函数处理。
改为inline函数减少调用开销,但C51 C251不支持inline,故使用宏代替。

原始函数
static int16_t mp3d_scale_pcm(float sample)
{       
        int16_t s;
    if (sample >=32766.5) return (int16_t) 32767;
    if (sample <= -32767.5) return (int16_t)-32768;
    s = (int16_t)(sample + .5f);
    s -= (s < 0);   /* away from zero, to be compliant */
    return s;
}

修改后
#define mp3d_scale_pcm(sample)(sample >=32766.5) ? (int16_t)32767 : ((sample <= -32767.5) ? (uint16_t)(-32768) : (uint16_t)sample)

因几乎所有数据均在-32768~32767之间,只有个别异常数据会超出int16范围,饱和截断。
执行判断时,把最有可能成立的条件,放在执行时间最短的路径,总体运行会更快。
调整判断顺序为
#define mp3d_scale_pcm(sample)(sample <32766.5) ? ((sample > -32767.5) ? (uint16_t)sample : (uint16_t)(-32768)) : (int16_t)32767

神农鼎 发表于 2026-1-6 17:19:10

能否给些具体建议,我们后续 TFPU/MDU32/DSP 协处理器如何增加 MP3解码的加速器

health 发表于 2026-1-6 22:16:04

神农鼎 发表于 2026-1-6 17:19
能否给些具体建议,我们后续 TFPU/MDU32/DSP 协处理器如何增加 MP3解码的加速器 ...
浮点计算还是太慢了,速度快还是得用定点算法。
加速 MP3解码 浮点运算,除了频率提升,
就是加大乘法器和加法器的数量,并行计算,
类似于SIMD指令。

神农鼎 发表于 2026-1-7 10:53:23

health 发表于 2026-1-6 22:16
浮点计算还是太慢了,速度快还是得用定点算法。
加速 MP3解码 浮点运算,除了频率提升,
就是加大乘法器和 ...
帮定义 几条 需要的指令,往哪送,得到啥结果,回到哪

health 发表于 2026-1-8 12:02:01

神农鼎 发表于 2026-1-7 10:53
帮定义 几条 需要的指令,往哪送,得到啥结果,回到哪
这方面我懂的不多,先随便抛个砖。

MOV DMBIR,#op op op op
8位指令码分成4部分,每部分2bit,
00 无操作
01 乘法
10 加法
11 待定

四路运算器并行计算,
DR4= DR4(op) DR0
DR12 = DR12 (op) DR8
DR20 = DR20 (op) DR16
DR28 = DR28 (op) DR24

举例
MOV DMBIR, #0b00 01 10 01
即表示
DR4= DR4* DR0
DR12 = DR12 + DR8
DR20 = DR20 * DR16
DR28 无操作
页: 1 2 3 [4] 5
查看完整版本: MP3解码播放流畅@Ai8051U核心板-擎天柱,8051U移植minimp3解码库