batcd 发表于 2025-12-27 09:05
不知道什么原因最后的时候会有杂音
找到了原因extern const unsigned char song;
长度和song文件的设置不一致导致的
attach://126483.mp4
batcd 发表于 2025-12-27 09:23
找到了原因extern const unsigned char song;
长度和song文件的设置不一致导致的
你这个是用C版本播的还是汇编播的?
health 发表于 2025-12-29 21:46
你这个是用C版本播的还是汇编播的?
汇编的C的卡的有点严重
minimp3针对STC MCU和C251继续优化。
先找出性能瓶颈,再针对性重点处理。
keil软仿真下的性能分析,各函数执行时间占比。
虽然指令周期与STC硬件不完全相同,还有FPU硬件加速器的参与,绝对的执行时间并不符合真实硬件,但是比较各函数的相对比例还是有参考意义的。
由上图可见,mp3d_synth函数占据了大部分的执行时间。
因此,先拿mp3d_synth函数下手。
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);
}
}
音频数据输出范围判断及浮点转整数
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
能否给些具体建议,我们后续 TFPU/MDU32/DSP 协处理器如何增加 MP3解码的加速器
神农鼎 发表于 2026-1-6 17:19
能否给些具体建议,我们后续 TFPU/MDU32/DSP 协处理器如何增加 MP3解码的加速器 ...
浮点计算还是太慢了,速度快还是得用定点算法。
加速 MP3解码 浮点运算,除了频率提升,
就是加大乘法器和加法器的数量,并行计算,
类似于SIMD指令。
health 发表于 2026-1-6 22:16
浮点计算还是太慢了,速度快还是得用定点算法。
加速 MP3解码 浮点运算,除了频率提升,
就是加大乘法器和 ...
帮定义 几条 需要的指令,往哪送,得到啥结果,回到哪
神农鼎 发表于 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 无操作