# Introduction

How do you generate sound programmatically? beep is a simple note-playing program I’ve written using the PortAudio library, written in C. (Ok, the title is a pun: I really mean the C programming language.) It is a minimal working example of sound generation: it is simple enough to understand very quickly, and is easy to play around with.

# Try it

A prerequisite to compile and run beep is that you must have a C compiler, and the PortAudio dev libraries installed. On Ubuntu this can be installed by running something like:

(For other operating systems, see PortAudio’s website.)

To download and complile beep:

To play a 440Hz sine wave, run

# Generating sounds in C (low-level)

To make sounds on a computer, we tell our speaker to vibrate. (Obviously.)

                /.
/ \
/  \\
/   \\
/     \\
/      \\
/       \\
/         \\
/          \\
/           \\
/            \\
/            \\
/             \\
/             ||
/             || <- ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
/             ||
/            //
/           //
/         //
/       //
/      //
/     //
/   //
/  //
//

\______________/
v


It works as follows: 44100 times per second—44100 frames per second—our speaker asks our program, “choose any number for v from -1.0 to 1.0”. We are in power to answer. We can return the same number for every frame, but then the speaker won’t move. We can give it -1,+1,-1,+1,-1+1 (rapidly moving back and forth 44100 times per second) but it will be too high pitched (44kHz) to hear. We can set v equal to the result of a function the frame number: f(n)=sin(2*PI*440*n/44100), and, like mathematical magic, we will hear a clean tone.

That’s how low-level APIs for generating sound usually work, and that’s the API that PortAudio exposes to us. It’s nice that PortAudio offers such a low-level API, because it gives us power. But, in order to generate note-worthy sounds, we’ll want to add a minimal layer of abstraction.

# Generating sounds in C (with an abstraction)

Instead of thinking of our interface to the speaker as simply an infinite stream of frames, we might want to think of it as a stream of notes. We can define a “note” as a structure which has a duration, a frequency, a waveform shape, and amplitude (volume). For example, imagine a 1-second-long, 440Hz sine wave, at 100% volume…that’s a note. Ideally, we’d like to be able to play a note with something like the following:

We’ll call a note a beep_note and define it as:

When we’re actively playing notes, we’ll need to remember which frame we’re on. So, we’ll create an object (beep_head) to keep track of which note is playing and which frame we’re at. (To keep things simple, for now, we can only play one note at a time; we can’t compose notes.)

Our note will need a waveform (beep_waveform). Examples of waveforms are sine, triangle, sawtooth, square—but a waveform could be any math formula. We can think of a waveform as a function which takes a beep_head as an input and produces a frame value as output:

For a sine wave, this will be f(frame)=sin(2*PI*frequency*frame/44100)*amplitude). In C:

The final code can be found on GitHub.

Future enhancements include adding envelopes, and supporting note composition, but the purpose of this program was to keep things simple.