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(){
Oscillator wt = new Oscillator(this, Oscillator.SINE_WAVE,
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.

Oscillator class

Inside the Oscillaor class we can see that there is a constructor 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.

In the instruments shown thus far, these arguments have been filled by the following line inside the createChain() method.

		Oscillator wt = new Oscillator(this, Oscillator.SINE_WAVE, 
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.

The oscillator class has a number of methods to generate wavetable data. The sine wave generating method is shown below.

public final class Oscillator{
	/**
	 * Static function returning a sineWave created from
	 * from a certain number of samples.
	 * @param numOfSamples the number of samples to create
	 * @return an array containing the sinewaves sample data
	 */
	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() {
// musical score construction 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); // make arpeggios 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); }   // modify the phrases 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); // add phrases to their parts part1.addPhrase(phrase1); part2.addPhrase(phrase2); part3.addPhrase(phrase3);   // add parts to the score Score score = new Score(part1);
score.addPart(part2);
score.addPart(part3);
// display the score View.show(score); // instrument declaration int sampleRate = 22000; Instrument saw = new SawtoothInst(sampleRate); Instrument tri = new TriangleInst(sampleRate); Instrument sin = new SineInst(sampleRate); Instrument[] ensemble = {tri, saw, sin}; // render Write.au(score, "Arps.au", ensemble); } }

Enjoy.



jMusic Tutorial Index


© 2001 Andrew Brown