Assignment 5

Important dates

Assigned25 Jul 2018 @ 11:30h
Due3 Aug 2018 @ 23:59h

Description

Write functions to convert musical notation into frequencies and durations.

In this assignment, you need to write a set of functions for converting descriptions of a musical tunes like "Ab4 Bb8 C8 D4 C Eb G#- Ab+" into arrays of note frequencies and durations. My test code will provide you with strings that contain space-separated note descriptions, where each note is described with:

Note name (required)

A musical note name from A through G. Unless otherwise specified, our tunes will start in the octave (range) where A is 440 Hz; the remaining note frequencies in an octave can be calculated from the frequency of A using a multiplicative conversion factor. This conversion factor will depend on the number of semitones away from A that the note can be found (see details below).

Sharp or flat (optional)

A b means that the note is flat (lowered by one semitone from its usual frequency). A # means that the note is sharp (raised by one semitone). Again, see the description of semitones below. If neither sharp nor flat is specified, the frequency is whatever you get from calling noteFrequency().

Octave change (optional)

If the + modifier is present, it means that this note is one octave up from the previous one. If - is present , the note is one octave down from the previous one. Changing octave changes the frequency of all following notes according to the simple mathematical relationship described below.

Note length (optional)

A measure of note length — actually the period of a note relative to a whole note. A half note (denoted by the number 2) is one-half the length of a whole note, a quarter note (denoted by the number 4) is one-quarter the length of a whole note, etc. A description of this is used to calculate note length is given below. If no length is specified, the note should have the same length as the previous note. In my tests, the first note will always have a length. I will only use the following note lengths:

Length Note Beats

1

Whole note

4

2

Half note

2

4

Quarter note

1

8

Eighth note

$\frac{1}{2}$

eine kleine Musiktheorie (a little music theory)

Frequencies and semitones

Calculating the frequency of a specific note (as you will do in the noteFrequency function) depends on two things:

  1. the name of the note (A through G) and

  2. the baseline frequency of A within the given octave.

The name of the note is used to calculate a conversion factor that can be multiplied by the baseline frequency to get the final note frequency. This conversion factor will be semitone ratio $f_S = \sqrt[12]{2}$ raised to the power of the number of semitones between the note and A, given here:

Note Semitones from A

A

0

B

2

C

3

D

5

E

7

F

8

G

10

For example, in the octave for which A is 440 Hz, the frequency of the note C is given by:

\[ f_C = f_A \times \left( \sqrt[12]{2} \right)^3 = 440 \times 1.0594630943593^3 = 523.25 \textrm{ Hz} \]

We can check our calculations against a list of frequencies given on Wikipedia.

Octaves

Musical notes have the interesting property that every octave has same notes with frequencies exactly double those in the octave below. For example, our "standard" (or "tenor") A has a frequency of 440 Hz, but the A below it has a frequency of 220 Hz, then 110 Hz below that, then 55 Hz, 27.5 Hz, etc. When we change octaves, therefore, we only need to double or halve the baseline frequency that we are using to calculate note frequencies.

Note durations

The duration of a note depends on the number of beats in that note and the tempo of the overall tune. A beat is actually a period in the wave sense (i.e., $T = \frac{1}{f}$), so it’s a measure of duration. A quarter note has one beat, a half note has two beats and a whole note has four beats (at least in the kinds of music we’ll be playing!). The tempo of a tune is a frequency expressed in beats per minute, so to calculate the duration of, e.g., a whole note at 120 bpm, we simply need to apply a couple of conversion factors:

\[ 4 \times \frac{1}{120 / \textrm{min}} \times \frac{60 \textrm{ s}}{1 \textrm{ min}} = 2 \textrm{ s} \]

Assignment details

For this assignment, you need to implement four functions declared in the tune-parser.h header file. You must implement at least a stub (empty) function for each in order for your assignment to compile. Then, if you finish the implementation of some of the functions, you will get some of the marks. If you complete all of the functions correctly you will receive all of the marks.

Please read the above description of theory carefully, then read the header file carefully, then complete and submit your work as tune-parser.cpp (all in one file). I would strongly encourage you to test your code using function calls such as the following:

// The following should evaluate to 261.62 Hz:
double middleC = noteFrequency('C', 220);

// The following should evaluate to 2 s:
double wholeNote = noteDuration(4, 120);

// A little ditty I just made up:
string tune = "Ab4 Bb8 C8 D4 C Eb G#- Ab+";

// How many notes are in this tune?
int noteCount = countNotes(tune);

// Allocate space to store the frequencies and lengths of each note
double frequencies[noteCount];
double durations[noteCount];

// Figure out what notes would play this tune at 120 beats per minute:
int parsed = parseTune(tune, freqencies, durations, noteCount, 120);

// at this point, parsed should be equal to noteCount and the correct
// frequencies and durations should be stored in those two arrays

Here are some examples of expected parseTune() results:

Whole tune Note Frequency Duration

A2 G- F G A+1 @ tempo 120

A2

440 Hz (always start in 440 Hz octave)

1s (half note = 2 beats)

G-2

391.9954 Hz (G in the 220 Hz octave)

1s (stay with last duration)

F2

349.2282 Hz (still in the 220 Hz octave)

1s (stay with last duration)

G2

391.9954 Hz (G in the 220 Hz octave)

1s (stay with last duration)

A+1

440 Hz (back up to the 440 Hz octave)

1s (whole note = 4 beats)

Ab4 Bb8 C8 D4 C Eb G#- Ab+ @ tempo 96

Ab4

415.3047 Hz (A♭: semitone below A440)

0.625 s (quarter note = 1 beat)

Bb8

466.1638 Hz (B♭: semitone below B)

0.3125 s (eighth note = 1/2 beat)

C8

523.2511 Hz (C above 440)

0.3125 s (eighth note = 1/2 beat)

D4

587.3295 Hz (D above 440)

0.625 s (quarter note = 1 beat)

C

523.2511 Hz (C above 440)

0.625 s (stick with previous duration)

Eb

622.2540 Hz (E♭: semitone below E)

0.625 s (stick with previous duration)

G#-

415.3047 Hz (G♯ in the 220 Hz octave)

0.625 s (stick with previous duration)

Ab+

415.3047 Hz (A♭ in the 440 Hz octave)

0.625 s (stick with previous duration)

As always, assignments in this course must be done individually. You can (and are encouraged to!) work together on exercises, but you must do the assignments yourself. If in doubt, come and talk with me.