[STM32L4+] 【STEVAL-STWINKT1B测评】使用麦克风进行声音录制

[复制链接]
3136|4
 楼主| OldestTrick 发表于 2024-8-14 21:47 | 显示全部楼层 |阅读模式
本帖最后由 OldestTrick 于 2024-8-14 21:47 编辑


1、STWINKT1B上有一个模拟MEMS麦克风(IMP23ABSU)和一个数字麦克风(IMP34DT05),我们可以通过语音控制STWINKT1B
实现一些操作。下面的演示是使用麦克风进行声音录制。
2、模拟IMP23ABSU配合运放TS922EUT将采集的信号通过2路ADC传输给单片机。

7507166bcb29263867.png

数字麦克风使用DFSDM模块对PDM信号进行处理。

2311066bcb2a058f65.png

下面使用ST提供的扩展库进行录音测试。首先通过把片上USB模拟成一个USB麦克风,把STWINKT1B上的模拟麦克风和数字麦克风采集音频信号通过USB传输给电脑,这样在电脑可以使用录音软件进行录音.
使能2个麦克风
  1. #define ONBOARD_ANALOG_MIC          1
  2. #define ONBOARD_DIGITAL_MIC         1

  3. /* Select the sampling frequencies for the microphones
  4.    If the digital microphone is enabled then the max frequency is 48000Hz,
  5.    otherwise is 192000Hz.  */
  6. #define AUDIO_IN_SAMPLING_FREQUENCY 48000


  7. #define AUDIO_IN_CHANNELS     (ONBOARD_ANALOG_MIC+ONBOARD_DIGITAL_MIC)
