DEPARTMENT OF COMPUTING

CS 3005: Programming in C++

Instrument Class

Introduction

We will define an instrument for audio generation as a combination of a waveform and an envelope. The waveform will provide the shape of the oscillating sound waves and the envelope will provide the shape of the amplitude of individual notes played by the instrument.

The first example shows a sine waveform with an ADSR envelope.

sine-ADSR-instrument.png

The second example shows a square waveform with an AD envelope.

square-AD-instrument.png

Assignment

In this assignment, you will create a class to represent an instrument. This class will also be capable of rendering a sound for an instrument using its waveform and envelope. The instrument can be used to generate a variety of sounds, with different frequencies and durations.

You will also create a simple program that generates an instrument and saves a sound generated by the instrument to a WAV file.

Sample interactions with the program may look like this:

A sine waveform with an AD envelope

$ ./program-instrument-test/instrument_test 
Samples/Second: 44100
Seconds: 0.5
Bits/Sample[8,16,24,32]: 32
Waveform style: sine
Envelope style: AD
Maximum amplitude: 1.0
Attack seconds: 0.1
Frequency: 440.0
WAV filename: instrument-sine-AD.wav

A square waveform with an ADSR envelope

$ ./program-instrument-test/instrument_test 
Samples/Second: 44100
Seconds: 0.5
Bits/Sample[8,16,24,32]: 32
Waveform style: square
Envelope style: ADSR
Maximum amplitude: 1.0
Attack seconds: 0.05
Decay seconds: 0.15
Release seconds: 0.005
Sustain amplitude: 0.7
Frequency: 400.0
WAV filename: instrument-square-ADSR.wav

Bad waveform or envelope names

$ ./program-instrument-test/instrument_test 
Samples/Second: 44100
Seconds: 0.5
Bits/Sample[8,16,24,32]: 32
Waveform style: fred
Waveform style 'fred' is not known.
Envelope style: wilma
Maximum amplitude: 1.0
Envelope style 'wilma' is not known.
Frequency: 440.0
Segmentation fault (core dumped)

The segmentation fault is because the waveform or envelope are not configured. We will consider this to be acceptable behavior for this test program.

Multiplying AudioTrack Objects

If two audio tracks have the sample number of samples, you can multiply them on a sample by sample basis. For example, if the first audio track has the five values [0.1, 0.2, 0.3, 0.4, -0.5] and the second track has the five values [0.6, 0.7, 0.8, 0.9, 1.0], the result will be and audio track object with the values [0.6, 0.14, 0.24, 0.36, -0.5].

It only makes sense to multiple two audio tracks if they have the same sample rate (samples per second) and duration (seconds).

Generating AudioTrack Samples for an Instrument

The envelope for an instrument is used to fill an audio track object, using the envelope’s method for generating amplitudes. Note this is a set of positive amplitudes based on the form of the envelope object.

The waveform for an instrument is used to fill a different audio track object, using the waveform’s method for generating samples. Note that this is a set of values that oscillate between positive and negative values depending on the shape of the waveform, and the frequency of the sample.

Finally, an instrument’s audio track samples are set by multiplying the two audio track objects together.

Creating an Instrument

An instrument is a pairing of an envelope and a waveform. To create an instrument, the envelope and waveform are created first, then they are used to configure the new instrument.

Programming Requirements

Update library-audiofiles/AudioTrack.{h,cpp}

AudioTrack Class

public Methods:

Create library-instrument/Instrument.{h,cpp}

Instrument Class

Data Members:

The Instrument class should contain data members to track the following information. These data members should be protected or private. They are not allowed to be public.

public Methods:

Create library-instrument/Makefile

This file must contain rules such that any of the following commands will build the libinstrument.a library:

This file must contain rules such that the following command will install the libinstrument.a library into the lib directory, and all .h files to the include directory:

Create library-commands/instrument_test_aux.{h,cpp}

Functions:

Update library-commands/Makefile

Add instrument_test_aux.{h,cpp} in the appropriate places to add them to the library and install the header file.

Create program-instrument-test/instrument_test.cpp

Functions:

Create program-instrument-test/Makefile

This file must contain rules such that any of the following commands will build the instrument_test program:

Create program-instrument-test/.gitignore

The file program-instrument-test/.gitignore needs to store one line of text:

instrument_test

Update Makefile

Update the project-level Makefile so that make and make all in the project directory will call make install in the library-instrument directory, and make in the program-instrument-test directory.

Additional Documentation

TBA

Grading Instructions

To receive credit for this assignment:

Extra Challenges (Not Required)

TBA

Last Updated 02/18/2025