Skip to content

Commit

Permalink
Merge pull request #7542 from laturetab/316896-banjofrettedfifthstring
Browse files Browse the repository at this point in the history
Fix #316896: Banjo fifth string fret numbers
  • Loading branch information
RomanPudashkin committed Feb 20, 2021
2 parents cc3c72a + 25f55ae commit e96274c
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 14 deletions.
2 changes: 1 addition & 1 deletion src/libmscore/instrument.h
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ class Instrument
void setMidiActions(const QList<NamedEventList>& l) { _midiActions = l; }
void setArticulation(const QList<MidiArticulation>& l) { _articulation = l; }
const StringData* stringData() const { return &_stringData; }
void setStringData(const StringData& d) { _stringData = d; }
void setStringData(const StringData& d) { _stringData.set(d); }

void setLongName(const QString& f);
void setShortName(const QString& f);
Expand Down
111 changes: 98 additions & 13 deletions src/libmscore/stringdata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ bool StringData::bFretting = false;

StringData::StringData(int numFrets, int numStrings, int strings[])
{
instrString strg = { 0, false };
instrString strg = { 0, false, 0 };
_frets = numFrets;

for (int i = 0; i < numStrings; i++) {
Expand All @@ -47,6 +47,15 @@ StringData::StringData(int numFrets, QList<instrString>& strings)
}
}

// called from import (musicxml/guitarpro/...)
void StringData::set(const StringData& src)
{
*this = src;
if (isFiveStringBanjo()) {
configBanjo5thString();
}
}

//---------------------------------------------------------
// read
//---------------------------------------------------------
Expand All @@ -67,6 +76,9 @@ void StringData::read(XmlReader& e)
e.unknown();
}
}
if (isFiveStringBanjo()) {
configBanjo5thString();
}
}

//---------------------------------------------------------
Expand Down Expand Up @@ -330,17 +342,35 @@ bool StringData::convertPitch(int pitch, int pitchOffset, int* string, int* fret
return false;
}

// look for a suitable string, starting from the highest
// NOTE: this assumes there are always enough frets to fill
// the interval between any fretted string and the next
for (int i = strings - 1; i >= 0; i--) {
instrString strg = stringTable.at(i);
if (pitch >= strg.pitch) {
if (pitch == strg.pitch || !strg.open) {
if (isFiveStringBanjo()) {
// special case: open banjo 5th string
if (pitch == stringTable.at(0).pitch) {
*string = 4;
*fret = 0;
return true;
}
// test remaining 4 strings from highest to lowest
for (int i = 4; i > 0; i--) {
instrString strg = stringTable.at(i);
if (pitch >= strg.pitch) {
*string = strings - i - 1;
*fret = pitch - strg.pitch;
return true;
}
}
} else {
// look for a suitable string, starting from the highest
// NOTE: this assumes there are always enough frets to fill
// the interval between any fretted string and the next
for (int i = strings - 1; i >= 0; i--) {
instrString strg = stringTable.at(i);
if (pitch >= strg.pitch) {
if (pitch == strg.pitch || !strg.open) {
*string = strings - i - 1;
}
*fret = pitch - strg.pitch;
return true;
}
*fret = pitch - strg.pitch;
return true;
}
}

Expand All @@ -365,7 +395,11 @@ int StringData::getPitch(int string, int fret, int pitchOffset) const
return INVALID_PITCH;
}
instrString strg = stringTable.at(strings - string - 1);
return strg.pitch - pitchOffset + (strg.open ? 0 : fret);
int pitch = strg.pitch - pitchOffset + (strg.open ? 0 : fret);
if (strg.startFret > 0 && fret >= strg.startFret) {
pitch -= strg.startFret; // banjo 5th string adjustment
}
return pitch;
}

//---------------------------------------------------------
Expand All @@ -387,9 +421,14 @@ int StringData::fret(int pitch, int string, int pitchOffset) const

pitch += pitchOffset;

int fret = pitch - stringTable[strings - string - 1].pitch;
const instrString& strg = stringTable[strings - string - 1];
int fret = pitch - strg.pitch;
if (fret > 0 && strg.startFret > 0) {
fret += strg.startFret; // banjo 5th string adjustment
}

// fret number is invalid or string cannot be fretted
if (fret < 0 || fret >= _frets || (fret > 0 && stringTable[strings - string - 1].open)) {
if (fret < 0 || fret >= _frets || (fret > 0 && strg.open)) {
return FRET_NONE;
}
return fret;
Expand Down Expand Up @@ -428,6 +467,52 @@ void StringData::sortChordNotes(QMap<int, Note*>& sortedNotes, const Chord* chor
}
}

//---------------------------------------------------------
// configBanjo5thString
// Assumes isFiveStringBanjo() has already been called.
// This method looks at the banjo tuning and sets startFret
// appropriately.
//---------------------------------------------------------

void StringData::configBanjo5thString()
{
// banjo 5th string (pitch 67 == G)
instrString& strg5 = stringTable[0];

_frets = 24; // not needed after bug #316931 is fixed

// adjust startFret if using a 5th string capo (6..12)
if (strg5.pitch > 67 && strg5.pitch < 74) {
strg5.startFret = strg5.pitch - 62;
} else {
strg5.startFret = 5; // no 5th string capo
}
}

//---------------------------------------------------------
// adjustBanjo5thFret
// Convert 5th string fret number from (0, 1, 2, 3...) to (0, 6, 7, 8...).
// Called from import (GuitarPro mostly)
// Returns adjusted fret number
//---------------------------------------------------------

int StringData::adjustBanjo5thFret(int fret) const
{
return (fret > 0 && isFiveStringBanjo()) ? fret + stringTable[0].startFret : fret;
}

//---------------------------------------------------------
// isFiveStringBanjo
// Based only on number of strings and tuning - other info
// may not be available when this is called. Checks 5th string
// pitch is higher than 4th (i.e. not a 5 string bass)
//---------------------------------------------------------

bool StringData::isFiveStringBanjo() const
{
return stringTable.size() == 5 && stringTable[0].pitch > stringTable[1].pitch;
}

#if 0
//---------------------------------------------------------
// MusicXMLStepAltOct2Pitch
Expand Down
7 changes: 7 additions & 0 deletions src/libmscore/stringdata.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@ class Note;

// defines the string of an instrument
struct instrString {
instrString(int p = 0, bool o = false, int s = 0)
: pitch(p), open(o), startFret(s) {}
int pitch; // the pitch of the string
bool open; // true: string is open | false: string is fretted
int startFret; // banjo 5th string starts on 5th fret

bool operator==(const instrString& d) const { return d.pitch == pitch && d.open == open; }
};
Expand All @@ -49,6 +52,7 @@ class StringData
StringData() {}
StringData(int numFrets, int numStrings, int strings[]);
StringData(int numFrets, QList<instrString>& strings);
void set(const StringData& src);
bool convertPitch(int pitch, Staff* staff, const Fraction& tick, int* string, int* fret) const;
int fret(int pitch, int string, Staff* staff, const Fraction& tick) const;
void fretChords(Chord* chord) const;
Expand All @@ -64,6 +68,9 @@ class StringData
void write(XmlWriter&) const;
void writeMusicXML(XmlWriter& xml) const;
bool operator==(const StringData& d) const { return d._frets == _frets && d.stringTable == stringTable; }
void configBanjo5thString();
int adjustBanjo5thFret(int fret) const;
bool isFiveStringBanjo() const;
};
} // namespace Ms
#endif

0 comments on commit e96274c

Please sign in to comment.