0

I've finished pset3 - Music, it compiles and runs pretty well, but a strange bug happens in frequency function. If a note value contains either a sharp # or a flat b, the value of char semitone gets set to "\377\377\377\377" when the char is declared. Thus frequency is not calculated correctly. Can someone help me and explain what's wrong? Thanks in advance!

The helpers.c snippet containing the frequency function:

// Helper functions for music
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
#include <math.h>

#include "helpers.h"

string notes[] = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"}; //All notes in an octave
string notesLetters[] = {"C", "D", "E", "F", "G", "A", "B"}; //All notes without accidentals

//Returns an item's position in an array. If there's no such item, returns -1
int indexOf (string a[], int size, string item)
{
    for (int i = 0; i < size; i++)
    {
        if (!strcmp(a[i],item))
        {
            return i;
        }
    }
    return -1;
}

// Calculates frequency (in Hz) of a note
int frequency(string note)
{
    int noteLen = strlen(note);
    char semitone[noteLen];
    semitone[noteLen-1] = '\0';
    semitone[0] = note[0]; //Semitone's first symbol is the note's letter
    int octave = note[noteLen-1] - 48; //Octave is the note's last symbol
    //Convert its ASCII code into a number from 0 to 8 by subtracting 48

    if (noteLen == 3) //If there is an accidental in the note
    {
        //If there is a flat, convert it to sharp and move its note letter one step left
        if (strstr(note,"b") > 0)
        {
            semitone[1] = '#';
            char letter[2]; letter[0] = note[0]; letter[1] = '\0';
            int letterPos = indexOf (notesLetters, 7, letter); //Move the letter before the flat one note left
            //7 is the notesLettes array size
            semitone[0] = *notesLetters[letterPos-1];
        }
    }
    int semitonePos = indexOf (notes, 12, semitone) + 1; //Find the resulting semitone in the octave
    //12 is the notes array size
    //Since array indices are counted from 0 instead of 1, add 1 to get the semitone's position in an octave

    double n = (octave - 4) * 12 + (semitonePos - 10); //Number of semitones from this note to A4
    //4 is the octave of the A4 note, 10 is the A4's position in its octave
    int result = round(440 * pow(2.00,n/12.00));
    //440 is the A4's frequency, Hz

    return result;
}        
1

Wow. Such a complex implementation using almost every string function. For example, in strstr(note,"b") > 0 you already know that only one character could be 'b', so this could as well be note[1] == 'b'.

"\377\377\377\377" is actually a -1 (octal notation, first digit represents two bits, the other two represent three bits, which means all bits set). Which isn't that surprising, as you never set semitone[1] in that case, so it remains at whichever value it had. And so indexOf returns -1 as well.

The fix is a simple

        else
        {
            semitone[1] = '#';
        }
1
  • Thank you greatly, it did the trick (obviously)! Jeez, it really was that simple - should have paid more attention to filling semitone with chars. – OlikovArtyom Jun 15 '18 at 6:15

You must log in to answer this question.

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