分类: 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