Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a simple but well structured musical notation class (musical score) in java?

I'm creating audio and effects in my game on the fly with very basic sound synthesis. Basically, I have some methods that can play a sound given a frequency & amplitude & duration.

For short phrases and melodies, I'd like to come up with a basic notation so that I can easily rewrite or add new melodies into the code (in the end maybe I could read from files, but that is probably overkill).

I'm not sure how to implement this however.

I've started by creating an enum EqualTemperamentTuning which contains all 88 basic piano notes with a MIDI # field and a frequency field. This at least means I can deal in note names and not frequencies.

public enum EqualTemperamentTuning {
    A_0         (1, 27.5),
    A_SHARP_0   (2, 29.1352),
        ...
    C_8         (88, 4186.01);

    private int num;
    private double frequency;

    EqualTemperamentTuning(int num, double frequency){

        this.num = num;
        this.frequency = frequency;
    }

    public double getFrequency(){
        return frequency;
    }

    public double getNum(){
        return num;
    }
}

Then I started creating more objects, first a Note that holds an EqualTemperamentTuning, an amplitude and a length:

public class Note {

    /** Note frequency */
    private double frequency;
    /** Note Amplitude */
    private double amplitude;
    /** Note length */
    private int length;     

    public Note(EqualTemperamentTuning tuning, double amplitude, int length){

        this.frequency = tuning.getFrequency();
        this.amplitude = amplitude;
        this.length = length;   
    }

    public double getFrequency(){
        return frequency;
    }

    public double getAmplitude(){
        return amplitude;
    }

    public int getLength(){
        return length;  
    }
}

Finally to define the melody I want to play, I created a NotePhrase class:

public class NotePhrase {

    /** The arrayList of notes*/
    private Note[] notes;

    public NotePhrase(Note[] notes){

        this.notes = notes;
    }

    public double getFrequency(int counter){

        // for each note in the array
        for (int i = 0; i< notes.length; i++){

            // for each unit of length per note
            for (int j=0; j<notes[i].getLength(); j++){

                counter--;

                // return the frequency at this point
                if (counter <= 0) return notes[i].getFrequency();

            }
        }
        return -1;  
    }
}

Then in my audio generating class I have a loop (with counter) that generates samples from a wave generator. Every time I need a new sample to play, it sets the frequency of the wave according to the NotePhrase.getFrequency(int counter) method above. This should (I haven't actually tested yet!) just play the NotePhrase melody according to the frequency and amplitude (to be added).

Problem is, it doesn't seem very elegant and more specifically it's very difficult to "write" a melody in any kind of legible way. I have to code a whole bunch of new Note objects and then construct a NotePhrase object with an array of them... It's not obvious to me how I would hard code a bunch of these melodies and then easily switch between them later.

Really I would like to create an enum of Melodies or something like that, where I can easily hard code a human legible configuration for each different melody, and then when I want to use them, just pass the enum type to the audio player...

The best I've got is:

private static enum Melody {
    NOKIA_RINGTONE ( new Note(EqualTemperamentTuning.E_5, 0.5, 1), new Note(EqualTemperamentTuning.D_5, 0.5, 1))
    ;

    private Note[] notes = new Note[2];

    Melody (Note note1, Note note2){
        this.notes[0] = note1;
        this.notes[1] = note2;
    }
}

Which I would then load into a NotePhrase object at runtime. This isn't much good because I have to create a new constructor for melodies with different amount of notes. If I do it the other way round and construct the enum with an array of notes, then I'm just "writing" the melody elsewhere and in two parts which seems even more confusing...

So I'm stuck as to how to structure this properly? ie what classes to create and what info they should hold... I want to get this "right" because, I might like to expand the notation in the future to include effects (echo etc) and I've already found with my very little experience, that the right classes, structure and relationships (even names) can make my programs very easy or difficult to understand.

Apologies for the essay, this might not be a very well phrased (ahem) question, but as a java & OOP beginner, any hints would be very welcome!

EDIT**

Thanks for the answers & suggestions, very helpful. Thinking about the answers given in this case triggered me to rethink my general audio implementation, which is pretty shaky right now. Not sure who I should mark as correct though, as I'm really just going to take all recommendations on board and try and go from there.

like image 466
kiman Avatar asked May 23 '12 16:05

kiman


People also ask

How do you make musical notation?

Find that first note on your instrument or piano. Once you are certain that is the right note, write it down. To do this, write the right pitch, right below the rhythm (so write the pitch on the staff, and give it the same rhythm as written above the staff). Do this for all pitches, in sequence.

What is simple notation in music?

Simplified music notation It is based on classical staff notation, but incorporates sharps and flats into the shape of the note heads. Notes such as double sharps and double flats are written at the pitch they are actually played at, but preceded by symbols called history signs that show they have been transposed.

How can I improve musical notation?

Practice Makes Perfect… Many musicians may feel that writing music is obvious — and they are often right — but just as you had to practice making letters before you could write, so too must you practice every notehead, articulation, and dynamic before giving others your scores.

How many types of music notation are there?

What Are the Types of Musical Notation? Most musical notation falls into one of five categories. All have unique histories, but traditional staff-based notation contains the most intricacies. This notation includes noteheads, bar lines, time signatures, clefs, key signatures, and dynamics, among many other elements.


2 Answers

Don't use an enum for a Melody since the Melody doesn't represent a true constant, but rather a collection of Note data. I'd recommend not using arrays either but rather an ArrayList<Note> which is more flexible.

In Melody, I'd tie the Note to a Measure and a Beat, and would give the Melody class an addNote(Note, int measure, int beatFraction), same for remove Note.

Consider making your 12 core notes as enums, and then use them plus an octave int to create a Note object.

... there are many ways to play with this exercise. The "key" is to keep on experimenting.

like image 145
Hovercraft Full Of Eels Avatar answered Sep 25 '22 21:09

Hovercraft Full Of Eels


What comes in mind is implementing a simple internal DSL which will be as close as possible to the notation you use to write down the music notes. In java it could look like

MelodyTrack  track1 = MelodyTrack().create().setTiming(TimeSignature.C)
.eighth(Notes.E5)
.bar().half(Notes.B5).quarter(Notes.A5).quarter(Notes.B5).bar().half(Notes.C6)

there is a good book on DSLs, written by Martin Fowler

This is just an example of how it could look like, I do not insist on one form or another - the basic idea is that your DSL must be readable both by the programmers and domain-experts(musicians). And the way the data is represented in your sequencer should not affect the way you write down the melodies i.e. to make it harder.

P.S. If you are doing something serious, you should try to use an external DSL a.k.a. a midi file or something like that and a sequencing library of some kind, and to store music in the separate resource files of your application.

like image 22
Boris Treukhov Avatar answered Sep 24 '22 21:09

Boris Treukhov