Programming Lab 1
Making noise




This lab demonstrates how to generate whitenoise and how to write soundfiles in the C/C++ programming language.

These instructions are set up for use with mambo. First, telnet or ssh to mambo.

To access the mambo filesystem directly from a macintosh computer, go to the Chooser menu, in the IP window, type mambo.peabody.jhu.edu. Log into mambo with your username and password. There will be a dialog box which gives you an option of folders to mount, choose the one which has your user name (or choose the home folder. You should now be able to read/write to your mambo account on a macintosh computer.

Step 1: Create a subdirectory once you are logged into mambo. You can do this directly on the macintosh, or you can type these commands in mambo:
   mkdir prog
You can, of course, name the directory prog anything, or you could put the directory into your class directory, etc.
Step 2: In the mambo terminal, go into the directory you just created. To do this, type:
   cd prog
Where prog is the name of the directory which you created in Step 1.
Step 3: Now you are ready to start programming. Here is a program which you should write (or copy and paste) into a file called noise1.cpp on mambo (click here for copying the file).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 
17
#include "soundfile.h"

int main(void) {
   SoundHeader header;
   header.setChannels(1);
   header.setSrate(44100);
   SoundFileWrite soundfile("test.wav", header);

   int sampleCount = 44100;
   int i;
   double sample = 0.0;
   
   for (i=0; i<sampleCount; i++) {
      sample = drand48() * 2 - 1;
      soundfile.writeSampleDouble(sample);
   }
} 

This program will write one second of whitenoise to the file test.wav in your current directory when it is run.

To write the program in a file, you can use some macintosh text editor. In linux, you can try pico which is a simple text editor which is very easy to learn. If you want to learn a more powerful text editor, then you should learn to use vi or emacs. Ask me and I can get you started with one of them.

Step 4: To compile the program run the following command in the mambo terminal:
   mkprog noise1
This will call the mkprog script which compiles the program and links it to the soundfile library.
Step 5: Now that the program has been compiled, there should be a program in the current directory called noise1. To run the program type:
   noise1
This will create a file in the current directory called test.wav. Open up the soundfile in the Peak sound editor on a macintosh to see the waveform of the sound.
Step 6: Now that you have compiled and run the program, let's look at the individual pieces of the program. The program is written in C/C++, so if you know how to program in C/C++, then you can skip down to the exercises.

All C program contain at least one function called main. Here is the shorted program which can be written in C:

int main(void) { }
There are four components to the program:
2. main This is the name of the function.
1. int This is the return value for the function. It indicates the type of data which is outputted from the function. In this case the function main should return an integer to the operating system when it is done.
3. (void) This is a list of input parameters which can be sent to the function. In this case, void means that there are no allowable inputs.
4. { } After the input parameter list to the function, there is a set of curly braces between which you place the definition of what the function does. In the noise generating program, the contents of the program goes from line 4 to 16. The closing brace for the main function is on line 17.

Inside of the main function, an output soundfile is prepared. Line 7 is where the soundfile is created with a name of test.wav. The soundfile needs to know how many channels and what the sampling rate is, so there is a variable called header which was created to give it that information.

Lines 13-16 do all of the work in the program. This is a for loop which means that the code on lines 14 and 15 are called continuously until the loop is exited.

The structure of a for loop is:

   for (start; condition; increment) { }
start is the starting code which usually sets a counter to 0, as it does for the noise1 program. The condition code is used to check to see if the loop should be run (again). If the condition is true, then do the loop one more time; otherwise, stop looping. After each loop, the code in increment is called. This code is usually adding one to the counting variable which was initialized in start.

For the loop on lines 14-16, the looping variable is i. It is first set to 0 at the start of the loop. The loop is run until i = sampleCount. sampleCount is set to the value 44100, which is one second of sound at the sampling rate of the soundfile. So, the loop will be run 44,100 times before the loop is exited.

What is happening inside of the for loop? There are two lines of code which are being called:

    sample = drand48() * 2 - 1;
    soundfile.writeSampleDouble(sample);
The first line generates a random number in the range from -1 to +1. drand48 is a builtin function (in linux) which will generate a random floating point number from 0.0 to 1.0. This number is then scaled to get it into the range
Exercises:
  1. Modify the noise1.cpp program to set the amplitude of the sound to 1/10 of the maximum amplitude. This can be done by adding the line:
       sample = sample * 0.1;
    
    After line 14 in the program.
  2. Write every random sample twice (or three times, etc) to the soundfile, how does this change the sound of the noise? To do this exercise, just copy and paste line 15 several times.
  3. Write the average of two random values to a sound file instead of the actual random sequence. Calculate the random sample something like this:
       sample2 = sample1;
       sample1 = drand48() * 2 - 1;
       sample  = (sample1 + sample2) / 2;
    
  4. Write the samples to a stereo soundfile instead of a monophonic soundfile.
  5. Write the samples to a stereo soundfile, but delay the sequence in one channel by 5 samples. Do something like this in the for loop using a stereo soundfile:
       sample5 = sample4;
       sample4 = sample3;
       sample3 = sample2;
       sample2 = sample1;
       sample1 = drand48() * 2 - 1;
       soundfile.writeSampleDouble(sample1);
       soundfile.writeSampleDouble(sample5);
    
  6. Write random samples in the range from 0.0 to +1.0 to the output soundfile. How does this affect the sound of the noise?




Post Script:

If you want to download the library source code for writing soundfiles and compile/run on your own computer, choose one of the following two files to download: You could copy these files in a terminal by typing:
   wget http://peabody.sapp.org/class/350.867/lab/prog1/soundfile-2.0.tgz

Now unpack the compressed file:

   tar xvzf soundfile-2.0.tgz

Change directory into the soundfile directory:

   cd soundfile-2.0

Now compile the library:

   make library
OSX people will have to modify the Makefile to get it to compile correctly. These changes should be done in the osx-specific file above.
  • remove -O6 from Makefile.library and Makefile.examples
  • change the compiler from g++ to c++2
  • change the OS type from LINUX to OSX
  • If you get a message like: libSystem.dylib load command 9 unknown cmd field Then that means that you need to update your Developer tools to match the version of OS X which you are running.

Once the library is compiled, you can compile the example programs in the examples directory by typing this command:

   make examples

To compile your own programs, place them in the examples directory and type the command:

   make program
Where program.cpp is the name of the program you placed into the examples directory.

To compile your program outside of the example program, you can modify the mkprog script which is used to compile the programs on mambo.