本帖最后由 OldestTrick 于 2024-8-14 21:47 编辑
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, 下载次数: 2)
STWINTK1B_REC.part2.rar
(10 MB, 下载次数: 1)
STWINTK1B_REC.part3.rar
(1.04 MB, 下载次数: 1)
|
|