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
ENVELOPEE{Shift+N}FE 0A7.0Command and Statement

 
 Syntax  
ENVELOPE toneNum [ , [ attack ] [ , [ decay ] [ , [ sustain ] [ , [ release ] [ , [ waveform ] [ , pulseWidth ] ] ] ] ] ]
 
ParametersTypeLegal Value(s)Default ValueNote(s)
toneNumUnsigned Byte0 ~ 9T parameter of PLAY
attackUnsigned Byte0 ~ 15*old value*Due to a bug, values up to 255 are accepted
decayUnsigned Byte0 ~ 15*old value*Due to a bug, values up to 255 are accepted
sustainUnsigned Byte0 ~ 15*old value*Due to a bug, values up to 255 are accepted
releaseUnsigned Byte0 ~ 15*old value*Due to a bug, values up to 255 are accepted
waveformUnsigned Byte 
  1. Triangle
  2. Sawtooth
  3. Rectangle
  4. Noise
  5. Triangle + Ring
old valueRing with ((voice - 1 -1) mod 3) +1.
pulseWidthUnsigned Integer0 ~ 4095old valueOnly used if waveform is 2 (rectangle).
 
 
 Purpose 
State management.  Define a PLAY "instrument" (toneNum).

 
 Remarks 
ENVELEOPE allows you to define an "instrument" to be used with PLAY.  This allows you to set several SID parameters for any voice used in a PLAY command/statement.  (The main parameter of a sound, frequency, is set by a "note" in PLAY.)  Although ENVELOPE provides several parameters to customize your "instrument", real musical instruments have complex waveforms that can not be immitated with only a handful of parameters.  So don't expect your "instruments" to sound much like anything real.
 
The toneNum is the only required parameter.  It is a number referring to a virtual "musical instrument" which may be used in subsequent PLAY statement(s) with a "T" parameter.  On power-up, BASIC defines the 10 toneNums shown in the following table.  Unfortunately, the values are not reset when a program is RUN, so any program that uses PLAY should use ENVELOPE before any PLAY statement.  Otherwise the last-defined "instrument" will be in effect and thus PLAY'd music may sound wrong.  Also, there is bug in the BASIC power-up routine: the low byte of each pulseWidth is never set, so the pulseWidth will be slightly random depending on the powe-up value of uninitialized RAM (therefore the table shows a range of values for pulseWidth).  On a related note, BASIC provides no way to read any of the parameters assigned to a toneNum.  To do so, you would need to PEEK one of several secret variables.
 
In any case, the pulseWidth only applies to a rectangular waveform, and the equivalent Duty Cycle (described later) is shown if applicable.  Importantly, any Duty Cycle greater than 50% is equilavant to another less than 50% and is shown where applicable.  The time-period parameters (described below) are shown in the table using the average of NTSC and PAL values; if you need more precision, see tables for those specific parameters.  Strangely, the "drum" (toneNum 3) has a non-zero sustain; percussion instruments should normally use zero.
 
 
toneNumDescriptionattackdecaysustainreleasewaveformpulseWidth
range
Duty Cycle
range
0Piano0: 2ms9: 750ms0: 0%0: 6ms2: rectangle1536 ~ 179137.5% ~ 43.7%
1Accordian12: 1000ms0: 6ms12: 80%0: 6ms1: sawtooth0 ~ 255
2Calliope0: 2ms0: 6ms15: 100%0: 6ms0: triangle0 ~ 255
3Drum0: 2ms5: 168ms5: 33.33%0: 6ms3: noise0 ~ 255
4Flute9: 250ms4: 114ms4: 26.67%0: 6ms0: triangle0 ~ 255
5Guitar0: 2ms9: 750ms2: 13.33%1: 24ms1: sawtooth0 ~ 255
6Harpischord0: 2ms9: 750ms0: 0%0: 6ms2: rectangle512 ~ 76712.5% ~ 18.7%
7Organ0: 2ms9: 750ms9: 60%0: 6ms2: rectangle2048 ~ 230350.0% ~ 56.2% 
43.8% ~ 50%
8Trumpet8: 100ms9: 750ms4: 26.67%1: 24ms2: rectangle512 ~ 767 12.5% ~ 18.7%
9Xylophone0: 2ms9: 750ms0: 0%0: 6ms0: triangle0 ~ 255
 
