Extended Drum Kit: Introducing classes with multiple methodsThis demo class enhances the simple drum kit class in a number of ways. So hold on to your hat! Firstly, the structure of the class is reorganised into a more object-oriented design where different sections are divided into separate methods (functions). In this way, the class is more reflective of a conventional Java program. This is a breakaway from what we have been doing in earlier tutorials where the entire process has been compacted into the 'main' method .... but more on this later. Secondly, in order to make the drum patterns more interesting there are numerous random changes throughout. Thirdly, rather than storing all the drum phrases in one part, in this class each drum type (snare, kick, etc.) are stored in their own part. Why? So far in these tutorials jMusic files have been exported as MIDI files. As MIDI files all drums share the one MIDI channel and so jMusic drum parts are combined during the conversion process into one MIDI track. However, jMusic can also output audio files and to do so each part needs to have a different instrument - snare is different to kick which is different to closed hihat which is different to open hihat. Hence, this class creates a jMusic score with each instrument having its own part so it can be written as either a MIDI or an audio file. In this tutorial we will only deal with the MIDI file exporting. Have a listen to the MIDI playback below to hear the result.
This class divides the work of the program into several sections. After the class declares its class variables we start by running the main() method. It immediately calls the constructor which, in turn, calls methods to create the bass drum, snare and hi hat phrases. Next, the doScore() method puts all the phrases into parts and into a score. Control passes back to the main() method which sets the tempo and saves the score as a MIDI file. Here is a diagram of that passing of control between the methods. Let's have a closer look at the code.
Lines 1-3 import useful packages that we need to use in the program.
The code above declares all the class variable for use in this program. Class variables, declared outside methods, can be used by any methods within the class. These variables are declared private because they only need to be accessed from within this class, not from other classes. They need to be static because the class is static, a result of having a static method; main() in this case.
The main() method will be the first to be executed when the program runs.
The constructor method always has the same name as the class. It also does not require a return type in the declaration (notice there is no void keyword as in the other methods). After printing a message to the standard output the constructor calls each of the other methods in the class one after another to do their bit of the job. The crash cymbal part is so trivial (one note) that the constructor does that itself rather than use a different method. After each part is created the doScore() method packs all the parts into a score. Notice that each of the method class begins with the word this. That indicates that the method is in this class. Often the keyword this is left off method calls - in which case it is assumed - but it is good practice to include it as it reminds you of exactly what is going on.
The doBassDrum() method first prints a message confirming that it has been called. There are two for-loops, one inside the other. We say the loops are nested. The outer loop, which uses the r index counter, forces the inner loop to repeat 8 times over. The inner loop, whic uses the i index counter, adds a note and a rest to the phrBD phrase each time around the loop. resulting in four note and rest pairs. A two bar pattern in all (assuming simple quadruple time), 16 bars in all.
The doSnare() method is a more involved version of the bass drum method. There are two loops, the i loop nested inside the j loop. The j loop repeats 16 times and the i loop produces a one bar phrase. The first three beats of the phrase are created in the j loop, a rest, a note, and another rest - each a crotchet (quarter note) long. The first three semiquavers (16th notes) of the final beat are created in the i loop. There is a 1 in 3 chance (at random) of a note being generated on each semiquaver, otherwise a rest is used. The final semiquaver pulse of the bar is always set as a rest after the i loop has completed.
Once you understand the snare method, the doHiHats() method should look familiar. There are two loops, one nested inside the other. The outside loop, r, repeats the inner process sight times. Inside the r loop a closed hihat is added at the start of each two bar group. Notice, that this method does two phrases at once. It fills the closed and open hihat phrases at the same time. In order for them to be in sync (that is no open and closed hats together) rests are added to the alternate phrase for every note added to the primary phrase. The next 30 semiquavers are determined inside the i loop which chooses a closed (pitch 42) or open (pitch 46) hihat note. There is a one in sixteen chance of getting an open hihat - so mostly we will get closed hihats. Additionally, the dynamic value of each note is determined at random between 45 and 125. On completion of the i loop control drops back out to the r loop where the last semiquaver of the group will always be a semiquaver note.
Now its time to bring all the drum phases and parts together into a score. In this method each phrase is added to the appropriate part - one for each the instrument sound. Then each of the parts is added to the score, called pattern1. After this method control passes back to the constructor method which, now also complete, passes control back to the main() method for saving the now complete score as a MIDI file. Audio: For those of you who can't wait to get the audio version of this class working, below are links to the source and audio samples required. Drum samples required - download these files: Kick, Snare, Hats, OpenHH |
|
|
|
|
|
|