Now suppress the second accidental in the bar

git-svn-id: https://svn.code.sf.net/p/pianobooster/code/trunk@72 ba081f5d-443b-49a7-ac4b-446c3f91f371
This commit is contained in:
louisjb 2009-09-08 20:26:39 +00:00
parent 1be64a1519
commit 1cda5c60e1
20 changed files with 185 additions and 34 deletions

View File

@ -53,6 +53,7 @@ void CBar::setTimeSig(int top, int bottom)
}
}
m_beatLength = (CMidiFile::getPulsesPerQuarterNote() *4)/ m_currentTimeSigBottom;
m_barLength = m_beatLength * getTimeSigTop();
}
int CBar::addDeltaTime(int ticks)

View File

@ -57,6 +57,7 @@ public:
int getTimeSigTop() {return m_currentTimeSigTop;} // The Numerator
int getBeatLength() {return m_beatLength;}
int getBarLength() {return m_barLength;} // in ppqn
void setPlayFromBar(double bar);
void setPlayFromBar(int bar, int beat = 0, int ticks = 0);
@ -121,7 +122,8 @@ private:
int m_deltaTime;
int m_beatLength;
int m_beatLength; //in ppqn ticks
int m_barLength; // m_beatLength * getTimeSigTop() (also in ppqn ticks)
int m_startTimeSigTop; // The time Sig at the start of the piece
int m_startTimeSigBottom;

View File

@ -47,7 +47,6 @@ INCLUDE( ${QT_USE_FILE} )
IF (USE_PCH)
INCLUDE(precompile/PCHSupport_26.cmake)
INCLUDE_DIRECTORIES( precompile .)
ENDIF(USE_PCH)

View File

@ -74,6 +74,7 @@ public:
static int playZoneLate() {return m_playZoneLate;}
static int silenceTimeOut() {return 8000;} // the time in msec before everything goes quiet
static int chordNoteGap() {return 10;} // all notes in a cord must be spaced less than this a gap
static int chordMaxLength() {return 20;} // the max time between the start and end of a cord
static CColour menuColour() {return CColour(0.1, 0.6, 0.6);}

View File

@ -168,9 +168,11 @@ bool CFindChord::findChord(CMidiEvent midi, int channel, whichPart_t part)
return foundChord;
}
m_runningDeltaTime += midi.deltaTime();
m_noteGapTime += midi.deltaTime();
if (m_runningDeltaTime >= m_cfg_ChordNoteGap && m_currentChord.length() > 0)
if ((m_noteGapTime >= m_cfg_ChordNoteGap || m_cordSpanGapTime > m_cfg_ChordMaxLength)
&& m_currentChord.length() > 0 )
{
foundChord = true;
m_completeChord = m_currentChord;
@ -183,8 +185,12 @@ bool CFindChord::findChord(CMidiEvent midi, int channel, whichPart_t part)
if ( hand != PB_PART_none)
{
m_currentChord.addNote(hand, midi.note());
m_currentChord.setDeltaTime(m_runningDeltaTime + m_currentChord.getDeltaTime());
m_runningDeltaTime = 0;
m_currentChord.setDeltaTime(m_noteGapTime + m_currentChord.getDeltaTime());
if (m_currentChord.length() <= 1)
m_cordSpanGapTime = 0;
else
m_cordSpanGapTime += m_noteGapTime; // measure the span of the cord
m_noteGapTime = 0;
}
}
return foundChord;

View File

@ -180,10 +180,12 @@ public:
void reset()
{
m_runningDeltaTime = 0;
m_noteGapTime = 0;
m_cordSpanGapTime = 0;
m_completeChord.clear();
m_currentChord.clear();
m_cfg_ChordNoteGap = CMidiFile::ppqnAdjust(Cfg::chordNoteGap());
m_cfg_ChordMaxLength = CMidiFile::ppqnAdjust(Cfg::chordMaxLength());
}
@ -197,10 +199,12 @@ public:
bool findChord(CMidiEvent midi, int channel, whichPart_t part);
private:
int m_runningDeltaTime;
int m_noteGapTime;
int m_cordSpanGapTime;
CChord m_currentChord;
CChord m_completeChord;
int m_cfg_ChordNoteGap;
int m_cfg_ChordMaxLength;
};
#endif // __CHORD_H__

