实现高精度卷积混响--嵌入式MCU篇

一、硬件平台

MCU选用NXP的RT1052,SDRAM使用NT5SV16M16CS-6K,CODEC选用CS4270

二、软件实现

1、I2S配置
配置I2S为48K,立体声,24bit,MCLK = 12.2888M,BCLK = 3.0722M

void xBSP_I2S_Init(void)
{
	sai_config_t config;

	IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_03_SAI1_MCLK, 1U);
	IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_03_SAI1_MCLK, 0x10B0u);
	
	IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B1_12_SAI1_RX_DATA00, 1U);
	IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B1_12_SAI1_RX_DATA00, 0x10B0u);
	
	
	IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B1_13_SAI1_TX_DATA00, 1U);
	IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B1_13_SAI1_TX_DATA00, 0x10B0u);

	
	IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B1_14_SAI1_TX_BCLK, 1U);
	IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B1_14_SAI1_TX_BCLK, 0x10B0u);
	
	IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B1_15_SAI1_TX_SYNC, 1U);	
	IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B1_15_SAI1_TX_SYNC, 0x10B0u);



	//时钟初始化
	CLOCK_InitAudioPll(&audioPllConfig);

	//使用PLL时钟
	CLOCK_SetMux(kCLOCK_Sai1Mux, C052_SAI1_CLOCK_SOURCE_SELECT);
	CLOCK_SetDiv(kCLOCK_Sai1PreDiv, C052_SAI1_CLOCK_SOURCE_PRE_DIVIDER);
	CLOCK_SetDiv(kCLOCK_Sai1Div, C052_SAI1_CLOCK_SOURCE_DIVIDER);

	edma_config_t sai_dmaConfig = {0};
	/* Init DMA and create handle for DMA */
	EDMA_GetDefaultConfig(&sai_dmaConfig);
	EDMA_Init(C052_DMA, &sai_dmaConfig);
	//RX
	EDMA_CreateHandle(&dmaRxHandle, C052_DMA, C052_RX_CHANNEL);
	//TX
	EDMA_CreateHandle(&dmaTxHandle, C052_DMA, C052_TX_CHANNEL);

	/* Init DMAMUX */
	DMAMUX_Init(C052_DMAMUX);
	//RX
	DMAMUX_SetSource(C052_DMAMUX, C052_RX_CHANNEL, (uint8_t)C052_SAI_RX_SOURCE);
	DMAMUX_EnableChannel(C052_DMAMUX, C052_RX_CHANNEL);
	//TX
	DMAMUX_SetSource(C052_DMAMUX, C052_TX_CHANNEL, (uint8_t)C052_SAI_TX_SOURCE);
	DMAMUX_EnableChannel(C052_DMAMUX, C052_TX_CHANNEL);
	
	

	/* Init SAI module */
	/*
	 * sai_config.masterSlave      = kSAI_Master;
	 * sai_config.mclkSource       = kSAI_MclkSourceSysclk;
	 * sai_config.protocol         = kSAI_BusLeftJustified;
	 * sai_config.syncMode         = kSAI_ModeAsync;
	 * sai_config.mclkOutputEnable = true;
	 */

	SAI_TxGetDefaultConfig(&config);
	config.masterSlave = kSAI_Master;
	config.protocol = kSAI_BusI2S;  //kSAI_BusI2S
	SAI_TxInit(C052_SAI, &config);

	SAI_RxGetDefaultConfig(&config);
	config.masterSlave = kSAI_Master;
	config.protocol = kSAI_BusI2S;	//
	SAI_RxInit(C052_SAI, &config);

	/* Configure the audio format */
	format.bitWidth = kSAI_WordWidth32bits;  //必须是32位
	format.channel =  0;
	format.sampleRate_Hz = kSAI_SampleRate48KHz;
	format.masterClockHz = C052_SAI_CLK_FREQ;
	format.protocol = config.protocol;
	format.stereo = kSAI_Stereo;
	format.isFrameSyncCompact = false;
	format.watermark = 16;//FSL_FEATURE_SAI_FIFO_COUNT / 2;

	//RX 接收存在DMA
	format.channel =  0;
	format.channelMask = 0;
	SAI_TransferRxCreateHandleEDMA(C052_SAI, &rxHandle, xBSP_AudioRxCallback, NULL, &dmaRxHandle);
	SAI_TransferRxSetFormatEDMA(C052_SAI, &rxHandle, &format, C052_SAI_CLK_FREQ, format.masterClockHz);
	sai_transfer_receive.dataSize = AUDIO_DOT_NUM*4;
	sai_transfer_receive.data = (uint8_t *)&audioRecDMATempBuff[sai_receive_fifo_index * AUDIO_DOT_NUM];
	

	//TX 接收存在DMA
	format.channel =  0;
	format.channelMask = 0;
	SAI_TransferTxCreateHandleEDMA(C052_SAI, &txHandle, xBSP_AudioTxCallback, NULL, &dmaTxHandle);
	SAI_TransferTxSetFormatEDMA(C052_SAI, &txHandle, &format, C052_SAI_CLK_FREQ, format.masterClockHz);
	sai_transfer_send.dataSize = AUDIO_DOT_NUM*4;
	sai_transfer_send.data = (uint8_t *)&audioSendDMATempBuff[sai_send_fifo_write * AUDIO_DOT_NUM];
	
	

}

