Commodore‎ > ‎BASIC‎ > ‎Keywords‎ > ‎

PLAY

Keyword Abbreviation Token (hex) Version(s) Classification
PLAY P{Shift+L} FE 04 7.0 Command and Statement

 
  Syntax   
PLAY music
 
Parameters Type Legal Value(s) Default Value Note(s)
music String 0 ~ 255 chars
See remarks for valid characters
 
 
  Purpose  
Audio generation (or state management).  Plays a series of musical notes (typically).

 
  Remarks  
PLAY parses a string, music, and performs the "commands" within.  It is like a mini-language within BASIC.  Most commands will be voice selection, a musical note, or an octave change.  Each command begins with a single letter and may (depending on command) be followed by a parameter; a "note" is a special case that is built of two commands: a duration and a pitch.  Spaces may be used in music for legibility to the programmer; they have no effect on how commands are processed.
 
While the mini-language is a bit complex, if you are familiar with (western) music notation and the English language, then it shouldn't be too difficult to grasp.  Generally much easier than using a long list of DATA statements containing machine-specific frequency values (typically used in pre-7.0 versions of BASIC).  Another nice thing is that once you get a piece of music written successfully, you can alter the way it is "performed" with related statements ENVELOPE, FILTER, TEMPO, and VOL.
 
To play a note, BASIC needs three pieces of information: the voice to use, the duration of the note, and the pitch of the note.
 
First consider the voice parameter (V), because it is rather simple. 
V parameter Type Legal Value(s) Default Value Note(s)
voice Numeral "1" ~ "3"
Selects a SID voice for the next note
BASIC can play up to three voices simultaneously.  The limit of three is imposed by the SID audio chip.  Several properties of each voice are set with ENVELOPE.  The voice selected in the music string will be effective for all following notes, or until another voice is specified.  (That is, it does not have to be given for each note.)
 
The next thing BASIC needs to play a note is a duration, given (primarily) by a specific character.  Optionally, a note duration may be extended by 50% by using one (or more) dots before the pitch character; however unlike real music notation, PLAY does not understand the concept of a double-dotted (or tripple-dotted, etc.) note.  It also does not matter where the dot appears, as long as it appears before the pitch character(s) (described below).  Any more than one dot is unnecessary and will be treated as a single dot.  All durations are relative to the current TEMPO.  The primary duration character will remain in effect for all following notes, or until the next primary duration character is encountered (so it isn't needed for every note).  However the dot character only affects the next pitch character(s) .
Duration
Character(s)
Meaning Relative
duration
".W" dotted Whole note 150% (48/32)
"W" Whole note (1)  100% (32/32) 
".H"  dotted Half note  75% (24/32) 
"H"  Half note (1/2) 50% (16/32) 
".Q"  dotted Quarter note  37.5% (12/32) 
"Q" Quarter note (1/4) 25% (8/32) 
".I"  dotted eIghth note  18.75% (6/32)
"I"  eIghth note (1/8) 12.5% (4/32) 
".S"  dotted sixteenth note  9.375% (3/32) 
"S"  sixteenth note (1/16)  6.25% (2/32) 
 
The third and final thing BASIC needs to play a note is a pitch (relative frequency), given (primarily) by a letter A to G.  This specifies one of seven primary notes in an octave [sic].  Optionally, a primary pitch character may be preceded by a flat or sharp character ("$" or "#" respectively).  Unlike the dot (see duration above), the sharp/flat character must precede the primary pitch character.  Like the dot character, a sharp/flat may occur anywhere before the primary pitch character, it may occur multiple times, it only affects the next primary pitch character, and BASIC has no concept of double (tripple, etc.) sharp/flat notes.  If sharp(s) and flat(s) are both specified prior to a primary pitch character, the last one will used (so, for example, a flat followed by sharp will not produce a neutral but a sharp).  A sharp will select the next-higher value of the twelve extended notes (semi-tones [sic]) in an octave [sic].  A flat will select the next-lower value of the twelve extended notes (semi-tones [sic]) in an octave [sic].  Conceptually, the pitch specifies a frequency relative to the current octave (described below).  A special character, R, indicates a rest.  A rest has a duration like all notes, but it has no frequency because it is not a "real note" but rather the absense of a note (conceptually, a note of zero frequency).
Pitch
Character(s)
Alias Meaning Relative
frequency
Power of 21/12
R   Rest  - infinity 
"C" "#B" prior octave Natural C 1.000 0
"#C"  "$D" Sharp C  1.059
"$D"  "#C"  Flat D  1.059
"D"    Natural D 1.122 
"#D"  "$E"  Sharp D  1.189 
"$E"  "#D"  Flat E  1.189 
"E"  "$F" Natural E  1.260 
"$F"  "E"  Flat F [sic]  1.260 
"#E"  "F"  Sharp E [sic]  1.335 
"F"  "#E"  Natural F  1.335 
"#F"  "$G"  Sharp F  1.414 
"$G"  "#F"  Flat G  1.414 
"G"    Natural G  1.498 
"#G"  "$A"  Sharp G  1.587 
"$A"  "G#"  Flat A  1.587 
"A"    Natural A  1.682 
"#A"  "$B"  Sharp A  1.782  10 
"$B"  "#A"  Flat B  1.782  10 
"B"  "$C" next octave  Natural B  1.888  11 
"$C" next octave "B"  Flat C [sic]  1.888  11 
"#B"  "C" next octave Sharp B [sic]  2.000  12 
Now there are several details that may be relevant.  Rests do not actually play a zero-frequency note, but simply wait the appropriate duration before playing the next note in the same voice.  This technical detail affects the way a voice with a large release value will sound (see T parameter, below).  For real (non-rest) notes, PLAY takes the highest-possible octave value of a note and, when needed, successively divides the frequency by two until the correct octave is obtained.  Usually this is equivalent to the concept described above; however in the case of a "Sharp B" it results in an intermediate overflow in the highest octave (6).  This does not generate an error, but obviously sounds wrong compared to other octaves (however, because "Sharp B" is not defined in contemporary music anyway, this is not too surprising).  Interestingly in western music, although there are 7 primary notes per octave [sic], there are only 12 (not 14) extended notes per octave [sic].  This extended set of notes are often referred to as semi-tones (which would be technically correct if there were 14 of them).  Anyway, two of the primary notes do not have a sharp (B and E as it turns out), and the next-higher primary notes of those (C and F) do not have flats.  However, BASIC does not understand these exceptions; it treats a "sharp B" [sic] as "natural C", "sharp E" [sic] as "natural F", "flat C" [sic] as "natural B", and "flat F" [sic] as "natural E".  Finally, the exceptional "Flat C" belongs to the next-lower octave (Natural B) and, similarly, the exceptional "Sharp B" belongs to the next-higher octave (Natural C).  This leads to the trivial fact that you can generate a note in the otherwise "illegal" octave of -1; you can generate "natural B octave -1" with "flat C octave 0".  A non-obvious consequence of the way PLAY works is that natural notes D and G are the only notes which have no alias.
 
The actual frequency generated for a note is based not only the pitch character(s), but the current "octave".  It is set simply with the O parameter: 
O parameter Type Legal Value(s) Base Frequency
"Natural C"
Note(s)
octave Numeral "0" ~ "6"
  1. 16.3 Hz
  2. 32.6 Hz
  3. 65.2 Hz
  4. 130 Hz
  5. 260 Hz
  6. 521 Hz
  7. 1043 Hz
Selects octave for current voice
BASIC remembers the octave assigned to each voice, and uses it for all notes of that voice until it is changed by another O parameter.  However, BASIC provides no way to read the current value of octave.  If you need to do that, you'll have to PEEK into a secret variable (actually an array).  Thankfully, the base frequency is adjusted for NTSC/PAL machine standards.  The rather arbitrary-looking values for Base Frequency result in a "Natural A" note in octave 2 having a frequency of 110 Hz.  Which is an (arbitrary) music standard.  Strangely, PLAY allows the not-so-useful octave 0 (might be okay for sound effects) but does not allow octave 7 at all (thus the maximum frequency BASIC can play is about 2 kHz, which isn't very high).  However an NTSC machine is capable of producing all notes in octave 7 and a PAL machine can produce all but the highest (Natural B).  Another problem with the O parameter is it only accepts a literal value between 0 and 6; it would be useful (perhaps more useful) to allow relative values; like O+ and O- or maybe single-character equivalents like "N" and "P" (for next and previous octave).  Because BASIC lacks "relative octaves" quite a bit of work must be done to a music string in order to play it in a different octave (unless you are lucky and all notes in music are in the same octave).
 