初始化2个麦克风,DFSDM和ADC1

  1. __weak int32_t BSP_AUDIO_IN_Init(uint32_t Instance, BSP_AUDIO_Init_t *AudioInit)
  2. {
  3.   if (Instance >= AUDIO_IN_INSTANCES_NBR)
  4.   {
  5.     return BSP_ERROR_WRONG_PARAM;
  6.   }
  7.   else
  8.   {
  9.     /* Store the audio record context */
  10.     AudioInCtx[Instance].Device          = AudioInit->Device;
  11.     AudioInCtx[Instance].ChannelsNbr     = AudioInit->ChannelsNbr;
  12.     AudioInCtx[Instance].SampleRate      = AudioInit->SampleRate;
  13.     AudioInCtx[Instance].BitsPerSample   = AudioInit->BitsPerSample;
  14.     AudioInCtx[Instance].Volume          = AudioInit->Volume;
  15.     AudioInCtx[Instance].State           = AUDIO_IN_STATE_RESET;

  16.     if (Instance == 0U)
  17.     {
  18.       return BSP_ERROR_WRONG_PARAM;
  19.     }
  20.     else
  21.     {
  22.       if ((AudioInCtx[Instance].Device & ONBOARD_DIGITAL_MIC_MASK) != 0U)
  23.       {
  24.         MX_DFSDM_Config dfsdm_config;

  25.         DMic_OnBoard_DfsdmChannel.Instance = DMIC_ONBOARD_CHANNEL;
  26.         DMic_OnBoard_DfsdmFilter.Instance  = DMIC_ONBOARD_FILTER;

  27.         DFSDM_FilterMspInit(&DMic_OnBoard_DfsdmFilter);
  28.         DFSDM_ChannelMspInit(&DMic_OnBoard_DfsdmChannel);

  29.         dfsdm_config.FilterInstance  = DMIC_ONBOARD_FILTER;
  30.         dfsdm_config.ChannelInstance = DMIC_ONBOARD_CHANNEL;
  31.         dfsdm_config.DigitalMicPins  = DFSDM_CHANNEL_SAME_CHANNEL_PINS;
  32.         dfsdm_config.DigitalMicType  = DFSDM_CHANNEL_SPI_FALLING;
  33.         dfsdm_config.Channel4Filter  = DFSDM_CHANNEL_5;
  34.         dfsdm_config.RegularTrigger  = DFSDM_FILTER_SW_TRIGGER;
  35.         dfsdm_config.DmaMode         = DISABLE;
  36.         dfsdm_config.Activation      = ENABLE;
  37.         dfsdm_config.Multiplexer     = DFSDM_CHANNEL_EXTERNAL_INPUTS;
  38.         dfsdm_config.SincOrder       = DFSDM_FILTER_ORDER(AudioInCtx[Instance].SampleRate);
  39.         dfsdm_config.Oversampling    = DFSDM_OVER_SAMPLING(AudioInCtx[Instance].SampleRate);
  40.         dfsdm_config.ClockDivider    = DFSDM_CLOCK_DIVIDER(AudioInCtx[Instance].SampleRate);
  41.         dfsdm_config.RightBitShift   = DFSDM_MIC_BIT_SHIFT(AudioInCtx[Instance].SampleRate);

  42.         /* Default configuration of DFSDM filters and channels */
  43.         if (MX_DFSDM_Init(&DMic_OnBoard_DfsdmFilter, &DMic_OnBoard_DfsdmChannel, &dfsdm_config) != HAL_OK)
  44.         {
  45.           /* Return BSP_ERROR_PERIPH_FAILURE when operations are not correctly done */
  46.           return BSP_ERROR_PERIPH_FAILURE;
  47.         }

  48.       }
  49.       if ((AudioInCtx[Instance].Device & ONBOARD_ANALOG_MIC_MASK) != 0U)
  50.       {
  51.         MX_DFSDM_Config dfsdm_config;

  52.         dfsdm_config.FilterInstance  = AMIC_ONBOARD_FILTER;
  53.         dfsdm_config.ChannelInstance = AMIC_ONBOARD_CHANNEL;
  54.         dfsdm_config.DigitalMicPins  = DFSDM_CHANNEL_SAME_CHANNEL_PINS; /*NU*/
  55.         dfsdm_config.DigitalMicType  = DFSDM_CHANNEL_SPI_FALLING;/*NU*/
  56.         dfsdm_config.Channel4Filter  = DFSDM_CHANNEL_0;
  57.         if (AudioInCtx[Instance].ChannelsNbr == 1U)
  58.         {
  59.           dfsdm_config.RegularTrigger = DFSDM_FILTER_SW_TRIGGER;
  60.         }
  61.         else
  62.         {
  63.           dfsdm_config.RegularTrigger = DFSDM_FILTER_SYNC_TRIGGER;
  64.         }
  65.         dfsdm_config.DmaMode       = DISABLE;
  66.         dfsdm_config.Activation      = DISABLE;
  67.         dfsdm_config.Multiplexer     = DFSDM_CHANNEL_ADC_OUTPUT;
  68.         dfsdm_config.SincOrder       = SINC_ORDER;
  69.         dfsdm_config.Oversampling    = DECIMATION_RATIO_DFSDM;
  70.         dfsdm_config.ClockDivider    = 1;/*NU*/
  71.         dfsdm_config.RightBitShift   = RBITSHIFT;

  72.         /* Default configuration of DFSDM filters and channels */
  73.         if (MX_DFSDM_Init(&AMic_OnBoard_DfsdmFilter, &AMic_OnBoard_DfsdmChannel, &dfsdm_config) != HAL_OK)
  74.         {
  75.           /* Return BSP_ERROR_PERIPH_FAILURE when operations are not correctly done */
  76.           return BSP_ERROR_PERIPH_FAILURE;
  77.         }

  78.         /*adc init*/
  79.         MX_ADC1_Init();

  80.       }
  81.     }
  82. }
  83.   /* Update BSP AUDIO IN state */
  84.   AudioInCtx[Instance].State = AUDIO_IN_STATE_STOP;
  85.   /* Return BSP status */
  86.   return BSP_ERROR_NONE;

启动声音采集
  1. nt32_t BSP_AUDIO_IN_Record(uint32_t Instance, uint8_t *pBuf, uint32_t NbrOfBytes)
  2. {
  3.   int32_t ret = BSP_ERROR_NONE;
  4.   AudioInCtx[Instance].pBuff = (uint16_t *)pBuf;

  5.   if (Instance >= AUDIO_IN_INSTANCES_NBR)
  6.   {
  7.     return BSP_ERROR_WRONG_PARAM;
  8.   }
  9.   else if (Instance == 0U)
  10.   {
  11.     return BSP_ERROR_WRONG_PARAM;
  12.   }
  13.   else
  14.   {
  15.     if ((AudioInCtx[Instance].Device & ONBOARD_ANALOG_MIC_MASK) != 0U)
  16.     {
  17.       if (HAL_ADC_Start(&ADC1_Handle) != HAL_OK)
  18.       {
  19.         ret =  BSP_ERROR_PERIPH_FAILURE;
  20.       }
  21.       (void)HAL_DFSDM_FilterRegularStart_DMA(&AMic_OnBoard_DfsdmFilter, DFSDM_OUT, NbrOfBytes);
  22.     }

  23.     if ((AudioInCtx[Instance].Device & ONBOARD_DIGITAL_MIC_MASK) != 0U)
  24.     {
  25.       if (HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&DMic_OnBoard_DfsdmFilter,
  26.                                                      (int32_t *) RecBuff,
  27.                                                      NbrOfBytes))
  28.       {
  29.         ret =  BSP_ERROR_PERIPH_FAILURE;
  30.       }
  31.     }
  32.   }

  33.   /* Update BSP AUDIO IN state */
  34.   AudioInCtx[Instance].State = AUDIO_IN_STATE_RECORDING;
  35.   return ret;
  36. }