View File

@ -269,6 +269,9 @@ void CDraw::checkAccidental(CSymbol symbol, float x, float y)
accidental = symbol.getStavePos().getAccidental();
if (symbol.getAccidentalModifer() == PB_ACCIDENTAL_MODIFER_suppress_accidental)
accidental = 0; // Suppress the accidental if it is the same bar
if (accidental != 0)
{
//drColour (Cfg::lineColour());

View File

@ -121,7 +121,7 @@ void GuiTopBar::reloadKeyCombo(bool major)
void GuiTopBar::on_keyCombo_activated(int index)
{
CStavePos::setKeySignature(index - 6);
CStavePos::setKeySignature(index - 6, 0);
m_song->refreshScroll();
}
@ -144,7 +144,7 @@ void GuiTopBar::on_transposeSpin_valueChanged(int value)
int newValue = nextKey[(diff + i + arraySize(nextKey)) % arraySize(nextKey) ];
CStavePos::setKeySignature( newValue );
CStavePos::setKeySignature( newValue, 0 );
newValue += 6;
keyCombo->setCurrentIndex(newValue);

View File

@ -53,8 +53,9 @@
#define MIDI_PB_chordSeparator 0x0ff3 // All the notes (note on) between these counts as one chord
#define MIDI_PB_tempo 0x0ff4
#define MIDI_PB_timeSignature 0x0ff5
#define MIDI_PB_collateRawMidiData 0x0ff6
#define MIDI_PB_outputRawMidiData 0x0ff7 // Raw data is used for used for a SYSTEM_EVENT
#define MIDI_PB_keySignature 0x0ff6
#define MIDI_PB_collateRawMidiData 0x0ff7
#define MIDI_PB_outputRawMidiData 0x0ff8 // Raw data is used for used for a SYSTEM_EVENT
/*===================================*/
/* */

View File

@ -30,7 +30,7 @@
#include "MidiTrack.h"
#include "Util.h"
#define OPTION_DEBUG_TRACK 0
#define OPTION_DEBUG_TRACK 1//fixme 0
#if OPTION_DEBUG_TRACK
#define ppDEBUG_TRACK(args) ppDebugTrack args
#else
@ -199,9 +199,37 @@ void CMidiTrack::readTimeSignatureEvent()
b4 = readByte(); /* Ignore the last bytes */
event.metaEvent(readDelaTime(), MIDI_PB_timeSignature, timeSigNumerator, 1<<timeSigDenominator);
m_trackEventQueue->push(event);
ppDEBUG_TRACK((4,"Time Signature %d/%d metronome %d quarter %d", timeSigNumerator, 1<<timeSigDenominator, b3, b4));
ppDEBUG_TRACK((4,"Key Signature %d/%d metronome %d quarter %d", timeSigNumerator, 1<<timeSigDenominator, b3, b4));
}
/* Key Signature */
void CMidiTrack::readKeySignatureEvent()
{
byte_t len;
CMidiEvent event;
int keySig;
int majorKey;
len = readVarLen();
if (len!=2)
{
errorFail(SMF_CORRUPTED_MIDI_FILE);
return;
}
keySig = static_cast<char>(readByte()); // force sign converstion The key sig 0=middle C
majorKey =readByte(); // Major or Minor
if (keySig >= 7 || keySig <= -7 )
{
errorFail(SMF_CORRUPTED_MIDI_FILE);
return;
}
event.metaEvent(readDelaTime(), MIDI_PB_keySignature, keySig, majorKey);
m_trackEventQueue->push(event);
ppDEBUG_TRACK((4,"Key Signature %d maj/min %d", keySig, majorKey));
}
void CMidiTrack::readMetaEvent(byte_t type)
{
@ -267,11 +295,8 @@ void CMidiTrack::readMetaEvent(byte_t type)
break;
case METAKEYSIG: /* Key Signature */
{
data = readDataEvent(2);
ppDEBUG_TRACK((4,"Key Signature %d %s", (int)(data>>8), ((data&0xff) ==0)?"Major":"Minor"));
break;
}
readKeySignatureEvent();
break;
case METATEXT: /* Text Event */
text = readTextEvent();
@ -313,11 +338,14 @@ void CMidiTrack::readMetaEvent(byte_t type)
ppDEBUG_TRACK((2,"MIDI Port %lu", data));
break;
case 0x09: // meta type
text = readTextEvent();
ppDEBUG_TRACK((2,"fixme midi meta event 0x%02x %s", type, text.c_str()));
break;
default: /* Unknown meta type */
text = readTextEvent();
//strict_error("SM9");
ppDEBUG_TRACK((99,"UNKNOWN meta event 0x%02x %s", type, text.c_str()));
errorFail(SMF_UNKNOW_EVENT);
ppLogWarn("unknown midi meta event 0x%02x %s", type, text.c_str());
//errorFail(SMF_UNKNOW_EVENT);
break;
}
}
@ -342,7 +370,6 @@ void CMidiTrack::decodeSystemMessage( byte_t status, byte_t data1 )
default:
ppDEBUG_TRACK((99,"UNKNOWN"));
ignoreSysexEvent(data1);
//strict_error("SM8");
//read_sysex_event();
errorFail(SMF_UNKNOW_EVENT);
break;

