首先也是最重要的是:我说大话了,本文也就是一个思路而已,如果你是音乐播放小白也想弄明白原理可以往下看,否则,return -1;
现有的音乐格式千差万别,于是就有了ffmpeg话说这个框架真是够牛逼,音频视频转码都不在话下,我是个死脑筋,遇到不懂的老是想弄明白,对于音乐播放感觉是一头雾水,经过几天的研究以后大致想明白了,对一个mp3文件要播放出来需要经过几个步骤:
1.转码,其实也就是提取文件中有用的音频信息
2.经过第一步得到的wav波形文件
3.调用声卡来播放wav文件,对于linux 3.0以后的内核一般为alsa驱动,windows对wav也是天然支持的
关于转码可以见大婶写的转码系列教程http://lfp001.iteye.com/blog/739585
转码命令:
ffmepg -i 1.mp3 -f wav 1.wav
编译: gcc -o alsa alsa.c -lasound
播放命令
./alsa 1.wav
//alsa.c 编写者未知,纯属引用 #include<stdio.h> #include<stdlib.h> #include <string.h> #include <alsa/asoundlib.h> struct WAV_HEADER { char rld[4]; //riff 标志符号 int rLen; char wld[4]; //格式类型(wave) char fld[4]; //"fmt" int fLen; //sizeof(wave format matex) short wFormatTag; //编码格式 short wChannels; //声道数 int nSamplesPersec ; //采样频率 int nAvgBitsPerSample;//WAVE文件采样大小 short wBlockAlign; //块对齐 short wBitsPerSample; //WAVE文件采样大小 char dld[4]; //”data“ int wSampleLength; //音频数据的大小 } wav_header; int set_pcm_play(FILE *fp); int main(int argc,char *argv[]) { if(argc!=2) { printf("Usage:wav-player+wav file name\n"); exit(1); } int nread; FILE *fp; fp=fopen(argv[1],"rb"); if(fp==NULL) { perror("open file failed:\n"); exit(1); } nread=fread(&wav_header,1,sizeof(wav_header),fp); printf("nread=%d\n",nread); //printf("RIFF 标志%s\n",wav_header.rld); printf("文件大小rLen:%d\n",wav_header.rLen); //printf("wld=%s\n",wav_header.wld); //printf("fld=%s\n",wav_header.fld); // printf("fLen=%d\n",wav_header.fLen); //printf("wFormatTag=%d\n",wav_header.wFormatTag); printf("声道数:%d\n",wav_header.wChannels); printf("采样频率:%d\n",wav_header.nSamplesPersec); //printf("nAvgBitsPerSample=%d\n",wav_header.nAvgBitsPerSample); //printf("wBlockAlign=%d\n",wav_header.wBlockAlign); printf("采样的位数:%d\n",wav_header.wBitsPerSample); // printf("data=%s\n",wav_header.dld); printf("wSampleLength=%d\n",wav_header.wSampleLength); set_pcm_play(fp); return 0; } int set_pcm_play(FILE *fp) { int rc; int ret; int size; snd_pcm_t* handle; //PCI设备句柄 snd_pcm_hw_params_t* params;//硬件信息和PCM流配置 unsigned int val; int dir=0; snd_pcm_uframes_t frames; char *buffer; int channels=wav_header.wChannels; int frequency=wav_header.nSamplesPersec; int bit=wav_header.wBitsPerSample; int datablock=wav_header.wBlockAlign; unsigned char ch[100]; //用来存储wav文件的头信息 rc=snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0); if(rc<0) { perror("\nopen PCM device failed:"); exit(1); } snd_pcm_hw_params_alloca(¶ms); //分配params结构体 if(rc<0) { perror("\nsnd_pcm_hw_params_alloca:"); exit(1); } rc=snd_pcm_hw_params_any(handle, params);//初始化params if(rc<0) { perror("\nsnd_pcm_hw_params_any:"); exit(1); } rc=snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); //初始化访问权限 if(rc<0) { perror("\nsed_pcm_hw_set_access:"); exit(1); } //采样位数 switch(bit/8) { case 1:snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_U8); break ; case 2:snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); break ; case 3:snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S24_LE); break ; } rc=snd_pcm_hw_params_set_channels(handle, params, channels); //设置声道,1表示单声>道,2表示立体声 if(rc<0) { perror("\nsnd_pcm_hw_params_set_channels:"); exit(1); } val = frequency; rc=snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); //设置>频率 if(rc<0) { perror("\nsnd_pcm_hw_params_set_rate_near:"); exit(1); } rc = snd_pcm_hw_params(handle, params); if(rc<0) { perror("\nsnd_pcm_hw_params: "); exit(1); } rc=snd_pcm_hw_params_get_period_size(params, &frames, &dir); /*获取周期长度*/ if(rc<0) { perror("\nsnd_pcm_hw_params_get_period_size:"); exit(1); } size = frames * datablock; /*4 代表数据快长度*/ buffer =(char*)malloc(size); fseek(fp,58,SEEK_SET); //定位歌曲到数据区 while (1) { memset(buffer,0,sizeof(buffer)); ret = fread(buffer, 1, size, fp); if(ret == 0) { printf("歌曲写入结束\n"); break; } else if (ret != size) { } // 写音频数据到PCM设备 while(ret = snd_pcm_writei(handle, buffer, frames)<0) { usleep(2000); if (ret == -EPIPE) { /* EPIPE means underrun */ fprintf(stderr, "underrun occurred\n"); //完成硬件参数设置,使设备准备好 snd_pcm_prepare(handle); } else if (ret < 0) { fprintf(stderr, "error from writei: %s\n", snd_strerror(ret)); } } } snd_pcm_drain(handle); snd_pcm_close(handle); free(buffer); return 0; }
时间: 2024-10-27 07:20:12