This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

HOW TO CONVERT SGTL5000 DATA INTO WAV FILE?

Hello Team,

First Thanks to all Nordic support:)

My problem :

I have interfaced SGTL5000 with Nrf52832 (used SDK 16) I'm getting the audio data on aux connector and also getting data in form of integer value ( negative and positive values ) 

Now I have take a log of this integer values using jlink RTT viewer but I don't know how to convert this values into wav file?

{ I played one song and based on that I take log on RTT viewer  }

2) I also want to transmit this data on ble Nordic uart service and from android I want to convert this data into wav file ( live streaming - some real time delay is acceptable) but I don't how to convert data into wav file?

Thanks! 

  • Hi,

    This repository may provide some useful tips and links.

    I'm not aware of any specific libraries for converting to WAV format, but as far as I can see, the input from SGTL5000 is PCM format, so any PCM to WAV converters should do the job.

    Best regards,
    Jørgen

  • Thanks for the reply!

    Actually, I already used this example in my customize code but I don't know how to convert integer data into a .wav file

    I have spent lots of time behind this but still, I have not got success! 

    I have attached the recorded data file please let me know if is it the right file for .wav conversion or not?

    Please help me out with this  

    Thanks!

  • If this file format is not right then please let me know how to generate the right file format for .wav file

  • Hi,

    I spoke with our developers that made the Python script to convert the WAV file to C in the GitHub repository. They recommend using the built in package "wave" in Python to convert from PCM array to WAV, for instance like this:

    import wave
    
    # Raw uint8 values
    pcm = [0x01, 0x02, etc.]
    
    # Assume 1 channel, 16-bits (2 bytes), 16 kHz 
    # w = open("my_file.wav", "wb")
    w.setparams((1, 2, 16000, len(pcm)/2, 'NONE', 'not compressed'))
    w.writeframes(bytes(pcm))
    w.close()

    This should likely work with the endianness used by nRF52 without any explicit converting, but if not, you just needs to re-arrange the bytes in the pcm-array: 

    pcm = [0x01, 0x02, 0x03, 0x04]
    to:
    pcm = [0x02, 0x01, 0x04, 0x03]
    Best regards,
    Jørgen
  • HellO,

    Thanks for the reply!

    Here is the my I2S setting .

    //@@@@@@   I2S setting  @@@@@@@@@@@@@@@@@@@

    #define AUDIO_FRAME_WORDS 320
    #define I2S_BUFFER_SIZE_WORDS AUDIO_FRAME_WORDS * 2 // Double buffered - I2S lib will switch between using first and second half
    static uint32_t m_i2s_tx_buffer[I2S_BUFFER_SIZE_WORDS];
    static uint32_t m_i2s_rx_buffer[I2S_BUFFER_SIZE_WORDS];

    /* Include car sample to demonstrate that sample can be played from application as well */
    #define SAMPLE_LEN 67200
    extern const uint8_t car_sample[SAMPLE_LEN];
    static uint8_t * p_sample = (uint8_t *)car_sample;
    static uint32_t sample_idx = 0;


    int16_t data_audio[(AUDIO_FRAME_WORDS/2)];

    //@@@@@@@@@@@@@@@@@@@@@@@@@@

    //@@@@@@@@@@@@@@ i2c event handler @@@@@@@@@@@@@@@@@

    static bool i2s_sgtl5000_driver_evt_handler(drv_sgtl5000_evt_t * p_evt)
    {
    bool ret = false;
    //NRF_LOG_INFO("i2s_sgtl5000_driver_evt_handler %d", p_evt->evt);

    //NRF_LOG_INFO("%d",p_evt->param.rx_buf_received.p_data_received);
    switch (p_evt->evt)
    {
    case DRV_SGTL5000_EVT_I2S_RX_BUF_RECEIVED:
    {

    uint16_t * p_buffer = (uint16_t *) p_evt->param.rx_buf_received.p_data_received;
    i2s_buffer_size_words = p_evt->param.rx_buf_received.number_of_words;
    int16_t pcm_stream[i2s_buffer_size_words]; // int16_t - i2s_buffer_size_words size; means we only cover half of data_to_send_buffer, which is fine since we are only using LEFT channel

    memcpy(data_audio, p_buffer, i2s_buffer_size_words);

    ret = true;
    }
    break;
    case DRV_SGTL5000_EVT_I2S_TX_BUF_REQ:
    {
    //NRF_LOG_INFO("i2s_sgtl5000_driver_evt_handler TX BUF REQ");

    /* Play sample! 16kHz sample played on 32kHz frequency! If frequency is changed, this approach needs to change. */
    /* Playback of this 16kHz sample depends on I2S MCK, RATIO, Alignment, format, and channels! Needs to be DIV8, RATIO 128X, alignment LEFT, format I2S, channels LEFT. */

    uint16_t * p_buffer = (uint16_t *) p_evt->param.tx_buf_req.p_data_to_send;
    uint32_t i2s_buffer_size_words = p_evt->param.rx_buf_received.number_of_words;
    int16_t pcm_stream[i2s_buffer_size_words]; // int16_t - i2s_buffer_size_words size; means we only cover half of data_to_send_buffer, which is fine since we are only using LEFT channel

    /* Clear pcm buffer */
    memset(pcm_stream, 0, sizeof(pcm_stream));

    /* Check if playing the next part of the sample will exceed the sample size, if not, copy over part of sample to be played */
    if (sample_idx < SAMPLE_LEN)
    {
    /* Copy sample bytes into pcm_stream (or remaining part of sample). This should fill up half the actual I2S transmit buffer. */
    /* We only want half becuase the sample is a 16kHz sample, and we are running the SGTL500 at 32kHz; see DRV_SGTL5000_FS_31250HZ */
    uint32_t bytes_to_copy = ((sample_idx + sizeof(pcm_stream)) < SAMPLE_LEN) ? sizeof(pcm_stream) : SAMPLE_LEN - sample_idx - 1;
    memcpy(pcm_stream, &p_sample[sample_idx], bytes_to_copy);
    sample_idx += bytes_to_copy;
    ret = true;
    }
    else
    {
    /* End of buffer reached. */
    sample_idx = 0;
    ret = false;
    }

    /* Upsample the decompressed audio */
    /* i < i2s_buffer_size_words * 2 because we have a uint16_t buffer pointer */
    for (int i = 0, pcm_stream_idx = 0; i < i2s_buffer_size_words * 2; i += 2)
    {
    for (int j = i; j < (i + 2); ++j)
    {
    p_buffer[j] = pcm_stream[pcm_stream_idx];

    }
    ++pcm_stream_idx;
    }


    }
    break;
    }

    return ret;
    }

    //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

    //@@@@@@@@@@@@@@ Here I am logging the my audio data @@@@@@@@@@@

    // Enter main loop.
    for (;;)
    {
    idle_state_handle();



    for(int i = 0; i < (AUDIO_FRAME_WORDS / 2) ; i++)
    {
    NRF_LOG_RAW_INFO("%d\n,",data_audio[i]);


    NRF_LOG_FLUSH();
    }

    }//FOR LOOP CLOSED BRACKET
    }//MAIN LOOP CLOSED BRACKET

    Please let me know the right settings for getting audio data. 

Related