// Note: Instrumentation statements are highlighted in green 

#include <vobject.hpp>
#pragma hdrstop
#include "note.hpp"

///////////////////////////////////////////////////////////////////////////////
// Note
///////////////////////////////////////////////////////////////////////////////

// Visual Member Definition 
VISIBILITY_START(Note, "Note", 0)
VVARIABLE(Note, relativeName, "Relative name", 0, 0)
VVARIABLE(Note, absoluteName, "Absolute name", 0, 0)
VVARIABLE(Note, midiNumber, "Midi number", 0, 0)
VVARIABLE(Note, frequency, "Frequency", 0, 0)
VBITSET_VARIABLE(Note, status, NoteStatus, "Status", 0, 0)
VISIBILITY_END

Note::Note(void) :
  relativeName("A"),
  absoluteName("A4"),
  midiNumber(69),
  frequency(440),
  status(IS_VALID)
{
}

Note::Note(char * relative_name, char * absolute_name, unsigned short midi_number, unsigned short _frequency, unsigned short _status) :
  relativeName(relative_name),
  absoluteName(absolute_name),
  midiNumber(midi_number),
  frequency(_frequency),
  status(_status)
{
}

Note::~Note(void)
{
}

Note::Note(const Note &note)
{
  *this = note;
}

Note & Note::operator=(const Note &note)
{
  relativeName = note.relativeName;
  absoluteName = note.absoluteName;
  midiNumber = note.midiNumber;
  frequency = note.frequency;
  status = note.status;
  return *this;
}

bool Note::operator==(const Note &note) const
{
  return absoluteName == note.absoluteName;
}

///////////////////////////////////////////////////////////////////////////////
// MusicalNoteTable
///////////////////////////////////////////////////////////////////////////////

// Visual Member Definition 
VISIBILITY_START(MusicalNoteTable, "MusicalNoteTable", 0)
VVCONTAINER(MusicalNoteTable, noteTable, "Note Table", 0, 0)
VISIBILITY_END

MusicalNoteTable::MusicalNoteTable(void)
{
  noteTable.push_back(Note("E",    "E3",    40, 164.81));
  noteTable.push_back(Note("F",    "F3",    41, 174.61));
  noteTable.push_back(Note("F#",  "F#3",  42, 185.00));
  noteTable.push_back(Note("G",    "G3",    43, 196.00));
  noteTable.push_back(Note("G#",  "G#3",  44, 207.65));
  noteTable.push_back(Note("A",    "A3",    45, 220.00));
  noteTable.push_back(Note("A#",  "A#3",  46, 233.08));
  noteTable.push_back(Note("B",    "B3",    47, 246.94));
  noteTable.push_back(Note("C",    "C4",    48, 261.63));  
  noteTable.push_back(Note("C#",  "C#4",  49, 277.18));
  noteTable.push_back(Note("D",    "D4",    50, 293.67));
  noteTable.push_back(Note("D#",  "D#4",  51, 311.13));
  noteTable.push_back(Note("E",    "E4",    52, 329.23));
  noteTable.push_back(Note("F",    "F4",    53, 349.23));
  noteTable.push_back(Note("F#",  "F#4",  54, 369.99));
  noteTable.push_back(Note("G",    "G4",    55, 392.00));
  noteTable.push_back(Note("G#",  "G#4",  56, 415.30));
  noteTable.push_back(Note("A",    "A4",    57, 440.00));
  noteTable.push_back(Note("A#",  "A#4",  58, 466.16));
  noteTable.push_back(Note("B",    "B4",    59, 493.88));
  noteTable.push_back(Note("C",    "C5",    60, 523.25));
  noteTable.push_back(Note("C#",  "C#5",  61, 554.37));
  noteTable.push_back(Note("D",    "D5",    62, 587.33));
  noteTable.push_back(Note("D#",   "D#5",  63, 622.25));
  noteTable.push_back(Note("E",    "E5",    64, 659.29));
  noteTable.push_back(Note("F",    "F5",    65, 696.46));
  noteTable.push_back(Note("F#",  "F#5",  66, 739.99));
  noteTable.push_back(Note("G",    "G5",    67, 783.99));
  noteTable.push_back(Note("G#",  "G#5",  68, 830.61));
  noteTable.push_back(Note("A",    "A5",    69, 880.00));
  noteTable.push_back(Note("A#",  "A#5",  70, 932.33));
  noteTable.push_back(Note("B",    "B5",    71, 987.77));
  noteTable.push_back(Note("C",    "C6",    72, 1046.5));
  noteTable.push_back(Note("C#",  "C#6",  73, 1108.7));
  noteTable.push_back(Note("D",    "D6",    74, 1174.7));
  noteTable.push_back(Note("D#",  "D#6",  75, 1244.5));
  noteTable.push_back(Note("E",    "E6",    76, 1318.5));
  noteTable.push_back(Note("F",    "F6",    77, 1396.9));
  noteTable.push_back(Note("F#",  "F#6",  78, 1480.0));
  noteTable.push_back(Note("G",    "G6",    79, 1568.0));
  noteTable.push_back(Note("G#",  "G#6",  80, 1661.2));
  noteTable.push_back(Note("A",    "A6",    81, 1760.0));
  noteTable.push_back(Note("A#",  "A#6",  82, 1864.7));
  noteTable.push_back(Note("B",    "B6",    83, 1975.5));
  noteTable.push_back(Note("C",    "C7",    84, 2093.0));
  noteTable.push_back(Note("C#",  "C#7",  85, 2217.5));
}

MusicalNoteTable::~MusicalNoteTable(void)
{
}

MusicalNoteTable::MusicalNoteTable(const MusicalNoteTable & note_table)
{
  *this = note_table;
}

