pianobooster/src/Notation.h

233 lines
6.9 KiB
C++

/*********************************************************************************/
/*!
@file Notation.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/>.
*/
/*********************************************************************************/
#ifndef __NOTATION_H__
#define __NOTATION_H__
#include <cassert>
#include "MidiFile.h"
#include "Queue.h"
#include "Symbol.h"
#include "Chord.h"
#include "Bar.h"
#define MAX_SYMBOLS 20 // The maximum number of symbols that can be stored in one slot
class CSlot
{
public:
CSlot()
{
clear();
}
void clear()
{
m_length = 0;
m_deltaTime = 0;
m_av8Left = 0;
m_av8Right = 0;
m_maxLeftEdge = 0;
}
CSymbol getSymbol(int index) {return m_symbols[index];}
CSymbol* getSymbolPtr(int index) {return &m_symbols[index];}
musicalSymbol_t getSymbolType(int index) {return m_symbols[index].getType();}
int length() {return m_length;}
void setDeltaTime(qint64 delta) {m_deltaTime = delta;}
void addDeltaTime(qint64 delta) {m_deltaTime += delta;}
qint64 getDeltaTime() {return m_deltaTime;}
qint64 getLeftSideDeltaTime() {return m_deltaTime + m_maxLeftEdge;}
void setAv8Left(int val) {m_av8Left = val;}
int getAv8Left() {return m_av8Left;}
// return false on error
bool addSymbol(CSymbol symbol);
void analyse();
void setSymbol(qint64 delta, CSymbol symbol)
{
clear();
setDeltaTime(delta);
addSymbol(symbol);
}
void transpose(int amount)
{
for (int i = 0; i < m_length; i++)
{
m_symbols[i].transpose(amount);
}
}
void setNoteColor(int note, CColor color)
{
for (int i = 0; i < m_length; i++)
{
if (note == 0 || note == m_symbols[i].getNote())
m_symbols[i].setColor(color);
}
}
void setNoteTimming(int note, qint64 timing)
{
for (int i = 0; i < m_length; i++)
{
if (note == m_symbols[i].getNote() || note == 0)
m_symbols[i].setPianistTiming(timing);
}
if (timing < m_maxLeftEdge)
m_maxLeftEdge = timing;
}
void clearAllNoteTimmings()
{
for (int i = 0; i < m_length; i++)
{
m_symbols[i].setPianistTiming(NOT_USED);
}
m_maxLeftEdge = 0;
}
protected:
private:
qint64 m_deltaTime;
CSymbol m_symbols[MAX_SYMBOLS];
int m_length;
int m_av8Left;
int m_av8Right;
qint64 m_maxLeftEdge; // the furthest the note will appear on the left hand edge (used when removing the note)
};
// remembers the state of a running accidental
// Don't display the accidental twice in the same bar
class CNoteState
{
public:
CNoteState()
{
clear();
}
void clear()
{
m_barChangeCounter = -1;
m_accidentalState = PB_ACCIDENTAL_MODIFER_noChange;
m_noteLength = 0;
m_backLink = 0;
}
void setBarChange(int value){m_barChangeCounter = value;}
int getBarChange(){return m_barChangeCounter;}
void setAccidentalState(accidentalModifer_t value){m_accidentalState = value;}
accidentalModifer_t getAccidentalState(){return m_accidentalState;}
void setBackLink(CNoteState * link){m_backLink = link;}
CNoteState * getBackLink(){return m_backLink;}
private:
int m_barChangeCounter;
accidentalModifer_t m_accidentalState;
int m_noteLength; // Used to determine the note length
CNoteState* m_backLink;
};
enum {
NOTATE_demisemiquaverBoundary, // Demisemiquaver / Thirty-second note
NOTATE_threesixtyforthBoundary, // Three-sixtyforth note (thirty-second note with dot)
NOTATE_semiquaverBoundary, // Semiquaver / Sixteenth note
NOTATE_threethirtysecondBoundary, // Three-thirty-second note (sixteenth note with dot)
NOTATE_quaverBoundary, // Quaver / Eighth note
NOTATE_threesixteenthBoundary, // Three-sixteenth note (eighth note with dot)
NOTATE_crotchetBoundary, // Crotchet / Quarter note
NOTATE_threeeighthBoundary, // Three-eighth note (quarter note with dot)
NOTATE_minimBoundary, // Minim / Half note
NOTATE_threequaterBoundary, // Three-quater note (half note with dot)
NOTATE_semibreveBoundary, // Semibreve / Whole note
NOTATE_breveBoundary, // Breve / Double whole note
NOTATE_MAX_PARAMS // == MUST BE LAST ===
};
// Define a chord
class CNotation
{
public:
CNotation()
{
m_midiInputQueue = new CQueue<CMidiEvent>(1000);
m_slotQueue = new CQueue<CSlot>(200);
reset();
m_displayChannel = 0;
}
~CNotation()
{
delete m_midiInputQueue;
delete m_slotQueue;
}
void reset();
void resetNoteColor(CColor color);
void setChannel(int channel) {m_displayChannel = channel;}
CSlot nextSlot();
void midiEventInsert(CMidiEvent event);
int midiEventSpace() { return m_midiInputQueue->space();}
static void setCourtesyAccidentals(bool setting){m_cfg_displayCourtesyAccidentals = setting;}
static bool displayCourtesyAccidentals(){return m_cfg_displayCourtesyAccidentals; }
private:
CSlot nextBeatMarker();
int nextMergeSlot();
void findNoteSlots();
CSlot nextNoteSlot();
accidentalModifer_t detectSuppressedNatural(int note);
void setupNotationParamaters();
void calculateScoreNoteLength();
CQueue<CSlot>* m_slotQueue; // Queue of symbol slots that have not been read yet
CQueue<CMidiEvent>* m_midiInputQueue; // A Queue of midi events
CSlot m_currentSlot;
qint64 m_currentDeltaTime; // time difference between this and the previous slot
int m_beatPerBarCounter;
int m_earlyBarChangeCounter;
qint64 m_earlyBarChangeDelta; // Counts the ppqn in one bar
CSlot m_mergeSlots[2];
int m_displayChannel;
CFindChord m_findScrollerChord;
CBar m_bar;
CNoteState m_noteState[MAX_MIDI_NOTES];
static bool m_cfg_displayCourtesyAccidentals;
static int cfg_param[NOTATE_MAX_PARAMS];
};
#endif // __NOTATION_H__