Back to main page
Back to sound contents
This section shows how to add envelopes to waveforms, which are controlled by sound option envelope. With an envelope, it is possible to modify the amplitude of a wave sound, so that the resulting wave is more similar to real sounds.
Since we want to play the sound and draw the waveform everytime we call the play function, we set some sound options defaults to avoid rewriting them.
set_sound_defaults(
player = "mplayer",
draw_wave = true,
draw_wave_options = [terminal = png,
pic_height = 200,
pic_width = 800] )$
With the pairs envelope, we'll be able to define our own envelope as a sequence of linear segments. Arguments to pairs are lists of coordinates of points in the unit square, representing relative distances, both vertically and horizontally. These points are the extremes of the line segments, and can be given in any order, since Maxima will sort them with respect to the abscissas in increasing order.
play( envelope = pairs([1/2,1], [0, 0.2], [1, 0.2]), wave (2000 * sin(2*%pi*440*t), t, 0, 2) )$
You can compare this result with a pure sinusoidal wave of frequency 440 Hz without envelope.
play(wave (2000 * sin(2*%pi*440*t), t, 0, 2))$
By default, no envelope is applied; but once you define an envelope, it will be applied to all the next sound objects, until it is re-defined or setting to none, the default value. In this example, we generate three waves of different frequency and amplitude.
play( envelope = pairs([0,1], [1, 0.3]), wave (2000 * sin(2*%pi*440*t), t, 0, 0.5), envelope = none, wave (1000 * sin(2*%pi*2200*t), t, 0, 0.5, 1/2), envelope = pairs([0,1], [0.5, 0.2], [1, 0]), wave (500 * sin(2*%pi*2200*t), t, 0, 0.5, 1))$
One of the most used envelopes is the ADSR (attack-decay-sustain-release) envelope (details in http://en.wikipedia.org/wiki/ADSR). adsr needs four arguments: attack time, decay time, sustain level and release time. Time quantities are ratios of the duration of the sound object; their sum can't be greater than one.
play( envelope = adsr(0.01, 0.1, 0.8, 0.4), wave (2000 * sin(2*%pi*440*t), t, 0, 2) )$
You can also define a function as an envelope.
play( envelope = function(u*u, u, -1, 1), wave (2000 * sin(2*%pi*440*t), t, 0, 2) )$
Modulating the amplitude.
play( envelope = function(0.2*sin(t) + 0.5, t, 0, 10), wave (2000 * sin(2*%pi*440*t), t, 0, 2) )$
The musical term vibrato is a regular and repetitive variation in amplitude for the duration of a single note. We can simulate this effect by means of option envelope. In this example, a vibrato is performed with increasing frequency and decreasing amplitude.
play( envelope = function((1/5-t/50)*sin(2*%pi*(3+6*t/5)*t) + 0.5, t, 0, 5), wave (2000 * sin(2*%pi*440*t), t, 0, 2) )$
If we want an envelope produced by a set of pairs, but joined by a smooth curve, we can make use of the Lagrange interpolator.
load(interpol) $ pol : lagrange ([[0,0.1],[0.2,0.4],[0.3, 0.2],[0.5, 0.8],[0.7, 0.6],[0.9, 0.1],[1,0]]) $ f(x) := ''pol $ draw2d( terminal = png, pic_height = 200, pic_width = 800, explicit(f(t),t,0,1)) $
play( envelope = function(f(t), t, 0, 1), wave (2000 * sin(2*%pi*440*t), t, 0, 2) )$
Three gongs (hmm, well, not exactly ... but something similar).
gong(freq, start) := wave(1000*sin(sin(2*%pi*freq*t+ 5*sin(2*%pi*1.98*freq*t))), t, 0, 1.5, start) $ play( envelope = adsr(0.01, 0.1, 0.8, 0.8), gong(200, 0), gong(250, 1.6), gong(300, 3.2) )$
Now, the three gongs (or whatever they are) without envelopes. Get the difference?
play( gong(200, 0), gong(250, 1.6), gong(300, 3.2) )$
Back to main page
Back to sound contents