Published using Google Docs
_New - ChAppendixB.Music Library Functions.doc
Updated automatically every 5 minutes

Making Music with Python

Bill Manaris and Andrew Brown

draft manuscript

(Copyrighted material - do not republish or share)

Appendix B:  Music Library Functions

To simplify making music, the Python Music library defines many musical functions for you.  These functions are organized in terms of four fundamental classes (Note, Phrase, Part, Score), and a few additional classes (Mod, Read, Write, View).  Each of these functions may have several flavors, giving you increasing control and expression over musical parameters.

These functions are presented below in terms of class.

Note Functions

Note objects contain the simplest possible musical events, consisting of pitch, duration, etc.  The music library provides several functions to create musical notes.  It also provides several others to retrieve or modify attributes (e.g., pitch) or existing notes. You can often choose to either modify an existing note, or create a new one with the proper attributes.  The decision depends on the context.  Pick the option that appears more natural or efficient (to you, to the computer, or both).

Here are functions used to create musical notes.  Each of these functions creates a new Note object, so you need to save it in a variable (or other memory location).

Function

Description

Note(pitch, duration)

Creates a new note, where pitch is 0-127, and duration is a float (e.g., 1.0 is a quarter note).

Note(pitch, duration, dynamic)

Creates a new note, where pitch is 0-127, duration is a float, and dynamic is 0-127.

Note(pitch, duration, dynamic, pan)

Creates a new note, where pitch is 0-127, duration is a float, dynamic is 0-127, and pan is 0.0 (left) to 1.0 (right).

Below are functions used to retrieve and modify attributes of existing notes.  It is assumed that a note has already been created, for example, as follows:

   
           n = Note(C4, HN)

Function

Description

n.getPitch()

Retrieves the pitch (0-127) of note n.

n.setPitch(pitch)

Sets the pitch (0-127) of note n.

n.getDuration()

Retrieves the duration (a float) of note n.

n.setDuration(duration)

Sets the duration (a float) of note n.

n.getDynamic()

Retrieves the dynamic (0-127) of note n.

n.setDynamic(dynamic)

Sets the dynamic (0-127) of note n.

n.getPan()

Retrieves the pan (0.0-1.0) of note n.

n.setPan(pan)

Sets the pan (0.0-1.0) of note n.

n.isRest()

Checks if note n is a rest or a note with pitch.  Returns a Boolean value (True or False).

n.copy()

Returns a new note with the same attributes as note n.  This is used to create a copy to be modified, while the original note is not affected.

Finally, here are some helper note functions:

Function

Description

Note.freqToMidiPitch(freq)

Converts freq (a float) in Hertz (e.g., 440.0) to the equivalent MIDI pitch (e.g., 69).

Note.midiPitchToFreq(pitch)

Converts pitch (0-127) from a MIDI value to the equivalent frequency in Hertz (a float).

Phrase Functions

Phrase objects contain a sequence of Note objects.  These Note objects are played sequentially (i.e., one after the other).  If a gap is desired between two notes, then a Rest note should be introduced.  Phrases may also contain chords (i.e., sets of concurrent notes).

Phrases have start times.  If no start time is specified, then the phrase starts at the end of the previous phrase (or at the beginning of the piece, if this is the first phrase).

The music library provides several functions to create musical phrases.  It also provides several others to retrieve or modify existing phrases.  

Here are functions used to create phrases.  Each of these functions creates a new Phrase object, so you need to store it in a variable (or other memory location) to be able to use it later.

Function

Description

Phrase()

Creates an empty phrase. This phrase starts at the end of the previous phrase (or at the beginning of the piece, if this is the first phrase).

Phrase(startTime)

Creates an empty phrase starting at specified time (e.g., 0.0 is beginning of piece, 1.0 is a quarter note into the piece, etc.).

Phrase(note)

Creates a phrase containing the specified note.

Below are functions used to retrieve and modify attributes of existing phrases.  It is assumed that a phrase has already been created, for example, as follows:

   
            phr = Phrase()

Function

Description

phr.addNote(note)

Appends the given note to the phrase.

phr.addNote(pitch, duration)

Appends a new note of given pitch (0-127) and duration (a float) to the phrase.

phr.addNoteList(listOfPitches, listOfDurations,
listOfDynamics,
listOfPanoramics
)

Appends the notes specified in terms of pitches (a list), durations (a list), dynamics (a list), and panning values (a list) to the phrase. The lists are parallel.  Dynamics and panoramics lists are optional.

phr.addChord(listOfPitches, duration, dynamics, panoramics)

Appends a chord containing the specified pitches (a list) and having the specified duration (a float), dynamics (0 - 127), and panoramics (0.0 - 1.0).  Dynamics and panoramics values are optional.

