1.1同步方式和異步方式
MadLib是以幀爲單位解碼mp3文件的,所謂同步方式是指解碼函數在解碼完一幀後才返回並帶回出錯信息,異步方式是指解碼函數在調用後立即返回,通過消息傳遞解碼狀態信息。
1.2 Mad API 的調用順序
1、mad_decoder_init()【decoder.h】
Minimad.c中給出了一個函數調用過程的實例。首先定義一個mad_decoder變量(解碼器對象),這時不需要對解碼器對象進行任何初始化。調用mad_decoder_init()函數對剛纔創建的decoder對象進行初始化,mad_decoder_init()函數定義於decoder.h頭文件中。原型如下:
void mad_decoder_init(struct mad_decoder *, //解碼器對象指針
void *,//自定義消息指針,這個值被複制進mad_decoder的cb_data成員
enum mad_flow (*)(void *, struct mad_stream *),//input回調函數
enum mad_flow (*)(void *, struct mad_header const *),//header回調函數
enum mad_flow (*)(void *,struct mad_stream const *,struct mad_frame *),//filter回調函數
enum mad_flow (*)(void *,struct mad_header const *,struct mad_pcm *),//output回調函數
enum mad_flow (*)(void *,struct mad_stream *,struct mad_frame *),//error回調函數
enum mad_flow (*)(void *, void *, unsigned int *)//message回調函數
);
其中的input回到函數和output回調函數是必須定義並傳遞給mad_decoder_init()的,message回調函數在異步工作模式下必選,其他回調函數都可選。
2、mad_stream_buffer()【stream.h】
Input回調函數具有兩個參數,第一個參數是個void指針,指向自定義消息結構,在input回調函數內部對消息進行解釋並調用mad_stream_buffer()函數對輸入流進行初始化,具體參考minimad.c中input函數的寫法。mad_stream_buffer()函數原型如下:
void mad_stream_buffer(struct mad_stream *,//輸入流指針
unsigned char const *, //文件起始地址
unsigned long//文件長度
);
第一個參數指向一個mad_stream變量,mad_stream結構定義在stream.h頭文件裏,用於記錄文件的地址和當前處理的位置。第二、三個參數分別是mp3文件在內存中映像的起始地址和文件長度。mad_stream_buffer()函數將mp3文件與mad_stream結構進行關聯。Input回調函數在解碼器啓動後會被調用一次,在整個解碼過程中都不再被調用。
Output回調函數的原型是:
enum mad_flow (*output_func)(void *,struct mad_header const *,struct mad_pcm *)
Output回調函數將解碼得到的原始PCM塊作爲參數傳入,在這裏可以進行一些解碼後的操作如加入均衡器等。MadLib使用的PCM結構mad_pcm在頭文件synth.h中定義:
struct mad_pcm {
unsigned int samplerate; /* sampling frequency (Hz) */
unsigned short channels; /* number of channels */
unsigned short length; /* number of samples per channel */
mad_fixed_t samples[2][1152]; /* PCM output samples [ch][sample] */
};
Madlib解碼器是以幀爲單位進行解碼的,mad_pcm每次攜帶最多1152個PCM採樣數據(左右聲道共2*1152個),每個採樣使用32bit存放,只使用了其中的24bit,但目前大多數的音頻設備支持的是16bit量化分辨率,所以在交給聲卡輸出前還要自己進行轉換,將24bit分辨率降低爲16bit。length成員指定了當前PCM數據塊的實際大小。
另外兩個參數分別將自定義消息結構和已解碼幀的幀頭傳入,以處理用戶消息和獲取幀信息。Output回調函數在madlib每解碼完成一個幀後被調用,直到全部解碼完成或出錯。
Input和output回調函數的返回值是一個mad_folw枚舉類型,在decoder.h頭文件中定義如下:
enum mad_flow {
MAD_FLOW_CONTINUE = 0x0000, /* continue normally */
MAD_FLOW_STOP = 0x0010, /* stop decoding normally */
MAD_FLOW_BREAK = 0x0011, /* stop decoding and signal an error */
MAD_FLOW_IGNORE = 0x0020 /* ignore the current frame */
};
3、mad_decoder_run()【decoder.h】
獲取了待解嗎的mp3文件後解碼器開始運行。mad_decoder_run()函數可以看作是mad解碼器的運行入口。其原型如下:
int mad_decoder_run(struct mad_decoder * decoder, enum mad_decoder_mode mode)
第一、二個參數將初始化好的decoder變量和解碼器工作模式(同步或異步)進行關聯。後面我們會看到真正完成解碼工作的並不是mad_decoder_run,而是根據工作模式的不同在它的內部調用了另外不同的函數進行解碼。函數返回後解碼就完成了。
4、mad_decoder_finish()【decoder.h】
最後調用mad_decoder_finish()進行最後的清理工作。