Amplitude Modulation

This tutorial explains what happens when the modulating frequency is increased into the audible range - tremolo becomes timbre.

Hear the result of this tutorial's music below.

View / Download source - Instrument source code

View / Download source - Composition source code

Instrument

Here is the code:
import jm.audio.io.*;
import jm.audio.synth.*;
import jm.music.data.Note;
import jm.audio.AudioObject;

 
/**
* A basic amplitude modulation synthesis instrument
* which implements envelope and volume control
* @author Andrew Brown
*/

 
public final class AMInst extends jm.audio.Instrument{
//----------------------------------------------
// Attributes
//----------------------------------------------
/** the sample rate passed to the instrument */

private int sampleRate;

/** the sample rate passed to the instrument */

private int channels;

 
//----------------------------------------------
// Constructor
//----------------------------------------------
/**
* Basic default constructor to set an initial
* sampling rate.
* @param sampleRate
*/

public AMInst(int sampleRate){
this.sampleRate = sampleRate;
this.channels = 1;
}

 
//----------------------------------------------
// Methods
//----------------------------------------------
/**
* Initialisation method used to build the objects that
* this instrument will use.
*/

public void createChain(){

Oscillator mod = new Oscillator(this, Oscillator.SINE_WAVE,
this.sampleRate, this.channels);
mod.setFrqRatio((float)7.5);
mod.setAmp(0.5f);
Envelope env = new Envelope(mod,
new double[] {0.0, 0.0, 0.4, 1.0, 1.0, 0.8});

Value offsetAmp = new Value(this, this.sampleRate,
this.channels, (float)1.0);
Add add = new Add(new AudioObject[] {env, offsetAmp});

Oscillator carr = new Oscillator(add, Oscillator.SINE_WAVE,
WaveTable.AMPLITUDE);
Envelope env2 = new Envelope(carr,
new double[] {0.0, 0.0, 0.5, 1.0, 1.0, 0.0});
SampleOut sout = new SampleOut(env2);

}
}

Amplitude Modulation

This instrument alters (modulates) the amplitude of one waveform (the carrier) by the sample values of a second (the modulator). In classic amplitude modulation, as used in this instrument, the amplitude of the carrier wave is continually varied by the amplitude of the modulator wave. When the frequency of the modulator is beyond about 10hz additional partials are generated creating a timbral effect. When using sine waves, as in this example, two partials (side bands) are generated above and below the fundamental frequency of the carrier. The frequencies of the side bands are at the carrier frequency + and – the modulator frequency. The amplitude of the sidebands is half of the carrier, the modulator energy is split equally between the two side bands.

	Oscillator mod = new Oscillator(this, Oscillator.SINE_WAVE, 
this.sampleRate, this.channels);
mod.setFrqRatio((float)7.5);
mod.setAmp(0.5f);
Envelope env = new Envelope(mod,
new double[] {0.0, 0.0, 0.4, 1.0, 1.0, 0.8});

The instrument first creates a modulator sine wave of a frequency relative to the Note pitch. Thus is will be in the audible range and have a timbral effect. The maximum level of modulation is set by adjusting the modulator’s amplitude. An envelope is applied to the modulator such that the amount of modulation will vary over the duration of the note.

	Value offsetAmp = new Value(this, this.sampleRate, 
this.channels, (float)1.0);
Add add = new Add(new AudioObject[] {env, offsetAmp});

The resulting values of the oscillator have values that are both positive and negative, and because negative envelope values are not what is wanted we offset them by adding a constant value of 1.0 to them. (Assuming that 1.0 is the normal maximum sample value).

	Oscillator carr = new Oscillator(add, Oscillator.SINE_WAVE, 
WaveTable.AMPLITUDE);
Envelope env2 = new Envelope(carr,
new double[] {0.0, 0.0, 0.5, 1.0, 1.0, 0.0});
SampleOut sout = new SampleOut(env2);

The result of this process is passed as the amplitude input to the carrier oscillator. The frequency of the carrier in jMusic is, by default, the Note frequency from the score. The amplitude of the carrier will vary according to the modulation values, in this case a sine wave that shifts up and down at a constant rate. Because the rate is very fast, individual shifts are not audible, rather that overall effect of the modulation results in side bands.
 

Composition Example

More details to come.

import jm.JMC;
import jm.music.data.*;
import jm.audio.*;
import jm.util.*;
 
public final class AMSimpleTest implements JMC{
public static void main(String[] args){
Score score = new Score("JMDemo - Audio test");
Part part = new Part("wave", 0);
Phrase phr = new Phrase(0.0);
int sampleRate = 44100;
Instrument inst = new AMInst(sampleRate);
 
Note note = new Note(C4, 4.0);
phr.addNote(note);
 
part.addPhrase(phr);
score.addPart(part);
Write.au(score, "AMSimpleTest.au", inst);
}
}



jMusic Tutorial Index


© 2001 Andrew Brown