在中断里面调用函数将数据发送给USB
  1. void HAL_DFSDM_FilterRegConvCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
  2. {
  3.   UNUSED(hdfsdm_filter);
  4.   uint32_t j;

  5.   if (AudioInCtx[1].IsMultiBuff == 1U)
  6.   {
  7.     /* Call the record update function to get the second half */
  8.     BSP_AUDIO_IN_TransferComplete_CallBack(1);
  9.   }
  10.   else
  11.   {
  12.     if ((AudioInCtx[1].Device & ONBOARD_DIGITAL_MIC_MASK) != 0U)
  13.     {
  14.       for (j = 0U; j < ((AudioInCtx[1].SampleRate / 1000U) * N_MS_PER_INTERRUPT); j++)
  15.       {
  16.         /*DMIC_ONBOARD_CHANNEL*/
  17.         AudioInCtx[1].HP_Filters[0].Z = ((RecBuff[j + ((AudioInCtx[1].SampleRate / 1000U) * N_MS_PER_INTERRUPT)] / 256) * (int32_t)(AudioInCtx[1].Volume)) / 128;
  18.         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;
  19.         AudioInCtx[1].HP_Filters[0].oldIn = AudioInCtx[1].HP_Filters[0].Z;
  20.         AudioInCtx[1].pBuff[AudioInCtx[1].ChannelsNbr * j] = (uint16_t) SaturaLH(AudioInCtx[1].HP_Filters[0].oldOut, -32760, 32760);
  21.         /*AMIC_ONBOARD_CHANNEL*/
  22.         AudioInCtx[1].HP_Filters[1].Z = ((DFSDM_OUT[j + ((AudioInCtx[1].SampleRate / 1000U) * N_MS_PER_INTERRUPT)] / 256) * (int32_t)(AudioInCtx[1].Volume)) / 512;
  23.         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;
  24.         AudioInCtx[1].HP_Filters[1].oldIn = AudioInCtx[1].HP_Filters[1].Z;
  25.         AudioInCtx[1].pBuff[(AudioInCtx[1].ChannelsNbr * j) + 1U] = (uint16_t) SaturaLH(AudioInCtx[1].HP_Filters[1].oldOut, -32760, 32760);
  26.       }
  27.     }
  28.     if (AudioInCtx[1].Device == ONBOARD_ANALOG_MIC_MASK)
  29.     {
  30.       for (j = 0U; j < ((AudioInCtx[1].SampleRate / 1000U) * N_MS_PER_INTERRUPT); j++)
  31.       {
  32.         AudioInCtx[1].HP_Filters[1].Z = ((DFSDM_OUT[j + ((AudioInCtx[1].SampleRate / 1000U) * N_MS_PER_INTERRUPT)] / 256) * (int32_t)(AudioInCtx[1].Volume)) / 512;
  33.         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;
  34.         AudioInCtx[1].HP_Filters[1].oldIn = AudioInCtx[1].HP_Filters[1].Z;
  35.         AudioInCtx[1].pBuff[AudioInCtx[1].ChannelsNbr * j] = (uint16_t) SaturaLH(AudioInCtx[1].HP_Filters[1].oldOut, -32760, 32760);
  36.       }
  37.     }
  38.     BSP_AUDIO_IN_TransferComplete_CallBack(1);
  39.   }
  40. }

  41. /**
  42.   * [url=home.php?mod=space&uid=247401]@brief[/url]  Half regular conversion complete callback.
  43.   * @param  hdfsdm_filter   DFSDM filter handle.
  44.   * @retval None
  45.   */
  46. void HAL_DFSDM_FilterRegConvHalfCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
  47. {
  48.   UNUSED(hdfsdm_filter);
  49.   uint32_t j;

  50.   if (AudioInCtx[1].IsMultiBuff == 1U)
  51.   {
  52.     /* Call the record update function to get the second half */
  53.     BSP_AUDIO_IN_HalfTransfer_CallBack(1);
  54.   }
  55.   else
  56.   {
  57.     if ((AudioInCtx[1].Device & ONBOARD_DIGITAL_MIC_MASK) != 0U)
  58.     {
  59.       for (j = 0U; j < ((AudioInCtx[1].SampleRate / 1000U)* N_MS_PER_INTERRUPT); j++)
  60.       {
  61.         /*DMIC_ONBOARD_CHANNEL*/
  62.         AudioInCtx[1].HP_Filters[0].Z = ((RecBuff[j] / 256) * (int32_t)(AudioInCtx[1].Volume)) / 128;
  63.         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;
  64.         AudioInCtx[1].HP_Filters[0].oldIn = AudioInCtx[1].HP_Filters[0].Z;
  65.         AudioInCtx[1].pBuff[AudioInCtx[1].ChannelsNbr * (j)] = (uint16_t) SaturaLH(AudioInCtx[1].HP_Filters[0].oldOut, -32760, 32760);
  66.         /*AMIC_ONBOARD_CHANNEL*/
  67.         AudioInCtx[1].HP_Filters[1].Z = ((DFSDM_OUT[j]  / 256) * (int32_t)(AudioInCtx[1].Volume)) / 512;
  68.         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;
  69.         AudioInCtx[1].HP_Filters[1].oldIn = AudioInCtx[1].HP_Filters[1].Z;
  70.         AudioInCtx[1].pBuff[(AudioInCtx[1].ChannelsNbr * j) + 1U] = (uint16_t) SaturaLH(AudioInCtx[1].HP_Filters[1].oldOut, -32760, 32760);
  71.       }
  72.     }
  73.     if (AudioInCtx[1].Device == ONBOARD_ANALOG_MIC_MASK)
  74.     {
  75.       for (j = 0U; j < ((AudioInCtx[1].SampleRate / 1000U)* N_MS_PER_INTERRUPT); j++)
  76.       {
  77.         AudioInCtx[1].HP_Filters[1].Z = ((DFSDM_OUT[j]  / 256) * (int32_t)(AudioInCtx[1].Volume)) / 512;
  78.         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;
  79.         AudioInCtx[1].HP_Filters[1].oldIn = AudioInCtx[1].HP_Filters[1].Z;
  80.         AudioInCtx[1].pBuff[AudioInCtx[1].ChannelsNbr * j] = (uint16_t) SaturaLH(AudioInCtx[1].HP_Filters[1].oldOut, -32760, 32760);
  81.       }
  82.     }
  83.     BSP_AUDIO_IN_HalfTransfer_CallBack(1);
  84.   }

  85. }