void xBSP_I2S_Start(void)
{
	__disable_irq();
	NVIC_SetPriority(DMA0_DMA16_IRQn, 0);
	NVIC_SetPriority(DMA1_DMA17_IRQn, 1);
	SAI_TransferReceiveEDMA(C052_SAI, &rxHandle, &sai_transfer_receive);
	SAI_TransferSendEDMA(C052_SAI, &txHandle, &sai_transfer_send);
	xBSP_I2S_MclkOutput(true);
	__enable_irq();
	
}

2、卷积长度设置为32768,MATLAB导出ROMM3的脉冲响应数据

3、内存划分
OCRAM = 32K,DTCM = 416KB, ITCM = 64KB,最大限度使用内部内存,加快访问速度

				LDR     R0,=0x400AC038
				LDR     R1,=0x00AA0000
				STR     R1,[R0]
				LDR     R0,=0x400AC040
				LDR     R1,=0x00200007
				STR     R1,[R0]
				LDR     R0,=0x400AC044
				LDR     R1,=0x6AAAAAAF ; OCRAM = 32K,DTCM = 416KB, ITCM = 64KB
				STR     R1,[R0]			

4、配置SDRAM
修改DCD数组,配置SDRAM超频到200M

const uint8_t dcd_sdram[1072] = {
/*0000*/ 0xD2, 0x04, 0x30, 0x41, 0xCC, 0x03, 0xAC, 0x04, 0x40, 0x0F, 0xC0, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 
/*0010*/ 0x40, 0x0F, 0xC0, 0x6C, 0xFF, 0xFF, 0xFF, 0xFF, 0x40, 0x0F, 0xC0, 0x70, 0xFF, 0xFF, 0xFF, 0xFF, 
/*0020*/ 0x40, 0x0F, 0xC0, 0x74, 0xFF, 0xFF, 0xFF, 0xFF, 0x40, 0x0F, 0xC0, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 
/*0030*/ 0x40, 0x0F, 0xC0, 0x7C, 0xFF, 0xFF, 0xFF, 0xFF, 0x40, 0x0F, 0xC0, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 
/*0040*/ 0x40, 0x0D, 0x80, 0x30, 0x00, 0x00, 0x20, 0x01, 0x40, 0x0D, 0x81, 0x00, 0x00, 0x18, 0x00, 0x00, 
/*0050*/ 0x40, 0x0F, 0xC0, 0x14, 0x00, 0x01, 0x0D, 0x40, 0x40, 0x1F, 0x80, 0x14, 0x00, 0x00, 0x00, 0x00, 
/*0060*/ 0x40, 0x1F, 0x80, 0x18, 0x00, 0x00, 0x00, 0x00, 0x40, 0x1F, 0x80, 0x1C, 0x00, 0x00, 0x00, 0x00, 
/*0070*/ 0x40, 0x1F, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x40, 0x1F, 0x80, 0x24, 0x00, 0x00, 0x00, 0x00, 
/*0080*/ 0x40, 0x1F, 0x80, 0x28, 0x00, 0x00, 0x00, 0x00, 0x40, 0x1F, 0x80, 0x2C, 0x00, 0x00, 0x00, 0x00, 
/*0090*/ 0x40, 0x1F, 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0x40, 0x1F, 0x80, 0x34, 0x00, 0x00, 0x00, 0x00, 
/*00a0*/ 0x40, 0x1F, 0x80, 0x38, 0x00, 0x00, 0x00, 0x00, 0x40, 0x1F, 0x80, 0x3C, 0x00, 0x00, 0x00, 0x00, 
/*00b0*/ 0x40, 0x1F, 0x80, 0x40, 0x00, 0x00, 0x00, 0x00, 0x40, 0x1F, 0x80, 0x44, 0x00, 0x00, 0x00, 0x00, 
/*00c0*/ 0x40, 0x1F, 0x80, 0x48, 0x00, 0x00, 0x00, 0x00, 0x40, 0x1F, 0x80, 0x4C, 0x00, 0x00, 0x00, 0x00, 
/*00d0*/ 0x40, 0x1F, 0x80, 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x1F, 0x80, 0x54, 0x00, 0x00, 0x00, 0x00, 
/*00e0*/ 0x40, 0x1F, 0x80, 0x58, 0x00, 0x00, 0x00, 0x00, 0x40, 0x1F, 0x80, 0x5C, 0x00, 0x00, 0x00, 0x00, 
/*00f0*/ 0x40, 0x1F, 0x80, 0x60, 0x00, 0x00, 0x00, 0x00, 0x40, 0x1F, 0x80, 0x64, 0x00, 0x00, 0x00, 0x00, 
/*0100*/ 0x40, 0x1F, 0x80, 0x68, 0x00, 0x00, 0x00, 0x00, 0x40, 0x1F, 0x80, 0x6C, 0x00, 0x00, 0x00, 0x00, 
/*0110*/ 0x40, 0x1F, 0x80, 0x70, 0x00, 0x00, 0x00, 0x00, 0x40, 0x1F, 0x80, 0x74, 0x00, 0x00, 0x00, 0x00, 
/*0120*/ 0x40, 0x1F, 0x80, 0x78, 0x00, 0x00, 0x00, 0x00, 0x40, 0x1F, 0x80, 0x7C, 0x00, 0x00, 0x00, 0x00, 
/*0130*/ 0x40, 0x1F, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x40, 0x1F, 0x80, 0x84, 0x00, 0x00, 0x00, 0x00, 
/*0140*/ 0x40, 0x1F, 0x80, 0x88, 0x00, 0x00, 0x00, 0x00, 0x40, 0x1F, 0x80, 0x8C, 0x00, 0x00, 0x00, 0x00, 
/*0150*/ 0x40, 0x1F, 0x80, 0x90, 0x00, 0x00, 0x00, 0x00, 0x40, 0x1F, 0x80, 0x94, 0x00, 0x00, 0x00, 0x00, 
/*0160*/ 0x40, 0x1F, 0x80, 0x98, 0x00, 0x00, 0x00, 0x00, 0x40, 0x1F, 0x80, 0x9C, 0x00, 0x00, 0x00, 0x00, 
/*0170*/ 0x40, 0x1F, 0x80, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x1F, 0x80, 0xA4, 0x00, 0x00, 0x00, 0x00, 
/*0180*/ 0x40, 0x1F, 0x80, 0xA8, 0x00, 0x00, 0x00, 0x00, 0x40, 0x1F, 0x80, 0xAC, 0x00, 0x00, 0x00, 0x00, 
/*0190*/ 0x40, 0x1F, 0x80, 0xB0, 0x00, 0x00, 0x00, 0x10, 0x40, 0x1F, 0x80, 0xB4, 0x00, 0x00, 0x00, 0x00, 
/*01a0*/ 0x40, 0x1F, 0x80, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x40, 0x1F, 0x82, 0x04, 0x00, 0x01, 0x10, 0xF9, 
/*01b0*/ 0x40, 0x1F, 0x82, 0x08, 0x00, 0x01, 0x10, 0xF9, 0x40, 0x1F, 0x82, 0x0C, 0x00, 0x01, 0x10, 0xF9, 
/*01c0*/ 0x40, 0x1F, 0x82, 0x10, 0x00, 0x01, 0x10, 0xF9, 0x40, 0x1F, 0x82, 0x14, 0x00, 0x01, 0x10, 0xF9, 
/*01d0*/ 0x40, 0x1F, 0x82, 0x18, 0x00, 0x01, 0x10, 0xF9, 0x40, 0x1F, 0x82, 0x1C, 0x00, 0x01, 0x10, 0xF9, 
/*01e0*/ 0x40, 0x1F, 0x82, 0x20, 0x00, 0x01, 0x10, 0xF9, 0x40, 0x1F, 0x82, 0x24, 0x00, 0x01, 0x10, 0xF9, 
/*01f0*/ 0x40, 0x1F, 0x82, 0x28, 0x00, 0x01, 0x10, 0xF9, 0x40, 0x1F, 0x82, 0x2C, 0x00, 0x01, 0x10, 0xF9, 
/*0200*/ 0x40, 0x1F, 0x82, 0x30, 0x00, 0x01, 0x10, 0xF9, 0x40, 0x1F, 0x82, 0x34, 0x00, 0x01, 0x10, 0xF9, 
/*0210*/ 0x40, 0x1F, 0x82, 0x38, 0x00, 0x01, 0x10, 0xF9, 0x40, 0x1F, 0x82, 0x3C, 0x00, 0x01, 0x10, 0xF9, 
/*0220*/ 0x40, 0x1F, 0x82, 0x40, 0x00, 0x01, 0x10, 0xF9, 0x40, 0x1F, 0x82, 0x44, 0x00, 0x01, 0x10, 0xF9, 
/*0230*/ 0x40, 0x1F, 0x82, 0x48, 0x00, 0x01, 0x10, 0xF9, 0x40, 0x1F, 0x82, 0x4C, 0x00, 0x01, 0x10, 0xF9, 
/*0240*/ 0x40, 0x1F, 0x82, 0x50, 0x00, 0x01, 0x10, 0xF9, 0x40, 0x1F, 0x82, 0x54, 0x00, 0x01, 0x10, 0xF9, 
/*0250*/ 0x40, 0x1F, 0x82, 0x58, 0x00, 0x01, 0x10, 0xF9, 0x40, 0x1F, 0x82, 0x5C, 0x00, 0x01, 0x10, 0xF9, 
/*0260*/ 0x40, 0x1F, 0x82, 0x60, 0x00, 0x01, 0x10, 0xF9, 0x40, 0x1F, 0x82, 0x64, 0x00, 0x01, 0x10, 0xF9, 
/*0270*/ 0x40, 0x1F, 0x82, 0x68, 0x00, 0x01, 0x10, 0xF9, 0x40, 0x1F, 0x82, 0x6C, 0x00, 0x01, 0x10, 0xF9, 
/*0280*/ 0x40, 0x1F, 0x82, 0x70, 0x00, 0x01, 0x10, 0xF9, 0x40, 0x1F, 0x82, 0x74, 0x00, 0x01, 0x10, 0xF9, 
/*0290*/ 0x40, 0x1F, 0x82, 0x78, 0x00, 0x01, 0x10, 0xF9, 0x40, 0x1F, 0x82, 0x7C, 0x00, 0x01, 0x10, 0xF9, 
/*02a0*/ 0x40, 0x1F, 0x82, 0x80, 0x00, 0x01, 0x10, 0xF9, 0x40, 0x1F, 0x82, 0x84, 0x00, 0x01, 0x10, 0xF9, 
/*02b0*/ 0x40, 0x1F, 0x82, 0x88, 0x00, 0x01, 0x10, 0xF9, 0x40, 0x1F, 0x82, 0x8C, 0x00, 0x01, 0x10, 0xF9, 
/*02c0*/ 0x40, 0x1F, 0x82, 0x90, 0x00, 0x01, 0x10, 0xF9, 0x40, 0x1F, 0x82, 0x94, 0x00, 0x01, 0x10, 0xF9, 
/*02d0*/ 0x40, 0x1F, 0x82, 0x98, 0x00, 0x01, 0x10, 0xF9, 0x40, 0x1F, 0x82, 0x9C, 0x00, 0x01, 0x10, 0xF9, 
/*02e0*/ 0x40, 0x1F, 0x82, 0xA0, 0x00, 0x01, 0x10, 0xF9, 0x40, 0x1F, 0x82, 0xA4, 0x00, 0x01, 0x10, 0xF9, 
/*02f0*/ 0x40, 0x1F, 0x82, 0xA8, 0x00, 0x01, 0x10, 0xF9, 0x40, 0x2F, 0x00, 0x00, 0x10, 0x00, 0x00, 0x04, 
/*0300*/ 0x40, 0x2F, 0x00, 0x08, 0x00, 0x03, 0x05, 0x24, 0x40, 0x2F, 0x00, 0x0C, 0x06, 0x03, 0x05, 0x24, 
/*0310*/ 0x40, 0x2F, 0x00, 0x10, 0x80, 0x00, 0x00, 0x1B, 0x40, 0x2F, 0x00, 0x14, 0x82, 0x00, 0x00, 0x1B, 
/*0320*/ 0x40, 0x2F, 0x00, 0x18, 0x84, 0x00, 0x00, 0x1B, 0x40, 0x2F, 0x00, 0x1C, 0x86, 0x00, 0x00, 0x1B, 
/*0330*/ 0x40, 0x2F, 0x00, 0x20, 0x90, 0x00, 0x00, 0x21, 0x40, 0x2F, 0x00, 0x24, 0xA0, 0x00, 0x00, 0x19, 
/*0340*/ 0x40, 0x2F, 0x00, 0x28, 0xA8, 0x00, 0x00, 0x17, 0x40, 0x2F, 0x00, 0x2C, 0xA9, 0x00, 0x00, 0x1B, 
/*0350*/ 0x40, 0x2F, 0x00, 0x30, 0x00, 0x00, 0x00, 0x21, 0x40, 0x2F, 0x00, 0x04, 0x00, 0x00, 0x79, 0xA8, 
/*0360*/ 0x40, 0x2F, 0x00, 0x40, 0x00, 0x00, 0x0F, 0x31, 0x40, 0x2F, 0x00, 0x44, 0x00, 0x65, 0x29, 0x22, 
/*0370*/ 0x40, 0x2F, 0x00, 0x48, 0x00, 0x01, 0x09, 0x20, 0x40, 0x2F, 0x00, 0x4C, 0x50, 0x21, 0x0A, 0x08, 
/*0380*/ 0x40, 0x2F, 0x00, 0x80, 0x00, 0x00, 0x00, 0x21, 0x40, 0x2F, 0x00, 0x84, 0x00, 0x88, 0x88, 0x88, 
/*0390*/ 0x40, 0x2F, 0x00, 0x94, 0x00, 0x00, 0x00, 0x02, 0x40, 0x2F, 0x00, 0x98, 0x00, 0x00, 0x00, 0x00, 
/*03a0*/ 0x40, 0x2F, 0x00, 0x90, 0x80, 0x00, 0x00, 0x00, 0x40, 0x2F, 0x00, 0x9C, 0xA5, 0x5A, 0x00, 0x0F, 
/*03b0*/ 0xCF, 0x00, 0x0C, 0x1C, 0x40, 0x2F, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x01, 0xCC, 0x00, 0x14, 0x04, 
/*03c0*/ 0x40, 0x2F, 0x00, 0x90, 0x80, 0x00, 0x00, 0x00, 0x40, 0x2F, 0x00, 0x9C, 0xA5, 0x5A, 0x00, 0x0C, 
/*03d0*/ 0xCF, 0x00, 0x0C, 0x1C, 0x40, 0x2F, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x01, 0xCC, 0x00, 0x14, 0x04, 
/*03e0*/ 0x40, 0x2F, 0x00, 0x90, 0x80, 0x00, 0x00, 0x00, 0x40, 0x2F, 0x00, 0x9C, 0xA5, 0x5A, 0x00, 0x0C, 
/*03f0*/ 0xCF, 0x00, 0x0C, 0x1C, 0x40, 0x2F, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x01, 0xCC, 0x00, 0x1C, 0x04, 
/*0400*/ 0x40, 0x2F, 0x00, 0xA0, 0x00, 0x00, 0x00, 0x33, 0x40, 0x2F, 0x00, 0x90, 0x80, 0x00, 0x00, 0x00, 
/*0410*/ 0x40, 0x2F, 0x00, 0x9C, 0xA5, 0x5A, 0x00, 0x0A, 0xCF, 0x00, 0x0C, 0x1C, 0x40, 0x2F, 0x00, 0x3C, 
/*0420*/ 0x00, 0x00, 0x00, 0x01, 0xCC, 0x00, 0x0C, 0x04, 0x40, 0x2F, 0x00, 0x4C, 0x50, 0x21, 0x0A, 0x09, 
};