View File

@ -102,7 +102,7 @@ private:
{
m_midiError = error;
if (m_midiError != SMF_NO_ERROR)
ppError("Error Fail %d", m_midiError);
ppError("Midi error %d", m_midiError);
}
}
@ -152,6 +152,7 @@ private:
void ignoreSysexEvent(byte_t data);
void readTimeSignatureEvent();
void readKeySignatureEvent();
void decodeSystemMessage( byte_t status, byte_t data1 );

View File

@ -94,7 +94,7 @@ void CSlot::analyse()
CSlot CNotation::nextBeatMarker()
{
const int cfg_barGap = CMidiFile::getPulsesPerQuarterNote() * 30 / DEFAULT_PPQN;
const int cfg_barGap = CMidiFile::ppqnAdjust(30);
CSlot slot;
@ -140,6 +140,31 @@ int CNotation::nextMergeSlot()
return nearestIndex;
}
accidentalModifer_t CNotation::detectSuppressedNatural(int note)
{
accidentalModifer_t modifer = PB_ACCIDENTAL_MODIFER_noChange;
if (note <= 0 || note +1 >= MAX_MIDI_NOTES)
return modifer;
while (m_earlyBarChangeDelta >= m_bar.getBarLength())
{
m_earlyBarChangeDelta -= m_bar.getBarLength();
m_earlyBarChangeCounter++;
}
//int accidental = CStavePos::getStaveAccidental(note);
// check if this note has occured in this bar before
if (m_noteState[note].getBarChange() == m_earlyBarChangeCounter)
modifer = PB_ACCIDENTAL_MODIFER_suppress_accidental;
/*
if (m_noteState[note + 1].getBarChange() == m_earlyBarChangeCounter)
modifer = PB_ACCIDENTAL_MODIFER_above;
if (m_noteState[note - 1].getBarChange() == m_earlyBarChangeCounter)
modifer = PB_ACCIDENTAL_MODIFER_below;*/
m_noteState[note].setBarChange(m_earlyBarChangeCounter);
return modifer;
}
void CNotation::findNoteSlots()
{
CMidiEvent midi;
@ -154,6 +179,7 @@ void CNotation::findNoteSlots()
midi = m_midiInputQueue->pop();
m_currentDeltaTime += midi.deltaTime();
m_earlyBarChangeDelta += midi.deltaTime();
if (midi.type() == MIDI_PB_chordSeparator || midi.type() == MIDI_PB_EOF)
{
if (m_currentSlot.length() > 0)
@ -173,6 +199,8 @@ void CNotation::findNoteSlots()
else if (midi.type() == MIDI_PB_timeSignature)
m_bar.setTimeSig(midi.data1(), midi.data2());
else if (midi.type() == MIDI_PB_keySignature)
CStavePos::setKeySignature(midi.data1(), midi.data2());
else if (midi.type() == MIDI_NOTE_ON)
{
whichPart_t hand = CNote::findHand( midi, m_displayChannel, PB_PART_both );
@ -185,8 +213,12 @@ void CNotation::findNoteSlots()
symbolType = PB_SYMBOL_note;
CSymbol symbol(symbolType, hand, midi.note());
symbol.setColour(Cfg::noteColour());
// check if this note has occured in this bar before
symbol.setAccidentalModifer(detectSuppressedNatural(midi.note()));
if (m_currentSlot.addSymbol(symbol) == false) {
ppLogWarn("[%d] Over the Max symbols limit", m_displayChannel + 1); //fix me
ppLogWarn("[%d] Over the Max symbols limit", m_displayChannel + 1); //fixme
}
m_currentSlot.addDeltaTime(m_currentDeltaTime);
m_currentDeltaTime = 0;
@ -195,6 +227,7 @@ void CNotation::findNoteSlots()
if (midi.note() < MIDI_BOTTOM_C)
m_currentSlot.setAv8Left(MIDI_OCTAVE);
}
}
}
}
@ -255,6 +288,8 @@ void CNotation::midiEventInsert(CMidiEvent event)
void CNotation::reset()
{
const int cfg_earlBarLead = CMidiFile::ppqnAdjust(8);
size_t i;
m_currentDeltaTime = 0;
m_midiInputQueue->clear();
@ -263,6 +298,13 @@ void CNotation::reset()
m_mergeSlots[i].clear();
m_currentSlot.clear();
m_beatPerBarCounter=0;
m_earlyBarChangeCounter = 0;
m_earlyBarChangeDelta = cfg_earlBarLead; // We want to detect the bar change early
m_bar.reset();
m_findScrollerChord.reset();
for( i = 0; i < MAX_MIDI_NOTES; i++)
{
m_noteState[i].clear();
}
}

