There’s this question, about how to get the Arduino Audio Library to work in PIO:
That’s great, but I have some projects that can’t use the Arduino Audio Library:
The Arduino Library is hard-coded for 16-bit 44.1kHz throughout, with a 128-sample buffer (2.9ms latency), and its USB connection is further hard-coded for stereo. That’s fine for just playing around with audio processing, or making synthesizers, or any number of things that don’t need the dynamic range or the I/O count of a serious pro-audio rig, but my specs are closer to the pro world.
For one project, I need 8 channels of 32-bit audio, on both USB and TDM (total of 16-in, 16-out, including both connections), and the physical/acoustic geometry requires about 0.2ms of latency, analog-to-analog. The datasheets for several TDM CODEC chips say that that latency and channel count are possible, only if I run them at 96kHz. (“Double Speed”, as Cirrus calls it; “Quad Speed” gives me 196kHz and even fewer samples of group delay, but not enough channels)
That comes up about 3 samples too fast at 96kHz, which is easy to fix with a 3-sample buffer. But because that latency needs to be exact and is not yet known precisely, I think the practical requirement is no buffer at all (or a buffer of 1, depending on how you think of it), except for an explicit, tweakable delay somewhere in the DSP chain.
Since that completely nukes the Arduino framework’s notion of audio, and imposes a (very!) strict timing requirement (MUST service EVERY sample IMMEDIATELY and completely, at 96kHz), how can I create a new project to do this?
I don’t mind breaking away from the Arduino framework altogether, but I would like a portable project folder that I can put on a fresh PC with a fresh installation of VSCode+PIO, and have it work.
My goal here is to have a template project that includes:
- Globally-defined, compile-time-adjustable sample rate, likely 48kHz or a multiple of it.
- Standards-compliant (works everywhere with no explicit drivers) USB Audio+Serial, with its own compile-time choice of audio channel count and bit-depth, each direction.
- I2S/TDM audio, with its own compile-time choice of channel count and bit-depth.
- Boilerplate DSP section, just to demonstrate how to read and write the USB and I2S/TDM I/O.
- No audio buffer. (or a buffer of 1, depending on how you think of it) This is to support absolute minimal latency, at the expense of some throughput. Practically, it ends up with a 3-frame pipeline for I2S/TDM: clock in, process, clock out. (USB is exempt from this requirement, for obvious reasons)
Copy that template, change the audio settings as needed, and start writing the application code.
I suspect I’ll end up with a top-priority interrupt for each I2S/TDM frame, and the DSP application code also runs in that ISR, but I’m open to any architecture that essentially ends up with, in order of preemptive task priority:
- An “add your DSP code here” section that meets the timing requirements.
- A USB Audio+Serial driver that “just works” in the background.
- An “add your front-panel code here” section that does everything else too, including calculating coefficients, communicating with a PC app via USB Serial, managing the CODEC chip, etc.
It would be nice to still be able to use the other Arduino functions and libraries for #3, but that’s not a hard requirement. The sample timing, and easy flexibility on USB and I2S/TDM, are.