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

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

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

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

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

前言

錄音例程涉及了錄音和播放兩大塊內(nèi)容,上篇筆記說了播放,這篇就來說說錄音這塊,也就是音頻編碼這部分功能。

上篇筆記中的這段話太裝逼了,我決定再復(fù)制下,嘿嘿。

“我的錘子便簽中有上個(gè)月記下的一句話,“斯蒂芬·平克說,寫作之難,在于把網(wǎng)狀思考,用樹狀結(jié)構(gòu),體現(xiàn)在線性展開的語句里。”這篇代碼解析也有類似的困難,代碼的網(wǎng)狀結(jié)構(gòu),如何用文章這種線性載體來體現(xiàn)。”

跟上篇筆記的做法一樣,還是挑出了主干,來講下自己的理解。另外在文章最后添加了一個(gè)模塊拓?fù)鋱D來幫助消化。

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

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

第一部分 App_StartRec

App_StartRec是由按鍵觸發(fā)的,也就是按鍵按下去就開始錄音。

BOOL App_StartRec(void)
{
    S_AUDIOCHUNK_HEADER sAudioChunkHeader;

    // 這回就不是Decode了,改用Encode。
    // Initiate NuLiteEx audio encode lib with temp buffer provided for lib.
    NuLiteExApp_EncodeInitiate(&g_sApp.sNuLiteExAppEncode, (UINT8 *)&g_sApp.uTempBuf);

    // Start to encode NuLiteEx data with sample rate, bit per frame and saved data information into audio chunk header.
    if (NuLiteExApp_EncodeStart(&g_sApp.sNuLiteExAppEncode, &sAudioChunkHeader, ADC_SAMPLE_RATE, E_NULITEEX_ENCODE_BPS_10) == FALSE)
        return FALSE;

    // SPIFlash utility function provide encode data write into SPIFlash.
    // detail info please refer "SPIFlashUtil.h"
    SPIFlahUtil_StartWriteEncodeData(&sAudioChunkHeader, AUDIOROM_STORAGE_START_ADDR, NULL);

    // Light record led for display status.
    OUT5(0);

    // Start to record PCM data into buffer for produc NuLiteEx encode data.
    Record_StartRec();

    return TRUE;    
}

可以看到App_StartRec主要牽扯了NuLiteExApp_EncodeStart和Record兩部分子函數(shù)。

重中之重NuLiteExApp_EncodeStart

NuLiteExApp_EncodeStart(&g_sApp.sNuLiteExAppEncode, &sAudioChunkHeader, ADC_SAMPLE_RATE, E_NULITEEX_ENCODE_BPS_10);照例對(duì)代碼做了中文注解方便消化。

g_sApp.sNuLiteExAppEncode是全局變量,涉及編碼庫的操作。sAudioChunkHeader是一個(gè)臨時(shí)變量,用來做音頻塊頭部信息。

 

BOOL NuLiteExApp_EncodeStart( S_NULITEEX_APP_ENCODE *psNuLiteExAppEncode, S_AUDIOCHUNK_HEADER *psAudioChunkHeader, 
                              UINT16 u16SampleRate, enum eNuLiteExEncodeBPS eBitPerSample)
{
    if ( (eBitPerSample > NULITEEXAPP_ENCODE_MAX_BITRATE) || (u16SampleRate == 0) )
        return FALSE;
    else
    {
        psAudioChunkHeader->u16SmplRate = u16SampleRate;
        psAudioChunkHeader->u32BitPerFrame = eBitPerSample;
    }

    // 將全局變量申請(qǐng)的內(nèi)存?zhèn)魅虢o編碼庫,方便其工作執(zhí)行。將音頻塊頭部傳入,編碼庫最后的輸出結(jié)果會(huì)體現(xiàn)在這里。另外的采樣率信息是輸入變量,輔助生成最后的音頻塊。
    // NuLiteEx encoder initiates work buffer.
    // Set bit rate and sample rate information for audio chunk header.
    NuLiteEx_EncodeInitiate((UINT8 *)psNuLiteExAppEncode->au32WorkBuf, psNuLiteExAppEncode->pau8TempBuf, 
        psAudioChunkHeader, (enum eNuLiteExEncodeBPS)psAudioChunkHeader->u32BitPerFrame, psAudioChunkHeader->u16SmplRate);

    // Reset encode buffer read index and write index
    psNuLiteExAppEncode->sEncodeBufCtrl.u16BufWriteIdx = 0;
    psNuLiteExAppEncode->sEncodeBufCtrl.u16BufReadIdx = 0;

    // Set Encoded frame size, Storage Utility will refer to this size to write data.
    psNuLiteExAppEncode->sEncodeBufCtrl.u16FrameSize =  (psAudioChunkHeader->u32BitPerFrame)>>3;
    psNuLiteExAppEncode->sEncodeBufCtrl.u16BufCount = (psNuLiteExAppEncode->sEncodeBufCtrl.u16FrameSize)*NULITEEXAPP_ENCODE_BUF_COUNT;

    // 這一步很關(guān)鍵,設(shè)置錄音模塊部分的緩存。
    // Set input buffer size, PCM buffer pointer, frame size and sample rate.
    Record_SetInBufRecord(  &psNuLiteExAppEncode->sInBufCtrl, 
                            NULITEEXAPP_IN_BUF_SIZE,
                            psNuLiteExAppEncode->i16InBuf,
                            NULITEEX_ENCODE_SAMPLE_PER_FRAME,
                            psAudioChunkHeader->u16SmplRate);

    // 都要做這一步操作,錄音模塊的操作順序就是這樣:SetInBufRecord ->Add -> StartRec。
    // Set application input buffer to record(ADC) output buffer.
    Record_Add(&psNuLiteExAppEncode->sInBufCtrl, psAudioChunkHeader->u16SmplRate);

    return TRUE;
}

