• 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 安装 并记录信息



    tips

    须要调用的库和文件为: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
    ");
    	*(outputptr++)=ldata;
    	*(outputptr++)=rdata;
    	//printf("buflen%d
    ",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);
    	}
    	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
    ",
    	  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
    ");
    		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
    ");
    		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
    ");
    		return -1;
    		
    	}
    	while((fd_sound = open("/dev/dsp",O_WRONLY)) == -1) {
    		 printf("Can not open /dev/dsp
    ");
    		 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
    ");
    				goto exit;
    			}
    		}
    		else
    		{
    			goto exit;
    		}
    		//printf("sample:%d,channel:%d,bits:%d,vol_val:%d
    ", 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
    ");
    	}
    	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] 为音量大小


  • 相关阅读:
    axios的使用/
    jQuery好玩的双向控制轮播
    vue的路由跳转方式/两种
    vfor的某些注意事项
    vue使用插件时不能撑满页面?
    swiper中的双向控制器不生效问题
    sass的安装及使用
    .net必懂题
    软件架构初读01
    EJB
  • 原文地址:https://www.cnblogs.com/hrhguanli/p/3866542.html
Copyright © 2020-2023  润新知