找回密码
 立即注册
楼主: health

MP3解码播放流畅@Ai8051U核心板-擎天柱,8051U移植minimp3解码库

[复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:424
  • 最近打卡:2026-01-09 07:47:24
已绑定手机

6

主题

113

回帖

1098

积分

金牌会员

积分
1098
发表于 2025-12-27 09:23:10 | 显示全部楼层
bat*** 发表于 2025-12-27 09:05
不知道什么原因最后的时候会有杂音

找到了原因extern const unsigned char song[27510];
长度和song文件的设置不一致导致的


回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:111
  • 最近打卡:2026-01-09 00:32:58

21

主题

184

回帖

1749

积分

金牌会员

积分
1749
发表于 2025-12-29 21:46:40 | 显示全部楼层
bat*** 发表于 2025-12-27 09:23
找到了原因extern const unsigned char song[27510];
长度和song文件的设置不一致导致的

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

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:424
  • 最近打卡:2026-01-09 07:47:24
已绑定手机

6

主题

113

回帖

1098

积分

金牌会员

积分
1098
发表于 2025-12-30 04:45:50 | 显示全部楼层
hea*** 发表于 2025-12-29 21:46
你这个是用C版本播的还是汇编播的?

汇编的C的卡的有点严重
回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:111
  • 最近打卡:2026-01-09 00:32:58

21

主题

184

回帖

1749

积分

金牌会员

积分
1749
发表于 6 天前 | 显示全部楼层
minimp3针对STC MCU和C251继续优化。
先找出性能瓶颈,再针对性重点处理。

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

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

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:111
  • 最近打卡:2026-01-09 00:32:58

21

主题

184

回帖

1749

积分

金牌会员

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

原始程序

  1. static void mp3d_synth(float *xl, mp3d_sample_t *dstl, int nch, float *lins)
  2. {
  3.     int i;
  4.     float *xr = xl + 576*(nch - 1);
  5.     mp3d_sample_t *dstr = dstl + (nch - 1);
  6.     static const float g_win[] = {
  7.         -1,26,-31,208,218,401,-519,2063,2000,4788,-5517,7134,5959,35640,-39336,74992,
  8.         -1,24,-35,202,222,347,-581,2080,1952,4425,-5879,7640,5288,33791,-41176,74856,
  9.         -1,21,-38,196,225,294,-645,2087,1893,4063,-6237,8092,4561,31947,-43006,74630,
  10.         -1,19,-41,190,227,244,-711,2085,1822,3705,-6589,8492,3776,30112,-44821,74313,
  11.         -1,17,-45,183,228,197,-779,2075,1739,3351,-6935,8840,2935,28289,-46617,73908,
  12.         -1,16,-49,176,228,153,-848,2057,1644,3004,-7271,9139,2037,26482,-48390,73415,
  13.         -2,14,-53,169,227,111,-919,2032,1535,2663,-7597,9389,1082,24694,-50137,72835,
  14.         -2,13,-58,161,224,72,-991,2001,1414,2330,-7910,9592,70,22929,-51853,72169,
  15.         -2,11,-63,154,221,36,-1064,1962,1280,2006,-8209,9750,-998,21189,-53534,71420,
  16.         -2,10,-68,147,215,2,-1137,1919,1131,1692,-8491,9863,-2122,19478,-55178,70590,
  17.         -3,9,-73,139,208,-29,-1210,1870,970,1388,-8755,9935,-3300,17799,-56778,69679,
  18.         -3,8,-79,132,200,-57,-1283,1817,794,1095,-8998,9966,-4533,16155,-58333,68692,
  19.         -4,7,-85,125,189,-83,-1356,1759,605,814,-9219,9959,-5818,14548,-59838,67629,
  20.         -4,7,-91,117,177,-106,-1428,1698,402,545,-9416,9916,-7154,12980,-61289,66494,
  21.         -5,6,-97,111,163,-127,-1498,1634,185,288,-9585,9838,-8540,11455,-62684,65290
  22.     };
  23.     float *zlin = lins + 15*64;
  24.     const float *w = g_win;
  25.     zlin[4*15]     = xl[18*16];
  26.     zlin[4*15 + 1] = xr[18*16];
  27.     zlin[4*15 + 2] = xl[0];
  28.     zlin[4*15 + 3] = xr[0];
  29.     zlin[4*31]     = xl[1 + 18*16];
  30.     zlin[4*31 + 1] = xr[1 + 18*16];
  31.     zlin[4*31 + 2] = xl[1];
  32.     zlin[4*31 + 3] = xr[1];
  33.     mp3d_synth_pair(dstr, nch, lins + 4*15 + 1);
  34.     mp3d_synth_pair(dstr + 32*nch, nch, lins + 4*15 + 64 + 1);
  35.     mp3d_synth_pair(dstl, nch, lins + 4*15);
  36.     mp3d_synth_pair(dstl + 32*nch, nch, lins + 4*15 + 64);
  37.     for (i = 14; i >= 0; i--)
  38.     {
  39. #define LOAD(k) float w0 = *w++; float w1 = *w++; float *vz = &zlin[4*i - k*64]; float *vy = &zlin[4*i - (15 - k)*64];               
  40. #define S0(k) { uint16_t j; LOAD(k); for (j = 0; j < 4; j++) b[j]  = vz[j]*w1 + vy[j]*w0, a[j]  = vz[j]*w0 - vy[j]*w1; }       
  41. #define S1(k) { uint16_t j; LOAD(k); for (j = 0; j < 4; j++) b[j] += vz[j]*w1 + vy[j]*w0, a[j] += vz[j]*w0 - vy[j]*w1; }       
  42. #define S2(k) { uint16_t j; LOAD(k); for (j = 0; j < 4; j++) b[j] += vz[j]*w1 + vy[j]*w0, a[j] += vy[j]*w1 - vz[j]*w0; }
  43.         float a[4], b[4];
  44.         zlin[4*i]     = xl[18*(31 - i)];
  45.         zlin[4*i + 1] = xr[18*(31 - i)];
  46.         zlin[4*i + 2] = xl[1 + 18*(31 - i)];
  47.         zlin[4*i + 3] = xr[1 + 18*(31 - i)];
  48.         zlin[4*(i + 16)]   = xl[1 + 18*(1 + i)];
  49.         zlin[4*(i + 16) + 1] = xr[1 + 18*(1 + i)];
  50.         zlin[4*(i - 16) + 2] = xl[18*(1 + i)];
  51.         zlin[4*(i - 16) + 3] = xr[18*(1 + i)];
  52.         S0(0) S2(1) S1(2) S2(3) S1(4) S2(5) S1(6) S2(7)
  53.                 dstr[(15 - i)*nch] = mp3d_scale_pcm(a[1]);
  54.                 dstr[(17 + i)*nch] = mp3d_scale_pcm(b[1]);
  55.         dstl[(15 - i)*nch] = mp3d_scale_pcm(a[0]);
  56.         dstl[(17 + i)*nch] = mp3d_scale_pcm(b[0]);
  57.                 dstr[(47 - i)*nch] = mp3d_scale_pcm(a[3]);
  58.                 dstr[(49 + i)*nch] = mp3d_scale_pcm(b[3]);
  59.         dstl[(47 - i)*nch] = mp3d_scale_pcm(a[2]);
  60.         dstl[(49 + i)*nch] = mp3d_scale_pcm(b[2]);
  61.     }
  62. }
复制代码


经循环展开,增加中间变量,保存临时计算结果,避免重复计算。
改进后的源码如下
  1. static void mp3d_synth(float *xl, int16_t *dstl, int nch, float *lins)
  2. {
  3.     int i;       
  4. //    float *xr = xl;
  5. //    int16_t *dstr = dstl;
  6.     static const float g_win[] = {
  7.         -1,26,-31,208,218,401,-519,2063,2000,4788,-5517,7134,5959,35640,-39336,74992,
  8.         -1,24,-35,202,222,347,-581,2080,1952,4425,-5879,7640,5288,33791,-41176,74856,
  9.         -1,21,-38,196,225,294,-645,2087,1893,4063,-6237,8092,4561,31947,-43006,74630,
  10.         -1,19,-41,190,227,244,-711,2085,1822,3705,-6589,8492,3776,30112,-44821,74313,
  11.         -1,17,-45,183,228,197,-779,2075,1739,3351,-6935,8840,2935,28289,-46617,73908,
  12.         -1,16,-49,176,228,153,-848,2057,1644,3004,-7271,9139,2037,26482,-48390,73415,
  13.         -2,14,-53,169,227,111,-919,2032,1535,2663,-7597,9389,1082,24694,-50137,72835,
  14.         -2,13,-58,161,224,72,-991,2001,1414,2330,-7910,9592,70,22929,-51853,72169,
  15.         -2,11,-63,154,221,36,-1064,1962,1280,2006,-8209,9750,-998,21189,-53534,71420,
  16.         -2,10,-68,147,215,2,-1137,1919,1131,1692,-8491,9863,-2122,19478,-55178,70590,
  17.         -3,9,-73,139,208,-29,-1210,1870,970,1388,-8755,9935,-3300,17799,-56778,69679,
  18.         -3,8,-79,132,200,-57,-1283,1817,794,1095,-8998,9966,-4533,16155,-58333,68692,
  19.         -4,7,-85,125,189,-83,-1356,1759,605,814,-9219,9959,-5818,14548,-59838,67629,
  20.         -4,7,-91,117,177,-106,-1428,1698,402,545,-9416,9916,-7154,12980,-61289,66494,
  21.         -5,6,-97,111,163,-127,-1498,1634,185,288,-9585,9838,-8540,11455,-62684,65290
  22.     };
  23.     float *zlin = lins + 15*64;
  24.     const float *w = g_win;
  25.        
  26.     zlin[4*15]     = xl[18*16];
  27. //    zlin[4*15 + 1] = xr[18*16];
  28.     zlin[4*15 + 2] = xl[0];
  29. //    zlin[4*15 + 3] = xr[0];
  30.     zlin[4*31]     = xl[1 + 18*16];
  31. //    zlin[4*31 + 1] = xr[1 + 18*16];
  32.     zlin[4*31 + 2] = xl[1];
  33. //    zlin[4*31 + 3] = xr[1];
  34. //    mp3d_synth_pair(dstr, 1, lins + 4*15 + 1);
  35. //    mp3d_synth_pair(dstr + 32, 1, lins + 4*15 + 64 + 1);
  36.     mp3d_synth_pair(dstl, 1, lins + 4*15);
  37.     mp3d_synth_pair(dstl + 32, 1, lins + 4*15 + 64);
  38.     for (i = 14; i >= 0; i--)
  39.     {
  40. #define LOAD(k) float w0 = *w++; float w1 = *w++; float  *vz = &zlin[4*i - k*64]; float  *vy = &zlin[4*i - (15 - k)*64]; float vzz = *vz; float vyy = *vy;
  41. #define S0(k) {LOAD(k); b0  = vzz*w1 + vyy*w0; a0  = vzz*w0 - vyy*w1; vzz = vz[2]; vyy = vy[2]; b2  = vzz*w1 + vyy*w0; a2  = vzz*w0 - vyy*w1;}
  42. #define S1(k) {LOAD(k); b0 += vzz*w1 + vyy*w0, a0 += vzz*w0 - vyy*w1; vzz = vz[2]; vyy = vy[2]; b2 += vzz*w1 + vyy*w0, a2 += vzz*w0 - vyy*w1;}
  43. #define S2(k) {LOAD(k); b0 += vzz*w1 + vyy*w0, a0 += vyy*w1 - vzz*w0; vzz = vz[2]; vyy = vy[2]; b2 += vzz*w1 + vyy*w0, a2 += vyy*w1 - vzz*w0;}
  44.                 float a0, a2, b0, b2;
  45.         zlin[4*i]     = xl[18*(31 - i)];
  46. //        zlin[4*i + 1] = xr[18*(31 - i)];
  47.         zlin[4*i + 2] = xl[1 + 18*(31 - i)];
  48. //        zlin[4*i + 3] = xr[1 + 18*(31 - i)];
  49.         zlin[4*(i + 16)]     = xl[1 + 18*(1 + i)];
  50. //        zlin[4*(i + 16) + 1] = xr[1 + 18*(1 + i)];
  51.         zlin[4*(i - 16) + 2] = xl[18*(1 + i)];
  52. //        zlin[4*(i - 16) + 3] = xr[18*(1 + i)];
  53.        
  54.         S0(0) S2(1) S1(2) S2(3) S1(4) S2(5) S1(6) S2(7)
  55.        
  56.         dstl[15 - i] = mp3d_scale_pcm(a0);
  57.         dstl[17 + i] = mp3d_scale_pcm(b0);
  58.         dstl[47 - i] = mp3d_scale_pcm(a2);
  59.         dstl[49 + i] = mp3d_scale_pcm(b2);
  60.     }
  61. }
复制代码
回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:111
  • 最近打卡:2026-01-09 00:32:58

21

主题

184

回帖

1749

积分

金牌会员

积分
1749
发表于 6 天前 | 显示全部楼层
音频数据输出范围判断及浮点转整数
int16_t mp3d_scale_pcm(float sample)
高频调用,每个输出数据都要经过此函数处理。
改为inline函数减少调用开销,但C51 C251不支持inline,故使用宏代替。

原始函数
  1. static int16_t mp3d_scale_pcm(float sample)
  2. {       
  3.         int16_t s;
  4.     if (sample >=  32766.5) return (int16_t) 32767;
  5.     if (sample <= -32767.5) return (int16_t)-32768;
  6.     s = (int16_t)(sample + .5f);
  7.     s -= (s < 0);   /* away from zero, to be compliant */
  8.     return s;
  9. }
复制代码


修改后
#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
1 喜欢他/她就送朵鲜花吧,赠人玫瑰,手有余香!
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:290
  • 最近打卡:2026-01-09 10:19:02

819

主题

1万

回帖

2万

积分

管理员

积分
21729
发表于 3 天前 | 显示全部楼层
能否给些具体建议,我们后续 TFPU/MDU32/DSP 协处理器如何增加 MP3解码的加速器
回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:111
  • 最近打卡:2026-01-09 00:32:58

21

主题

184

回帖

1749

积分

金牌会员

积分
1749
发表于 3 天前 | 显示全部楼层
神*** 发表于 2026-1-6 17:19
能否给些具体建议,我们后续 TFPU/MDU32/DSP 协处理器如何增加 MP3解码的加速器 ...

浮点计算还是太慢了,速度快还是得用定点算法。
加速 MP3解码 浮点运算,除了频率提升,

就是加大乘法器和加法器的数量,并行计算,
类似于SIMD指令。

点评

帮定义几条需要的指令,往哪送,得到啥结果,回到哪  详情 回复 发表于 前天 10:53
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:290
  • 最近打卡:2026-01-09 10:19:02

819

主题

1万

回帖

2万

积分

管理员

积分
21729
发表于 前天 10:53 | 显示全部楼层
hea*** 发表于 2026-1-6 22:16
浮点计算还是太慢了,速度快还是得用定点算法。
加速 MP3解码 浮点运算,除了频率提升,
就是加大乘法器和 ...

帮定义 几条 需要的指令,往哪送,得到啥结果,回到哪
回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:111
  • 最近打卡:2026-01-09 00:32:58

21

主题

184

回帖

1749

积分

金牌会员

积分
1749
发表于 昨天 12:02 | 显示全部楼层
神*** 发表于 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 无操作

回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-1-9 21:07 , Processed in 0.115809 second(s), 91 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表