diff --git a/src/GlView.cpp b/src/GlView.cpp index b1356c7..9378052 100644 --- a/src/GlView.cpp +++ b/src/GlView.cpp @@ -229,7 +229,7 @@ void CGLView::drawDisplayText() if (accuracyBarStart == 0) { QFontMetrics fm(m_timeRatingFont); accuracyText = tr("Accuracy:"); - accuracyBarStart=fm.horizontalAdvance(accuracyText + " ") + TEXT_LEFT_MARGIN; + accuracyBarStart=fm.boundingRect(accuracyText + " ").right() + TEXT_LEFT_MARGIN; } renderText(TEXT_LEFT_MARGIN, y-4,0 ,accuracyText, m_timeRatingFont); diff --git a/src/GuiTopBar.cpp b/src/GuiTopBar.cpp index 4ac8b09..d94cc74 100644 --- a/src/GuiTopBar.cpp +++ b/src/GuiTopBar.cpp @@ -128,6 +128,7 @@ void GuiTopBar::on_transposeSpin_valueChanged(int value) { unsigned int i; //C Db D Eb E F F# G Ab A Bb B const int nextKey[] = { 0, -5, 2, -3, 4, -1, 6, 1, -4, 3, -2, 5}; + const int nextKeySize = arraySize(nextKey); if (!m_song) return; int diff = value - m_song->getTranspose(); int oldValue = CStavePos::getKeySignature(); @@ -135,13 +136,13 @@ void GuiTopBar::on_transposeSpin_valueChanged(int value) oldValue = 6; // if key is Eb change to D# // Find the old value in the table - for (i=0; i < arraySize(nextKey); i++) + for (i=0; i < nextKeySize; i++) { if (oldValue == nextKey[i]) break; } - int newValue = nextKey[(diff + i + arraySize(nextKey)) % arraySize(nextKey) ]; + int newValue = nextKey[(diff + i + nextKeySize) % nextKeySize ]; CStavePos::setKeySignature( newValue, 0 ); diff --git a/src/MidiEvent.h b/src/MidiEvent.h index 246a245..ca8e8a5 100644 --- a/src/MidiEvent.h +++ b/src/MidiEvent.h @@ -82,6 +82,7 @@ #define METASEQEVENT 0x7F #define GM_PIANO_PATCH 0 // The default grand piano sound +#define isPianoOrOrganPatch(p) (((p) >= 0 && (p) <=7) || ((p) >= 16 && (p) <= 23 )) /*! * @brief xxxxx. @@ -107,6 +108,7 @@ public: int deltaTime(){return m_deltaTime;} void addDeltaTime(int delta){m_deltaTime +=delta;} + void subtractDeltaTime(int delta){m_deltaTime -=delta;} void setDeltaTime(int delta){m_deltaTime = delta;} //////////////////////////////////////////////////////////////////////////////// @@ -232,6 +234,33 @@ public: //@brief how long the midi note was played for long getDuration(){return m_duration;} + + /** + * This merges two MidiEvents (this and the other MidiEvent) + * The MidiEvent that happens first (has the lowest delta time) + * then a COPY of that MidiEvent is returned. + * The original is then cleared so that it type is set to MIDI_NONE + * The MidiEvent that happens second will have it delta time reduced + * using the delta time form the first MidiEvent. + * NOTE Both this and the otherMidiEvent will be altered when call this method. + */ + CMidiEvent getNextMergedEvent(CMidiEvent &otherMidiEvent) + { + CMidiEvent result; + int thisDelta = deltaTime(); + int otherDelta = otherMidiEvent.deltaTime(); + if ( thisDelta <= otherDelta ) { + result = *this; + otherMidiEvent.subtractDeltaTime(thisDelta); + clear(); + } else { + result = otherMidiEvent; + subtractDeltaTime(otherDelta); + otherMidiEvent.clear(); + } + return result; + } + std::string event_type_str(int atype) { std::string r; diff --git a/src/TrackList.cpp b/src/TrackList.cpp index 4794643..ce866c9 100644 --- a/src/TrackList.cpp +++ b/src/TrackList.cpp @@ -89,20 +89,44 @@ void CTrackList::examineMidiEvent(CMidiEvent event) // Returns true if there is a piano part on channels 3 & 4 bool CTrackList::pianoPartConvetionTest() { - if ((m_midiFirstPatchChannels[CONVENTION_LEFT_HAND_CHANNEL] == GM_PIANO_PATCH && + if (m_midiFirstPatchChannels[CONVENTION_LEFT_HAND_CHANNEL] == GM_PIANO_PATCH && m_midiActiveChannels[CONVENTION_LEFT_HAND_CHANNEL] == true && - m_midiFirstPatchChannels[CONVENTION_RIGHT_HAND_CHANNEL] <= GM_PIANO_PATCH)) + m_midiFirstPatchChannels[CONVENTION_RIGHT_HAND_CHANNEL] <= GM_PIANO_PATCH) return true; if (m_midiFirstPatchChannels[CONVENTION_RIGHT_HAND_CHANNEL] == GM_PIANO_PATCH && m_midiActiveChannels[CONVENTION_RIGHT_HAND_CHANNEL] == true && - m_midiFirstPatchChannels[CONVENTION_LEFT_HAND_CHANNEL] <= GM_PIANO_PATCH) + m_midiFirstPatchChannels[CONVENTION_LEFT_HAND_CHANNEL] <= GM_PIANO_PATCH) return true; - if (m_midiFirstPatchChannels[CONVENTION_LEFT_HAND_CHANNEL] == GM_PIANO_PATCH && - m_midiActiveChannels[CONVENTION_LEFT_HAND_CHANNEL] == true && - m_midiFirstPatchChannels[CONVENTION_RIGHT_HAND_CHANNEL] <= GM_PIANO_PATCH) - return true; + return false; +} + +bool CTrackList::findLeftAndRightPianoParts() +{ + int patchA = -1; + int chanA = -1; + + for (int chan = 0 ; chan < MAX_MIDI_CHANNELS; chan++) { + if (m_midiActiveChannels[chan]) { + int patch = m_midiFirstPatchChannels[chan]; + if (isPianoOrOrganPatch(patch)) { + if (patchA == -1) { + patchA = patch; + chanA = chan; + } else { + if (patchA == patch) { + if (averageNotePitch(chan) < averageNotePitch(chanA)) { + CNote::setChannelHands(chan, chanA); + } else { + CNote::setChannelHands(chanA, chan); + } + return true; + } + } + } + } + } return false; } @@ -211,6 +235,9 @@ void CTrackList::refresh() m_song->setActiveChannel(CNote::bothHandsChan()); ppLogInfo("Active both"); } + else if (findLeftAndRightPianoParts()) { + m_song->setActiveChannel(CNote::bothHandsChan()); + } else { if (m_trackQtList.count() > 0) diff --git a/src/TrackList.h b/src/TrackList.h index 36bdcd2..2431e5a 100644 --- a/src/TrackList.h +++ b/src/TrackList.h @@ -71,6 +71,7 @@ public: void currentRowChanged(int currentRow); void examineMidiEvent(CMidiEvent event); bool pianoPartConvetionTest(); + bool findLeftAndRightPianoParts(); int guessKeySignature(int chanA, int chanB); // The programme name now starts at 1 with 0 = "(none)" @@ -86,6 +87,18 @@ public: void changeListWidgetItemView(unsigned int index, QListWidgetItem* listWidgetItem); + double averageNotePitch(int chan) { + int totalNoteCount = 0; + double sumOffAllPitches = 0.0; + + for (int note = 0; note < MAX_MIDI_NOTES; note++) { + int frequency = m_noteFrequency[chan][note]; + totalNoteCount += frequency; + sumOffAllPitches += frequency * note; + } + return sumOffAllPitches / totalNoteCount; + } + private: QString getChannelProgramName(int chan); @@ -95,6 +108,7 @@ private: bool m_midiActiveChannels[MAX_MIDI_CHANNELS]; int m_midiFirstPatchChannels[MAX_MIDI_CHANNELS]; int m_noteFrequency[MAX_MIDI_CHANNELS][MAX_MIDI_NOTES]; + float m_averagePitch[MAX_MIDI_CHANNELS]; }; #endif //__TRACK_LIST_H__