Back to main page
Back to sound contents

Sound from sampled data

This section shows how to make use of sampled data to generate sounds. The sound object to be used is sample.

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 = [dimensions = [800, 200]] )$

Maxima lists are common objects for storing sequences of numbers.

load (descriptive)$
data_size : 15000 $
param : 0.0009 $
data : random_exp(param, data_size) $
data : data - mean(data) $
play(sample(data))$
Download wav file

Note that the duration in seconds of this sound can be calculated by

(%i7) float(data_size / sound_sample_rate);
(%o7)                           0.91552734375

Sound object sample also accepts 1D arrays. Wave plot is saved in png format and mplayer is called.

a: make_array (flonum, 10000) $
for i:0 thru 9999 do a[i]: random(1.0)-0.5 $
sound_sample_rate: 10000; /* sound duration = 1 sec. */

play(sample(a)) $
Download wav file

Another source of samples are wav files. It is possible to read data from already existing sound files to later transform them and create new wav files. Only wav files with 8 or 16 bits per sample were tested.

In this example, we read boo.wav and look at the result of function load_sound_wav, we then reverse the whole sample and create a new sound file.

(%i10) boo : load_sound_wav("boo.wav")$

"Number of channels.: 1" 
"Samples per second.: 11025" 
"Bits per sample....: 8" 
"Number of samples..: 16533" 

(%i11) /* Number of samples per second */
       boo[1];
(%o11)                               11025

(%i12) /* Total number of samples */
       length(boo[2]);
(%o12)                               16533

(%i13) /* First sample. Only one channel */
       boo[2][1];
(%o13)                               [128]

(%i14) /* Transform list of lists into list of numbers */
       boo_list : flatten(boo[2])$

(%i15) /* Plot the soundwave */
       draw2d(
          terminal      = png,
          point_type    = dot,
          points_joined = true,
          points(boo_list))$

Looking at this plot we see that samples take positive values (wav files save samples of 8 bits as unsigned). We need to move the horizontal axis downwards to get a correct soundwave with positive and negative samples. After that we reverse the wave and call function play.

boo_list : boo_list - (lmax(boo_list)+lmin(boo_list)) * 0.5 $ /*move waveform downwards*/
sound_sample_rate : boo[1] $ /* set sample rate*/
play(sample(reverse(boo_list))) $
Download wav file

Let's now calculate the Fourier transform of a sound read from a wav file. From last example, remember that variable boo_list contains the samples taken from file boo.wav.

(%i16) load("fft")$

(%i17) /* add zeroes to complete a power of 2 */
       boo_list2: append(boo_list,
                         makelist(0, 2^ceiling(log(length(boo_list))/log(2)) - length(boo_list))) $


(%i18) /* Calculate the Discrete Fourier Transform */
       tf: fft(boo_list2) $

(%i19) /* extract real and imaginary components */
       rtf: realpart(tf) $
       itf: imagpart(tf) $

(%i20) /* Let's draw the DFT */
       set_draw_defaults(
         dimensions  = [800, 600],
         points_joined = true,
         point_type    = dot,
         grid          = true) $

       draw(
         gr2d(
           title = "Real part",
           points(rtf)),
         gr2d(
           title = "Imaginary part",
             points(itf))) $

Back to main page
Back to sound contents


by Mario Rodríguez Riotorto