美文网首页
MTK FAQ:如何实现连续的PCM流播放

MTK FAQ:如何实现连续的PCM流播放

作者: 体感互动 | 来源:发表于2019-08-20 14:33 被阅读0次

    实现这类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.

    来源:http://bbs.16rd.com/thread-479503-1-1.html

    相关文章

      网友评论

          本文标题:MTK FAQ:如何实现连续的PCM流播放

          本文链接:https://www.haomeiwen.com/subject/svlpsctx.html