Chinaunix首页 | 论坛 | 博客
  • 博客访问: 280198
  • 博文数量: 76
  • 博客积分: 1500
  • 博客等级: 上尉
  • 技术积分: 594
  • 用 户 组: 普通用户
  • 注册时间: 2011-08-05 23:43
文章分类

全部博文(76)

文章存档

2014年(4)

2013年(3)

2012年(20)

2011年(49)

分类: LINUX

2012-07-02 11:01:38

转载于:http://blog.sina.com.cn/s/blog_81e410670100w47s.html

在Linux下先安装libmad,安装方法见libmad-0.15.1b中的README和INSTALL文件。

安装libmad后,将libmad-0.15.1b中的mad.h复制过来,程序可以参照libmad-0.15.1b中的minimad.c例程。

 

# include
# include
# include
# include
# include
# include
# include
# include
# include
# include "mad.h"


#undef putchar

static int decode(unsigned char const *, unsigned long);

int soundfd;
int writedsp(int c) {
 return write(soundfd, (char *)&c, 1);
}

//查看要播放MP3音乐的属性,查找相应的频率等,程序做相同的设置。

void set_dsp()
{
    int rate=44100;;            

    int format=AFMT_S16_LE;

    int channels=2;  

    int value;          

    soundfd=open ("/dev/dsp", O_WRONLY);
    //ioctl(soundfd, SNDCTL_DSP_SPEED,&rate);
    //ioctl(soundfd, SNDCTL_DSP_SETFMT,&format);
    //ioctl(soundfd, SNDCTL_DSP_CHANNELS,&channels);

    value = 16;    
    ioctl(soundfd, SNDCTL_DSP_SAMPLESIZE, &value);

    value = 0;

    ioctl(soundfd, SNDCTL_DSP_STERE0, &value);

    value = 96000;

    ioctl(soundfd, SNDCTL_DSP_SPEED, &value);
}

int main(int argc, char *argv[])
{
    struct stat stat;
    void *fdm;

    if (argc != 1)
      return 1;

    if (fstat(STDIN_FILENO, &stat) == -1 || stat.st_size == 0)
      return 2;

    fdm = mmap(0, stat.st_size, PROT_READ, MAP_SHARED, STDIN_FILENO, 0);
    if (fdm == MAP_FAILED)
      return 3;

    set_dsp(); //here

    decode(fdm, stat.st_size);

    if (munmap(fdm, stat.st_size) == -1)
      return 4;

    close(soundfd); //here

    return 0;
}

struct buffer {
    unsigned char const *start;
    unsigned long length;
};

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 inline
signed int scale(mad_fixed_t sample)
{
    sample += (1L << (MAD_F_FRACBITS - 16));

    if (sample >= MAD_F_ONE)
       sample = MAD_F_ONE - 1;
    else if (sample < -MAD_F_ONE)
         sample = -MAD_F_ONE;

    return sample >> (MAD_F_FRACBITS + 1 - 16);
}

//输出函数做相应的修改,目的是解决播放音乐时声音卡的问题。

static
enum mad_flow output(void *data,
  struct mad_header const *header,
  struct mad_pcm *pcm)
{
 unsigned int nchannels, nsamples;
 mad_fixed_t const *left_ch, *right_ch;

 // pcm->samplerate contains the sampling frequency

 nchannels = pcm->channels;
 nsamples = pcm->length;
 left_ch   = pcm->samples[0];
 right_ch = pcm->samples[1];

 short buf[nsamples *2];
 int i = 0;

 while (nsamples--) {
      signed int sample;
   // output sample(s) in 16-bit signed little-endian PCM
   sample = scale(*left_ch++);
   buf[i] = sample & 0xFFFF;

   if (nchannels == 2) {
    sample = scale(*right_ch++);
    buf[++i] = sample & 0xFFFF;
   }
   i++;
 }
 write(soundfd, &buf[0], i * 2);

 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 0xx (%s) at byte offset %u\n",
       stream->error, mad_stream_errorstr(stream),
          stream->this_frame - buffer->start);

   

    return MAD_FLOW_CONTINUE;
}

static
int decode(unsigned char const *start, unsigned long length)
{
    struct buffer buffer;
    struct mad_decoder decoder;
    int result;

     

     buffer.start  = start;
     buffer.length = length;

      

      mad_decoder_init(&decoder, &buffer,input, 0 , 0 , output,
                error, 0 );

     

      result = mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC);

      

      mad_decoder_finish(&decoder);

      return result;
}

编译程序gcc -o mp3play mp3play.c -lmad

最后运行程序./mp3play < 1.mp3

阅读(2401) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~