1、STWINKT1B上有一个模拟MEMS麦克风(IMP23ABSU)和一个数字麦克风(IMP34DT05),我们可以通过语音控制STWINKT1B
实现一些操作。下面的演示是使用麦克风进行声音录制。
2、模拟IMP23ABSU配合运放TS922EUT将采集的信号通过2路ADC传输给单片机。
数字麦克风使用DFSDM模块对PDM信号进行处理。
下面使用ST提供的扩展库进行录音测试。首先通过把片上USB模拟成一个USB麦克风,把STWINKT1B上的模拟麦克风和数字麦克风采集音频信号通过USB传输给电脑,这样在电脑可以使用录音软件进行录音.
使能2个麦克风
#define ONBOARD_ANALOG_MIC 1
#define ONBOARD_DIGITAL_MIC 1
/* Select the sampling frequencies for the microphones
If the digital microphone is enabled then the max frequency is 48000Hz,
otherwise is 192000Hz. */
#define AUDIO_IN_SAMPLING_FREQUENCY 48000
#define AUDIO_IN_CHANNELS (ONBOARD_ANALOG_MIC+ONBOARD_DIGITAL_MIC)
初始化2个麦克风,DFSDM和ADC1
复制__weak int32_t BSP_AUDIO_IN_Init(uint32_t Instance, BSP_AUDIO_Init_t *AudioInit) { if (Instance >= AUDIO_IN_INSTANCES_NBR) { return BSP_ERROR_WRONG_PARAM; } else { /* Store the audio record context */ AudioInCtx[Instance].Device = AudioInit->Device; AudioInCtx[Instance].ChannelsNbr = AudioInit->ChannelsNbr; AudioInCtx[Instance].SampleRate = AudioInit->SampleRate; AudioInCtx[Instance].BitsPerSample = AudioInit->BitsPerSample; AudioInCtx[Instance].Volume = AudioInit->Volume; AudioInCtx[Instance].State = AUDIO_IN_STATE_RESET; if (Instance == 0U) { return BSP_ERROR_WRONG_PARAM; } else { if ((AudioInCtx[Instance].Device & ONBOARD_DIGITAL_MIC_MASK) != 0U) { MX_DFSDM_Config dfsdm_config; DMic_OnBoard_DfsdmChannel.Instance = DMIC_ONBOARD_CHANNEL; DMic_OnBoard_DfsdmFilter.Instance = DMIC_ONBOARD_FILTER; DFSDM_FilterMspInit(&DMic_OnBoard_DfsdmFilter); DFSDM_ChannelMspInit(&DMic_OnBoard_DfsdmChannel); dfsdm_config.FilterInstance = DMIC_ONBOARD_FILTER; dfsdm_config.ChannelInstance = DMIC_ONBOARD_CHANNEL; dfsdm_config.DigitalMicPins = DFSDM_CHANNEL_SAME_CHANNEL_PINS; dfsdm_config.DigitalMicType = DFSDM_CHANNEL_SPI_FALLING; dfsdm_config.Channel4Filter = DFSDM_CHANNEL_5; dfsdm_config.RegularTrigger = DFSDM_FILTER_SW_TRIGGER; dfsdm_config.DmaMode = DISABLE; dfsdm_config.Activation = ENABLE; dfsdm_config.Multiplexer = DFSDM_CHANNEL_EXTERNAL_INPUTS; dfsdm_config.SincOrder = DFSDM_FILTER_ORDER(AudioInCtx[Instance].SampleRate); dfsdm_config.Oversampling = DFSDM_OVER_SAMPLING(AudioInCtx[Instance].SampleRate); dfsdm_config.ClockDivider = DFSDM_CLOCK_DIVIDER(AudioInCtx[Instance].SampleRate); dfsdm_config.RightBitShift = DFSDM_MIC_BIT_SHIFT(AudioInCtx[Instance].SampleRate); /* Default configuration of DFSDM filters and channels */ if (MX_DFSDM_Init(&DMic_OnBoard_DfsdmFilter, &DMic_OnBoard_DfsdmChannel, &dfsdm_config) != HAL_OK) { /* Return BSP_ERROR_PERIPH_FAILURE when operations are not correctly done */ return BSP_ERROR_PERIPH_FAILURE; } } if ((AudioInCtx[Instance].Device & ONBOARD_ANALOG_MIC_MASK) != 0U) { MX_DFSDM_Config dfsdm_config; dfsdm_config.FilterInstance = AMIC_ONBOARD_FILTER; dfsdm_config.ChannelInstance = AMIC_ONBOARD_CHANNEL; dfsdm_config.DigitalMicPins = DFSDM_CHANNEL_SAME_CHANNEL_PINS; /*NU*/ dfsdm_config.DigitalMicType = DFSDM_CHANNEL_SPI_FALLING;/*NU*/ dfsdm_config.Channel4Filter = DFSDM_CHANNEL_0; if (AudioInCtx[Instance].ChannelsNbr == 1U) { dfsdm_config.RegularTrigger = DFSDM_FILTER_SW_TRIGGER; } else { dfsdm_config.RegularTrigger = DFSDM_FILTER_SYNC_TRIGGER; } dfsdm_config.DmaMode = DISABLE; dfsdm_config.Activation = DISABLE; dfsdm_config.Multiplexer = DFSDM_CHANNEL_ADC_OUTPUT; dfsdm_config.SincOrder = SINC_ORDER; dfsdm_config.Oversampling = DECIMATION_RATIO_DFSDM; dfsdm_config.ClockDivider = 1;/*NU*/ dfsdm_config.RightBitShift = RBITSHIFT; /* Default configuration of DFSDM filters and channels */ if (MX_DFSDM_Init(&AMic_OnBoard_DfsdmFilter, &AMic_OnBoard_DfsdmChannel, &dfsdm_config) != HAL_OK) { /* Return BSP_ERROR_PERIPH_FAILURE when operations are not correctly done */ return BSP_ERROR_PERIPH_FAILURE; } /*adc init*/ MX_ADC1_Init(); } } } /* Update BSP AUDIO IN state */ AudioInCtx[Instance].State = AUDIO_IN_STATE_STOP; /* Return BSP status */ return BSP_ERROR_NONE;
启动声音采集
nt32_t BSP_AUDIO_IN_Record(uint32_t Instance, uint8_t *pBuf, uint32_t NbrOfBytes)
{
int32_t ret = BSP_ERROR_NONE;
AudioInCtx[Instance].pBuff = (uint16_t *)pBuf;
if (Instance >= AUDIO_IN_INSTANCES_NBR)
{
return BSP_ERROR_WRONG_PARAM;
}
else if (Instance == 0U)
{
return BSP_ERROR_WRONG_PARAM;
}
else
{
if ((AudioInCtx[Instance].Device & ONBOARD_ANALOG_MIC_MASK) != 0U)
{
if (HAL_ADC_Start(&ADC1_Handle) != HAL_OK)
{
ret = BSP_ERROR_PERIPH_FAILURE;
}
(void)HAL_DFSDM_FilterRegularStart_DMA(&AMic_OnBoard_DfsdmFilter, DFSDM_OUT, NbrOfBytes);
}
if ((AudioInCtx[Instance].Device & ONBOARD_DIGITAL_MIC_MASK) != 0U)
{
if (HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&DMic_OnBoard_DfsdmFilter,
(int32_t *) RecBuff,
NbrOfBytes))
{
ret = BSP_ERROR_PERIPH_FAILURE;
}
}
}
/* Update BSP AUDIO IN state */
AudioInCtx[Instance].State = AUDIO_IN_STATE_RECORDING;
return ret;
}
在中断里面调用函数将数据发送给USB
void HAL_DFSDM_FilterRegConvCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
{
UNUSED(hdfsdm_filter);
uint32_t j;
if (AudioInCtx[1].IsMultiBuff == 1U)
{
/* Call the record update function to get the second half */
BSP_AUDIO_IN_TransferComplete_CallBack(1);
}
else
{
if ((AudioInCtx[1].Device & ONBOARD_DIGITAL_MIC_MASK) != 0U)
{
for (j = 0U; j < ((AudioInCtx[1].SampleRate / 1000U) * N_MS_PER_INTERRUPT); j++)
{
/*DMIC_ONBOARD_CHANNEL*/
AudioInCtx[1].HP_Filters[0].Z = ((RecBuff[j + ((AudioInCtx[1].SampleRate / 1000U) * N_MS_PER_INTERRUPT)] / 256) * (int32_t)(AudioInCtx[1].Volume)) / 128;
AudioInCtx[1].HP_Filters[0].oldOut = (0xFC * (AudioInCtx[1].HP_Filters[0].oldOut + AudioInCtx[1].HP_Filters[0].Z - AudioInCtx[1].HP_Filters[0].oldIn)) / 256;
AudioInCtx[1].HP_Filters[0].oldIn = AudioInCtx[1].HP_Filters[0].Z;
AudioInCtx[1].pBuff[AudioInCtx[1].ChannelsNbr * j] = (uint16_t) SaturaLH(AudioInCtx[1].HP_Filters[0].oldOut, -32760, 32760);
/*AMIC_ONBOARD_CHANNEL*/
AudioInCtx[1].HP_Filters[1].Z = ((DFSDM_OUT[j + ((AudioInCtx[1].SampleRate / 1000U) * N_MS_PER_INTERRUPT)] / 256) * (int32_t)(AudioInCtx[1].Volume)) / 512;
AudioInCtx[1].HP_Filters[1].oldOut = (0xFC * (AudioInCtx[1].HP_Filters[1].oldOut + AudioInCtx[1].HP_Filters[1].Z - AudioInCtx[1].HP_Filters[1].oldIn)) / 256;
AudioInCtx[1].HP_Filters[1].oldIn = AudioInCtx[1].HP_Filters[1].Z;
AudioInCtx[1].pBuff[(AudioInCtx[1].ChannelsNbr * j) + 1U] = (uint16_t) SaturaLH(AudioInCtx[1].HP_Filters[1].oldOut, -32760, 32760);
}
}
if (AudioInCtx[1].Device == ONBOARD_ANALOG_MIC_MASK)
{
for (j = 0U; j < ((AudioInCtx[1].SampleRate / 1000U) * N_MS_PER_INTERRUPT); j++)
{
AudioInCtx[1].HP_Filters[1].Z = ((DFSDM_OUT[j + ((AudioInCtx[1].SampleRate / 1000U) * N_MS_PER_INTERRUPT)] / 256) * (int32_t)(AudioInCtx[1].Volume)) / 512;
AudioInCtx[1].HP_Filters[1].oldOut = (0xFC * (AudioInCtx[1].HP_Filters[1].oldOut + AudioInCtx[1].HP_Filters[1].Z - AudioInCtx[1].HP_Filters[1].oldIn)) / 256;
AudioInCtx[1].HP_Filters[1].oldIn = AudioInCtx[1].HP_Filters[1].Z;
AudioInCtx[1].pBuff[AudioInCtx[1].ChannelsNbr * j] = (uint16_t) SaturaLH(AudioInCtx[1].HP_Filters[1].oldOut, -32760, 32760);
}
}
BSP_AUDIO_IN_TransferComplete_CallBack(1);
}
}
/**
* [url=home.php?mod=space&uid=247401]@brief[/url] Half regular conversion complete callback.
* @param hdfsdm_filter DFSDM filter handle.
* @retval None
*/
void HAL_DFSDM_FilterRegConvHalfCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
{
UNUSED(hdfsdm_filter);
uint32_t j;
if (AudioInCtx[1].IsMultiBuff == 1U)
{
/* Call the record update function to get the second half */
BSP_AUDIO_IN_HalfTransfer_CallBack(1);
}
else
{
if ((AudioInCtx[1].Device & ONBOARD_DIGITAL_MIC_MASK) != 0U)
{
for (j = 0U; j < ((AudioInCtx[1].SampleRate / 1000U)* N_MS_PER_INTERRUPT); j++)
{
/*DMIC_ONBOARD_CHANNEL*/
AudioInCtx[1].HP_Filters[0].Z = ((RecBuff[j] / 256) * (int32_t)(AudioInCtx[1].Volume)) / 128;
AudioInCtx[1].HP_Filters[0].oldOut = (0xFC * (AudioInCtx[1].HP_Filters[0].oldOut + AudioInCtx[1].HP_Filters[0].Z - AudioInCtx[1].HP_Filters[0].oldIn)) / 256;
AudioInCtx[1].HP_Filters[0].oldIn = AudioInCtx[1].HP_Filters[0].Z;
AudioInCtx[1].pBuff[AudioInCtx[1].ChannelsNbr * (j)] = (uint16_t) SaturaLH(AudioInCtx[1].HP_Filters[0].oldOut, -32760, 32760);
/*AMIC_ONBOARD_CHANNEL*/
AudioInCtx[1].HP_Filters[1].Z = ((DFSDM_OUT[j] / 256) * (int32_t)(AudioInCtx[1].Volume)) / 512;
AudioInCtx[1].HP_Filters[1].oldOut = (0xFC * (AudioInCtx[1].HP_Filters[1].oldOut + AudioInCtx[1].HP_Filters[1].Z - AudioInCtx[1].HP_Filters[1].oldIn)) / 256;
AudioInCtx[1].HP_Filters[1].oldIn = AudioInCtx[1].HP_Filters[1].Z;
AudioInCtx[1].pBuff[(AudioInCtx[1].ChannelsNbr * j) + 1U] = (uint16_t) SaturaLH(AudioInCtx[1].HP_Filters[1].oldOut, -32760, 32760);
}
}
if (AudioInCtx[1].Device == ONBOARD_ANALOG_MIC_MASK)
{
for (j = 0U; j < ((AudioInCtx[1].SampleRate / 1000U)* N_MS_PER_INTERRUPT); j++)
{
AudioInCtx[1].HP_Filters[1].Z = ((DFSDM_OUT[j] / 256) * (int32_t)(AudioInCtx[1].Volume)) / 512;
AudioInCtx[1].HP_Filters[1].oldOut = (0xFC * (AudioInCtx[1].HP_Filters[1].oldOut + AudioInCtx[1].HP_Filters[1].Z - AudioInCtx[1].HP_Filters[1].oldIn)) / 256;
AudioInCtx[1].HP_Filters[1].oldIn = AudioInCtx[1].HP_Filters[1].Z;
AudioInCtx[1].pBuff[AudioInCtx[1].ChannelsNbr * j] = (uint16_t) SaturaLH(AudioInCtx[1].HP_Filters[1].oldOut, -32760, 32760);
}
}
BSP_AUDIO_IN_HalfTransfer_CallBack(1);
}
}
发送数据到PC
void BSP_AUDIO_IN_HalfTransfer_CallBack(uint32_t Instance)
{
UNUSED(Instance);
AudioProcess();
BSP_LED_Off(LED1);
}
void AudioProcess(void)
{
Send_Audio_to_USB((int16_t *)PCM_Buffer, (AUDIO_IN_SAMPLING_FREQUENCY / 1000)*AUDIO_IN_CHANNELS * N_MS_PER_INTERRUPT);
}
枚举出来的麦克风
录音软件使用免费的 ocenaudio
选择 麦克风 (STM32 AUDIO Streaming in FS Mode)
开始录音
我感觉录制的效果还是挺好的。
录制的音频文件因为太大没法上传,所以分包了。
STWINTK1B_REC.part1.rar (10 MB)
STWINTK1B_REC.part2.rar (10 MB)
STWINTK1B_REC.part3.rar (1.04 MB)。
---------------------
作者:OldestTrick
链接:https://bbs.21ic.com/icview-3396078-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。