国产成人av人人爽人人澡-亚洲国产日韩欧美一区-好吊日视频这里只有精品-日本高清精品视频在线

您好,歡迎進(jìn)入深圳市穎特新科技有限公司官方網(wǎng)站!

您現(xiàn)在的位置:首頁(yè) 新聞資訊 >> 新聞?lì)^條 >> ISD9160學(xué)習(xí)筆記03_ISD9160音頻解碼代碼分析
新聞資訊
NEWS INFORMATION

ISD9160學(xué)習(xí)筆記03_ISD9160音頻解碼代碼分析

發(fā)布時(shí)間:2019-05-22

錄音例程涉及了錄音和播放兩大塊內(nèi)容,這篇筆記就先來說說播放,暫且先擊破解碼這部分功能。

我的錘子便簽中有上個(gè)月記下的一句話,“斯蒂芬·平克說,寫作之難,在于把網(wǎng)狀思考,用樹狀結(jié)構(gòu),體現(xiàn)在線性展開的語句里。”這篇代碼解析也有類似的困難,代碼的網(wǎng)狀結(jié)構(gòu),如何用文章這種線性載體來體現(xiàn)。我盡量挑出了主干,來講解自己的理解。另外在文章最后添加了一個(gè)模塊拓?fù)鋱D來幫助消化。

我還是建議大家還是多琢磨下源碼,代碼的事還是讓代碼來說話,筆記是一個(gè)輔助的概括梳理。

本文作者twowinter,轉(zhuǎn)載請(qǐng)注明:http://blog.csdn.net/iotisan/

查看代碼主邏輯,主要是App_StartPlay和App_ProcessPlay這兩個(gè)函數(shù)。下面就分別進(jìn)行分析。

第一部分 App_StartPlay

BOOL App_StartPlay(void)
{
    // Initiate NuLiteEx audio decode lib with callback functions stored in g_asAppCallBack[0]
    NuLiteExApp_DecodeInitiate(&g_sApp.sNuLiteExAppDecode, (UINT8 *)&g_sApp.uTempBuf, 0);

    // Start NuLiteEx decode lib to decode NuLiteEx file stored from address and played from audio channel 0.
    // And decode the first frame of PCMs.
    if ( NuLiteExApp_DecodeStartPlayByAddr(&g_sApp.sNuLiteExAppDecode, AUDIOROM_STORAGE_START_ADDR, 0) == FALSE )
        return FALSE;

    // Light playback led(PB9) for display status.
    OUT4(0);

    // Start Ultraio Timer & HW pwm for UltraIO curve output
    ULTRAIO_START();

    // Start to playback audio. 
    Playback_StartPlay();
}

可以看到App_StartPlay主要牽扯了NuLiteExApp和Playback兩部分子函數(shù)。

重中之重 NuLiteExApp_DecodeStartPlayByAddr

由于對(duì)音頻編解碼這塊比較陌生,我還是給對(duì)應(yīng)代碼做了中文注解方便消化。

