| 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 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 |
ENVELOPE toneNum [ , [ attack ] [ , [ decay ] [ , [ sustain ] [ , [ release ] [ , [ waveform ] [ , pulseWidth ] ] ] ] ] ]
State management. Define a PLAY "instrument" (toneNum).
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.
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".
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).
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.
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:
© H2Obsession, 2014 |