
所幸手里有Altera公司的一个工程,借助对该工程的分析、minimad.c中少的可怜的注释和网上搜索的Linux
音频方面的相关知识,反复思考
编码,总算把libmad库用起来了,现记录一下其使用方法,在帮助别人的同时也方便自己回头查询。在开始之前,最好先把mp3
文件格式和Linux音频编程方面的知识先学习一下,不然后面有的东西可能听不懂,还有就是一定要熟悉Linux系统,后面的代码都是在linux系统中用gcc编译的,在Windows下不能用的。首先看下面几个问题,这也是我一开始最迷惑的,弄明白这几个问题了,也就对libmad库的使用相当熟悉了: minimad.c怎么编译?编译后怎么运行?运行时的输入输出分别是什么,或者说运行时什么效果?怎样播放minimad输出的数据?或者说怎么播放解码后的数据?minimad运行时,mp3数据来源是标准输入,能不能改为从文件中读入数据?该怎么改?minimad运行时首先要将整个mp3文件读入内存,能不能改成边解码边读入的形式,比如每次读入16K,解码完再读入16K,而又不影响播放的连贯性,这样可以节省内存开销,方便在嵌入式系统中使用;怎样用libmad做一个简单的mp3播放器? 一个一个来讲吧。 #include #include #include #include #include #include #include #include #include #include "mad.h" #define BUFSIZE 8192 /* * This is a private message structure. A generic pointer to this structure * is passed to each of the callback functions. Put here any data you need * to access from within the callbacks. */ struct buffer { FILE *fp/*file pointer*/ unsigned int flen/*file length*/ unsigned int fpos/*current position*/ unsigned char fbuf[BUFSIZE]/*buffer*/ unsigned int fbsize/*indeed size of buffer*/ }typedef struct buffer mp3_fileint soundfd/*soundcard file*/ unsigned int prerate = 0/*the pre simple rate*/ int writedsp(int c) { return write(soundfd, (char *)&c, 1)} void set_dsp() { int format = AFMT_S16_LEint channels = 2soundfd = open("/dev/dsp", O_WRONLY)ioctl(soundfd, SNDCTL_DSP_SETFMT, &format)ioctl(soundfd, SNDCTL_DSP_CHANNELS, &channels)} /* * This is perhaps the simplest example use of the MAD high-level API. * Standard input is mapped into memory via mmap(), then the high-level API * is invoked with three callbacks: input, output, and error. The output * callback converts MAD's high-resolution PCM samples to 16 bits, then * writes them to standard output in little-endian, stereo-interleaved * format. */ static int decode(mp3_file *mp3fp)int main(int argc, char *argv[]) { long flen, fsta, fendint dlenmp3_file *mp3fpif (argc != 2) return 1mp3fp = (mp3_file *)malloc(sizeof(mp3_file))if((mp3fp->fp = fopen(argv[1], "r")) == NULL) { printf("can't open source file.\n")return 2} fsta = ftell(mp3fp->fp)fseek(mp3fp->fp, 0, SEEK_END)fend = ftell(mp3fp->fp)flen = fend - fstaif(flen fp, 0, SEEK_SET)fread(mp3fp->fbuf, 1, BUFSIZE, mp3fp->fp)mp3fp->fbsize = BUFSIZEmp3fp->fpos = BUFSIZEmp3fp->flen = flenset_dsp()decode(mp3fp)close(soundfd)fclose(mp3fp->fp)return 0} /* * This is the input callback. The purpose of this callback is to (re)fill * the stream buffer which is to be decoded. In this example, an entire file * has been mapped into memory, so we just call mad_stream_buffer() with the * address and length of the mapping. When this callback is called a second * time, we are finished decoding. */ static enum mad_flow input(void *data, struct mad_stream *stream) { mp3_file *mp3fpint ret_codeint unproc_data_size/*the unprocessed data's size*/ int copy_sizemp3fp = (mp3_file *)dataif(mp3fp->fpos flen) { unproc_data_size = stream->bufend - stream->next_framememcpy(mp3fp->fbuf, mp3fp->fbuf+mp3fp->fbsize-unproc_data_size, unproc_data_size)copy_size = BUFSIZE - unproc_data_sizeif(mp3fp->fpos + copy_size >mp3fp->flen) { copy_size = mp3fp->flen - mp3fp->fpos} fread(mp3fp->fbuf+unproc_data_size, 1, copy_size, mp3fp->fp)mp3fp->fbsize = unproc_data_size + copy_sizemp3fp->fpos += copy_size/*Hand off the buffer to the mp3 input stream*/ mad_stream_buffer(stream, mp3fp->fbuf, mp3fp->fbsize)ret_code = MAD_FLOW_CONTINUE} else { ret_code = MAD_FLOW_STOP} return ret_code} /* * The following utility routine performs simple rounding, clipping, and * scaling of MAD's high-resolution samples down to 16 bits. It does not * perform any dithering or noise shaping, which would be recommended to * obtain any exceptional audio quality. It is therefore not recommended to * use this routine if high-quality output is desired. */ static inline signed int scale(mad_fixed_t sample) { /* round */ sample += (1L <= MAD_F_ONE) sample = MAD_F_ONE - 1else if (sample >(MAD_F_FRACBITS + 1 - 16)} /* * This is the output callback function. It is called after each frame of * MPEG audio data has been completely decoded. The purpose of this callback * is to output (or play) the decoded PCM audio. */ static enum mad_flow output(void *data, struct mad_header const *header, struct mad_pcm *pcm) { unsigned int nchannels, nsamplesunsigned int ratemad_fixed_t const *left_ch, *right_ch/* pcm->samplerate contains the sampling frequency */ rate= pcm->sampleratenchannels = pcm->channelsnsamples = pcm->lengthleft_ch = pcm->samples[0]right_ch = pcm->samples[1]/* update the sample rate of dsp*/ if(rate != prerate) { ioctl(soundfd, SNDCTL_DSP_SPEED, &rate)prerate = rate} while (nsamples--) { signed int sample/* output sample(s) in 16-bit signed little-endian PCM */ sample = scale(*left_ch++)writedsp((sample >>0) &0xff)writedsp((sample >>8) &0xff)if (nchannels == 2) { sample = scale(*right_ch++)writedsp((sample >>0) &0xff)writedsp((sample >>8) &0xff)} } return MAD_FLOW_CONTINUE} /* * This is the error callback function. It is called whenever a decoding * error occurs. The error is indicated by stream->errorthe list of * possible MAD_ERROR_* errors can be found in the mad.h (or stream.h) * header file. */ static enum mad_flow error(void *data, struct mad_stream *stream, struct mad_frame *frame) { mp3_file *mp3fp = datafprintf(stderr, "decoding error 0x%04x (%s) at byte offset %u\n", stream->error, mad_stream_errorstr(stream), stream->this_frame - mp3fp->fbuf)/* return MAD_FLOW_BREAK here to stop decoding (and propagate an error) */ return MAD_FLOW_CONTINUE} /* * This is the function called by main() above to perform all the decoding. * It instantiates a decoder object and configures it with the input, * output, and error callback functions above. A single call to * mad_decoder_run() continues until a callback function returns * MAD_FLOW_STOP (to stop decoding) or MAD_FLOW_BREAK (to stop decoding and * signal an error). */ static int decode(mp3_file *mp3fp) { struct mad_decoder decoderint result/* configure input, output, and error functions */ mad_decoder_init(&decoder, mp3fp, input, 0 /* header */, 0 /* filter */, output, error, 0 /* message */)/* start decoding */ result = mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC)/* release the decoder */ mad_decoder_finish(&decoder)return result}分享到:
WMA和WAV都是音频格式,这两种音频格式主要有以下不同。
1、音质不同。
WAV是无损音频格,WMA则不是,它是有损的。
2、保存的大小不同。
由于原因一,所以WAV文件大小相对也比较大。
WMA文件,文件大小相对较小。
3、文件组成不同。
WAV文件由文件头和数据体两大部分组成,其中文件头又分为RIFF/WAV文件标识段和声音数据格式说明段两部分。常见的WAV声音文件有两种,分别对应于单声道(11.025KHz采样率、8Bit的采样值)和双声道(44.1KHz采样率、16Bit的采样值)。
WMA文件,它的头16个字节是固定的,为十六进制的“30 26 B2 75 8E 66 CF 11 A6 D9 00 AA 00 62 CE 6C”, 用来标识这个是否为WMA文件。接下来的8个字节为一个整数,表示整个WMA文件头部的大小,这个头部里面包含了Tag信息等所有非音频信息,头部后面的是音频信息。
4、可编码设备不同。
WAV对音频流的编码没有硬性规定,除了PCM之外,还有几乎所有支持ACM规范的编码都可以为WAV的音频流进行编码。
WMA可以用于多种格式的编码文件中。应用程序可以使用Windows Media Format SDK进行WMA格式的编码和解码。一些常见的支持WMA的应用程序包括Windows Media Player、Windows Media Encoder、RealPlayer、Winamp等等。其它一些平台,例如Linux和移动设备中的软硬件也支持此格式。
扩展资料:
WAV音频格式的优点包括:
简单的编/解码(几乎直接存储来自模/数转换器(ADC)的信号)、普遍的认同/支持以及无损耗存储。WAV格式的主要缺点是需要音频存储空间。
对于小的存储限制或小带宽应用而言,这可能是一个重要的问题。WAV格式的另外一个潜在缺陷是在32位WAV文件中的2G限制,这种限制已在为SoundForge开发的W64格式中得到了改善。
WMA音频格式的优点包括:
WMA 7之后的WMA支持证书加密,未经许可(即未获得许可证书),即使是非法拷贝到本地,也是无法收听的。
同时,微软公司开始时宣称的:同文件比MP3体积小一倍而音质不变,也得到了兑现。
事实上,这个说法,仅仅适用于低比特率的情况,另外,微软公司在WMA 9大幅改进了其引擎,实际上几乎可以在同文件同音质下比MP3体积少1/3左右。
参考资料:百度百科-WMA
参考资料: 百度百科-WAV
评论列表(0条)