ImageVerifierCode 换一换
格式:DOCX , 页数:20 ,大小:87.48KB ,
资源ID:4942137      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/4942137.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(流媒体MP3播放器教程.docx)为本站会员(b****3)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

流媒体MP3播放器教程.docx

1、流媒体MP3播放器教程基于libmad 的简单MP3流媒体播放器的实现介绍 本文在 Fedora 5 Linux 下实现了一个基于 libmad 的 mp3 流媒体播放器。此流媒体播放器可以播放基于 HTTP 1.1 协议传输的 MP3 流媒体数据。 基本原理是:从 HTTP 服务器获得 MP3 媒体信息,然后通过网络传输把 MP3 数据以数据流的形式接收到 MP3 流媒体播放器客户端,由客户端通过 libmad 解码 MP3 数据流,得到 PCM 音频数据,写入音频设备,播放音乐。本文的流媒体播放器只是实现了必要的简单功能,没有考虑太多情况。比如,没有考虑实时播放控制,这样的话就不能随意选取

2、播放点进行播放。 本文的 MP3 流媒体播放器创建两个线程,使用两个缓冲区保存 MP3 数据,可以一边下载数据,一边播放音乐。编译运行此 MP3 流媒体播放器需要安装 libmad ( 以及 ALSA(Advanced Linux Sound Architecture) (http:/www.alsa-project.org)相关的软件。ALSA包括4部分,分别是 sound driver, sound library , sound utilities 以及 tools。至少应该安装 sound driver, sound library 。编译程序时连接库的选项是:-lmad -lasou

3、nd -lpthread。 本文的 MP3 流媒体播放器使用双缓冲区,一个是数据接收缓冲区,另一个是数据解码缓冲区。主程序结构如下图所示,图中的蓝色线表示数据流向。图 1:MP3 流媒体播放器主程序结构图2libmad简介 MAD (libmad)是一个开源的高精度 MPEG 音频解码库,支持 MPEG-1(Layer I, Layer II 和 LayerIII(也就是 MP3)。LIBMAD 提供 24-bit 的 PCM 输出,完全是定点计算,非常适合没有浮点支持的平台上使用。使用 libmad 提供的一系列 API,就可以非常简单地实现 MP3 数据解码工作。在 libmad 的源代码

4、文件目录下的 mad.h 文件中,可以看到绝大部分该库的数据结构和 API 等。 本文用到的 libmad 中的主要数据结构有:struct mad_stream, struct mad_synth, struct mad_frame。它们的定义如下: 清单 1:libmad 中的主要数据结构 struct mad_stream unsigned char const *buffer; /* input bitstream buffer */ unsigned char const *bufend; /* end of buffer */ unsigned long skiplen; /* b

5、ytes to skip before next frame */ int sync; /* stream sync found */ unsigned long freerate; /* free bitrate (fixed) */ unsigned char const *this_frame; /* start of current frame */ unsigned char const *next_frame; /* start of next frame */ struct mad_bitptr ptr; /* current processing bit pointer */

6、struct mad_bitptr anc_ptr; /* ancillary bits pointer */ unsigned int anc_bitlen; /* number of ancillary bits */ unsigned char (*main_data)MAD_BUFFER_MDLEN;/* Layer III main_data() */ unsigned int md_len; /* bytes in main_data */ int options; /* decoding options (see below) */ enum mad_error error; /

7、* error code (see above) */; 更多内容请看流媒体播放器流媒体文件格式播放技巧专题,或 如果缓冲区最后一个 MPEG 数据帧只有部分数据包括在缓冲区中,那么 struct mad_stream 中的 next_frame 域指到不完整数据的开始地址。 由于缓冲区的 MPEG 数据帧不一定完整,所以不完整的 MPEG 帧的数据必须拷贝到下一次解码操作的缓冲区中,进行再次解码。这里我们还看到 bufend 指向缓冲区数据的最后地址,也就是最后一字节的地址加 1 的位置。mad_stream.bufend mad_stream.next_frame 就是剩余的未被解码的 M

8、PEG 帧的数据的字节数量(假设此帧在缓冲区中不完整)。mad_stream 的 error 域用来记录操作 mad_stream 得到的错误代码。错误代码在 mad.h 中有很详细的定义。 清单 2:错误代码在 mad.h 中的详细定义 struct mad_synth mad_fixed_t filter222168; /* polyphase filterbank outputs */ /* cheopeosv */ unsigned int phase; /* current processing phase */ struct mad_pcm pcm; /* PCM output *

9、/ ; mad_synth 中的关键域 pcm 保存解码和合成后得到的 PCM 数据。清单 3:mad_synth 中的关键域struct mad_pcm unsigned int samplerate; /* sampling frequency (Hz) */ unsigned short channels; /* number of channels */ unsigned short length; /* number of samples per channel */ mad_fixed_t samples21152; /* PCM output samples chsample *

10、/; struct mad_pcm 定义了音频的采样率、每个声道个数以及最后的 PCM 采样数据。这些参数可用来初始化音频设备。清单 4:struct mad_pcmstruct mad_frame struct mad_header header; /* MPEG audio header */ int options; /* decoding options (from stream) */ mad_fixed_t sbsample23632; /* synthesis subband filter samples */ mad_fixed_t (*overlap)23218; /* La

11、yer III block overlap data */; mad_frame 是记录 MPEG 帧解码后的数据的数据结构,其中的 mad_header 尤其重要,其用来记录 MPEG 帧的一些基本信息,比如 MPEG 层数、声道模式、流比特率、采样比特率等等。声道模式包括单声道、双声道、联合立体混音声以及一般立体声。清单 5:mad_frameenum mad_mode MAD_MODE_SINGLE_CHANNEL = 0, /* single channel */ MAD_MODE_DUAL_CHANNEL = 1, /* dual channel */ MAD_MODE_JOINT_

12、STEREO = 2, /* joint (MS/intensity) stereo */ MAD_MODE_STEREO = 3 /* normal LR stereo */;struct mad_header enum mad_layer layer; /* audio layer (1, 2, or 3) */ enum mad_mode mode; /* channel mode */ int mode_extension; /* additional mode info */ enum mad_emphasis emphasis; /* de-emphasis to use */ u

13、nsigned long bitrate; /* stream bitrate (bps) */ unsigned int samplerate; /* sampling frequency (Hz) */ unsigned short crc_check; /* frame CRC accumulator */ unsigned short crc_target; /* final target CRC checksum */ int flags; /* flags */ int private_bits; /* private bits */ mad_timer_t duration; /

14、* audio playing time of frame */; 下面就本文使用的 API 的功能做简单介绍。 在本文中用到的 API 包括:void mad_stream_init(struct mad_stream *) void mad_synth_init(struct mad_synth *);void mad_frame_init(struct mad_frame *); 以上3个 API 初始化解码需要的数据结构。void mad_stream_buffer(struct mad_stream *, unsigned char const *, unsigned long);

15、此函数把原始的未解码的 MPEG 数据和 mad_stream 数据结构关联,以便使用 mad_frame_decode( ) 来解码 MPEG 帧数据。int mad_frame_decode(struct mad_frame *, struct mad_stream *); 把 mad_stream 中的 MPEG 帧数据解码。void mad_synth_frame(struct mad_synth *, struct mad_frame const *); 把解码后的音频数据合成 PCM 采样。void mad_stream_finish(struct mad_stream *);vo

16、id mad_frame_finish(struct mad_frame *); mad_synth_finish(struct mad_synth); 以上 3 个 API 在解码完毕后使用,释放 libmad 占用的资源等。更多内容请看流媒体播放器流媒体文件格式播放技巧专题,或 3PCM 音频设备的操作 对音频设备的操作主要是初始化音频设备以及往音频设备发送 PCM(Pulse Code Modulation)数据。为了方便,本文使用 ALSA(Advanced Linux Sound Architecture)提供的库和驱动。在编译和运行本文中的 MP3 流媒体播放器的时候,必须先安装

17、ALSA 相关的文件。本文用到的主要对 PCM 设备操作的函数分为 PCM 设备初始化的函数以及 PCM 接口的一些操作函数。PCM 硬件设备参数设置和初始化的函数有:int snd_pcm_hw_params_malloc (snd_pcm_hw_params_t *ptr)int snd_pcm_hw_params_any (snd_pcm_t *pcm, snd_pcm_hw_params_t *params)void snd_pcm_hw_params_free (snd_pcm_hw_params_t *obj)int snd_pcm_hw_params_set_Access ( s

18、nd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t _access)int snd_pcm_hw_params_set_format ( snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_format_t val)int snd_pcm_hw_params_set_channels(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val)int snd_pcm_hw_params_set_rate_ne

19、ar(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir) PCM 接口的操作函数: int snd_pcm_hw_params (snd_pcm_t *pcm, snd_pcm_hw_params_t *params) int snd_pcm_prepare (snd_pcm_t *pcm) int snd_pcm_open (snd_pcm_t *pcm, const char *name, snd_pcm_stream_t stream, int mode) int snd_pcm_close

20、(snd_pcm_t *pcm) snd_pcm_sframes_t snd_pcm_writei (snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size) 这些函数用到了 snd_pcm_hw_params_t 结构,此结构包含用来播放 PCM 数据流的硬件信息配置。在往音频设备(声卡)写入音频数据之前,必须设置访问类型、采样格式、采样率、声道数等。 首先使用 snd_pcm_open () 打开 PCM 设备,在 ALSA 中,PCM 设备都有名字与之对应。比如我们可以定义 PCM 设备名字为 char *pcm_name =

21、 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_pa

22、rams_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 帧只是一个声道需要的数据,如果使用多个声道,那么第一帧是第一个声道的数据,第二帧是第二个声道的数据

23、,依此类推。函数 snd_pcm_hw_params_set_format() 设置数据格式,主要控制输入的音频数据的类型、无符号还是有符号、是 little-endian 还是 bit-endian。比如对于 16-bit 长度的采样数据可以设置为: SND_PCM_FORMAT_S16_LE 有符号16 bit Little Endian SND_PCM_FORMAT_S16_BE 有符号16 bit Big Endian SND_PCM_FORMAT_U16_LE 无符号16 bit Little Endian SND_PCM_FORMAT_U16_BE 无符号 16 bit Big E

24、ndian 比如对于 32-bit 长度的采样数据可以设置为:SND_PCM_FORMAT_S32_LE 有符号32 bit Little Endian SND_PCM_FORMAT_S32_BE 有符号32 bit Big Endian SND_PCM_FORMAT_U32_LE 无符号32 bit Little Endian SND_PCM_FORMAT_U32_BE 无符号 32 bit Big Endian 函数 snd_pcm_hw_params_set_channels() 设置音频设备的声道,常见的就是单声道和立体声,如果是立体声,设置最后一个参数为2。snd_pcm_hw_pa

25、rams_set_rate_near () 函数设置音频数据的最接近目标的采样率。snd_pcm_hw_params( ) 从设备配置空间选择一个配置,让函数 snd_pcm_prepare() 准备好 PCM 设备,以便写入 PCM 数据。snd_pcm_writei() 用来把交错的音频数据写入到音频设备。初始化 PCM 设备的例程如下:清单 6:初始化 PCM 设备的例程/* open a PCM device */int open_device(struct mad_header const *header) int err; snd_pcm_hw_params_t *hw_param

26、s; char *pcm_name = plughw:0,0; int rate = header-samplerate; int channels = 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(cannot open audio device %s (%s)n, pcm_name, snd_strerror (err); return -1;

27、if (err = snd_pcm_hw_params_malloc (&hw_params) 0) printf(cannot allocate hardware parameter structure (%s)n, snd_strerror (err); return -1; if (err = snd_pcm_hw_params_any (playback_handle, hw_params) 0) printf(cannot initialize hardware parameter structure (%s)n, snd_strerror (err); return -1; if

28、(err = snd_pcm_hw_params_set_access (playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED) 0) printf(cannot set access type (%s)n, snd_strerror (err); return -1; if (err = snd_pcm_hw_params_set_format (playback_handle, hw_params, SND_PCM_FORMAT_S32_LE) 0) printf(cannot set sample format (%s)n,

29、snd_strerror (err); return -1; if (err = snd_pcm_hw_params_set_rate_near (playback_handle, hw_params, &rate, 0) 0) printf(cannot set sample rate (%s)n, snd_strerror (err); return -1; if (err = snd_pcm_hw_params_set_channels (playback_handle, hw_params, channels) 0) printf(cannot set channel count (%

30、s)n, snd_strerror (err); return -1; if (err = snd_pcm_hw_params (playback_handle, hw_params) 0) printf(cannot set parameters (%s)n, snd_strerror (err); return -1; snd_pcm_hw_params_free (hw_params); if (err = snd_pcm_prepare (playback_handle) 0) printf(cannot prepare audio interface for use (%s)n, snd_strerror (err); return -1; return 0; 这里配置的 PCM 格式是 SND_PCM_FORMAT_S32_LE,采样的格式是每个采样有 32-bit 的数据,数据按照 little-endian 存放。如果通过 mad_frame_decode() 函数得到 PCM 数据后,要求每个采样数据只占 16-bit,需要把数据进行MAD的定点类型到 signed short

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1