Back to main page
Back to sound contents

Envelopes

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) )$
Download wav file

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))$
Download wav file

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))$
Download wav file

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) )$
Download wav file

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) )$
Download wav file

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) )$
Download wav file

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) )$
Download wav file

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) )$
Download wav file

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) )$
Download wav file

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) )$
Download wav file

Back to main page
Back to sound contents


by Mario Rodríguez Riotorto