怎么使用libmadWord文档格式.docx
《怎么使用libmadWord文档格式.docx》由会员分享,可在线阅读,更多相关《怎么使用libmadWord文档格式.docx(12页珍藏版)》请在冰点文库上搜索。
#include
intmain(intargc,char*argv[])
{
intid,fd,i;
charbuf[1024];
intrate;
/*simplerate44.1KHz*/
intformat;
/*quatizeargs*/
intchannels;
/*soundchannel*/
if(argc!
=2)
{
fprintf(stderr,"
usage:
%s\n"
argv[0]);
exit(-1);
}
if((fd=open(argv[1],O_RDONLY))<
0)
Can'
topensoundfile!
\n"
);
exit(-2);
if((id=open("
/dev/dsp"
O_WRONLY))0)
write(id,buf,i);
//printf("
i=%d\n"
i);
close(fd);
close(id);
exit(0);
}
编译pcmplay文件,然后就可以用生成的可执行程序播放第一步中声称的tmp.pcm文件,命令如下:
gcc-opcmplaypcmplay.c
./pcmplaytmp.pcm
播放时可能会变调,这是因为上面这段代码中将音频设备采样率固定设置为44.1k,而mp3文件不一定是这个采样率,解决方法后面会讲。
当然可以改,而且改起来相当的简单,如果不知道怎么改只能说明自己没仔细看minimad.c,你可能不知道structstat是什么,也不清楚mmap()函数有什么用,但这些都可以在网上查到的,查了之后稍加分析就会发现原来就是把一片数据放入一块内存并得到它的长度而已,那改成文件读入的方式也很容易,用fopen打开文件,计算一下文件的长度,然后用fread把数据全部读出来即可,这里就不贴代码了。
修改input()函数,在调用libmad中的mad_decoder_run()实现播放时,首先检查待解码缓存区中有没有数据,有则解码,没有则调用input()函数一次以填充数据(填充多少可以自己指定),然后开始解码,解码后的数据交给output()函数处理,解码过程中,一旦待解码缓存区中的解码数据不够则再次调用input()函数……在这里还要提一下structbuffer这个结构体,这个结构体是在input、output和decoder之间传送数据的载体,可以自行定义,比如我的数据来源是文件,待解码数据缓存区大小为4K,要传递的私有数据包括文件指针、当前的位置、数据缓冲区、缓冲区的实际大小、文件的总大小等,则我这里定义如下:
structbuffer{
FILE*fp;
/*filepointer*/
unsignedintflen;
/*filelength*/
unsignedintfpos;
/*currentposition*/
unsignedcharfbuf[BUFSIZE];
/*buffer*/
unsignedintfbsize;
/*indeedsizeofbuffer*/
};
typedefstructbuffermp3_file;
修改input()函数为如下形式,则每次调用填充BUFSIZE字节的数据:
static
enummad_flowinput(void*data,
structmad_stream*stream)
mp3_file*mp3fp;
intret_code;
intunproc_data_size;
/*theunprocesseddata'
ssize*/
intcopy_size;
mp3fp=(mp3_file*)data;
if(mp3fp->
fposflen)
unproc_data_size=stream->
bufend-stream->
next_frame;
memcpy(mp3fp->
fbuf,mp3fp->
fbuf+mp3fp->
fbsize-unproc_data_size,unproc_data_size);
copy_size=BUFSIZE-unproc_data_size;
fpos+copy_size>
mp3fp->
flen)
copy_size=mp3fp->
flen-mp3fp->
fpos;
fread(mp3fp->
fbuf+unproc_data_size,1,copy_size,mp3fp->
fp);
fbsize=unproc_data_size+copy_size;
fpos+=copy_size;
/*Handoffthebuffertothemp3inputstream*/
mad_stream_buffer(stream,mp3fp->
fbsize);
ret_code=MAD_FLOW_CONTINUE;
else
ret_code=MAD_FLOW_STOP;
returnret_code;
注意:
在上面的代码中涉及到了断桢问题,即一桢跨了两个BUFSIZE,这时候应该将缓冲区中的剩余数据先移至缓冲区头部,然后再从文件中读出数据填充缓冲区。
5.怎样用libmad设计一个简单的mp3播放器?
修改output()函数。
我在上面说过了,解码后的数据通过output()函数进行处理,在minimad.c中output()函数直接将解码后的数据送到标准输出,其实只要将这里修改为送到音频设备就可以实现播放了。
还有一点需要说明的是:
mp3文件的采样率不是固定不变的,解码后的数据中包括采样率,在播放过程中,一旦采样率发生变化,要重新设置一下音频设备。
新建一个mp3player.c文件,然后将下面的代码复制进去,编译生成mp3player,这就是一个简单的mp3播放器了,可以用./mp3player1.mp3命令来播放1.mp3文件。
#include"
mad.h"
#defineBUFSIZE8192
/*
*Thisisaprivatemessagestructure.Agenericpointertothisstructure
*ispassedtoeachofthecallbackfunctions.Puthereanydatayouneed
*toaccessfromwithinthecallbacks.
*/
intsoundfd;
/*soundcardfile*/
unsignedintprerate=0;
/*thepresimplerate*/
intwritedsp(intc)
returnwrite(soundfd,(char*)&
c,1);
voidset_dsp()
intformat=AFMT_S16_LE;
intchannels=2;
soundfd=open("
O_WRONLY);
ioctl(soundfd,SNDCTL_DSP_SETFMT,&
format);
ioctl(soundfd,SNDCTL_DSP_CHANNELS,&
channels);
*ThisisperhapsthesimplestexampleuseoftheMADhigh-levelAPI.
*Standardinputismappedintomemoryviammap(),thenthehigh-levelAPI
*isinvokedwiththreecallbacks:
input,output,anderror.Theoutput
*callbackconvertsMAD'
shigh-resolutionPCMsamplesto16bits,then
*writesthemtostandardoutputinlittle-endian,stereo-interleaved
*format.
staticintdecode(mp3_file*mp3fp);
longflen,fsta,fend;
intdlen;
if(argc!
return1;
mp3fp=(mp3_file*)malloc(sizeof(mp3_file));
if((mp3fp->
fp=fopen(argv[1],"
r"
))==NULL)
printf("
can'
topensourcefile.\n"
return2;
fsta=ftell(mp3fp->
fseek(mp3fp->
fp,0,SEEK_END);
fend=ftell(mp3fp->
flen=fend-fsta;
if(flenfp,0,SEEK_SET);
fbuf,1,BUFSIZE,mp3fp->
fbsize=BUFSIZE;
fpos=BUFSIZE;
flen=flen;
set_dsp();
decode(mp3fp);
close(soundfd);
fclose(mp3fp->
return0;
*Thisistheinputcallback.Thepurposeofthiscallbackisto(re)fill
*thestreambufferwhichistobedecoded.Inthisexample,anentirefile
*hasbeenmappedintomemory,sowejustcallmad_stream_buffer()withthe
*addressandlengthofthemapping.Whenthiscallbackiscalledasecond
*time,wearefinisheddecoding.
*Thefollowingutilityroutineperformssimplerounding,clipping,and
*scalingofMAD'
shigh-resolutionsamplesdownto16bits.Itdoesnot
*performanyditheringornoiseshaping,whichwouldberecommendedto
*obtainanyexceptionalaudioquality.Itisthereforenotrecommendedto
*usethisroutineifhigh-qualityoutputisdesired.
staticinline
signedintscale(mad_fixed_tsample)
/*round*/
sample+=(1L<
=MAD_F_ONE)
sample=MAD_F_ONE-1;
elseif(sample>
(MAD_F_FRACBITS+1-16);
*Thisistheoutputcallbackfunction.Itiscalledaftereachframeof
*MPEGaudiodatahasbeencompletelydecoded.Thepurposeofthiscallback
*istooutput(orplay)thedecodedPCMaudio.
enummad_flowoutput(void*data,
structmad_headerconst*header,
structmad_pcm*pcm)
unsignedintnchannels,nsamples;
unsignedintrate;
mad_fixed_tconst*left_ch,*right_ch;
/*pcm->
sampleratecontainsthesamplingfrequency*/
rate=pcm->
samplerate;
nchannels=pcm->
channels;
nsamples=pcm->
length;
left_ch=pcm->
samples[0];
right_ch=pcm->
samples[1];
/*updatethesamplerateofdsp*/
if(rate!
=prerate)
ioctl(soundfd,SNDCTL_DSP_SPEED,&
rate);
prerate=rate;
while(nsamples--){
signedintsample;
/*outputsample(s)in16-bitsignedlittle-endianPCM*/
sample=scale(*left_ch++);
writedsp((sample>
>
0)&
0xff);
8)&
if(nchannels==2){
sample=scale(*right_ch++);
returnMAD_FLOW_CONTINUE;
*Thisistheerrorcallbackfunction.Itiscalledwheneveradecoding
*erroroccurs.Theerrorisindicatedbystream->
error;
thelistof
*possibleMAD_ERROR_*errorscanbefoundinthemad.h(orstream.h)
*headerfile.
staticenummad_flowerror(void*data,
structmad_stream*stream,
structmad_frame*frame)
mp3_file*mp3fp=data;
decodingerror0x%04x(%s)atbyteoffset%u\n"
stream->
error,mad_stream_errorstr(stream),
this_frame-mp3fp->
fbuf);
/*returnMAD_FLOW_BREAKheretostopdecoding(andpropagateanerror)*/
*Thisisth