# 7. Sound The sound verbs need the SDL build and an audio device. Without one they refuse by name, and a machine with no sound card still runs the interpreter — only `SOUND` and `PLAY` fail, and they say so. ## SOUND ``` 10 SOUND 1, 4000, 60 ``` Voice, frequency, duration. Voices are numbered from 1. The duration is in *jiffies* — sixtieths of a second — as on a C128, so 60 is one second. Further arguments give a frequency sweep: a step, a direction and a range, which is what makes a siren or a laser. **`SOUND` does not block.** On a C128 the note starts and the program carries on; here the same is true, and it has to be — an embedded interpreter that stopped the host's frame loop for a second would freeze the game. ## PLAY `PLAY` takes a string of notes: ``` 10 PLAY "C D E F G" ``` Within the string: | | | |---|---| | `A` to `G` | a note | | `#` `$` | sharp, flat | | `O` *n* | octave | | `V` *n* | voice | | `T` *n* | envelope preset | | `U` *n* | volume | | `W`, `H`, `Q`, `I`, `S` | whole, half, quarter, eighth, sixteenth notes | | `R` | rest | | `.` | dotted | Notes are queued and released in time, paced by the host's clock. A program that `PLAY`s and then carries on works the way you expect; a program that `PLAY`s and then immediately `QUIT`s may not hear all of it. `M` — measure — is accepted and does nothing. There is no bar-line accounting to do. ## TEMPO ``` 10 TEMPO 8 ``` How fast `PLAY` releases its queue. The number is the same range a C128 uses; the constant that turns it into milliseconds is a calibration choice rather than a transcription, so it may not match a real machine exactly. ## ENVELOPE and VOL ``` 10 ENVELOPE 0, 5, 9, 4, 6 20 VOL 8 ``` `ENVELOPE` defines one of the ten presets `PLAY`'s `T` selects: attack, decay, sustain and release. `VOL` sets the overall volume, 0 to 15. ## FILTER `FILTER` parses and then **refuses at execution**: ``` ? 10 : RUNTIME ERROR FILTER needs an audio device that can filter, and this one cannot ``` It sets the SID's filter cutoff, band switches and resonance. The audio backend synthesises raw waveforms and mixes them; there is no filter stage to configure and SDL supplies no primitive to build one from. Refusing is deliberate — a program that asks for a low-pass and gets an unfiltered square wave has been lied to. This is the one verb still waiting on a capability from the graphics library. It is filed there rather than worked around here. ## The clock Everything with a duration — `SOUND`, `PLAY`, `TEMPO`, and `SLEEP` from Chapter 2's neighbourhood — is paced by a clock the *host* provides. The standalone interpreter sets it from a monotonic timer every step, so it just works. An embedded host that never sets the clock gets durations that expire immediately: audible, but never a hang. That is the intended failure direction.