发送数据到PC
  1. void BSP_AUDIO_IN_HalfTransfer_CallBack(uint32_t Instance)
  2. {
  3.   UNUSED(Instance);
  4.   AudioProcess();
  5.   BSP_LED_Off(LED1);
  6. }
  7. void AudioProcess(void)
  8. {
  9.   Send_Audio_to_USB((int16_t *)PCM_Buffer, (AUDIO_IN_SAMPLING_FREQUENCY / 1000)*AUDIO_IN_CHANNELS * N_MS_PER_INTERRUPT);
  10. }
枚举出来的麦克风


5129066bcb3794484b.png
录音软件使用免费的 ocenaudio

选择 麦克风 (STM32 AUDIO Streaming in FS Mode)

5120366bcb389eedfc.png
开始录音
322766bcb39859286.png

我感觉录制的效果还是挺好的。
录制的音频文件因为太大没法上传,所以分包了。
STWINTK1B_REC.part1.rar (10 MB, 下载次数: 2)
STWINTK1B_REC.part2.rar (10 MB, 下载次数: 1)
STWINTK1B_REC.part3.rar (1.04 MB, 下载次数: 1)


呐咯密密 发表于 2024-8-15 14:05 | 显示全部楼层
语音识别能做吗
 楼主| OldestTrick 发表于 2024-8-15 15:42 | 显示全部楼层

可以试试
[鑫森淼焱垚] 发表于 2024-8-15 17:28 | 显示全部楼层
为大佬点赞
 楼主| OldestTrick 发表于 2024-8-16 09:30 | 显示全部楼层
您需要登录后才可以回帖 登录 | 注册

本版积分规则

23

主题

45

帖子

7

粉丝
快速回复 在线客服 返回列表 返回顶部