BOOL NuLiteExApp_DecodeStartPlayByAddr(S_NULITEEX_APP_DECODE *psNuLiteExAppDecode, UINT32 u32NuLiteExStorageStartAddr, UINT8 u8PlaybackChannel)
{
    UINT16 u16SampleRate;
    // NuLiteEx解碼庫(kù)初始化對(duì)應(yīng)的工作緩沖區(qū),應(yīng)用層傳入temp緩存來方便解碼庫(kù)內(nèi)部工作。另外根據(jù)傳入的SPI地址從SPI取文件,獲取采樣率。
    // NuLiteEx decoder initiates work buffer and returns sample rate.
    if ( (u16SampleRate = NuLiteEx_DecodeInitiate(  (UINT8*)psNuLiteExAppDecode->au32DecodeWorkBuf, 
                                                    psNuLiteExAppDecode->pau8TempBuf, 
                                                    u32NuLiteExStorageStartAddr, 
                                                    g_asAppCallBack[psNuLiteExAppDecode->u8CallbackIndex].pfnReadDataCallback )) == 0 )
        return FALSE;   

    // 給Playback模塊對(duì)接對(duì)應(yīng)的工作緩沖區(qū),方便其下一步播放。
    // Initiate and set output buffer variable(include frame size, buffer size etc.) 
    Playback_SetOutputBuf(  &psNuLiteExAppDecode->sOutBufCtrl,
                            NULITEEXAPP_OUT_BUF_SIZE,
                            psNuLiteExAppDecode->i16OutBuf,
                            NULITEEXAPP_OUT_SAMPLES_PER_FRAME,
                            u16SampleRate );

    // 工作緩沖區(qū),置有效位。
    // Trigger active flag of output buffer for NuLiteEx decoding
    BUF_CTRL_SET_ACTIVE(&psNuLiteExAppDecode->sOutBufCtrl);

    // 工作緩沖區(qū)中的讀寫指針賦值。
    // Pre-decode one frame
    psNuLiteExAppDecode->sOutBufCtrl.u16BufWriteIdx = NULITEEXAPP_OUT_SAMPLES_PER_FRAME;
    if ( NuLiteExApp_DecodeProcess(psNuLiteExAppDecode) == FALSE )
    {
        BUF_CTRL_SET_INACTIVE(&psNuLiteExAppDecode->sOutBufCtrl);
        return FALSE;
    }
    psNuLiteExAppDecode->sOutBufCtrl.u16BufReadIdx = NULITEEXAPP_OUT_SAMPLES_PER_FRAME;

    // 記錄當(dāng)前播放的channel,用來停止播放。
    // Record play channel index for stopping to play.
    psNuLiteExAppDecode->u8PlaybackChannel = u8PlaybackChannel;
    // 準(zhǔn)備播放,把這里的循環(huán)緩沖區(qū)同playback共用。
    // Add audio codec into channel and preper to play codec.
    Playback_Add(psNuLiteExAppDecode->u8PlaybackChannel, &psNuLiteExAppDecode->sOutBufCtrl);

    return TRUE;
}

也很重要的Playback_StartPlay

void Playback_StartPlay(void)
{
    INT16 *pi16PcmBuf;

    if( s_u8PlayCtrl == PLAYBACK_NOACTION ) // 這個(gè)s_u8PlayCtrl是playback模塊內(nèi)部處理的。
    {
        #if ( PLAYBACK_CHANNEL_COUNT > 1)
        pi16PcmBuf = g_ai16DACSamples;
        #else
        pi16PcmBuf = &g_psDacBufCtrl->pi16Buf[g_psDacBufCtrl->u16BufReadIdx];// PCM數(shù)據(jù)緩沖區(qū)復(fù)制。
        #endif

        #if ((APU_FILTER_ENABLE == 1)&&(APU_UPSAMPLE == 2))
        NuDACFilterEx_Up2Initial(g_au8Up2WorkBuf);
        #elif ((APU_FILTER_ENABLE == 1)&&(APU_UPSAMPLE == 4))
        NuDACFilterEx_Up4Initial(g_au8Up4WorkBuf);
        #endif
        g_u8AppCtrl|=APPCTRL_PLAY;
        s_u8PlayCtrl |= PLAYBACK_START;
        #if (APU_ENABLE)
        {
            UINT8 u8Count;

            for( u8Count = 0; u8Count < 8; u8Count ++)
                g_ai16DACSamples[u8Count] = 0;      //Clear virtual buffer
        }
        #endif

        Playback_ResetChannelVolume(0);

        SPK_Start(); // 這里頭開始調(diào)用DPWM來播放DPWM->DATA,DPWM_START_PLAY(DPWM);

        #if (APU_PDMA_ENABLE)
        PdmaCtrl_Start(APU_PDMA_CH, (uint32_t *)pi16PcmBuf, (uint32_t *)&DPWM->DATA, 8);// 將PCM緩沖數(shù)據(jù)傳到DPWM->DATA中。
        #endif

    }
}

第二部分 App_ProcessPlay

App_ProcessPlay只調(diào)用了如下這個(gè)函數(shù)

