Audio Library

Status
Not open for further replies.
Committed mixer8 and mixer16 to github. Can anyone see a good reason for a Mixer2 and a Mixer32? Overkill? Or enabling perfectly efficient system design?
 
Committed mixer8 and mixer16 to github. Can anyone see a good reason for a Mixer2 and a Mixer32? Overkill? Or enabling perfectly efficient system design?

Sounds good to me. I would also like to see a mixer, which can be controlled by separate inputs instead of setting gain (VCA-alike).
 
I've just pushed the Mid/Side encoding/decoding components to my fork, together with a little example that widens the stereo image a little.

Committed mixer8 and mixer16 to github. Can anyone see a good reason for a Mixer2 and a Mixer32? Overkill? Or enabling perfectly efficient system design?

A mixer2 (or mixer1) would be a more neat way to set the gain of a single signal I'd say. I found the mixer4 a bit of an overkill in the Mid/Side example, but it's an easy way to control gain.
 
A mixer2 (or mixer1) would be a more neat way to set the gain of a single signal I'd say. I found the mixer4 a bit of an overkill in the Mid/Side example, but it's an easy way to control gain.

Agreed, overkill results in wasted RAM, even if not CPU time.

The solution here would be a mixer2 (which I will add), but I cant do a mixer1 because its not actually a mixer.


What we're talking about here is a single channel gain object, preferably with an additional input port to connect sine waves or similar for modulation of gain (a VCA). It could be connected inline between the sound source and the mixer (or sound output)

BUT
if you have a 16 channel mixer you dont want 16 inline gain objects, only to then run each sample through the mixer's gain as well, its a waste of juice, and incorporates mathematical noise/degradation (if that's even the correct terminology).

So the gain object principle could be applied to the mixers to create additional mixers with gain inputs per mixer channel. I'm going to let the concept ferment for a bit, though, mixers could potentially have gain, or multiply, or indeed other processes hard coded into them, but how far do you go before it's not modular anymore, and there are too many complex object types??

edit: On reflection we would only ever need to add the gain element because that is the only bit that is duplicated in the mixer, otherwise the modular route is preferred.

For now, i think a mixer2, and an inline gain object with a VCA style input would be ideal. It could be used in place of a mixer in many situations, particularly synths.
 
Last edited:
Agreed.

A gain component with VCA is already present I think (the multiply effect). However, it doesn't have a static multiplier (e.g. setGain(float))... To me it seemed adding the SynthDC object purely for that constant VCA signal is overkill, and a simple constant gain component would be more efficient.
The mixer2 would come close enough to that constant situation I guess.
 
Great, thx!

The audio designer is pretty simple I discovered... All required data should be in list.html and you can copy/paste the required data of a similar object.
 
Way ahead of you!

mixertypes.jpg

<commit>
 
@Pensive, thanks for posting, I have really been enjoying your bitcrusher addition.
Word of warning, it will crash if values are at 0, maybe an idea to automatically initialize values at 44100/16?

I had a dream...
splitter.png
How hard would it be to implement this? :)
It would take us a great leap closer to dynamic patch cabling

I'm still figuring this out, but will have a try.
Thanks Paul for this great library!
Alex
 
I had a dream...
View attachment 3529
How hard would it be to implement this? :)
It would take us a great leap closer to dynamic patch cabling

Alex

I think you can do this already - the link from object to object is a pointer and there can be multiple pointers,

I have been thinking of writing a selector object that works the other way - select one of n inputs to a single output. I need this for my software defined radio project. For the radio to transmit the audio signal path has to be reconfigured. The nice thing about a selector is its computationally very cheap since you just fiddle with some pointers.

Rich
 
Last edited:
@Pensive, thanks for posting, I have really been enjoying your bitcrusher addition.
Word of warning, it will crash if values are at 0, maybe an idea to automatically initialize values at 44100/16?

I had a dream...
View attachment 3529
How hard would it be to implement this? :)
It would take us a great leap closer to dynamic patch cabling

I'm still figuring this out, but will have a try.
Thanks Paul for this great library!
Alex

I thought I'd handled all ranges of values but I'll have a look.

Re splitter you mean a dynamically assigned splitter than can be changed on the fly I assume. But all the audio connections would need to be allocated anyway, so it would be a patch to give a little more functionality, where what we really need is audio audioconnection.create and audioconnection.destroy

Would be a very easy addition though.
 
Hi!

