Newer
Older
Import / applications / HighwayDash / ports / Framework / Music.h
//  BlockyFroggy
//  Copyright © 2017 John Ryland.
//  All rights reserved.
#pragma once
#ifndef MUSIC_H
#define MUSIC_H


#include <vector>
#include <cstdint>


extern float g_semiToneFreq[256];


class SemiTone
{
public:
    SemiTone(uint8_t a_note = 0) : m_note(a_note) {}
    int octave()
    {
        return m_note / 12;
    }
    const char* tone()
    {
        const char* tones[12] = { "C_", "C#", "D_", "D#", "E_", "F_", "F#", "G_", "G#", "A_", "A#", "B_" };
        return tones[m_note % 12];
    }
    float frequency()
    {
        return g_semiToneFreq[m_note];
    }
private:
    uint8_t  m_note;
};


class MusicalScore
{
public:
    std::vector<SemiTone>  m_notes;
};


class MusicalNotation
{
public:
    MusicalNotation();
    ~MusicalNotation();
    
    //
    // Notation:
    //      "C_4"     - Regular Middle C (4th octave)
    //      "C#4"     - Middle C sharp
    //      "Db4"     - D flat (same as middle C#)
    //      "   "     - Rest
    // So for each tempo unit of time, 3 characters are used
    // To sustain a note for another tempo unit:
    //      "---"
    //
    // Each octave has 12 semi-tones (the 12 semi tones are C,C#,D,D#,E,F,F#,G,G#,A,A#,B)
    // Usually pianos only support up to 8 octaves (88 or occassionally 97 piano keys)
    // So 12 semi-tones over 8 octaves means that a 7-bit number is sufficient to represent
    // any typical semi-tone. An 8-bit value should provide range for also non-typical use.
    //
    // Compared to the 3 character representation, as an 8-bit value in hex, it is 2-bytes,
    // so not a great saving. In binary as 1 byte is a bit more significant.
    //
    // Canonically it should be convinient to represent the semi-tone as an 8-bit value for
    // lookup in freq table or calculation
    //
    MusicalScore parseHumanReadableNotation(const char* /*a_notation*/)
    {
        MusicalScore score;
        
        return score;
    }
};


#endif // MUSIC_H