241 lines
6.5 KiB
C++
241 lines
6.5 KiB
C++
#include <guitar/Fretboard.hpp>
|
|
#include <guitar/GlobalDefs.hpp>
|
|
#include <common/block.hpp>
|
|
|
|
bool Fretboard::isOnFretboard(const Note ¬e)
|
|
{
|
|
for(int frIndex=0;frIndex<mFrets+1;frIndex++)
|
|
{
|
|
for(int srIndex=0;srIndex<size();srIndex++)
|
|
{
|
|
Note &srchNote=operator[](srIndex)[frIndex];
|
|
if(srchNote.getNote()==note.getNote()&&srchNote.getOctave()==note.getOctave())return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
searches for a note mapping starting at top (sixth string), fret 0,
|
|
*/
|
|
|
|
bool Fretboard::getAt(const Note ¬e,FrettedNote &frettedNote)
|
|
{
|
|
for(int srIndex=0;srIndex<size();srIndex++)
|
|
{
|
|
for(int frIndex=0;frIndex<mFrets+1;frIndex++)
|
|
{
|
|
Note &srchNote=operator[](srIndex)[frIndex];
|
|
if(srchNote.getNote()==note.getNote()&&srchNote.getOctave()==note.getOctave())
|
|
{
|
|
frettedNote.setNote(note);
|
|
frettedNote.setString(srIndex);
|
|
frettedNote.setFret(frIndex);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
searches for a note mapping starting at top (sixth string), fret 0,
|
|
*/
|
|
bool Fretboard::getAt(const Note ¬e,Block<FrettedNote> &frettedNotes)
|
|
{
|
|
frettedNotes.remove();
|
|
|
|
for(int srIndex=0;srIndex<size();srIndex++)
|
|
{
|
|
for(int frIndex=0;frIndex<mFrets+1;frIndex++)
|
|
{
|
|
Note &srchNote=operator[](srIndex)[frIndex];
|
|
if(srchNote.getNote()==note.getNote()&&srchNote.getOctave()==note.getOctave())
|
|
{
|
|
FrettedNote frettedNote;
|
|
frettedNote.setNote(note);
|
|
frettedNote.setString(srIndex);
|
|
frettedNote.setFret(frIndex);
|
|
frettedNotes.insert(&frettedNote);
|
|
}
|
|
}
|
|
}
|
|
return frettedNotes.size()?true:false;
|
|
}
|
|
|
|
/*
|
|
Get the fretted notes for the given chord. The root may be repeated.
|
|
Returns true if it mapped all of the notes of the chord, false if some
|
|
or all notes were unable to be mapped. Partial success would return
|
|
false but the frettedNotes array may contain some notes.
|
|
@param [In] Chord the chord to get fretting for.
|
|
@param [Out] Fretted notes corresponding to the chord
|
|
*/
|
|
|
|
bool Fretboard::getAt(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("'"));
|
|
GlobalDefs::outDebug(message);
|
|
returnCode=false;
|
|
}
|
|
}
|
|
|
|
// need to come up with a strategy here for mapping notes on the fretboard
|
|
|
|
if(isBarChord) // check to see if we can fill in some notes at the bar chord fret
|
|
{
|
|
getFillerNotes(frettedNotes[0].getFret(),chord,frettedNotes);
|
|
}
|
|
return returnCode;
|
|
}
|
|
|
|
/*
|
|
Find filler notes for given chord on given fret on empty string.
|
|
*/
|
|
bool Fretboard::getFillerNotes(int fret,const Music::Chord &chord,Block<FrettedNote> &frettedNotes)
|
|
{
|
|
bool notesInChord;
|
|
for(int stringIndex=0;stringIndex<size();stringIndex++)
|
|
{
|
|
Note ¬e=operator[](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;
|
|
}
|
|
|
|
bool Fretboard::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;
|
|
}
|
|
|
|
/*
|
|
* searches for a note mapping starting at top (sixth string), fret 0,
|
|
* 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 Fretboard::getAt(const Note ¬e,FrettedNote &frettedNote,Block<FrettedNote> &containedNotes)
|
|
{
|
|
for(int srIndex=0;srIndex<size();srIndex++)
|
|
{
|
|
for(int frIndex=0;frIndex<mFrets+1;frIndex++)
|
|
{
|
|
Note &srchNote=operator[](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)>4)continue;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/* 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 Fretboard::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;
|
|
}
|
|
|
|
/*
|
|
Returns the greatest distance between fretted note and grouping of notes
|
|
@param frettedNote - The fretted note to get distance.
|
|
@param frettedNotes - The collection of notes with which to compare distances
|
|
*/
|
|
int Fretboard::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;
|
|
}
|
|
return maxDistance;
|
|
}
|
|
|
|
void Fretboard::createFretboard(const Tuning &tuning,int frets)
|
|
{
|
|
mTuning=tuning;
|
|
mFrets=frets;
|
|
createFretboard();
|
|
}
|
|
|
|
bool Fretboard::play(MIDIOutputDevice &device)
|
|
{
|
|
for(int string=0;string<size();string++)
|
|
{
|
|
Notes &stringNotes=operator[](string);
|
|
stringNotes.play(device);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void Fretboard::createFretboard(void)
|
|
{
|
|
size(mTuning.getStrings());
|
|
for(int string=0;string<size();string++)
|
|
{
|
|
Notes &stringNotes=operator[](string);
|
|
stringNotes.size(mFrets+1);
|
|
Note fretNote=mTuning[string];
|
|
for(int fret=0;fret<mFrets+1;fret++)
|
|
{
|
|
stringNotes[fret]=fretNote;
|
|
fretNote++;
|
|
}
|
|
}
|
|
}
|
|
|
|
String Fretboard::toString(void)const
|
|
{
|
|
String strFretboard;
|
|
for(int string=0;string<size();string++)
|
|
{
|
|
Notes &stringNotes=((Array<Notes>&)*this).operator[](string);
|
|
strFretboard+=stringNotes.toString();
|
|
if(string<size()-1)strFretboard+=String("\n");
|
|
}
|
|
return strFretboard;
|
|
}
|
|
|