Yes a splitter (ideally with volume control or simple on/off of each output) would enable things like in this horrible drawing, using splitters S1 and S2 to set two filters to be either in parallel or series on the fly:
unnamed.jpg
I forgot the mixer for the two signals going into filter2 but you get the idea. This would also open new doors for modulation patching, fx bypassing etc :)

Cheers
Alex
 
Hi guys,

i am new to the teensy and building a drum synth using the audio library. Because i want to synthesize cymbals which involves multiple fm modulated oscillators, filters and envelopes i would like to put all of these in its own class. Unfortunately this was not as straight forward as i hoped.
My intention was to make a compound oscillator based on multiple fm oscillators by extending audio stream. This resulted in the following error message on compilation:

Code:
In file included from Teensy_DrumMachine_v2.ino:9:0:
SynthMetallicFoundation.h:28: error: 'oscillator' is not a type
SynthMetallicFoundation.h:28: error: expected identifier before numeric constant
SynthMetallicFoundation.h:28: error: expected ',' or '...' before numeric constant

Just including Audio library classes in my class also results in the same compilation eror.

Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
//#include <AudioStream.h>

#ifndef synth_metallic_h_
#define synth_metallic_h_

class SynthMetallicFoundation //: public AudioStream
{
public:
        
        void start_oscillators()
        {          
           oscillator.begin(0.9,300,WAVEFORM_SINE); 
        }

        AudioSynthWaveform       oscillator;
        AudioMixer4              OutMixer;
        AudioConnection          patchCordMetallicFM(oscillator,0,OutMixer,0);
        
	//virtual void update(void);
private:

        

}; 
#endif

Am i missing something here ?
 
Am i missing something here ?

This isn't how the audio library works.

The objects are the components and connections between them. It doesn't work recursively. You can't build an audio library object which is internally composed of other audio library objects & connections.

To do something like that, you'd have to copy the actual code from those other objects into your new object. That code is designed to receive and transmit audio blocks, so you'd have to redesign all that code to work as 1 integrated unit. The receiving and transmitting of audio blocks is how an object communicates to the rest of the system, not how data flows within an object.

The audio library is designed to let you very easily create audio projects, using a graphical tool to define the interconnection of the objects. But inside the objects, the code is extremely optimized. The system is NOT designed for that type of easy design inside the objects. Very low-level, high optimized programming is used inside the actual objects.
 
I cant do a mixer1 because its not actually a mixer.

What we're talking about here is a single channel gain object, preferably with an additional input port to connect sine waves or similar for modulation of gain (a VCA). It could be connected inline between the sound source and the mixer (or sound output)

Yes. A VCA is needed. The current Envelope object is effectively a VCA with the control input hardwired to an ADSR (well, dAhDSR) envelope generator. There is a need for a VCA with an exposed control port.

if you have a 16 channel mixer you dont want 16 inline gain objects, only to then run each sample through the mixer's gain as well, its a waste of juice, and incorporates mathematical noise/degradation (if that's even the correct terminology).

Its not clear that there is any degradation of the signal if a mixer object channel is set to unity gain.
However, making unity-gain mixer objects (i.e. mixers which assume appropriate pre-attenuation of all inputs) would probably be useful, as these would be lighter than the existing mixer objects.

For now, i think a mixer2, and an inline gain object with a VCA style input would be ideal. It could be used in place of a mixer in many situations, particularly synths.

I agree with that conclusion.

Next question, should there be two VCA objects (one linear, one logarithmic) or one with a switchable behaviour? I suspect two separate ones, as the 'gain element' (ie a multiply operation) is linear, so the log one needs extra code.
 
View attachment 3529
How hard would it be to implement this? :)
It would take us a great leap closer to dynamic patch cabling

Having established that you mean switchable outputs, not just a simple fanout, that does seem like a useful object (although the name should reflect that).
The common configurations are individually switchable outputs, and a serial mode (one output on, all the others off), typically used with a clock (clock input advances to the next output).

That might be easier as two objects:
one called toggles (or toggles2, toggles4, toggles8, etc) with individually selectable, individual outputs using methods like enable(n) and disable(n)
and another called sequence (or sequence8, sequence16 etc) with methods like setOutput(n), advance, advance(x). x would be a signed value so advance(-1) is possible as well as advance(3) and so on. advance with no parameters is just syntactic sugar for the most common option, advance(1).
 
building a drum synth using the audio library. Because i want to synthesize cymbals which involves multiple fm modulated oscillators, filters and envelopes i would like to put all of these in its own class.
Adding an FM operator object to the audio library would be a very useful thing. You would do that by using one of the existing objects as a model, which will show you how they work internally and allow you to test how much memory and CPU is used. You can then optimize CPU usage by making goofd algorithmic choices and by appropriate use of the ARM4 Math/DSP instructions - you will find plenty of examples of that inside the library.