三、验证

验证原理,声音输出到声卡,声卡输出到MCU板子,MCU板子输出声音连回声卡,声卡把声音输出到电脑。通过MATLAB把脉冲响应数据计算出来。
1、声卡模块本身参数
如下所示,声音通过声卡后对低频和高频具有衰减
在这里插入图片描述

2、抓取MCU混响的脉冲响应数据
在这里插入图片描述
3、MATLAB对比原本脉冲响应数据和MCU混响脉冲响应
原本的ROOM3的脉冲响应数据
在这里插入图片描述

MCU的脉冲响应数据
在这里插入图片描述

4、音频对比
MCU_ROOM3_ir_conv1-reverb.wav 为MCU脉冲响应卷积后音频
PC_ROOM3_ir_conv1-reverb.wav 为原本脉冲响应卷积后音频
TEST MONO GUITAR 48kHZ 24bits 4S.wav 为原音频
https://github.com/BrotherSix/MATLAB_REVERB_AUDIO_WAV

四、总结

1、单声道算法执行周期为25ms,立体声算法执行周期为50ms。在立体声情况下,混响表现为Pre Delay最低为50ms,所以在使用空间比较大的混响时候,需要手动把脉冲响应数据往前50ms。

2、在RT1052平台上,较为完美地实现了混响卷积,而且实时性较为强,仅需要50ms延时。

欢迎技术交流QQ 736009573

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值