pianobooster/src/StavePosition.h

159 lines
6.0 KiB
C++

/*********************************************************************************/
/*!
@file StavePosition.h
@brief xxxxxx.
@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/>.
*/
/*********************************************************************************/
#ifndef __STAVE_POS_H__
#define __STAVE_POS_H__
#include "Util.h"
#include "Chord.h"
typedef struct {
int pianoNote; // 1 is Middle C, 2 is D
int accidental;
} staveLookup_t;
#define NOT_USED 0x7fffffff
#define MAX_STAVE_INDEX 16
#define MIN_STAVE_INDEX -16
//----------------------------------------------------------------------------
// CStavePos
//----------------------------------------------------------------------------
//! @brief Calculates the position on the stave from the stave index number.
class CStavePos
{
public:
////////////////////////////////////////////////////////////////////////////////
//! @brief The default constructor.
CStavePos()
{
m_staveIndex = 0;
m_accidental = 0;
setHand(PB_PART_none);
};
////////////////////////////////////////////////////////////////////////////////
//! @brief Constructs the Stave position object.
//! @param hand the top (right hand) or the bottom the (left hand) see @ref whichPart_t.
//! @param index the save index number: 0 central line, 5 = top line, -5 the bottom line.
//! @param accidental Indicates an accidental 0 = none, 1=sharp, -1 =flat.
CStavePos(whichPart_t hand, int index, int accidental = 0)
{
m_staveIndex = index;
m_accidental = accidental;
setHand(hand);
};
////////////////////////////////////////////////////////////////////////////////
//! @brief Sets which stave the note will appear on
//! @param hand the top (right hand) or the bottom the (left hand) see @ref whichPart_t.
void setHand(whichPart_t hand)
{
m_hand = hand;
m_offsetY = getStaveCenterY();
if (m_hand == PB_PART_right)
m_offsetY += staveCentralOffset();
else if (m_hand == PB_PART_left)
m_offsetY -= staveCentralOffset();
}
void notePos(whichPart_t hand, int midiNote, int clef = -1); // in fact clef is of type musicalSymbol_t but causes circular reference
////////////////////////////////////////////////////////////////////////////////
//! @brief Sets which stave the note will appear on
//! return The position on the stave.
float getPosY()
{
return verticalNoteSpacing() * static_cast<float>(m_staveIndex) + m_offsetY;
}
float getPosYAccidental() {
int accidental = m_accidental;
if (accidental == 2) accidental = 1;
else if (accidental == -2) accidental = -1;
return getPosY() + static_cast<float>(accidental) * verticalNoteSpacing() / 2;
}
float getPosYRelative() { return getPosY() - m_staveCenterY;} // get the Y position relative to the stave centre
////////////////////////////////////////////////////////////////////////////////
//! @brief The accidental
//! return 0 = none, 1=sharp, -1 =flat, 2=natural.
int getAccidental() {return m_accidental;}
int getStaveIndex() {return m_staveIndex;}
whichPart_t getHand() {return m_hand;}
static float getVerticalNoteSpacing(){return verticalNoteSpacing();}
static float getStaveCenterY(){return m_staveCenterY;}
static void setStaveCenterY(float y) { m_staveCenterY = y; }
static void setKeySignature(int key, int majorMinor);
static int getKeySignature() {return m_KeySignature;}
static void setStaveCentralOffset(float gap) { m_staveCentralOffset = gap; }
static float verticalNoteSpacing() {return 7;}
static float staveHeight() {return verticalNoteSpacing() * 8;}
static float staveCentralOffset() {return m_staveCentralOffset;}
// convert the midi note to the note name A B C D E F G
static staveLookup_t midiNote2Name(int midiNote);
static const staveLookup_t* getstaveLookupTable(int key);
// do we show a sharp or a flat for this key signature
// returns 0 = none, 1=sharp, -1 =flat, 2=natural (# Key) , -2=natural (b Key)
static int getStaveAccidental(int midiNote)
{
return m_staveLookUpTable[midiNote%12].accidental;
}
// returns 0 = none, 1=above, -1 =below, (a natural is either above or below)
static int getStaveAccidentalDirection(int midiNote)
{
int accidentalDirection = getStaveAccidental(midiNote);
if (accidentalDirection == 2) // A natural so change to above
accidentalDirection = 1;
else if (accidentalDirection == -2) // A natural so change to below
accidentalDirection = -1;
return accidentalDirection;
}
private:
// fixme TODO This could be improved as the calculations could a done in the constructor
int m_staveIndex; // 0 central line, 5 = top line, -5 the bottom line,
int m_accidental; // 0 = none, 1=sharp, -1 =flat, 2=natural
float m_offsetY;
whichPart_t m_hand;
static int m_KeySignature;
static int m_KeySignatureMajorMinor;
static const staveLookup_t* m_staveLookUpTable;
static float m_staveCentralOffset;
static float m_staveCenterY;
};
#endif //__STAVE_POS_H__