MTK FAQ:如何實現連續的PCM流播放
實現這類PCM的播放(類似於TTS)思路及samplecode如下:
使用雙buffer的機制,TTS使用一個,DSP使用另一個,兩個大小一樣。其中DSP使用的由DSP自行管理,TTS使用的由TTS自行管理。建議TTS使用ringbuffer的機制,設定一個寫指標和一個讀指標,分別指示TTS可以寫入的開始位置和DSP可以讀出的開始位置,兩者的差為可以寫入和可以讀出的長度。
使用流程:
1.開始TTS合成.
2.合成出來第一段PCM資料後呼叫tts_media_play函式,開始播放,設定callback函式Pcm_play_callback。(在開始播放後,tts_media_play只應被呼叫一次,後面喂資料應該是由Pcm_play_callback來完成)
3.TTS繼續合成資料,合成完後就放合適大小(透過計算讀指標與寫指標的差)的PCM資料到TTSbuffer寫指標指示的位置中,並暫停下來等待DSP的event發生。TTSenging如果不能暫停就只能把多出來的資料丟棄。
4.等DSP有event發生底層就會自動呼叫Pcm_play_callback,如果是MEDIA_DATA_REQUEST的event,就從TTSbuffer裡面複製合適大小(透過GetWriteBuffer獲知DSP可以接受的資料,和TTSbuffer的寫指標與讀指標的差做比較,取其中的小者)的資料到DSPbuffer.如果DSP的event上來時TTS還來不及合成資料就立刻返回。
5.如果TTS把所有資料都合成完畢並全部傳給了DSP的buffer,或者從DSP收到MEDIA_END,MEDIA_ERROR,MEDIA_TERMINATED,就呼叫Stop,Close,DataFinished停止播放。
下面是samplecode,供參考:
#defineTTS_BUFFER_LEN1*1024
typedefunsignedcharuint8;
typedefsignedcharint8;
typedefunsignedshortintuint16;
typedefsignedshortintint16;
typedefunsignedintuint32;
typedefsignedintint32;
structVParam
{
uint8*buf_p;
uint32buf_len;
uint32offset;
FS_HANDLEfilehandle;
MHdl*mhdl_handle;
}TTSParam;
kal_uint16tts_ring_buf[TTS_BUFFER_LEN];
voidtts_init(void)
{
TTSParam.buf_p=tts_ring_buf;
TTSParam.buf_len=0;
}
staticvoidPcm_play_callback(MHdl*mhdl,Media_Eventevent)
{
switch(event){
caseMEDIA_END:
caseMEDIA_ERROR:
caseMEDIA_TERMINATED:
{
TTSParam.mhdl_handle->Stop(TTSParam.mhdl_handle);
TTSParam.mhdl_handle->Close(TTSParam.mhdl_handle);
/*closethefile*/
FS_Close(TTSParam.filehandle);
break;
}
caseMEDIA_DATA_REQUEST:
{
kal_uint32read_size=0;
TTSParam.mhdl_handle->GetWriteBuffer(
TTSParam.mhdl_handle,
&TTSParam.buf_p,
&TTSParam.buf_len);
FS_Read(TTSParam.filehandle,TTSParam.buf_p,TTSParam.buf_len,&read_size);
if(read_size>0)
{
TTSParam.mhdl_handle->WriteDataDone(
TTSParam.mhdl_handle,
read_size);
TTSParam.mhdl_handle->FinishWriteData(TTSParam.mhdl_handle);
}
else
{
/*closethefile*/
FS_Close(TTSParam.filehandle);
}
}
}
}
kal_int32tts_media_play(void)
{
/*----------------------------------------------------------------*/
/*LocalVariables*/
/*----------------------------------------------------------------*/
kal_uint32read_size=0;
kal_int32audio_format;
kal_int32result;
Media_Statusaud_ret;
Media_PCM_Stream_ParamvpFormat;
void*param=NULL;
/*----------------------------------------------------------------*/
/*CodeBody*/
/*----------------------------------------------------------------*/
{
vpFormat.isStereo=0;
vpFormat.bitPerSample=16;
vpFormat.sampleFreq=8000;
param=&vpFormat;
TTSParam.filehandle=FS_Open(L"C:\\Images\\OutPcm.pcm",FS_READ_ONLY);
if((TTSParam.mhdl_handle=PCM_Strm_Open(Pcm_play_callback,param))==NULL)
{
return;
}
TTSParam.mhdl_handle->SetBuffer(
TTSParam.mhdl_handle,
(kal_uint8*)tts_ring_buf,
TTS_BUFFER_LEN*2);
TTSParam.mhdl_handle->GetWriteBuffer(
TTSParam.mhdl_handle,
&TTSParam.buf_p,
&TTSParam.buf_len);
FS_Read(TTSParam.filehandle,TTSParam.buf_p,TTSParam.buf_len*2,&read_size);
//hereshouldbeerrorhandlingforFS_Read
if(read_size>0)
{
TTSParam.mhdl_handle->WriteDataDone(
TTSParam.mhdl_handle,
read_size);
aud_ret=TTSParam.mhdl_handle->Play(TTSParam.mhdl_handle);
}
else
{
/*closethefile*/
FS_Close(TTSParam.filehandle);
}
}
}
voidtts_test1(void)
{
tts_init();
tts_media_play();
}
因為在singlebankflash的情況下,為了防止同時讀寫一個bank的情況發生,需要把wavetable的資料搬到RAM上,所以設定為RW資料。但如果你的flash本身是multibank,卻開啟了singlebanksupport,那麼只要保證wavetable放在和FAT不相同的一個bank上,就可以不必搬到RAM上,亦即可以修改為const.
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31529038/viewspace-2654280/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- [FAQ09717]如何去掉mtk自行開發的OOBE快速嚮導 功能中的某段操作引導影片的播放?
- MTK_on_line_FAQ_HW_Wearable_MT2601
- MTK_on_line_FAQ_SW_ALPS_Framework+-+Resource+ManagerTheme+ManagerFramework
- Tinyalsa PCM API 實現深度剖析API
- 如何實現 Android 短影片跨頁面的流暢續播?Android
- mtk faq:聽筒用小喇叭,外放用大喇叭的軟體配置
- iOS開發 整合ijkplayer實現直播#拉流#播放iOS
- 最大連續子陣列和的實現陣列
- 實時流(直播流)播放、上牆(大屏播放)解決方案
- web 頁面如何實現不同分組資料的連續序號?Web
- 音訊開發之錄製播放pcm檔案音訊
- Nginx+FFmpeg實現rtsp流轉hls流,在WEB通過H5 video實現視訊播放NginxWebH5IDE
- MTK FAQ:在檔案管理器中刪除某首歌,再次進入音樂播放器列表,被刪除的歌曲依然顯示播放器
- MTK FAQ:為什麼在single bank的flash中要把wavetable定義為RW data
- Mac實用技巧:如何設定長按delete實現連續刪除小技巧!Macdelete
- Flink SQL 如何實現資料流的 Join?SQL
- APP是如何實現自動續費的?APP
- Android多媒體之SoundPool+pcm流的音訊操作Android音訊
- 如何實現視訊加密全平臺播放加密
- 如何使用 pyqt 實現 Groove 音樂播放器QT播放器
- JMeter流媒體線上播放HLS外掛BlazeMeter - HLS Plugin實現視訊線上播放壓測JMeterPlugin
- Android多媒體之認識聲音、錄音與播放(PCM)Android
- NGINX如何實現rtmp推流服務Nginx
- 如何實現自動化工作流?
- 播放器EasyPlayer.js H5流媒體播放器如何結合m7s流媒體伺服器、obs推流,然後使用播放器播放播放器JSH5伺服器
- 實驗室銀訊PCM配置
- FFmpeg 播放 RTSP/Webcam 流Web
- CAD連續標註如何使用
- 一句話實現MySQL庫中的按連續等值分組MySql
- 會員自動續費該如何實現
- hive生成連續的時間和連續的數Hive
- 如何實現一流的專案可預測性?
- 尋找連續或不連續的子字串字串
- H.265流媒體播放器EasyPlayer.js H5流媒體播放器如何驗證影片播放是否走硬解播放器JSH5
- 硬解碼播放器上如何實現截GIF功能?播放器
- redis實現統計使用者連續登陸天數Redis
- Kafka如何實現實時流處理 Part 1 - André MeloKafka
- 資料庫180:連續出現的數字資料庫