打印
[STM32L4+]

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

[复制链接]
2147|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 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)


使用特权

评论回复
沙发
呐咯密密| | 2024-8-15 14:05 | 只看该作者
语音识别能做吗

使用特权

评论回复
板凳
OldestTrick|  楼主 | 2024-8-15 15:42 | 只看该作者

可以试试

使用特权

评论回复
地板
[鑫森淼焱垚]| | 2024-8-15 17:28 | 只看该作者
为大佬点赞

使用特权

评论回复
5
OldestTrick|  楼主 | 2024-8-16 09:30 | 只看该作者

感谢大佬

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

23

主题

45

帖子

3

粉丝