MyMinimad ── Linux下用libmad寫的mp3解碼播放程式(二)

來源:互聯網
上載者:User

裝上fedora12後發現沒有/dev/dsp了,所以用ALSA把這個程式重寫了下。

 

程式說明:其實本來應該是在output函數中設定採樣率和聲道數的,但有莫名奇妙的問題。

所以定了個一般化的

#define SAMPLE_RATE 44100
#define CHANNELS 2
#define PCM_DEVICE "plughw:0,0"

即:mp3的採樣率為44100Hz,聲道數為2(立體聲)

 

原始碼:

/*<br /> * 本程式是從 minimad 改進而來,如要更詳細的說明請參看 minimad.c<br /> *<br /> * MyMinimad.c , 2009/12/25 , SiChuan University , China<br /> *<br /> * 編譯: gcc MyMinimad.c -o MyMinimad -lmad -lasound<br /> * 運行: ./MyMinimad filename.mp3<br /> */<br />#include <stdio.h><br />#include <stdlib.h><br />#include <unistd.h><br />#include <sys/stat.h><br />#include <sys/mman.h><br />#include <sys/soundcard.h><br />#include <sys/ioctl.h><br />#include <sys/fcntl.h><br />#include <sys/types.h><br />#include <mad.h><br />#include <alsa/asoundlib.h><br />#define SAMPLE_RATE 44100<br />#define CHANNELS 2<br />#define PCM_DEVICE "plughw:0,0"<br />static snd_pcm_hw_params_t *hwparams = NULL;<br />static snd_pcm_t *pcm_handle = NULL;<br />struct buffer<br />{<br /> unsigned char const *start;<br /> unsigned long length;<br />};<br />static int decode (unsigned char const *, unsigned long);<br />static int init_alsa ();<br />int main (int argc, char *argv[])<br />{<br /> struct stat stat;<br /> void *fdm;<br /> char const *file;<br /> int fd;<br /> file = argv[1];<br /> fd = open (file, O_RDONLY);<br /> if (fstat (fd, &stat) == -1 || stat.st_size == 0)<br /> return -1;<br /> fdm = mmap (0, stat.st_size, PROT_READ, MAP_SHARED, fd, 0);<br /> if (fdm == MAP_FAILED)<br /> return -1;<br /> if (init_alsa () == -1)<br /> {<br /> fprintf (stderr, "init_alsa() error/n");<br /> return -1;<br /> }<br /> decode (fdm, stat.st_size);<br /> if (munmap (fdm, stat.st_size) == -1)<br /> return -1;<br /> return 0;<br />}<br />static int init_alsa ()<br />{<br /> snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;<br /> char *pcm_name;<br /> int rate = SAMPLE_RATE; /* Sample rate */<br /> int exact_rate; /* Sample rate returned by */<br /> pcm_name = strdup (PCM_DEVICE);<br /> snd_pcm_hw_params_alloca (&hwparams);<br /> if (snd_pcm_open (&pcm_handle, pcm_name, stream, 0) < 0)<br /> {<br /> fprintf (stderr, "Error opening PCM device %s/n", pcm_name);<br /> return -1;<br /> }<br /> if (snd_pcm_hw_params_any (pcm_handle, hwparams) < 0)<br /> {<br /> fprintf (stderr, "Can not configure this PCM device./n");<br /> return -1;<br /> }<br /> if (snd_pcm_hw_params_set_access (pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0)<br /> {<br /> fprintf (stderr, "Error setting access./n");<br /> return -1;<br /> }<br /> if (snd_pcm_hw_params_set_format (pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE) < 0)<br /> {<br /> fprintf (stderr, "Error setting format./n");<br /> return -1;<br /> }<br /> exact_rate = rate;<br /> if (snd_pcm_hw_params_set_rate_near (pcm_handle, hwparams, &exact_rate, 0) < 0)<br /> {<br /> fprintf (stderr, "Error setting rate./n");<br /> return -1;<br /> }<br /> if (rate != exact_rate)<br /> {<br /> fprintf (stderr, "The rate %d Hz is not supported by your hardware./n==> Using %d Hz instead./n", rate, exact_rate);<br /> }<br /> if (snd_pcm_hw_params_set_channels (pcm_handle, hwparams, CHANNELS) < 0)<br /> {<br /> fprintf (stderr, "Error setting channels./n");<br /> return -1;<br /> }<br /> if (snd_pcm_hw_params (pcm_handle, hwparams) < 0)<br /> {<br /> fprintf (stderr, "Error setting HW params./n");<br /> return -1;<br /> }<br /> return 0;<br />}</p><p>static enum mad_flow input (void *data, struct mad_stream *stream)<br />{<br /> struct buffer *buffer = data;<br /> if (!buffer->length)<br /> return MAD_FLOW_STOP;<br /> mad_stream_buffer (stream, buffer->start, buffer->length);<br /> buffer->length = 0;<br /> return MAD_FLOW_CONTINUE;<br />}<br />/*這一段是處理採樣後的pcm音頻 */<br />static inline signed int scale (mad_fixed_t sample)<br />{<br /> sample += (1L << (MAD_F_FRACBITS - 16));<br /> if (sample >= MAD_F_ONE)<br /> sample = MAD_F_ONE - 1;<br /> else if (sample < -MAD_F_ONE)<br /> sample = -MAD_F_ONE;<br /> return sample >> (MAD_F_FRACBITS + 1 - 16);<br />}<br />static enum mad_flow output (void *data, struct mad_header const *header, struct mad_pcm *pcm)<br />{<br /> unsigned int nchannels, nsamples, n;<br /> mad_fixed_t const *left_ch, *right_ch;<br /> unsigned char Output[6912], *OutputPtr;<br /> int fmt, wrote, speed, exact_rate, err, dir;<br /> nchannels = pcm->channels;<br /> n = nsamples = pcm->length;<br /> left_ch = pcm->samples[0];<br /> right_ch = pcm->samples[1];<br /> fmt = AFMT_S16_LE;<br /> speed = pcm->samplerate * 2; /*播放速度是採樣率的兩倍 */<br /> OutputPtr = Output;<br /> while (nsamples--)<br /> {<br /> signed int sample;<br /> sample = scale (*left_ch++);<br /> *(OutputPtr++) = sample >> 0;<br /> *(OutputPtr++) = sample >> 8;<br /> if (nchannels == 2)<br /> {<br /> sample = scale (*right_ch++);<br /> *(OutputPtr++) = sample >> 0;<br /> *(OutputPtr++) = sample >> 8;<br /> }<br /> }<br /> OutputPtr = Output;<br /> snd_pcm_writei (pcm_handle, OutputPtr, n);<br /> OutputPtr = Output;<br /> return MAD_FLOW_CONTINUE;<br />}<br />static enum mad_flow error (void *data, struct mad_stream *stream, struct mad_frame *frame)<br />{<br /> return MAD_FLOW_CONTINUE;<br />}<br />static int decode (unsigned char const *start, unsigned long length)<br />{<br /> struct buffer buffer;<br /> struct mad_decoder decoder;<br /> int result;<br /> buffer.start = start;<br /> buffer.length = length;<br /> mad_decoder_init (&decoder, &buffer, input, 0, 0, output, error, 0);<br /> mad_decoder_options (&decoder, 0);<br /> result = mad_decoder_run (&decoder, MAD_DECODER_MODE_SYNC);<br /> mad_decoder_finish (&decoder);<br /> return result;<br />}<br />

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.