Home
CBM
  ASCII-X
  BASIC
    Disk Commands
    Enter RUN mode
    Program Format
    Secret Variables
    Variable Format
    Expressions
    Keywords
      (divide)
      (equal)
      (less)
      (minus)
      (more)
      (multiply)
      (plus)
      (power)
      Abs
      And
      Append
      Asc
      Atn
      Auto
      Backup
      Bank
      Begin
      Bend
      Bload
      Boot
      Box
      Bsave
      Bump
      Catalog
      Char
      Chr
      Circle
      Close
      Clr
      Cmd
      Collect
      Collision
      Color
      Concat
      Cont
      Copy
      Cos
      Data
      Dclear
      Dclose
      Dec
      Def
      Delete
      Dim
      Directory
      Dispose
      Dload
      Do
      Dopen
      Draw
      Ds
      Ds string
      Dsave
      Dverify
      El
      Else
      End
      Envelope
      Er
      Err
      Exit
      Exp
      Fast
      Fetch
      Filter
      Fn
      For
      Fre
      Get
      Get num
      Getkey
      Go
      Gosub
      Goto
      Graphic
      Gshape
      Header
      Help
      Hex
      If
      Input
      Input num
      Instr
      Int
      Joy
      Key
      Left
      Len
      Let
      List
      Load
      Locate
      Log
      Loop
      Mid
      Monitor
      Movspr
      New
      Next
      Not
      Off
      On
      Open
      Or
      Paint
      Peek
      Pen
      Pi
      Play
      Pointer
      Poke
      Pos
      Pot
      Print
      Print num
      Pudef
      Quit
      Rclr
      Rdot
      Read
      Record
      Rem
      Rename
      Renumber
      Restore
      Resume
      Return
      Rgr
      Right
      Rlum
      Rnd
      Rreg
      Rspcolor
      Rsppos
      Rsprite
      Run
      Rwindow
      Save
      Scale
      Scnclr
      Scratch
      Sgn
      Sin
      Sleep
      Slow
      Sound
      Spc
      Sprcolor
      Sprdef
      Sprite
      Sprsav
      Sqr
      Sshape
      St
      Stash
      Step
      Stop
      Str
      Swap
      Sys
      Tab
      Tan
      Tempo
      Then
      Ti
      Ti string
      To
      Trap
      Troff
      Tron
      Until
      Using
      Usr
      Val
      Verify
      Vol
      Wait
      While
      Width
      Window
      Xor
    Syntax
    Tokens
  C128
  D64plus
  Disk
  Escape Codes
  Hardware
  PCxface
  PETSCII
  Pet2asc
Futurama
IBM PC-AT
Contact
Games
Glossary
Hall of fame
Hall of shame
Miscellaneous
Privacy policy
Programming
Twisty puzzles
KeywordAbbreviationToken (hex)Version(s)Classification
PLAYP{Shift+L}FE 047.0Command and Statement

 
 Syntax  
PLAY music
 
ParametersTypeLegal Value(s)Default ValueNote(s)
musicString0 ~ 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 parameterTypeLegal Value(s)Default ValueNote(s)
voiceNumeral"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)
MeaningRelative
duration
".W"dotted Whole note150% (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)
AliasMeaningRelative
frequency
Power of 21/12
R Rest - infinity 
"C""#B" prior octaveNatural C1.0000
"#C" "$D"Sharp C 1.059
"$D" "#C" Flat D 1.059
"D"  Natural D1.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 octaveSharp 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 parameterTypeLegal Value(s)Base Frequency
"Natural C"
Note(s)
octaveNumeral"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 numeralEquivalent VOLMaster
volume
"0"00% (silence)
"1"6.667% 
"2" 20.00% 
"3" 533.33%
"4" 46.67%
"5"853.33% 
"6" 10 66.67%
"7" 1280.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