This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

how to change usbd_audio example in nrf5 SDK 17.02 to send 16kHZ voice data to pc ?

My requirement is to send 16kHz 1channel voice data stream to pc . 

I use  16khz (2 channel and 1 channel) wav and 1 48khz (2 channel) wav as input  (converted to .c  file) data to directly send to m_temp_buffer in main.c (nRF5_SDK_17.0.2_d674dde\examples\peripheral\usbd_audio), and play a song in pc and  then use recording tool in pc to record the data from nrf52 usb mic .

result is :

48khz input wav :the output recording is exactly same with the input.

16khz input wav(2 channel):the output recording is distorted.

16khz input wav(1 channel):the output recording is distorted.

my change to the main.c is as follows:

/**
 * @brief User event handler @ref app_usbd_audio_user_ev_handler_t (headphones)
 */
static void hp_audio_user_ev_handler(app_usbd_class_inst_t const * p_inst,
                                     app_usbd_audio_user_event_t   event)
{
    app_usbd_audio_t const * p_audio = app_usbd_audio_class_get(p_inst);
    UNUSED_VARIABLE(p_audio);
    switch (event)
    {
        case APP_USBD_AUDIO_USER_EVT_CLASS_REQ:
            hp_audio_user_class_req(p_inst);
            break;
        case APP_USBD_AUDIO_USER_EVT_RX_DONE:
        {
            ret_code_t ret;

#if 0
            /* Block from headphones copied into buffer, send it into microphone input */
            ret = app_usbd_audio_class_tx_start(&m_app_audio_microphone.base, m_temp_buffer, m_temp_buffer_size);
            if (NRF_SUCCESS == ret)
            {
                bsp_board_led_invert(LED_AUDIO_RX);
            }
#endif
            break;
        }
        default:
            break;
    }
}




static void hp_sof_ev_handler(uint16_t framecnt)
{
    UNUSED_VARIABLE(framecnt);
    if (APP_USBD_STATE_Configured != app_usbd_core_state_get())
    {
        return;
    }
    size_t rx_size = app_usbd_audio_class_rx_size_get(&m_app_audio_headphone.base);
    m_temp_buffer_size = rx_size;
//NRF_LOG_INFO("%d %d",rx_size,sizeof(m_temp_buffer));
    if (rx_size > 0)
    {
        ASSERT(rx_size <= sizeof(m_temp_buffer));
        ret_code_t ret;

#if 1
             memcpy(m_temp_buffer,samplelg1+offset,BUFFER_SIZE*4);
              m_temp_buffer_size= BUFFER_SIZE*4;
              offset+=BUFFER_SIZE*4;
              if(offset>=652032)
              {
                offset=0;
                }
 #endif
            /* Block from headphones copied into buffer, send it into microphone input */
            ret = app_usbd_audio_class_tx_start(&m_app_audio_microphone.base, m_temp_buffer, m_temp_buffer_size);
            if (NRF_SUCCESS == ret)
            {
                bsp_board_led_invert(LED_AUDIO_RX);
            }

    }
}

question is how to change usbd_audio example to send 16kHZ 1channel voice data to pc properly?

Parents
  • Hi 

    The USB audio support in Windows is not very well documented, but it seems that there is no way to get sample frequencies below 44.1kHz to work properly. 

    I have seen similar requests before, but we were unable to find any way to get Windows to properly detect devices with lower frequencies. 

    A possible workaround to this issue is to upsample the 16kHz signal to 48kHz before sending it to the host, but this will come at a cost of CPU processing and memory. 

    To multiply the sampling frequency by a factor of three you have to add two empty samples for every source sample, and apply a low pass filter to fill in the blanks. 

    Best regards
    Torbjørn

Reply
  • Hi 

    The USB audio support in Windows is not very well documented, but it seems that there is no way to get sample frequencies below 44.1kHz to work properly. 

    I have seen similar requests before, but we were unable to find any way to get Windows to properly detect devices with lower frequencies. 

    A possible workaround to this issue is to upsample the 16kHz signal to 48kHz before sending it to the host, but this will come at a cost of CPU processing and memory. 

    To multiply the sampling frequency by a factor of three you have to add two empty samples for every source sample, and apply a low pass filter to fill in the blanks. 

    Best regards
    Torbjørn

Children
  • hi Torbjørn,

    i change the DESCRIPTOR in the code to:

    APP_USBD_AUDIO_FORMAT_DESCRIPTOR(m_mic_form_desc,
    APP_USBD_AUDIO_AS_FORMAT_I_DSC( /* Format type 1 descriptor */
    2, /* Number of channels */
    2, /* Subframe size */
    16, /* Bit resolution */
    1, /* Frequency type */
    APP_USBD_U24_TO_RAW_DSC(16000)) /* Frequency */
    );

    APP_USBD_AUDIO_FORMAT_DESCRIPTOR(m_hp_form_desc,
    APP_USBD_AUDIO_AS_FORMAT_III_DSC( /* Format type 3 descriptor */
    2, /* Number of channels */
    2, /* Subframe size */
    16, /* Bit resolution */
    1, /* Frequency type */
    APP_USBD_U24_TO_RAW_DSC(16000)) /* Frequency */
    );

    and strange thing is  it works in some version of  Windows 10 ( for ex: it can not work in my laptop which is windows 10 pro os 20h2 build 19042.1165, but my another PC can work with this change which is windows 10 pro os 21h1 build 19042.1165).

    and after the change , i found that in the windows 10 pro os 21h1  i can send the 16KHZ  2 channel voice data rightly because the recording from the mic of the 16KHZ 2 channel is good .

    Does that mean change the  DESCRIPTOR is another solution(just need a right version of windows 10) comparing your solution upsampling  the 16kHz signal to 48kHz?

    Thanks

  • Hi 

    My bad. I discussed this with a colleague of mine, and he had also been able to get 16kHz to work in windows. 

    He was even able to share the code he used for the test:

    pdm_cat.zip

    The code integrates with SDK v17.0.2. 

    Can you give his code a try and see if it works better?

    Best regards
    Torbjørn

Related