0

My code uses the minor scale pattern to calculate semitone distances and thus, frequencies of each note, and the "produces all correct notes for octaves 3-5" passes but fails for Ab3 and Bb5. I believe this to be because check50 wasn't implemented to recognize that some notes are enharmonic (Ab3 is the same as G#3 and Bb5 is the same as A#5). Is this the case or am I missing something in my code?

// Calculates frequency (in Hz) of a note
int frequency(string note)
{
    char letter = note[0], acc = '\0';
    int octave;

    // parse the note string
    if (strlen(note) == 2)
    {
        // 0 - 9 are contiguous so arithemtic can be done with them
        octave = note[1] - '0';
    }
    else
    {
        acc = note[1];
        octave = note[2] - '0';
    }

    // for octaves of A
    int f = DEFAULT_FREQ * pow(2, octave - DEFAULT_OCTAVE);

    int frequency;

    // accidentals
    int qual = 0;
    if (acc != '\0')
    {
        if (strcmp(&acc, "b") == 0)
        {
            qual -= 1;
        }
        else
        {
            qual += 1;
        }
    }

    // letters
    int interval = letter - 'A';
    string pattern = "2122122";
    float sum = 0.0;
    for (int i = 0; i < interval; i++)
    {
        // sum the number of steps to the letter from A
        sum += pattern[i] - '0';
    }

    /**
     * Calculate the sum of semitones (using the "2122122" minor scale pattern)
     * from A to the note letter and compensate for the letters below A by
     * subtracting that number of semitones from 12.
     *
     * If the letter is below A, then the resulting number needs to be
     * multiplied by -1 in to work with the frequency equation:
     *          (2 ** (n/12)) * frequency of A octave
     * Accidentals are also taken into by adding 1 to or subtracting one to the
     * semitone sum.
     *
     * Else, we just calculate the frequency using the formula as is.
     */
     float n = 0.0;
     if (interval > 1)
     {
         n = (SEMITONES - sum) * -1;
         frequency = round(f * pow(2, (n + qual) / SEMITONES));
     }
     else
     {
         frequency = round(f * pow(2, (sum + qual) / SEMITONES));
     }
     return frequency;
}

check50

:) bday.txt and helpers.c exist
:) helpers.c compiles
:) bday.txt is correct
:) is_rest identifies "" as a rest
:) is_rest identifies "A4" as not a rest
:) fraction of "1/8" returns duration 1
:) fraction of "1/4" returns duration 2
:) fraction of "3/8" returns duration 3
:) fraction of "1/2" returns duration 4
:) note A4 has frequency 440
:) note A6 has frequency 1760
:) note A#5 has frequency 932
:( note Ab3 has frequency 208
    expected "208", not "233"
:) note C3 has frequency 131
:( note Bb5 has frequency 932
    expected "932", not "1047"
:) produces all correct notes for octaves 3-5
1

strcmp is the wrong tool to compare characters (and strings must end in a null terminator, which your &acc... maybe, by accident, does if there's a null byte after the variable).

Just use if (acc == 'b').

1
  • Wow can't believe I missed that! Thanks – Kel May 28 '18 at 0:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .