#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