Does a better job at detecting the left and right hand piano parts.

This commit is contained in:
louis-barman 2020-05-14 14:51:45 +01:00
parent 8bc1f43f73
commit b397bbaa52
5 changed files with 81 additions and 10 deletions

View File

@ -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);

View File

@ -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 );

View File

@ -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;

View File

@ -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)

View File

@ -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__