ISD9160学习笔记04_ISD9160音频编码代码分析

摘要:
前言录制程序包括录制和播放。最后一个音符是演奏。本文将讨论录音,即音频编码。最后一个注释中的这一段太做作了。我决定再复制一次,呵呵。“我上个月在我的锤子备忘录中写了一个句子,”斯蒂芬·平克说,写作的难点是在树形结构的线性扩展句子中反映网状思维。“这种代码分析也有类似的困难。如何用线性载体(如文章)反映代码的网状结构?”和前面的笔记一样,我仍然选择了要点并告诉自己

前言

录音例程涉及了录音和播放两大块内容,上篇笔记说了播放,这篇就来说说录音这块,也就是音频编码这部分功能。

上篇笔记中的这段话太装逼了,我决定再复制下,嘿嘿。

“我的锤子便签中有上个月记下的一句话,“斯蒂芬·平克说,写作之难,在于把网状思考,用树状结构,体现在线性展开的语句里。”这篇代码解析也有类似的困难,代码的网状结构,如何用文章这种线性载体来体现。”

跟上篇笔记的做法一样,还是挑出了主干,来讲下自己的理解。另外在文章最后添加了一个模块拓扑图来帮助消化。

本文作者twowinter,转载请注明:http://blog.csdn.net/iotisan/

查看代码主逻辑,主要是App_StartRec和App_ProcessRec这两个函数。下面就分别进行分析。

第一部分 App_StartRec

App_StartRec是由按键触发的,也就是按键按下去就开始录音。

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两部分子函数。

重中之重NuLiteExApp_EncodeStart

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

g_sApp.sNuLiteExAppEncode是全局变量,涉及编码库的操作。sAudioChunkHeader是一个临时变量,用来做音频块头部信息。

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;
    }

    // 将全局变量申请的内存传入给编码库,方便其工作执行。将音频块头部传入,编码库最后的输出结果会体现在这里。另外的采样率信息是输入变量,辅助生成最后的音频块。
    // 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;

    // 这一步很关键,设置录音模块部分的缓存。
    // 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这里头涉及一个关键函数,PDMA会把ADC数据直接放到s_pi16AdcBuf里头。

void Record_StartRec(void)
{

    g_u8AppCtrl |= APPCTRL_RECORD;

    #if (ADC_FILTER_ENABLE == 1)
    NoiseFilter_ResetIIR2();
    s_pi16AdcBuf = g_ai16ADCSamples;
    #else
    // 主要是缓冲区的处理
    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

这个部分调用了这个关键函数。SPIFlashUtil_WriteEncodeData。主线程会在大部分时间执行SPIFlashUtil_4KPagePartialWriting,将缓冲逐步写入到SPI FLASH中。

另一个关键函数是NuLiteExApp_EncodeProcess。这是NuLiteEx库的一个编码处理应用。

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

其在内部调用了NuLiteEx_EncodeProcess,这是NuLiteEx库的API。

总结

源码拓扑结构

ISD9160学习笔记04_ISD9160音频编码代码分析第1张

免责声明:文章转载自《ISD9160学习笔记04_ISD9160音频编码代码分析》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇第2章 两种调用JS的方法——在HTML中使用JavaScriptVB.NET中LINQ TO List泛型查询语句(分组,聚合函数)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Android DeepLink 深度链接技术实现

一、DeepLink 技术介绍 DeepLink,即为深度链接技术,主要应用场景是通过Web页面直接调用Android原生app,并且把需要的参数通过Uri的形式,直接传递给app,节省用户的注册成本。 DeepLink 通常运用于App社交分享、App广告引流、App裂变活动、Web to App、分享效果统计、沉默用户唤醒等场景,对广告引流、活动推广、...

激活windows专业版(激活windows10专业版,解决“我们无法在此设备上激活windows因为无法连接到你的组织的激活服务器 ”)

本来系统用的好好的,但是前几天系统突然提示我要去取设置里面激活windows,我就想:我的系统好像是原厂正版的吧,怎么就过期了呢?没办法只能搜索下怎么激活,去系统城,各大网站什么的试了好多密钥全部不行。最后找到了一个能用的,今天记录一下 Solution 以管理员身份打开cmd 然后 slmgr.vbs -skms zh.us.to粘贴进去运行,好了之后去...

【纯净镜像】原版Windows7集成USB3.0+NVME补丁+UEFI引导旗舰版下载

系统简述: 1. 基于MSDN原版Windows7 Ultimate With SP1系统制作,无任何插件和垃圾软件。 2. 系统集成IE11浏览器,装完系统后默认浏览器就是IE11。 3.系统注入了部分补丁,如NVME补丁等。 4. 部署过程中会调用IT天空的万能驱动助理,进行基本驱动安装(网卡、USB3.0驱动),确保可以基本开机使用。 5. 系统部署...

最近使用 .NET Core 遇到的一些坑

最近.NET Core升级到2.0后开始慢慢捣鼓的多了起来,但遇到了不少坑,所以特来记录下。 第一个坑  条件编译符   我们在编写一些方法的时候通常会为Debug模式增加一些输出日志等以便我们检查,也会为Release模式增加或修改一些特定的参数,但今天我在写这些的时候就遇到了这个坑#if !DEBUG  #endif 中间的代码 不能我怎么更改配置环境...

如何上传网站程序(文件浏览器上传网页、FileZilla上传网站程序)

问题场景: 网页制作完成后,程序需上传至虚拟主机。 注意事项: Windows系统的主机请将全部网页文件直接上传到FTP根目录,即/。 Linux系统的主机请将全部网页文件直接上传到/htdocs目录下。 由于Linux主机的文件名是区别大小写的,文件命名需要注意规范,建议使用小写字母,数字或者带下划线,不要使用汉字 。 如果网页文件较多,上传较慢,强烈建...

常用EXE文件反编译工具【转】

http://www.cnblogs.com/happyday56/p/3740108.html PE Explorer V1.99 R5 绿色汉化特别版_强大的可视化汉化集成工具 功能极为强大的可视化汉化集成工具,可直接浏览、修改软件资源,包括菜单、对话框、字符串表等; 另外,还具备有 W32DASM 软件的反编译能力和PEditor 软件的 PE 文件...