phr.getEndTime()

Returns the phrase’s end time (a float).

phr.getNoteList()

Returns the phrase’s notes (a list).

phr.getSize()

Returns the number of notes in phrase phr.

phr.getStartTime()

Returns the phrase’s start time (a float).

phr.setStartTime(startTime)

Sets the phrase’s startTime (a float).

phr.setDynamic(dynamic)

Set the dynamic (0 – 127) of the phrase.

phr.copy()

Returns a new phrase with the same notes and attributes as phrase phr.  This is used to create a copy to be modified, while the original phrase is not affected.

phr.empty()

Removes all notes from phrase phr.

Part Functions

A Part object contains a set of Phrase objects to be played by a particular instrument.  These phrase objects are played in parallel (i.e., simultaneously), and thus may overlap (according to their start times and durations).  Even if the particular instrument does not allow for polyphony (e.g., a flute), a part using this instrument can have different simultaneous melodies.  In other words, a part can be thought of as a group of several instruments of the same type (e.g., flutes), each playing a different melody (a phrase).

There are 128 different instruments to pick from (see Appendix A).

Parts may have a title (a string).  

Parts may also be assigned to one of sixteen MIDI channels (0 – 15) available on a standard computer’s audio system.  Each MIDI channel is capable of playing any of the 128 different instruments possible, but only one at a time. So, it is important to keep parts using different instruments in different MIDI channels. If two parts are using the same instrument, they may be assigned to the same MIDI channel.  

It should be noted that MIDI channel 9 is reserved for percussion sounds.  Regardless of a part’s selected instrument, if that part is assigned to MIDI channel 9, its notes will generate percussion sounds, based on the notes’ pitches (see Appendix A).

The music library provides several functions to create musical parts.  It also provides several others to retrieve or modify existing parts.

Here are functions used to create parts.  Each of these functions creates a new Part object, so you need to save it in a variable (or other memory location).

Function

Description

Part()

Creates an empty part.

Part(instrument)

Creates an empty part with the timbre of the specified instrument (0 – 127).

Part(instrument, channel)

Creates an empty part with the timbre of the specified instrument (0 – 127), and using the specified MIDI channel (0 – 15).

Part(title, instrument, channel)

Creates an empty part with the specified title (a string), with the timbre of the specified instrument (0 – 127), and using the specified MIDI channel (0 – 15).

Part(phrase)

Creates a Part containing the specified phrase.

Below are functions used to retrieve and modify attributes of existing parts.  It is assumed that a part has already been created, for example, as follows:

part = Part("An example flute part", FLUTE, 0)

This creates a part with a descriptive title, using instrument FLUTE (see Appendix A, for a complete list of instruments), and assigned to MIDI channel 0 of the computer’s audio system.  Again, you should assign parts with different instruments to different MIDI channels (0-8, and 10-15).  Remember that MIDI channel 9 is dedicated to percussive sounds, as explained above.

Function

Description

part.addPhrase(phrase)

Add a phrase to this part.  If the phrase does not have a specific start time, it is added to the end of the part.

part.addPhraseList(listOfPhrases)

Adds the specified phrases (a list) to the part. If a phrase does not have a specific start time, it is added to the end of the part.

part.copy()

Returns a new Part with the same phrases and attributes as part.  This is used to create a copy to be modified, while the original part is not affected.

part.empty()

Removes all phrases from this part.

part.getChannel()

Returns the channel for this part.

part.getEndTime()

Returns the part’s end time (a float).

part.getInstrument()

Returns the part’s instrument number (MIDI program change).

part.getPhraseList()

Returns the part’s phrases (a list).

part.getSize()

Returns the number of phrases in this part.

part.getTempo()

Returns the part’s tempo (a float).

part.getTitle()

Returns the part’s title (a string).

part.getVolume()

Returns the part’s volume (0 – 127).

part.setChannel(channel)

Sets the MIDI channel for this part (0 – 15).

part.setInstrument(instrument)

Set instrument number (MIDI program change) for this part (0 – 127).

part.setPan(pan)

Sets the pan position for all notes in this part (0.0 – 1.0).

part.setTempo(tempo)

Sets the part’s tempo (a float).

part.setTitle(title)

Give the part a new title (a string).

part.setDynamic(dynamic)

Set the part’s dynamic (0 – 127). 

Score Functions

A Score object contains a set of Part objects.  Score contents (parts, phrases, notes) are algorithmically generated, or read from a standard MIDI file (see Read.midi()).  Scores can be written to standard MIDI files (see Write.midi()).

The music library provides several functions to create musical scores.  It also provides several others to retrieve or modify existing scores.

