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

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所有,任何人未经允许禁止转载。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值