233 lines
7.0 KiB
C++
233 lines
7.0 KiB
C++
#include <guitar/ChordMapper.hpp>
|
|
|
|
bool ChordMapper::map(const Music::Chord &chord,Block<FrettedNote> &frettedNotes)
|
|
{
|
|
FrettedNote frettedNote;
|
|
bool returnCode=true;
|
|
bool isBarChord=false;
|
|
|
|
frettedNotes.remove();
|
|
if(getAt(chord.getRoot(),frettedNote,frettedNotes)) // try to set the root on the top string
|
|
{
|
|
frettedNotes.insert(&frettedNote);
|
|
isBarChord=true;
|
|
}
|
|
for(int index=chord.size()-1;index>=0;index--)
|
|
{
|
|
Note ¬e=((Music::Chord&)chord)[index];
|
|
if(getAt(note,frettedNote,frettedNotes))frettedNotes.insert(&frettedNote);
|
|
else
|
|
{
|
|
String message("[Fretboard::getAt] Unable to map note '"+note.toString()+String("'"));
|
|
returnCode=false;
|
|
}
|
|
}
|
|
if(!returnCode)
|
|
{
|
|
isBarChord=false;
|
|
returnCode=true;
|
|
frettedNotes.remove();
|
|
int noteCount=0;
|
|
int chordIndex=2;
|
|
int direction=-1;
|
|
|
|
|
|
|
|
/*
|
|
while(noteCount<chord.size())
|
|
{
|
|
if(chordIndex<0)chordIndex=chord.size()-1;
|
|
else if(chordIndex>=chord.size())chordIndex=0;
|
|
Note ¬e=((Music::Chord&)chord)[chordIndex];
|
|
if(getAt(Fretboard::Strings-1,-1,note,frettedNote,frettedNotes))frettedNotes.insert(&frettedNote);
|
|
else returnCode=false;
|
|
chordIndex+=direction;
|
|
noteCount++;
|
|
}
|
|
*/
|
|
}
|
|
if(isBarChord && frettedNotes.size()) // check to see if we can fill in some notes at the bar chord fret
|
|
{
|
|
getFillerNotes(frettedNotes[0].getFret(),chord,frettedNotes);
|
|
}
|
|
return returnCode;
|
|
}
|
|
|
|
|
|
/*
|
|
* searches for a note mapping starting at given string at fret 0 (note string 0 is the top (6th)string
|
|
* takes care of string collisions.
|
|
* @param note - The note to find a mapping for.
|
|
* @param fretted note - If result is true contains note mapping.
|
|
* @param containedNotes - Notes that are already in the mapping, used
|
|
to limit selected notes and to minimize distance between notes.
|
|
*/
|
|
|
|
bool ChordMapper::getAt(int startingString,int direction,const Note ¬e,FrettedNote &frettedNote,Block<FrettedNote> &containedNotes)
|
|
{
|
|
for(int stringCount=0,srIndex=startingString;stringCount<Fretboard::Strings;stringCount++,srIndex+=direction)
|
|
{
|
|
if(srIndex>=Fretboard::Strings)srIndex=0;
|
|
else if(srIndex<0)srIndex=Fretboard::Strings-1;
|
|
for(int frIndex=0;frIndex<mFretboard.getFrets()+1;frIndex++)
|
|
{
|
|
Note &srchNote=mFretboard[srIndex][frIndex];
|
|
if(srchNote.getNote()==note.getNote())
|
|
{
|
|
frettedNote.setNote(note);
|
|
frettedNote.setString(srIndex);
|
|
frettedNote.setFret(frIndex);
|
|
if(contains(frettedNote,containedNotes))continue;
|
|
if(distance(frettedNote,containedNotes)>MaxFretDistance)continue;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
Get the FrettedNote for the given Note.
|
|
@param note - The note we are looking to map.
|
|
@param frettedNote - The fretted note we are looking for (get's filled in on success)
|
|
@param containedNotes - List of frettednotes we already have (so don't choose any of these).
|
|
|
|
*/
|
|
bool ChordMapper::getAt(const Note ¬e,FrettedNote &frettedNote,Block<FrettedNote> &containedNotes)
|
|
{
|
|
for(int srIndex=0;srIndex<mFretboard.size();srIndex++)
|
|
{
|
|
if(srIndex>=Fretboard::Strings)srIndex=0;
|
|
for(int frIndex=0;frIndex<mFretboard.getFrets()+1;frIndex++)
|
|
{
|
|
Note &srchNote=mFretboard[srIndex][frIndex];
|
|
if(srchNote.getNote()==note.getNote())
|
|
{
|
|
frettedNote.setNote(note);
|
|
frettedNote.setString(srIndex);
|
|
frettedNote.setFret(frIndex);
|
|
if(contains(frettedNote,containedNotes))continue;
|
|
if(distance(frettedNote,containedNotes)>MaxFretDistance)continue;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
Returns the greatest distance between fretted note and grouping of notes
|
|
Distance is simply fret distance, does not account for string distance
|
|
@param frettedNote - The fretted note to get distance.
|
|
@param frettedNotes - The collection of notes with which to compare distances
|
|
*/
|
|
int ChordMapper::distance(const FrettedNote &frettedNote,Block<FrettedNote> &frettedNotes)
|
|
{
|
|
int maxDistance=0;
|
|
int currDistance;
|
|
|
|
for(int index=0;index<frettedNotes.size();index++)
|
|
{
|
|
FrettedNote &currNote=frettedNotes[index];
|
|
currDistance=frettedNote.getFret()-currNote.getFret();
|
|
if(currDistance<0)currDistance=-currDistance;
|
|
if(currDistance>maxDistance)maxDistance=currDistance;
|
|
}
|
|
OutputDebugString(String(String("Distance is :")+String().fromInt(maxDistance)+String("\n")).str());
|
|
return maxDistance;
|
|
}
|
|
|
|
/*
|
|
Return the distance between two fretted notes.
|
|
*/
|
|
int ChordMapper::distance(const FrettedNote &firstNote,const FrettedNote &secondNote)
|
|
{
|
|
int fretDistance=firstNote.getFret()-secondNote.getFret();
|
|
return fretDistance<0?-fretDistance:fretDistance;
|
|
}
|
|
|
|
/*
|
|
Find filler notes for given chord on given fret on empty string.
|
|
*/
|
|
bool ChordMapper::getFillerNotes(int fret,const Music::Chord &chord,Block<FrettedNote> &frettedNotes)
|
|
{
|
|
bool notesInChord;
|
|
for(int stringIndex=0;stringIndex<mFretboard.size();stringIndex++)
|
|
{
|
|
Note ¬e=mFretboard[stringIndex][fret];
|
|
FrettedNote frettedNote;
|
|
frettedNote.setNote(note);
|
|
frettedNote.setString(stringIndex);
|
|
frettedNote.setFret(fret);
|
|
if(!contains(frettedNote,frettedNotes)&&isIn(frettedNote,chord))frettedNotes.insert(&frettedNote);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
/* Check to see if the fretted note exists in the collection of fretted notes.
|
|
* @param frettedNote - The fretted note to check for
|
|
* @param frettedNotes - The collection of fretted notes
|
|
*/
|
|
bool ChordMapper::contains(const FrettedNote &frettedNote,Block<FrettedNote> &frettedNotes)
|
|
{
|
|
for(int index=0;index<frettedNotes.size();index++)
|
|
{
|
|
FrettedNote &currNote=frettedNotes[index];
|
|
if(currNote.getString()==frettedNote.getString())return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
Check to see if the given note is part of the chord
|
|
@param frettedNote - The note
|
|
@param chord - The chord
|
|
@return - True if the given note is part of the chord, false otherwise
|
|
*/
|
|
bool ChordMapper::isIn(const FrettedNote &frettedNote,const Music::Chord &chord)
|
|
{
|
|
for(int index=0;index<chord.size();index++)
|
|
if(frettedNote.getNote()==((Music::Chord&)chord)[index])return true;
|
|
return false;
|
|
}
|
|
|
|
void ChordMapper::getNearestNote(const FrettedNote &frettedNote,const Note &srchNote,FrettedNote &foundNote)
|
|
{
|
|
bool found=false;
|
|
int stringOffset=1;
|
|
int fretOffset=1;
|
|
|
|
while(!found)
|
|
{
|
|
if(getNearestNoteInRange(frettedNote,srchNote,foundNote,stringOffset,fretOffset))found=true;
|
|
stringOffset++;
|
|
fretOffset++;
|
|
}
|
|
}
|
|
|
|
bool ChordMapper::getNearestNoteInRange(const FrettedNote &frettedNote,const Note &srchNote,FrettedNote &foundNote,int stringOffset,int fretOffset)
|
|
{
|
|
for(int currentString=frettedNote.getString()-1;currentString<frettedNote.getString()+1;currentString++)
|
|
{
|
|
for(int currentFret=frettedNote.getFret()-1;currentFret<frettedNote.getFret()+1;currentFret++)
|
|
{
|
|
if(currentString>=Fretboard::Strings || currentString<0)continue;
|
|
if(currentFret>=Fretboard::Frets || currentFret<0)continue;
|
|
Note ¬e=mFretboard[currentString][currentFret];
|
|
if(note==srchNote)
|
|
{
|
|
FrettedNote frettedNote;
|
|
frettedNote.setNote(note);
|
|
frettedNote.setString(currentString);
|
|
frettedNote.setFret(currentFret);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
|