Here are functions used to create scores.  Each of these functions creates a new Score object, so you need to save it in a variable (or other memory location).


Function

Description

Score()

Creates an empty score.

Score(title)

Creates an empty score with the specified title (a string).

Score(tempo)

Creates an empty score with the specified tempo (in beats-per-minute, e.g., 120.0).

Score(title, tempo)

Creates an empty score with the specified title (a string), and with the specified tempo (in beats-per-minute, e.g., 120.0).

Score(part)

Creates a score containing the specified part.

Below are functions used to retrieve and modify attributes of an existing Score object.  It is assumed that a score has already been created, for example, as follows:

   
score = Score(
"Morning glory", 135.0)

This creates a score with the descriptive title “Morning glory”, with a tempo of 135 beats per minute.  

Function

Description

score.addPart(part)

Add a part to this score.

score.addPartList(listOfParts)

Adds the specified parts (a list) to the score.

score.copy()

Returns a new score with the same parts and attributes as score.  This is used to create a copy to be modified, while the original score is not affected.

score.empty()

Removes all parts from this score.

score.getDenominator()

Returns the time signature denominator for this score.

score.getEndTime()

Returns the score’s end time (a float).

score.getKeyQuality()

Returns the score's key quality (0 is Major, 1 is minor).

score.getKeySignature()

Returns the score’s key signature (as an integer).  Zero (0) means the score is in the key of C.  A positive (+) integer indicates the number of sharps, whereas a negative (–) integer indicates the number of flats.

score.getNumerator()

Returns the time signature numerator for this score.

score.getPartList()

Returns the score’s parts (a list).

score.getSize()

Returns the number of parts in this score.

score.getTempo()

Returns the score’s tempo (a float).

score.getTitle()

Returns the score’s title (a string).

score.getVolume()

Returns the score’s volume (0 – 127).

score.setDenominator(denominator)

Sets the time signature denominator for this score.

score.setKeyQuality(quality)

Sets the score's key quality (0 is Major, 1 is minor).

score.setKeySignature(signature)

Sets the score’s key signature (as an integer).  Zero (0) means the score is in the key of C.  A positive (+) integer indicates the number of sharps, whereas a negative (–) integer indicates the number of flats.

score.setNumerator(numerator)

Sets the time signature’s numerator for this score.

score.setPan(pan)

Sets the pan position for all notes in this score (0.0 – 1.0).

score.setTempo(tempo)

Sets the score’s tempo (in beats-per-minute, e.g., 120.0).

score.setTimeSignature(num, den)

Specifies the score’s time signature (i.e., num / den).

score.setTitle(title)

Give the part a new title (a string).

View Functions

There are a number of functions to help you visually display music in Python. These are part of the View class.  Of these functions, notation(), sketch(), and pianoRoll() also allow adding new notes to the musical material being displayed.  However, these notes cannot be saved back to the original program (that called the View functions) - only to an external MIDI file.  

Function

Description

View.notation(material)

Display the phrase as staff notation, where material may be a Score, Part or Phrase.

View.internal(material)

Print out the music data to the screen, where material may be a Score, Part or Phrase.

View.sketch(material)

Display the music as a small piano-roll display, where material may be a Score, Part or Phrase.

View.pianoRoll(material)

Display the music as a piano-roll display, where material may be a Score, Part or Phrase.

Mod Functions

The Mod class contains many functions for modifying, or varying, phrases, parts and scores. Each of this functions modifies the data passed to them.  For example, the Mod.repeat() function creates repetitions of the given musical material.  It is called like this:

Mod.repeat(phrase, 41)

This will modify phrase to contain a total of 41 copies of the original musical material.

Below are the available Mod functions.  You may apply these functions repeatedly to achieve a desired effect.

Function

Description

Mod.accent(material, beats)

Accents the first beat of each measure in material. Beats (a float) is the number of beats per measure.  Material may be a Phrase, Part, or Score.

Mod.accent(material, meter, accentedBeats, accentAmount)

Accents by accentAmount (an int) at the accentedBeats locations (a list of floats, denoting time in quarter notes). Meter (a float) is the number of beats per measure.  Material may be a Phrase, Part, or Score.

Mod.append(material1, material2)

Appends material2 to material1. Works with notes, phrases, parts, and scores.  In the case of notes, it extends the duration value of the first note (without changing its pitch).

Mod.bounce(material)

Adjusts the pan values of all notes in material  to alternate between extreme left and right from note to note. Material may be a Phrase, Part, or Score.

Mod.changeLength(phrase, newLength)

Alters the phrase so that its notes are stretched or compressed until the phrase is the specified length (number of beats - a float).  It works in the same manner as elongate(), except it takes an absolute length parameter not a ratio.