Four other commands are available with PLAY.  They are T, X, U, and M.  The "M" command ("measure end") is the simplest.  It takes no arguments and waits for all voices to finish before proceeding.  Normally, PLAY proceeds "non-stop" and only pauses when a "note" (real or rest) appears for a voice which is already playing.  For generating sound effects (rare with PLAY) it allows you to suspend execution of the BASIC program until your effect plays its full duration.  For actual music, this is a convenient short-cut for the author.  You can avoid writing rests for voice(s) in some cases.
 
The "U" command sets the master volume.  Unlike VOL which accepts a value 0 to 15, the "U" command requires a single numeral "0" ~ "9" to follow and sets the master volume according to the following table.  Unlike most PLAY commands, it affects all voices.
U numeral Equivalent VOL Master
volume
"0" 0 0% (silence)
"1" 6.667% 
"2"  20.00% 
"3"  5 33.33%
"4"  46.67%
"5" 8 53.33% 
"6"  10  66.67%
"7"  12 80.00% 
"8"  14  93.33% 
"9"  15  100.0%
 
The "X" command enables or disables the SID filter for the current voice.  It requires a single numeral "0" or "1" to follow which (respectively) disables or enables filtering (see FILTER).  An interesting side-effect is it waits for the current voice to finish playing before it actually updates the filter routing, so it is similar to the "M" command.
 
The "T" command selects an "instrument" ("Tone number") for the current voice.  It requires a single numeral "0" ~ "9" to follow which sets the voice to one of the "instruments" defined by ENVELOPE.  This affects several qualities of a voice simultaneously; in particular, the volume dynamics (attack, decay, sustain, and release) and the waveform.  This is usually one of the first commands used; which makes it ironic that I listed it last!
 
If any of the commands which take a parameter have a value which is not legal (as described in the appropriate section above), PLAY will (quite naturally) generate ILLEGAL QUANTITY ERROR.  If an unknown character is found, the same error is also generated (however, the error should logically be SYNTAX).
 
Examples (need lots more):
PLAY "V1 T0 Q A A A" : REM three sequential notes (all quarter notes, voice 1, "piano")

READY.
PLAY "V1 Q A V2 A V3 A" : REM three simultaneous notes, each a seperate voice (all quarter notes)

READY.
 
 
  Compare With  
 
  Contrast With  
  See Also  

© H2Obsession, 2014, 2017
Comments