Back to main page
Back to sound contents
This section shows the principal functions and sound options available in package sound.
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 = "vlc", draw_wave = true, draw_wave_options = [terminal = png, pic_height = 200, pic_width = 800] )$
A note for Windows users: there are probably better ways for playing wav files from Maxima, but these steps worked for me:
Let's begin with a sinusoidal waveform. Function play is called here with only one argument, namely sound object wave, which in turn is defined as a sinusoidal signal of frequency 440 cycles per second (440 Hz) from time t1 = 0 s to t2 = 0.5 s. This pure wave sound corresponds to A4, key A of the fourth octave; in Latin speaking countries (Spain, France, Italy) and others (Russia) this key is called Do4.
We get three results from the following function call:
play ( wave(1000 * sin(2*%pi*440*t), t, 0, 0.5) );
A side effect of function play is that the resulting wave is stored in global variable sound_sample, which is a lisp 2d array, containing the samples of the channels:
(%i23) /* number of channels */ sound_sample_channels(); (%o23) 1 (%i24) /* sample size */ sound_sample_size(); (%o24) 8192 (%i25) /* sample of channel #1 in Maxima list format */ sound_sample_list (1); (%o25) [0.0, 5502.834111437016, 10849.36032083387, 15887.71064924192, ................................. - 10849.36032082994, - 5502.834111438126] (%i26) /* list length is 8192, of course */ length(%); (%o26) 8192 (%i27) /* 3rd sample of channel #1, indexing starts at 0 */ sound_sample[0,2]; (%o27) 10849.36032083387
Waveforms are saved in wav files in 16 bits per sample. By default, samples are normalized to range [-32767, 32767], but this behavior can be changed setting sound option normalize to none or any positive integer less or equal than 32767; default is auto.
In this example, we add two waveforms of different frequency (A4 and A3, or Do4 and Do3) and amplitude.
play ( wave(1000 * sin(2*%pi*440*t) + 500 * sin(2*%pi*220*t), t, 0, 0.5) );
Now we want to divide our signal in three parts:
Note that in this example the sound_sample_rate (samples per second) is set to 20000 (default is 16384). The fifth argument to the second wave object indicates when the sound must start; by default, with only four arguments, the sound starts at t = 0. See also this and this examples.
sample_rate : 20000 $ play ( wave((1000 - 2000*t) * sin(2*%pi*440*t), t, 0, 1/2), wave(1000*sin(2*%pi*(2700*t + 300)*t), t, 0, 1, 1/2 + 1/5));
Sound object wave accepts more than four arguments. In this example, the same wave, of duration 1 second, is repeated two times, beginning at t = 0 and 1/2 seconds. In the overlapping interval, [1/2, 1] the waves are added. The total signal has a duration of 1.5 seconds.
play ( wave(1500 * sin(2*%pi*440*t), t, 0, 1, 0, 1/2) );
Perhaps one wants the samples to be saved in a plane text file for further processing. In this case, make use of option file_format = txt; by default it is equal to wav.
Note that whenever the play function is called, the generated waveform is stored in the Lisp array sample_array. But we don't want to make use of this array this time.
This example also demonstrates how to save computing time. We want tone A4 for 1 second, but we tell Maxima to only compute 0.25 seconds (from 0 to 0.25); after that, Maxima must repeat the same waveform at t = 0, 0.25, 0.5 and 0.75, that is one second in total.
play ( file_format = txt, wave(1000 * sin(2*%pi*440*t), t, 0, 0.25, 0, 0.25, 0.5, 0.75) ) $
/* Read file as a Maxima list */ s: read_list("maxout.txt")$ /* Divide amplitude by 2 and draw */ draw2d( points_joined = true, point_size = 0, points(s / 2))$
Dial tons. Or is this R2-D2?
random_dial_call (num) := block([n, t, dial_tones, amp : 1000], dial_tones : [/* 1= */ (sin(4379*t)+sin(7596*t))/2, /* 2= */ (sin(4379*t)+sin(8394*t))/2, /* 3= */ (sin(4379*t)+sin(9280*t))/2, /* A= */ (sin(4379*t)+sin(10260*t))/2, /* 4= */ (sin(4838*t)+sin(7596*t))/2, /* 5= */ (sin(4838*t)+sin(8394*t))/2, /* 6= */ (sin(4838*t)+sin(9280*t))/2, /* B= */ (sin(4838*t)+sin(10260*t))/2, /* 7= */ (sin(5353*t)+sin(7596*t))/2, /* 8= */ (sin(5353*t)+sin(8394*t))/2, /* 9= */ (sin(5353*t)+sin(9280*t))/2, /* C= */ (sin(5353*t)+sin(10260*t))/2, /* *= */ (sin(5912*t)+sin(7596*t))/2, /* 0= */ (sin(5912*t)+sin(8394*t))/2, /* #= */ (sin(5912*t)+sin(9280*t))/2, /* D= */ (sin(5912*t)+sin(10260*t))/2], n : length (dial_tones), makelist(wave(amp * dial_tones[1 + random(n)], t, 0.0, 0.1, 0.2*(k-1)), k, 1, num)) $ apply( play, random_dial_call (9)) $
Back to main page
Back to sound contents