Additive
Synthesis
jMusic can be used to create instruments with all manner of
synthesis systems.
One of the easiest to understand is additive synthesis, where multiple
sine waves of different frequencies are summed.
The final Audio file will sound like this: AddSynthTest.au [1774kb ]
Click here to view source for AddSynthInt.java
Lets have a closer look
There is a constructor that just takes the sampleRate and
provides defaults for all other settings. This provides a tone similar
to the one in the audio example above. To use it create an instrument
like this:
Instrument inst = new AddSynthInst(44100);
Next, let's look at the constructor which sets up all the
variables such as frequencies and amplitudes.
public AddSynthInst(int sampleRate, float[] overtoneRatios, float[] overtoneVolumes, double[][] envPointArray){
this.overtoneRatios = overtoneRatios; this.overtoneVolumes = overtoneVolumes;
double[][] tempPoints = new double[envPointArray.length][];
for (int i=0; i<envPointArray.length; i++) { tempPoints[i] = envPoints; } allEnvPoints = tempPoints; this.sampleRate = sampleRate; }
|
The constructor above takes a series of arrays for the
frequency, volume and envelope of each harmonic. Make sure when using this
constructor that the number of values in each array match (i.e., five values
in each array if you want five harmonics).
The audio object organisation shown in the flow chart above is depicted
in jMusic code below, taken from the AddSynthInst class. This shows the
inner workings of the class. The for loop allows the instrument to support
any number of overtones, specified by the number of elements in the arrays
passed to the constructor.
public void createChain(){ Envelope[] env = new Envelope[overtoneRatios.length]; Volume[] vol = new Volume[overtoneRatios.length]; Oscillator[] osc = new Oscillator[overtoneRatios.length]; for(int i=0;i<overtoneRatios.length;i++){ osc[i] = new Oscillator(this, Oscillator.SINE_WAVE, this.sampleRate,2); osc[i].setFrqRatio(overtoneRatios[i]); env[i] = new Envelope(osc[i], allEnvPoints[i]); vol[i] = new Volume(env[i], overtoneVolumes[i]); }
Add add = new Add(vol); StereoPan span = new StereoPan(add); SampleOut sout = new SampleOut(span); }
|
Now let's look
at a class that uses the additive synthesis instrument.
Click here to view source.
import jm.JMC; import jm.util.*; import jm.music.data.*; import jm.midi.*;
import jm.audio.synth.*; import jm.audio.Instrument;
import java.io.File;
public final class AddSynthTest implements JMC{ public static void main(String[] args){ Score s = new Score("Additive synthesis test"); Part p = new Part("Flute", 0); Phrase phr = new Phrase(); for(int i=0;i<6;i++) { Note n = new Note(A2+i*6, 0.5*(i+1)); phr.addNote(n); } p.addPhrase(phr); s.addPart(p); AddSynthInst inst = new AddSynthInst(44100); Instrument[] ensemble = {inst}; Write.au(s, "AddSynthTest.au",ensemble); } }
|
Try modifying this class to create a more interesting sound by using
the alternate constructor that takes arrays of values.
All instruments in jMusic extend the Instrument class, by doing this they
inherit a great deal of automatic behaviour
that is useful but on no concern for us in this tutorial.
The code above creates four sine waves, each one at a higher frequency
- specified by the setfrqRatio() method.
Each overtone is also at a different loudness - higher frequencies are
at lower levels, as is common in natural sounds.
These harmonics are added together, passed through an amplitude envelope
object, panned as appropriate for the note,
then written to an audio file on disk.
Musical Example
import jm.JMC; import jm.music.data.*; import jm.audio.*; import jm.util.*public final class HarmonicsTest implements JMC{ public static void main(String[] args){ Score score = new Score("JMDemo - Additive synthesis test"); Part part = new Part("wave", 0); Phrase phr = new Phrase(0.0); int sampleRate = 44100; Instrument inst = new OvertoneInst(sampleRate); Note note = new Note(C4, 4.0); phr.addNote(note); part.addPhrase(phr); score.addPart(part); Write.au(score, "HarmonicsTest.au", inst); } }
|
The code above uses the instrument to render a simple jMusic score
that has just one note.
|