The attack, decay, and release values specify a machine-specific time period.  The attack period uses the following scale (three signifigant digits).  The attack determines the time it takes for the amplitude (volume) of a voice to rise from its current value (typically zero = silence) to peak chip amplitude (see VOL) when a "note" in a PLAY statment is first "struck".
attackNTSC TimePAL Time
01.96 ms2.04 ms
17.84 ms8.16 ms
215.7 ms16.3 ms
323.5 ms24.5 ms
437.3 ms38.8 ms
554.9 ms
57.1 ms
666.7 ms69.4 ms
778.4 ms81.6 ms
898.0 ms102 ms
9245 ms255 ms
10490 ms510 ms
11784 ms816 ms
12980 ms1020 ms
132940 ms3060 ms
144900 ms5100 ms
157840 ms8160 ms
 
The decay and release values both use the following machine-specific time periods, although they have different purposes (the table below shows three significant digits).  The decay sets the time for the amplitude of a voice to drop from the peak value to its sustain level (see below).  Note the amplitude of the voice might never reach the peak value if the "note" ends very quickly (relative to the attack time period).  Note the amplitude of the voice might not have yet "decayed" to the sustain level if the "note" ends very quickly (relative to the sum of attack and decay time periods).  In those cases, sustain is irrelevant.  
 
Assuming the sustain level is reached (see below), the voice will continue at that (relative) amplitude until the "note" of the PLAY statement ends, and then its amplitude will drop to zero (silence) over a period determined by release.  Generally, percussion instruments (drums) and some string instruments (piano and harp) will have a zero sustain level, and thus release is typically irrelevant (unless the "note" ends quickly as described above).  For non-percussion instruments (any non-zero sustain), a large release value will cause the next "note" in a PLAY statement to "blend" with the last; this is because the amplitude of the last note would have hardly dropped at all when the next "note" begins (assuming both notes are using the same voice).
decay
release
NTSC TimePAL Time
05.88 ms6.12 ms
123.5 ms24.5 ms
247.1 ms49.0 ms
370.6 ms73.5 ms
4112 ms116 ms
5165 ms
171 ms
6200 ms208 ms
7235245 ms
8294 ms 306 ms
9735 ms765 ms
101470 ms1530 ms
112350 ms2450 ms
122940 ms3060 ms
138820 ms9180 ms
1414700 ms15300 ms
1523500 ms24500 ms
 
The sustain parameter sets the primary amplitude (loudness) of a "note" relative to the current master volume (see VOL).  It is a simple fraction of sutain divided by fifteen (i.e., voice_amplitude = sustain * master_volume / 15).  I've provided a table showing this in percent.  It is used mostly by non-percussion instruments that can sustain a "note" indefinately, like a trumpet (well, a human would run out of breath eventually).  For such instruments, a "note" that is PLAY'd will remain at this relative volume level after the attack and decay time periods until the "note" ends, at which time the release phase begins (see above).  If the "note" plays for a very short duration (see attack and decay above), the voice may never reach the sustain (relative) amplitude.  Most precussion and some string instruments can't sustain the volume of a "note" indefinately; these typically use a zero sustain value.
sustainrelative
volume
00.000% (silence)
16.667%
213.33%
320.00%
426.67%
533.33%
640.00%
746.67%
853.33%
960.00%
1066.67%
1173.33%
1280.00%
1386.67%
1493.33%
15100.0%
 
