Mp3算法在 cortex上的移植
前些日子搞了一个产品,使用的是 cortex-m3芯片,涉及到音频部分,由于在裸板上做,Libmad
需要资源较多,所以就 helix_mp3
移植
1. 下载 helix_mp3包
2. 编辑\helix_mp3\real\assembly.h
#ifndef _ASSEMBLY_H
#define _ASSEMBLY_H
static __inline int MULSHIFT32(int x, int y)
{
int ret;
long long temp=x;
temp = temp*y;
ret = (int)(temp>>32);
return ret;
/*
__asm {
mov eax, x
imul y
mov eax, edx
}
*/
}
static __inline int FASTABS(int x)
{
int sign;
sign = x >> (sizeof(int) * 8 - 1);
x ^= sign;
x -= sign;
return x;
}
static __inline int CLZ(int x)
{
int numZeros;
if (!x)
return (sizeof(int) * 8);
numZeros = 0;
while (!(x & 0x80000000)) {
numZeros++;
x <<= 1;
}
return numZeros;
}
/* MADD64, SHL64, SAR64:
* write in assembly to avoid dependency on run-time lib for 64-bit shifts, muls
* (sometimes compiler thunks to function calls instead of code generating)
* required for Symbian emulator
*/
//typedef long long __int64;
//typedef __int64 Word64;
static __inline long long MADD64(long long sum, int x, int y)
{
/*
unsigned int sumLo = ((unsigned int *)&sum)[0];
int sumHi = ((int *)&sum)[1];
__asm {
mov eax, x
imul y
add eax, sumLo
adc edx, sumHi
}
*/
return (sum + ((long long)x * y));
}
/*
static __inline Word64 SHL64(Word64 x, int n)
{
unsigned int xLo = ((unsigned int *)&x)[0];
int xHi = ((int *)&x)[1];
unsigned char nb = (unsigned char)n;
if (n < 32) {
__asm {
mov edx, xHi
mov eax, xLo
mov cl, nb
shld edx, eax, cl
shl eax, cl
}
} else if (n < 64) {
// shl masks cl to 0x1f
__asm {
mov edx, xLo
mov cl, nb
xor eax, eax
shl edx, cl
}
} else {
__asm {
xor edx, edx
xor eax, eax
}
}
}
*/
static __inline long long SAR64(long long x, int n)
{
long long ret = x;
ret = ret>>n;
return ret;
/*
unsigned int xLo = ((unsigned int *)&x)[0];
int xHi = ((int *)&x)[1];
unsigned char nb = (unsigned char)n;
// if (n < 32)
{
__asm {
mov edx, xHi
mov eax, xLo
mov cl, nb
shrd eax, edx, cl
sar edx, cl
}
}
else if (n < 64) {
// sar masks cl to 0x1f
__asm {
mov edx, xHi
mov eax, xHi
mov cl, nb
sar edx, 31
sar eax, cl
}
} else {
__asm {
sar xHi, 31
mov eax, xHi
mov edx, xHi
}
}
*/
}
#endif /* _ASSEMBLY_H */
这里只把汇编转化为 C代码
使用
1. 环境MDK3.40
2. 加入文件
3. 增加路径
4. 加入头文件
a) #include "third_party/helix_mp3/pub/mp3dec.h"
5. 播放代码
if((g_ulFlags & BUFFER_PLAYING) && (g_ulFlags & BUFFER_PAUSE)==0)
{
if(g_pcmSel>=ONE_SMPLE_SIZE)
{
//somewhat arbitrary trigger to refill buffer –
//should always be enough for a full frame
if (bytesLeft < 2*MAINBUF_SIZE && !eofReached)
{
nRead = FillReadBuffer(readBuf, readPtr,
READBUF_SIZE, bytesLeft, &g_sFileObject);
bytesLeft += nRead;
readPtr = readBuf;
if (nRead == 0) eofReached = 1;
}
//find start of next MP3 frame - assume EOF if no sync found
offset = MP3FindSyncWord(readPtr, bytesLeft);
if (offset < 0)
{
outOfData = 1;
//break;
}
else
{
readPtr += offset;
bytesLeft -= offset;
// decode one MP3 frame - if offset < 0 then bytesLeft was less than a full frame
err=MP3Decode(hMP3Decoder, &readPtr,
&bytesLeft,g_pcmBuf+4608-g_pcmSel, 0);
nFrames++;
if (err) // error occurred
{
switch (err) {
case ERR_MP3_INDATA_UNDERFLOW:
outOfData = 1;
break;
:// do nothing - next call to decode will provide more mainData
case ERR_MP3_MAINDATA_UNDERFLOW
break;
case ERR_MP3_FREE_BITRATE_SYNC:
default:
outOfData = 1;
break;
}
}
else // no error
{
MP3GetLastFrameInfo(hMP3Decoder, &mp3FrameInfo);
if(nFrames == 1)
{
usprintf(g_pcFormat, "%d Hz %d bit ",
mp3FrameInfo.samprate,mp3FrameInfo.bitrate);
if(mp3FrameInfo.nChans == 1)
strcat(g_pcFormat, "Mono");
else
strcat(g_pcFormat, "Stereo");
SoundSetFormat(mp3FrameInfo.samprate,
mp3FrameInfo.bitsPerSample,mp3FrameInfo.nChans);
}
// if(xx > mp3FrameInfo.outputSamps) xx = 10;
g_pcmSel -= mp3FrameInfo.outputSamps;
}
// udp_sendx((u8_t *)g_pucBuffer,xx); //将解码数据发送给服务端
}
}
//这里使用两个缓存,边解码边播放
if(g_pcmSel <= (MP3_DECODE_BUF_SIZE - 1024))
{
if(g_ulFlags & BUFFER_BOTTOM_EMPTY)
{
memmove(g_pucBuffer,g_pcmBuf,1024*sizeof(short));
memmove(g_pcmBuf,g_pcmBuf+1024,
(MP3_DECODE_BUF_SIZE-1024)*sizeof(short));
SoundBufferPlay(g_pucBuffer,1024*sizeof(short), BufferCallback);
g_pcmSel+=1024;
g_ulFlags &= ~BUFFER_BOTTOM_EMPTY;
}
else if(g_ulFlags & BUFFER_TOP_EMPTY)
{
memmove(&g_pucBuffer[AUDIO_BUFFER_SIZE>>1],
g_pcmBuf,1024*sizeof(short));
memmove(g_pcmBuf,g_pcmBuf+1024,
(MP3_DECODE_BUF_SIZE-1024)*sizeof(short));
g_pcmSel+=1024;
SoundBufferPlay(&g_pucBuffer[AUDIO_BUFFER_SIZE>>1],
1024*sizeof(short), BufferCallback);
g_ulFlags &= ~BUFFER_TOP_EMPTY;
DisplayTime();
}
}
}
测试板子