MusicalNoteTable & MusicalNoteTable::operator=(const MusicalNoteTable & note_table)
{
  noteTable.erase(noteTable.begin(), noteTable.end()) ;
  NoteVector::const_iterator note_iter = note_table.noteTable.begin();
  while (note_iter != note_table.noteTable.end()) {
    noteTable.push_back(*note_iter);
    note_iter++;
  }
  return *this;
}

MusicalNoteTable::iterator MusicalNoteTable::GetNoteIterator(Note & a_note)
{
  return std::find(noteTable.begin(), noteTable.end(), a_note);
}

Note * MusicalNoteTable::GetAbsoluteNote(char * note_name)
{
  NoteVector::iterator note_iter = std::find(noteTable.begin(), noteTable.end(), Note("", note_name, 0, 0));
  if (note_iter != noteTable.end())
    return &(*note_iter);
  else
    return NULL;
}

MusicalNoteTable::iterator MusicalNoteTable::GetRelativeNoteIterator(char * note_name)
{
  NoteVector::iterator note_iter = noteTable.begin();
  while(note_iter != noteTable.end()) {
    if (!strcmp(note_name, (*note_iter).relativeName.c_str()))
      return note_iter;
    note_iter++;
  }
  return noteTable.end();
}

void MusicalNoteTable::CreateValidNoteVector(unsigned short scale_flags, unsigned short key_flags, NoteVector & valid_notes)
{
  NoteVector::iterator note_iter;
  switch (key_flags)
  {
    case E_KEY :
      note_iter = GetRelativeNoteIterator("E");
      break;

    case F_KEY :
      note_iter = GetRelativeNoteIterator("F");
      break;

    case FG_KEY :
      note_iter = GetRelativeNoteIterator("F#");
      break;

    case G_KEY :
      note_iter = GetRelativeNoteIterator("G");
      break;

    case GA_KEY :
      note_iter = GetRelativeNoteIterator("G#");
      break;

    case A_KEY :
      note_iter = GetRelativeNoteIterator("A");
      break;

    case AB_KEY :
      note_iter = GetRelativeNoteIterator("A#");
      break;

    case B_KEY :
      note_iter = GetRelativeNoteIterator("B");
      break;

    case C_KEY :
      note_iter = GetRelativeNoteIterator("C");
      break;

    case CD_KEY :
      note_iter = GetRelativeNoteIterator("C#");
      break;

    case D_KEY :
      note_iter = GetRelativeNoteIterator("D");
      break;

    case DE_KEY :
      note_iter = GetRelativeNoteIterator("D#");
      break;

  }

  switch (scale_flags)
  {
    case MAJOR :
      valid_notes.push_back(*note_iter);
      valid_notes.push_back(*(note_iter + 2));
      valid_notes.push_back(*(note_iter + 4));
      valid_notes.push_back(*(note_iter + 5));
      valid_notes.push_back(*(note_iter + 7));
      valid_notes.push_back(*(note_iter + 9));
      valid_notes.push_back(*(note_iter + 11));
      break;

    case MINOR :
      valid_notes.push_back(*note_iter);
      valid_notes.push_back(*(note_iter + 2));
      valid_notes.push_back(*(note_iter + 3));
      valid_notes.push_back(*(note_iter + 5));
      valid_notes.push_back(*(note_iter + 7));
      valid_notes.push_back(*(note_iter + 8));
      valid_notes.push_back(*(note_iter + 10));
      break;

     case MAJOR_PENTATONIC :
      valid_notes.push_back(*note_iter);
      valid_notes.push_back(*(note_iter + 2));
      valid_notes.push_back(*(note_iter + 4));
      valid_notes.push_back(*(note_iter + 7));
      valid_notes.push_back(*(note_iter + 9));
      break;

    case MINOR_PENTATONIC :
      valid_notes.push_back(*note_iter);
      valid_notes.push_back(*(note_iter + 3));
      valid_notes.push_back(*(note_iter + 5));
      valid_notes.push_back(*(note_iter + 7));
      valid_notes.push_back(*(note_iter + 10));
      break;

    case BLUES :
      valid_notes.push_back(*note_iter);
      valid_notes.push_back(*(note_iter + 3));
      valid_notes.push_back(*(note_iter + 5));
      valid_notes.push_back(*(note_iter + 6));
      valid_notes.push_back(*(note_iter + 7));
      valid_notes.push_back(*(note_iter + 10));
      break;

    case ALL_NOTES :
      valid_notes.push_back(*note_iter);
      valid_notes.push_back(*(note_iter + 1));
      valid_notes.push_back(*(note_iter + 2));
      valid_notes.push_back(*(note_iter + 3));
      valid_notes.push_back(*(note_iter + 4));
      valid_notes.push_back(*(note_iter + 5));
      valid_notes.push_back(*(note_iter + 6));
      valid_notes.push_back(*(note_iter + 7));
      valid_notes.push_back(*(note_iter + 8));
      valid_notes.push_back(*(note_iter + 9));
      valid_notes.push_back(*(note_iter + 10));
      valid_notes.push_back(*(note_iter + 11));
      break;
  }
}

bool MusicalNoteTable::IsValidNote(Note & a_note, NoteVector & valid_notes)
{
  NoteVector::iterator note_iter = valid_notes.begin();
  while(note_iter != valid_notes.end()) {
    if (a_note.relativeName == (*note_iter).relativeName)
      return true;
    note_iter++;
  }
  return false;
}

bool MusicalNoteTable::IsRootNote(Note & a_note, NoteVector & valid_notes)
{
   return a_note.relativeName == (*valid_notes.begin()).relativeName;
}

Copyright 2002-2007 Outerface Technologies, Inc.