Tuning Systems
In this tutorial we explore the use of different tuning
systems.
The example class allows a musical piece to be rendered in one of four
tuning systems, the equal temperment system used in modern times, just
intonation, pythagorean tuning, and mean-tone. This demonstrates that
with the ability of jMusic to play audio notes at any frequency you
are not limited to the chromatic tuning normally associated with MIDI
systems. It is possible to implement tuning schemes that don't even
follow the conventional pattern of 12 notes to the octave.
The differences in tunings sounds like this :
Equal
Just
Click here to view source.
Lets have a closer look.
import jm.music.data.*; import jm.JMC; import jm.util.Write; import jm.audio.Instrument;
|
Here we import the usual suspects for a jMusic piece, we
need the Instrument class for the audio rendering.
public final class Tuning_Systems implements JMC{ public static void main(String[] args){ new Tuning_Systems(); }
|
The class is declared and implements the JMC which allows
us to use the jMusic constatans such as C (crotchet) for a rhythm value
of 1.0 etc.
The main method is quite simple, and simply calls the constructor
to create an instance of the class.
public Tuning_Systems() { int[] pitchSop = {G4,A4,B4,BF4,A5,AS5,B4,A4, BF4,AF4,G4,A4,B4,BF4,C5,CS5, D5,CS5,B4,C5,BF4,C5,B4,A4,BF4,G4,D5, CS5,B4,C5,BF4,C5,B4,A4,BF4,G4, REST,E4,A4,BF4,REST,E4,A4,B4,REST,E4,A4,C5,REST}; double[] rhythmSop = {Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,2.5, Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q, C,Q,Q,Q,C,Q,Q,Q,C,Q,Q,Q,2.5}; int[] pitchAlto = {G4,D4,CS4,D4,G4,D4,A3, REST, E4, DS4,CS4,REST,D4,CS4,B3, FS4,CS4,REST,FS4,CS4,REST,FS4,CS4,REST,F3}; double[] rhythmAlto = {DC,C,DC,C,DC,C,2.5,DC,C, DC,C,DC,C,DC,C, Q,Q,DC,Q,Q,DC,Q,Q,DC,2.5};
|
The constructor takes no argments.
The first task is to have some music to text the tuning
systems with.
We have used the first section of the one of Bela Bartok's simple but
interesting piano works.
The pitch and rhythm values are in separate arrays, because we need
to process the pitches later on.
public static final double [] EQUAL = {1.0, 1.059, 1.122, 1.189, 1.26, 1.335, 1.414, 1.498, 1.587, 1.682, 1.782, 1.888}, JUST = {1.0, 1.067, 1.125, 1.2, 1.25, 1.333, 1.406, 1.5, 1.6, 1.667, 1.8, 1.875}, PYTHAGOREAN = {1.0, 1.053, 1.125, 1.185, 1.265, 1.333, 1.404, 1.5, 1.58, 1.687, 1.778, 1.898}, MEAN = {1.0, 1.07, 1.118, 1.196, 1.25, 1.337, 1.398, 1.496, 1.6, 1.672, 1.789, 1.869};
|
The above excerpt is not from Tuning_Systems.java, it is
from JMC.java
Because this class implements JMC, it has acess to all of the constants
that are declared there.
In the current version of Tuning_Systems.java, EQUAL (equal
temperment) is used. Equal temperment basically sacrifices portability
(the ability to transpose) for authenticity (true intervals).
If transposition is not an issue, then it may be a good
idea to use a tuning system that uses truer intervals.
These arrays hold the ratio values of each semitone scale
degree as a multiple of the root of the scale. For example, C4 is the
first (zeroth) scale degree and has a ration of 1:1.0 with itself, C#
has a ration of 1:1.059 in the chromatic system, and so on.
Here is a table of all the values for these tuning systems.
double[] modeRatios = EQUAL; |
As stated above, the currently active tuning system is assigned
to the variable modeRatios.
This is where you can experiment with the different tuning systems that
are in JMC, or (even better) make you own up!
e Score score = new Score("Bartok", 130); score.addPart(createPart(pitchSop, rhythmSop, 0, modeRatios)); score.addPart(createPart(pitchAlto, rhythmAlto, 1, modeRatios)); |
A score is created and two parts are added, the soprano
and alto parts. A separate method, creatPart, is used for this purpose.
We will see more about this method below. For now we are only concerned
that it returns a Part that is added to the score.
Instrument[] insts = new Instrument[2]; for (int i=0; i<2; i++) { insts[i] = new SquareLPFInst(22050, 500); } Write.au(score, "TuningSystems.au", insts); } |
Next, the score is rended as an audio file. This requires
the declaration of a couple of jMusic audio instruments.
We use instances of the SquareLPFinst that takes a sample rate and low
pass filter cutoff frequency as arguments.
These instruments are added to the instrument array, insts, which is
passed to the Write() method.
If you don't have the Instrument it can be downloaded from the jMusic
web site, via the instrument page.
or you can simply use another instrument of your choice.
private Part createPart(int[] pitches, double[] rhythms, int instrument, double[] modeRatios) { Part part = new Part("", instrument); Phrase phrase = new Phrase(); for (int i=0; i<pitches.length; i++) { if (pitches[i] == REST ) { int pitch = REST; phrase.addNote(new Note(pitch, rhythms[i])); } else { int degree = pitches[i]%12; double pitch = FRQ[pitches[i] - degree] * modeRatios[degree]; phrase.addNote(new Note(pitch, rhythms[i])); } } part.addPhrase(phrase); return part; } |
This method, mentioned earlier, is where all the interesting
work of this example is done.
Each of the pitches is turned into the appropriate frequency for the
current tuning system. Notes are created using that pitch and added
to a Phrase with is added to a Part and returned to the calling method.
In more detail, each pitch is processed in turn;
for (int i=0; i<pitches.length; i++) {
If the pitch is a REST then a rest-note is created with
the corresponding rhythm value and added to the phrase.
Otherwise the pitch's frequency needs to be calculated.
First, we work out which semitone degree it is.
int degree = pitches[i]%12;
Next we calulate the frequency by looking up the appropriate
ratio in the current tuning ratio array and multiplying the root frequency
by that ration value.
double pitch = FRQ[pitches[i] - degree] * modeRatios[degree];
Finally, we create a note of that frequency with the corresponding
rhythmValue and add it to the Phrase.
phrase.addNote(new Note(pitch, rhythms[i]));
Now that the Phrase is created we add it to the Part which
is then returned.
Rending a retuned MIDI file
For those of you that don't want to go to the trouble of
writing out your music as pitch and rhythm arrays, below is a link to
a modified version of the above class that reads in a MIDI file and
renders out an audio file in the specified tuning system. This should
save you some time :)
Tuning_Systems_MIDI.java
|