也很重要的Record_StartRec

上面說錄音模塊的操作順序就是這樣:SetInBufRecord ->Add -> StartRec。這就來了。 
硬件PDMA這里頭涉及一個(gè)關(guān)鍵函數(shù),PDMA會(huì)把ADC數(shù)據(jù)直接放到s_pi16AdcBuf里頭。

void Record_StartRec(void)
{

    g_u8AppCtrl |= APPCTRL_RECORD;

    #if (ADC_FILTER_ENABLE == 1)
    NoiseFilter_ResetIIR2();
    s_pi16AdcBuf = g_ai16ADCSamples;
    #else
    // 主要是緩沖區(qū)的處理
    if ( BUF_CTRL_ISNOT_CALLBACK(g_psAdcBufCtrl))   
        s_pi16AdcBuf = &g_psAdcBufCtrl->pi16Buf[g_psAdcBufCtrl->u16BufWriteIdx];
    else
        s_pi16AdcBuf = g_ai16ADCSamples;
    #endif

    // 采用了硬件PDMA的方式
    #if (ADC_PDMA_ENABLE == 1)  
    PdmaCtrl_Start(ADC_PDMA_CH, (uint32_t *)&ADC->DAT, (uint32_t *)s_pi16AdcBuf, 8);
    #endif

    MIC_Start();
}

第二部分 App_ProcessRec

這個(gè)部分調(diào)用了這個(gè)關(guān)鍵函數(shù)。SPIFlashUtil_WriteEncodeData。主線程會(huì)在大部分時(shí)間執(zhí)行SPIFlashUtil_4KPagePartialWriting,將緩沖逐步寫入到SPI FLASH中。

另一個(gè)關(guān)鍵函數(shù)是NuLiteExApp_EncodeProcess。這是NuLiteEx庫的一個(gè)編碼處理應(yīng)用。

// Keep encode PCM buffer data to NuLiteEx lib.
NuLiteExApp_EncodeProcess(&g_sApp.sNuLiteExAppEncode);

其在內(nèi)部調(diào)用了NuLiteEx_EncodeProcess,這是NuLiteEx庫的API。

總結(jié)

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

 

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

傳真:0755-82591176

郵箱:vicky@yingtexin.net

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

亚洲中文字幕在线观看黑人 | 国产一区二区三中文字幕| 日本人妻免费一区二区三区| 国产乱淫av一区二区三区| 果冻传媒精选麻豆白晶晶| 老司机精品视频在线免费看| 丰满人妻熟妇乱又乱精品古代| 欧美亚洲国产日韩一区二区| 自拍偷拍一区二区三区| 日本大学生精油按摩在线观看| 夜夜躁狠狠躁日日躁视频黑人| 日本人妻的诱惑在线观看| 久久精品国产99国产免费| 美女被后入视频在线观看| 亚洲综合日韩精品欧美综合区| 亚洲中文字幕人妻av| 亚洲一区二区三区一区| 欧美大胆美女a级视频| 日韩一区中文免费视频| 人妻久久这里只有精品| 九九视频通过这里有精品| 女同伦理国产精品久久久| 99视频精品免费视频播放| 国产一区欧美一区日本道| 亚洲伦片免费偷拍一区| 日本精品中文字幕在线视频| 91天堂免费在线观看| 日韩综合国产欧美一区| 国产盗摄精品一区二区视频| 国产视频在线一区二区| 国产精品乱子伦一区二区三区| 日韩18一区二区三区| 午夜精品久久久免费视频| 国产精品亚洲综合天堂夜夜| 亚洲性日韩精品一区二区| 99久免费精品视频在线观| 亚洲日本久久国产精品久久| 99久久国产亚洲综合精品| 色鬼综合久久鬼色88| 久久99亚洲小姐精品综合| 午夜亚洲精品理论片在线观看|