Audio Objects
This tutorial provides details some of the
jMusic audio objects and has a class that uses three different instruments.
Hear the result of this tutorial's music
below.
Arps.mp3 [200K]
View
/ Download source - Instrument
source code
View / Download source
- Composition source code
Let's have a closer look the heart of the simplest of rendering instruments
in jMusic.
public void createChain(){
WaveTable wt = new WaveTable(this, this.sampleRate,
Oscillator.getSineWave(this.sampleRate), channels);
SampleOut sout = new SampleOut(span);
} |
The arrangement of audio classes is pictured below.
Notice that your instrument classes draw upon a number of audio object
classes, most extending the AudioObject class itself.
Wavetable class
Inside the WaveTable class we can see that there is a constructor (shown
below) that takes four arguments,
an audio instrument, the current sample rate, an array of floating point
values to be used as the lookup table,
and the number of channels for this instrument.
public WaveTable(Instrument inst, int sampleRate,
float[] waveTable, int channels){
super(inst, sampleRate, "[WaveTable]");
this.waveTable = waveTable;
this.channels = channels;
}
|
In the instruments shown thus far, these
arguments have been filled by the following line inside the createChain()
method.
WaveTable wt = new WaveTable(this,
this.sampleRate,
Oscillator.getSineWave(this.sampleRate),
channels); |
Each wavetable instance takes an array of floats that describe the
wave table data.
Often this data is one cycle of a waveform provided by the Oscillator
class.
The timbral information is provided by the Oscillator class that, in
this case, returns a single cycle of sine wave floating point
values to be used as a wave table.
Oscillator class
The oscillator class has a number of methods
to generate wavetable data. The sine wave generating method is shown
below.
public final class Oscillator{
public static float[] getSineWave(int numOfSamples){
float[] sampleArray = new float[numOfSamples];
float increment = (float)(Math.PI*2) / (float)numOfSamples;
float x = (float)0.0;
for(int i=0;i<numOfSamples;i++){
sampleArray[i] = (float)((float)Math.sin(x+(
(float)2.0*(float)Math.PI)));
x += increment;
}
return sampleArray;
}
|
There are methods to generate the following
wave tables and you can always add others that you might want to include.
SquareWave, PulseWave, SawTooth, and TriangleWave.
SampleOut class
The sampleout class constructor takes the
previous audio object in the chain as its only argument.
SampleOut sout = new SampleOut(span); |
Arpeggio composition
This program creates a three part score from a four note cell. Each
subsequent layer is both higher and faster than the one below it, and
a different instrument is assigned to each part so that each has its
own timbre. The dynamic of each note is set randomly within a specified
range and the panning position is set to a specific location for two
of the parts and at random for the third. The three phrases, once constructed,
are modified in various ways-In particular there is considerable use
of volume fading in and out, and the highest part has the note order
randomised using the Mod.shuffle() method.
import jm.music.data.*;
import jm.music.tools.*;
import jm.JMC;
import jm.audio.*;
import jm.util.*;
public class Arps implements JMC {
public static void main(String[] args) {
new Arps();
}
public Arps() {
int[] pitches = {60, 67, 72, 74};
Phrase phrase1 = new Phrase();
Phrase phrase2 = new Phrase();
Phrase phrase3 = new Phrase();
Part part1 = new Part("One", 0);
Part part2 = new Part("Two", 1);
Part part3 = new Part("Three", 2);
int loop = pitches.length;
for (int i = 0; i < loop * 4; i++) {
for (int j = 0; j < loop; j++) {
for (int k = 0; k < loop; k++) {
Note n3 = new Note(pitches[k] + 24,
0.0625,
(int)(Math.random() * 60 + 20));
n3.setPan(Math.random());
phrase3.addNote(n3);
}
Note n = new Note(pitches[j],
SEMI_QUAVER,
(int)(Math.random() * 40 + 80));
n.setPan(0.2);
phrase1.addNote(n);
}
Note n2 = new Note(pitches[i % pitches.length] - 24,
CROTCHET,
(int)(Math.random() * 40 + 40));
n2.setPan(0.8);
phrase2.addNote(n2);
}
Mod.cycle(phrase3, pitches.length * 4.0 + 9.0);
Mod.shuffle(phrase3);
Mod.fadeOut(phrase3, 9.0);
Mod.fadeIn(phrase1, 16);
Mod.fadeOut(phrase2, 8);
part1.addPhrase(phrase1);
part2.addPhrase(phrase2);
part3.addPhrase(phrase3);
Score score = new Score(part1);
score.addPart(part2);
score.addPart(part3);
View.show(score);
int sampleRate = 22000;
Instrument saw = new SawtoothInst(sampleRate);
Instrument tri = new TriangleInst(sampleRate);
Instrument sin = new SineInst(sampleRate);
Instrument[] ensemble = {tri, saw, sin};
Write.au(score, "Arps.au", ensemble);
}
}
|
Enjoy.