Mod.compress(material, ratio)

Compresses (or expands) the material. Compression ratio numbers between 0 and 1.  Values larger than 1 expand.  Negative values invert the volume about the mean. This compression applies only to the volume of the notes.  It will multiply the difference between each note’s volume and the volume, by the compression ratio.  Thus, a ratio of 0 will change every note's volume to the average volume; 1 will leave every note unchanged; and 2 will make every note's volume twice as far from the mean. Negative values will have a similar affect but leave the volume of each note on the other side of the mean. Material may be a Phrase, Part, or Score.

Mod.consolidate(part)

Merges parts phrases into one phrase.  This works well with View.notate(part), so that notate() can display all the notes in the part (View.notate() works only with a single phrase).

Mod.cycle(material, numberOfNotes)

Repeats the material until it contains the specified number of notes.  The repetitions work in the same manner as Mod.repeat(), except that the final repetition will not be a complete copy of the original if the note count is reached before the repetition is completed.  Material may be a Phrase, Part, or Score.

Mod.elongate(material, scaleFactor)

Stretch the time of each note in the phrase by scaleFactor (a float). Material may be a Phrase, Part, or Score.

Mod.fadeIn(material, fadeLength)

Linearly fades in the material (fadeLength is quarter notes). Material may be a Phrase, Part, or Score.

Mod.fadeOut(material, fadeLength)

Linearly fades out the material (fadeLength is quarter notes). Material may be a Phrase, Part, or Score. 

Mod.fillRests(material)

Lengthens notes followed by a rest in material by creating one longer note and deleting the rest. This will reduce the overall note count. Material may be a Phrase, Part, or Score.

Mod.invert(material)

Mirror the pitch of notes in the material around the first note's pitch. The order of the notes is not affected it is only the pitches that are mirrored.  That is, notes which are n semitones above the first pitch will be changed to be n semitones below. Material may be a Phrase, Part, or Score.

Mod.mutate(phrase)

Mutate phrase by changing one pitch and one duration value.  The new pitch is selected randomly between the lowest and the highest note of phrase.  The random duration is selected from those in the existing notes.

Mod.palindrome(material)

Extend the phrase by adding all notes backwards, repeating the last note of the material. Material may be a Phrase, Part, or Score.

Mod.randomize(material, pitchVariation, durationVariation, dynamicVariation)

Randomly adjusts every note’s pitch, duration, and dynamic values to a random value within the range plus or minus the specified amount; pitchVariation is an int (make sure result stays within 0-127); durationVariation is a float (e.g., 1.0 is a quarter note); dynamicVariation is an int (make sure result stays within 0-127). Material may be a Phrase, Part, or Score.

Mod.repeat(material, number)

Repeat the material a number of times.  Material may be a Phrase, Part, or Score. For example, Mod.repeat(phrase, 2) will play phrase two times.

Mod.retrograde(material)

Reverse the order of notes in the material. Material may be a Phrase, Part, or Score.

Mod.rotate(material)

Move the notes around the material, first becoming second, second becoming third, ... and last becoming first. Material may be a Phrase, Part, or Score.

Mod.shake(material)

Randomly adjusts the volume of notes to create uneven loudness. Material may be a Phrase, Part, or Score.

Mod.shake(material, amount)

Randomly adjusts the volume of notes to create uneven loudness. Amount (an int) denotes how strong the effect will be, e.g., 5 will be +/-5 from the current volume. Material may be a Phrase, Part, or Score.

Mod.shuffle(material)

Randomise the order of notes in the material without repeating any note. Material may be a Phrase, Part, or Score.

Mod.spread(material)

Randomly adjusts the pan values of all notes in material to create an even spread across the stereo spectrum. Material may be a Phrase, Part, or Score.

Mod.tiePitches(material)

Joins consecutive notes in material that have the same pitch, creating one longer note. This is similar to the musical function of a tie. This will reduce the overall note count. Material may be a Phrase, Part, or Score.

Mod.tieRests(material)

Joins consecutive rests in material creating a longer note. This is similar to the musical function of a tie. This will reduce the overall note count. Material may be a Phrase, Part, or Score.

Mod.transpose(material, semitones)

Chromatic transposition. It shift the pitch of every note in the material by the given number of semitones. Material may be a Phrase, Part, or Score.

Mod.transpose(material, steps, scale, key)

Diatonic transposition. It shift the pitch of every note in the material by the given number of scale degrees (steps), given the scale and key. Material may be a Phrase, Part, or Score.  Key is an integer (0 means the key of C, a positive integer indicates the number of sharps, whereas a negative integer indicates the number of flats).   See Appendix A for a list of available scales.

11