mirror of
https://github.com/pschatzmann/arduino-audio-tools.git
synced 2024-09-21 10:27:27 +00:00
DRAFT support for maximilian
This commit is contained in:
parent
692302cdc5
commit
f44db7203d
@ -120,6 +120,7 @@ Dependent on the example you might need to install some of the following librari
|
||||
- [TTS](https://github.com/pschatzmann/TTS) A Text to Speach Engine
|
||||
- [flite](https://github.com/pschatzmann/arduino-flite) A Text to Speach Engine
|
||||
- [arduino-stk](https://github.com/pschatzmann/Arduino-STK) Synthesis ToolKit in C++ (STK)
|
||||
- [Maximilian](https://github.com/pschatzmann/Maximilian) cross-platform and multi-target audio synthesis and signal processing library
|
||||
- [Mozzi](https://github.com/pschatzmann/Mozzi) A sound synthesis library for Arduino
|
||||
- [ESP8266Audio](https://github.com/earlephilhower/ESP8266Audio) to play different audio Formats
|
||||
|
||||
|
29
examples/examples-maximilian/01-TestTone/01-testTone.ino
Normal file
29
examples/examples-maximilian/01-TestTone/01-testTone.ino
Normal file
@ -0,0 +1,29 @@
|
||||
#include "AudioTools.h"
|
||||
#include "AudioLibs/MaximilianDSP.h"
|
||||
|
||||
// Define output
|
||||
I2SStream out;
|
||||
Maximilian maximilian(out);
|
||||
|
||||
//This shows how the fundamental building block of digital audio - the sine wave.
|
||||
maxiOsc mySine;//One oscillator - can be called anything. Can be any of the available waveforms.
|
||||
|
||||
void setup() {//some inits
|
||||
// setup logging
|
||||
Serial.begin(115200);
|
||||
AudioLogger::instance().begin(Serial, AudioLogger::Info);
|
||||
// setup Aduio output
|
||||
auto cfg = out.defaultConfig(TX_MODE);
|
||||
out.begin(cfg);
|
||||
maxiSettings::setup(cfg.sample_rate, cfg.channels, 512);
|
||||
}
|
||||
|
||||
void play(double *output) {
|
||||
output[0]=mySine.sinewave(440);
|
||||
output[1]=output[0];
|
||||
}
|
||||
|
||||
// Arduino loop
|
||||
void loop() {
|
||||
maximilian.loop();
|
||||
}
|
32
examples/examples-maximilian/02-TwoTones/02-TwoTones.ino
Executable file
32
examples/examples-maximilian/02-TwoTones/02-TwoTones.ino
Executable file
@ -0,0 +1,32 @@
|
||||
//This examples shows another fundamental building block of digital audio - adding two sine waves together. When you add waves together they create a new wave whose amplitude at any time is computed by adding the current amplitudes of each wave together. So, if one wave has an amplitude of 1, and the other has an amplitude of 1, the new wave will be equal to 2 at that point in time. Whereas, later, if one wave has an amplitude of -1, and the other has an amplitude of 1, the new wave - the one you hear - will equal 0. This can create some interesting effects, including 'beating', when the waves interact to create a single wave that fades up and down based on the frequencies of the two interacting waves. The frequency of the 'beating' i.e. the fading in and out, is equal to the difference in frequency between the two waves.
|
||||
|
||||
#include "MaximilianDSP.h"
|
||||
|
||||
// Define output
|
||||
I2SStream out;
|
||||
Maximilian maximilian(out);
|
||||
|
||||
maxiOsc mySine,myOtherSine;//Two oscillators with names.
|
||||
|
||||
void setup() {//some inits
|
||||
// setup logging
|
||||
Serial.begin(115200);
|
||||
AudioLogger::instance().begin(Serial, AudioLogger::Info);
|
||||
|
||||
// setup Aduio output
|
||||
auto cfg = out.defaultConfig(TX_MODE);
|
||||
out.begin(cfg);
|
||||
maxiSettings::setup(cfg.sample_rate, cfg.channels, 512);
|
||||
}
|
||||
|
||||
void play(double *output) {//this is where the magic happens. Very slow magic.
|
||||
//output[0] is the left output. output[1] is the right output
|
||||
output[0]=mySine.sinewave(440)+myOtherSine.sinewave(441);//these two sines will beat together. They're now a bit too loud though..
|
||||
output[1]=output[0];
|
||||
}
|
||||
|
||||
|
||||
// Arduino loop
|
||||
void loop() {
|
||||
maximilian.loop();
|
||||
}
|
37
examples/examples-maximilian/03-AM1/03-AM1.ino
Executable file
37
examples/examples-maximilian/03-AM1/03-AM1.ino
Executable file
@ -0,0 +1,37 @@
|
||||
#include "MaximilianDSP.h"
|
||||
|
||||
// Define Arduino output
|
||||
I2SStream out;
|
||||
Maximilian maximilian(out);
|
||||
|
||||
//This shows how to use maximilian to do basic amplitude modulation. Amplitude modulation is when you multiply waves together. In maximilian you just use the * inbetween the two waveforms.
|
||||
|
||||
maxiOsc mySine,myOtherSine;//Two oscillators. They can be called anything. They can be any of the available waveforms. These ones will be sinewaves
|
||||
|
||||
void setup() {//some inits
|
||||
// setup logging
|
||||
Serial.begin(115200);
|
||||
AudioLogger::instance().begin(Serial, AudioLogger::Info);
|
||||
|
||||
// setup Aduio output
|
||||
auto cfg = out.defaultConfig(TX_MODE);
|
||||
out.begin(cfg);
|
||||
maxiSettings::setup(cfg.sample_rate, cfg.channels, 512);
|
||||
}
|
||||
|
||||
void play(double *output) {
|
||||
|
||||
// This form of amplitude modulation is straightforward multiplication of two waveforms.
|
||||
// Notice that the maths is different to when you add waves.
|
||||
// The waves aren't 'beating'. Instead, the amplitude of one is modulating the amplitude of the other
|
||||
// Remember that the sine wave has positive and negative sections as it oscillates.
|
||||
// When you multiply something by -1, its phase is inverted but it retains its amplitude.
|
||||
// So you hear 2 waves per second, not 1, even though the frequency is 1.
|
||||
output[0]=mySine.sinewave(440)*myOtherSine.sinewave(1);
|
||||
output[1]=output[0];
|
||||
}
|
||||
|
||||
// Arduino loop
|
||||
void loop() {
|
||||
maximilian.loop();
|
||||
}
|
41
examples/examples-maximilian/04-AM2/04-AM2.ino
Executable file
41
examples/examples-maximilian/04-AM2/04-AM2.ino
Executable file
@ -0,0 +1,41 @@
|
||||
#include "MaximilianDSP.h"
|
||||
|
||||
// Define Arduino output
|
||||
I2SStream out;
|
||||
Maximilian maximilian(out);
|
||||
|
||||
//This shows how to use maximilian to do basic amplitude modulation.
|
||||
//It also shows what happens when you modulate waves with waves that have frequencies over 20 hz.
|
||||
//You start to get interesting effects.
|
||||
|
||||
maxiOsc mySine,myOtherSine,myPhasor;//Three oscillators. They can be called anything. They can be any of the available waveforms.
|
||||
|
||||
|
||||
void setup() {//some inits
|
||||
// setup logging
|
||||
Serial.begin(115200);
|
||||
AudioLogger::instance().begin(Serial, AudioLogger::Info);
|
||||
|
||||
// setup Aduio output
|
||||
auto cfg = out.defaultConfig(TX_MODE);
|
||||
out.begin(cfg);
|
||||
maxiSettings::setup(cfg.sample_rate, cfg.channels, 512);
|
||||
}
|
||||
|
||||
void play(double *output) {
|
||||
|
||||
//Using the phasor we can create a ramp, and use this ramp to set the frequency of one of the waves.
|
||||
//When the frequency of the lower waveform passes over the threshold of 20hz, we start to hear two new waveforms.
|
||||
//The frequency of the first new wave is the sum of the two original waves.
|
||||
//The frequency of the second new wave is the difference of the two original waves.
|
||||
//So you hear two new waves, one going up, one going down.
|
||||
|
||||
output[0]=mySine.sinewave(440)*myOtherSine.sinewave(myPhasor.phasor(0.01,0,440));
|
||||
output[1]=output[0];
|
||||
|
||||
}
|
||||
|
||||
// Arduino loop
|
||||
void loop() {
|
||||
maximilian.loop();
|
||||
}
|
51
examples/examples-maximilian/05-FM1/05-FM1.ino
Executable file
51
examples/examples-maximilian/05-FM1/05-FM1.ino
Executable file
@ -0,0 +1,51 @@
|
||||
// One way of thinking about FM synthesis is to see it as vibrato.
|
||||
// You make a pitch, then vary it up and down at some rate.
|
||||
// You can change the speed of the pitch variation (modulation frequency), and also the amount of variation (modulation index).
|
||||
// In FM, usually only one of the waveforms - the carrier that provides the initial pitch - is sent to the output.
|
||||
// The frequency of the the carrier wave is continually adjusted at a rate equal to the frequency of the second wave (the modulator).
|
||||
// So at any given point in time, the frequency of the carrier can increase by an amount equal to the current amp of the modulator.
|
||||
// This has some interesting effects.
|
||||
|
||||
#include "MaximilianDSP.h"
|
||||
|
||||
// Define Arduino output
|
||||
I2SStream out;
|
||||
Maximilian maximilian(out);
|
||||
// Maximilian
|
||||
maxiOsc mySine,myOtherSine;//Two oscillators
|
||||
|
||||
|
||||
void setup() {//some inits
|
||||
// setup logging
|
||||
Serial.begin(115200);
|
||||
AudioLogger::instance().begin(Serial, AudioLogger::Info);
|
||||
|
||||
// setup Aduio output
|
||||
auto cfg = out.defaultConfig(TX_MODE);
|
||||
out.begin(cfg);
|
||||
maxiSettings::setup(cfg.sample_rate, cfg.channels, 512);
|
||||
}
|
||||
|
||||
void play(double *output) {
|
||||
|
||||
// In this example, the 'myOtherSine.sinewave' is at an amplitude of 1, it's original amplitude.
|
||||
// This is pretty simple and not too useful.
|
||||
//output[0]=mySine.sinewave(440*myOtherSine.sinewave(1));
|
||||
|
||||
// Perhaps you should comment out the above line and uncomment the below one instead
|
||||
// It shows how the frequency of the carrier is altered by ADDING a second waveform to its frequency value.
|
||||
// The carrier frequency is 440, and the modulation frequency is 1.
|
||||
// It also shows how the modulation index works. In this case the modulation index is 100
|
||||
// Try adjusting the modolation index. Also, try altering the modulation frequency.
|
||||
output[0]=mySine.sinewave(440+(myOtherSine.sinewave(1)*100));
|
||||
output[1]=output[0];
|
||||
|
||||
}
|
||||
|
||||
// In complex FM systems you can have lots of modulators stacked together in interesting ways, and theoretically this can make any sound.
|
||||
// John Chowning is the guy you probably want to talk to about that.
|
||||
|
||||
// Arduino loop
|
||||
void loop() {
|
||||
maximilian.loop();
|
||||
}
|
31
examples/examples-maximilian/06-FM2/06-FM2.ino
Executable file
31
examples/examples-maximilian/06-FM2/06-FM2.ino
Executable file
@ -0,0 +1,31 @@
|
||||
// Nothing much to say about this other than I like it.
|
||||
|
||||
#include "MaximilianDSP.h"
|
||||
|
||||
// Define Arduino output
|
||||
I2SStream out;
|
||||
Maximilian maximilian(out);
|
||||
// Maximilian
|
||||
maxiOsc mySine,myOtherSine,myLastSine,myPhasor;//Three oscillators
|
||||
|
||||
|
||||
void setup() {//some inits
|
||||
// setup logging
|
||||
Serial.begin(115200);
|
||||
AudioLogger::instance().begin(Serial, AudioLogger::Info);
|
||||
|
||||
// setup Aduio output
|
||||
auto cfg = out.defaultConfig(TX_MODE);
|
||||
out.begin(cfg);
|
||||
maxiSettings::setup(cfg.sample_rate, cfg.channels, 512);
|
||||
}
|
||||
|
||||
void play(double *output) {
|
||||
output[0]=mySine.sinewave(myOtherSine.sinewave(myLastSine.sinewave(0.1)*30)*440);//awesome bassline
|
||||
output[1]=output[0];
|
||||
}
|
||||
|
||||
// Arduino loop
|
||||
void loop() {
|
||||
maximilian.loop();
|
||||
}
|
51
examples/examples-maximilian/07-Counting1/07-Counting1.ino
Executable file
51
examples/examples-maximilian/07-Counting1/07-Counting1.ino
Executable file
@ -0,0 +1,51 @@
|
||||
|
||||
#include "MaximilianDSP.h"
|
||||
|
||||
// Define Arduino output
|
||||
I2SStream out;
|
||||
Maximilian maximilian(out);
|
||||
|
||||
// Maximilian
|
||||
maxiOsc mySine; // This is the oscillator we will use to generate the test tone
|
||||
maxiClock myClock; // This will allow us to generate a clock signal and do things at specific times
|
||||
double freq; // This is a variable that we will use to hold and set the current frequency of the oscillator
|
||||
|
||||
void setup() {
|
||||
// setup logging
|
||||
Serial.begin(115200);
|
||||
AudioLogger::instance().begin(Serial, AudioLogger::Info);
|
||||
|
||||
// setup audio output
|
||||
auto cfg = out.defaultConfig(TX_MODE);
|
||||
out.begin(cfg);
|
||||
maxiSettings::setup(cfg.sample_rate, cfg.channels, 512);
|
||||
|
||||
// setup maximilian
|
||||
myClock.setTicksPerBeat(1);//This sets the number of ticks per beat
|
||||
myClock.setTempo(120);// This sets the tempo in Beats Per Minute
|
||||
freq=20; // Here we initialise the variable
|
||||
}
|
||||
|
||||
void play(double *output) {
|
||||
|
||||
myClock.ticker(); // This makes the clock object count at the current samplerate
|
||||
|
||||
//This is a 'conditional'. It does a test and then does something if the test is true
|
||||
|
||||
if (myClock.tick) { // If there is an actual tick at this time, this will be true.
|
||||
|
||||
freq+=100; // DO SOMETHING
|
||||
|
||||
} // The curly braces close the conditional
|
||||
|
||||
//output[0] is the left output. output[1] is the right output
|
||||
|
||||
output[0]=mySine.sinewave(freq);//simple as that!
|
||||
output[1]=output[0];
|
||||
|
||||
}
|
||||
|
||||
// Arduino loop
|
||||
void loop() {
|
||||
maximilian.loop();
|
||||
}
|
52
examples/examples-maximilian/08-Counting2/08-Counting2.ino
Executable file
52
examples/examples-maximilian/08-Counting2/08-Counting2.ino
Executable file
@ -0,0 +1,52 @@
|
||||
// This example shows how you can create a basic counter with a phasor.
|
||||
// A phasor oscillator can create a ramp between any two values.
|
||||
// It takes three inputs - frequency, start value and stop value.
|
||||
// These are all double precision floats, so it's a continuous slide.
|
||||
// If you write it into an integer, it will round it off for you.
|
||||
// This creates a bunch of steps.
|
||||
|
||||
#include "MaximilianDSP.h"
|
||||
|
||||
// Define Arduino output
|
||||
I2SStream out;
|
||||
Maximilian maximilian(out);
|
||||
|
||||
// Maximilian
|
||||
maxiOsc myCounter,mySquare;//these oscillators will help us count and play sound
|
||||
int CurrentCount;//we're going to put the current count in this variable so that we can use it more easily.
|
||||
|
||||
|
||||
void setup() {//some inits
|
||||
// setup logging
|
||||
Serial.begin(115200);
|
||||
AudioLogger::instance().begin(Serial, AudioLogger::Info);
|
||||
|
||||
// setup audio output
|
||||
auto cfg = out.defaultConfig(TX_MODE);
|
||||
out.begin(cfg);
|
||||
maxiSettings::setup(cfg.sample_rate, cfg.channels, 512);
|
||||
}
|
||||
|
||||
void play(double *output) {
|
||||
|
||||
// Here you can see that CurrentCount is an int. It's taking the continuous output of the phasor and convering it.
|
||||
// You don't need to explicityly 'cast' (i.e. change) the value from a float to an int.
|
||||
// It happens automagically in these cases.
|
||||
|
||||
// Once every second, CurrentCount counts from 1 until it gets to 9, then resets itself.
|
||||
// When it reaches 9 it resets, so the values you get are 1-8.
|
||||
|
||||
CurrentCount=myCounter.phasor(1, 1, 9);//phasor can take three arguments; frequency, start value and end value.
|
||||
|
||||
// If we multiply the output of CurrentCount by 100, we get 100,200,300,400,500,600,700,800 in that order.
|
||||
// These become the frequency of the oscillator.
|
||||
// In this case, the oscillator is an antialiased sawtooth wave. Yum.
|
||||
output[0]=mySquare.sawn(CurrentCount*100);
|
||||
output[1]=output[0];
|
||||
|
||||
}
|
||||
|
||||
// Arduino loop
|
||||
void loop() {
|
||||
maximilian.loop();
|
||||
}
|
45
examples/examples-maximilian/08-Counting3/08-Counting3.ino
Executable file
45
examples/examples-maximilian/08-Counting3/08-Counting3.ino
Executable file
@ -0,0 +1,45 @@
|
||||
#include "MaximilianDSP.h"
|
||||
|
||||
// Define Arduino output
|
||||
I2SStream out;
|
||||
Maximilian maximilian(out);
|
||||
|
||||
// Maximilian
|
||||
maxiOsc myCounter,mySwitchableOsc;//these oscillators will help us count and make sound.
|
||||
int CurrentCount;//we're going to put the current count in this variable so that we can use it more easily.
|
||||
double myOscOutput;//we're going to stick the output here to make it easier to mess with stuff.
|
||||
|
||||
void setup() {//some inits
|
||||
// setup logging
|
||||
Serial.begin(115200);
|
||||
AudioLogger::instance().begin(Serial, AudioLogger::Info);
|
||||
|
||||
// setup audio output
|
||||
auto cfg = out.defaultConfig(TX_MODE);
|
||||
out.begin(cfg);
|
||||
maxiSettings::setup(cfg.sample_rate, cfg.channels, 512);
|
||||
}
|
||||
|
||||
void play(double *output) {
|
||||
|
||||
CurrentCount=myCounter.phasor(1, 1, 9);//phasor can take three arguments; frequency, start value and end value.
|
||||
|
||||
// here we use a conditional to make something happen at a specific time.
|
||||
|
||||
if (CurrentCount<5)//simple if statement
|
||||
|
||||
myOscOutput=mySwitchableOsc.square(CurrentCount*100);
|
||||
|
||||
else if (CurrentCount>=5)//and the 'else' bit.
|
||||
|
||||
myOscOutput=mySwitchableOsc.sinewave(CurrentCount*50);//one osc object can produce whichever waveform you want.
|
||||
|
||||
output[0]=myOscOutput;
|
||||
output[1]=output[0];
|
||||
|
||||
}
|
||||
|
||||
// Arduino loop
|
||||
void loop() {
|
||||
maximilian.loop();
|
||||
}
|
45
examples/examples-maximilian/08-Counting4/08-Counting4.ino
Executable file
45
examples/examples-maximilian/08-Counting4/08-Counting4.ino
Executable file
@ -0,0 +1,45 @@
|
||||
#include "MaximilianDSP.h"
|
||||
|
||||
// Define Arduino output
|
||||
I2SStream out;
|
||||
Maximilian maximilian(out);
|
||||
|
||||
// Maximilian
|
||||
maxiOsc myCounter,mySwitchableOsc,another;//these oscillators will help us count and make sound.
|
||||
int CurrentCount;//we're going to put the current count in this variable so that we can use it more easily.
|
||||
double myOscOutput;//we're going to stick the output here to make it easier to mess with stuff.
|
||||
int myArray[10]={100,200,300,400,300,200,100,240,640,360};
|
||||
|
||||
void setup() {//some inits
|
||||
// setup logging
|
||||
Serial.begin(115200);
|
||||
AudioLogger::instance().begin(Serial, AudioLogger::Info);
|
||||
|
||||
// setup audio output
|
||||
auto cfg = out.defaultConfig(TX_MODE);
|
||||
out.begin(cfg);
|
||||
maxiSettings::setup(cfg.sample_rate, cfg.channels, 512);
|
||||
}
|
||||
|
||||
void play(double *output) {
|
||||
|
||||
CurrentCount=myCounter.phasor(1*((another.sawn(0.1)+1)/2), 1, 9);//phasor can take three arguments; frequency, start value and end value.
|
||||
|
||||
if (CurrentCount<5) {//simple if statement
|
||||
|
||||
myOscOutput=mySwitchableOsc.square(myArray[CurrentCount]);
|
||||
}
|
||||
|
||||
else if (CurrentCount>=5) {//and the 'else' bit.
|
||||
|
||||
myOscOutput=mySwitchableOsc.sawn(myArray[CurrentCount]);//one osc object can produce whichever waveform you want.
|
||||
}
|
||||
output[0]=myOscOutput;//point me at your speakers and fire.
|
||||
output[1]=output[0];
|
||||
|
||||
}
|
||||
|
||||
// Arduino loop
|
||||
void loop() {
|
||||
maximilian.loop();
|
||||
}
|
70
examples/examples-maximilian/09-Envelopes/09-Envelopes.ino
Executable file
70
examples/examples-maximilian/09-Envelopes/09-Envelopes.ino
Executable file
@ -0,0 +1,70 @@
|
||||
//Envelopes allow you to shape the sound. The basic idea is that a sound has the following shape
|
||||
// Attack: This is how long it takes to fade up to maximum volume
|
||||
// Decay: This is how long it takes to reach the sustain level.
|
||||
// Sustain: This is the sustain level
|
||||
// Release: This is how long it takes to fade out.
|
||||
|
||||
#include "MaximilianDSP.h"
|
||||
|
||||
// Define Arduino output
|
||||
I2SStream out;
|
||||
Maximilian maximilian(out);
|
||||
|
||||
// Maximilian
|
||||
maxiOsc myCounter,mySwitchableOsc;//
|
||||
int CurrentCount;//
|
||||
double myOscOutput,myCurrentVolume;//
|
||||
maxiEnv myEnvelope;
|
||||
|
||||
|
||||
void setup() {//some inits
|
||||
// setup logging
|
||||
Serial.begin(115200);
|
||||
AudioLogger::instance().begin(Serial, AudioLogger::Info);
|
||||
|
||||
// setup audio output
|
||||
auto cfg = out.defaultConfig(TX_MODE);
|
||||
out.begin(cfg);
|
||||
maxiSettings::setup(cfg.sample_rate, cfg.channels, 512);
|
||||
|
||||
|
||||
//Timing is in ms
|
||||
myEnvelope.setAttack(0);
|
||||
myEnvelope.setDecay(1); // Needs to be at least 1
|
||||
myEnvelope.setSustain(1);
|
||||
myEnvelope.setRelease(1000);
|
||||
|
||||
}
|
||||
|
||||
void play(double *output) {
|
||||
|
||||
//notice that we feed in a value of 1. to create an envelope shape we can apply later.
|
||||
myCurrentVolume=myEnvelope.adsr(1.,myEnvelope.trigger);
|
||||
|
||||
CurrentCount=myCounter.phasor(1, 1, 9);//phasor can take three arguments; frequency, start value and end value.
|
||||
|
||||
// You'll notice that these 'if' statements don't require curly braces "{}".
|
||||
// This is because there is only one outcome if the statement is true.
|
||||
|
||||
if (CurrentCount==1) myEnvelope.trigger=1; //trigger the envelope
|
||||
|
||||
else myEnvelope.trigger=0;//release the envelope to make it fade out only if it's been triggered
|
||||
|
||||
if (CurrentCount<5)
|
||||
|
||||
myOscOutput=mySwitchableOsc.sawn(CurrentCount*100);
|
||||
|
||||
else if (CurrentCount>=5)//and the 'else' bit.
|
||||
|
||||
myOscOutput=mySwitchableOsc.sinewave(CurrentCount*50);//one osc object can produce whichever waveform you want.
|
||||
|
||||
|
||||
output[0]=myOscOutput*myCurrentVolume;//left speaker
|
||||
output[1]=output[0];
|
||||
|
||||
}
|
||||
|
||||
// Arduino loop
|
||||
void loop() {
|
||||
maximilian.loop();
|
||||
}
|
67
examples/examples-maximilian/10-Filters/10-Filters.ino
Executable file
67
examples/examples-maximilian/10-Filters/10-Filters.ino
Executable file
@ -0,0 +1,67 @@
|
||||
// Here is an example of a Maximilian filter being used.
|
||||
// There are a number of filters in Maximilian, including low and high pass filters.
|
||||
// There are also resonant filters and a state variable filter.
|
||||
|
||||
|
||||
#include "MaximilianDSP.h"
|
||||
|
||||
// Define Arduino output
|
||||
I2SStream out;
|
||||
Maximilian maximilian(out);
|
||||
|
||||
// Maximilian
|
||||
maxiOsc myCounter,mySwitchableOsc;//
|
||||
int CurrentCount;//
|
||||
double myOscOutput,myCurrentVolume, myFilteredOutput;//
|
||||
maxiEnv myEnvelope;
|
||||
maxiFilter myFilter;
|
||||
|
||||
void setup() {//some inits
|
||||
// setup logging
|
||||
Serial.begin(115200);
|
||||
AudioLogger::instance().begin(Serial, AudioLogger::Info);
|
||||
|
||||
// setup audio output
|
||||
auto cfg = out.defaultConfig(TX_MODE);
|
||||
out.begin(cfg);
|
||||
maxiSettings::setup(cfg.sample_rate, cfg.channels, 512);
|
||||
|
||||
//Timing is in ms
|
||||
myEnvelope.setAttack(0);
|
||||
myEnvelope.setDecay(1); // Needs to be at least 1
|
||||
myEnvelope.setSustain(1);
|
||||
myEnvelope.setRelease(1000);
|
||||
|
||||
}
|
||||
|
||||
void play(double *output) {
|
||||
|
||||
myCurrentVolume=myEnvelope.adsr(1.,myEnvelope.trigger);
|
||||
|
||||
CurrentCount=myCounter.phasor(1, 1, 9);//phasor can take three arguments; frequency, start value and end value.
|
||||
|
||||
// You'll notice that these 'if' statements don't require curly braces "{}".
|
||||
// This is because there is only one outcome if the statement is true.
|
||||
|
||||
if (CurrentCount==1) myEnvelope.trigger=1; //trigger the envelope
|
||||
|
||||
else myEnvelope.trigger=0;//release the envelope to make it fade out only if it's been triggered
|
||||
|
||||
myOscOutput=mySwitchableOsc.sawn(100);
|
||||
|
||||
// Below, the oscilator signals are being passed through a low pass filter.
|
||||
// The middle input is the filter cutoff. It is being controlled by the envelope.
|
||||
// Notice that the envelope is being amplified so that it scales between 0 and 1000.
|
||||
// The last input is the resonance.
|
||||
myFilteredOutput=myFilter.lores(myOscOutput,myCurrentVolume*1000,10);
|
||||
|
||||
output[0]=myFilteredOutput;//left speaker
|
||||
output[1]=output[0];
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Arduino loop
|
||||
void loop() {
|
||||
maximilian.loop();
|
||||
}
|
32
examples/examples-maximilian/11-Mixing/11-Mixing.ino
Executable file
32
examples/examples-maximilian/11-Mixing/11-Mixing.ino
Executable file
@ -0,0 +1,32 @@
|
||||
#include "MaximilianDSP.h"
|
||||
|
||||
// Define Arduino output
|
||||
I2SStream out;
|
||||
Maximilian maximilian(out);
|
||||
|
||||
// Maximilian
|
||||
maxiOsc myOsc,myAutoPanner;//
|
||||
double myStereoOutput[2];
|
||||
maxiMix myOutputs;//this is the stereo mixer channel.
|
||||
|
||||
void setup() {//some inits
|
||||
// setup logging
|
||||
Serial.begin(115200);
|
||||
AudioLogger::instance().begin(Serial, AudioLogger::Info);
|
||||
|
||||
// setup audio output
|
||||
auto cfg = out.defaultConfig(TX_MODE);
|
||||
out.begin(cfg);
|
||||
maxiSettings::setup(cfg.sample_rate, cfg.channels, 512);
|
||||
}
|
||||
|
||||
void play(double *output) {
|
||||
myOutputs.stereo(myOsc.noise(),myStereoOutput,(myAutoPanner.sinewave(1)+1)/2);//Stereo, Quad or 8 Channel. Specify the input to be mixed, the output[numberofchannels], and the pan (0-1,equal power).
|
||||
output[0]=myStereoOutput[0];//When working with mixing, you need to specify the outputs explicitly
|
||||
output[1]=myStereoOutput[1];//
|
||||
}
|
||||
|
||||
// Arduino loop
|
||||
void loop() {
|
||||
maximilian.loop();
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
//Using BPF equation from http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
|
||||
//Example contributed by Rebecca Fiebrink
|
||||
|
||||
#include "MaximilianDSP.h"
|
||||
|
||||
// Define Arduino output
|
||||
I2SStream out;
|
||||
Maximilian maximilian(out);
|
||||
|
||||
// Maximilian
|
||||
float xs[3], ys[3];
|
||||
float a0, a1, a2, b0, b1, b2;
|
||||
float f0 = 400; //THE FREQUENCY
|
||||
float Q = 1.0;
|
||||
|
||||
maxiOsc mySwitchableOsc;
|
||||
|
||||
void setup() {//some inits
|
||||
// setup logging
|
||||
Serial.begin(115200);
|
||||
AudioLogger::instance().begin(Serial, AudioLogger::Info);
|
||||
|
||||
// setup audio output
|
||||
auto cfg = out.defaultConfig(TX_MODE);
|
||||
out.begin(cfg);
|
||||
maxiSettings::setup(cfg.sample_rate, cfg.channels, 512);
|
||||
|
||||
// setup maximilian
|
||||
double w0 = 2*PI*f0/44100;
|
||||
double alpha = sin(w0)/(2*Q);
|
||||
//Band-pass reson:
|
||||
// b0 = alpha;
|
||||
// b1 = 0;
|
||||
// b2 = -1 * alpha;
|
||||
// a0 = 1 + alpha;
|
||||
// a1 = -2*cos(w0);
|
||||
// a2 = 1 - alpha;
|
||||
|
||||
//Notch:
|
||||
b0 = 1;
|
||||
b1 = -2*cos(w0);
|
||||
b2 = 1;
|
||||
a0 = 1 + alpha;
|
||||
a1 = -2*cos(w0);
|
||||
a2 = 1 - alpha;
|
||||
|
||||
//LPF:
|
||||
// b0 = (1 - cos(w0))/2;
|
||||
// b1 = 1 - cos(w0);
|
||||
// b2 = (1 - cos(w0))/2;
|
||||
// a0 = 1 + alpha;
|
||||
// a1 = -2*cos(w0);
|
||||
// a2 = 1 - alpha;
|
||||
}
|
||||
|
||||
void play(double *output) {
|
||||
xs[0] = mySwitchableOsc.sawn(400);
|
||||
ys[0] = (b0/a0)*xs[0] + (b1/a0)*xs[1] + (b2/a0)*xs[2]
|
||||
- (a1/a0)*ys[1] - (a2/a0)*ys[2];
|
||||
|
||||
*output = ys[0];
|
||||
|
||||
ys[2] = ys[1]; ys[1] = ys[0];
|
||||
xs[2] = xs[1]; xs[1] = xs[0];
|
||||
}
|
||||
|
||||
// Arduino loop
|
||||
void loop() {
|
||||
maximilian.loop();
|
||||
}
|
77
examples/examples-maximilian/14-MonoSynth/14-MonoSynth.ino
Executable file
77
examples/examples-maximilian/14-MonoSynth/14-MonoSynth.ino
Executable file
@ -0,0 +1,77 @@
|
||||
//This shows how to use maximilian to build a monophonic synth
|
||||
|
||||
#include "MaximilianDSP.h"
|
||||
|
||||
// Define Arduino output
|
||||
I2SStream out;
|
||||
Maximilian maximilian(out);
|
||||
|
||||
//These are the synthesiser bits
|
||||
maxiOsc VCO1,VCO2,LFO1,LFO2;
|
||||
maxiFilter VCF;
|
||||
maxiEnv ADSR;
|
||||
|
||||
//This is a bunch of control signals so that we can hear something
|
||||
maxiOsc timer;//this is the metronome
|
||||
int currentCount,lastCount;//these values are used to check if we have a new beat this sample
|
||||
|
||||
//and these are some variables we can use to pass stuff around
|
||||
|
||||
double VCO1out,VCO2out,LFO1out,LFO2out,VCFout,ADSRout;
|
||||
|
||||
|
||||
void setup() {//some inits
|
||||
// setup logging
|
||||
Serial.begin(115200);
|
||||
AudioLogger::instance().begin(Serial, AudioLogger::Info);
|
||||
|
||||
// setup audio output
|
||||
auto cfg = out.defaultConfig(TX_MODE);
|
||||
out.begin(cfg);
|
||||
maxiSettings::setup(cfg.sample_rate, cfg.channels, 512);
|
||||
|
||||
// setup maximilian
|
||||
|
||||
ADSR.setAttack(1000);
|
||||
ADSR.setDecay(1);
|
||||
ADSR.setSustain(1);
|
||||
ADSR.setRelease(1000);
|
||||
}
|
||||
|
||||
void play(double *output) {
|
||||
|
||||
//so this first bit is just a basic metronome so we can hear what we're doing.
|
||||
|
||||
currentCount=(int)timer.phasor(0.5);//this sets up a metronome that ticks every 2 seconds
|
||||
|
||||
|
||||
if (lastCount!=currentCount) {//if we have a new timer int this sample, play the sound
|
||||
ADSR.trigger=1;
|
||||
|
||||
cout << "tick\n";//the clock ticks
|
||||
|
||||
lastCount=0;//set lastCount to 0
|
||||
}
|
||||
|
||||
//and this is where we build the synth
|
||||
|
||||
ADSRout=ADSR.adsr(1.0,ADSR.trigger);
|
||||
|
||||
LFO1out=LFO1.sinebuf(0.2);//this lfo is a sinewave at 0.2 hz
|
||||
|
||||
VCO1out=VCO1.pulse(55,0.6);//here's VCO1. it's a pulse wave at 55 hz, with a pulse width of 0.6
|
||||
VCO2out=VCO2.pulse(110+LFO1out,0.2);//here's VCO2. it's a pulse wave at 110hz with LFO modulation on the frequency, and width of 0.2
|
||||
|
||||
|
||||
VCFout=VCF.lores((VCO1out+VCO2out)*0.5, ADSRout*10000, 10);//now we stick the VCO's into the VCF, using the ADSR as the filter cutoff
|
||||
|
||||
double finalSound=VCFout*ADSRout;//finally we add the ADSR as an amplitude modulator
|
||||
ADSR.trigger=0;
|
||||
output[0]=finalSound;
|
||||
output[1]=finalSound;
|
||||
}
|
||||
|
||||
// Arduino loop
|
||||
void loop() {
|
||||
maximilian.loop();
|
||||
}
|
97
examples/examples-maximilian/15-PolySynth/15-PolySynth.ino
Normal file
97
examples/examples-maximilian/15-PolySynth/15-PolySynth.ino
Normal file
@ -0,0 +1,97 @@
|
||||
|
||||
//This shows how to use maximilian to build a polyphonic synth.
|
||||
|
||||
#include "MaximilianDSP.h"
|
||||
|
||||
// Define Arduino output
|
||||
I2SStream out;
|
||||
Maximilian maximilian(out);
|
||||
|
||||
//These are the synthesiser bits
|
||||
maxiOsc VCO1[6],VCO2[6],LFO1[6],LFO2[6];
|
||||
maxiFilter VCF[6];
|
||||
maxiEnv ADSR[6];
|
||||
|
||||
//This is a bunch of control signals so that we can hear something
|
||||
maxiOsc timer;//this is the metronome
|
||||
int currentCount,lastCount,voice=0;//these values are used to check if we have a new beat this sample
|
||||
|
||||
//and these are some variables we can use to pass stuff around
|
||||
double VCO1out[6],VCO2out[6],LFO1out[6],LFO2out[6],VCFout[6],ADSRout[6],mix,pitch[6];
|
||||
|
||||
|
||||
void setup() {//some inits
|
||||
// setup logging
|
||||
Serial.begin(115200);
|
||||
AudioLogger::instance().begin(Serial, AudioLogger::Info);
|
||||
|
||||
// setup audio output
|
||||
auto cfg = out.defaultConfig(TX_MODE);
|
||||
out.begin(cfg);
|
||||
maxiSettings::setup(cfg.sample_rate, cfg.channels, 512);
|
||||
|
||||
// setup maximilian
|
||||
for (int i=0;i<6;i++) {
|
||||
ADSR[i].setAttack(0);
|
||||
ADSR[i].setDecay(200);
|
||||
ADSR[i].setSustain(0.2);
|
||||
ADSR[i].setRelease(2000);
|
||||
}
|
||||
}
|
||||
|
||||
void play(double *output) {
|
||||
|
||||
mix=0;//we're adding up the samples each update and it makes sense to clear them each time first.
|
||||
|
||||
//so this first bit is just a basic metronome so we can hear what we're doing.
|
||||
|
||||
currentCount=(int)timer.phasor(8);//this sets up a metronome that ticks 8 times a second
|
||||
|
||||
if (lastCount!=currentCount) {//if we have a new timer int this sample, play the sound
|
||||
|
||||
if (voice==6) {
|
||||
voice=0;
|
||||
}
|
||||
|
||||
ADSR[voice].trigger=1;//trigger the envelope from the start
|
||||
pitch[voice]=voice+1;
|
||||
voice++;
|
||||
|
||||
}
|
||||
|
||||
//and this is where we build the synth
|
||||
|
||||
for (int i=0; i<6; i++) {
|
||||
|
||||
|
||||
ADSRout[i]=ADSR[i].adsr(1.,ADSR[i].trigger);//our ADSR env is passed a constant signal of 1 to generate the transient.
|
||||
|
||||
LFO1out[i]=LFO1[i].sinebuf(0.2);//this lfo is a sinewave at 0.2 hz
|
||||
|
||||
VCO1out[i]=VCO1[i].pulse(55*pitch[i],0.6);//here's VCO1. it's a pulse wave at 55 hz, with a pulse width of 0.6
|
||||
VCO2out[i]=VCO2[i].pulse((110*pitch[i])+LFO1out[i],0.2);//here's VCO2. it's a pulse wave at 110hz with LFO modulation on the frequency, and width of 0.2
|
||||
|
||||
|
||||
VCFout[i]=VCF[i].lores((VCO1out[i]+VCO2out[i])*0.5, 250+((pitch[i]+LFO1out[i])*1000), 10);//now we stick the VCO's into the VCF, using the ADSR as the filter cutoff
|
||||
|
||||
mix+=VCFout[i]*ADSRout[i]/6;//finally we add the ADSR as an amplitude modulator
|
||||
|
||||
|
||||
}
|
||||
|
||||
output[0]=mix*0.5;//left channel
|
||||
output[1]=mix*0.5;//right channel
|
||||
|
||||
|
||||
// This just sends note-off messages.
|
||||
for (int i=0; i<6; i++) {
|
||||
ADSR[i].trigger=0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Arduino loop
|
||||
void loop() {
|
||||
maximilian.loop();
|
||||
}
|
80
examples/examples-maximilian/16-Replicant/16-Replicant.ino
Normal file
80
examples/examples-maximilian/16-Replicant/16-Replicant.ino
Normal file
@ -0,0 +1,80 @@
|
||||
|
||||
//Bizarelly, this sounds a little bit like Kraftwerk's 'Metropolis', although it isn't. Funny that.
|
||||
|
||||
#include "MaximilianDSP.h"
|
||||
|
||||
// Define Arduino output
|
||||
I2SStream out;
|
||||
Maximilian maximilian(out);
|
||||
|
||||
// Maximilian
|
||||
maxiOsc sound,bass,timer,mod,lead,lead2,leadmod;//here are the synth bits
|
||||
maxiEnv envelope, leadenvelope;//some envelopes
|
||||
maxiFilter filter, filter2;//some filters
|
||||
maxiDelayline delay;//a delay
|
||||
convert mtof;//a method for converting midi notes to frequency
|
||||
double bassout,leadout, delayout;//some variables to hold the data and pass it around
|
||||
int trigger, trigger2, newnote;//some control variables
|
||||
int currentCount,lastCount,playHead=0, currentChord=0;//some other control variables
|
||||
int pitch[8]={57,57,59,60};//the bassline for the arpeggio
|
||||
int chord[8]={0,0,7,2,5,5,0,0};//the root chords for the arpeggio
|
||||
float currentPitch,leadPitch;//the final pitch variables
|
||||
|
||||
//here's the lead line trigger array, followed by the pitches
|
||||
int leadLineTrigger[256]={1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
int leadLinePitch[15]={69,67,65,64,67,66,64,62,65,64,62,57,55,60,57};
|
||||
|
||||
|
||||
|
||||
void setup() {//some inits
|
||||
// setup logging
|
||||
Serial.begin(115200);
|
||||
AudioLogger::instance().begin(Serial, AudioLogger::Info);
|
||||
|
||||
// setup audio output
|
||||
auto cfg = out.defaultConfig(TX_MODE);
|
||||
out.begin(cfg);
|
||||
maxiSettings::setup(cfg.sample_rate, cfg.channels, 512);
|
||||
|
||||
}
|
||||
|
||||
void play(double *output) {//this is where the magic happens. Very slow magic.
|
||||
|
||||
currentCount=(int)timer.phasor(9);//this sets up a metronome that ticks every so often
|
||||
|
||||
if (lastCount!=currentCount) {//if we have a new timer int this sample, play the sound
|
||||
trigger=1;//play the arpeggiator line
|
||||
trigger2=leadLineTrigger[playHead%256];//play the lead line
|
||||
if (trigger2==1) {//if we are going to play a note
|
||||
leadPitch=mtof.mtof(leadLinePitch[newnote]);//get the next pitch val
|
||||
newnote++;//and iterate
|
||||
if (newnote>14) {
|
||||
newnote=0;//make sure we don't go over the edge of the array
|
||||
}
|
||||
}
|
||||
currentPitch=mtof.mtof(pitch[(playHead%4)]+chord[currentChord%8]);//write the frequency val into currentPitch
|
||||
playHead++;//iterate the playhead
|
||||
if (playHead%32==0) {//wrap every 4 bars
|
||||
currentChord++;//change the chord
|
||||
}
|
||||
//cout << "tick\n";//the clock ticks
|
||||
lastCount=0;//set lastCount to 0
|
||||
}
|
||||
|
||||
bassout=filter2.lores(envelope.adsr(bass.saw(currentPitch*0.5)+sound.pulse(currentPitch*0.5,mod.phasor(1)),1,0.9995, 0.25, 0.9995, 1, trigger),9250,2);//new, simple ADSR.
|
||||
leadout=filter.lores(leadenvelope.ar(lead2.saw(leadPitch*4)+lead.pulse(leadPitch+(leadmod.sinebuf(1.9)*1.5), 0.6), 0.00005, 0.999975, 50000, trigger2),5900,10);//leadline
|
||||
|
||||
delayout=(leadout+(delay.dl(leadout, 14000, 0.8)*0.5))/2;//add some delay
|
||||
|
||||
if(trigger!=0)trigger=0;//set the trigger to off if you want it to trigger immediately next time.
|
||||
|
||||
|
||||
output[0]=(bassout)/2;//sum output
|
||||
output[1]=(bassout)/2;
|
||||
|
||||
}
|
||||
|
||||
// Arduino loop
|
||||
void loop() {
|
||||
maximilian.loop();
|
||||
}
|
51
examples/examples-maximilian/20-FFT/20-FFT.ino
Normal file
51
examples/examples-maximilian/20-FFT/20-FFT.ino
Normal file
@ -0,0 +1,51 @@
|
||||
|
||||
#include "MaximilianDSP.h"
|
||||
#include "libs/maxim.h"
|
||||
|
||||
// Define Arduino output
|
||||
I2SStream out;
|
||||
Maximilian maximilian(out);
|
||||
|
||||
// Maximilian
|
||||
maxiOsc mySine, myPhasor; // This is the oscillator we will use to generate the test tone
|
||||
maxiFFT myFFT;
|
||||
|
||||
|
||||
|
||||
void setup() {
|
||||
// setup logging
|
||||
Serial.begin(115200);
|
||||
AudioLogger::instance().begin(Serial, AudioLogger::Info);
|
||||
|
||||
// setup audio output
|
||||
auto cfg = out.defaultConfig(TX_MODE);
|
||||
out.begin(cfg);
|
||||
maxiSettings::setup(cfg.sample_rate, cfg.channels, 512);
|
||||
|
||||
// setup maximilian
|
||||
myFFT.setup(1024, 512, 256);
|
||||
|
||||
}
|
||||
|
||||
void play(double *output) {
|
||||
|
||||
|
||||
float myOut=mySine.sinewave(myPhasor.phasor(0.2,100,5000));
|
||||
//output[0] is the left output. output[1] is the right output
|
||||
|
||||
if (myFFT.process(myOut)) {
|
||||
|
||||
//if you want you can mess with FFT frame values in here
|
||||
|
||||
}
|
||||
|
||||
output[0]=myOut;//simple as that!
|
||||
output[1]=output[0];
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Arduino loop
|
||||
void loop() {
|
||||
maximilian.loop();
|
||||
}
|
21
examples/examples-maximilian/Unsupported/12.SamplePlayer.cpp
Executable file
21
examples/examples-maximilian/Unsupported/12.SamplePlayer.cpp
Executable file
@ -0,0 +1,21 @@
|
||||
#include "maximilian.h"
|
||||
|
||||
maxiSample beats; //We give our sample a name. It's called beats this time. We could have loads of them, but they have to have different names.
|
||||
|
||||
void setup() {//some inits
|
||||
|
||||
beats.load("/Users/michaelgrierson/Documents/workspace/Maximilian/beat2.wav");//load in your samples. Provide the full path to a wav file.
|
||||
printf("Summary:\n%s", beats.getSummary());//get info on samples if you like.
|
||||
|
||||
}
|
||||
|
||||
void play(double *output) {//this is where the magic happens. Very slow magic.
|
||||
|
||||
//output[0]=beats.play();//just play the file. Looping is default for all play functions.
|
||||
output[0]=beats.play(0.68);//play the file with a speed setting. 1. is normal speed.
|
||||
//output[0]=beats.play(0.5,0,44100);//linear interpolationplay with a frequency input, start point and end point. Useful for syncing.
|
||||
//output[0]=beats.play4(0.5,0,44100);//cubic interpolation play with a frequency input, start point and end point. Useful for syncing.
|
||||
|
||||
output[1]=output[0];
|
||||
}
|
||||
|
32
examples/examples-maximilian/Unsupported/17.Compressor.cpp
Normal file
32
examples/examples-maximilian/Unsupported/17.Compressor.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
#include "maximilian.h"
|
||||
|
||||
maxiSample beats; //We give our sample a name. It's called beats this time. We could have loads of them, but they have to have different names.
|
||||
maxiDyn compressor; //this is a compressor
|
||||
double out;
|
||||
|
||||
void setup() {//some inits
|
||||
|
||||
beats.load("/Users/michaelgrierson/Documents/workspace/Maximilian/ofxMaxim/examples/OSX/ofMaximExample007OSX_Granular/bin/data/beat2.wav");//load in your samples. Provide the full path to a wav file.
|
||||
printf("Summary:\n%s", beats.getSummary());//get info on samples if you like.
|
||||
|
||||
compressor.setAttack(100);
|
||||
compressor.setRelease(300);
|
||||
compressor.setThreshold(0.25);
|
||||
compressor.setRatio(5);
|
||||
|
||||
//you can set these any time you like.
|
||||
|
||||
}
|
||||
|
||||
void play(double *output) {//this is where the magic happens. Very slow magic.
|
||||
|
||||
|
||||
//here, we're just compressing the file in real-time
|
||||
//arguments are input,ratio,threshold,attack,release
|
||||
out=compressor.compress(beats.play());
|
||||
|
||||
output[0]=out;
|
||||
output[1]=out;
|
||||
|
||||
}
|
||||
|
58
examples/examples-maximilian/Unsupported/18.DrumMachine.cpp
Normal file
58
examples/examples-maximilian/Unsupported/18.DrumMachine.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
#include "maximilian.h"
|
||||
|
||||
maxiSample kick,snare; //we've got two sampleplayers
|
||||
|
||||
maxiOsc timer; //and a timer
|
||||
|
||||
int currentCount,lastCount,playHead,hit[16]={1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1}; //This is the sequence for the kick
|
||||
int snarehit[16]={0,0,0,0,1,0,0,0,0,0,0,0,1,1,0,0};//This is the sequence for the snare
|
||||
|
||||
int kicktrigger,snaretrigger;
|
||||
|
||||
double sampleOut;
|
||||
|
||||
void setup() {//some inits
|
||||
|
||||
//YOU HAVE TO PROVIDE THE SAMPLES....
|
||||
|
||||
kick.load("/Users/yourusername/somewhere/kick.wav");//load in your samples. Provide the full path to a wav file.
|
||||
snare.load("/Users/yourusername/somewhere/snare.wav");//load in your samples. Provide the full path to a wav file.
|
||||
|
||||
|
||||
printf("Summary:\n%s", kick.getSummary());//get info on samples if you like.
|
||||
//beats.getLength();
|
||||
}
|
||||
|
||||
void play(double *output) {//this is where the magic happens. Very slow magic.
|
||||
|
||||
currentCount=(int)timer.phasor(8);//this sets up a metronome that ticks 8 times a second
|
||||
|
||||
|
||||
if (lastCount!=currentCount) {//if we have a new timer int this sample, play the sound
|
||||
|
||||
kicktrigger=hit[playHead%16];//get the value out of the array for the kick
|
||||
snaretrigger=snarehit[playHead%16];//same for the snare
|
||||
playHead++;//iterate the playhead
|
||||
lastCount=0;//reset the metrotest
|
||||
}
|
||||
|
||||
if (kicktrigger==1) {//if the sequence has a 1 in it
|
||||
|
||||
kick.trigger();//reset the playback position of the sample to 0 (the beginning)
|
||||
|
||||
}
|
||||
|
||||
if (snaretrigger==1) {
|
||||
|
||||
snare.trigger();//likewise for the snare
|
||||
|
||||
}
|
||||
|
||||
sampleOut=kick.playOnce()+snare.playOnce();//just play the file. No looping.
|
||||
|
||||
output[0]=sampleOut;//left channel
|
||||
output[1]=sampleOut;//right channel
|
||||
|
||||
kicktrigger = 0;//set trigger to 0 at the end of each sample to guarantee retriggering.
|
||||
snaretrigger = 0;
|
||||
}
|
55
examples/examples-maximilian/Unsupported/19.Enveloping2.cpp
Normal file
55
examples/examples-maximilian/Unsupported/19.Enveloping2.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
#include "maximilian.h"
|
||||
|
||||
//this tutorial explains how to use the maxiEnv
|
||||
|
||||
maxiSample sound1;
|
||||
|
||||
maxiOsc timer,snarePhase; //and a timer
|
||||
|
||||
maxiEnv envelope;//this is going to be an envelope
|
||||
|
||||
int currentCount,lastCount,playHead,
|
||||
|
||||
sequence[16]={1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0}; //This is the sequence for the kick
|
||||
|
||||
int sampleTrigger;
|
||||
|
||||
double sampleOut;
|
||||
|
||||
void setup() {//some inits
|
||||
|
||||
//YOU HAVE TO PROVIDE THE SAMPLES....
|
||||
|
||||
sound1.load("/Users/mickgrierson/Documents/audio/68373__juskiddink__Cello_open_string_bowed.wav");//load in your samples. Provide the full path to a wav file.
|
||||
|
||||
|
||||
printf("Summary:\n%s", sound1.getSummary());//get info on samples if you like.
|
||||
//beats.getLength();
|
||||
}
|
||||
|
||||
void play(double *output) {//this is where the magic happens. Very slow magic.
|
||||
|
||||
currentCount=(int)timer.phasor(8);//this sets up a metronome that ticks 8 times a second
|
||||
|
||||
|
||||
if (lastCount!=currentCount) {//if we have a new timer int this sample, play the sound
|
||||
|
||||
sampleTrigger=sequence[playHead%16];
|
||||
playHead++;//iterate the playhead
|
||||
lastCount=0;//reset the metrotest
|
||||
|
||||
}
|
||||
|
||||
//the envelope we're using here is an AR envelope.
|
||||
//It has an input (which in this case is a sound)
|
||||
//It has an attack coefficient, a hold val (in samples)
|
||||
//and a release coefficient. Finally, it has a trigger input.
|
||||
//If you stick a 1 in the trigger input, it retriggers the envelope
|
||||
sampleOut=envelope.ar(sound1.play(1.), 0.1, 0.9999, 1, sampleTrigger); //
|
||||
|
||||
output[0]=sampleOut;//left channel
|
||||
output[1]=sampleOut;//right channel
|
||||
|
||||
sampleTrigger = 0;//set trigger to 0 at the end of each sample to guarantee retriggering.
|
||||
|
||||
}
|
57
examples/examples-maximilian/Unsupported/21.Recording.cpp
Normal file
57
examples/examples-maximilian/Unsupported/21.Recording.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
#include "maximilian.h"
|
||||
|
||||
// Here we define a double floating value that will contain our
|
||||
// frame of lovely maximilian generated audio
|
||||
double out;
|
||||
|
||||
// Our oscillator to fill our frame up with my favourite wave
|
||||
maxiOsc osc;
|
||||
|
||||
// Our ramp to modulate the oscillators
|
||||
maxiOsc ramp;
|
||||
|
||||
// We declare our recorder object here, which will call it's
|
||||
// default constructor.
|
||||
maxiRecorder recorder;
|
||||
|
||||
void setup() {
|
||||
|
||||
// Call setup here, make sure you do this so the recorder
|
||||
// knows where to write the file. Currently the recorder
|
||||
// will write the wav file to the directory that this file
|
||||
// is in if you use linux but with mac and windows I
|
||||
// strongly reccomend putting an absolute file path to the
|
||||
// directory you want to write to. Also, when in Windows,
|
||||
// remember to do double '\' characters because they
|
||||
// count as an escape which will nullify any path you write
|
||||
recorder.setup("lovesong.wav");
|
||||
|
||||
// This must be called to start the asynchronous thread to
|
||||
// manage the recorder's internal memory
|
||||
recorder.startRecording();
|
||||
}
|
||||
|
||||
void play(double *output) {
|
||||
|
||||
// A pulse wave!!! Yay
|
||||
out = osc.pulse(90, ramp.phasor(.2));
|
||||
|
||||
// Fill our output buffer
|
||||
output[0]=out;
|
||||
output[1]=out;
|
||||
|
||||
// After we have filled our output array, send the array
|
||||
// and the size of the array (in this case the amount of
|
||||
// channels, but in ofx or juce you might need to do
|
||||
// something like channels*bufferSize).
|
||||
recorder.passData(output, maxiSettings::channels);
|
||||
}
|
||||
|
||||
// We don't need to worry about telling the recorder to stop;
|
||||
// when the stack unwinds and the maximillian program stops,
|
||||
// the recorder will have its destructor called and the wav
|
||||
// will be written for you. If you would like to do something
|
||||
// more dynamic, look at the class definition in maximilian.h -
|
||||
// the api allows for stricter control of the object.
|
||||
|
||||
|
68
src/AudioLibs/maximilian/MaximilianDSP.h
Normal file
68
src/AudioLibs/maximilian/MaximilianDSP.h
Normal file
@ -0,0 +1,68 @@
|
||||
#pragma once
|
||||
#include "AudioConfig.h"
|
||||
#include "maximilian.h"
|
||||
|
||||
// Maximilian play function - return an array of 2 channels
|
||||
void play(double *channels);//run dac!
|
||||
|
||||
namespace audio_tools {
|
||||
|
||||
/**
|
||||
* @brief AudioTools integration with Maximilian
|
||||
*
|
||||
*/
|
||||
class Maximilian {
|
||||
public:
|
||||
|
||||
Maximilian(Print &out, int bufferSize=DEFAULT_BUFFER_SIZE){
|
||||
buffer_size = bufferSize;
|
||||
p_buffer = new uint8_t[bufferSize];
|
||||
p_sink = &out;
|
||||
}
|
||||
|
||||
~Maximilian() {
|
||||
delete[] p_buffer;
|
||||
}
|
||||
|
||||
/// Setup Maximilian with audio parameters
|
||||
void begin(AudioBaseInfo cfg){
|
||||
maxiSettings::setup(cfg.sample_rate, cfg.channels, DEFAULT_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
/// Defines the volume. The values are between 0.0 and 1.0
|
||||
void setVolume(float f){
|
||||
volume = f;
|
||||
if (volume>1){
|
||||
volume = 1;
|
||||
}
|
||||
if (volume<0){
|
||||
volume = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// Copies the audio data from maximilian to the audio sink, Call this method from the Arduino Loop.
|
||||
void copy() {
|
||||
// fill buffer with data
|
||||
double out[2];
|
||||
uint16_t samples = buffer_size / sizeof(uint16_t);
|
||||
int16_t *p_samples = (int16_t *)p_buffer;
|
||||
for (uint16_t j=0;j<samples;j+=2){
|
||||
play(out);
|
||||
// convert to int16
|
||||
p_samples[j] = out[0]*32767*volume;
|
||||
p_samples[j+1] = out[1]*32767*volume;
|
||||
}
|
||||
// write buffer to audio sink
|
||||
unsigned int result = p_sink->write(p_buffer, buffer_size);
|
||||
LOGI("bytes written %u", result)
|
||||
}
|
||||
|
||||
protected:
|
||||
uint8_t *p_buffer=nullptr;
|
||||
float volume=1.0;
|
||||
int buffer_size=256;
|
||||
Print *p_sink=nullptr;
|
||||
};
|
||||
|
||||
|
||||
} // namespace
|
@ -160,7 +160,7 @@ class IIR : public Filter<T> {
|
||||
* @tparam T
|
||||
*/
|
||||
template <typename T>
|
||||
class BiQuadDF1 : public Filter<float> {
|
||||
class BiQuadDF1 : public Filter<T> {
|
||||
public:
|
||||
BiQuadDF1(const T (&b)[3], const T (&a)[3])
|
||||
: b_0(b[0] / a[0]),
|
||||
|
Loading…
Reference in New Issue
Block a user