View File

@ -128,6 +128,31 @@ private:
int 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 = 0;
m_accidentalState = PB_ACCIDENTAL_MODIFER_noChange;
m_noteLength = 0;
}
void setBarChange(int value){m_barChangeCounter = value;}
int getBarChange(){return m_barChangeCounter;}
void setAccidentalState(accidentalModifer_t value){m_accidentalState = value;}
accidentalModifer_t setAccidentalState(){return m_accidentalState;}
private:
int m_barChangeCounter;
accidentalModifer_t m_accidentalState;
int m_noteLength; // Used to determine the note length
};
// Define a chord
class CNotation
@ -160,16 +185,21 @@ private:
int nextMergeSlot();
void findNoteSlots();
CSlot nextNoteSlot();
accidentalModifer_t detectSuppressedNatural(int note);
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;
int m_currentDeltaTime;
int m_beatPerBarCounter;
int m_earlyBarChangeCounter;
int 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];
};
#endif // __NOTATION_H__

View File

@ -311,8 +311,8 @@ void CSettings::setCurrentSongName(const QString & name)
m_song->loadSong(getCurrentSongLongFileName());
loadSongSettings();
m_guiTopBar->refresh(true);
m_guiSidePanel->refresh();
m_guiTopBar->refresh(true);
m_mainWindow->setWindowTitle("Piano Booster - " + m_song->getSongTitle());
}

View File

