PDM data to speaker

Hi,I am working with pdm mic to read data .I can able to get the audio data using dmic_read api in pcm format.I got clock of 1280000 and sampling rate of 16000 of each 16 bit sample.Now I want to play that data in tas2562 speaker amplifier.I configured pins for i2s tx i.e,clock,fclk,data out pin and I got clock frequency of 507936 of sampling rate 15873.And I got following output.I am making buffer slab free for every loop.


00> [00:00:00.001,215] <inf> dmic_sample: DMIC sample
00> [00:00:00.001,229] <inf> dmic_nrfx_pdm: PDM clock frequency: 1280000, actual PCM rate: 16000
00> [00:00:00.001,268] <inf> i2s_nrfx: I2S MCK frequency: 507936, actual PCM rate: 15873
00> Configure Stream Successful.
00> Trigger Command Successful.
00> [00:00:10.911,696] <err> dmic_nrfx_pdm: No room in RX queue
00> [00:00:11.012,512] <err> i2s_nrfx: Next buffers not supplied on time
00> [00:00:11.952,097] <err> dmic_sample: read failed: -11

Parents
  • Hello,

    It is difficult to say exact without seeing the entire application, and being able to reproduce, but you should try replacing i2s_buf_write() with i2s_write(). The issue is that i2s_buf_write() is blocking waiting for a free buffer, but this is not being provided. Also, you should only free the mem_slab if there is an error (because i2s_write() frees it upon success).

    ret = i2s_write(i2s_dev_tx, buffer, size);
    if (ret) {
        LOG_ERR("Failed to write I2S buffer: %d", ret);
        k_mem_slab_free(&mem_slab, buffer);  // only free on error
        return 0;
    }

    Try increasing the block count from 8 to e.g. 16.

    #define BLOCK_COUNT 16

    Try moving dmic_trigger() to after the I2S has been configured:

    	config.word_size = 16;
    	config.channels = NUMBER_OF_CHANNELS;
    	config.format = I2S_FMT_DATA_FORMAT_I2S;
    	config.options = I2S_OPT_BIT_CLK_MASTER | I2S_OPT_FRAME_CLK_MASTER;
    	config.frame_clk_freq = MAX_SAMPLE_RATE;
    	config.mem_slab = &mem_slab;
    	config.block_size = BLOCK_SIZE;
    	config.timeout = READ_TIMEOUT;
    	if (!configure_streams(i2s_dev_tx, &config))
    	{
    		return 0;
    	}
    	
    	ret = dmic_trigger(dmic_dev, DMIC_TRIGGER_START);
    	if (ret < 0)
    	{
    		LOG_ERR("START trigger failed: %d", ret);
    		return ret;
    	}

    Let me know if that changes anything. If not, it would be helpful if you could zip and post the application that you are using to replicate this, so that I can try to do it on a DK.

    Best regards,

    Edvin

  • I tried with the changes you mentioned but the errors its throwing ,I am attaching logs and zip file .00> [00:00:00.001,184] <inf> dmic_sample: DMIC sample
    00> [00:00:00.001,197] <inf> dmic_nrfx_pdm: PDM clock frequency: 1280000, actual PCM rate: 16000
    00> [00:00:00.001,222] <inf> i2s_nrfx: I2S MCK frequency: 507936, actual PCM rate: 15873
    00> Configure Stream Successful.
    00> Trigger Command Successful.
    00> [00:00:10.911,696] <err> dmic_nrfx_pdm: No room in RX queue
    00> [00:00:11.012,482] <err> i2s_nrfx: Next buffers not supplied on time
    00> [00:00:11.952,065] <err> dmic_sample: read failed: -11


    8358.dmic.zip

  • I think the BLOCK_COUNT needs to be at least AUDIO_Q_LEN + 10. The AUDIO_Q_LEN uses blocks from the mem_slab (size = BLOCK_COUNT), and then you need some more for the dmic. I think the limit is AUDIO_Q_LEN + 2 for DMIC DMA + 4 for I2S tx queue and 2 for I2S HW. In addition, you need 2 for handover. Perhaps use AUDIO_Q_LEN + 12 to be sure. 

    Best regards,

    Edvin

  • Yes,when I follow this buffers I am just loosing one block of audio per second but audio flow is working fine.But when I used I2S_RX and TX there it worked even for 4 blocks in mem_slab without issue .Is it because here  PDM to I2s it's taking many blocks in recent approach(threads).
    And in final I want to know reading data from PDM Mic and getting PCM data will cause more processing in time in compare with using I2S MIC  with i2s_read?.I want to confirm what mic should I use as I will be doing more processing before sending to speaker.Will both the processes will require same processing or different?

    With Regards,

    Kashyap

  • And also to mention I can see noticeable delay in the output while listening audio in speaker.Why we are getting delay ? we are doing using threads and process is straight we read and just send in speaker.I kept AUDIO_Q_LEN + 12 memory. And if I do processing in between will delay will be increased?

  • The reason for all this is that the pdm is sampling a bit faster than the I2S is outputting. This means (as an example, not actual numbers) that if the mic records for 1 second, that results in the speaker playing 1.1 seconds (a bit of slow motion). The difference is listed in the table that you pasted earlier:

    The reason the nRF54L15 is not capable to do Audio over Bluetooth LE (like the nRF5340 is) is because it lacks a HW component, the Audio PLL, which is responsible for adjusting the clock speed to avoid these mismatches. 

    There may be better ways to do this than what I suggested. It was just an attempt to make the error that you saw go away. Perhaps you can make it work with just 2 buffers, if you handle the logic yourself. Just make sure that wherever you are trying to store your dmic buffers to are free/available.

    Best regards,

    Edvin

  • Hi Edvin,thanks for that response.I understood how its working.

    And in final I want to know reading data from PDM Mic and getting PCM data will cause more processing in time in compare with using I2S MIC  with i2s_read?.I want to confirm what mic should I use as I will be doing more processing before sending to speaker.Will both the processes will require same processing or different

    Can you clarify me this thing ?

Reply
  • Hi Edvin,thanks for that response.I understood how its working.

    And in final I want to know reading data from PDM Mic and getting PCM data will cause more processing in time in compare with using I2S MIC  with i2s_read?.I want to confirm what mic should I use as I will be doing more processing before sending to speaker.Will both the processes will require same processing or different

    Can you clarify me this thing ?

Children
  • That questions itself is as clear as mud. Don't expect an answer unless you completely re-write that so other people have a chance to understand it.

    As a general hint: Mess with both PDM and I²S settings until sampling frequencies match exactly and use these settings going forward.

    Re-sampling (the other way to handle the difference) is non-trivial in both code and CPU cycle usage especially if both frequencies are close to each other.

Related