电子音乐识别器
一、项目名称: 电子音乐识别器
二、项目概述:
开发板开发语音采集和编码方式。采用8kHz的PCM编码方式,然后用后台对PCM进行识别和量化,通过FFT快速傅里叶变换,形成频谱图,识别出音高。根据这个音高值对比形成电子校音器。[size=15.3333px] 这个项目展现LPC54114的特征,包括:灵敏的板载麦克风,以及高速的DSPlib来实现FFT功能,使用双核通讯来传递识别出来的频率,并通过串口显示出来。
三、作品实物图 1. 开发板加电运行图
2. 实测响应图
3 显示在开关变化后输出的频率
四、演示视频
五、项目文档 [size=15.3333px]5.1 产品逻辑框图 [size=15.3333px]5.2 [size=15.3333px]使用说明 [size=15.3333px]5.2.1 首先需要编译创建cm0内核的bin可执行文件,主要代码如下,用uart_write输出形成的音频数据 - if (has_received)
- {
- has_received = 0;
- ch=msg.DATA;
- USART_WriteBlocking(DEMO_USART, &ch, 1);
- rpmsg_lite_send(my_rpmsg, my_ept, remote_addr, (char *)&msg, sizeof(THE_MESSAGE), RL_DONT_BLOCK);
- }
复制代码5.2.2 在cm4内核中引入这个bin文件,写入代码区,这个bin文件就编译进了整个项目中。 - #define CORE1_BOOT_ADDRESS (void *)0x20010000
- #if defined(__CC_ARM)
- extern uint32_t Image$CORE1_REGION$Base;
- extern uint32_t Image$CORE1_REGION$Length;
- #define CORE1_IMAGE_START &Image$CORE1_REGION$Base
复制代码使用keil的时候,需要修订内存分布如下 编译后的结果如下,这样就可以把程序写入内存了。 [size=15.3333px]
[size=15.3333px]5.2.3 音乐识别,需要[size=15.3333px]DMIC_CtrlClrIntrHwvad功能和DMIC_TransferReceiveDMA功能,实现的功能是在声音启动后,开始读取DMIC直接进入DMA,因为DMA的buffer只有16字节,所以当超过16字节的数据,需要及时写入数组。 [size=15.3333px]以下数据确定了8kHz的采样速率,以实现数据采集,这样可以最大识别4kHz的音频数据。对应最高B7的音高 3951.07Hz
- dmic_channel_cfg.divhfclk = kDMIC_PdmDiv1;
- dmic_channel_cfg.osr = 25U;
- dmic_channel_cfg.gainshft = 3U;
- dmic_channel_cfg.preac2coef = kDMIC_CompValueZero;
- dmic_channel_cfg.preac4coef = kDMIC_CompValueZero;
- dmic_channel_cfg.dc_cut_level = kDMIC_DcCut155;
- dmic_channel_cfg.post_dc_gain_reduce = 0U;
- dmic_channel_cfg.saturate16bit = 1U;
- dmic_channel_cfg.sample_rate = kDMIC_PhyFullSpeed;
- DMIC_Init(DMIC0);
复制代码
[size=15.3333px]
[size=15.3333px]5.2.4 音乐识别采用dsp的功能,因此需要引入DSPlib中的fft函数。识别之后,生成的数组用fft变换直接生成频谱,并识别出音乐的基因频率。 - /*start DSP FFT */
- arm_cfft_f32(&arm_cfft_sR_f32_len1024, testInput_f32_10khz, ifftFlag, doBitReverse); //Process the data through the CFFT/CIFFT module
- arm_cmplx_mag_f32(testInput_f32_10khz, testOutput, fftSize); // Process the data through the Complex Magnitude Module for calculating the magnitude at each bin
- arm_max_f32(testOutput, fftSize, &maxValue, &testIndex); // Calculates maxValue and returns corresponding BIN value
- if (testIndex != refIndex) { status = ARM_MATH_TEST_FAILURE;} // Check results...
- if ( status != ARM_MATH_SUCCESS) { PRINTF("ARM_MATH Fails. \r\n");; }
- else {
- PRINTF("testIndex= %d \r\n", testIndex);
- };
- /*end of DSP FFT */
复制代码
5.2.5 生成的数据,即testIndex数据,启动双核通讯功能,传送的cm0 内核,如5.2.1所述输出到UART串口。 - /* Initialize MCMGR before calling its API */
- MCMGR_Init();
- /* Register the application event before starting the secondary core */
- MCMGR_RegisterEvent(kMCMGR_RemoteApplicationEvent, RPMsgRemoteReadyEventHandler, (void *)&RPMsgRemoteReadyEventData);
- /* Boot Secondary core application */
- MCMGR_StartCore(kMCMGR_Core1, CORE1_BOOT_ADDRESS, (uint32_t)rpmsg_lite_base, kMCMGR_Start_Synchronous);
- /* Print the initial banner */
- PRINTF("\r\nRPMsg demo starts in primary Core0.\r\n");
- /* Wait until the secondary core application signals the rpmsg remote has been initialized and is ready to communicate. */
- while(APP_RPMSG_READY_EVENT_DATA != RPMsgRemoteReadyEventData) {};
- my_rpmsg = rpmsg_lite_master_init(rpmsg_lite_base, SH_MEM_TOTAL_SIZE, RPMSG_LITE_LINK_ID, RL_NO_FLAGS, &rpmsg_ctxt);
- my_ept = rpmsg_lite_create_ept(my_rpmsg, LOCAL_EPT_ADDR, my_ept_read_cb, (void *)&has_received, &my_ept_context);
- has_received = 0;
- /* Wait until the secondary core application signals the rpmsg remote endpoint has been created. */
- while(APP_RPMSG_EP_READY_EVENT_DATA != RPMsgRemoteReadyEventData) {};
复制代码
[size=15.3333px]5.2.6 核心的代码是启动后初始化外设后,进入中断状态,等待声音驱动的中断响应程序,实现对以上程序的逐个调用。 - void DMIC0_HWVAD_Callback(void)
- {
- ...
- }
复制代码5.2.7 测试后显示的截图 [size=15.3333px]5.3 工程项目文件 |