PSynth's VCF UI is shown in Figure 4.
Note that it is possible to add a second EG into the VCF that would manipulate the filter's resonance. That way, both filter cutoff frequency and resonance would be dynamic.
The MusicPlayer Class
The MusicPlayer class was developed for use in the examples for playing simple musical tunes. I thought the examples would sound more real world if they were heard during the playing of a melody. MusicPlayer plays a melody contained in an array of Note objects. A very abridged version of the song , "Somewhere Over the Rainbow" is coded as follows:
private Note [] song = {
new Note(0,2),
new Note(60,2), new Note(72,2), new Note(71,4), new Note(67,8),
new Note(69,8), new Note(71,4), new Note(72,4), new Note(60,2),
new Note(69,2), new Note(67,1),
new Note(57,2), new Note(65,2), new Note(64,4), new Note(60,8),
new Note(62,8), new Note(64,4), new Note(65,4), new Note(62,4),
new Note(59,8), new Note(60,8), new Note(62,4), new Note(64,4),
new Note(60,1),
new Note(0,4)
};
Note instances are comprised of two integer values. The first is the midi note number, which determines the note's frequency, and the second is the note's duration. A 1 is a whole note, a 2 is a half note, a 4 is a quarter note, and so on. A Note object with a midi note number of 0 is a rest (period of silence) for the specified duration.
I'll show how a MusicPlayer object is used before describing how it works,. The code snippet below shows how to incorporate it into the typical signal chain. You will note that the class's constructor takes references to the oscillator that will produce the sound, a VCA, a VCF, and to the array of Note objects. The VCA and VCF are optional, so a null could be passed in their places.
MusicPlayer is a sample provider for reasons that will be discussed shortly. As such, it has to have its sample provider initialized (in this case, the osc is providing its samples) and the SamplePlayer that follows must set the MusicPlayer as its sample provider.
// Create music player MusicPlayer mp = new MusicPlayer(osc, vca, vcf, song); // Set the music player's sample provider mp.setSampleProvider(osc); // Create a sample player SamplePlayer player = new SamplePlayer(); // Sets the sample player's sample provider player.setSampleProvider(mp); // Start the player player.startPlayer(); // Play song mp.playSong();
When the playSong method is called the song is played. A loop count can also be set, which allows the song to repeat as many times as required. The playSong method is shown below:
public void playSong() {
int notesInSong = notes.length;
do {
for (int n = 0; n < notesInSong; n++) {
// Get note from song
Note note = notes[n];
// Get midi note number for note
int mnn = note.midiNoteNumber;
// A mnn of 0 is a rest so no need to set osc frequency
if (mnn != 0) {
// Convert to real frequency
double frequency = midiNoteNumberToFrequency(mnn);
// Inform osc
osc.setFrequency(frequency);
}
// Get duration indication
int durationTics = getNoteDurationInTics(note.durationTag);
// Play the note if it is not a rest
if (mnn != 0) {
if (vca != null) {
vca.noteOn();
}
if (vcf != null) {
vcf.noteOn();
}
}
// Delay for the duration of note or rest
delay(durationTics);
if (vca != null) {
vca.noteOff();
}
if (vcf != null) {
vcf.noteOff();
}
}
} while (--loopCount > 0);
}
Observe that noteOn and noteOff events are generated for each note for triggering the EGs associated with the vca and vcf. This makes it sound as if the notes are being played on a keyboard.
Note also that note duration timing is derived from counting the buffers of samples passing through the MusicPlayer module as, on average, this is a very accurate measure of time. Since the sample rate and the buffer size are fixed (in the SamplePlayer class), time per buffer can be calculated at approximately 45.3 milliseconds. If we assign a duration for a 32nd note, we can calculate the duration of all of the other, longer duration notes from that. Dividing a notes required duration by the buffer processing time results in a count of buffers that must pass during the time a note sounds. See MusicPlayer.java for the details.
Conclusions
With this article, we have added three new components to our electronic music arsenal: a VCA, a VCF, and a music player. We have discussed how each of these components works and have shown how they are incorporated into our electronic music architecture. You can hear the operation of these new components by listening to the examples that were discussed in the last installment. In the next and final article of this series, I will discuss Delay and Phaser special effects, which can add even more color and spice to your electronic music mix.
Resources
The code for the complete article series can be downloaded here. Source code, executable code, sound examples and javadocs and are all in this jar file.
The following books contain valuable information on electronic music production and digital signal processing.
- Computer Music: Synthesis, Composition and Performance, Charles Dodge, Thomas A. Jerse, 1985, 1997. Schirmer Books.
- Elements of Computer Music, F. Richard Moore, 1990, Prentice-Hall.
- A Programmers Guide To Sound, Tim Kientzle, 1998, Addison-Wesley.
- Digital Audio with Java, Craig A. Lindley, 2000, Prentice-Hall.
- PSynth – An iPhone/iPod Touch synthesizer app available from iTunes.
— Craig Lindley is a hardware engineer who, until recently, had been writing large-scale Java applications.
Creating Music Components in Java (Part One in this series)
Music Components in Java: Creating Oscillators (Part Two in this series)