BOOL NuLiteExApp_DecodeProcess(S_NULITEEX_APP_DECODE *psNuLiteExAppDecode)
{
    INT16 *pi16OutBuf;

    // 環(huán)形緩沖區(qū)非激活狀態(tài),這個(gè)只有在應(yīng)用層置位(按鍵停止、或者啟動(dòng)失敗等情況)
    if (BUF_CTRL_IS_INACTIVE(&psNuLiteExAppDecode->sOutBufCtrl))
        return FALSE;

    // 環(huán)形緩沖區(qū)還有未讀數(shù)據(jù)
    if ( Playback_NeedUpdateOutputBuf(&psNuLiteExAppDecode->sOutBufCtrl) )
    {
        // 由核心庫(kù)來判斷這個(gè)文件是否解析完了
        // Check end of file
        if(NuLiteEx_DecodeIsEnd((UINT8*)psNuLiteExAppDecode->au32DecodeWorkBuf))
        {
            // Trigger inactive flag of output buffer to stop NuLiteEx decoding
            BUF_CTRL_SET_INACTIVE(&psNuLiteExAppDecode->sOutBufCtrl);
            // Use to represnt no active(or end) of decoding
            psNuLiteExAppDecode->sOutBufCtrl.u16SampleRate = 0;
            return FALSE;
        }

        // Record output data buffer pointer(for duplicate & process)
        pi16OutBuf = (PINT16)&psNuLiteExAppDecode->sOutBufCtrl.pi16Buf[psNuLiteExAppDecode->sOutBufCtrl.u16BufWriteIdx];

        // 核心庫(kù)繼續(xù)發(fā)揮其巨大作用,開足馬力讀取文件中PCM數(shù)據(jù)轉(zhuǎn)到緩沖區(qū)。
        NuLiteEx_DecodeProcess( (UINT8*)psNuLiteExAppDecode->au32DecodeWorkBuf, 
                                psNuLiteExAppDecode->pau8TempBuf, 
                                pi16OutBuf, 
                                g_asAppCallBack[psNuLiteExAppDecode->u8CallbackIndex].pfnReadDataCallback, 
                                g_asAppCallBack[psNuLiteExAppDecode->u8CallbackIndex].pfnUserEventCallback);

        // PlayBack依舊共享這個(gè)緩沖區(qū),準(zhǔn)備對(duì)數(shù)據(jù)進(jìn)行進(jìn)一步處理
        // Update write index of output buffer and avoid buffer overflow
        Playback_UpdateOutputBuf(&psNuLiteExAppDecode->sOutBufCtrl);

        // Duplicate data into buffer for using duplication callback function.
        if ( psNuLiteExAppDecode->u8CtrlFlag&(NULITEEXAPP_CTRL_DUPLICATE_TO_BUF|NULITEEXAPP_CTRL_DUPLICATE_TO_FUNC) )
        {
            if ( psNuLiteExAppDecode->u8CtrlFlag & NULITEEXAPP_CTRL_DUPLICATE_TO_BUF )
                BufCtrl_WriteWithCount(psNuLiteExAppDecode->psDuplicateOutBufCtrl, NULITEEXAPP_OUT_SAMPLES_PER_FRAME, pi16OutBuf );
            else 
                psNuLiteExAppDecode->pfnDuplicateFunc(NULITEEXAPP_OUT_SAMPLES_PER_FRAME, pi16OutBuf);
        }       
    }   
    return TRUE;
}

總結(jié)

源碼拓?fù)浣Y(jié)構(gòu)

 

聯(lián)系方式0755-82591179

傳真:0755-82591176

郵箱:vicky@yingtexin.net

地址:深圳市龍華區(qū)民治街道民治大道973萬眾潤(rùn)豐創(chuàng)業(yè)園A棟2樓A08

日本最新不卡免费一区二区| 亚洲综合精品天堂夜夜| 国产又粗又长又大高潮视频| 精品日韩中文字幕视频在线| 麻豆印象传媒在线观看| 欧美日韩欧美国产另类| 麻豆在线观看一区二区| 日本女人亚洲国产性高潮视频| 在线观看免费午夜福利| 亚洲欧美日产综合在线网| 日韩精品区欧美在线一区| 国产专区亚洲专区久久| 韩国日本欧美国产三级| 高潮少妇高潮久久精品99| 中文字幕一区二区三区中文| 久久99亚洲小姐精品综合| 国产欧美精品对白性色| 国产一区二区三区四区免费| 亚洲欧美日韩国产成人 | 韩国日本欧美国产三级| 欧美乱码精品一区二区三| 最近中文字幕高清中文字幕无| 91精品国自产拍老熟女露脸 | 亚洲视频一区自拍偷拍另类| 白丝美女被插入视频在线观看| 狠色婷婷久久一区二区三区| 亚洲另类女同一二三区| 黄色日韩欧美在线观看| 国产免费黄片一区二区| 国产精品欧美激情在线观看| 国产日本欧美韩国在线| 亚洲男人天堂成人在线视频| 国产日韩欧美在线播放| 欧美字幕一区二区三区| 国产日韩欧美综合视频| 在线观看视频日韩成人| 欧美人妻少妇精品久久性色| 夫妻性生活真人动作视频| 大香蕉伊人精品在线观看| 人妻少妇系列中文字幕| 国产一区二区三区午夜精品|