[Plain]
/*
* This program is improved from minimad. For more details, see minimad. c.
*
* MyMinimad. c, 2008/09/17, SiChuan University, China
*
* Compilation: gcc MyMinimad. c-o MyMinimad-lmad-g-Wall
* Run:./MyMinimad filename.pdf
*/
# Include <stdio. h>
# Include <stdlib. h>
# Include <unistd. h>
# Include <sys/stat. h>
# Include <sys/mman. h>
# Include <sys/soundcard. h>
# Include <sys/ioctl. h>
# Include <sys/fcntl. h>
# Include <sys/types. h>
# Include <mad. h>
Struct buffer {
Unsigned char const * start;
Unsigned long length;
};
Static int sfd;/* sound device descriptor */
Static int decode (unsigned char const *, unsigned long );
Int main (int argc, char * argv [])
{
Struct stat;
Void * OFDM;
Char const * file;
Int fd;
File = argv [1];
Fd = open (file, O_RDONLY );
If (sfd = open ("/dev/dsp", O_WRONLY) <0 ){
Printf ("can not open device !!! /N ");
Return 5;
}
Ioctl (sfd, SNDCTL_DSP_SYNC, 0);/* This sentence can be skipped */
If (fstat (fd, & stat) =-1 | stat. st_size = 0)
Return 2;
OFDM = mmap (0, stat. st_size, PROT_READ, MAP_SHARED, fd, 0 );
If (fdm = MAP_FAILED)
Return 3;
Decode (OFDM, stat. st_size );
If (munmap (OFDM, stat. st_size) =-1)
Return 4;
Ioctl (sfd, SNDCTL_DSP_RESET, 0 );
Close (sfd );
Return 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;
}
/* This section is the pcm audio after processing the sample */
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, n;
Mad_fixed_t const * left_ch, * right_ch;
Unsigned char Output [6912], * OutputPtr;
Int fmt, wrote, speed;
Nchannels = pcm-> channels;
N = nsamples = pcm-> length;
Left_ch = pcm-> samples [0];
Right_ch = pcm-> samples [1];
Fmt = AFMT_S16_LE;
Speed = pcm-> samplerate * 2;/* the playback speed is twice the sampling rate */
Ioctl (sfd, SNDCTL_DSP_SPEED, & (speed ));
Ioctl (sfd, SNDCTL_DSP_SETFMT, & fmt );
Ioctl (sfd, SNDCTL_DSP_CHANNELS, & (pcm-> channels ));
OutputPtr = Output;
While (nsamples --){
Signed int sample;
Sample = scale (* left_ch ++ );
* (OutputPtr ++) = sample> 0;
* (OutputPtr ++) = sample> 8;
If (nchannels = 2 ){
Sample = scale (* right_ch ++ );
* (OutputPtr ++) = sample> 0;
* (OutputPtr ++) = sample> 8;
}
}
N * = 4;/* The data length is 4 times of pcm audio sampling */
OutputPtr = Output;
While (n ){
Wrote = write (sfd, OutputPtr, n );
OutputPtr + = wrote;
N-= wrote;
}
OutputPtr = Output;
Return MAD_FLOW_CONTINUE;
}
Static
Enum mad_flow error (void * data,
Struct mad_stream * stream, struct mad_frame * frame)
{
Return MAD_FLOW_CONTINUE;
}
Static
Int decode (unsigned char const * start, unsigned long length)
{
Struct buffer;
Struct mad_decoder decoder;
Int result;
Buffer. start = start;
Buffer. length = length;
Mad_decoder_init (& decoder, & buffer, input, 0, 0, output, error, 0 );
Mad_decoder_options (& decoder, 0 );
Result = mad_decoder_run (& decoder, MAD_DECODER_MODE_SYNC );
Mad_decoder_finish (& decoder );
Return result;
}