This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

SK-AM62: Real-time sound processing with minimal latency

Part Number: SK-AM62

Hello. I'm involved in the development of guitar pedals. The previous hardware platform I used was based on a specialized DSP processor and an audio codec. This allowed for audio reception, processing, and output in a sample-by-sample pipeline with minimal delay, without accumulation.

Currently, I'm working on a new hardware platform based on the AM62 SoC. For initial testing, I'm using the EVM SK-AM62 powered by Processor SDK RT-Linux for AM62x. I'm using the ALSA library for C++ for audio signal reception and output.

I've encountered an issue: I can't reduce the size of the input and output buffers to less than 64 samples using the ALSA API. Although, based on the documentation for the McASP interface and the TLV320AIC3106IRGZT codec, they don't have mandatory requirements for a minimum buffer size, and this limitation appears to be purely a software constraint.

Could you please advise on how to reduce the size of the input and output buffers to at least 8 samples?

  • Hi Yakov,

    Could you share the ALSA commands that you were using in sample-by-sample pipeline?

    On AM62x currently we are able to record and playback using the following commands with the latest SDK release: https://dr-download.ti.com/software-development/software-development-kit-sdk/MD-PvdSyIiioq/09.00.00.03/tisdk-default-image-am62xx-evm.wic.xz

    amixer sset ‘Left PGA Mixer Mic3L’ on
    amixer sset ‘Right PGA Mixer Mic3R’ on
    amixer sset ‘Left PGA Mixer Mic3R’ on
    amixer sset ‘Right PGA Mixer Mic3L’ on

    arecord -Dhw:0,0 -r 48000 -c 2 --period-size=64 -d 20 -f S16_LE | aplay -Dhw:0,0

    In my example above period-size is set to 64 bytes.

    Please refer the below two links to understand the relation between period, period-size and buffer-size in ALSA:

    https://users.suse.com/~mana/alsa090_howto.html

    www.linuxjournal.com/.../6735

    Best Regards,

    Suren

  • Thank you for the quick response.
    I apologize for the inaccuracy in my initial message. I was attempting to change not the buffer size but the period size in order to reduce the latency between signal input and output. To do this, I used the following C++ code. Actually, I used this code twice, both for the recording device and for the playback device.

    snd_pcm_uframes_t frames = 8;
    snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);
    rc = snd_pcm_hw_params(handle, params);
    if (rc < 0) {
           fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc));
    }

    Next, I queried the current period size:

    snd_pcm_hw_params_get_period_size(params, &frames, &dir);

    And the obtained value was 64. I also tried setting the period size to 16 and 32, but I always ended up with a period size of 64.
    Based on the description of how the ALSA driver works, I concluded that the period size determines how many samples must accumulate before they are either fed into a recording program or sent to the audio output when a program is playing sound. In a system processing samples one by one, the periods of the input and output buffers should ideally be set to 1. However, this can result in too frequent interrupts. Therefore, I am considering working with a period size of 8. But, as I mentioned above, the ALSA API does not allow me to set this value below 64.

    Is there any way to change this?

  • Hi Yakov,

    If you look at this diagram, 

    If periods = 8 frames and each as 2 channels interleaved with represented as 4 bytes per frame(16-bit stereo), then the periodsize would be 64. (8*2*4=64)

    Can you reduce the frames to 4 or 2 and see the period size change as you are expecting 32/16.

    You could also look at this:

    stackoverflow.com/.../the-meaning-of-period-in-alsa

    Best Regards,

    Suren

  • Thank you for your help, Suren
    I carefully reviewed the materials you referred to, as well as the documentation for the ALSA API and the ‘arecord’ command, and I found discrepancies.
    1) periodsize
    In the article users.suse.com/.../alsa090_howto.html, it is measured in bytes:
    snd_pcm_uframes_t periodsize = 8192; /* Periodsize (bytes) */
    And it seems that your recommendations are also based on this. However, if you look at the documentation for the ‘arecord’ command at linux.die.net/.../arecord, you can see:
    ” --period-size=# Distance between interrupts is # frames ...”
    Also, in the documentation at www.alsa-project.org/.../group___p_c_m___h_w___params.html for the ‘snd_pcm_hw_params_set_period_size_near’ function within the ALSA API, which I use in my program, it is stated that the ‘val’ parameter that sets the period size is specified in frames. This is also indicated by the data type ‘snd_pcm_uframes_t’, which stands for Unsigned frames quantity (www.alsa-project.org/.../group___p_c_m.html
    Based on this information, I assume that periodsize should be specified in the number of frames.

    2) Latency
    In the article users.suse.com/.../alsa090_howto.html, playback latency is determined by the formula:
    /* latency = periodsize * periods / (rate * bytes_per_frame) */
    Where periodsize is specified in bytes. Thus, latency is equal to the size of the buffer in frames divided by the sample rate. Similarly, the reception latency for audio should be calculated.

    However, if we look at the article www.linuxjournal.com/.../6735, it states: “The buffer can be quite large, and transferring it in one operation could result in unacceptable delays, called latency. To solve this, ALSA splits the buffer up into a series of periods (called fragments in OSS/Free) and transfers the data in units of a period.” In other materials (alsa.opensrc.org/Period, www.alsa-project.org/.../FramesPeriods), it is also mentioned that the time between interrupts for processing a batch of samples is determined by the length of the period. Therefore, I conclude that the delay between the signal arriving at the audio card’s input and when it becomes available in the application’s memory is determined by the period size plus the time taken by the operating system to process the interrupt, which can be omitted for approximate calculations. Similarly, the playback latency for audio should be calculated in a similar manner.

    I might have misunderstood something, and I hope you will correct me if I’m wrong. However, in my further reasoning, I will proceed with the assumption that latency is calculated as the period size in frames divided by the sample rate.

    3) My task
    Let’s consider my task based on the considerations mentioned above. The requirements for the input and output audio signals are as follows: a sampling frequency of 48 kHz (Fs), a bit depth of at least 24 bits, and two parallel audio channels - left and right. The received signal is processed according to a DSP algorithm before being played back. This process occurs continuously. The total system latency should not exceed 670 microseconds (latency_max).
    The period sizes (period_size) for the input and output buffers will be set to be the same. Therefore, the receive latency (latency_in) and playback latency (latency_out) should also be equal. For synchronization purposes, the DSP algorithm will process signals at a frequency of 48 kHz. Thus, the latency for processing a signal batch (latency_dsp) will have the same duration.
    For the sake of simplifying calculations in the initial approximation, I propose omitting the time for interrupt processing by the operating system.
    The total system latency is calculated as follows:
    latency_total = latency_in + latency_dsp + latency_out
    Considering the reasoning presented above, we can represent it as:
    latency_total = (3 * period_size) / Fs
    Knowing the sampling frequency Fs and that latency_total ≤ latency_max, we get:
    (3 * period_size) / 48000 ≤ 0.000670
    Additionally, period_size should be a power of 2. From this, we can derive that period_size ≤ 8.

    And now I’m returning to my initial message.
    I’ve encountered an issue: I can’t reduce input periodsize and output periodsize to less than 64 frames using the ALSA API. Although, based on the documentation for the McASP interface and the TLV320AIC3106IRGZT codec, they don’t have mandatory requirements for a minimum period size, and this limitation appears to be purely a software constraint.
    Could you please advise on how to reduce input period_size and output period_size to at least 8 frames ?

    Best Regards,
    Yakov

  • Hi Yakov,

    Give me few days time to respond, as I am checking on this internally with experts.

    Best Regards,

    Suren

  • Hi Yakov,

    Have you reached out to the ALSA community for help on this?

    Our McASP/UDMA imposes a restriction of 32-bytes minimum for period size https://git.ti.com/cgit/ti-linux-kernel/ti-linux-kernel/tree/sound/soc/ti/udma-pcm.c?h=ti-linux-6.1.y#n23

    This should mean 8-samples period-size should work, assuming 4-bytes (32bits) per sample.

    Best Regards,

    Suren

  • Thank you for provided information. I need few day to check out it and I'll report my results.
    Best Regards,
    Yakov

  • Sure Yakov.  Will wait for your results.

    Best Regards,

    Suren

  • Hi Yakov,

    I also had this question and have been following this post.  Do you have any results to report from your investigation?

    Best regards,
    Jason