Examples of Output Only. No Input

From our github, I had a question about using the Tympan_Library purely for output for synthesis.

One example sketch that only generates output would be this one: https://github.com/Tympan/Tympan_Library/tree/master/examples/02-Utility/OutputToneWithSteppedAmplitude

When you go inside the sketch, you can see that it creates a Tympan objects, two audio objects, and then a couple audio connections:

// Create the audio library objects that we'll use
Tympan                    myTympan(TympanRev::D, audio_settings);   //use C or D
AudioSynthWaveform_F32    sineWave(audio_settings);   //from the Tympan_Library
AudioOutputI2S_F32        audioOutput(audio_settings);//from the Tympan_Library

// Create the audio connections from the sineWave object to the audio output object
AudioConnection_F32 patchCord10(sineWave, 0, audioOutput, 0);  //connect to left output
AudioConnection_F32 patchCord11(sineWave, 0, audioOutput, 1);  //connect to right output

So, the part that creates the audio is the AudioSynthWaveform_F32. This is a merely a float32 extension to the AudioSynthWaveform that is in the original Teensy Audio library. As a general way of thinking, if you can configure the Teensy Audio library to do what you want, you can configure the Tympan_Library to do the same thing.

If you want to make your own crazy-cool synthesis effects, you need to compose the synthesis modules using connecting existing audio objects, or you need to write your own audio classes. Again, this is just like the original Teensy Audio library.

There is the possibility of injecting audio from outside the Teensy Audio universe and inserting it into the Teensy Audio universe by using AudioPlayQueue_F32 (or the regular Teensy Audio library version: AudioPlayQueue) but I think that you’d find it just as easy to learn to make your own audio object from scratch rather than force an AudioPlayQueue to suit your purpose.



I’m an author of initial question on github.

