Hi, I am working on a project for which I'd like to write a custom output object for the Teensy audio library (using Teensy 3.6). To this end I have been studying the existing output objects in the Audio Library github. The code for these objects involves a lot of bit register stuff that gets pretty cryptic, so I wanted to make a post here to help check / expand my understanding.

The essential thing I'm interested in understanding is how the output objects convert from audio buffer processing, which updates at an interval determined by [sample rate / buffersize], to individual sample output, which has to output individual sample values at the sample rate.

I see in the source code for AudioOutputAnalog that the object has its own interrupt service routine which is attached to a direct memory transfer object. When this gets called it fills a source buffer for the DMA with the samples from the input buffer to AudioOutputAnalog. This DMA object then updates the DAC value sample by sample at a rate set by DMAMUX_SOURCE_PDB (not sure what this stands for). Does this seem mostly correct?

In my use case, I want to create an output object that writes to a series of shift registers chips using the Teensy's SPI port. I am going to use this to output to shift registers based on values received via the Teensy's USB audio port or possible from SD card audio files. To do this I need to call the SPI transfer function at the sample rate, or some predictable division thereof, I realize that I probably can't use DMA for this, so I'm wondering what the best method would be to ensure synchronicity and avoid issues with buffer overruns. I'm thinking I probably need to create some sort of ISR to execute the SPI transfer, but I wanted to get some advice to determine best practices before starting.