pianobooster/src/StavePosition.cpp

324 lines
9.2 KiB
C++

/*********************************************************************************/
/*!
@file StavePos.h
@brief xxx.
@author L. J. Barman
Copyright (c) 2008-2013, L. J. Barman, all rights reserved
This file is part of the PianoBooster application
PianoBooster is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
PianoBooster is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with PianoBooster. If not, see <http://www.gnu.org/licenses/>.
*/
/*********************************************************************************/
#include "StavePosition.h"
#include "Draw.h"
float CStavePos::m_staveCenterY;
int CStavePos::m_KeySignature;
int CStavePos::m_KeySignatureMajorMinor;
const staveLookup_t* CStavePos::m_staveLookUpTable;
float CStavePos::m_staveCentralOffset = (staveHeight() * 3)/2;
////////////////////////////////////////////////////////////////////////////////
//! @brief Calculates the position of a note on the stave
void CStavePos::notePos(whichPart_t hand, int midiNote, int clef) // in fact clef is of type musicalSymbol_t but causes circular reference
{
const int notesInAnOctive = 7; // Don't count middle C twice
const int semitonesInAnOctive = 12;
setHand(hand);
int index = midiNote % semitonesInAnOctive;
const staveLookup_t* lookUpItem;
lookUpItem = &m_staveLookUpTable[index];
if (clef == -1) {
if (m_hand == PB_PART_right)
clef = PB_SYMBOL_gClef;
if (m_hand == PB_PART_left)
clef = PB_SYMBOL_fClef;
}
if ((m_hand == PB_PART_right && clef == PB_SYMBOL_gClef) || (m_hand == PB_PART_left && clef == PB_SYMBOL_gClef))
m_staveIndex = lookUpItem->pianoNote - 7;
else if ((m_hand == PB_PART_left && clef == PB_SYMBOL_fClef) || (m_hand == PB_PART_right && clef == PB_SYMBOL_fClef))
m_staveIndex = lookUpItem->pianoNote + 5;
m_staveIndex += (midiNote/semitonesInAnOctive)*notesInAnOctive - notesInAnOctive*5 ;
m_accidental = lookUpItem->accidental;
//ppLogTrace("chan %d Note %2d - %2d (%d %d %d),\n", midiNote, m_staveIndex, m_accidental,
//index%semitonesInAnOctive, lookUpItem->pianoNote, (midiNote/semitonesInAnOctive)*notesInAnOctive);
}
// convert the midi note to the note name C=1, D=2, E=3, F=4, G=5, A=6, B=7
staveLookup_t CStavePos::midiNote2Name(int midiNote)
{
const staveLookup_t* staffLookupC = getstaveLookupTable(0); // Key of C so we get all the not names
const int semitonesInAnOctive = 12;
int index = midiNote % semitonesInAnOctive;
staveLookup_t item = staffLookupC[index];
if (item.accidental != 0) // should it be a sharp or a flat
{
// Should it be called for example G# or Ab
if (item.pianoNote != m_staveLookUpTable[index].pianoNote)
{
item.pianoNote = m_staveLookUpTable[index].pianoNote;
if (m_KeySignature > 0)
item.accidental = 1; // And change to sharp
else
item.accidental = -1; // But use a flat
}
}
return item;
}
void CStavePos::setKeySignature(int key, int majorMinor)
{
m_KeySignature = key;
m_KeySignatureMajorMinor = majorMinor;
if (key == NOT_USED)
key = 0;
m_staveLookUpTable = getstaveLookupTable(key);
CDraw::forceCompileRedraw();
}
const staveLookup_t* CStavePos::getstaveLookupTable(int key)
{
const staveLookup_t* staveLookup;
static const staveLookup_t staffLookupFlat6[] = { // Gb [Bb Eb Ab Db Gb Cb]
{1, 2}, // Cn
{2, 0}, //.Db
{2, 2}, // Dn
{3, 0}, //.Eb
{3, 2}, // En
{4, 0}, //.F
{5, 0}, //-Gb
{5, 2}, // Gn
{6, 0}, //.Ab
{6, 2}, // An
{7, 0}, //.Bb
{8, 0} //.Cb also called Bn
};
static const staveLookup_t staffLookupFlat5[] = { // Db [Bb Eb Ab Db Gb]
{1, 0}, //.C
{2, 0}, //-Db
{2, 2}, // Dn
{3, 0}, //.Eb
{3, 2}, // En
{4, 0}, //.F
{5, 0}, //.Gb
{5, 2}, // Gn
{6, 0}, //.Ab
{6, 2}, // An
{7, 0}, //.Bb
{7, 2} // Bn
};
static const staveLookup_t staffLookupFlat4[] = { // Ab [Bb Eb Ab Db]
{1, 0}, //.C
{2, 0}, //.Db
{2, 2}, // Dn
{3, 0}, //.Eb
{3, 2}, // En
{4, 0}, //.F
{5,-1}, // Gb
{5, 0}, //.G
{6, 0}, //-Ab
{6, 2}, // An
{7, 0}, //.Bb
{7, 2} // Bn
};
static const staveLookup_t staffLookupFlat3[] = { // Eb [Bb Eb Ab]
{1, 0}, //.C
{2,-1}, // Db
{2, 0}, //.D
{3, 0}, //-Eb
{3, 2}, // En
{4, 0}, //.F
{5,-1}, // Gb
{5, 0}, //.G
{6, 0}, //.Ab
{6, 2}, // An
{7, 0}, //.Bb
{7, 2} // Bn
};
static const staveLookup_t staffLookupFlat2[] = { // Bb [Bb Eb]
{1, 0}, //.C
{2,-1}, // Db
{2, 0}, //.D
{3, 0}, //.Eb
{3, 2}, // En
{4, 0}, //.F
{4, 1}, // F# (Gb)
{5, 0}, //.G
{6,-1}, // Ab
{6, 0}, //.A
{7, 0}, //-Bb
{7, 2} // Bn
};
static const staveLookup_t staffLookupFlat1[] = { // F [Bb]
{1, 0}, //.C
{1, 1}, // C# (Db)
{2, 0}, //.D
{3,-1}, // Eb
{3, 0}, //.E
{4, 0}, //-F
{4, 1}, // F#
{5, 0}, //.G
{6,-1}, // Ab
{6, 0}, //.A
{7, 0}, //.Bb
{7, 2} // Bn
};
// more flats Cb Gb Db Ab Eb Bb <--> F# C# G# D# A# E# more sharps
static const staveLookup_t staffLookupC[] = {
{1, 0}, //-C
{1, 1}, // C#
{2, 0}, //.D
{3,-1}, // Eb
{3, 0}, //.E
{4, 0}, //.F
{4, 1}, // F#
{5, 0}, //.G
{5, 1}, // G# (or Ab)
{6, 0}, //.A
{7,-1}, // Bb
{7, 0} //.B
};
static const staveLookup_t staffLookupSharp1[] = { // G [F#]
{1, 0}, //.C
{1, 1}, // C#
{2, 0}, //.D
{2, 1}, // D# (Eb)
{3, 0}, //.E
{4,-2}, // Fn
{4, 0}, //.F#
{5, 0}, //-G
{5, 1}, // G#
{6, 0}, //.A
{7,-1}, // Bb
{7, 0} //.B
};
static const staveLookup_t staffLookupSharp2[] = { // D [F# C#]
{1,-2}, // Cn
{1, 0}, //.C#
{2, 0}, //-D
{2, 1}, // D#
{3, 0}, //.E
{4,-2}, // Fn
{4, 0}, //.F#
{5, 0}, //.G
{5, 1}, // G#
{6, 0}, //.A
{6, 1}, // A# (Bb)
{7, 0} //.B
};
static const staveLookup_t staffLookupSharp3[] = { // A [F# C# G#]
{1,-2}, // Cn
{1, 0}, //.C#
{2, 0}, //.D
{2, 1}, // D#
{3, 0}, //.E
{4,-2}, // Fn
{4, 0}, //.F#
{5,-2}, // Gn
{5, 0}, //.G#
{6, 0}, //-A
{6, 1}, // A#
{7, 0} //.B
};
static const staveLookup_t staffLookupSharp4[] = { // E [F# C# G# D#]
{1,-2}, // Cn
{1, 0}, //.C#
{2,-2}, // Dn
{2, 0}, //.D#
{3, 0}, //-E
{4,-2}, // Fn
{4, 0}, //.F#
{5,-2}, // Gn
{5, 0}, //.G#
{6, 0}, //.A
{6, 1}, // A#
{7, 0} //.B
};
static const staveLookup_t staffLookupSharp5[] = { // B [F# C# G# D# A#]
{1,-2}, // Cn
{1, 0}, //.C#
{2,-2}, // Dn
{2, 0}, //.D#
{3, 0}, //.E
{4,-2}, // Fn
{4, 0}, //.F#
{5,-2}, // Gn
{5, 0}, //.G#
{6,-2}, // An
{6, 0}, //.A#
{7, 0} //-B
};
// I think there should be some double sharps here ??
static const staveLookup_t staffLookupSharp6[] = { // F# [F# C# G# D# A# E#]
{1,-2}, // Cn
{1, 0}, //.C#
{2,-2}, // Dn
{2, 0}, //.D#
{3,-2}, // En
{3, 0}, //.E# (really F natural!!!!)
{4, 0}, //-F#
{5,-2}, // Gn
{5, 0}, //.G#
{6,-2}, // An
{6, 0}, //.A#
{7, 0} //.B
};
// Cb Gb Db Ab Eb Bb <> F# C# G# D# A# E#
switch (key)
{
case -6: staveLookup = staffLookupFlat6; break;
case -5: staveLookup = staffLookupFlat5; break;
case -4: staveLookup = staffLookupFlat4; break;
case -3: staveLookup = staffLookupFlat3; break;
case -2: staveLookup = staffLookupFlat2; break;
case -1: staveLookup = staffLookupFlat1; break;
case 0: staveLookup = staffLookupC; break;
case 1: staveLookup = staffLookupSharp1; break;
case 2: staveLookup = staffLookupSharp2; break;
case 3: staveLookup = staffLookupSharp3; break;
case 4: staveLookup = staffLookupSharp4; break;
case 5: staveLookup = staffLookupSharp5; break;
case 6: staveLookup = staffLookupSharp6; break;
default: staveLookup = staffLookupC; break;
}
return staveLookup;
}