I’m currently working on a project of a modular synthesizer (https://en.wikipedia.org/wiki/Eurorack). I’ve created math for, made a virtual implementation for VCV Rack and now porting it on hardware.

My first attempt to implement it was with ESP32/PCM5102, which was a good starting point. PCM5102 has samplerate/depth up to 384kh/32bit and ESP32 has two cores. Unfortunately, it seems that ESP32 has not enough CPU: my code is relatively computationally heavy and even with optimization, I think, I wont be able to fit my ideas into that chip (currently I can run 1 channel on 48khz/32bit). What I am aiming for is 2 channels, 96k/32bit, so that means 168k sample calculations in a sec.

I’ve switched to Teensy 4.1, and it has enormous FPU performance. My code there runs much faster on it, with a lot of headroom in terms of performance. Sadly, the standard audio lib has a limitation in samplerate/bit depth, which you all aware of and that kills whole idea.


Why 44100/16bit is not enough.

  1. In terms of professional audio (no sarcasm here, I truly believe that modular synths can be done on cheap microcontrollers and available DACs and there are plenty of modules available) 44100/16 is absolute minimum as you cannot go below than that. It’s not only about quality (which is really important) but also about marketing (think of it like trying to sell steam engine in 2020).
  2. Aliasing (https://theproaudiofiles.com/digital-audio-aliasing/). When you are generating harmonic-rich signal, the lower your samplerate the worst the aliasing (non-harmonic, uncontrollable, non-musical kind of noise).
  3. Simply it’s outdated. Why limiting to 44100/16, where there are plenty of DACs on market that support much better audio quality and has internal clock.

[tbc] (sorry, writing it in pauses in a really big meeting, so there will be more posts today :))

Now on Tympan library. So far it the only lib for Teensy that supports samplerates/bit depths that I need, and has some level of maturity.

For my particular task, I don’t need 90% of Tympan functionality (like SD/effects/FFT and things specific for hearing loss).

All I need is a driver where I can set I2S params and write some bytes to the pipe. Basically, here is the code of my simple lib that I wrote for ESP32: https://gist.github.com/dchaplinsky/a7a32066653a683fbc5d7cc068847e5d

And here is the usage example:

void loop() {
int32_t sample[2];
for (long i = 0; i < samplerate; i++) {
sample[0] = osc.process(sequence[interruptCounter], param1) * 10000000 * 100;
sample[1] = sample[0];

and ultimately I’m looking for something like that.

And here are all peculiar options I have:

  1. Ditch Teensy as an architecture and switch to different chip (but I love it’s performance!)
  2. Write my own low-level lib, with only functionality I need (but I’m quite bad at low level stuff, interrupts, DMA, etc)
  3. Use Tympan as is, implementing my code as additional patchable modules (but so far I cannot even properly compile it on my mac)
  4. Fork Tympan, to remove all code I don’t need and only leave parts I’m interesting in, polishing it here and there as I go (and I’m inclined to at least try it).
  5. Extract IO related code from Tympan to an external low-level lib and create PR for Tympan that will use that lib for IO (but I’m not sure that it’ll fit Tympan architecture/general idea)

And here I need your advice and, probably, help.

@dchaplinsky Happy to hear that you found us, and that you can use Tympan for your project. We love it when folks find ways to branch out with our work.

I don’t have a specific answer to your question, I do the hardware for Tympan, but I will say that we have a new version, the Tympan Rev E in the works which builds upon the Teensy 4.1. Our prototypes are under test right now.

While the hardware is still in beta and not so easy to get, our Tympan library should be getting updated to work with the Teensy 4.1!

Hello @biomurph!

Won’t you mind if I ask some questions on I2S implementation later on?

Or maybe you can point me to a good documentation on how to implement it? So far I’m a bit knocked off with all the new things I need to master: mysterious constants, interrupts, DMA and stuff.

Also, is there any specific issue with Tympan Library on Teensy 4.1? Any chance to get it working on that chip (as I mentioned so far I wasn’t able to build it at all :(, will give it another try tonight)?

Oh lord, spent another couple of hours on it and now I understand why you are saying that it’s not yet ready for Teensy 4.* — in fact input_i2s_f32.cpp and output_i2s_f32.cpp are relying heavily on constants from kinetisk.h, which is only available for Teensy 3.*.

Seems that original Audio lib worked it out by putting tons of
#if defined(KINETISK)
#elif defined(IMXRT1062)

code in input/output classes. Will try to backport that spaghetti to my altered version of Tympan library to see if it works.

Gosh, I wasn’t prepared to that :frowning:

Close but no cigar :frowning:

Did backport for begin/config_i2s from current implementation of TeensyAudio, but have no clue what to do with isr_32.
Seems like I don’t have enough experience to pull that one.

Please help :frowning:

There’s a developmental branch of our library that supports T4.x as well as T3.x. It works at the full range of sample rates that we’ve used to date (up to 96 kHz, four channel audio). It could run faster, if your AIC works faster. The new branch is here:


Because Teensy is also in the process of changing how the SD works, using this new branch of the Tympan library requires a beta version of Teensyduino…v1.54 Beta4 or later. As of this writing, they’re at v1.54 Beta 5, which is actually what I’ve been using:


So, yes, we do Teensy 4.x.


1 Like

As for your desire to strip everything away, you’re certainly welcome to do that. Interacting with any I2S audio chip is not trivial as it usually involves interacting with the DMA peripheral within the microcontroller. So, IMO, you’ll want to keep the library for the AudioInputI2S_F32 and AudioOutputI2S_F32 classes. You can simply not invoke any of the other libraries.

To get access to the audio (ie, to inject your own synthesized audio), you could use and AudioPlayQueue_F32 as I suggested. Or, you could write your own audio class, which is what I recommend. You might not be interested in figuring out the basics of doing an empty audio class, which is understandable. But, check the example sketch that has an empty one ready for your use!


When you open up the sketch in the Arduino IDE, note the second file tab. It shows the file MyAudioAlgorithm.m. Scroll down to find the function "applyMyAlgorithm(audio_block_f32_t *audio_block). In that function, there’s a whole bunch of examples showing you how to access or manipulate the audio data.

In your case, where you’re synthesizing data, you’ll simply replace all those comments with your own function call to your synthesis routines. Then, copy your samples into the audio_block (audio_block->data[i] = my_samples[i];) and you’re done!


Thanks for your help, Chip!

I’ll give it a try soon!

Also, today I’ve realized that Teensy Audio supports rates higher than 44100 on TeensyAudio for Teensy 4.x out of the box (by simply editing AUDIO_SAMPLE_RATE_EXACT in AudioStream.h), which wasn’t documented at all! It’s still 16bit tho, but for me it was a major leap forward, and I’ve managed to test higher sample rates using oscilloscope today

Once again, thanks for your help!

I’ve managed to cut all the external dependencies, build it and run without instantiating Tympan class.

And it works!

I’m a happy man now!

Next thing to try is to move my math to generate sound and integrate external controls for the oscillator from USB midi keyboard.