@ -58,12 +58,13 @@ void CSong::loadSong(const QString & filename)
if (index >= 0)
m_songTitle = m_songTitle.right( m_songTitle.length() - index - 1);
QString fn = filename;
#ifdef _WIN32
filename = filename.replace('/','\\');
fn = fn.replace('/','\\');
#endif
m_midiFile->setLogLevel(3);
m_midiFile->openMidiFile(string(filename.toAscii()));
ppLogInfo("Opening song %s", string(filename.toAscii()).c_str());
m_midiFile->openMidiFile(string(fn.toAscii()));
ppLogInfo("Opening song %s", string(fn.toAscii()).c_str());
transpose(0);
midiFileInfo();
m_midiFile->setLogLevel(99);
@ -83,6 +84,7 @@ void CSong::midiFileInfo()
{
m_trackList->clear();
setTimeSig(0,0);
CStavePos::setKeySignature( NOT_USED, 0 );
// Read the next events to find the active channels
CMidiEvent event;

View File

@ -43,7 +43,7 @@ class CSong : public CConductor
public:
CSong()
{
CStavePos::setKeySignature(0);
CStavePos::setKeySignature( NOT_USED, 0 );
m_midiFile = new CMidiFile;
m_trackList = new CTrackList;

View File

@ -32,6 +32,7 @@
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;
@ -84,9 +85,12 @@ staveLookup_t CStavePos::midiNote2Name(int midiNote)
return item;
}
void CStavePos::setKeySignature(int key)
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();
}

View File

@ -113,7 +113,7 @@ public:
static float getVerticalNoteSpacing(){return verticalNoteSpacing();}
static float getStaveCenterY(){return m_staveCenterY;}
static void setStaveCenterY(float y) { m_staveCenterY = y; }
static void setKeySignature(int key);
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;}
@ -122,6 +122,13 @@ public:
// 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
static int getStaveAccidental(int midiNote)
{
return m_staveLookUpTable[midiNote%12].accidental;
}
private:
// fixme TODO This could be improved as the calculations could a done in the constructor
@ -132,6 +139,7 @@ private:
static int m_KeySignature;
static int m_KeySignatureMajorMinor;
static const staveLookup_t* m_staveLookUpTable;
static float m_staveCentralOffset;
static float m_staveCenterY;

View File

@ -52,6 +52,13 @@ typedef enum
PB_SYMBOL_theEnd
} musicalSymbol_t;
typedef enum {
PB_ACCIDENTAL_MODIFER_noChange,
PB_ACCIDENTAL_MODIFER_suppress_accidental,
PB_ACCIDENTAL_MODIFER_force_natural
} accidentalModifer_t;
#define BEAT_MARKER_OFFSET 20 // used to ensure that beat markers are drawn under the note by drawing them early
class CSymbol
@ -125,6 +132,16 @@ public:
int getNoteIndex() { return m_index; }
int getNoteTotal() { return m_total; }
////////////////////////////////////////////////////////////////////////////////
//! @brief The accidental
//! return 0 = none, 1=sharp, -1 =flat, 2=natural.
int getAccidental() {
return getStavePos().getAccidental();
}
void setAccidentalModifer(accidentalModifer_t value) {m_accidentalModifer = value;}
accidentalModifer_t getAccidentalModifer() {return m_accidentalModifer;}
private:
@ -136,11 +153,13 @@ private:
m_midiDuration = 0;
m_pianistTiming = NOT_USED;
setIndex(0,0);
m_accidentalModifer = PB_ACCIDENTAL_MODIFER_noChange;
}
CStavePos m_stavePos;
musicalSymbol_t m_symbolType;
byte m_midiNote;
accidentalModifer_t m_accidentalModifer; // Used to suppress the second sharp in the same bar
unsigned long m_midiDuration;
whichPart_t m_hand;

View File

@ -202,7 +202,8 @@ void CTrackList::refresh()
}
}
CStavePos::setKeySignature(guessKeySignature(CNote::rightHandChan(),CNote::leftHandChan()));
if (CStavePos::getKeySignature() == NOT_USED)
CStavePos::setKeySignature(guessKeySignature(CNote::rightHandChan(),CNote::leftHandChan()), 0);
int goodChan = -1;
// Find an unused channel that we can use for the keyboard