概述:
闲着也是闲着,就学习了下LibMad解码MP3(解码成PCM数据流),顺便把Windows上播放PCM,以及PCM文件转换成WAV文件学习了下。以前做过PCM转WAV,原理很简单,就是在PCM流前面加上一个WAV数据头。借鉴了网上的一些文章,感谢大家。
LIbMad解码部分:
在初始化LibMad前,我们需要定义回调函数
//读取mp3资源的函数
mad_flow input_fun(void *data, struct mad_stream *stream)
{
MP3File* pMp3 = (MP3File*)data;
if ( stream->buffer == NULL )
{
mad_stream_buffer(stream, pMp3->szBuffer, pMp3->nBufferUse);
return MAD_FLOW_CONTINUE;
}
pMp3->nBufferPos = stream->next_frame - pMp3->szBuffer;
int nRemain = pMp3->nBufferUse - pMp3->nBufferPos;
memcpy(pMp3->szBuffer, pMp3->szBuffer+pMp3->nBufferPos, nRemain);
size_t nRead = fread(pMp3->szBuffer+nRemain, 1, pMp3->nBufferPos, pMp3->fp);
if ( nRead <= 0 )
{
return MAD_FLOW_STOP;
}
pMp3->nBufferPos = 0;
pMp3->nBufferUse = nRemain + nRead;
mad_stream_buffer(stream, pMp3->szBuffer, pMp3->nBufferUse);
return MAD_FLOW_CONTINUE;
}
//处理mp3头部信息的函数
mad_flow header_fun(void *data, struct mad_header const *header)
{
return MAD_FLOW_CONTINUE;
}
输出函数
mad_flow output_fun(void *data, struct mad_header const *header, struct mad_pcm *pcm)
{
int *left_ch = pcm->samples[0], *right_ch = pcm->samples[1];
int nLength = pcm->length;
int nMalloc = nLength*2;
if (pcm->channels == 2)//双声道,存储空间扩大4倍
nMalloc = nLength * 4;
if ( g_pBuffer == NULL )
g_pBuffer = (unsigned char*)malloc(nMalloc);
else
{
if ( g_nSize<nMalloc )
{
free(g_pBuffer);
g_pBuffer = (unsigned char*)malloc(nMalloc);
}
}
g_nSize = nMalloc;
unsigned char* pBase = g_pBuffer;
for (int i = 0; i < nLength; ++i)
{
signed int sample = scale(*left_ch++);
*(pBase++) = sample >> 0;
*(pBase++) = sample >> 8;
if (pcm->channels == 2)
{
signed int sample = scale(*right_ch++);
*(pBase++) = sample >> 0;
*(pBase++) = sample >> 8;
}
}
//播放
g_pcmPlayer.Play(g_pBuffer, nMalloc);
// FILE* fp = fopen("mp3.dat", "ab+");
// if( fp )
// {
// fwrite(pBase, 1, nMalloc, fp);
// fclose(fp);
// }
g_nFrames&#