程序說明:其實本來應(yīng)該是在output函數(shù)中設(shè)置采樣率和聲道數(shù)的,但有莫名奇妙的問題。
所以定了個一般化的
#define SAMPLE_RATE 44100
#define CHANNELS 2
#define PCM_DEVICE "plughw:0,0"
即:mp3的采樣率為44100Hz,聲道數(shù)為2(立體聲)
源代碼:
* 本程序是從 minimad 改進而來,如要更詳細的說明請參看 minimad.c * MyMinimad.c , 2009/12/25 , SiChuan University , China * 編譯: gcc MyMinimad.c -o MyMinimad -lmad -lasound * 運行: ./MyMinimad filename.mp3 #include <sys/soundcard.h> #include <alsa/asoundlib.h> #define SAMPLE_RATE 44100 #define PCM_DEVICE "plughw:0,0" static snd_pcm_hw_params_t *hwparams = NULL; static snd_pcm_t *pcm_handle = NULL; unsigned char const *start; static int decode (unsigned char const *, unsigned long); int main (int argc, char *argv[]) fd = open (file, O_RDONLY); if (fstat (fd, &stat) == -1 || stat.st_size == 0) fdm = mmap (0, stat.st_size, PROT_READ, MAP_SHARED, fd, 0); fprintf (stderr, "init_alsa() error/n"); decode (fdm, stat.st_size); if (munmap (fdm, stat.st_size) == -1) snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK; int rate = SAMPLE_RATE; /* Sample rate */ int exact_rate; /* Sample rate returned by */ pcm_name = strdup (PCM_DEVICE); snd_pcm_hw_params_alloca (&hwparams); if (snd_pcm_open (&pcm_handle, pcm_name, stream, 0) < 0) fprintf (stderr, "Error opening PCM device %s/n", pcm_name); if (snd_pcm_hw_params_any (pcm_handle, hwparams) < 0) fprintf (stderr, "Can not configure this PCM device./n"); if (snd_pcm_hw_params_set_access (pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) fprintf (stderr, "Error setting access./n"); if (snd_pcm_hw_params_set_format (pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE) < 0) fprintf (stderr, "Error setting format./n"); if (snd_pcm_hw_params_set_rate_near (pcm_handle, hwparams, &exact_rate, 0) < 0) fprintf (stderr, "Error setting rate./n"); fprintf (stderr, "The rate %d Hz is not supported by your hardware./n==> Using %d Hz instead./n", rate, exact_rate); if (snd_pcm_hw_params_set_channels (pcm_handle, hwparams, CHANNELS) < 0) fprintf (stderr, "Error setting channels./n"); if (snd_pcm_hw_params (pcm_handle, hwparams) < 0) fprintf (stderr, "Error setting HW params./n");
static enum mad_flow input (void *data, struct mad_stream *stream) struct buffer *buffer = data; mad_stream_buffer (stream, buffer->start, buffer->length); return MAD_FLOW_CONTINUE; static inline signed int scale (mad_fixed_t sample) sample += (1L << (MAD_F_FRACBITS - 16)); else if (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, exact_rate, err, dir; nchannels = pcm->channels; n = nsamples = pcm->length; left_ch = pcm->samples[0]; right_ch = pcm->samples[1]; speed = pcm->samplerate * 2; /*播放速度是采樣率的兩倍 */ sample = scale (*left_ch++); *(OutputPtr++) = sample >> 0; *(OutputPtr++) = sample >> 8; sample = scale (*right_ch++); *(OutputPtr++) = sample >> 0; *(OutputPtr++) = sample >> 8; snd_pcm_writei (pcm_handle, OutputPtr, n); 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 mad_decoder decoder; 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);
|