MP3/WAV 播放
一.编译libmad
1.先下载压缩包到本地,并解压
tar -xvzf libmad-0.15.1b.tar.gz -C ./
2.进入源代码文件夹并配置
编写一个配置文件,便于< 改动和编译 > 文件内容例如以下
./configure CC=arm-linux-gcc --host=arm-linux --build=i686-pc-linux-gnu --enable-fpm=arm --enable-shared --disable-debugging --prefix=/home/tang/WIFI-Music/MPlayer/libmad-0.15.1b_install
运行配置 并记录信息
3.make 编译 并记录信息
Tips
改动makefile ,删除 " --fforce-mem "
4. make install 安装 并记录信息
须要调用的库和文件为:libmad.so mad.h
二.编写 程序代码
1.可播放wav、mp3 两种格式代码。
< play-wav-or-mp3.c >
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <linux/types.h> #include <fcntl.h> #include <sys/types.h> #include <semaphore.h> #include <sys/stat.h> #include <string.h> #include <errno.h> #include <linux/soundcard.h> #include <termio.h> #include <getopt.h> #include <time.h> #include <strings.h> #include <signal.h> #include "wav.h" #include "mad.h" #include <sys/mman.h> #define SND_OUT_BUF_SIZE 0x2000 struct buffer { unsigned char const *start; unsigned long length; }; int fd_sound; int n; int vol_val; int i=0; static enum mad_flow input(void *data, struct mad_stream *stream) { struct buffer *buffer = data; if (!buffer->length) return MAD_FLOW_STOP; mad_stream_buffer(stream, buffer->start, buffer->length); buffer->length = 0; return MAD_FLOW_CONTINUE; } static signed int scale(mad_fixed_t sample) { /* round */ sample += (1L << (MAD_F_FRACBITS - 16)); /* clip */ if (sample >= MAD_F_ONE) sample = MAD_F_ONE - 1; else if (sample < -MAD_F_ONE) sample = -MAD_F_ONE; /* quantize */ return sample >> (MAD_F_FRACBITS + 1 - 16); } static enum mad_flow output(void *data, struct mad_header const *header, struct mad_pcm *pcm) { unsigned short nchannels ,nsamples; unsigned int nsamplerate; unsigned char ldata,rdata; unsigned char outputbuf[8196],*outputptr; int write_num; mad_fixed_t const *left_ch, *right_ch; /* pcm->samplerate contains the sampling frequency */ nchannels = pcm->channels; nsamplerate = pcm->samplerate; n=nsamples = pcm->length; left_ch = pcm->samples[0]; right_ch = pcm->samples[1]; if(i==0){ int bits_set=16; ioctl(fd_sound, SNDCTL_DSP_SYNC, &nsamplerate); ioctl(fd_sound, SOUND_PCM_WRITE_RATE, &nsamplerate); ioctl(fd_sound, SNDCTL_DSP_SETFMT, &bits_set); ioctl(fd_sound, SOUND_PCM_WRITE_CHANNELS, &nchannels); ioctl(fd_sound, SOUND_MIXER_WRITE_VOLUME, &vol_val); } i++; outputptr=outputbuf; while (nsamples--) { signed int sample; /* output sample(s) in 16-bit signed little-endian PCM */ sample = scale(*left_ch++); ldata = (sample >> 0); rdata = (sample >> 8); //printf("ssss\n"); *(outputptr++)=ldata; *(outputptr++)=rdata; //printf("buflen%d\n",strlen(outputbuf[i])); if (nchannels == 2) { sample = scale(*right_ch++); ldata = (sample >> 0); rdata = (sample >> 8); *(outputptr++)=ldata; *(outputptr++)=rdata; } } n*=4; outputptr=outputbuf; while(n) { write_num=write(fd_sound,outputptr,n); outputptr+=write_num; n-=write_num; //printf("n:%d\n",n); } outputptr=outputbuf; return MAD_FLOW_CONTINUE; } static enum mad_flow error(void *data, struct mad_stream *stream, struct mad_frame *frame) { struct buffer *buffer = data; fprintf(stderr, "decoding error 0x%04x (%s) at byte offset %u\n", stream->error, mad_stream_errorstr(stream), stream->this_frame - buffer->start); /* return MAD_FLOW_BREAK here to stop decoding (and propagate an error) */ return MAD_FLOW_CONTINUE; } static int decode(unsigned char const *start, unsigned long length) { struct buffer buffer; struct mad_decoder decoder; int result; /* initialize our private message structure */ buffer.start = start; buffer.length = length; /* configure input, output, and error functions */ mad_decoder_init(&decoder, &buffer, 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; } int main(int argc, char **argv) { if(argc < 3) { printf("argc error\n"); return -1; } int rate_set, bits_set, ch_set,fd_file_path=0,DataLen; char file_path[256]={0}; int *psound_data_buf=NULL; struct stat stat; void *fdm; //ch_set=2; //bits_set=16; //rate_set=44100; if(sscanf(argv[1], "%s", &file_path)!= 1 ||sscanf(argv[2], "%d", &vol_val)!= 1) { printf("argv error\n"); return -1; } if(vol_val<0) vol_val=26; if(strcmp(&file_path[strlen(file_path)-4],".wav")!=0 && strcmp(&file_path[strlen(file_path)-4],".mp3")!=0) { printf("file is not wav or mp3 farmat\n"); return -1; } while((fd_sound = open("/dev/dsp",O_WRONLY)) == -1) { printf("Can not open /dev/dsp\n"); return -1; } fd_file_path = open(file_path,O_RDONLY); if(fd_file_path == -1) { printf("fd_file_path open file error"); goto exit; } if(strcmp(&file_path[strlen(file_path)-4],".wav")==0) { wav_struct FileWav; psound_data_buf=(int *)malloc(SND_OUT_BUF_SIZE); if(psound_data_buf == NULL) goto exit; memset(&FileWav,0,sizeof(FileWav)); if((DataLen = read(fd_file_path, &FileWav, sizeof(FileWav)))>0) { if((strncmp(FileWav.rif_info.riff,RIFF_FIELD,strlen(RIFF_FIELD)) == 0)&&(strncmp(FileWav.rif_info.wave,WAVE_FIELD,strlen(WAVE_FIELD)) == 0)) { rate_set=FileWav.fmt_info.sample_rate; ch_set=FileWav.fmt_info.channel_nb; bits_set=FileWav.fmt_info.bits_per_sample; } else { printf("wav head error\n"); goto exit; } } else { goto exit; } //printf("sample:%d,channel:%d,bits:%d,vol_val:%d\n", rate_set,ch_set,bits_set,vol_val); ioctl(fd_sound, SNDCTL_DSP_SYNC, &rate_set); ioctl(fd_sound, SOUND_PCM_WRITE_RATE, &rate_set); ioctl(fd_sound, SNDCTL_DSP_SETFMT, &bits_set); ioctl(fd_sound, SOUND_PCM_WRITE_CHANNELS, &ch_set); ioctl(fd_sound, SOUND_MIXER_WRITE_VOLUME, &vol_val); while((DataLen=read(fd_file_path, psound_data_buf ,SND_OUT_BUF_SIZE))>0) write(fd_sound, psound_data_buf, DataLen); free(psound_data_buf); } /*mp3 play*/ else if(strcmp(&file_path[strlen(file_path)-4],".mp3")==0) { if(fstat(fd_file_path,&stat)==-1||stat.st_size==0) goto exit; fdm=mmap(0,stat.st_size,PROT_READ,MAP_SHARED,fd_file_path,0); if(fdm==MAP_FAILED) goto exit; decode(fdm,stat.st_size); } exit: if(munmap(fdm,stat.st_size)==-1) { printf("munmap error\n"); } if(fd_file_path>0) { close(fd_file_path); fd_file_path=0; } if(fd_sound>0) { close(fd_sound); fd_sound=0; } return 0; }
< wav.h >
#ifndef _WAV_H_ #define _WAV_H_ /*_____ I N C L U D E S ____________________________________________________*/ /*_____ M A C R O S ________________________________________________________*/ #define WAV_HEADER_SIZE sizeof(wav_struct) /* RIFF info */ #define RIFF_FIELD "RIFF" #define WAVE_FIELD "WAVE" /* FMT info */ #define FMT_FIELD "FMT " #define FMT_LENGTH ((unsigned long)(16)) /* data start beg of sector */ /* wave format */ #define PCM_FMT ((unsigned short)0x0100) /* channel number */ #define MONO ((unsigned short)0x0100) #define STEREO ((unsigned short)0x0200) /* bytes per sample */ #define ONE_BYTE ((unsigned short)0x0100) #define TWO_BYTE ((unsigned short)0x0200) /* bits per sample */ #define EIGHT_BIT ((unsigned short)0x0800) #define SIXTEEN_BIT ((unsigned short)0x1000) /* DATA info */ #define DATA_FIELD 'data' /*_____ D E F I N I T I O N ________________________________________________*/ /* WAV Format Structure */ typedef struct { /* RIFF info */ char riff[4]; unsigned long pack_length; char wave[4]; } riff_struct; typedef struct { /* FMT info */ char fmt[4]; unsigned long fmt_length; unsigned short wav_format; unsigned short channel_nb; unsigned long sample_rate; unsigned long bytes_per_second; unsigned short bytes_per_sample; unsigned short bits_per_sample; } fmt_struct; typedef struct { /* DATA info */ char dat[4]; unsigned long data_length; } data_struct; typedef struct { riff_struct rif_info; fmt_struct fmt_info; data_struct dat_info; } wav_struct; /*_____ D E C L A R A T I O N ______________________________________________*/ #endif /* _WAV_H_ */
动态编译 arm-none-linux-gnueabi-gcc play-wav-or-mp3.c -o play-wav-or-mp3 -lmad -L./
执行 ./play-wav-or-mp3 xxx.mp3/wav 70
argc[1] 为播放歌曲,argc[2] 为音量大小