Floating-Point Audio Library Extension

I haven't been the one maintaining the OpenAudio library...I haven't been the maintainer for years and years, so its examples look quite different than I remember them. I'm having difficulty finding an example that uses AudioSettings to change the sample rate or block size. That's unfortunate.

Back when I wrote the original version of the library, you had to pass your AudioSettings to each audio class via its constructor when you were instantiating it. I am assuming that this is still true for the OpenAudio library, but I could be wrong.

Looking at your code, I see that you create the AudioSettings but that you do not pass it to your other audio classes when creating them. So, I would suggest changing your two instantiating lines to be:

Code:
AudioOutputI2S_F32 i2sOut(audio_settings);
AudioSynthWaveformSine_F32 sine(audio_settings);

If that alone doesn't work, I would also suggest that you try adding the I2S input block, even if you don't connect it to anything. My memory from long ago is that it sometimes it is involved with certain timing events. So, try adding:

Code:
AudioInputI2S_F32 i2sIn(audio_settings);

Good luck!

Chip
 
Looking at your code, I see that you create the AudioSettings but that you do not pass it to your other audio classes when creating them. So, I would suggest changing your two instantiating lines to be:
Thank for pointing it out, but it's a code which illustrated a different problem. Later I corrected it as you suggested, yet it did not work.

As for getting rid of these direct references to AUDIO_BLOCK_SAMPLES in F32, it makes sense, but I have one doubt. Small values may evidently cause considerable overhead. However, for small AUDIO_BLOCK_SAMPLES like 4, a compiler may tend to unroll loops, which may at least partially alleviate that overhead.

Thus, I would suggest first testing this by modifying #define AUDIO_BLOCK_SAMPLES 4 to extern int AUDIO_BLOCK_SAMPLES; and assigning 4 to the latter somewhere in the code. Then, profile both variants in order to compare the CPU usage. If the difference is small, that seems ok, as F32 may evidently come with some overhead in exchange for precision and flexibility.
 
Hopefully I'm in the right place to ask this question.

I'm trying to get AudioEffectPlateReverb_F32 working.
I've got a small design that starts with oscillators and envelopes in I16 space and sends it through the converters to F32 space, through the reverb (verb_F32) and then back through a set of converters back to I16 space and out the i2s outputs.
The audio is making it through the design and is unmolested when the verb_F32.mix() is set to zero.
But when the mix is turned up the reverb sort of clips the leading and trailing edges of the notes making almost a click noise. I can here the reverb reverberating while the sound is there, but the amplitude is all one level, there are no tails and just abruptly cuts the sound off.

I would expect the reverb to ring out longer, but maybe I'm misunderstanding what the plate reverb does.

the attached sketch just sets up the simple design then loops through turning on and off the envelops, changing the mix value after every four notes with mix values of 0.0, 0.5, and 1.0 and repeats.
1730263078709.png
 

Attachments

  • tad2.ino
    7.9 KB · Views: 31
I think i know what is causing it. I've always used the reverb in real time processing, using the i2s input. It ensures there is always a stream of input data. An oscillator + envelope send Null blocks of audio data when the Note is off and that is breaking the Reverb, it cuts off once there is no incoming audio data. Needs better null block handling.

I have just pushed the fix to the

also tested your example on my hardware. Should work fine now.
 
I think i know what is causing it. I've always used the reverb in real time processing, using the i2s input. It ensures there is always a stream of input data. An oscillator + envelope send Null blocks of audio data when the Note is off and that is breaking the Reverb, it cuts off once there is no incoming audio data. Needs better null block handling.

I have just pushed the fix to the

also tested your example on my hardware. Should work fine now.
Wow! thanks! that was fast!

The tails are coming through now.
There is still a click when the note off happens if the tails are still ringing.

Also, I haven't tried it but will the spring reverb also have this same issue?
 
Also, I haven't tried it but will the spring reverb also have this same issue?
A quick code inspection suggests “yes”. This is a perennial issue with audio objects, unfortunately.

Inspecting your fix for plate reverb, I think you still have a potential bug. The same silent block is used for both left and right inputs if a null block is received, but since it’s supposed to be stereo I think possibly you should check each individually and allocate and zero a block if needed. Not 100% sure, haven’t checked the code thoroughly.
 
Inspecting your fix for plate reverb, I think you still have a potential bug. The same silent block is used for both left and right inputs if a null block is received, but since it’s supposed to be stereo I think possibly you should check each individually and allocate and zero a block if needed. Not 100% sure, haven’t checked the code thoroughly.
You are right. The blocks are writable, each channel needs a separate block of silence to be processed. I have a fix, just needs a bit more testing.
Will push it next week.
 
I was looking for a neat solution for the bypass system. Came up with a new function which takes pointers to the received or created audio blocks, checks them against NULL and generates silence blocks if necessary. This way the same bypass function can be used to validate the inputs and generate zeroed blocks, depending on the bypass mode. The component's update method can then decide whether to transmit the blocks directly and return (bypass is engaged) or to process them further and trasmit later (bypass disengaged).
There are 3 modes for bypass:
  1. BYPASS_MODE_PASS - classic bypass where the inpuit is routed directly to the output. With NULL input blocks it tries to allocate new ones and zeroes the data block. This mode is used as input validation.
  2. BYPASS_MODE_OFF - the output is muted (sends silence) when bypassed. Useful when buiding parallel effect loops with mixers.
  3. BYPASS_MODE_TRAILS - this one mutes the input only, feeding the effect with silence. Used for reverbs/delays to let them naturally fade out. Disadvatage is it loads the CPU as if the effect was always ON.
Plate, spring and SC reverbs and the stereo ping-pong delay are now updated with the new bypass system and should work fine with envelope.

The tails are coming through now.
There is still a click when the note off happens if the tails are still ringing.
I can't hear any clicks and i've tried your example with the new bypass. Also noticed you have a very low amplitude set for the oscillator (0.04f).
 
I can't hear any clicks and i've tried your example with the new bypass. Also noticed you have a very low amplitude set for the oscillator (0.04f).
It sounds great now--no clicks at all.
I had oscillator at 0.04 because it was super loud into a pair of old apple earbuds (i mistakenly had it at 1.0 first and OUCH!)-- I should have changed sgtl5000_1.volume(0.80) down instead.
Anyway, thank you so much for this! It really solved a the dynamic range problem with 16bit freeverbs.
 
If you're interested in having floating-point audio blocks, this feature has recently been added to the Aviate Audio Multiverse software. It's a wrapper around the Teensy Audio library and runs on a Teensy MicroMod with the intent of making it easy to write your own Teensy audio effects and have them run on a guitar stomp box with professional UI.

If you use the Multiverse software package it adds some key stuff:
- floating point support via audio_block_float32_t, allocateFloat(), receiveReadOnlyFloat(), etc.
- graphical interface for building multiple audio chain presets in any order,and ability to bypass and control them in realtime

I also wrote BALibray, my own extention to the Audio library, and I have support for the Multiverse hardware so you can also just use the hardware as regular Teensy with the Arduino IDE, Platform IO, whatever, etc. if you wish. The Multiverse actually started as this and just kinda exploded from there.
 
Back
Top