流媒体MP3播放器教程Word格式.docx
- 文档编号:17895546
- 上传时间:2022-12-11
- 格式:DOCX
- 页数:20
- 大小:87.48KB
流媒体MP3播放器教程Word格式.docx
《流媒体MP3播放器教程Word格式.docx》由会员分享,可在线阅读,更多相关《流媒体MP3播放器教程Word格式.docx(20页珍藏版)》请在冰豆网上搜索。
structmad_stream,structmad_synth,structmad_frame。
它们的定义如下:
清单1:
libmad中的主要数据结构
structmad_stream{
unsignedcharconst*buffer;
/*inputbitstreambuffer*/
unsignedcharconst*bufend;
/*endofbuffer*/
unsignedlongskiplen;
/*bytestoskipbeforenextframe*/
intsync;
/*streamsyncfound*/
unsignedlongfreerate;
/*freebitrate(fixed)*/
unsignedcharconst*this_frame;
/*startofcurrentframe*/
unsignedcharconst*next_frame;
/*startofnextframe*/
structmad_bitptrptr;
/*currentprocessingbitpointer*/
structmad_bitptranc_ptr;
/*ancillarybitspointer*/
unsignedintanc_bitlen;
/*numberofancillarybits*/
unsignedchar(*main_data)[MAD_BUFFER_MDLEN];
/*LayerIIImain_data()*/
unsignedintmd_len;
/*bytesinmain_data*/
intoptions;
/*decodingoptions(seebelow)*/
enummad_errorerror;
/*errorcode(seeabove)*/
};
更多内容请看流媒体播放器
流媒体文件格式播放技巧专题,或
如果缓冲区最后一个MPEG数据帧只有部分数据包括在缓冲区中,那么structmad_stream中的next_frame域指到不完整数据的开始地址。
∙由于缓冲区的MPEG数据帧不一定完整,所以不完整的MPEG帧的数据必须拷贝到下一次解码操作的缓冲区中,进行再次解码。
这里我们还看到bufend指向缓冲区数据的最后地址,也就是最后一字节的地址加1的位置。
mad_stream.bufend–mad_stream.next_frame就是剩余的未被解码的MPEG帧的数据的字节数量(假设此帧在缓冲区中不完整)。
mad_stream的error域用来记录操作mad_stream得到的错误代码。
错误代码在mad.h中有很详细的定义。
∙清单2:
错误代码在mad.h中的详细定义
∙structmad_synth{
∙mad_fixed_tfilter[2][2][2][16][8];
/*polyphasefilterbankoutputs*/
∙/*[ch][eo][peo][s][v]*/
∙unsignedintphase;
/*currentprocessingphase*/
∙structmad_pcmpcm;
/*PCMoutput*/
∙};
mad_synth中的关键域pcm保存解码和合成后得到的PCM数据。
清单3:
mad_synth中的关键域
structmad_pcm{
unsignedintsamplerate;
/*samplingfrequency(Hz)*/
unsignedshortchannels;
/*numberofchannels*/
unsignedshortlength;
/*numberofsamplesperchannel*/
mad_fixed_tsamples[2][1152];
/*PCMoutputsamples[ch][sample]*/
structmad_pcm定义了音频的采样率、每个声道个数以及最后的PCM采样数据。
这些参数可用来初始化音频设备。
清单4:
structmad_pcm
structmad_frame{
structmad_headerheader;
/*MPEGaudioheader*/
/*decodingoptions(fromstream)*/
mad_fixed_tsbsample[2][36][32];
/*synthesissubbandfiltersamples*/
mad_fixed_t(*overlap)[2][32][18];
/*LayerIIIblockoverlapdata*/
mad_frame是记录MPEG帧解码后的数据的数据结构,其中的mad_header尤其重要,其用来记录MPEG帧的一些基本信息,比如MPEG层数、声道模式、流比特率、采样比特率等等。
声道模式包括单声道、双声道、联合立体混音声以及一般立体声。
清单5:
mad_frame
enummad_mode{
MAD_MODE_SINGLE_CHANNEL=0,/*singlechannel*/
MAD_MODE_DUAL_CHANNEL=1,/*dualchannel*/
MAD_MODE_JOINT_STEREO=2,/*joint(MS/intensity)stereo*/
MAD_MODE_STEREO=3/*normalLRstereo*/
structmad_header{
enummad_layerlayer;
/*audiolayer(1,2,or3)*/
enummad_modemode;
/*channelmode*/
intmode_extension;
/*additionalmodeinfo*/
enummad_emphasisemphasis;
/*de-emphasistouse*/
unsignedlongbitrate;
/*streambitrate(bps)*/
unsignedshortcrc_check;
/*frameCRCaccumulator*/
unsignedshortcrc_target;
/*finaltargetCRCchecksum*/
intflags;
/*flags*/
intprivate_bits;
/*privatebits*/
mad_timer_tduration;
/*audioplayingtimeofframe*/
∙下面就本文使用的API的功能做简单介绍。
在本文中用到的API包括:
voidmad_stream_init(structmad_stream*)
voidmad_synth_init(structmad_synth*);
voidmad_frame_init(structmad_frame*);
以上3个API初始化解码需要的数据结构。
voidmad_stream_buffer(structmad_stream*,unsignedcharconst*,unsignedlong);
此函数把原始的未解码的MPEG数据和mad_stream数据结构关联,以便使用mad_frame_decode()来解码MPEG帧数据。
intmad_frame_decode(structmad_frame*,structmad_stream*);
把mad_stream中的MPEG帧数据解码。
voidmad_synth_frame(structmad_synth*,structmad_frameconst*);
把解码后的音频数据合成PCM采样。
voidmad_stream_finish(structmad_stream*);
voidmad_frame_finish(structmad_frame*);
mad_synth_finish(structmad_synth);
以上3个API在解码完毕后使用,释放libmad占用的资源等。
3.PCM音频设备的操作
对音频设备的操作主要是初始化音频设备以及往音频设备发送PCM(PulseCodeModulation)数据。
为了方便,本文使用ALSA(AdvancedLinuxSoundArchitecture)提供的库和驱动。
在编译和运行本文中的MP3流媒体播放器的时候,必须先安装ALSA相关的文件。
本文用到的主要对PCM设备操作的函数分为PCM设备初始化的函数以及PCM接口的一些操作函数。
PCM硬件设备参数设置和初始化的函数有:
intsnd_pcm_hw_params_malloc(snd_pcm_hw_params_t**ptr)
intsnd_pcm_hw_params_any(snd_pcm_t*pcm,snd_pcm_hw_params_t*params)
voidsnd_pcm_hw_params_free(snd_pcm_hw_params_t*obj)
intsnd_pcm_hw_params_set_Access(snd_pcm_t*pcm,
snd_pcm_hw_params_t*params,
snd_pcm_access_t_access)
intsnd_pcm_hw_params_set_format(snd_pcm_t*pcm,
snd_pcm_format_tval)
intsnd_pcm_hw_params_set_channels(snd_pcm_t*pcm,
unsignedintval)
intsnd_pcm_hw_params_set_rate_near(snd_pcm_t*pcm,
unsignedint*val,int*dir)
∙PCM接口的操作函数:
∙intsnd_pcm_hw_params(snd_pcm_t*pcm,snd_pcm_hw_params_t*params)
∙intsnd_pcm_prepare(snd_pcm_t*pcm)
∙intsnd_pcm_open(snd_pcm_t**pcm,constchar*name,
∙snd_pcm_stream_tstream,intmode)
∙intsnd_pcm_close(snd_pcm_t*pcm)
∙snd_pcm_sframes_tsnd_pcm_writei(snd_pcm_t*pcm,
∙constvoid*buffer,snd_pcm_uframes_tsize)
这些函数用到了snd_pcm_hw_params_t结构,此结构包含用来播放PCM数据流的硬件信息配置。
在往音频设备(声卡)写入音频数据之前,必须设置访问类型、采样格式、采样率、声道数等。
首先使用snd_pcm_open()打开PCM设备,在ALSA中,PCM设备都有名字与之对应。
比如我们可以定义PCM设备名字为char*pcm_name="
plughw:
0,0"
。
最重要的PCM设备接口是“plughw”以及“hw”接口。
使用“plughw”接口,程序员不必过多关心硬件,而且如果设置的配置参数和实际硬件支持的参数不一致,ALSA会自动转换数据。
如果使用“hw”接口,我们就必须检测硬件是否支持设置的参数了。
Plughw后面的两个数字分别表示设备号和次设备(subdevice)号。
snd_pcm_hw_params_malloc()在栈中分配snd_pcm_hw_params_t结构的空间,然后使用snd_pcm_hw_params_any()函数用声卡的全配置空间参数初始化已经分配的snd_pcm_hw_params_t结构。
snd_pcm_hw_params_set_access()设置访问类型,常用访问类型的宏定义有:
SND_PCM_ACCESS_RW_INTERLEAVED
交错访问。
在缓冲区的每个PCM帧都包含所有设置的声道的连续的采样数据。
比如声卡要播放采样长度是16-bit的PCM立体声数据,表示每个PCM帧中有16-bit的左声道数据,然后是16-bit右声道数据。
SND_PCM_ACCESS_RW_NONINTERLEAVED
非交错访问。
每个PCM帧只是一个声道需要的数据,如果使用多个声道,那么第一帧是第一个声道的数据,第二帧是第二个声道的数据,依此类推。
函数snd_pcm_hw_params_set_format()设置数据格式,主要控制输入的音频数据的类型、无符号还是有符号、是little-endian还是bit-endian。
比如对于16-bit长度的采样数据可以设置为:
∙SND_PCM_FORMAT_S16_LE有符号16bitLittleEndian
∙SND_PCM_FORMAT_S16_BE有符号16bitBigEndian
∙SND_PCM_FORMAT_U16_LE无符号16bitLittleEndian
∙SND_PCM_FORMAT_U16_BE无符号16bitBigEndian
∙
比如对于32-bit长度的采样数据可以设置为:
SND_PCM_FORMAT_S32_LE有符号32bitLittleEndian
SND_PCM_FORMAT_S32_BE有符号32bitBigEndian
SND_PCM_FORMAT_U32_LE无符号32bitLittleEndian
SND_PCM_FORMAT_U32_BE无符号32bitBigEndian
函数snd_pcm_hw_params_set_channels()设置音频设备的声道,常见的就是单声道和立体声,如果是立体声,设置最后一个参数为2。
snd_pcm_hw_params_set_rate_near()函数设置音频数据的最接近目标的采样率。
snd_pcm_hw_params()从设备配置空间选择一个配置,让函数snd_pcm_prepare()准备好PCM设备,以便写入PCM数据。
snd_pcm_writei()用来把交错的音频数据写入到音频设备。
初始化PCM设备的例程如下:
清单6:
初始化PCM设备的例程
/*openaPCMdevice*/
intopen_device(structmad_headerconst*header)
{
interr;
snd_pcm_hw_params_t*hw_params;
char*pcm_name="
;
intrate=header->
samplerate;
intchannels=2;
if(header->
mode==0){
channels=1;
}else{
channels=2;
}
if((err=snd_pcm_open(&
playback_handle,
pcm_name,SND_PCM_STREAM_PLAYBACK,0))<
0){
printf("
cannotopenaudiodevice%s(%s)\n"
pcm_name,
snd_strerror(err));
return-1;
if((err=snd_pcm_hw_params_malloc(&
hw_params))<
cannotallocatehardwareparameterstructure(%s)\n"
if((err=snd_pcm_hw_params_any(playback_handle,hw_params))<
cannotinitializehardwareparameterstructure(%s)\n"
if((err=snd_pcm_hw_params_set_access(playback_handle,hw_params,
SND_PCM_ACCESS_RW_INTERLEAVED))<
cannotsetaccesstype(%s)\n"
if((err=snd_pcm_hw_params_set_format(playback_handle,
hw_params,SND_PCM_FORMAT_S32_LE))<
cannotsetsampleformat(%s)\n"
if((err=snd_pcm_hw_params_set_rate_near(playback_handle,
hw_params,&
rate,0))<
cannotsetsamplerate(%s)\n"
if((err=snd_pcm_hw_params_set_channels(playback_handle,
hw_params,channels))<
cannotsetchannelcount(%s)\n"
if((err=snd_pcm_hw_params(playback_handle,
hw_params))<
cannotsetparameters(%s)\n"
snd_pcm_hw_params_free(hw_params);
if((err=snd_pcm_prepare(playback_handle))<
cannotprepareaudiointerfaceforuse(%s)\n"
return0;
}
∙这里配置的PCM格式是SND_PCM_FORMAT_S32_LE,采样的格式是每个采样有32-bit的数据,数据按照little-endian存放。
如果通过mad_frame_decode()函数得到PCM数据后,要求每个采样数据只占16-bit,需要把数据进行MAD的定点类型到signedshort
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 流媒体 MP3 播放 教程