本帖最后由 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)
STWINTK1B_REC.part2.rar
(10 MB)
STWINTK1B_REC.part3.rar
(1.04 MB)
|