DMIC pop / click sounds between each memory block

I'm trying to continuously stream data from the dmic interface, in this case over serial though only for testing.
Things seem to be largely working except for pop/click artifacts between every block.
In this case the memory slab is setup for 4 blocks with enough memory for 100ms of audio, default settings taken from the dmic sample.
The pop is usually about 0.5-1ms long and per recording looks exactly the same each time and occurs in intervals equal to the block size. Large block size means less frequent intervals.

This smells like either samples are dropped between each block or I'm getting garbage data inserted somehow, though it does feel more like audio is missing/overwritten when a pop occurs.
Giving a really large block size like 1000ms of audio make the pop occasionally not occur.

My understanding is that the dmic driver continuously reads data as soon as the start flag is given and will choose a free memory block from the slab to write to. As long as I process a returned block quickly enough and free it then the dmic should not run out of memory or drop samples (if that is even a possible behaviour)?
I can't see an off by one error or similar in the way I grab the data either. It's a bit puzzling.
The interface is not throwing me any errors with debug log enabled.

Attached a sample recording and the project code. The python script can be used to translate the ASCII HEX string to a binary.

Using NCS 2.5.0

3527.dmic.zip


5684.silence_with_clicks.zip

  • Hi Timon

    I did some tests myself in order to evaluate the performance of the UART communication. 

    Trying out the code you sent me I connected the logic analyzer to the TX line in order to see if there could be any issues with the UART communication, and the results were interesting: 

    After every byte I see a gap of around 3.5us, which means the overall throughput will be reduced by a significant factor. 

    Exactly why this happens I am not sure, but I wouldn't be surprised if the console driver (printk) sends data to the underlying transport layer (UART in this case) byte by byte, which means the UART driver is not able to buffer multiple bytes in one transaction. 

    I did a quick rewrite of the code integrating a more efficient UART layer, utilizing the UART async driver to send larger buffers in one go, and now communication seems more efficient: 

    Most bytes are sent back to back, except for a ~35us delay when switching from one buffer to the next. 

    There is a larger delay every 100ms which I assume shows that the bandwidth is now more than sufficient to send the data in time. 

    Can you try out my code and see if it solves the glitching issue? 

    319611_dmic_issue.zip

    Please note I use a wrapper for the UART async driver called 'app_uart' in order to simplify the UART interface, but everything is included in the repo. In order to track my changes you can check the git log. 

    Best regards
    Torbjørn

  • Hi Torbjørn,

    that is really interesting and yes it does fix the issue!
    I'm a bit puzzled as that means something works very differently than I thought with the dmic driver but I'm glad to know that I can ensure things stream correctly if there is definitely no bandwidth bottleneck.
    There is that "starting pop" still but that is fine and seems to be what the Thingy:53 firmware mentioned.
    Also good to know that UART is not async by default

    Thank you for looking at this so thoroughly, it's much appreciated!


  • Hi Timon

    Very good to hear that this fixed the issue Slight smile

    If you look into the exact timings of the printk calls maybe you would find when they start to lag too much behind the DMIC operation to cause issues. I understand the desire to fully understand what is happening, but it is probably not worth the investment in time in this case. 

    The best of luck with your project!

    Best regards
    Torbjørn

Related