Envelope

Envelopes, together with the choice of a sound (loaded as an AudioSample), establish a sound’s individual quality or timbre.

Envelope objects are used to help shape the sound of AudioSample instruments used to play notes.   They utilize four adjustable parameters:

Figure-6.25-Graph-of-ADSR-envelope

  • Attack models the beginning of the sound, i.e, how long it takes for the sound to begin sounding fully, once it has been started.  It is the initial build up of the sound.
  • Decay models the initial loss of energy after the Attack, i.e., how long it takes for the sound to reach its normal level, after the maximum of the initial attack.
  • Sustain models how long the sound maintains its normal level.
  • Release models the end of the sound, i.e., how long it takes for the sound to finish sounding, after it has been stopped.

For more information on Envelopes, see here and here.

Creating an Envelope

An envelope is created as follows:

Function Description
Envelope(attackTimes, attackValues, delayTime, sustainValue, releaseTime) Creates a new envelope, with attackTimes (a list of times in milliseconds, relative from the previous time), attackValues (a list of sound levels between 0.0 and 1.0 to be reached at the corresponding attack time), delayTime (how many milliseconds to reach the sustain sound level), sustainValue (a sound level between 0.0 and 1.0), and releaseTime (how many milliseconds it takes for the sound to end, after it has been stopped).

For example,

env = Envelope([20, 10, 10, 10], [1.0, 0.8, 1.0, 0.8], 30, 0.6, 30)

creates an Envelope object env, which may be used to help shape an AudioSample, as follows:

  • Attack has four different times, namely 20, 10, 10, and 10 (in milliseconds from the previous time), each with an amplitude of 1.0, 0.8, 1.0, and 0.8 (where 1.0 means max sound level, and 0.0 means silence).
  • Decay of 30 milliseconds (from the last attack value) to reach the sustain level.
  • Sustain level of 0.6 (relative to max sound).
  • Release of 30 milliseconds (from when the sound is stopped).

Once an Envelope env has been created, the following functions are available:

Function Description
env.getAttackTimes() Retrieve the list of attack times of envelope env.
env.setAttackTimes( attackTimes ) Set the list of attack times of envelope env.
env.getAttackValues() Retrieve the list of attack values of envelope env.
env.setAttackValues( attackValues ) Set the list of attack values of envelope env.
env.getAttackTimesAndValues() Retrieve both lists of attack times and values of envelope env.
env.setAttackTimesAndValues( attackTimes, attackValues ) Sets both lists of attack times and values of envelope env.
env.getSustain() Retrieve the sustain value of envelope env.
env.setSustain( sustainValue ) Set the sustain value of envelope env.
env.getDelay() Retrieve the delay of envelope env.
env.setDelay( delayTime ) Set the delay of envelope env.
env.getRelease() Retrieve the release time of envelope env.
env.setRelease( releaseTime ) Set the release time of envelope env.
env.getLength() Retrieve the total length of envelope env in milliseconds. This is calculated from the envelope’s parameters (i.e., attack, delay, sustain, and release).  There is no setLength() function.  To set the envelope’s length you simply adjust attack, delay, sustain, and release times.

Example

The following demonstrates how to use an envelope to shape the sound of a loop:

# audioLoopWithEnvelope.py
# 
# Demonstrates how to create a loop using an audio file and an envelope. 
# This may be used for ambient or drone backdrops of sound to build on.
#

from music import *

loopTimes = 4

# load audio instruments
a1 = AudioSample("moondog.Bird_sLament.wav")

# define an envelope
e1 = Envelope([20, 60, 100, 10], [0.0, 0.8, 1.0, 0.8], 30, 0.6, 30)
#e1 = Envelope()

# create musical data structure
score = Score()

part1 = Part(0, 0)

phrase1 = Phrase()

# create musical data
pitches   = [A4] * loopTimes
durations = [4.12152] * loopTimes   # duration is in seconds (assuming 60bpm)
volumes   = [120] * loopTimes
pannings  = [0.5] * loopTimes
lengths   =  durations              # force playing length to be same as noted duration!

phrase1.addNoteList(pitches, durations, volumes, pannings, lengths)

part1.addPhrase(phrase1)

score.addPart(part1)

# play it!
#Play.audio( score, [a1] )
Play.audio( score, [a1], [e1] )