The Audio library source is on github, here
https://github.com/PaulStoffregen/Audio

and currently there is only one object which allows frequency modulation, so I suggest studying how that works and then using it as a basis. You will find it as AudioSynthWaveformSineModulated in synth_sine.h and synth_sine.cpp

Comparing the FM and non-FM versions of the sine object:
Code:
 AudioSynthWaveformSineModulated() : AudioStream(1, inputQueueArray), magnitude(16384) {}
Code:
 AudioSynthWaveformSine() : AudioStream(0, NULL), magnitude(16384) {}
you can see that the FM version has an input (a buffer of 128 16-bit samples) as well as an output.

Once you are familiar with how AudioSynthWaveformSineModulated works, you will be in a good position to code your own one-operator FM object.
Once that works well, look into the gui directory to see how objects are represented in the gui interface, and also add an example for the example directory.
And then send a github pull request!

My intention was to make a compound oscillator based on multiple fm oscillators by extending audio stream.
Still a good plan; make a one-operator FM object and then you (or anyone else) can compose multi-operator oscillators as they like.
 
The audio library is designed to let you very easily create audio projects, using a graphical tool to define the interconnection of the objects. But inside the objects, the code is extremely optimized. The system is NOT designed for that type of easy design inside the objects. Very low-level, high optimized programming is used inside the actual objects.

Ok clear, this also means that i cannot create "convenience" classes to aggregate multiple elements together without recursion ? This also results in the same compilation error.
A workaround is to do it procedurally but this is not as nice. (I must admit that my C++ is a bit rusty so i could just be making some rooky mistake here)

Once you are familiar with how AudioSynthWaveformSineModulated works, you will be in a good position to code your own one-operator FM object.
Once that works well, look into the gui directory to see how objects are represented in the gui interface, and also add an example for the example directory.
And then send a github pull request!

Still a good plan; make a one-operator FM object and then you (or anyone else) can compose multi-operator oscillators as they like.

I have already extended AudioSynthWaveForm for one-operator FM modulation for all waveforms and included a modulation depth control (to ease the use of single modulators for multiple carriers). Aditionally the AudioSynthEnvelope currently only processes audio data, as i needed it to modulate filter frequencies i extended it to send out the flat envelope. I still need to add an offset control to this.

The switch class discussed above and constants also sound quite usefull to me if i have some time i'll look into it.

After some cleanup i'll post it on GitHub somewhere this week.
 
@Pensive, thanks for posting, I have really been enjoying your bitcrusher addition.
Word of warning, it will crash if values are at 0, maybe an idea to automatically initialize values at 44100/16?

OK, code is in place to catch zeroes, and always has been.

bitcrusher limits values to 1-15, anything below 1 becomes 1, anything above 15 becomes 15. 0 would effectively mute the output so rather pointless.

samplerate does similiar, anything below 1 becomes 1, max is similarly limited 44100.

but it might be this:
Code:
sampleRate = 1;
sampleStep = 44100 / sampleRate; // calculate the number of samples to duplicate as we reduce the samplerate.

not only is this divide entirely pointless ( i believe I wrote this a little inebriated at 2AM =D thats just how I roll on a saturday..... ), but it is pointless relative to a 128 sample buffer. the sample buffer size dictates the procedure will collect the root sample at the start of every 128 samples, this gives an effective minimum samplerate of : 344.5 Hz, based on 44100.

so any number below 344 will have the same net result regardless. But we do not want it to crash =D

Can you tell me exactly which settings cause a crash? I'm sure it's not the bitcrusher, but please do check both, I've shelved my audio board temporarily for teensy-lc testing.

I'm sure i can make a bigger sample buffer (1024 or so) to improve the reduction but I'm not sure that the additional ram usage is worth it.
 
Can you tell me exactly which settings cause a crash? I'm sure it's not the bitcrusher, but please do check both, I've shelved my audio board temporarily for teensy-lc testing.


I cannot see any reason for a crash.
samplestep = 44100 / newsquishedsampleRate;

so at 345 Hz you should get 127 or 128, below that it will go up to 129, 130, or higher but the entire process is limited also by the number of audio samples (128). So it doesn't what samperate you set below 345, you'll always get 128 sample blocks of the same sample.

I need to see it crash to fix it, can you post some code please?
 
Status
Not open for further replies.
Back
Top