Real-time block processing setup on ARM Newbie question here. 

I'm working on a system that is running a 32khz sampling rate, audio, 16 bit DAC. 
Previously, our system had a very hard latency requirement of 1 sample. So no problem, we just read 1 sample in, did some processing within the sampling rate, and then read 1 sample out. 

Now that this requirement has been relaxed, I think that we can use block processing to do things such as spectrum computation and processing and use more than 1 sample to do the adding and multiplication, etc. 
Does this buy us blockSize * (1/fs) compute time?

My problem is, being a noob, I don't know how to formulate this new requirement in our chip's main() function.

So let's pretend we have some function SPI_Read(&amp;mic) which is reading a sample, and SPI_Write(&amp;output) which sends to a speaker. How would I transform this into a block based system?

The current system is setup like:

main() {
    while() { // check for interrupt
        // while loop executing on system timer set to 1 / fs
        SPI_Read(&amp;in); // read from adc
        // filters
        SPI_Write(&amp;out); // output to dac

    }
}


This is running on a cortex-M4, no codec.

Thank you for your help! (:
First, use a timer and an ISR to get accurate timing (don't forget to configure the NVIC so that this timer interrupt takes over any other ISR that would be running). Only this will ensure a consistant sample rate. Little variations in timing would create noticeable degradations of audio quality. In particular, in your current example, unless the "filters" code has no branches, the time at which the SPI_Write occurs will be jittery depending on the path taken in the code.

For block processing, you need a "ping-pong" buffering scheme.

In your per-sample ISR:

SPI_Write(output[active_buffer][sample_index]);
SPI_Read(input[active_buffer][sample_index]);
++sample_index;
if (sample_index &gt;= BUFFER_SIZE) {
  active_buffer = (active_buffer + 1) % NUM_BUFFERS;
  sample_index = 0;
}


In your main code:

while (render_buffer != active_buffer) {
  // Process samples from input[render_buffer][0] to input[render_buffer][BUFFER_SIZE - 1]
  // And write them to output[render_buffer][0] to output[render_buffer][BUFFER_SIZE - 1]
  render_buffer = (render_buffer + 1) % NUM_BUFFERS;
}


render_buffer and active_buffer are declared as volatile. Start with NUM_BUFFERS equal to 2. Higher values will introduce more latency, but might be necessary if the processing code has exceptionally long code paths.

The benefit of processing samples block by block is that some variables required by your DSP algorithm (such as filter state variables) can be kept in registers within the processing loop, saving load/stores. There are also situations in which you can benefit from batch load/stores. Finally, it makes it easier to schedule computations at "audio rate" (once per audio sample) and "control rate" (once per block).