The previous four parameters (attack, decay, sustain, and release) define the changes in amplitude for a "note" that is PLAY'd.  They should have a value between 0 and 15, but due to sloppy coding, any integer between 0 and 255 is accepted.  Values greater than 15 will only use the lower 4 bits.  Thus, effective_parameter = given_parameter AND 15.
 
The last two parameters, waveform (and perhaps pulseWidth) control the timbre of the sound, just like a "C" played on flute will sound different than a "C" played on a trumpet (even though they have similar amplitude envelopes).  For waveform, a value of 0 produces a triangle wave which is a poor digital imitation of a sine wave, and sounds similar to some wind instruments, like flutes (it sounds rather "soft", unlike a real sine wave which sounds very "full").  A value of 1 produces a sawtooth waveform and sounds like some brass instruments, like trumpets.  A value of 2 produces a rectangular waveform and is quite versatile because you can control its duty-cycle (described below).  A value of 3 produces a noise waveform which is mostly useful for sound effects like ocean waves and explosions, but might be useful for a precussion instrument like a snare drum.  The final value of 4 is quite special, it produces ring-modulation.
 
With ring-modulation, a voice will produce a triangle wave that is modulated with the frequency of the prior voice (or the last voice if the first is using ring-modulation).  This adds harmonic frequencies and is usefull for bell-like instruments.  However the "other voice" should normally not be played; its frequency (wheather it is playing or not) will affect the harmonics of the voice using ring-modulation.  This makes it difficult to use in a PLAY statement, unless the frequency of the "other voice" can remain fixed.  Assuming you don't want to hear the "other voice", this reduces the number of available voices from 3 to 2. The SID chip has a special bit that can be used to "hide" the output of voice 3, so one possibility is to use voice 3 as the "other voice" and voice 1 as the one using ring-modulation.  This way you can change the frequency of both voices easily with PLAY.  However BASIC provides no way to enable the "voice 3 off" feature.
 
If a rectangular waveform is selected, the final parameter, pulseWidth species the duty-cycle by this equation: dutyCycle = 100% * pulseWidth / 4096.  A pulseWidth of 2048 thus produces a 50% duty-cycle which is a special case of the rectangular waveform known as a square wave.  Using different values for pulseWidth allows a nice variety of sound timbres.  At 50% the sound quality is at its "fullest" sounding like some cross between a stringed instrument and a horn... the classic digital synthesizer sound.  As the duty-cycle moves away from 50%, the sound quality becomes more "reedy" and quieter.  You will hear nothing when the duty-cycle reaches 0% or 100%.  Values below 50% sound the same as their "complement" above 50%; so a 40% duty-cycle sounds the same as a 60% duty-cycle (they are both 10% away from 50%).  This is because the human ear is, by itself, indifferent to phase shifts (a 40% duty-cycle waveform is a 180-degree phase-shifted version of a 60% duty-cycle waveform).  A pair of ears can descriminate between phase shifts in some cases, but only relative to the same sound.
 
ENVELOPE will store the pulseWidth (if given) even if the waveform does not use it.
 
If toneNum is omitted, or any specified parameter has an invalid expression, SYNTAX ERROR is generated.  If any parameter is not numeric, TYPE MISMATCH ERROR occurs; you may manually convert a string with VAL.  Floating-point numbers are converted automatically with INT.  If the resulting parameter is not a Legal Value (see table above) then ILLEGAL QUANTITY ERROR occurs.
 
 
Examples:
ENVELOPE 3, 0,5,0,5, 3 : REM better 'drum' (3), ADSR=0/5/0/5 (no sustain), noise(3)

READY.
ENVELOPE 0, ,,,, ,512 : REM set 'piano' (0) pulse-width to 512 (12.5% duty-cycle)

READY.
ENVELOPE 9, ,,,, 1 : REM change 'xylophone' to sawtooth waveform

READY.
 
 Compare With 
 
 Contrast With 
 See Also 

© H2Obsession, 2014