audio MIDI Music Algorithms Interfaces Programming Acoustics Context
> Audio > Synthesis > Dynamic Instrument Parameters    
 
   

Dynamic Instrument Parameters

This tutorial shows how audio objects can have variations built into them.

Hear the result of this tutorial's music below.

Gongs3.mp3 [416K]

View / Download source - Instrument class

View / Download source - Composition class

Lets have a closer look. 

 
import jm.audio.io.*;
import jm.audio.synth.*;
import jm.music.data.Note;
import jm.audio.AudioObject;
 
/**
 * A basic sine instrument implementation
 * which changes the decay envelope on each instantiation.
 * @author Andrew Sorensen and Andrew R. Brown
 */
 
public final class VaryDecaySineInst extends jm.audio.Instrument{
	//----------------------------------------------
	// Attributes
	//----------------------------------------------
	/** The points to use in the construction of Envelopes */
	private EnvPoint[] pointArray = new EnvPoint[10];
	/** The number of channels */
	private int channels;
	/** the sample rate passed to the instrument */
	private int sampleRate;
 
	//----------------------------------------------
	// Constructor
	//----------------------------------------------
	/**
	 * Basic default constructor to set an initial 
	 * sampling rate.
	 * @param sampleRate 
	 */
	public VaryDecaySineInst(int sampleRate){
	    this(sampleRate, 2);
	}
	/**
	 * A constructor to set an initial 
	 * sampling rate and number of channels.
	 * @param sampleRate 
     */
	public VaryDecaySineInst(int sampleRate, int channels){
		this.sampleRate = sampleRate;
		this.channels = channels;
		EnvPoint[] tempArray = {
			new EnvPoint((float)0.0, (float)0.0),
			new EnvPoint((float)1.0, (float)0.001),
			new EnvPoint((float)0.5, (float)0.1),
			new EnvPoint((float)0.05, (float)(Math.random() * 0.4 + 0.3)),
			new EnvPoint((float)0.0, (float)(Math.random() * 0.3 + 0.7))
		};
		pointArray = tempArray;
	}
 
	//----------------------------------------------
	// Methods 
	//----------------------------------------------
	   
	/**
	 * Initialisation method used to build the objects that
	 * this instrument will use
	 */
	public void createChain(){
		WaveTable wt = new WaveTable(this, this.sampleRate, 
				Oscillator.getSineWave(this.sampleRate), channels);
		Envelope env = new Envelope(wt, pointArray);
		Volume vol = new Volume(env,(float)1.0);
		StereoPan span = new StereoPan(vol);
		SampleOut sout = new SampleOut(span);
	}	
}

Dynamic Envelope Change

The dynamic part of this instrument is in the declaration of envelope points.

		EnvPoint[] tempArray = {
			new EnvPoint((float)0.0, (float)0.0),
			new EnvPoint((float)1.0, (float)0.001),
			new EnvPoint((float)0.5, (float)0.1),
			new EnvPoint((float)0.05, (float)(Math.random() * 0.4 + 0.3)),
			new EnvPoint((float)0.0, (float)(Math.random() * 0.3 + 0.7))
		};

Notice that the last two EnvPoint's and have a randomised value, this will be calculated when the instrument is constructed.
Therefore each instance of the instrument will be slightly different.
We use this characteristic in the following piece to create an additive timbre where each partial has a slightly different envelope
and so the timbre changes over the duration of each note.

Compositional Example

This composition extends the Gong concept of the previous two tutorials. the pitch of notes is used to determine the overtone series for each gong.
There is plenty of randomness in both the setting of the fundamental pitch, the overtone intervals, and overtone loudness - thus some gong sounds
will be more convincing than others.

The score creates 5 gong tones (chords) each with 8 partials (parts). This imbedded loop struture takes up most of the code.

		Instrument[] ensemble = new Instrument[partCounter];
		
		for (int k = 0; k < partCounter; k++) {
			ensemble[k] = new VaryDecaySineInst(sampleRate);
		}

The VaryDecayinstrument described earlier is used for each part. In order to minimise code repetition the instrument array is created in a loop which
declares an instrument each iteration.
We are using multiple instances of the same instrument (rather than just one) because the envelopes of each instance will vary thus giving us
a dynamic timbrel result.

import jm.music.data.*;
import jm.music.tools.*;
import jm.JMC;
import jm.audio.*;
import jm.util.*;
 
// Gong-like timbres inspired by Claude Risset's early computer music pieces
 
public class Gongs3 implements JMC {
	
	public static void main(String[] args) {
		new Gongs3();
	}
	
	public Gongs3() {		
		// musical score construction
		Score score = new Score("Gongs 3");
		int partCounter = 0;
		double startTime = 0.0;
		// loop for a number of gongs
		for (int j = 0; j < 5; j++) {
			startTime = score.getEndTime();
			int fundPitch = (int)(Math.random() * 12 + C2);
			int pitch = 60;
			double length = Math.random() * 10.0 + 4.0;
			// loop for the number of partials in each gong
			for (int i = 0; i < 8; i++) {
				Part p = new Part("Part" + partCounter, partCounter);
				partCounter ++;
				Phrase phrase = new Phrase(startTime);
				if (i == 0 ) { // base pitch
					pitch = fundPitch;
					phrase.addNote(new Note(pitch, length + 2.0, 
						127 + C2 - pitch - (int) (Math.random() * 20)));
				} else { // overtones
					pitch = (int)(Math.random() * 16 + fundPitch + 8);
					phrase.addNote(new Note(pitch, length, 
						127 + C2 - pitch - (int) (Math.random() * 20)));
				}
				p.addPhrase(phrase);
				score.addPart(p);
			}
		}
		
		View.show(score);
		
		// instrument declaration
		int sampleRate = 11000;
		
		Instrument[] ensemble = new Instrument[partCounter];
		
		for (int k = 0; k < partCounter; k++) {
			ensemble[k] = new VaryDecaySineInst(sampleRate);
		}
			
		// render
		Write.au(score, "Gongs3.au", ensemble);
	}
}

 

 

 

jMusic Australia Council Queensland University of Technology Sitemap Contact Home Home http://www.qut.com http://explodingart.com/jmusic http://www.ozco.gov.au

Digital Instrument making Home