Channels ▼
RSS

JVM Languages

Music Components in Java: The Synthesizer Core


PSynth's VCF UI is shown in Figure 4.

Figure 4: PSynth's VCF UI.

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.

  1. Computer Music: Synthesis, Composition and Performance, Charles Dodge, Thomas A. Jerse, 1985, 1997. Schirmer Books.
  2. Elements of Computer Music, F. Richard Moore, 1990, Prentice-Hall.
  3. A Programmers Guide To Sound, Tim Kientzle, 1998, Addison-Wesley.
  4. Digital Audio with Java, Craig A. Lindley, 2000, Prentice-Hall.
  5. 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)


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video