pianobooster/src/Chord.cpp

206 lines
5.6 KiB
C++

/*********************************************************************************/
/*!
@file Chord.cpp
@brief Reads ahead from the songdata and collects chords to be matched.
@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/>.
*/
/*********************************************************************************/
#include "Chord.h"
#include "Cfg.h"
int CNote::m_leftHandChannel = -2;
int CNote::m_rightHandChannel = -2;
int CNote::m_rightHandTrack[MAX_MIDI_CHANNELS];
whichPart_t CNote::m_activeHand = PB_PART_both;
int CChord::m_cfg_highestPianoNote = 127; // The highest note on the users piano keyboard;
int CChord::m_cfg_lowestPianoNote = 0;
void CNote::reset()
{
CNote::setChannelHands(-2, -2); // -2 for not set -1 for none
for (int chan = 0; chan < MAX_MIDI_CHANNELS; chan++) {
m_rightHandTrack[chan]=-1;
}
}
void CNote::setChannelHands(int left, int right)
{
m_leftHandChannel = left;
m_rightHandChannel = right;
}
whichPart_t CNote::findHand(CMidiEvent midi, int whichChannel, whichPart_t whichPart)
{
int midiNote = midi.note();
int midiChannel = midi.channel();
whichPart_t hand = PB_PART_none;
// exit if it is not for this channel
if (midiChannel != whichChannel)
{
// return none if this is not being used with the other hand.
if (CNote::hasPianoPart(whichChannel) == false || CNote::hasPianoPart(midiChannel) == false)
return PB_PART_none;
}
int rightHandTrack = CNote::rightHandTrack(midiChannel);
if (midiChannel == whichChannel && rightHandTrack >= 0 ) {
hand = (midi.track() == rightHandTrack) ? PB_PART_right : PB_PART_left ;
} else if (midiChannel == CNote::rightHandChan()) {
hand = PB_PART_right;
} else if (midiChannel == CNote::leftHandChan()) {
hand = PB_PART_left;
} else if (midiChannel == whichChannel) {
hand = (midiNote >= MIDDLE_C) ? PB_PART_right : PB_PART_left ;
}
if (whichPart == PB_PART_left && hand == PB_PART_right)
hand = PB_PART_none;
if (whichPart == PB_PART_right && hand == PB_PART_left)
hand = PB_PART_none;
return hand;
}
void CChord::addNote(whichPart_t part, int note, int duration)
{
if (m_length >= MAX_CHORD_NOTES)
{
ppDEBUG(("Over the chord note limit"));
return;
}
if (searchChord(note)) // don't add duplicates
return;
m_notes[m_length] = CNote(part, note, duration);
m_length++;
}
//////////////// CChord /////////////////////
bool CChord::removeNote(int note)
{
int i;
bool noteFound = false;
for (i = 0; i < MAX_CHORD_NOTES; i++)
{
if (i >= m_length)
break;
if (noteFound == false)
{
if (getNote(i).pitch() == note)
noteFound = true;
}
else
{
// shove everything else up to remove the note
m_notes[i-1] = getNote(i);
}
}
if (noteFound)
m_length--;
return noteFound;
}
bool CChord::searchChord(int note, int transpose)
{
int i;
for (i = 0; i < m_length; i++)
{
if (getNote(i).pitch() + transpose == note)
return true;
}
return false;
}
int CChord::trimOutOfRangeNotes(int transpose)
{
int i;
int removedNotes = 0;
for (i = 0; i < MAX_CHORD_NOTES; i++)
{
if (i >= m_length)
break;
if (!isNotePlayable(getNote(i).pitch(), transpose) || !isHandPlayable(getNote(i).part()))
removedNotes++; // remove the note
else if (removedNotes)
{
// shove everything else up to remove the note
m_notes[i-removedNotes] = getNote(i);
}
}
m_length -= removedNotes;
return m_length;
}
bool CFindChord::findChord(CMidiEvent midi, int channel, whichPart_t part)
{
bool foundChord = false;
if (midi.type() == MIDI_PB_EOF)
{
if (m_currentChord.length() > 0)
{
m_completeChord = m_currentChord;
foundChord = true;
}
return foundChord;
}
m_noteGapTime += midi.deltaTime();
if ((m_noteGapTime >= m_cfg_ChordNoteGap || m_cordSpanGapTime > m_cfg_ChordMaxLength)
&& m_currentChord.length() > 0 )
{
foundChord = true;
m_completeChord = m_currentChord;
m_currentChord.clear();
}
if (midi.type() == MIDI_NOTE_ON)
{
whichPart_t hand = CNote::findHand( midi, channel, part );
if ( hand != PB_PART_none)
{
m_currentChord.addNote(hand, midi.note());
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;
}