Play

Play provides various functions to play musical material stored in Note, Phrase, Part, and Score objects.

There are three options.  You may play

  • MIDI music (using the MIDI synthesizer),
  • microtonal music (using standard MIDI instruments), and
  • music using audio files as instruments (very powerful!).

Playing MIDI material

The first function, Play.midi(), is used to play musical material stored in Note, Phrase, Part, and Score objects via the Java MIDI synthesizer.

Function Description
Play.midi(material) Play musical material through the Java synthesizer (material may be a Note, Phrase, Part, or Score).

The other Play functions are more advanced, and are intended for building interactive musical instruments.

Play.noteOn(pitch, volume, channel) Starts pitch sounding.  Specifically, it sends a NOTE_ON message with pitch (0-127), at given volume (0-127 – default is 100), to played on  channel (0-15 – default is 0) through the Java synthesizer.
Play.noteOff(pitch, channel) Stops pitch from sounding.  Specifically, it sends a NOTE_OFF message with pitch (0-127), on given channel (0-15 – default is 0) through the Java synthesizer.  If the pitch is not sounding on this channel, this has no effect.
Play.note(pitch, start, duration, volume, channel) Plays a note with pitch (0-127) to be sounded after start milliseconds, lasting duration milliseconds, at given volume (0-127 – default is 100), on  channel (0-15 – default is 0) through the Java synthesizer.
Play.allNotesOff() Stops all notes from sounding on all channels.

You can also make global changes interactively on instrument, volume, panning, and pitch bend.

Play.setInstrument(instrument, channel) Sets a MIDI instrument (0-127 – default is 0) for the given channel (0 – 15, default is 0).  Any notes played through channel will sound using instrument.
Play.getInstrument(channel) Returns the MIDI instrument (0-127) assigned to channel (0 – 15, default is 0).
Play.setVolume(volume, channel) Sets the global (main) volume (0-127) for this channel (0-15)  This is different from the velocity level of individual notes – see Play.noteOn().
Play.getVolume(channel) Returns the global (main) volume (0-127) for this channel (0-15).
Play.setPanning(position, channel) Sets the global (main) panning position (0-127) for this channel (0-15)  The default position is in the middle (64).

NOTE: Global panning does not affect the panning of a score being played through Play.midi() or Play.audio().

Play.getPanning(channel) Returns the global (main) position (0-127) for this channel (0-15).
Play.setPitchBend(bend, channel) Sets the pitch bend for this channel (0-15 – default is 0) to the Java synthesizer object. Pitch bend ranges from -8192 (max downward bend) to 8191 (max upward bend).  No pitch bend is 0 (this is the default).
Play.getPitchBend(channel) Returns the current pitch bend for this channel (0-15 – default is 0).

Playing Microtonal material

You may also play microtonal material.

This is done simply by creating Note objects using float (e.g., 443.1) pitch, such as

from music import *

note = Note(443.1, HN)     # create a note a bit over A4 (440.0)
Play.midi(note)            # and play it!

WARNING: For polyphony (to play concurrent microtonal notes), you must play notes on different MIDI channels.

The MIDI standard does not support microtones.  Microtones are rendered here using MIDI pitch bend.  However, there is only one pitch bend per channel.  Therefore, you need to spread concurrent notes across channels.  (Also, remember that channel 9 is special – percussion only.)

One way to do this is to create a different Phrase per voice, and store it in its own Part assigned to a unique channel. Another way is to use Play.noteOn() and send notes on different channels.

All other Play functions will work as documented.


Playing Audio material

You may also play music using audio files as instruments.

This is done by using the Play.audio() function.

Function Description
Play.audio(material, listOfAudioSamples, listOfEnvelopes) Play musical material using the provided AudioSamplesas instruments (with corresponding optional envelopes).

Material may be a Note, Phrase, Part, or Score.

Play.audio() works similarly to Play.midi(), except that it requires an additional parameter, the list of audio files that will be used as instruments to play the musical material.  There should be at least as many audio samples as channels being used.

Here is an example (a variation on furElise.py in Ch. 3):

# furElise.py
# Generates the theme from Beethoven's Fur Elise...
# using Moondog's "Bird's Lament" audio sample as instrument
# for rendering sound.

from music import *

# theme has some repetition, so break it up to maximize economy
# (also notice how we line up corresponding pitches and durations)
pitches1 = [E5, DS5, E5, DS5, E5, B4, D5, C5]
durations1 = [SN, SN, SN, SN, SN, SN, SN, SN]
pitches2 = [A4, REST, C4, E4, A4, B4, REST, E4]
durations2 = [EN, SN, SN, SN, SN, EN, SN, SN]
pitches3 = [GS4, B4, C5, REST, E4]
durations3 = [SN, SN, EN, SN, SN]
pitches4 = [C5, B4, A4]
durations4 = [SN, SN, EN]

# create an empty phrase, and construct theme from the above motifs
theme = Phrase()
theme.addNoteList(pitches1, durations1)
theme.addNoteList(pitches2, durations2)
theme.addNoteList(pitches3, durations3)
theme.addNoteList(pitches1, durations1) # again
theme.addNoteList(pitches2, durations2)
theme.addNoteList(pitches4, durations4)

# play it
a = AudioSample("moondog.Bird_sLament.wav", G4) # load an audio file

#Play.midi(theme)
Play.audio(theme, [a])

WARNING: For polyphony (to play concurrent notes), you must play notes on different channels.

AudioSamples do not support polyphony. Therefore, you need to spread concurrent notes across channels. (One channel per audio file.)

One way to do this is to create a different Phrase per voice, and store it in its own Part assigned to a unique channel. Another way is to use Play.audioOn() – see below.

The following Play audio functions are also available:

Play.audioOn(pitch, audioSample, velocity, panning) Starts pitch sounding using the given audio sample, with a given pitch (0-127), at given velocity (0-127 – default is 127), with a given panning (default uses the global panning set with setPanning()).
Play.audioOff(pitch, audioSample) Stops pitch from sounding   If the pitch is not sounding via this audio sample, this has no effect.
Play.audioNote(pitch, start, duration, audioSample, velocity, panning, envelope) Plays a note with pitch (0-127) to be sounded after start milliseconds, lasting duration milliseconds, using a given audio sample at given velocity (0-127 – default is 127), with a given panning (default uses the global panning set with setPanning()) and a given envelope (if no envelope is given, a default is used).
Play.allAudioNotesOff() Stops all notes from sounding on all audio samples.

Audio Envelopes

Finally, each AudioSample used as an instrument may be assigned a corresponding Envelope to help shape its attack, delay, sustain, and release.

NOTE: This can help create very interesting musical “instruments” from existing sounds  (recorded or downloaded audio files).

For more information, see the Envelope class.