aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormick grierson <mickgrierson@gmail.com>2015-08-27 13:33:41 +0100
committermick grierson <mickgrierson@gmail.com>2015-08-27 13:33:41 +0100
commit5b37d13616c303538a61b520e6930b322e4ff378 (patch)
treea616325e9bdd71ba22fd22ad419963035322e8a0
parentb155008277cbdba3534ca392d67e2db199d9c458 (diff)
redoing tutorials a bit
-rwxr-xr-xmain.cpp112
-rw-r--r--maximilian.cpp1
-rw-r--r--maximilianTest.xcodeproj/project.xcworkspace/xcuserdata/michaelgrierson.xcuserdatad/UserInterfaceState.xcuserstatebin89334 -> 60853 bytes
-rwxr-xr-xmaximilian_examples/1.TestTone.cpp13
-rwxr-xr-xmaximilian_examples/10.Filters.cpp59
-rwxr-xr-xmaximilian_examples/11.Mixing.cpp40
-rwxr-xr-xmaximilian_examples/14.monosynth.cpp2
-rw-r--r--maximilian_examples/15.polysynth.cpp6
-rwxr-xr-xmaximilian_examples/2.TwoTones.cpp11
-rwxr-xr-xmaximilian_examples/3.AM1.cpp16
-rwxr-xr-xmaximilian_examples/4.AM2.cpp18
-rwxr-xr-xmaximilian_examples/5.FM1.cpp28
-rwxr-xr-xmaximilian_examples/6.FM2.cpp10
-rwxr-xr-xmaximilian_examples/7.Counting.cpp26
-rwxr-xr-xmaximilian_examples/9.Envelopes.cpp60
15 files changed, 230 insertions, 172 deletions
diff --git a/main.cpp b/main.cpp
index e3e50cb..5cfdb74 100755
--- a/main.cpp
+++ b/main.cpp
@@ -1,81 +1,65 @@
#include "maximilian.h"
-//This shows how to use maximilian to build a polyphonic synth.
-
-//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];
-
+double outputs[2],moreoutputs[2]; //some track outputs
+double filtered,patch1,patch2,tune,delayed,
+mixed,ramp,filtered2,noise,pan,more;//a bunch of patch cables
+int beat,lastbeat,morebeats,lastmorebeats;//some rhythmic elemts
+double env[4]={200,0,0,50};//the kick drum pitch envelope data
+double env2[6]={10000,0,9000,5,0,5};//the hi hat pitch envelope dat
+double melody[14]={600,0,0,650,0,0,400,0,0,425,0,300,0,315};//the melody data
+int rhythm1[16]={1,0,0,1,0,0,1,0,0,1,0,0,1,0,1,0};//another way of doing a rhythm
+maxiOsc a,c,d,e,g,h,i,j,squarewave;//some oscillators
+maxiEnvelope b,f;//two envelopers
+maxiDelayline delay;//a delay line
+maxiFilter myfilter,antia;// a FAT filter
+maxiMix mymix,bobbins;//some panning busses
+maxiSample beats;
void setup() {//some inits
+ b.amplitude=env[0];//starting value for envelope b
+ f.amplitude=env2[0];//same for f
+ beats.load("/Users/michaelgrierson/Documents/workspace/Maximilian/beat2.wav");//put a path to a soundfile here. Wav format only.
- 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.
+void play(double *output) {//this is where the magic happens. Very slow magic.
+ beat=((int) c.phasor(8));//this oscillator is now a counter
+ morebeats=((int) e.phasor(0.5,0,16));//so is this one
+ patch1=b.line(4,env);//here's envelope b
+ patch2=f.line(6,env2);//here's envelop f
+ tune=g.saw(melody[morebeats]*0.25);//here's the melody, which occurs at certain times
- 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;
- }
+ if (lastbeat!=beat) {//this is a nice sample and hold routine for the kick drum
+ f.trigger(0, env2[0]);//it runs off the hi hat.
- ADSR[voice].trigger=1;//trigger the envelope from the start
- pitch[voice]=voice+1;
- voice++;
+ if (rhythm1[morebeats]==1) {
+ b.trigger(0, env[0]);//and gets played when it's time.
+ }
}
+ lastbeat=beat;//let's start again. It's a loop
+ ramp=i.phasor(0.5,1,2048);//create a basic ramp
+ pan=j.phasor(0.25);//some panning from a phasor (object is equal power)
+ delayed=delay.dl(tune, ramp, 0.9)*0.125;//the delay line
+ //then it all gets mixed.
+ mixed=((a.sinewave(patch1)*0.5)+((d.saw(patch2))*0.125)+(delayed*0.3)*0.5);
+ //add some noise
+ noise=i.noise()*0.25;
+ filtered2=beats.play(1*(1./16.),0,beats.length);
+ // filtered2=beats.play(-1);
- //and this is where we build the synth
+ more=squarewave.pulse(melody[morebeats],pan)*0.05;
+ //filter the noise! this lores takes values between 1 and 100 for res, and freq for cutoff.
+ filtered=myfilter.lores(filtered2, 1+(pan*10000), 10)*0.4;
- 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
-
-
- }
+ //now we send the sounds to some stereo busses.
+ mymix.stereo(more+mixed+delayed, outputs, 1-pan);
+ bobbins.stereo(filtered, moreoutputs, pan);//invert the pan
- output[0]=mix*0.5;//left channel
- output[1]=mix*0.5;//right channel
-
+ //mixing
- // This just sends note-off messages.
- for (int i=0; i<6; i++) {
- ADSR[i].trigger=0;
- }
+ output[0]=outputs[0]+moreoutputs[0]/10;//stick it in the out!!
+ output[1]=outputs[1]+moreoutputs[1]/10;
}
+
diff --git a/maximilian.cpp b/maximilian.cpp
index 7ba4978..1a79129 100644
--- a/maximilian.cpp
+++ b/maximilian.cpp
@@ -432,6 +432,7 @@ double maxiFilter::lopass(double input, double cutoff) {
outputs[0]=output;
return(output);
}
+
//as above
double maxiFilter::hipass(double input, double cutoff) {
output=input-(outputs[0] + cutoff*(input-outputs[0]));
diff --git a/maximilianTest.xcodeproj/project.xcworkspace/xcuserdata/michaelgrierson.xcuserdatad/UserInterfaceState.xcuserstate b/maximilianTest.xcodeproj/project.xcworkspace/xcuserdata/michaelgrierson.xcuserdatad/UserInterfaceState.xcuserstate
index 8959558..ec304f1 100644
--- a/maximilianTest.xcodeproj/project.xcworkspace/xcuserdata/michaelgrierson.xcuserdatad/UserInterfaceState.xcuserstate
+++ b/maximilianTest.xcodeproj/project.xcworkspace/xcuserdata/michaelgrierson.xcuserdatad/UserInterfaceState.xcuserstate
Binary files differ
diff --git a/maximilian_examples/1.TestTone.cpp b/maximilian_examples/1.TestTone.cpp
index 77783b4..b8da07c 100755
--- a/maximilian_examples/1.TestTone.cpp
+++ b/maximilian_examples/1.TestTone.cpp
@@ -1,14 +1,19 @@
+//This example shows how to create one of the most fundamental building blocks in computer audio. The sine wave.
+//The sine wave is an oscillator - it oscillates back and forth between two values in a particular shape.
+
+
#include "maximilian.h"
maxiOsc mySine;//let's create an oscillator and give it a name.
void setup() {//some inits
- //nothing to go here this time
+ //nothing to go here this time
}
void play(double *output) {//this is where the magic happens. Very slow magic.
-
- *output=mySine.sinewave(440);//simple as that!
-
+
+ //output[0] is the left output. output[1] is the right output
+ output[0]=mySine.sinewave(440);//simple as that!
+
}
diff --git a/maximilian_examples/10.Filters.cpp b/maximilian_examples/10.Filters.cpp
index b80b512..41e779a 100755
--- a/maximilian_examples/10.Filters.cpp
+++ b/maximilian_examples/10.Filters.cpp
@@ -1,33 +1,48 @@
+// 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 "maximilian.h"
maxiOsc myCounter,mySwitchableOsc;//
int CurrentCount;//
-double myOscOutput,myFilteredOutput;//
-double myEnvelopeData[6] = {500,0,1000,500,0,500};//this data will be used to make an envelope. Value and time to value in ms.
-maxiEnvelope myEnvelope;
+double myOscOutput,myCurrentVolume, myFilteredOutput;//
+maxiEnv myEnvelope;
maxiFilter myFilter;
void setup() {//some inits
- myEnvelope.amplitude=myEnvelopeData[0]; //initialise the envelope
+
+ //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) {
-
- CurrentCount=myCounter.phasor(1, 1, 9);//phasor can take three arguments; frequency, start value and end value.
-
- if (CurrentCount<5)//simple if statement
-
- myOscOutput=mySwitchableOsc.square(CurrentCount*100);
-
- else if (CurrentCount>=5)//and the 'else' bit.
-
- myOscOutput=mySwitchableOsc.saw(CurrentCount*50);//one osc object can produce whichever waveform you want.
-
- if (CurrentCount==1)
-
- myEnvelope.trigger(0,myEnvelopeData[0]); //trigger the envelope
-
- myFilteredOutput=myFilter.lores(myOscOutput,(myEnvelope.line(6, myEnvelopeData)),10);//lores takes an audio input, a frequency and a resonance factor (1-100)
-
- *output=myFilteredOutput;//point me at your speakers and fire.
+
+ 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
+
}
diff --git a/maximilian_examples/11.Mixing.cpp b/maximilian_examples/11.Mixing.cpp
index 6fd7a34..8f6e33c 100755
--- a/maximilian_examples/11.Mixing.cpp
+++ b/maximilian_examples/11.Mixing.cpp
@@ -1,40 +1,18 @@
#include "maximilian.h"
-maxiOsc myCounter,mySwitchableOsc,myAutoPanner;//
-int CurrentCount;//
-double myOscOutput,myFilteredOutput,myPanPosition;//
-double myStereoOutput[2];// we need an output for each channel.
-double myEnvelopeData[6] = {500,0,1000,500,0,500};//this data will be used to make an envelope. Value and time to value in ms.
-maxiEnvelope myEnvelope;
-maxiFilter myFilter;
+maxiOsc myOsc,myAutoPanner;//
+double myStereoOutput[2];
maxiMix myOutputs;//this is the stereo mixer channel.
void setup() {//some inits
- myEnvelope.amplitude=myEnvelopeData[0]; //initialise the envelope
+
}
void play(double *output) {
-
- CurrentCount=myCounter.phasor(1, 1, 9);//phasor can take three arguments; frequency, start value and end value.
-
- if (CurrentCount<5)//simple if statement
-
- myOscOutput=mySwitchableOsc.square(CurrentCount*100);
-
- else if (CurrentCount>=5)//and the 'else' bit.
-
- myOscOutput=mySwitchableOsc.saw(CurrentCount*50);//one osc object can produce whichever waveform you want.
-
- if (CurrentCount==1)
-
- myEnvelope.trigger(0,myEnvelopeData[0]); //trigger the envelope
-
- myFilteredOutput=myFilter.lores(myOscOutput,(myEnvelope.line(6, myEnvelopeData)),10);//lores takes an audio input, a frequency and a resonance factor (1-100)
-
- myPanPosition=myAutoPanner.sinewave(1);
-
- myOutputs.stereo(myFilteredOutput,myStereoOutput,myPanPosition);//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 explicityly
- output[1]=myStereoOutput[1];//
-
+
+
+ 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];//
+
}
diff --git a/maximilian_examples/14.monosynth.cpp b/maximilian_examples/14.monosynth.cpp
index 897c41a..265e3e4 100755
--- a/maximilian_examples/14.monosynth.cpp
+++ b/maximilian_examples/14.monosynth.cpp
@@ -42,7 +42,7 @@ void play(double *output) {
//and this is where we build the synth
- ADSRout=ADSR.adsr(1.0,ADSR.trigger);//our ADSR env has 8 value/time pairs.
+ ADSRout=ADSR.adsr(1.0,ADSR.trigger);
LFO1out=LFO1.sinebuf(0.2);//this lfo is a sinewave at 0.2 hz
diff --git a/maximilian_examples/15.polysynth.cpp b/maximilian_examples/15.polysynth.cpp
index 3e278cb..fefc261 100644
--- a/maximilian_examples/15.polysynth.cpp
+++ b/maximilian_examples/15.polysynth.cpp
@@ -47,8 +47,6 @@ void play(double *output) {
pitch[voice]=voice+1;
voice++;
- lastCount=0;
-
}
//and this is where we build the synth
@@ -56,7 +54,7 @@ void play(double *output) {
for (int i=0; i<6; i++) {
- ADSRout[i]=ADSR[i].adsr(1.,ADSR[i].trigger);//our ADSR env has 8 value/time pairs.
+ 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
@@ -74,6 +72,8 @@ void play(double *output) {
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;
}
diff --git a/maximilian_examples/2.TwoTones.cpp b/maximilian_examples/2.TwoTones.cpp
index 4e22994..fb29288 100755
--- a/maximilian_examples/2.TwoTones.cpp
+++ b/maximilian_examples/2.TwoTones.cpp
@@ -1,14 +1,17 @@
+//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 "maximilian.h"
maxiOsc mySine,myOtherSine;//Two oscillators with names.
void setup() {//some inits
- //nothing to go here this time
+ //nothing to go here this time
}
void play(double *output) {//this is where the magic happens. Very slow magic.
-
- *output=mySine.sinewave(440)+myOtherSine.sinewave(441);//these two sines will beat together. They're now a bit too loud though..
-
+
+ //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..
+
}
diff --git a/maximilian_examples/3.AM1.cpp b/maximilian_examples/3.AM1.cpp
index ec96c7f..384a7f5 100755
--- a/maximilian_examples/3.AM1.cpp
+++ b/maximilian_examples/3.AM1.cpp
@@ -1,15 +1,21 @@
#include "maximilian.h"
-//This shows how to use maximilian to do basic amplitude modulation
+//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
- //nothing to go here this time
+ //nothing to go here this time
}
void play(double *output) {
-
- *output=mySine.sinewave(440)*myOtherSine.sinewave(10);
-
+
+ // 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);
+
}
diff --git a/maximilian_examples/4.AM2.cpp b/maximilian_examples/4.AM2.cpp
index 4e783d3..7e80f38 100755
--- a/maximilian_examples/4.AM2.cpp
+++ b/maximilian_examples/4.AM2.cpp
@@ -1,16 +1,24 @@
#include "maximilian.h"
-//This shows how to use maximilian to do basic amplitude modulation
+//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
- //nothing to go here this time
+ //nothing to go here this time
}
void play(double *output) {
-
- *output=mySine.sinewave(440)*myOtherSine.sinewave(myPhasor.phasor(0.1,0,440));
-
+
+ //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));
+
}
diff --git a/maximilian_examples/5.FM1.cpp b/maximilian_examples/5.FM1.cpp
index c734dcf..14f6593 100755
--- a/maximilian_examples/5.FM1.cpp
+++ b/maximilian_examples/5.FM1.cpp
@@ -1,14 +1,34 @@
+// 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 "maximilian.h"
maxiOsc mySine,myOtherSine;//Two oscillators
void setup() {//some inits
- //nothing to go here this time
+ //nothing to go here this time
}
void play(double *output) {
-
- *output=mySine.sinewave(myOtherSine.sinewave(1)*440);
-
+
+ // 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));
+
}
+
+// 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. \ No newline at end of file
diff --git a/maximilian_examples/6.FM2.cpp b/maximilian_examples/6.FM2.cpp
index d9acd72..d9eddf5 100755
--- a/maximilian_examples/6.FM2.cpp
+++ b/maximilian_examples/6.FM2.cpp
@@ -1,14 +1,16 @@
+// Nothing much to say about this other than I like it.
+
#include "maximilian.h"
maxiOsc mySine,myOtherSine,myLastSine,myPhasor;//Three oscillators
void setup() {//some inits
- //nothing to go here this time
+ //nothing to go here this time
}
void play(double *output) {
-
- *output=mySine.sinewave(myOtherSine.sinewave(myLastSine.sinewave(0.1)*30)*440);//awesome bassline
-
+
+ output[0]=mySine.sinewave(myOtherSine.sinewave(myLastSine.sinewave(0.1)*30)*440);//awesome bassline
+
}
diff --git a/maximilian_examples/7.Counting.cpp b/maximilian_examples/7.Counting.cpp
index 7de2f0e..e620b3a 100755
--- a/maximilian_examples/7.Counting.cpp
+++ b/maximilian_examples/7.Counting.cpp
@@ -1,3 +1,10 @@
+// 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 "maximilian.h"
maxiOsc myCounter,mySquare;//these oscillators will help us count and play sound
@@ -5,11 +12,22 @@ int CurrentCount;//we're going to put the current count in this variable so that
void setup() {//some inits
- //nothing to go here this time
+ //nothing to go here this time
}
void play(double *output) {
-
- CurrentCount=myCounter.phasor(1, 1, 9);//phasor can take three arguments; frequency, start value and end value.
- *output=mySquare.square(CurrentCount*100);
+
+ // 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);
}
diff --git a/maximilian_examples/9.Envelopes.cpp b/maximilian_examples/9.Envelopes.cpp
index 806e14f..2cf74f6 100755
--- a/maximilian_examples/9.Envelopes.cpp
+++ b/maximilian_examples/9.Envelopes.cpp
@@ -1,33 +1,51 @@
+//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 "maximilian.h"
maxiOsc myCounter,mySwitchableOsc;//
int CurrentCount;//
double myOscOutput,myCurrentVolume;//
-double myEnvelopeData[4] = {1,0,0,500};//this data will be used to make an envelope. Value and time to value in ms.
-maxiEnvelope myEnvelope;
+maxiEnv myEnvelope;
void setup() {//some inits
- myEnvelope.amplitude=myEnvelopeData[0]; //initialise the envelope
+
+ //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.line(4,myEnvelopeData);
-
- CurrentCount=myCounter.phasor(1, 1, 9);//phasor can take three arguments; frequency, start value and end value.
-
- 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.
-
- if (CurrentCount==1)
-
- myEnvelope.trigger(0,myEnvelopeData[0]); //trigger the envelope
-
- *output=myOscOutput*myCurrentVolume;//point me at your speakers and fire.
+
+ //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
+
}