From 889e18e7ad16bfa4d8395755894d2f859f348d62 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Sun, 27 Nov 2022 00:25:34 +0100 Subject: [PATCH 001/109] Add basic implementation for figuredbass filter --- CMakeLists.txt | 2 + Makefile | 12 ++++- cli/figuredbass.cpp | 3 ++ include/tool-figuredbass.h | 36 +++++++++++++ src/tool-figuredbass.cpp | 107 +++++++++++++++++++++++++++++++++++++ src/tool-filter.cpp | 3 ++ 6 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 cli/figuredbass.cpp create mode 100644 include/tool-figuredbass.h create mode 100644 src/tool-figuredbass.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 0e5409eb..099f1433 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -89,6 +89,7 @@ set(SRCS src/tool-dissonant.cpp src/tool-esac2hum.cpp src/tool-extract.cpp + src/tool-figuredbass.cpp src/tool-filter.cpp src/tool-hproof.cpp src/tool-imitation.cpp @@ -148,6 +149,7 @@ set(HDRS include/tool-dissonant.h include/tool-esac2hum.h include/tool-extract.h + include/tool-figuredbass.h include/tool-hproof.h include/tool-imitation.h include/tool-mei2hum.h diff --git a/Makefile b/Makefile index 08eed9b3..ed4301b2 100644 --- a/Makefile +++ b/Makefile @@ -621,6 +621,16 @@ tool-extract.o: tool-extract.cpp tool-extract.h \ HumHash.h HumParamSet.h HumdrumFileStream.h \ HumRegex.h +tool-figuredbass.o: tool-figuredbass.cpp tool-figuredbass.h \ + HumTool.h Options.h HumdrumFileSet.h \ + HumdrumFile.h HumdrumFileContent.h \ + HumdrumFileStructure.h HumdrumFileBase.h \ + HumSignifiers.h HumSignifier.h HumdrumLine.h \ + HumdrumToken.h HumNum.h HumAddress.h \ + HumHash.h HumParamSet.h HumdrumFileStream.h \ + NoteGrid.h NoteCell.h Convert.h \ + HumRegex.h + tool-filter.o: tool-filter.cpp tool-filter.h \ HumTool.h Options.h HumdrumFileSet.h \ HumdrumFile.h HumdrumFileContent.h \ @@ -632,7 +642,7 @@ tool-filter.o: tool-filter.cpp tool-filter.h \ tool-chooser.h tool-chord.h tool-cint.h \ NoteGrid.h NoteCell.h HumRegex.h \ tool-composite.h tool-dissonant.h \ - tool-extract.h tool-homorhythm.h \ + tool-extract.h tool-figuredbass.h tool-homorhythm.h \ tool-homorhythm2.h tool-hproof.h \ tool-humdiff.h tool-shed.h tool-imitation.h \ tool-kern2mens.h tool-melisma.h tool-metlev.h \ diff --git a/cli/figuredbass.cpp b/cli/figuredbass.cpp new file mode 100644 index 00000000..b8c864ca --- /dev/null +++ b/cli/figuredbass.cpp @@ -0,0 +1,3 @@ +#include "humlib.h" + +STREAM_INTERFACE(Tool_figuredbass) diff --git a/include/tool-figuredbass.h b/include/tool-figuredbass.h new file mode 100644 index 00000000..e8a384a0 --- /dev/null +++ b/include/tool-figuredbass.h @@ -0,0 +1,36 @@ +#ifndef _TOOL_FIGUREDBASS_H +#define _TOOL_FIGUREDBASS_H + +#include "HumTool.h" +#include "HumdrumFile.h" +#include "NoteGrid.h" + +namespace hum { + +// START_MERGE + +class Tool_figuredbass : public HumTool { + + public: + Tool_figuredbass(void); + ~Tool_figuredbass(){}; + + bool run (HumdrumFileSet& infiles); + bool run (HumdrumFile& infile); + bool run (const string& indata, ostream& out); + bool run (HumdrumFile& infile, ostream& out); + + // protected: + + private: + bool nonCompoundIntervalsQ = false; + bool noAccidentalsQ = false; + int baseQ = 0; + +}; + +// END_MERGE + +} // end namespace hum + +#endif /* _TOOL_FIGUREDBASS_H */ diff --git a/src/tool-figuredbass.cpp b/src/tool-figuredbass.cpp new file mode 100644 index 00000000..b6e700c1 --- /dev/null +++ b/src/tool-figuredbass.cpp @@ -0,0 +1,107 @@ +#include "tool-figuredbass.h" +#include "Convert.h" +#include "HumRegex.h" + +using namespace std; + +namespace hum { + +// START_MERGE + +Tool_figuredbass::Tool_figuredbass(void) { + define("C|non-compound=b", "output compound intervals as non-compound intervals"); + define("A|no-accidentals=b", "ignore accidentals in figured bass output"); + define("b|base=i:0", "number of the base voice/spine"); +} + +bool Tool_figuredbass::run(HumdrumFileSet &infiles) { + bool status = true; + for (int i = 0; i < infiles.getCount(); i++) { + status &= run(infiles[i]); + } + return status; +} + +bool Tool_figuredbass::run(const string &indata, ostream &out) { + HumdrumFile infile(indata); + bool status = run(infile); + if (hasAnyText()) { + getAllText(out); + } else { + out << infile; + } + return status; +} + +bool Tool_figuredbass::run(HumdrumFile &infile, ostream &out) { + bool status = run(infile); + if (hasAnyText()) { + getAllText(out); + } else { + out << infile; + } + return status; +} + +bool Tool_figuredbass::run(HumdrumFile &infile) { + + nonCompoundIntervalsQ = getBoolean("non-compound"); + noAccidentalsQ = getBoolean("no-accidentals"); + baseQ = getInteger("base"); + + NoteGrid grid(infile); + + vector data; + data.resize(infile.getLineCount()); + + vector kernspines = infile.getKernSpineStartList(); + + int baseVoiceIndex = baseQ; + + for (int i=0; i<(int)grid.getSliceCount(); i++) { + NoteCell* baseCell = grid.cell(baseVoiceIndex, i); + for (int j=0; j<(int)grid.getVoiceCount(); j++) { + if(j == baseVoiceIndex) { + continue; + } + NoteCell* targetCell = grid.cell(j, i); + int basePitch = baseCell->getSgnDiatonicPitch(); + int targetPitch = targetCell->getSgnDiatonicPitch(); + int num = (basePitch == 0 || targetPitch == 0) ? 0 : abs(abs(targetPitch) - abs(basePitch)) + 1; + if(num > 9 && !nonCompoundIntervalsQ) { + num = num % 7; + } + if(num > 0) { + string accid = ""; + if (!noAccidentalsQ) { + // TODO improve for souble sharps and double flats + if(targetCell->getSgnKernPitch().find("-") != string::npos) { + accid = '-'; + } else if(targetCell->getSgnKernPitch().find("#") != string::npos) { + accid = '#'; + } + } + + data[baseCell->getLineIndex()] = accid + to_string(num) + " " + data[baseCell->getLineIndex()]; + } + } + } + + if(baseVoiceIndex < grid.getVoiceCount()) { + int trackIndex = kernspines[baseVoiceIndex + 1]->getTrack(); + infile.insertDataSpineBefore(trackIndex, data, ".", "**fb"); + } else { + int trackIndex = kernspines[baseVoiceIndex]->getTrack(); + // TODO segmentation fault + infile.appendDataSpine(data, ".", "**fb"); + } + + + return true; + +}; + + +// END_MERGE + +} // end namespace hum diff --git a/src/tool-filter.cpp b/src/tool-filter.cpp index 4f6716da..58b5f60d 100644 --- a/src/tool-filter.cpp +++ b/src/tool-filter.cpp @@ -28,6 +28,7 @@ #include "tool-dissonant.h" #include "tool-double.h" #include "tool-extract.h" +#include "tool-figuredbass.h" #include "tool-flipper.h" #include "tool-gasparize.h" #include "tool-half.h" @@ -230,6 +231,8 @@ bool Tool_filter::run(HumdrumFileSet& infiles) { RUNTOOL(dissonant, infile, commands[i].second, status); } else if (commands[i].first == "double") { RUNTOOL(double, infile, commands[i].second, status); + } else if (commands[i].first == "figuredbass") { + RUNTOOL(figuredbass, infile, commands[i].second, status); } else if (commands[i].first == "half") { RUNTOOL(half, infile, commands[i].second, status); } else if (commands[i].first == "homorhythm") { From 91946d25eb01377de6d7b9690422ba110e14eb46 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Sun, 27 Nov 2022 01:11:13 +0100 Subject: [PATCH 002/109] Fix typo --- src/tool-figuredbass.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tool-figuredbass.cpp b/src/tool-figuredbass.cpp index b6e700c1..67b1285d 100644 --- a/src/tool-figuredbass.cpp +++ b/src/tool-figuredbass.cpp @@ -74,7 +74,7 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { if(num > 0) { string accid = ""; if (!noAccidentalsQ) { - // TODO improve for souble sharps and double flats + // TODO improve for double sharps and double flats if(targetCell->getSgnKernPitch().find("-") != string::npos) { accid = '-'; } else if(targetCell->getSgnKernPitch().find("#") != string::npos) { From e1a6c3a7db590696b08f2eda58aca73fdb4d229e Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Sun, 27 Nov 2022 12:23:36 +0100 Subject: [PATCH 003/109] Remove unused var --- src/tool-figuredbass.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tool-figuredbass.cpp b/src/tool-figuredbass.cpp index 67b1285d..83506129 100644 --- a/src/tool-figuredbass.cpp +++ b/src/tool-figuredbass.cpp @@ -91,7 +91,6 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { int trackIndex = kernspines[baseVoiceIndex + 1]->getTrack(); infile.insertDataSpineBefore(trackIndex, data, ".", "**fb"); } else { - int trackIndex = kernspines[baseVoiceIndex]->getTrack(); // TODO segmentation fault infile.appendDataSpine(data, ".", "**fb"); } From a33cd71278d27e808b047b5946688fe15d2445f4 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Sun, 27 Nov 2022 19:44:59 +0100 Subject: [PATCH 004/109] Refactor with classes --- include/tool-figuredbass.h | 29 +++++++++ src/tool-figuredbass.cpp | 117 ++++++++++++++++++++++++++++--------- 2 files changed, 117 insertions(+), 29 deletions(-) diff --git a/include/tool-figuredbass.h b/include/tool-figuredbass.h index e8a384a0..112daa5d 100644 --- a/include/tool-figuredbass.h +++ b/include/tool-figuredbass.h @@ -9,6 +9,31 @@ namespace hum { // START_MERGE +class FiguredBassNumber { + public: + int number; + string accidentals; + FiguredBassNumber(int num, string accid); + string toString(bool nonCompoundIntervalsQ, bool noAccidentalsQ); +}; + +class FiguredBassSlice { + public: + int lineIndex; + vector numbers; + FiguredBassSlice(int index); + void add(FiguredBassNumber* number); + string toString(bool nonCompoundIntervalsQ, bool noAccidentalsQ); +}; + +class FiguredBassTrack { + public: + int voiceIndex; + vector slices; + FiguredBassTrack(int index); + void add(FiguredBassSlice* slice); +}; + class Tool_figuredbass : public HumTool { public: @@ -20,6 +45,10 @@ class Tool_figuredbass : public HumTool { bool run (const string& indata, ostream& out); bool run (HumdrumFile& infile, ostream& out); + vector getTrackData(FiguredBassTrack* track, int lineCount, bool nonCompoundIntervalsQ, bool noAccidentalsQ); + + FiguredBassNumber* createFiguredBassNumber(NoteCell* base, NoteCell* target); + // protected: private: diff --git a/src/tool-figuredbass.cpp b/src/tool-figuredbass.cpp index 83506129..9d041de7 100644 --- a/src/tool-figuredbass.cpp +++ b/src/tool-figuredbass.cpp @@ -51,55 +51,114 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { NoteGrid grid(infile); - vector data; - data.resize(infile.getLineCount()); + vector data; vector kernspines = infile.getKernSpineStartList(); int baseVoiceIndex = baseQ; + FiguredBassTrack* track = new FiguredBassTrack(baseVoiceIndex); + data.push_back(track); for (int i=0; i<(int)grid.getSliceCount(); i++) { - NoteCell* baseCell = grid.cell(baseVoiceIndex, i); + NoteCell* baseCell = grid.cell(track->voiceIndex, i); + FiguredBassSlice* slice = new FiguredBassSlice(baseCell->getLineIndex()); + track->add(slice); for (int j=0; j<(int)grid.getVoiceCount(); j++) { if(j == baseVoiceIndex) { continue; } NoteCell* targetCell = grid.cell(j, i); - int basePitch = baseCell->getSgnDiatonicPitch(); - int targetPitch = targetCell->getSgnDiatonicPitch(); - int num = (basePitch == 0 || targetPitch == 0) ? 0 : abs(abs(targetPitch) - abs(basePitch)) + 1; - if(num > 9 && !nonCompoundIntervalsQ) { - num = num % 7; - } - if(num > 0) { - string accid = ""; - if (!noAccidentalsQ) { - // TODO improve for double sharps and double flats - if(targetCell->getSgnKernPitch().find("-") != string::npos) { - accid = '-'; - } else if(targetCell->getSgnKernPitch().find("#") != string::npos) { - accid = '#'; - } - } - - data[baseCell->getLineIndex()] = accid + to_string(num) + " " + data[baseCell->getLineIndex()]; - } + + + FiguredBassNumber* number = createFiguredBassNumber(baseCell, targetCell); + slice->add(number); } } - if(baseVoiceIndex < grid.getVoiceCount()) { - int trackIndex = kernspines[baseVoiceIndex + 1]->getTrack(); - infile.insertDataSpineBefore(trackIndex, data, ".", "**fb"); - } else { - // TODO segmentation fault - infile.appendDataSpine(data, ".", "**fb"); + for (FiguredBassTrack* track: data) { + if(baseVoiceIndex < grid.getVoiceCount()) { + int trackIndex = kernspines[baseVoiceIndex + 1]->getTrack(); + infile.insertDataSpineBefore(trackIndex, getTrackData(track, infile.getLineCount(), nonCompoundIntervalsQ, noAccidentalsQ), ".", "**fb"); + } else { + // TODO segmentation fault + infile.appendDataSpine(getTrackData(track, infile.getLineCount(), nonCompoundIntervalsQ, noAccidentalsQ), ".", "**fb"); + } } - return true; +}; + +vector Tool_figuredbass::getTrackData(FiguredBassTrack* track, int lineCount, bool nonCompoundIntervalsQ, bool noAccidentalsQ) { + vector trackData; + trackData.resize(lineCount); + + for (FiguredBassSlice* slice: track->slices) { + trackData[slice->lineIndex] = slice->toString(nonCompoundIntervalsQ, noAccidentalsQ); + } + + return trackData; +}; + +FiguredBassNumber* Tool_figuredbass::createFiguredBassNumber(NoteCell* base, NoteCell* target) { + + int basePitch = base->getSgnDiatonicPitch(); + int targetPitch = target->getSgnDiatonicPitch(); + int num = (basePitch == 0 || targetPitch == 0) ? 0 : abs(abs(targetPitch) - abs(basePitch)) + 1; + string accid = ""; + if(target->getSgnKernPitch().find("-") != string::npos) { + accid = '-'; + } else if(target->getSgnKernPitch().find("#") != string::npos) { + accid = '#'; + } + + FiguredBassNumber* number = new FiguredBassNumber(num, accid); + return number; }; +FiguredBassTrack::FiguredBassTrack(int index) { + voiceIndex = index; +}; + +void FiguredBassTrack::add(FiguredBassSlice* slice) { + slices.push_back(slice); +}; + +FiguredBassSlice::FiguredBassSlice(int index) { + lineIndex = index; +}; + +void FiguredBassSlice::add(FiguredBassNumber* number) { + numbers.insert(numbers.begin(), number); + // numbers.push_back(number); +}; + +string FiguredBassSlice::toString(bool nonCompoundIntervalsQ, bool noAccidentalsQ) { + string str = ""; + bool first = true; + for (FiguredBassNumber* number: numbers) { + string num = number->toString(nonCompoundIntervalsQ, noAccidentalsQ); + if(num.length() > 0) { + if (!first) str += " "; + first = false; + str += number->toString(nonCompoundIntervalsQ, noAccidentalsQ); + } + } + return str; +}; + +FiguredBassNumber::FiguredBassNumber(int num, string accid) { + number = num; + accidentals = accid; +}; + +string FiguredBassNumber::toString(bool nonCompoundIntervalsQ, bool noAccidentalsQ) { + int num = (number > 9 && !nonCompoundIntervalsQ) ? number % 7 : number; + string accid = (!noAccidentalsQ) ? accidentals : ""; + return num > 0 ? to_string(num) + accid : ""; +}; + + // END_MERGE From ec80ffeaac57ffdf5a7e9fa901c41fbaa9238474 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Sun, 27 Nov 2022 20:52:49 +0100 Subject: [PATCH 005/109] Remove FiguredBassTrack and FiguredBassSlice --- include/tool-figuredbass.h | 27 +++++---------- src/tool-figuredbass.cpp | 67 ++++++++++++++++++-------------------- 2 files changed, 39 insertions(+), 55 deletions(-) diff --git a/include/tool-figuredbass.h b/include/tool-figuredbass.h index 112daa5d..dd4db494 100644 --- a/include/tool-figuredbass.h +++ b/include/tool-figuredbass.h @@ -11,29 +11,14 @@ namespace hum { class FiguredBassNumber { public: + int voiceIndex; + int lineIndex; int number; string accidentals; - FiguredBassNumber(int num, string accid); - string toString(bool nonCompoundIntervalsQ, bool noAccidentalsQ); -}; - -class FiguredBassSlice { - public: - int lineIndex; - vector numbers; - FiguredBassSlice(int index); - void add(FiguredBassNumber* number); + FiguredBassNumber(int num, string accid, int voiceIndex, int lineIndex); string toString(bool nonCompoundIntervalsQ, bool noAccidentalsQ); }; -class FiguredBassTrack { - public: - int voiceIndex; - vector slices; - FiguredBassTrack(int index); - void add(FiguredBassSlice* slice); -}; - class Tool_figuredbass : public HumTool { public: @@ -45,9 +30,13 @@ class Tool_figuredbass : public HumTool { bool run (const string& indata, ostream& out); bool run (HumdrumFile& infile, ostream& out); - vector getTrackData(FiguredBassTrack* track, int lineCount, bool nonCompoundIntervalsQ, bool noAccidentalsQ); + vector getTrackData(vector numbers, int lineCount, bool nonCompoundIntervalsQ, bool noAccidentalsQ); FiguredBassNumber* createFiguredBassNumber(NoteCell* base, NoteCell* target); + + vector findFiguredBassNumbersForLine(vector, int lineIndex); + + string formatFiguredBassNumbers(vector numbers, bool nonCompoundIntervalsQ, bool noAccidentalsQ); // protected: diff --git a/src/tool-figuredbass.cpp b/src/tool-figuredbass.cpp index 9d041de7..68e34007 100644 --- a/src/tool-figuredbass.cpp +++ b/src/tool-figuredbass.cpp @@ -51,49 +51,44 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { NoteGrid grid(infile); - vector data; + vector data; vector kernspines = infile.getKernSpineStartList(); int baseVoiceIndex = baseQ; - FiguredBassTrack* track = new FiguredBassTrack(baseVoiceIndex); - data.push_back(track); for (int i=0; i<(int)grid.getSliceCount(); i++) { - NoteCell* baseCell = grid.cell(track->voiceIndex, i); - FiguredBassSlice* slice = new FiguredBassSlice(baseCell->getLineIndex()); - track->add(slice); + NoteCell* baseCell = grid.cell(baseVoiceIndex, i); for (int j=0; j<(int)grid.getVoiceCount(); j++) { if(j == baseVoiceIndex) { continue; } NoteCell* targetCell = grid.cell(j, i); - - FiguredBassNumber* number = createFiguredBassNumber(baseCell, targetCell); - slice->add(number); + data.push_back(number); } } - for (FiguredBassTrack* track: data) { - if(baseVoiceIndex < grid.getVoiceCount()) { - int trackIndex = kernspines[baseVoiceIndex + 1]->getTrack(); - infile.insertDataSpineBefore(trackIndex, getTrackData(track, infile.getLineCount(), nonCompoundIntervalsQ, noAccidentalsQ), ".", "**fb"); - } else { - // TODO segmentation fault - infile.appendDataSpine(getTrackData(track, infile.getLineCount(), nonCompoundIntervalsQ, noAccidentalsQ), ".", "**fb"); - } + if(baseVoiceIndex < grid.getVoiceCount()) { + int trackIndex = kernspines[baseVoiceIndex + 1]->getTrack(); + infile.insertDataSpineBefore(trackIndex, getTrackData(data, infile.getLineCount(), nonCompoundIntervalsQ, noAccidentalsQ), ".", "**fb"); + } else { + // TODO segmentation fault + infile.appendDataSpine(getTrackData(data, infile.getLineCount(), nonCompoundIntervalsQ, noAccidentalsQ), ".", "**fb"); } return true; }; -vector Tool_figuredbass::getTrackData(FiguredBassTrack* track, int lineCount, bool nonCompoundIntervalsQ, bool noAccidentalsQ) { +vector Tool_figuredbass::getTrackData(vector numbers, int lineCount, bool nonCompoundIntervalsQ, bool noAccidentalsQ) { vector trackData; trackData.resize(lineCount); - for (FiguredBassSlice* slice: track->slices) { - trackData[slice->lineIndex] = slice->toString(nonCompoundIntervalsQ, noAccidentalsQ); + for (int i = 0; i < lineCount; i++) { + vector sliceNumbers = findFiguredBassNumbersForLine(numbers, i); + if(sliceNumbers.size() > 0) { + trackData[i] = formatFiguredBassNumbers(sliceNumbers, nonCompoundIntervalsQ, noAccidentalsQ); + } } return trackData; @@ -111,29 +106,27 @@ FiguredBassNumber* Tool_figuredbass::createFiguredBassNumber(NoteCell* base, Not accid = '#'; } - FiguredBassNumber* number = new FiguredBassNumber(num, accid); + FiguredBassNumber* number = new FiguredBassNumber(num, accid, target->getVoiceIndex(), target->getLineIndex()); return number; }; -FiguredBassTrack::FiguredBassTrack(int index) { - voiceIndex = index; -}; +vector Tool_figuredbass::findFiguredBassNumbersForLine(vector numbers, int lineIndex) { -void FiguredBassTrack::add(FiguredBassSlice* slice) { - slices.push_back(slice); -}; + vector filteredNumbers; -FiguredBassSlice::FiguredBassSlice(int index) { - lineIndex = index; -}; + copy_if(numbers.begin(), numbers.end(), back_inserter(filteredNumbers), [lineIndex](FiguredBassNumber* num) { + return num->lineIndex == lineIndex; + }); + + sort(filteredNumbers.begin(), filteredNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { + return a->voiceIndex > b->voiceIndex; + }); -void FiguredBassSlice::add(FiguredBassNumber* number) { - numbers.insert(numbers.begin(), number); - // numbers.push_back(number); + return filteredNumbers; }; -string FiguredBassSlice::toString(bool nonCompoundIntervalsQ, bool noAccidentalsQ) { +string Tool_figuredbass::formatFiguredBassNumbers(vector numbers, bool nonCompoundIntervalsQ, bool noAccidentalsQ) { string str = ""; bool first = true; for (FiguredBassNumber* number: numbers) { @@ -141,15 +134,17 @@ string FiguredBassSlice::toString(bool nonCompoundIntervalsQ, bool noAccidentals if(num.length() > 0) { if (!first) str += " "; first = false; - str += number->toString(nonCompoundIntervalsQ, noAccidentalsQ); + str += num; } } return str; }; -FiguredBassNumber::FiguredBassNumber(int num, string accid) { +FiguredBassNumber::FiguredBassNumber(int num, string accid, int voiceIdx, int lineIdx) { number = num; accidentals = accid; + voiceIndex = voiceIdx; + lineIndex = lineIdx; }; string FiguredBassNumber::toString(bool nonCompoundIntervalsQ, bool noAccidentalsQ) { From fd096f1ddd391c3574fbd5d82c48fb8c6144026c Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Sun, 27 Nov 2022 22:39:41 +0100 Subject: [PATCH 006/109] Add intervallsatz feature --- include/tool-figuredbass.h | 7 ++++- src/tool-figuredbass.cpp | 61 +++++++++++++++++++++++++++++++++----- 2 files changed, 60 insertions(+), 8 deletions(-) diff --git a/include/tool-figuredbass.h b/include/tool-figuredbass.h index dd4db494..38cd805a 100644 --- a/include/tool-figuredbass.h +++ b/include/tool-figuredbass.h @@ -31,10 +31,14 @@ class Tool_figuredbass : public HumTool { bool run (HumdrumFile& infile, ostream& out); vector getTrackData(vector numbers, int lineCount, bool nonCompoundIntervalsQ, bool noAccidentalsQ); + + vector getTrackDataForVoice(int voiceIndex, vector numbers, int lineCount, bool nonCompoundIntervalsQ, bool noAccidentalsQ); FiguredBassNumber* createFiguredBassNumber(NoteCell* base, NoteCell* target); - vector findFiguredBassNumbersForLine(vector, int lineIndex); + vector filterFiguredBassNumbersForLine(vector, int lineIndex); + + vector filterFiguredBassNumbersForLineAndVoice(vector, int lineIndex, int voiceIndex); string formatFiguredBassNumbers(vector numbers, bool nonCompoundIntervalsQ, bool noAccidentalsQ); @@ -44,6 +48,7 @@ class Tool_figuredbass : public HumTool { bool nonCompoundIntervalsQ = false; bool noAccidentalsQ = false; int baseQ = 0; + bool intervallsatzQ = false; }; diff --git a/src/tool-figuredbass.cpp b/src/tool-figuredbass.cpp index 68e34007..7a0c50ea 100644 --- a/src/tool-figuredbass.cpp +++ b/src/tool-figuredbass.cpp @@ -12,6 +12,7 @@ Tool_figuredbass::Tool_figuredbass(void) { define("C|non-compound=b", "output compound intervals as non-compound intervals"); define("A|no-accidentals=b", "ignore accidentals in figured bass output"); define("b|base=i:0", "number of the base voice/spine"); + define("i|intervallsatz=b", "display intervals under their voice and not under the lowest staff"); } bool Tool_figuredbass::run(HumdrumFileSet &infiles) { @@ -48,6 +49,7 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { nonCompoundIntervalsQ = getBoolean("non-compound"); noAccidentalsQ = getBoolean("no-accidentals"); baseQ = getInteger("base"); + intervallsatzQ = getBoolean("intervallsatz"); NoteGrid grid(infile); @@ -69,12 +71,28 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { } } - if(baseVoiceIndex < grid.getVoiceCount()) { - int trackIndex = kernspines[baseVoiceIndex + 1]->getTrack(); - infile.insertDataSpineBefore(trackIndex, getTrackData(data, infile.getLineCount(), nonCompoundIntervalsQ, noAccidentalsQ), ".", "**fb"); + if(intervallsatzQ) { + for (int voiceIndex = 0; voiceIndex < grid.getVoiceCount(); voiceIndex++) { + if(voiceIndex == baseVoiceIndex) { + continue; + } + vector trackData = getTrackDataForVoice(voiceIndex, data, infile.getLineCount(), nonCompoundIntervalsQ, noAccidentalsQ); + if(voiceIndex + 1 < grid.getVoiceCount()) { + int trackIndex = kernspines[voiceIndex + 1]->getTrack(); + infile.insertDataSpineBefore(trackIndex, trackData, ".", "**fb"); + } else { + int trackIndex = kernspines[voiceIndex]->getTrack(); + infile.appendDataSpine(trackData, ".", "**fb"); + } + } } else { - // TODO segmentation fault - infile.appendDataSpine(getTrackData(data, infile.getLineCount(), nonCompoundIntervalsQ, noAccidentalsQ), ".", "**fb"); + vector trackData = getTrackData(data, infile.getLineCount(), nonCompoundIntervalsQ, noAccidentalsQ); + if(baseVoiceIndex + 1 < grid.getVoiceCount()) { + int trackIndex = kernspines[baseVoiceIndex + 1]->getTrack(); + infile.insertDataSpineBefore(trackIndex, trackData, ".", "**fb"); + } else { + infile.appendDataSpine(trackData, ".", "**fb"); + } } return true; @@ -85,7 +103,21 @@ vector Tool_figuredbass::getTrackData(vector numbers trackData.resize(lineCount); for (int i = 0; i < lineCount; i++) { - vector sliceNumbers = findFiguredBassNumbersForLine(numbers, i); + vector sliceNumbers = filterFiguredBassNumbersForLine(numbers, i); + if(sliceNumbers.size() > 0) { + trackData[i] = formatFiguredBassNumbers(sliceNumbers, nonCompoundIntervalsQ, noAccidentalsQ); + } + } + + return trackData; +}; + +vector Tool_figuredbass::getTrackDataForVoice(int voiceIndex, vector numbers, int lineCount, bool nonCompoundIntervalsQ, bool noAccidentalsQ) { + vector trackData; + trackData.resize(lineCount); + + for (int i = 0; i < lineCount; i++) { + vector sliceNumbers = filterFiguredBassNumbersForLineAndVoice(numbers, i, voiceIndex); if(sliceNumbers.size() > 0) { trackData[i] = formatFiguredBassNumbers(sliceNumbers, nonCompoundIntervalsQ, noAccidentalsQ); } @@ -111,7 +143,7 @@ FiguredBassNumber* Tool_figuredbass::createFiguredBassNumber(NoteCell* base, Not return number; }; -vector Tool_figuredbass::findFiguredBassNumbersForLine(vector numbers, int lineIndex) { +vector Tool_figuredbass::filterFiguredBassNumbersForLine(vector numbers, int lineIndex) { vector filteredNumbers; @@ -126,6 +158,21 @@ vector Tool_figuredbass::findFiguredBassNumbersForLine(vecto return filteredNumbers; }; +vector Tool_figuredbass::filterFiguredBassNumbersForLineAndVoice(vector numbers, int lineIndex, int voiceIndex) { + + vector filteredNumbers; + + copy_if(numbers.begin(), numbers.end(), back_inserter(filteredNumbers), [lineIndex, voiceIndex](FiguredBassNumber* num) { + return num->lineIndex == lineIndex && num->voiceIndex == voiceIndex; + }); + + sort(filteredNumbers.begin(), filteredNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { + return a->voiceIndex > b->voiceIndex; + }); + + return filteredNumbers; +}; + string Tool_figuredbass::formatFiguredBassNumbers(vector numbers, bool nonCompoundIntervalsQ, bool noAccidentalsQ) { string str = ""; bool first = true; From 6a4f4b43786d76dea76bf842f4d3f7da23b337e0 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Sun, 27 Nov 2022 23:22:40 +0100 Subject: [PATCH 007/109] Add feature to sort figured bass numbers by interval --- include/tool-figuredbass.h | 8 +++++--- src/tool-figuredbass.cpp | 27 +++++++++++++++++++-------- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/include/tool-figuredbass.h b/include/tool-figuredbass.h index 38cd805a..9fdc2227 100644 --- a/include/tool-figuredbass.h +++ b/include/tool-figuredbass.h @@ -17,6 +17,7 @@ class FiguredBassNumber { string accidentals; FiguredBassNumber(int num, string accid, int voiceIndex, int lineIndex); string toString(bool nonCompoundIntervalsQ, bool noAccidentalsQ); + int getNumberB7(); }; class Tool_figuredbass : public HumTool { @@ -30,9 +31,9 @@ class Tool_figuredbass : public HumTool { bool run (const string& indata, ostream& out); bool run (HumdrumFile& infile, ostream& out); - vector getTrackData(vector numbers, int lineCount, bool nonCompoundIntervalsQ, bool noAccidentalsQ); + vector getTrackData(vector numbers, int lineCount, bool nonCompoundIntervalsQ, bool noAccidentalsQ, bool sortQ); - vector getTrackDataForVoice(int voiceIndex, vector numbers, int lineCount, bool nonCompoundIntervalsQ, bool noAccidentalsQ); + vector getTrackDataForVoice(int voiceIndex, vector numbers, int lineCount, bool nonCompoundIntervalsQ, bool noAccidentalsQ, bool sortQ); FiguredBassNumber* createFiguredBassNumber(NoteCell* base, NoteCell* target); @@ -40,7 +41,7 @@ class Tool_figuredbass : public HumTool { vector filterFiguredBassNumbersForLineAndVoice(vector, int lineIndex, int voiceIndex); - string formatFiguredBassNumbers(vector numbers, bool nonCompoundIntervalsQ, bool noAccidentalsQ); + string formatFiguredBassNumbers(vector numbers, bool nonCompoundIntervalsQ, bool noAccidentalsQ, bool sortQ); // protected: @@ -49,6 +50,7 @@ class Tool_figuredbass : public HumTool { bool noAccidentalsQ = false; int baseQ = 0; bool intervallsatzQ = false; + bool sortQ = false; }; diff --git a/src/tool-figuredbass.cpp b/src/tool-figuredbass.cpp index 7a0c50ea..838dd7f5 100644 --- a/src/tool-figuredbass.cpp +++ b/src/tool-figuredbass.cpp @@ -13,6 +13,7 @@ Tool_figuredbass::Tool_figuredbass(void) { define("A|no-accidentals=b", "ignore accidentals in figured bass output"); define("b|base=i:0", "number of the base voice/spine"); define("i|intervallsatz=b", "display intervals under their voice and not under the lowest staff"); + define("s|sort=b", "sort figured bass numbers by interval size and not by voice index"); } bool Tool_figuredbass::run(HumdrumFileSet &infiles) { @@ -50,6 +51,7 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { noAccidentalsQ = getBoolean("no-accidentals"); baseQ = getInteger("base"); intervallsatzQ = getBoolean("intervallsatz"); + sortQ = getBoolean("sort"); NoteGrid grid(infile); @@ -76,7 +78,7 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { if(voiceIndex == baseVoiceIndex) { continue; } - vector trackData = getTrackDataForVoice(voiceIndex, data, infile.getLineCount(), nonCompoundIntervalsQ, noAccidentalsQ); + vector trackData = getTrackDataForVoice(voiceIndex, data, infile.getLineCount(), nonCompoundIntervalsQ, noAccidentalsQ, sortQ); if(voiceIndex + 1 < grid.getVoiceCount()) { int trackIndex = kernspines[voiceIndex + 1]->getTrack(); infile.insertDataSpineBefore(trackIndex, trackData, ".", "**fb"); @@ -86,7 +88,7 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { } } } else { - vector trackData = getTrackData(data, infile.getLineCount(), nonCompoundIntervalsQ, noAccidentalsQ); + vector trackData = getTrackData(data, infile.getLineCount(), nonCompoundIntervalsQ, noAccidentalsQ, sortQ); if(baseVoiceIndex + 1 < grid.getVoiceCount()) { int trackIndex = kernspines[baseVoiceIndex + 1]->getTrack(); infile.insertDataSpineBefore(trackIndex, trackData, ".", "**fb"); @@ -98,28 +100,28 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { return true; }; -vector Tool_figuredbass::getTrackData(vector numbers, int lineCount, bool nonCompoundIntervalsQ, bool noAccidentalsQ) { +vector Tool_figuredbass::getTrackData(vector numbers, int lineCount, bool nonCompoundIntervalsQ, bool noAccidentalsQ, bool sortQ) { vector trackData; trackData.resize(lineCount); for (int i = 0; i < lineCount; i++) { vector sliceNumbers = filterFiguredBassNumbersForLine(numbers, i); if(sliceNumbers.size() > 0) { - trackData[i] = formatFiguredBassNumbers(sliceNumbers, nonCompoundIntervalsQ, noAccidentalsQ); + trackData[i] = formatFiguredBassNumbers(sliceNumbers, nonCompoundIntervalsQ, noAccidentalsQ, sortQ); } } return trackData; }; -vector Tool_figuredbass::getTrackDataForVoice(int voiceIndex, vector numbers, int lineCount, bool nonCompoundIntervalsQ, bool noAccidentalsQ) { +vector Tool_figuredbass::getTrackDataForVoice(int voiceIndex, vector numbers, int lineCount, bool nonCompoundIntervalsQ, bool noAccidentalsQ, bool sortQ) { vector trackData; trackData.resize(lineCount); for (int i = 0; i < lineCount; i++) { vector sliceNumbers = filterFiguredBassNumbersForLineAndVoice(numbers, i, voiceIndex); if(sliceNumbers.size() > 0) { - trackData[i] = formatFiguredBassNumbers(sliceNumbers, nonCompoundIntervalsQ, noAccidentalsQ); + trackData[i] = formatFiguredBassNumbers(sliceNumbers, nonCompoundIntervalsQ, noAccidentalsQ, sortQ); } } @@ -173,7 +175,13 @@ vector Tool_figuredbass::filterFiguredBassNumbersForLineAndV return filteredNumbers; }; -string Tool_figuredbass::formatFiguredBassNumbers(vector numbers, bool nonCompoundIntervalsQ, bool noAccidentalsQ) { +string Tool_figuredbass::formatFiguredBassNumbers(vector numbers, bool nonCompoundIntervalsQ, bool noAccidentalsQ, bool sortQ) { + if(sortQ) { + sort(numbers.begin(), numbers.end(), [nonCompoundIntervalsQ](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { + return (nonCompoundIntervalsQ) ? a->number > b->number : a->getNumberB7() > b->getNumberB7(); + + }); + } string str = ""; bool first = true; for (FiguredBassNumber* number: numbers) { @@ -195,11 +203,14 @@ FiguredBassNumber::FiguredBassNumber(int num, string accid, int voiceIdx, int li }; string FiguredBassNumber::toString(bool nonCompoundIntervalsQ, bool noAccidentalsQ) { - int num = (number > 9 && !nonCompoundIntervalsQ) ? number % 7 : number; + int num = (!nonCompoundIntervalsQ) ? getNumberB7() : number; string accid = (!noAccidentalsQ) ? accidentals : ""; return num > 0 ? to_string(num) + accid : ""; }; +int FiguredBassNumber::getNumberB7() { + return (number > 9) ? number % 7 : number; +}; // END_MERGE From 7ec9c5dc99f3b14e7cf73b5e1686001fde0ed0b1 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Mon, 28 Nov 2022 10:25:44 +0100 Subject: [PATCH 008/109] Fix compound octave --- src/tool-figuredbass.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tool-figuredbass.cpp b/src/tool-figuredbass.cpp index 838dd7f5..cab532d2 100644 --- a/src/tool-figuredbass.cpp +++ b/src/tool-figuredbass.cpp @@ -209,7 +209,8 @@ string FiguredBassNumber::toString(bool nonCompoundIntervalsQ, bool noAccidental }; int FiguredBassNumber::getNumberB7() { - return (number > 9) ? number % 7 : number; + int num = (number > 9) ? number % 7 : number; + return (number > 8 && num == 1) ? 8 : num; }; From 25b50a98f9715e7e3b2bc07ef1bd1b896f85322f Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Mon, 28 Nov 2022 10:55:47 +0100 Subject: [PATCH 009/109] Add feature for lowest note as base --- include/tool-figuredbass.h | 1 + src/tool-figuredbass.cpp | 22 +++++++++++++++++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/include/tool-figuredbass.h b/include/tool-figuredbass.h index 9fdc2227..4fb1e81c 100644 --- a/include/tool-figuredbass.h +++ b/include/tool-figuredbass.h @@ -51,6 +51,7 @@ class Tool_figuredbass : public HumTool { int baseQ = 0; bool intervallsatzQ = false; bool sortQ = false; + bool lowestQ = false; }; diff --git a/src/tool-figuredbass.cpp b/src/tool-figuredbass.cpp index cab532d2..91756ddd 100644 --- a/src/tool-figuredbass.cpp +++ b/src/tool-figuredbass.cpp @@ -14,6 +14,7 @@ Tool_figuredbass::Tool_figuredbass(void) { define("b|base=i:0", "number of the base voice/spine"); define("i|intervallsatz=b", "display intervals under their voice and not under the lowest staff"); define("s|sort=b", "sort figured bass numbers by interval size and not by voice index"); + define("l|lowest=b", "use lowest note as base note; -b flag will be ignored"); } bool Tool_figuredbass::run(HumdrumFileSet &infiles) { @@ -52,6 +53,7 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { baseQ = getInteger("base"); intervallsatzQ = getBoolean("intervallsatz"); sortQ = getBoolean("sort"); + lowestQ = getBoolean("lowest"); NoteGrid grid(infile); @@ -62,9 +64,22 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { int baseVoiceIndex = baseQ; for (int i=0; i<(int)grid.getSliceCount(); i++) { - NoteCell* baseCell = grid.cell(baseVoiceIndex, i); + int usedBaseVoiceIndex = baseVoiceIndex; + if(lowestQ) { + int lowestNotePitch = 99999; + for (int k=0; k<(int)grid.getVoiceCount(); k++) { + NoteCell* checkCell = grid.cell(k, i); + int checkCellPitch = abs(checkCell->getSgnDiatonicPitch()); + if(checkCellPitch > 0 && checkCellPitch < lowestNotePitch) { + lowestNotePitch = checkCellPitch; + usedBaseVoiceIndex = k; + } + } + cout << "!! " << lowestNotePitch << " " << usedBaseVoiceIndex << " " << to_string(i) << "\n"; + } + NoteCell* baseCell = grid.cell(usedBaseVoiceIndex, i); for (int j=0; j<(int)grid.getVoiceCount(); j++) { - if(j == baseVoiceIndex) { + if(j == usedBaseVoiceIndex) { continue; } NoteCell* targetCell = grid.cell(j, i); @@ -75,9 +90,6 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { if(intervallsatzQ) { for (int voiceIndex = 0; voiceIndex < grid.getVoiceCount(); voiceIndex++) { - if(voiceIndex == baseVoiceIndex) { - continue; - } vector trackData = getTrackDataForVoice(voiceIndex, data, infile.getLineCount(), nonCompoundIntervalsQ, noAccidentalsQ, sortQ); if(voiceIndex + 1 < grid.getVoiceCount()) { int trackIndex = kernspines[voiceIndex + 1]->getTrack(); From f7ee3fc6f58cf9ff65de2cf22e11d8886d38cc35 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Mon, 28 Nov 2022 11:13:02 +0100 Subject: [PATCH 010/109] Remove cout --- src/tool-figuredbass.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tool-figuredbass.cpp b/src/tool-figuredbass.cpp index 91756ddd..e5d8b434 100644 --- a/src/tool-figuredbass.cpp +++ b/src/tool-figuredbass.cpp @@ -75,7 +75,6 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { usedBaseVoiceIndex = k; } } - cout << "!! " << lowestNotePitch << " " << usedBaseVoiceIndex << " " << to_string(i) << "\n"; } NoteCell* baseCell = grid.cell(usedBaseVoiceIndex, i); for (int j=0; j<(int)grid.getVoiceCount(); j++) { From 5896b8e477159f7220f9c88a158b8fbfa6ee9774 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Mon, 28 Nov 2022 11:23:26 +0100 Subject: [PATCH 011/109] Refactor var names --- src/tool-figuredbass.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/tool-figuredbass.cpp b/src/tool-figuredbass.cpp index e5d8b434..0d96eccf 100644 --- a/src/tool-figuredbass.cpp +++ b/src/tool-figuredbass.cpp @@ -57,14 +57,12 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { NoteGrid grid(infile); - vector data; + vector numbers; vector kernspines = infile.getKernSpineStartList(); - int baseVoiceIndex = baseQ; - for (int i=0; i<(int)grid.getSliceCount(); i++) { - int usedBaseVoiceIndex = baseVoiceIndex; + int usedBaseVoiceIndex = baseQ; if(lowestQ) { int lowestNotePitch = 99999; for (int k=0; k<(int)grid.getVoiceCount(); k++) { @@ -83,13 +81,13 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { } NoteCell* targetCell = grid.cell(j, i); FiguredBassNumber* number = createFiguredBassNumber(baseCell, targetCell); - data.push_back(number); + numbers.push_back(number); } } if(intervallsatzQ) { for (int voiceIndex = 0; voiceIndex < grid.getVoiceCount(); voiceIndex++) { - vector trackData = getTrackDataForVoice(voiceIndex, data, infile.getLineCount(), nonCompoundIntervalsQ, noAccidentalsQ, sortQ); + vector trackData = getTrackDataForVoice(voiceIndex, numbers, infile.getLineCount(), nonCompoundIntervalsQ, noAccidentalsQ, sortQ); if(voiceIndex + 1 < grid.getVoiceCount()) { int trackIndex = kernspines[voiceIndex + 1]->getTrack(); infile.insertDataSpineBefore(trackIndex, trackData, ".", "**fb"); @@ -99,9 +97,9 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { } } } else { - vector trackData = getTrackData(data, infile.getLineCount(), nonCompoundIntervalsQ, noAccidentalsQ, sortQ); - if(baseVoiceIndex + 1 < grid.getVoiceCount()) { - int trackIndex = kernspines[baseVoiceIndex + 1]->getTrack(); + vector trackData = getTrackData(numbers, infile.getLineCount(), nonCompoundIntervalsQ, noAccidentalsQ, sortQ); + if(baseQ + 1 < grid.getVoiceCount()) { + int trackIndex = kernspines[baseQ + 1]->getTrack(); infile.insertDataSpineBefore(trackIndex, trackData, ".", "**fb"); } else { infile.appendDataSpine(trackData, ".", "**fb"); From 79401566cbadce71feaa35dd55f6a65262278999 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Mon, 28 Nov 2022 11:25:35 +0100 Subject: [PATCH 012/109] Rename nonCompoundIntervalsQ to compoundQ --- include/tool-figuredbass.h | 2 +- src/tool-figuredbass.cpp | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/include/tool-figuredbass.h b/include/tool-figuredbass.h index 4fb1e81c..412c0b1d 100644 --- a/include/tool-figuredbass.h +++ b/include/tool-figuredbass.h @@ -46,7 +46,7 @@ class Tool_figuredbass : public HumTool { // protected: private: - bool nonCompoundIntervalsQ = false; + bool compoundQ = false; bool noAccidentalsQ = false; int baseQ = 0; bool intervallsatzQ = false; diff --git a/src/tool-figuredbass.cpp b/src/tool-figuredbass.cpp index 0d96eccf..966e59a1 100644 --- a/src/tool-figuredbass.cpp +++ b/src/tool-figuredbass.cpp @@ -9,7 +9,7 @@ namespace hum { // START_MERGE Tool_figuredbass::Tool_figuredbass(void) { - define("C|non-compound=b", "output compound intervals as non-compound intervals"); + define("c|compound=b", "output compound intervals for intervals bigger than 9"); define("A|no-accidentals=b", "ignore accidentals in figured bass output"); define("b|base=i:0", "number of the base voice/spine"); define("i|intervallsatz=b", "display intervals under their voice and not under the lowest staff"); @@ -48,7 +48,7 @@ bool Tool_figuredbass::run(HumdrumFile &infile, ostream &out) { bool Tool_figuredbass::run(HumdrumFile &infile) { - nonCompoundIntervalsQ = getBoolean("non-compound"); + compoundQ = getBoolean("compound"); noAccidentalsQ = getBoolean("no-accidentals"); baseQ = getInteger("base"); intervallsatzQ = getBoolean("intervallsatz"); @@ -87,7 +87,7 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { if(intervallsatzQ) { for (int voiceIndex = 0; voiceIndex < grid.getVoiceCount(); voiceIndex++) { - vector trackData = getTrackDataForVoice(voiceIndex, numbers, infile.getLineCount(), nonCompoundIntervalsQ, noAccidentalsQ, sortQ); + vector trackData = getTrackDataForVoice(voiceIndex, numbers, infile.getLineCount(), compoundQ, noAccidentalsQ, sortQ); if(voiceIndex + 1 < grid.getVoiceCount()) { int trackIndex = kernspines[voiceIndex + 1]->getTrack(); infile.insertDataSpineBefore(trackIndex, trackData, ".", "**fb"); @@ -97,7 +97,7 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { } } } else { - vector trackData = getTrackData(numbers, infile.getLineCount(), nonCompoundIntervalsQ, noAccidentalsQ, sortQ); + vector trackData = getTrackData(numbers, infile.getLineCount(), compoundQ, noAccidentalsQ, sortQ); if(baseQ + 1 < grid.getVoiceCount()) { int trackIndex = kernspines[baseQ + 1]->getTrack(); infile.insertDataSpineBefore(trackIndex, trackData, ".", "**fb"); @@ -109,28 +109,28 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { return true; }; -vector Tool_figuredbass::getTrackData(vector numbers, int lineCount, bool nonCompoundIntervalsQ, bool noAccidentalsQ, bool sortQ) { +vector Tool_figuredbass::getTrackData(vector numbers, int lineCount, bool compoundQ, bool noAccidentalsQ, bool sortQ) { vector trackData; trackData.resize(lineCount); for (int i = 0; i < lineCount; i++) { vector sliceNumbers = filterFiguredBassNumbersForLine(numbers, i); if(sliceNumbers.size() > 0) { - trackData[i] = formatFiguredBassNumbers(sliceNumbers, nonCompoundIntervalsQ, noAccidentalsQ, sortQ); + trackData[i] = formatFiguredBassNumbers(sliceNumbers, compoundQ, noAccidentalsQ, sortQ); } } return trackData; }; -vector Tool_figuredbass::getTrackDataForVoice(int voiceIndex, vector numbers, int lineCount, bool nonCompoundIntervalsQ, bool noAccidentalsQ, bool sortQ) { +vector Tool_figuredbass::getTrackDataForVoice(int voiceIndex, vector numbers, int lineCount, bool compoundQ, bool noAccidentalsQ, bool sortQ) { vector trackData; trackData.resize(lineCount); for (int i = 0; i < lineCount; i++) { vector sliceNumbers = filterFiguredBassNumbersForLineAndVoice(numbers, i, voiceIndex); if(sliceNumbers.size() > 0) { - trackData[i] = formatFiguredBassNumbers(sliceNumbers, nonCompoundIntervalsQ, noAccidentalsQ, sortQ); + trackData[i] = formatFiguredBassNumbers(sliceNumbers, compoundQ, noAccidentalsQ, sortQ); } } @@ -184,17 +184,17 @@ vector Tool_figuredbass::filterFiguredBassNumbersForLineAndV return filteredNumbers; }; -string Tool_figuredbass::formatFiguredBassNumbers(vector numbers, bool nonCompoundIntervalsQ, bool noAccidentalsQ, bool sortQ) { +string Tool_figuredbass::formatFiguredBassNumbers(vector numbers, bool compoundQ, bool noAccidentalsQ, bool sortQ) { if(sortQ) { - sort(numbers.begin(), numbers.end(), [nonCompoundIntervalsQ](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { - return (nonCompoundIntervalsQ) ? a->number > b->number : a->getNumberB7() > b->getNumberB7(); + sort(numbers.begin(), numbers.end(), [compoundQ](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { + return (compoundQ) ? a->getNumberB7() > b->getNumberB7() : a->number > b->number; }); } string str = ""; bool first = true; for (FiguredBassNumber* number: numbers) { - string num = number->toString(nonCompoundIntervalsQ, noAccidentalsQ); + string num = number->toString(compoundQ, noAccidentalsQ); if(num.length() > 0) { if (!first) str += " "; first = false; @@ -211,8 +211,8 @@ FiguredBassNumber::FiguredBassNumber(int num, string accid, int voiceIdx, int li lineIndex = lineIdx; }; -string FiguredBassNumber::toString(bool nonCompoundIntervalsQ, bool noAccidentalsQ) { - int num = (!nonCompoundIntervalsQ) ? getNumberB7() : number; +string FiguredBassNumber::toString(bool compoundQ, bool noAccidentalsQ) { + int num = (compoundQ) ? getNumberB7() : number; string accid = (!noAccidentalsQ) ? accidentals : ""; return num > 0 ? to_string(num) + accid : ""; }; From 7d8579f14a4047dcf43a4a1b4c583f1ac6c344cd Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Mon, 28 Nov 2022 11:27:15 +0100 Subject: [PATCH 013/109] Rename noAccidentalsQ to accidentalsQ --- include/tool-figuredbass.h | 2 +- src/tool-figuredbass.cpp | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/include/tool-figuredbass.h b/include/tool-figuredbass.h index 412c0b1d..636a8600 100644 --- a/include/tool-figuredbass.h +++ b/include/tool-figuredbass.h @@ -47,7 +47,7 @@ class Tool_figuredbass : public HumTool { private: bool compoundQ = false; - bool noAccidentalsQ = false; + bool accidentalsQ = false; int baseQ = 0; bool intervallsatzQ = false; bool sortQ = false; diff --git a/src/tool-figuredbass.cpp b/src/tool-figuredbass.cpp index 966e59a1..e3c675c1 100644 --- a/src/tool-figuredbass.cpp +++ b/src/tool-figuredbass.cpp @@ -10,7 +10,7 @@ namespace hum { Tool_figuredbass::Tool_figuredbass(void) { define("c|compound=b", "output compound intervals for intervals bigger than 9"); - define("A|no-accidentals=b", "ignore accidentals in figured bass output"); + define("a|accidentals=b", "display accidentals in figured bass output"); define("b|base=i:0", "number of the base voice/spine"); define("i|intervallsatz=b", "display intervals under their voice and not under the lowest staff"); define("s|sort=b", "sort figured bass numbers by interval size and not by voice index"); @@ -49,7 +49,7 @@ bool Tool_figuredbass::run(HumdrumFile &infile, ostream &out) { bool Tool_figuredbass::run(HumdrumFile &infile) { compoundQ = getBoolean("compound"); - noAccidentalsQ = getBoolean("no-accidentals"); + accidentalsQ = getBoolean("accidentals"); baseQ = getInteger("base"); intervallsatzQ = getBoolean("intervallsatz"); sortQ = getBoolean("sort"); @@ -87,7 +87,7 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { if(intervallsatzQ) { for (int voiceIndex = 0; voiceIndex < grid.getVoiceCount(); voiceIndex++) { - vector trackData = getTrackDataForVoice(voiceIndex, numbers, infile.getLineCount(), compoundQ, noAccidentalsQ, sortQ); + vector trackData = getTrackDataForVoice(voiceIndex, numbers, infile.getLineCount(), compoundQ, accidentalsQ, sortQ); if(voiceIndex + 1 < grid.getVoiceCount()) { int trackIndex = kernspines[voiceIndex + 1]->getTrack(); infile.insertDataSpineBefore(trackIndex, trackData, ".", "**fb"); @@ -97,7 +97,7 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { } } } else { - vector trackData = getTrackData(numbers, infile.getLineCount(), compoundQ, noAccidentalsQ, sortQ); + vector trackData = getTrackData(numbers, infile.getLineCount(), compoundQ, accidentalsQ, sortQ); if(baseQ + 1 < grid.getVoiceCount()) { int trackIndex = kernspines[baseQ + 1]->getTrack(); infile.insertDataSpineBefore(trackIndex, trackData, ".", "**fb"); @@ -109,28 +109,28 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { return true; }; -vector Tool_figuredbass::getTrackData(vector numbers, int lineCount, bool compoundQ, bool noAccidentalsQ, bool sortQ) { +vector Tool_figuredbass::getTrackData(vector numbers, int lineCount, bool compoundQ, bool accidentalsQ, bool sortQ) { vector trackData; trackData.resize(lineCount); for (int i = 0; i < lineCount; i++) { vector sliceNumbers = filterFiguredBassNumbersForLine(numbers, i); if(sliceNumbers.size() > 0) { - trackData[i] = formatFiguredBassNumbers(sliceNumbers, compoundQ, noAccidentalsQ, sortQ); + trackData[i] = formatFiguredBassNumbers(sliceNumbers, compoundQ, accidentalsQ, sortQ); } } return trackData; }; -vector Tool_figuredbass::getTrackDataForVoice(int voiceIndex, vector numbers, int lineCount, bool compoundQ, bool noAccidentalsQ, bool sortQ) { +vector Tool_figuredbass::getTrackDataForVoice(int voiceIndex, vector numbers, int lineCount, bool compoundQ, bool accidentalsQ, bool sortQ) { vector trackData; trackData.resize(lineCount); for (int i = 0; i < lineCount; i++) { vector sliceNumbers = filterFiguredBassNumbersForLineAndVoice(numbers, i, voiceIndex); if(sliceNumbers.size() > 0) { - trackData[i] = formatFiguredBassNumbers(sliceNumbers, compoundQ, noAccidentalsQ, sortQ); + trackData[i] = formatFiguredBassNumbers(sliceNumbers, compoundQ, accidentalsQ, sortQ); } } @@ -184,7 +184,7 @@ vector Tool_figuredbass::filterFiguredBassNumbersForLineAndV return filteredNumbers; }; -string Tool_figuredbass::formatFiguredBassNumbers(vector numbers, bool compoundQ, bool noAccidentalsQ, bool sortQ) { +string Tool_figuredbass::formatFiguredBassNumbers(vector numbers, bool compoundQ, bool accidentalsQ, bool sortQ) { if(sortQ) { sort(numbers.begin(), numbers.end(), [compoundQ](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { return (compoundQ) ? a->getNumberB7() > b->getNumberB7() : a->number > b->number; @@ -194,7 +194,7 @@ string Tool_figuredbass::formatFiguredBassNumbers(vector num string str = ""; bool first = true; for (FiguredBassNumber* number: numbers) { - string num = number->toString(compoundQ, noAccidentalsQ); + string num = number->toString(compoundQ, accidentalsQ); if(num.length() > 0) { if (!first) str += " "; first = false; @@ -211,9 +211,9 @@ FiguredBassNumber::FiguredBassNumber(int num, string accid, int voiceIdx, int li lineIndex = lineIdx; }; -string FiguredBassNumber::toString(bool compoundQ, bool noAccidentalsQ) { +string FiguredBassNumber::toString(bool compoundQ, bool accidentalsQ) { int num = (compoundQ) ? getNumberB7() : number; - string accid = (!noAccidentalsQ) ? accidentals : ""; + string accid = (accidentalsQ) ? accidentals : ""; return num > 0 ? to_string(num) + accid : ""; }; From 8769e03ac949f0a4e47c8cf7509552151cbacb61 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Mon, 28 Nov 2022 12:00:44 +0100 Subject: [PATCH 014/109] Improve accidentals support --- src/tool-figuredbass.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/tool-figuredbass.cpp b/src/tool-figuredbass.cpp index e3c675c1..99d8e672 100644 --- a/src/tool-figuredbass.cpp +++ b/src/tool-figuredbass.cpp @@ -1,6 +1,7 @@ #include "tool-figuredbass.h" #include "Convert.h" #include "HumRegex.h" +#include using namespace std; @@ -142,12 +143,8 @@ FiguredBassNumber* Tool_figuredbass::createFiguredBassNumber(NoteCell* base, Not int basePitch = base->getSgnDiatonicPitch(); int targetPitch = target->getSgnDiatonicPitch(); int num = (basePitch == 0 || targetPitch == 0) ? 0 : abs(abs(targetPitch) - abs(basePitch)) + 1; - string accid = ""; - if(target->getSgnKernPitch().find("-") != string::npos) { - accid = '-'; - } else if(target->getSgnKernPitch().find("#") != string::npos) { - accid = '#'; - } + regex keepAccid("^\\(?\\w+([^\\w\\)]*)\\)?$"); + string accid = regex_replace(target->getSgnKernPitch(), keepAccid, "$1"); FiguredBassNumber* number = new FiguredBassNumber(num, accid, target->getVoiceIndex(), target->getLineIndex()); From 16c03a29b421ad78c73eebba31ab9f5b853486ff Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Mon, 28 Nov 2022 13:15:37 +0100 Subject: [PATCH 015/109] Remove accidentals that are already present in the key signature --- include/tool-figuredbass.h | 7 ++++-- src/tool-figuredbass.cpp | 47 ++++++++++++++++++++++++++++++++------ 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/include/tool-figuredbass.h b/include/tool-figuredbass.h index 636a8600..b06a25ad 100644 --- a/include/tool-figuredbass.h +++ b/include/tool-figuredbass.h @@ -15,7 +15,8 @@ class FiguredBassNumber { int lineIndex; int number; string accidentals; - FiguredBassNumber(int num, string accid, int voiceIndex, int lineIndex); + bool showAccidentals; + FiguredBassNumber(int num, string accid, bool showAccid, int voiceIndex, int lineIndex); string toString(bool nonCompoundIntervalsQ, bool noAccidentalsQ); int getNumberB7(); }; @@ -35,7 +36,7 @@ class Tool_figuredbass : public HumTool { vector getTrackDataForVoice(int voiceIndex, vector numbers, int lineCount, bool nonCompoundIntervalsQ, bool noAccidentalsQ, bool sortQ); - FiguredBassNumber* createFiguredBassNumber(NoteCell* base, NoteCell* target); + FiguredBassNumber* createFiguredBassNumber(NoteCell* base, NoteCell* target, string keySignature); vector filterFiguredBassNumbersForLine(vector, int lineIndex); @@ -43,6 +44,8 @@ class Tool_figuredbass : public HumTool { string formatFiguredBassNumbers(vector numbers, bool nonCompoundIntervalsQ, bool noAccidentalsQ, bool sortQ); + string getKeySignature(HumdrumFile& infile, int lineIndex); + // protected: private: diff --git a/src/tool-figuredbass.cpp b/src/tool-figuredbass.cpp index 99d8e672..2b0591bf 100644 --- a/src/tool-figuredbass.cpp +++ b/src/tool-figuredbass.cpp @@ -76,12 +76,13 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { } } NoteCell* baseCell = grid.cell(usedBaseVoiceIndex, i); + string keySignature = getKeySignature(infile, baseCell->getLineIndex()); for (int j=0; j<(int)grid.getVoiceCount(); j++) { if(j == usedBaseVoiceIndex) { continue; } NoteCell* targetCell = grid.cell(j, i); - FiguredBassNumber* number = createFiguredBassNumber(baseCell, targetCell); + FiguredBassNumber* number = createFiguredBassNumber(baseCell, targetCell, keySignature); numbers.push_back(number); } } @@ -138,15 +139,28 @@ vector Tool_figuredbass::getTrackDataForVoice(int voiceIndex, vectorgetSgnDiatonicPitch(); int targetPitch = target->getSgnDiatonicPitch(); int num = (basePitch == 0 || targetPitch == 0) ? 0 : abs(abs(targetPitch) - abs(basePitch)) + 1; - regex keepAccid("^\\(?\\w+([^\\w\\)]*)\\)?$"); - string accid = regex_replace(target->getSgnKernPitch(), keepAccid, "$1"); - FiguredBassNumber* number = new FiguredBassNumber(num, accid, target->getVoiceIndex(), target->getLineIndex()); + bool showAccid = false; + regex accidRegex("^\\(?(\\w)+([^\\w\\)]*)\\)?$"); + string accid = regex_replace(target->getSgnKernPitch(), accidRegex, "$2"); + + string accidWithPitch = regex_replace(target->getSgnKernPitch(), accidRegex, "$1$2"); + transform(accidWithPitch.begin(), accidWithPitch.end(), accidWithPitch.begin(), [](unsigned char c) { + return tolower(c); + }); + transform(keySignature.begin(), keySignature.end(), keySignature.begin(), [](unsigned char c) { + return tolower(c); + }); + if(accid.length() && keySignature.find(accidWithPitch) == std::string::npos) { + showAccid = true; + } + + FiguredBassNumber* number = new FiguredBassNumber(num, accid, showAccid, target->getVoiceIndex(), target->getLineIndex()); return number; }; @@ -201,16 +215,35 @@ string Tool_figuredbass::formatFiguredBassNumbers(vector num return str; }; -FiguredBassNumber::FiguredBassNumber(int num, string accid, int voiceIdx, int lineIdx) { +string Tool_figuredbass::getKeySignature(HumdrumFile& infile, int lineIndex) { + string keySignature = ""; + [&] { + for (int i = 0; i < infile.getLineCount(); i++) { + if(i > lineIndex) { + return; + } + HLp line = infile.getLine(i); + for (int j = 0; j < line->getFieldCount(); j++) { + if (line->token(j)->isKeySignature()) { + keySignature = line->getTokenString(j); + } + } + } + }(); + return keySignature; +}; + +FiguredBassNumber::FiguredBassNumber(int num, string accid, bool showAccid, int voiceIdx, int lineIdx) { number = num; accidentals = accid; voiceIndex = voiceIdx; lineIndex = lineIdx; + showAccidentals = showAccid; }; string FiguredBassNumber::toString(bool compoundQ, bool accidentalsQ) { int num = (compoundQ) ? getNumberB7() : number; - string accid = (accidentalsQ) ? accidentals : ""; + string accid = (accidentalsQ && showAccidentals) ? accidentals : ""; return num > 0 ? to_string(num) + accid : ""; }; From d73e246139ccb4cd48d963113f01f90d22cf354c Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Mon, 28 Nov 2022 22:51:38 +0100 Subject: [PATCH 016/109] Add feature to normalize figured bass numbers Remove octave and doubled intervals, use compound interval, sort intervals --- include/tool-figuredbass.h | 7 ++++--- src/tool-figuredbass.cpp | 42 +++++++++++++++++++++++++++++--------- 2 files changed, 36 insertions(+), 13 deletions(-) diff --git a/include/tool-figuredbass.h b/include/tool-figuredbass.h index b06a25ad..b1acd890 100644 --- a/include/tool-figuredbass.h +++ b/include/tool-figuredbass.h @@ -32,9 +32,9 @@ class Tool_figuredbass : public HumTool { bool run (const string& indata, ostream& out); bool run (HumdrumFile& infile, ostream& out); - vector getTrackData(vector numbers, int lineCount, bool nonCompoundIntervalsQ, bool noAccidentalsQ, bool sortQ); + vector getTrackData(vector numbers, int lineCount, bool nonCompoundIntervalsQ, bool noAccidentalsQ, bool sortQ, bool normalizeQ); - vector getTrackDataForVoice(int voiceIndex, vector numbers, int lineCount, bool nonCompoundIntervalsQ, bool noAccidentalsQ, bool sortQ); + vector getTrackDataForVoice(int voiceIndex, vector numbers, int lineCount, bool nonCompoundIntervalsQ, bool noAccidentalsQ, bool sortQ, bool normalizeQ); FiguredBassNumber* createFiguredBassNumber(NoteCell* base, NoteCell* target, string keySignature); @@ -42,7 +42,7 @@ class Tool_figuredbass : public HumTool { vector filterFiguredBassNumbersForLineAndVoice(vector, int lineIndex, int voiceIndex); - string formatFiguredBassNumbers(vector numbers, bool nonCompoundIntervalsQ, bool noAccidentalsQ, bool sortQ); + string formatFiguredBassNumbers(vector numbers, bool nonCompoundIntervalsQ, bool noAccidentalsQ, bool sortQ, bool normalizeQ); string getKeySignature(HumdrumFile& infile, int lineIndex); @@ -55,6 +55,7 @@ class Tool_figuredbass : public HumTool { bool intervallsatzQ = false; bool sortQ = false; bool lowestQ = false; + bool normalizeQ = false; }; diff --git a/src/tool-figuredbass.cpp b/src/tool-figuredbass.cpp index 2b0591bf..8f4f7de9 100644 --- a/src/tool-figuredbass.cpp +++ b/src/tool-figuredbass.cpp @@ -16,6 +16,7 @@ Tool_figuredbass::Tool_figuredbass(void) { define("i|intervallsatz=b", "display intervals under their voice and not under the lowest staff"); define("s|sort=b", "sort figured bass numbers by interval size and not by voice index"); define("l|lowest=b", "use lowest note as base note; -b flag will be ignored"); + define("n|normalize=b", "Remove octave and doubled intervals, use compound interval, sort intervals"); } bool Tool_figuredbass::run(HumdrumFileSet &infiles) { @@ -55,6 +56,12 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { intervallsatzQ = getBoolean("intervallsatz"); sortQ = getBoolean("sort"); lowestQ = getBoolean("lowest"); + normalizeQ = getBoolean("normalize"); + + if(normalizeQ) { + compoundQ = true; + sortQ = true; + } NoteGrid grid(infile); @@ -89,7 +96,7 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { if(intervallsatzQ) { for (int voiceIndex = 0; voiceIndex < grid.getVoiceCount(); voiceIndex++) { - vector trackData = getTrackDataForVoice(voiceIndex, numbers, infile.getLineCount(), compoundQ, accidentalsQ, sortQ); + vector trackData = getTrackDataForVoice(voiceIndex, numbers, infile.getLineCount(), compoundQ, accidentalsQ, sortQ, normalizeQ); if(voiceIndex + 1 < grid.getVoiceCount()) { int trackIndex = kernspines[voiceIndex + 1]->getTrack(); infile.insertDataSpineBefore(trackIndex, trackData, ".", "**fb"); @@ -99,7 +106,7 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { } } } else { - vector trackData = getTrackData(numbers, infile.getLineCount(), compoundQ, accidentalsQ, sortQ); + vector trackData = getTrackData(numbers, infile.getLineCount(), compoundQ, accidentalsQ, sortQ, normalizeQ); if(baseQ + 1 < grid.getVoiceCount()) { int trackIndex = kernspines[baseQ + 1]->getTrack(); infile.insertDataSpineBefore(trackIndex, trackData, ".", "**fb"); @@ -111,28 +118,28 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { return true; }; -vector Tool_figuredbass::getTrackData(vector numbers, int lineCount, bool compoundQ, bool accidentalsQ, bool sortQ) { +vector Tool_figuredbass::getTrackData(vector numbers, int lineCount, bool compoundQ, bool accidentalsQ, bool sortQ, bool normalizeQ) { vector trackData; trackData.resize(lineCount); for (int i = 0; i < lineCount; i++) { vector sliceNumbers = filterFiguredBassNumbersForLine(numbers, i); if(sliceNumbers.size() > 0) { - trackData[i] = formatFiguredBassNumbers(sliceNumbers, compoundQ, accidentalsQ, sortQ); + trackData[i] = formatFiguredBassNumbers(sliceNumbers, compoundQ, accidentalsQ, sortQ, normalizeQ); } } return trackData; }; -vector Tool_figuredbass::getTrackDataForVoice(int voiceIndex, vector numbers, int lineCount, bool compoundQ, bool accidentalsQ, bool sortQ) { +vector Tool_figuredbass::getTrackDataForVoice(int voiceIndex, vector numbers, int lineCount, bool compoundQ, bool accidentalsQ, bool sortQ, bool normalizeQ) { vector trackData; trackData.resize(lineCount); for (int i = 0; i < lineCount; i++) { vector sliceNumbers = filterFiguredBassNumbersForLineAndVoice(numbers, i, voiceIndex); if(sliceNumbers.size() > 0) { - trackData[i] = formatFiguredBassNumbers(sliceNumbers, compoundQ, accidentalsQ, sortQ); + trackData[i] = formatFiguredBassNumbers(sliceNumbers, compoundQ, accidentalsQ, sortQ, normalizeQ); } } @@ -195,16 +202,31 @@ vector Tool_figuredbass::filterFiguredBassNumbersForLineAndV return filteredNumbers; }; -string Tool_figuredbass::formatFiguredBassNumbers(vector numbers, bool compoundQ, bool accidentalsQ, bool sortQ) { +string Tool_figuredbass::formatFiguredBassNumbers(vector numbers, bool compoundQ, bool accidentalsQ, bool sortQ, bool normalizeQ) { + + vector normalizededNumbers; + + if(normalizeQ) { + copy_if(numbers.begin(), numbers.end(), back_inserter(normalizededNumbers), [](FiguredBassNumber* num) { + return num->getNumberB7() != 8 && num->getNumberB7() != 1; + }); + sort(normalizededNumbers.begin(), normalizededNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { + return a->getNumberB7() < b->getNumberB7(); + }); + normalizededNumbers.erase(unique(normalizededNumbers.begin(), normalizededNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) { + return a->getNumberB7() == b->getNumberB7(); + }), normalizededNumbers.end()); + } else { + normalizededNumbers = numbers; + } if(sortQ) { - sort(numbers.begin(), numbers.end(), [compoundQ](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { + sort(normalizededNumbers.begin(), normalizededNumbers.end(), [compoundQ](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { return (compoundQ) ? a->getNumberB7() > b->getNumberB7() : a->number > b->number; - }); } string str = ""; bool first = true; - for (FiguredBassNumber* number: numbers) { + for (FiguredBassNumber* number: normalizededNumbers) { string num = number->toString(compoundQ, accidentalsQ); if(num.length() > 0) { if (!first) str += " "; From deff304879aea5c7a0e89f5426774d4cf8091e49 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Tue, 29 Nov 2022 01:01:17 +0100 Subject: [PATCH 017/109] Add feature for abbreviated figures --- include/tool-figuredbass.h | 18 +++++-- src/tool-figuredbass.cpp | 96 +++++++++++++++++++++++++++++++++++--- 2 files changed, 104 insertions(+), 10 deletions(-) diff --git a/include/tool-figuredbass.h b/include/tool-figuredbass.h index b1acd890..e3b7abfc 100644 --- a/include/tool-figuredbass.h +++ b/include/tool-figuredbass.h @@ -21,6 +21,13 @@ class FiguredBassNumber { int getNumberB7(); }; +class FiguredBassAbbr { + public: + string str; + vector numbers; + FiguredBassAbbr(string s, vector n); +}; + class Tool_figuredbass : public HumTool { public: @@ -32,9 +39,9 @@ class Tool_figuredbass : public HumTool { bool run (const string& indata, ostream& out); bool run (HumdrumFile& infile, ostream& out); - vector getTrackData(vector numbers, int lineCount, bool nonCompoundIntervalsQ, bool noAccidentalsQ, bool sortQ, bool normalizeQ); + vector getTrackData(vector numbers, int lineCount, bool nonCompoundIntervalsQ, bool noAccidentalsQ, bool sortQ, bool normalizeQ, bool abbrQ); - vector getTrackDataForVoice(int voiceIndex, vector numbers, int lineCount, bool nonCompoundIntervalsQ, bool noAccidentalsQ, bool sortQ, bool normalizeQ); + vector getTrackDataForVoice(int voiceIndex, vector numbers, int lineCount, bool nonCompoundIntervalsQ, bool noAccidentalsQ, bool sortQ, bool normalizeQ, bool abbrQ); FiguredBassNumber* createFiguredBassNumber(NoteCell* base, NoteCell* target, string keySignature); @@ -42,7 +49,11 @@ class Tool_figuredbass : public HumTool { vector filterFiguredBassNumbersForLineAndVoice(vector, int lineIndex, int voiceIndex); - string formatFiguredBassNumbers(vector numbers, bool nonCompoundIntervalsQ, bool noAccidentalsQ, bool sortQ, bool normalizeQ); + string formatFiguredBassNumbers(vector numbers, bool nonCompoundIntervalsQ, bool noAccidentalsQ, bool sortQ, bool normalizeQ, bool abbrQ); + + vector getAbbrNumbers(vector); + + string getNumberString(vector numbers); string getKeySignature(HumdrumFile& infile, int lineIndex); @@ -56,6 +67,7 @@ class Tool_figuredbass : public HumTool { bool sortQ = false; bool lowestQ = false; bool normalizeQ = false; + bool abbrQ = false; }; diff --git a/src/tool-figuredbass.cpp b/src/tool-figuredbass.cpp index 8f4f7de9..99d66eee 100644 --- a/src/tool-figuredbass.cpp +++ b/src/tool-figuredbass.cpp @@ -17,6 +17,7 @@ Tool_figuredbass::Tool_figuredbass(void) { define("s|sort=b", "sort figured bass numbers by interval size and not by voice index"); define("l|lowest=b", "use lowest note as base note; -b flag will be ignored"); define("n|normalize=b", "Remove octave and doubled intervals, use compound interval, sort intervals"); + define("r|abbr=b", "Use abbreviated figures"); } bool Tool_figuredbass::run(HumdrumFileSet &infiles) { @@ -57,12 +58,25 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { sortQ = getBoolean("sort"); lowestQ = getBoolean("lowest"); normalizeQ = getBoolean("normalize"); + abbrQ = getBoolean("abbr"); + + if(abbrQ) { + normalizeQ = true; + } if(normalizeQ) { compoundQ = true; sortQ = true; } + if(false) { + compoundQ = true; + accidentalsQ = true; + sortQ = true; + lowestQ = true; + normalizeQ = true; + } + NoteGrid grid(infile); vector numbers; @@ -96,7 +110,7 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { if(intervallsatzQ) { for (int voiceIndex = 0; voiceIndex < grid.getVoiceCount(); voiceIndex++) { - vector trackData = getTrackDataForVoice(voiceIndex, numbers, infile.getLineCount(), compoundQ, accidentalsQ, sortQ, normalizeQ); + vector trackData = getTrackDataForVoice(voiceIndex, numbers, infile.getLineCount(), compoundQ, accidentalsQ, sortQ, normalizeQ, abbrQ); if(voiceIndex + 1 < grid.getVoiceCount()) { int trackIndex = kernspines[voiceIndex + 1]->getTrack(); infile.insertDataSpineBefore(trackIndex, trackData, ".", "**fb"); @@ -106,7 +120,7 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { } } } else { - vector trackData = getTrackData(numbers, infile.getLineCount(), compoundQ, accidentalsQ, sortQ, normalizeQ); + vector trackData = getTrackData(numbers, infile.getLineCount(), compoundQ, accidentalsQ, sortQ, normalizeQ, abbrQ); if(baseQ + 1 < grid.getVoiceCount()) { int trackIndex = kernspines[baseQ + 1]->getTrack(); infile.insertDataSpineBefore(trackIndex, trackData, ".", "**fb"); @@ -118,28 +132,28 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { return true; }; -vector Tool_figuredbass::getTrackData(vector numbers, int lineCount, bool compoundQ, bool accidentalsQ, bool sortQ, bool normalizeQ) { +vector Tool_figuredbass::getTrackData(vector numbers, int lineCount, bool compoundQ, bool accidentalsQ, bool sortQ, bool normalizeQ, bool abbrQ) { vector trackData; trackData.resize(lineCount); for (int i = 0; i < lineCount; i++) { vector sliceNumbers = filterFiguredBassNumbersForLine(numbers, i); if(sliceNumbers.size() > 0) { - trackData[i] = formatFiguredBassNumbers(sliceNumbers, compoundQ, accidentalsQ, sortQ, normalizeQ); + trackData[i] = formatFiguredBassNumbers(sliceNumbers, compoundQ, accidentalsQ, sortQ, normalizeQ, abbrQ); } } return trackData; }; -vector Tool_figuredbass::getTrackDataForVoice(int voiceIndex, vector numbers, int lineCount, bool compoundQ, bool accidentalsQ, bool sortQ, bool normalizeQ) { +vector Tool_figuredbass::getTrackDataForVoice(int voiceIndex, vector numbers, int lineCount, bool compoundQ, bool accidentalsQ, bool sortQ, bool normalizeQ, bool abbrQ) { vector trackData; trackData.resize(lineCount); for (int i = 0; i < lineCount; i++) { vector sliceNumbers = filterFiguredBassNumbersForLineAndVoice(numbers, i, voiceIndex); if(sliceNumbers.size() > 0) { - trackData[i] = formatFiguredBassNumbers(sliceNumbers, compoundQ, accidentalsQ, sortQ, normalizeQ); + trackData[i] = formatFiguredBassNumbers(sliceNumbers, compoundQ, accidentalsQ, sortQ, normalizeQ, abbrQ); } } @@ -202,7 +216,7 @@ vector Tool_figuredbass::filterFiguredBassNumbersForLineAndV return filteredNumbers; }; -string Tool_figuredbass::formatFiguredBassNumbers(vector numbers, bool compoundQ, bool accidentalsQ, bool sortQ, bool normalizeQ) { +string Tool_figuredbass::formatFiguredBassNumbers(vector numbers, bool compoundQ, bool accidentalsQ, bool sortQ, bool normalizeQ, bool abbrQ) { vector normalizededNumbers; @@ -219,11 +233,17 @@ string Tool_figuredbass::formatFiguredBassNumbers(vector num } else { normalizededNumbers = numbers; } + if(sortQ) { sort(normalizededNumbers.begin(), normalizededNumbers.end(), [compoundQ](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { return (compoundQ) ? a->getNumberB7() > b->getNumberB7() : a->number > b->number; }); } + + if(abbrQ) { + normalizededNumbers = getAbbrNumbers(normalizededNumbers); + } + string str = ""; bool first = true; for (FiguredBassNumber* number: normalizededNumbers) { @@ -237,6 +257,64 @@ string Tool_figuredbass::formatFiguredBassNumbers(vector num return str; }; +vector Tool_figuredbass::getAbbrNumbers(vector numbers) { + + vector abbrNumbers; + + vector figuredBassAbbrs = { + new FiguredBassAbbr("3", {}), + new FiguredBassAbbr("5", {}), + new FiguredBassAbbr("5 3", {}), + new FiguredBassAbbr("6 3", {6}), + new FiguredBassAbbr("5 4", {4}), + new FiguredBassAbbr("7 5 3", {7}), + new FiguredBassAbbr("7 3", {7}), + new FiguredBassAbbr("7 5", {7}), + new FiguredBassAbbr("6 5 3", {6, 5}), + new FiguredBassAbbr("6 4 3", {4, 3}), + new FiguredBassAbbr("6 4 2", {4, 2}), + new FiguredBassAbbr("9 5 3", {9}), + new FiguredBassAbbr("9 5", {9}), + new FiguredBassAbbr("9 3", {9}), + }; + + string numberString = getNumberString(numbers); + + auto it = find_if(figuredBassAbbrs.begin(), figuredBassAbbrs.end(), [numberString](FiguredBassAbbr* abbr) { + return abbr->str == numberString; + }); + + if (it != figuredBassAbbrs.end()) { + int index = it - figuredBassAbbrs.begin(); + FiguredBassAbbr* abbr = figuredBassAbbrs[index]; + copy_if(numbers.begin(), numbers.end(), back_inserter(abbrNumbers), [abbr](FiguredBassNumber* num) { + vector nums = abbr->numbers; + return find(nums.begin(), nums.end(), num->getNumberB7()) != nums.end(); + }); + + return abbrNumbers; + } + + return numbers; +}; + +string Tool_figuredbass::getNumberString(vector numbers) { + sort(numbers.begin(), numbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { + return a->getNumberB7() > b->getNumberB7(); + }); + string str = ""; + bool first = true; + for (FiguredBassNumber* nr: numbers) { + int num = nr->getNumberB7(); + if(num > 0) { + if (!first) str += " "; + first = false; + str += to_string(num); + } + } + return str; +}; + string Tool_figuredbass::getKeySignature(HumdrumFile& infile, int lineIndex) { string keySignature = ""; [&] { @@ -274,6 +352,10 @@ int FiguredBassNumber::getNumberB7() { return (number > 8 && num == 1) ? 8 : num; }; +FiguredBassAbbr::FiguredBassAbbr(string s, vector n) { + str = s; + numbers = n; +}; // END_MERGE From f1f049e612c157ec1d1d0295c7be04b623632723 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Tue, 29 Nov 2022 01:09:43 +0100 Subject: [PATCH 018/109] Remove unused if section --- src/tool-figuredbass.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/tool-figuredbass.cpp b/src/tool-figuredbass.cpp index 99d66eee..35be5992 100644 --- a/src/tool-figuredbass.cpp +++ b/src/tool-figuredbass.cpp @@ -69,14 +69,6 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { sortQ = true; } - if(false) { - compoundQ = true; - accidentalsQ = true; - sortQ = true; - lowestQ = true; - normalizeQ = true; - } - NoteGrid grid(infile); vector numbers; From 6565197621f1fa1f7532e5186731cf5d3578a6fc Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Tue, 29 Nov 2022 01:10:20 +0100 Subject: [PATCH 019/109] Remove option flags as parameters --- include/tool-figuredbass.h | 6 +++--- src/tool-figuredbass.cpp | 19 ++++++++++--------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/include/tool-figuredbass.h b/include/tool-figuredbass.h index e3b7abfc..83858cf6 100644 --- a/include/tool-figuredbass.h +++ b/include/tool-figuredbass.h @@ -39,9 +39,9 @@ class Tool_figuredbass : public HumTool { bool run (const string& indata, ostream& out); bool run (HumdrumFile& infile, ostream& out); - vector getTrackData(vector numbers, int lineCount, bool nonCompoundIntervalsQ, bool noAccidentalsQ, bool sortQ, bool normalizeQ, bool abbrQ); + vector getTrackData(vector numbers, int lineCount); - vector getTrackDataForVoice(int voiceIndex, vector numbers, int lineCount, bool nonCompoundIntervalsQ, bool noAccidentalsQ, bool sortQ, bool normalizeQ, bool abbrQ); + vector getTrackDataForVoice(int voiceIndex, vector numbers, int lineCount); FiguredBassNumber* createFiguredBassNumber(NoteCell* base, NoteCell* target, string keySignature); @@ -49,7 +49,7 @@ class Tool_figuredbass : public HumTool { vector filterFiguredBassNumbersForLineAndVoice(vector, int lineIndex, int voiceIndex); - string formatFiguredBassNumbers(vector numbers, bool nonCompoundIntervalsQ, bool noAccidentalsQ, bool sortQ, bool normalizeQ, bool abbrQ); + string formatFiguredBassNumbers(vector numbers); vector getAbbrNumbers(vector); diff --git a/src/tool-figuredbass.cpp b/src/tool-figuredbass.cpp index 35be5992..b9d87e50 100644 --- a/src/tool-figuredbass.cpp +++ b/src/tool-figuredbass.cpp @@ -102,7 +102,7 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { if(intervallsatzQ) { for (int voiceIndex = 0; voiceIndex < grid.getVoiceCount(); voiceIndex++) { - vector trackData = getTrackDataForVoice(voiceIndex, numbers, infile.getLineCount(), compoundQ, accidentalsQ, sortQ, normalizeQ, abbrQ); + vector trackData = getTrackDataForVoice(voiceIndex, numbers, infile.getLineCount()); if(voiceIndex + 1 < grid.getVoiceCount()) { int trackIndex = kernspines[voiceIndex + 1]->getTrack(); infile.insertDataSpineBefore(trackIndex, trackData, ".", "**fb"); @@ -112,7 +112,7 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { } } } else { - vector trackData = getTrackData(numbers, infile.getLineCount(), compoundQ, accidentalsQ, sortQ, normalizeQ, abbrQ); + vector trackData = getTrackData(numbers, infile.getLineCount()); if(baseQ + 1 < grid.getVoiceCount()) { int trackIndex = kernspines[baseQ + 1]->getTrack(); infile.insertDataSpineBefore(trackIndex, trackData, ".", "**fb"); @@ -124,28 +124,28 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { return true; }; -vector Tool_figuredbass::getTrackData(vector numbers, int lineCount, bool compoundQ, bool accidentalsQ, bool sortQ, bool normalizeQ, bool abbrQ) { +vector Tool_figuredbass::getTrackData(vector numbers, int lineCount) { vector trackData; trackData.resize(lineCount); for (int i = 0; i < lineCount; i++) { vector sliceNumbers = filterFiguredBassNumbersForLine(numbers, i); if(sliceNumbers.size() > 0) { - trackData[i] = formatFiguredBassNumbers(sliceNumbers, compoundQ, accidentalsQ, sortQ, normalizeQ, abbrQ); + trackData[i] = formatFiguredBassNumbers(sliceNumbers); } } return trackData; }; -vector Tool_figuredbass::getTrackDataForVoice(int voiceIndex, vector numbers, int lineCount, bool compoundQ, bool accidentalsQ, bool sortQ, bool normalizeQ, bool abbrQ) { +vector Tool_figuredbass::getTrackDataForVoice(int voiceIndex, vector numbers, int lineCount) { vector trackData; trackData.resize(lineCount); for (int i = 0; i < lineCount; i++) { vector sliceNumbers = filterFiguredBassNumbersForLineAndVoice(numbers, i, voiceIndex); if(sliceNumbers.size() > 0) { - trackData[i] = formatFiguredBassNumbers(sliceNumbers, compoundQ, accidentalsQ, sortQ, normalizeQ, abbrQ); + trackData[i] = formatFiguredBassNumbers(sliceNumbers); } } @@ -208,7 +208,7 @@ vector Tool_figuredbass::filterFiguredBassNumbersForLineAndV return filteredNumbers; }; -string Tool_figuredbass::formatFiguredBassNumbers(vector numbers, bool compoundQ, bool accidentalsQ, bool sortQ, bool normalizeQ, bool abbrQ) { +string Tool_figuredbass::formatFiguredBassNumbers(vector numbers) { vector normalizededNumbers; @@ -227,8 +227,9 @@ string Tool_figuredbass::formatFiguredBassNumbers(vector num } if(sortQ) { - sort(normalizededNumbers.begin(), normalizededNumbers.end(), [compoundQ](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { - return (compoundQ) ? a->getNumberB7() > b->getNumberB7() : a->number > b->number; + bool cQ = compoundQ; + sort(normalizededNumbers.begin(), normalizededNumbers.end(), [cQ](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { + return (cQ) ? a->getNumberB7() > b->getNumberB7() : a->number > b->number; }); } From 31703c4805e60d8409af45d76d341a512a54a2db Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Tue, 29 Nov 2022 01:25:34 +0100 Subject: [PATCH 020/109] Fix missing accidentals for abbreviated figures --- src/tool-figuredbass.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/tool-figuredbass.cpp b/src/tool-figuredbass.cpp index b9d87e50..d1ee42a7 100644 --- a/src/tool-figuredbass.cpp +++ b/src/tool-figuredbass.cpp @@ -280,9 +280,10 @@ vector Tool_figuredbass::getAbbrNumbers(vector nums = abbr->numbers; - return find(nums.begin(), nums.end(), num->getNumberB7()) != nums.end(); + return find(nums.begin(), nums.end(), num->getNumberB7()) != nums.end() || (num->showAccidentals && aQ); }); return abbrNumbers; From 7b364745a30dedd2ee5c7734cb6b6f4296503568 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Tue, 29 Nov 2022 01:38:22 +0100 Subject: [PATCH 021/109] Fix missing accidentals for octaves and unisons --- src/tool-figuredbass.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/tool-figuredbass.cpp b/src/tool-figuredbass.cpp index d1ee42a7..1b54e1db 100644 --- a/src/tool-figuredbass.cpp +++ b/src/tool-figuredbass.cpp @@ -213,8 +213,9 @@ string Tool_figuredbass::formatFiguredBassNumbers(vector num vector normalizededNumbers; if(normalizeQ) { - copy_if(numbers.begin(), numbers.end(), back_inserter(normalizededNumbers), [](FiguredBassNumber* num) { - return num->getNumberB7() != 8 && num->getNumberB7() != 1; + bool aQ = accidentalsQ; + copy_if(numbers.begin(), numbers.end(), back_inserter(normalizededNumbers), [aQ](FiguredBassNumber* num) { + return (num->getNumberB7() != 8 && num->getNumberB7() != 1) || (aQ && num->showAccidentals); }); sort(normalizededNumbers.begin(), normalizededNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { return a->getNumberB7() < b->getNumberB7(); From eef094d979c771a4c77b7d7bd0e08b39f4e94e98 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Tue, 29 Nov 2022 10:41:02 +0100 Subject: [PATCH 022/109] Fix missing 7 --- src/tool-figuredbass.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tool-figuredbass.cpp b/src/tool-figuredbass.cpp index 1b54e1db..4f85a91e 100644 --- a/src/tool-figuredbass.cpp +++ b/src/tool-figuredbass.cpp @@ -344,6 +344,9 @@ string FiguredBassNumber::toString(bool compoundQ, bool accidentalsQ) { int FiguredBassNumber::getNumberB7() { int num = (number > 9) ? number % 7 : number; + if(number > 9 && number % 7 == 0) { + num = 7; + } return (number > 8 && num == 1) ? 8 : num; }; From bd9c99fed6352748920319cca56fbf07532da015 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Tue, 29 Nov 2022 10:52:51 +0100 Subject: [PATCH 023/109] Improve text --- src/tool-figuredbass.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tool-figuredbass.cpp b/src/tool-figuredbass.cpp index 4f85a91e..9d4e79cb 100644 --- a/src/tool-figuredbass.cpp +++ b/src/tool-figuredbass.cpp @@ -16,8 +16,8 @@ Tool_figuredbass::Tool_figuredbass(void) { define("i|intervallsatz=b", "display intervals under their voice and not under the lowest staff"); define("s|sort=b", "sort figured bass numbers by interval size and not by voice index"); define("l|lowest=b", "use lowest note as base note; -b flag will be ignored"); - define("n|normalize=b", "Remove octave and doubled intervals, use compound interval, sort intervals"); - define("r|abbr=b", "Use abbreviated figures"); + define("n|normalize=b", "remove octave and doubled intervals, use compound interval, sort intervals"); + define("r|abbr=b", "use abbreviated figures"); } bool Tool_figuredbass::run(HumdrumFileSet &infiles) { From 0591008df4e41d51a3c2f73def0594e4292d83fe Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Tue, 29 Nov 2022 13:41:57 +0100 Subject: [PATCH 024/109] Add feature to hide intervals when they are sustained and the base is not changing --- include/tool-figuredbass.h | 5 ++++- src/tool-figuredbass.cpp | 26 ++++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/include/tool-figuredbass.h b/include/tool-figuredbass.h index 83858cf6..1ce95e6d 100644 --- a/include/tool-figuredbass.h +++ b/include/tool-figuredbass.h @@ -16,7 +16,9 @@ class FiguredBassNumber { int number; string accidentals; bool showAccidentals; - FiguredBassNumber(int num, string accid, bool showAccid, int voiceIndex, int lineIndex); + bool currAttackNumberDidChange; + bool isAttack; + FiguredBassNumber(int num, string accid, bool showAccid, int voiceIndex, int lineIndex, bool isAttack); string toString(bool nonCompoundIntervalsQ, bool noAccidentalsQ); int getNumberB7(); }; @@ -68,6 +70,7 @@ class Tool_figuredbass : public HumTool { bool lowestQ = false; bool normalizeQ = false; bool abbrQ = false; + bool attackQ = false; }; diff --git a/src/tool-figuredbass.cpp b/src/tool-figuredbass.cpp index 9d4e79cb..37c905f6 100644 --- a/src/tool-figuredbass.cpp +++ b/src/tool-figuredbass.cpp @@ -18,6 +18,7 @@ Tool_figuredbass::Tool_figuredbass(void) { define("l|lowest=b", "use lowest note as base note; -b flag will be ignored"); define("n|normalize=b", "remove octave and doubled intervals, use compound interval, sort intervals"); define("r|abbr=b", "use abbreviated figures"); + define("t|attack=b", "hide intervalls with no attack and when base does not change"); } bool Tool_figuredbass::run(HumdrumFileSet &infiles) { @@ -59,6 +60,7 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { lowestQ = getBoolean("lowest"); normalizeQ = getBoolean("normalize"); abbrQ = getBoolean("abbr"); + attackQ = getBoolean("attack"); if(abbrQ) { normalizeQ = true; @@ -75,7 +77,13 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { vector kernspines = infile.getKernSpineStartList(); + vector lastNumbers = {}; + lastNumbers.resize(3); + vector currentNumbers = {}; + for (int i=0; i<(int)grid.getSliceCount(); i++) { + currentNumbers.clear(); + currentNumbers.resize(3); int usedBaseVoiceIndex = baseQ; if(lowestQ) { int lowestNotePitch = 99999; @@ -96,8 +104,13 @@ bool Tool_figuredbass::run(HumdrumFile &infile) { } NoteCell* targetCell = grid.cell(j, i); FiguredBassNumber* number = createFiguredBassNumber(baseCell, targetCell, keySignature); + if(lastNumbers[j] != 0) { + number->currAttackNumberDidChange = targetCell->isSustained() && lastNumbers[j] != number->number; + } + currentNumbers[j] = number->number; numbers.push_back(number); } + lastNumbers = currentNumbers; } if(intervallsatzQ) { @@ -173,7 +186,7 @@ FiguredBassNumber* Tool_figuredbass::createFiguredBassNumber(NoteCell* base, Not showAccid = true; } - FiguredBassNumber* number = new FiguredBassNumber(num, accid, showAccid, target->getVoiceIndex(), target->getLineIndex()); + FiguredBassNumber* number = new FiguredBassNumber(num, accid, showAccid, target->getVoiceIndex(), target->getLineIndex(), target->isAttack()); return number; }; @@ -227,6 +240,14 @@ string Tool_figuredbass::formatFiguredBassNumbers(vector num normalizededNumbers = numbers; } + if(intervallsatzQ && attackQ) { + vector attackNumbers; + copy_if(normalizededNumbers.begin(), normalizededNumbers.end(), back_inserter(attackNumbers), [](FiguredBassNumber* num) { + return num->isAttack || num->currAttackNumberDidChange; + }); + normalizededNumbers = attackNumbers; + } + if(sortQ) { bool cQ = compoundQ; sort(normalizededNumbers.begin(), normalizededNumbers.end(), [cQ](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { @@ -328,12 +349,13 @@ string Tool_figuredbass::getKeySignature(HumdrumFile& infile, int lineIndex) { return keySignature; }; -FiguredBassNumber::FiguredBassNumber(int num, string accid, bool showAccid, int voiceIdx, int lineIdx) { +FiguredBassNumber::FiguredBassNumber(int num, string accid, bool showAccid, int voiceIdx, int lineIdx, bool isAtk) { number = num; accidentals = accid; voiceIndex = voiceIdx; lineIndex = lineIdx; showAccidentals = showAccid; + isAttack = isAtk; }; string FiguredBassNumber::toString(bool compoundQ, bool accidentalsQ) { From 8114128c9af2a717492eab870a33b3daf8da3bbf Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Thu, 22 Dec 2022 23:31:09 +0100 Subject: [PATCH 025/109] Fix indentation --- src/tool-figuredbass.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/tool-figuredbass.cpp b/src/tool-figuredbass.cpp index 37c905f6..910309cb 100644 --- a/src/tool-figuredbass.cpp +++ b/src/tool-figuredbass.cpp @@ -24,7 +24,7 @@ Tool_figuredbass::Tool_figuredbass(void) { bool Tool_figuredbass::run(HumdrumFileSet &infiles) { bool status = true; for (int i = 0; i < infiles.getCount(); i++) { - status &= run(infiles[i]); + status &= run(infiles[i]); } return status; } @@ -33,9 +33,9 @@ bool Tool_figuredbass::run(const string &indata, ostream &out) { HumdrumFile infile(indata); bool status = run(infile); if (hasAnyText()) { - getAllText(out); + getAllText(out); } else { - out << infile; + out << infile; } return status; } @@ -43,9 +43,9 @@ bool Tool_figuredbass::run(const string &indata, ostream &out) { bool Tool_figuredbass::run(HumdrumFile &infile, ostream &out) { bool status = run(infile); if (hasAnyText()) { - getAllText(out); + getAllText(out); } else { - out << infile; + out << infile; } return status; } @@ -183,7 +183,7 @@ FiguredBassNumber* Tool_figuredbass::createFiguredBassNumber(NoteCell* base, Not return tolower(c); }); if(accid.length() && keySignature.find(accidWithPitch) == std::string::npos) { - showAccid = true; + showAccid = true; } FiguredBassNumber* number = new FiguredBassNumber(num, accid, showAccid, target->getVoiceIndex(), target->getLineIndex(), target->isAttack()); @@ -200,7 +200,7 @@ vector Tool_figuredbass::filterFiguredBassNumbersForLine(vec }); sort(filteredNumbers.begin(), filteredNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { - return a->voiceIndex > b->voiceIndex; + return a->voiceIndex > b->voiceIndex; }); return filteredNumbers; @@ -215,7 +215,7 @@ vector Tool_figuredbass::filterFiguredBassNumbersForLineAndV }); sort(filteredNumbers.begin(), filteredNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { - return a->voiceIndex > b->voiceIndex; + return a->voiceIndex > b->voiceIndex; }); return filteredNumbers; From b96d656dd50b9cfc5c471972192ddb8aac532c80 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Thu, 22 Dec 2022 23:37:32 +0100 Subject: [PATCH 026/109] Align variable values --- src/tool-figuredbass.cpp | 46 ++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/tool-figuredbass.cpp b/src/tool-figuredbass.cpp index 910309cb..ec062cf8 100644 --- a/src/tool-figuredbass.cpp +++ b/src/tool-figuredbass.cpp @@ -10,15 +10,15 @@ namespace hum { // START_MERGE Tool_figuredbass::Tool_figuredbass(void) { - define("c|compound=b", "output compound intervals for intervals bigger than 9"); - define("a|accidentals=b", "display accidentals in figured bass output"); - define("b|base=i:0", "number of the base voice/spine"); + define("c|compound=b", "output compound intervals for intervals bigger than 9"); + define("a|accidentals=b", "display accidentals in figured bass output"); + define("b|base=i:0", "number of the base voice/spine"); define("i|intervallsatz=b", "display intervals under their voice and not under the lowest staff"); - define("s|sort=b", "sort figured bass numbers by interval size and not by voice index"); - define("l|lowest=b", "use lowest note as base note; -b flag will be ignored"); - define("n|normalize=b", "remove octave and doubled intervals, use compound interval, sort intervals"); - define("r|abbr=b", "use abbreviated figures"); - define("t|attack=b", "hide intervalls with no attack and when base does not change"); + define("s|sort=b", "sort figured bass numbers by interval size and not by voice index"); + define("l|lowest=b", "use lowest note as base note; -b flag will be ignored"); + define("n|normalize=b", "remove octave and doubled intervals, use compound interval, sort intervals"); + define("r|abbr=b", "use abbreviated figures"); + define("t|attack=b", "hide intervalls with no attack and when base does not change"); } bool Tool_figuredbass::run(HumdrumFileSet &infiles) { @@ -52,15 +52,15 @@ bool Tool_figuredbass::run(HumdrumFile &infile, ostream &out) { bool Tool_figuredbass::run(HumdrumFile &infile) { - compoundQ = getBoolean("compound"); - accidentalsQ = getBoolean("accidentals"); - baseQ = getInteger("base"); + compoundQ = getBoolean("compound"); + accidentalsQ = getBoolean("accidentals"); + baseQ = getInteger("base"); intervallsatzQ = getBoolean("intervallsatz"); - sortQ = getBoolean("sort"); - lowestQ = getBoolean("lowest"); - normalizeQ = getBoolean("normalize"); - abbrQ = getBoolean("abbr"); - attackQ = getBoolean("attack"); + sortQ = getBoolean("sort"); + lowestQ = getBoolean("lowest"); + normalizeQ = getBoolean("normalize"); + abbrQ = getBoolean("abbr"); + attackQ = getBoolean("attack"); if(abbrQ) { normalizeQ = true; @@ -167,9 +167,9 @@ vector Tool_figuredbass::getTrackDataForVoice(int voiceIndex, vectorgetSgnDiatonicPitch(); + int basePitch = base->getSgnDiatonicPitch(); int targetPitch = target->getSgnDiatonicPitch(); - int num = (basePitch == 0 || targetPitch == 0) ? 0 : abs(abs(targetPitch) - abs(basePitch)) + 1; + int num = (basePitch == 0 || targetPitch == 0) ? 0 : abs(abs(targetPitch) - abs(basePitch)) + 1; bool showAccid = false; regex accidRegex("^\\(?(\\w)+([^\\w\\)]*)\\)?$"); @@ -350,12 +350,12 @@ string Tool_figuredbass::getKeySignature(HumdrumFile& infile, int lineIndex) { }; FiguredBassNumber::FiguredBassNumber(int num, string accid, bool showAccid, int voiceIdx, int lineIdx, bool isAtk) { - number = num; - accidentals = accid; - voiceIndex = voiceIdx; - lineIndex = lineIdx; + number = num; + accidentals = accid; + voiceIndex = voiceIdx; + lineIndex = lineIdx; showAccidentals = showAccid; - isAttack = isAtk; + isAttack = isAtk; }; string FiguredBassNumber::toString(bool compoundQ, bool accidentalsQ) { From fbaeee003b90f3f16c3710be706d41fcaf6eb5a5 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Fri, 23 Dec 2022 00:31:48 +0100 Subject: [PATCH 027/109] Rename figuredbass command to fb --- CMakeLists.txt | 4 +- Makefile | 4 +- cli/figuredbass.cpp | 3 - include/tool-fb.h | 102 ++++--- include/tool-figuredbass.h | 81 ------ src/tool-fb.cpp | 582 ++++++++++++++++++------------------- src/tool-figuredbass.cpp | 382 ------------------------ src/tool-filter.cpp | 6 +- 8 files changed, 352 insertions(+), 812 deletions(-) delete mode 100644 cli/figuredbass.cpp delete mode 100644 include/tool-figuredbass.h delete mode 100644 src/tool-figuredbass.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 099f1433..6e3a7137 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -89,7 +89,7 @@ set(SRCS src/tool-dissonant.cpp src/tool-esac2hum.cpp src/tool-extract.cpp - src/tool-figuredbass.cpp + src/tool-fb.cpp src/tool-filter.cpp src/tool-hproof.cpp src/tool-imitation.cpp @@ -149,7 +149,7 @@ set(HDRS include/tool-dissonant.h include/tool-esac2hum.h include/tool-extract.h - include/tool-figuredbass.h + include/tool-fb.h include/tool-hproof.h include/tool-imitation.h include/tool-mei2hum.h diff --git a/Makefile b/Makefile index ed4301b2..6028d96a 100644 --- a/Makefile +++ b/Makefile @@ -621,7 +621,7 @@ tool-extract.o: tool-extract.cpp tool-extract.h \ HumHash.h HumParamSet.h HumdrumFileStream.h \ HumRegex.h -tool-figuredbass.o: tool-figuredbass.cpp tool-figuredbass.h \ +tool-fb.o: tool-fb.cpp tool-fb.h \ HumTool.h Options.h HumdrumFileSet.h \ HumdrumFile.h HumdrumFileContent.h \ HumdrumFileStructure.h HumdrumFileBase.h \ @@ -642,7 +642,7 @@ tool-filter.o: tool-filter.cpp tool-filter.h \ tool-chooser.h tool-chord.h tool-cint.h \ NoteGrid.h NoteCell.h HumRegex.h \ tool-composite.h tool-dissonant.h \ - tool-extract.h tool-figuredbass.h tool-homorhythm.h \ + tool-extract.h tool-fb.h tool-homorhythm.h \ tool-homorhythm2.h tool-hproof.h \ tool-humdiff.h tool-shed.h tool-imitation.h \ tool-kern2mens.h tool-melisma.h tool-metlev.h \ diff --git a/cli/figuredbass.cpp b/cli/figuredbass.cpp deleted file mode 100644 index b8c864ca..00000000 --- a/cli/figuredbass.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "humlib.h" - -STREAM_INTERFACE(Tool_figuredbass) diff --git a/include/tool-fb.h b/include/tool-fb.h index ea2cd47c..6df81eeb 100644 --- a/include/tool-fb.h +++ b/include/tool-fb.h @@ -1,57 +1,76 @@ -// -// Programmer: Craig Stuart Sapp -// Creation Date: Wed Mar 9 21:50:25 PST 2022 -// Last Modified: Wed Mar 9 21:50:28 PST 2022 -// Filename: tool-fb.h -// URL: https://github.com/craigsapp/humlib/blob/master/include/tool-fb.h -// Syntax: C++11; humlib -// vim: ts=3 noexpandtab -// -// Description: Extract figured bass numbers from musical content. -// Reference: https://github.com/WolfgangDrescher/humdrum-figured-bass-filter-demo -// - #ifndef _TOOL_FB_H #define _TOOL_FB_H #include "HumTool.h" #include "HumdrumFile.h" +#include "NoteGrid.h" namespace hum { // START_MERGE +class FiguredBassNumber { + public: + int voiceIndex; + int lineIndex; + int number; + string accidentals; + bool showAccidentals; + bool currAttackNumberDidChange; + bool isAttack; + FiguredBassNumber(int num, string accid, bool showAccid, int voiceIndex, int lineIndex, bool isAttack); + string toString(bool nonCompoundIntervalsQ, bool noAccidentalsQ); + int getNumberB7(); +}; + +class FiguredBassAbbr { + public: + string str; + vector numbers; + FiguredBassAbbr(string s, vector n); +}; + class Tool_fb : public HumTool { + public: - Tool_fb (void); - ~Tool_fb () {}; - - bool run (HumdrumFileSet& infiles); - bool run (HumdrumFile& infile); - bool run (const string& indata, ostream& out); - bool run (HumdrumFile& infile, ostream& out); - - protected: - void processFile (HumdrumFile& infile); - void initialize (void); - void processLine (HumdrumFile& infile, int index); - void setupScoreData (HumdrumFile& infile); - void getAnalyses (HumdrumFile& infile); - void getHarmonicIntervals(HumdrumFile& infile); - void calculateIntervals(vector& intervals, vector& tokens, int bassIndex); - void printOutput (HumdrumFile& infile); - void printLineStyle3 (HumdrumFile& infile, int line); - std::string getAnalysisTokenStyle3(HumdrumFile& infile, int line, int field); + Tool_fb(void); + ~Tool_fb(){}; + + bool run (HumdrumFileSet& infiles); + bool run (HumdrumFile& infile); + bool run (const string& indata, ostream& out); + bool run (HumdrumFile& infile, ostream& out); + + vector getTrackData(vector numbers, int lineCount); + + vector getTrackDataForVoice(int voiceIndex, vector numbers, int lineCount); + + FiguredBassNumber* createFiguredBassNumber(NoteCell* base, NoteCell* target, string keySignature); + + vector filterFiguredBassNumbersForLine(vector, int lineIndex); + + vector filterFiguredBassNumbersForLineAndVoice(vector, int lineIndex, int voiceIndex); + + string formatFiguredBassNumbers(vector numbers); + + vector getAbbrNumbers(vector); + + string getNumberString(vector numbers); + + string getKeySignature(HumdrumFile& infile, int lineIndex); + + // protected: private: - std::vector m_kernspines; - std::vector m_kerntracks; - std::vector m_track2index; - std::vector> m_keyaccid; - std::vector> m_intervals; - const int m_rest = -1000; - int m_reference = 0; // currently fixed to bass - int m_debugQ = false; + bool compoundQ = false; + bool accidentalsQ = false; + int baseQ = 0; + bool intervallsatzQ = false; + bool sortQ = false; + bool lowestQ = false; + bool normalizeQ = false; + bool abbrQ = false; + bool attackQ = false; }; @@ -60,6 +79,3 @@ class Tool_fb : public HumTool { } // end namespace hum #endif /* _TOOL_FB_H */ - - - diff --git a/include/tool-figuredbass.h b/include/tool-figuredbass.h deleted file mode 100644 index 1ce95e6d..00000000 --- a/include/tool-figuredbass.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef _TOOL_FIGUREDBASS_H -#define _TOOL_FIGUREDBASS_H - -#include "HumTool.h" -#include "HumdrumFile.h" -#include "NoteGrid.h" - -namespace hum { - -// START_MERGE - -class FiguredBassNumber { - public: - int voiceIndex; - int lineIndex; - int number; - string accidentals; - bool showAccidentals; - bool currAttackNumberDidChange; - bool isAttack; - FiguredBassNumber(int num, string accid, bool showAccid, int voiceIndex, int lineIndex, bool isAttack); - string toString(bool nonCompoundIntervalsQ, bool noAccidentalsQ); - int getNumberB7(); -}; - -class FiguredBassAbbr { - public: - string str; - vector numbers; - FiguredBassAbbr(string s, vector n); -}; - -class Tool_figuredbass : public HumTool { - - public: - Tool_figuredbass(void); - ~Tool_figuredbass(){}; - - bool run (HumdrumFileSet& infiles); - bool run (HumdrumFile& infile); - bool run (const string& indata, ostream& out); - bool run (HumdrumFile& infile, ostream& out); - - vector getTrackData(vector numbers, int lineCount); - - vector getTrackDataForVoice(int voiceIndex, vector numbers, int lineCount); - - FiguredBassNumber* createFiguredBassNumber(NoteCell* base, NoteCell* target, string keySignature); - - vector filterFiguredBassNumbersForLine(vector, int lineIndex); - - vector filterFiguredBassNumbersForLineAndVoice(vector, int lineIndex, int voiceIndex); - - string formatFiguredBassNumbers(vector numbers); - - vector getAbbrNumbers(vector); - - string getNumberString(vector numbers); - - string getKeySignature(HumdrumFile& infile, int lineIndex); - - // protected: - - private: - bool compoundQ = false; - bool accidentalsQ = false; - int baseQ = 0; - bool intervallsatzQ = false; - bool sortQ = false; - bool lowestQ = false; - bool normalizeQ = false; - bool abbrQ = false; - bool attackQ = false; - -}; - -// END_MERGE - -} // end namespace hum - -#endif /* _TOOL_FIGUREDBASS_H */ diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 334826e2..60f817d8 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -1,19 +1,7 @@ -// -// Programmer: Craig Stuart Sapp -// Creation Date: Wed Mar 9 21:55:00 PST 2022 -// Last Modified: Wed Mar 9 21:55:04 PST 2022 -// Filename: tool-fb.cpp -// URL: https://github.com/craigsapp/humlib/blob/master/src/tool-fb.cpp -// Syntax: C++11; humlib -// vim: ts=3 noexpandtab -// -// Description: Extract figured bass from melodic content. -// Reference: https://github.com/WolfgangDrescher/humdrum-figured-bass-filter-demo -// - #include "tool-fb.h" -#include "HumRegex.h" #include "Convert.h" +#include "HumRegex.h" +#include using namespace std; @@ -21,34 +9,27 @@ namespace hum { // START_MERGE - -///////////////////////////////// -// -// Tool_fb::Tool_fb -- Set the recognized options for the tool. -// - Tool_fb::Tool_fb(void) { - define("d|debug=b", "Print debug information"); - define("r|reference=i:0", "Reference kern spine (1 indexed)"); + define("c|compound=b", "output compound intervals for intervals bigger than 9"); + define("a|accidentals=b", "display accidentals in figured bass output"); + define("b|base=i:0", "number of the base voice/spine"); + define("i|intervallsatz=b", "display intervals under their voice and not under the lowest staff"); + define("s|sort=b", "sort figured bass numbers by interval size and not by voice index"); + define("l|lowest=b", "use lowest note as base note; -b flag will be ignored"); + define("n|normalize=b", "remove octave and doubled intervals, use compound interval, sort intervals"); + define("r|abbr=b", "use abbreviated figures"); + define("t|attack=b", "hide intervalls with no attack and when base does not change"); } - - -///////////////////////////////// -// -// Tool_fb::run -- Do the main work of the tool. -// - -bool Tool_fb::run(HumdrumFileSet& infiles) { +bool Tool_fb::run(HumdrumFileSet &infiles) { bool status = true; - for (int i=0; i numbers; -////////////////////////////// -// -// Tool_fb::getHarmonicIntervals -- Fill in -// + vector kernspines = infile.getKernSpineStartList(); -void Tool_fb::getHarmonicIntervals(HumdrumFile& infile) { - m_intervals.resize(infile.getLineCount()); + vector lastNumbers = {}; + lastNumbers.resize(3); + vector currentNumbers = {}; - vector tokens(m_kernspines.size(), NULL); - for (int i=0; igetSgnDiatonicPitch()); + if(checkCellPitch > 0 && checkCellPitch < lowestNotePitch) { + lowestNotePitch = checkCellPitch; + usedBaseVoiceIndex = k; + } + } } - fill(tokens.begin(), tokens.end(), (HTp)NULL); - for (int j=0; jisKern()) { + NoteCell* baseCell = grid.cell(usedBaseVoiceIndex, i); + string keySignature = getKeySignature(infile, baseCell->getLineIndex()); + for (int j=0; j<(int)grid.getVoiceCount(); j++) { + if(j == usedBaseVoiceIndex) { continue; } - int track = token->getTrack(); - int index = m_track2index.at(track); - tokens[index] = token; - // cerr << token << "\t"; - } - m_intervals[i].resize(m_kernspines.size()); - calculateIntervals(m_intervals[i], tokens, m_reference); - // cerr << endl; - - if (m_debugQ) { - for (int j=0; j<(int)m_intervals[i].size(); j++) { - m_free_text << tokens[j] << "\t("; - if (m_intervals[i][j] == m_rest) { - m_free_text << "R"; - } else { - m_free_text << m_intervals[i][j]; - } - m_free_text << ")"; - if (j < (int)m_intervals[i].size() - 1) { - m_free_text << "\t"; - } + NoteCell* targetCell = grid.cell(j, i); + FiguredBassNumber* number = createFiguredBassNumber(baseCell, targetCell, keySignature); + if(lastNumbers[j] != 0) { + number->currAttackNumberDidChange = targetCell->isSustained() && lastNumbers[j] != number->number; } - m_free_text << endl; + currentNumbers[j] = number->number; + numbers.push_back(number); } + lastNumbers = currentNumbers; } -} - - -////////////////////////////// -// -// Tool_fb::calculateIntervals -- -// - -void Tool_fb::calculateIntervals(vector& intervals, - vector& tokens, int bassIndex) { - if (intervals.size() != tokens.size()) { - cerr << "ERROR: Size if vectors do not match" << endl; - return; + if(intervallsatzQ) { + for (int voiceIndex = 0; voiceIndex < grid.getVoiceCount(); voiceIndex++) { + vector trackData = getTrackDataForVoice(voiceIndex, numbers, infile.getLineCount()); + if(voiceIndex + 1 < grid.getVoiceCount()) { + int trackIndex = kernspines[voiceIndex + 1]->getTrack(); + infile.insertDataSpineBefore(trackIndex, trackData, ".", "**fb"); + } else { + int trackIndex = kernspines[voiceIndex]->getTrack(); + infile.appendDataSpine(trackData, ".", "**fb"); + } + } + } else { + vector trackData = getTrackData(numbers, infile.getLineCount()); + if(baseQ + 1 < grid.getVoiceCount()) { + int trackIndex = kernspines[baseQ + 1]->getTrack(); + infile.insertDataSpineBefore(trackIndex, trackData, ".", "**fb"); + } else { + infile.appendDataSpine(trackData, ".", "**fb"); + } } - HTp reftok = tokens[m_reference]; - if (reftok->isNull()) { - reftok = reftok->resolveNull(); - } + return true; +}; - if (!reftok || reftok->isRest()) { - for (int i=0; i<(int)tokens.size(); i++) { - intervals[i] = m_rest; +vector Tool_fb::getTrackData(vector numbers, int lineCount) { + vector trackData; + trackData.resize(lineCount); + + for (int i = 0; i < lineCount; i++) { + vector sliceNumbers = filterFiguredBassNumbersForLine(numbers, i); + if(sliceNumbers.size() > 0) { + trackData[i] = formatFiguredBassNumbers(sliceNumbers); } - return; } - int base40ref = Convert::kernToBase40(reftok); + return trackData; +}; - for (int i=0; i<(int)tokens.size(); i++) { - if (i == m_reference) { - intervals[i] = m_rest; - continue; - } - if (tokens[i]->isRest()) { - intervals[i] = m_rest; - continue; - } - if (tokens[m_reference]->isRest()) { - intervals[i] = m_rest; - continue; - } - if (tokens[i]->isNull()) { - continue; +vector Tool_fb::getTrackDataForVoice(int voiceIndex, vector numbers, int lineCount) { + vector trackData; + trackData.resize(lineCount); + + for (int i = 0; i < lineCount; i++) { + vector sliceNumbers = filterFiguredBassNumbersForLineAndVoice(numbers, i, voiceIndex); + if(sliceNumbers.size() > 0) { + trackData[i] = formatFiguredBassNumbers(sliceNumbers); } - int base40 = Convert::kernToBase40(tokens[i]); - int interval = base40 - base40ref; - intervals[i] = interval; } -} + return trackData; +}; +FiguredBassNumber* Tool_fb::createFiguredBassNumber(NoteCell* base, NoteCell* target, string keySignature) { -////////////////////////////// -// -// Tool_fb::setupScoreData -- -// + int basePitch = base->getSgnDiatonicPitch(); + int targetPitch = target->getSgnDiatonicPitch(); + int num = (basePitch == 0 || targetPitch == 0) ? 0 : abs(abs(targetPitch) - abs(basePitch)) + 1; -void Tool_fb::setupScoreData(HumdrumFile& infile) { - infile.getKernSpineStartList(m_kernspines); - m_kerntracks.resize(m_kernspines.size()); - for (int i=0; i<(int)m_kernspines.size(); i++) { - m_kerntracks[i] = m_kernspines[i]->getTrack(); - } + bool showAccid = false; + regex accidRegex("^\\(?(\\w)+([^\\w\\)]*)\\)?$"); + string accid = regex_replace(target->getSgnKernPitch(), accidRegex, "$2"); - int maxtrack = infile.getMaxTrack(); - m_track2index.resize(maxtrack + 1); - fill(m_track2index.begin(), m_track2index.end(), -1); - for (int i=0; i<(int)m_kerntracks.size(); i++) { - m_track2index.at(m_kerntracks[i]) = i; + string accidWithPitch = regex_replace(target->getSgnKernPitch(), accidRegex, "$1$2"); + transform(accidWithPitch.begin(), accidWithPitch.end(), accidWithPitch.begin(), [](unsigned char c) { + return tolower(c); + }); + transform(keySignature.begin(), keySignature.end(), keySignature.begin(), [](unsigned char c) { + return tolower(c); + }); + if(accid.length() && keySignature.find(accidWithPitch) == std::string::npos) { + showAccid = true; } - if (m_reference >= (int)m_kernspines.size()) { - m_reference = (int)m_kernspines.size() - 1; - } - if (m_reference < 0) { - m_reference = 0; - } + FiguredBassNumber* number = new FiguredBassNumber(num, accid, showAccid, target->getVoiceIndex(), target->getLineIndex(), target->isAttack()); - vector pcs(7, 0); + return number; +}; - m_keyaccid.resize(infile.getLineCount()); - for (int i=0; iisKern()) { - continue; - } - if (token->isKeySignature()) { - fill(pcs.begin(), pcs.end(), 0); - HumRegex hre; - if (hre.search(token, "c#")) { pcs[0] = +1;} - if (hre.search(token, "d#")) { pcs[1] = +1;} - if (hre.search(token, "e#")) { pcs[2] = +1;} - if (hre.search(token, "f#")) { pcs[3] = +1;} - if (hre.search(token, "g#")) { pcs[4] = +1;} - if (hre.search(token, "a#")) { pcs[5] = +1;} - if (hre.search(token, "b#")) { pcs[6] = +1;} - if (hre.search(token, "c-")) { pcs[0] = -1;} - if (hre.search(token, "d-")) { pcs[1] = -1;} - if (hre.search(token, "e-")) { pcs[2] = -1;} - if (hre.search(token, "f-")) { pcs[3] = -1;} - if (hre.search(token, "g-")) { pcs[4] = -1;} - if (hre.search(token, "a-")) { pcs[5] = -1;} - if (hre.search(token, "b-")) { pcs[6] = -1;} - m_keyaccid[i] = pcs; - } - } - } +vector Tool_fb::filterFiguredBassNumbersForLine(vector numbers, int lineIndex) { - for (int i=1; i=0; i--) { - if (m_keyaccid[i].empty()) { - m_keyaccid[i] = m_keyaccid[i+1]; - } - } -} + vector filteredNumbers; + copy_if(numbers.begin(), numbers.end(), back_inserter(filteredNumbers), [lineIndex](FiguredBassNumber* num) { + return num->lineIndex == lineIndex; + }); + sort(filteredNumbers.begin(), filteredNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { + return a->voiceIndex > b->voiceIndex; + }); -////////////////////////////// -// -// Tool_fb:printOutput -- -// + return filteredNumbers; +}; -void Tool_fb::printOutput(HumdrumFile& infile) { - for (int i=0; i Tool_fb::filterFiguredBassNumbersForLineAndVoice(vector numbers, int lineIndex, int voiceIndex) { + vector filteredNumbers; + copy_if(numbers.begin(), numbers.end(), back_inserter(filteredNumbers), [lineIndex, voiceIndex](FiguredBassNumber* num) { + return num->lineIndex == lineIndex && num->voiceIndex == voiceIndex; + }); -////////////////////////////// -// -// Tool_fb::printLineStyle3 -- -// + sort(filteredNumbers.begin(), filteredNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { + return a->voiceIndex > b->voiceIndex; + }); -void Tool_fb::printLineStyle3(HumdrumFile& infile, int line) { - bool printed = false; - int reftrack = m_kerntracks[m_reference]; - bool tab = false; + return filteredNumbers; +}; - for (int i=0; igetTrack(); - if (printed || (track != reftrack + 1)) { - if (tab) { - m_humdrum_text << "\t" << token; - } else { - tab = true; - m_humdrum_text << token; - } - continue; - } - // print analysis spine and then next spine - if (tab) { - m_humdrum_text << "\t"; - } else { - tab = true; - } - m_humdrum_text << getAnalysisTokenStyle3(infile, line, i); - printed = true; - m_humdrum_text << "\t" << token; - } - m_humdrum_text << "\n"; -} +string Tool_fb::formatFiguredBassNumbers(vector numbers) { + vector normalizededNumbers; - -////////////////////////////// -// -// Tool_fb::getAnalysisTokenStyle3 -- -// - -string Tool_fb::getAnalysisTokenStyle3(HumdrumFile& infile, int line, int field) { - if (infile[line].isCommentLocal()) { - return "!"; + if(normalizeQ) { + bool aQ = accidentalsQ; + copy_if(numbers.begin(), numbers.end(), back_inserter(normalizededNumbers), [aQ](FiguredBassNumber* num) { + return (num->getNumberB7() != 8 && num->getNumberB7() != 1) || (aQ && num->showAccidentals); + }); + sort(normalizededNumbers.begin(), normalizededNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { + return a->getNumberB7() < b->getNumberB7(); + }); + normalizededNumbers.erase(unique(normalizededNumbers.begin(), normalizededNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) { + return a->getNumberB7() == b->getNumberB7(); + }), normalizededNumbers.end()); + } else { + normalizededNumbers = numbers; } - if (infile[line].isInterpretation()) { - HTp token = infile.token(line, 0); - if (token->compare(0, 2, "**") == 0) { - return "**fb"; - } else if (*token == "*-") { - return "*-"; - } else if (token->isLabel()) { - return *token; - } else if (token->isExpansionList()) { - return *token; - } else if (token->isKeySignature()) { - return *token; - } else if (token->isKeyDesignation()) { - return *token; - } else { - return "*"; - } + + if(intervallsatzQ && attackQ) { + vector attackNumbers; + copy_if(normalizededNumbers.begin(), normalizededNumbers.end(), back_inserter(attackNumbers), [](FiguredBassNumber* num) { + return num->isAttack || num->currAttackNumberDidChange; + }); + normalizededNumbers = attackNumbers; } - if (infile[line].isBarline()) { - HTp token = infile.token(line, 0); - return *token; + + if(sortQ) { + bool cQ = compoundQ; + sort(normalizededNumbers.begin(), normalizededNumbers.end(), [cQ](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { + return (cQ) ? a->getNumberB7() > b->getNumberB7() : a->number > b->number; + }); } - // create data token - string output; + if(abbrQ) { + normalizededNumbers = getAbbrNumbers(normalizededNumbers); + } - for (int i=(int)m_intervals[line].size()-1; i>=0; i--) { - if (i == m_reference) { - continue; + string str = ""; + bool first = true; + for (FiguredBassNumber* number: normalizededNumbers) { + string num = number->toString(compoundQ, accidentalsQ); + if(num.length() > 0) { + if (!first) str += " "; + first = false; + str += num; } - int base40int = m_intervals[line][i]; - string iname = Convert::base40ToIntervalAbbr(base40int); - output += iname; - output += " "; } - if (!output.empty()) { - output.resize((int)output.size() - 1); + return str; +}; + +vector Tool_fb::getAbbrNumbers(vector numbers) { + + vector abbrNumbers; + + vector figuredBassAbbrs = { + new FiguredBassAbbr("3", {}), + new FiguredBassAbbr("5", {}), + new FiguredBassAbbr("5 3", {}), + new FiguredBassAbbr("6 3", {6}), + new FiguredBassAbbr("5 4", {4}), + new FiguredBassAbbr("7 5 3", {7}), + new FiguredBassAbbr("7 3", {7}), + new FiguredBassAbbr("7 5", {7}), + new FiguredBassAbbr("6 5 3", {6, 5}), + new FiguredBassAbbr("6 4 3", {4, 3}), + new FiguredBassAbbr("6 4 2", {4, 2}), + new FiguredBassAbbr("9 5 3", {9}), + new FiguredBassAbbr("9 5", {9}), + new FiguredBassAbbr("9 3", {9}), + }; + + string numberString = getNumberString(numbers); + + auto it = find_if(figuredBassAbbrs.begin(), figuredBassAbbrs.end(), [numberString](FiguredBassAbbr* abbr) { + return abbr->str == numberString; + }); + + if (it != figuredBassAbbrs.end()) { + int index = it - figuredBassAbbrs.begin(); + FiguredBassAbbr* abbr = figuredBassAbbrs[index]; + bool aQ = accidentalsQ; + copy_if(numbers.begin(), numbers.end(), back_inserter(abbrNumbers), [abbr, aQ](FiguredBassNumber* num) { + vector nums = abbr->numbers; + return find(nums.begin(), nums.end(), num->getNumberB7()) != nums.end() || (num->showAccidentals && aQ); + }); + + return abbrNumbers; } - return output; -} + return numbers; +}; + +string Tool_fb::getNumberString(vector numbers) { + sort(numbers.begin(), numbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { + return a->getNumberB7() > b->getNumberB7(); + }); + string str = ""; + bool first = true; + for (FiguredBassNumber* nr: numbers) { + int num = nr->getNumberB7(); + if(num > 0) { + if (!first) str += " "; + first = false; + str += to_string(num); + } + } + return str; +}; + +string Tool_fb::getKeySignature(HumdrumFile& infile, int lineIndex) { + string keySignature = ""; + [&] { + for (int i = 0; i < infile.getLineCount(); i++) { + if(i > lineIndex) { + return; + } + HLp line = infile.getLine(i); + for (int j = 0; j < line->getFieldCount(); j++) { + if (line->token(j)->isKeySignature()) { + keySignature = line->getTokenString(j); + } + } + } + }(); + return keySignature; +}; + +FiguredBassNumber::FiguredBassNumber(int num, string accid, bool showAccid, int voiceIdx, int lineIdx, bool isAtk) { + number = num; + accidentals = accid; + voiceIndex = voiceIdx; + lineIndex = lineIdx; + showAccidentals = showAccid; + isAttack = isAtk; +}; + +string FiguredBassNumber::toString(bool compoundQ, bool accidentalsQ) { + int num = (compoundQ) ? getNumberB7() : number; + string accid = (accidentalsQ && showAccidentals) ? accidentals : ""; + return num > 0 ? to_string(num) + accid : ""; +}; + +int FiguredBassNumber::getNumberB7() { + int num = (number > 9) ? number % 7 : number; + if(number > 9 && number % 7 == 0) { + num = 7; + } + return (number > 8 && num == 1) ? 8 : num; +}; +FiguredBassAbbr::FiguredBassAbbr(string s, vector n) { + str = s; + numbers = n; +}; // END_MERGE } // end namespace hum - - - diff --git a/src/tool-figuredbass.cpp b/src/tool-figuredbass.cpp deleted file mode 100644 index ec062cf8..00000000 --- a/src/tool-figuredbass.cpp +++ /dev/null @@ -1,382 +0,0 @@ -#include "tool-figuredbass.h" -#include "Convert.h" -#include "HumRegex.h" -#include - -using namespace std; - -namespace hum { - -// START_MERGE - -Tool_figuredbass::Tool_figuredbass(void) { - define("c|compound=b", "output compound intervals for intervals bigger than 9"); - define("a|accidentals=b", "display accidentals in figured bass output"); - define("b|base=i:0", "number of the base voice/spine"); - define("i|intervallsatz=b", "display intervals under their voice and not under the lowest staff"); - define("s|sort=b", "sort figured bass numbers by interval size and not by voice index"); - define("l|lowest=b", "use lowest note as base note; -b flag will be ignored"); - define("n|normalize=b", "remove octave and doubled intervals, use compound interval, sort intervals"); - define("r|abbr=b", "use abbreviated figures"); - define("t|attack=b", "hide intervalls with no attack and when base does not change"); -} - -bool Tool_figuredbass::run(HumdrumFileSet &infiles) { - bool status = true; - for (int i = 0; i < infiles.getCount(); i++) { - status &= run(infiles[i]); - } - return status; -} - -bool Tool_figuredbass::run(const string &indata, ostream &out) { - HumdrumFile infile(indata); - bool status = run(infile); - if (hasAnyText()) { - getAllText(out); - } else { - out << infile; - } - return status; -} - -bool Tool_figuredbass::run(HumdrumFile &infile, ostream &out) { - bool status = run(infile); - if (hasAnyText()) { - getAllText(out); - } else { - out << infile; - } - return status; -} - -bool Tool_figuredbass::run(HumdrumFile &infile) { - - compoundQ = getBoolean("compound"); - accidentalsQ = getBoolean("accidentals"); - baseQ = getInteger("base"); - intervallsatzQ = getBoolean("intervallsatz"); - sortQ = getBoolean("sort"); - lowestQ = getBoolean("lowest"); - normalizeQ = getBoolean("normalize"); - abbrQ = getBoolean("abbr"); - attackQ = getBoolean("attack"); - - if(abbrQ) { - normalizeQ = true; - } - - if(normalizeQ) { - compoundQ = true; - sortQ = true; - } - - NoteGrid grid(infile); - - vector numbers; - - vector kernspines = infile.getKernSpineStartList(); - - vector lastNumbers = {}; - lastNumbers.resize(3); - vector currentNumbers = {}; - - for (int i=0; i<(int)grid.getSliceCount(); i++) { - currentNumbers.clear(); - currentNumbers.resize(3); - int usedBaseVoiceIndex = baseQ; - if(lowestQ) { - int lowestNotePitch = 99999; - for (int k=0; k<(int)grid.getVoiceCount(); k++) { - NoteCell* checkCell = grid.cell(k, i); - int checkCellPitch = abs(checkCell->getSgnDiatonicPitch()); - if(checkCellPitch > 0 && checkCellPitch < lowestNotePitch) { - lowestNotePitch = checkCellPitch; - usedBaseVoiceIndex = k; - } - } - } - NoteCell* baseCell = grid.cell(usedBaseVoiceIndex, i); - string keySignature = getKeySignature(infile, baseCell->getLineIndex()); - for (int j=0; j<(int)grid.getVoiceCount(); j++) { - if(j == usedBaseVoiceIndex) { - continue; - } - NoteCell* targetCell = grid.cell(j, i); - FiguredBassNumber* number = createFiguredBassNumber(baseCell, targetCell, keySignature); - if(lastNumbers[j] != 0) { - number->currAttackNumberDidChange = targetCell->isSustained() && lastNumbers[j] != number->number; - } - currentNumbers[j] = number->number; - numbers.push_back(number); - } - lastNumbers = currentNumbers; - } - - if(intervallsatzQ) { - for (int voiceIndex = 0; voiceIndex < grid.getVoiceCount(); voiceIndex++) { - vector trackData = getTrackDataForVoice(voiceIndex, numbers, infile.getLineCount()); - if(voiceIndex + 1 < grid.getVoiceCount()) { - int trackIndex = kernspines[voiceIndex + 1]->getTrack(); - infile.insertDataSpineBefore(trackIndex, trackData, ".", "**fb"); - } else { - int trackIndex = kernspines[voiceIndex]->getTrack(); - infile.appendDataSpine(trackData, ".", "**fb"); - } - } - } else { - vector trackData = getTrackData(numbers, infile.getLineCount()); - if(baseQ + 1 < grid.getVoiceCount()) { - int trackIndex = kernspines[baseQ + 1]->getTrack(); - infile.insertDataSpineBefore(trackIndex, trackData, ".", "**fb"); - } else { - infile.appendDataSpine(trackData, ".", "**fb"); - } - } - - return true; -}; - -vector Tool_figuredbass::getTrackData(vector numbers, int lineCount) { - vector trackData; - trackData.resize(lineCount); - - for (int i = 0; i < lineCount; i++) { - vector sliceNumbers = filterFiguredBassNumbersForLine(numbers, i); - if(sliceNumbers.size() > 0) { - trackData[i] = formatFiguredBassNumbers(sliceNumbers); - } - } - - return trackData; -}; - -vector Tool_figuredbass::getTrackDataForVoice(int voiceIndex, vector numbers, int lineCount) { - vector trackData; - trackData.resize(lineCount); - - for (int i = 0; i < lineCount; i++) { - vector sliceNumbers = filterFiguredBassNumbersForLineAndVoice(numbers, i, voiceIndex); - if(sliceNumbers.size() > 0) { - trackData[i] = formatFiguredBassNumbers(sliceNumbers); - } - } - - return trackData; -}; - -FiguredBassNumber* Tool_figuredbass::createFiguredBassNumber(NoteCell* base, NoteCell* target, string keySignature) { - - int basePitch = base->getSgnDiatonicPitch(); - int targetPitch = target->getSgnDiatonicPitch(); - int num = (basePitch == 0 || targetPitch == 0) ? 0 : abs(abs(targetPitch) - abs(basePitch)) + 1; - - bool showAccid = false; - regex accidRegex("^\\(?(\\w)+([^\\w\\)]*)\\)?$"); - string accid = regex_replace(target->getSgnKernPitch(), accidRegex, "$2"); - - string accidWithPitch = regex_replace(target->getSgnKernPitch(), accidRegex, "$1$2"); - transform(accidWithPitch.begin(), accidWithPitch.end(), accidWithPitch.begin(), [](unsigned char c) { - return tolower(c); - }); - transform(keySignature.begin(), keySignature.end(), keySignature.begin(), [](unsigned char c) { - return tolower(c); - }); - if(accid.length() && keySignature.find(accidWithPitch) == std::string::npos) { - showAccid = true; - } - - FiguredBassNumber* number = new FiguredBassNumber(num, accid, showAccid, target->getVoiceIndex(), target->getLineIndex(), target->isAttack()); - - return number; -}; - -vector Tool_figuredbass::filterFiguredBassNumbersForLine(vector numbers, int lineIndex) { - - vector filteredNumbers; - - copy_if(numbers.begin(), numbers.end(), back_inserter(filteredNumbers), [lineIndex](FiguredBassNumber* num) { - return num->lineIndex == lineIndex; - }); - - sort(filteredNumbers.begin(), filteredNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { - return a->voiceIndex > b->voiceIndex; - }); - - return filteredNumbers; -}; - -vector Tool_figuredbass::filterFiguredBassNumbersForLineAndVoice(vector numbers, int lineIndex, int voiceIndex) { - - vector filteredNumbers; - - copy_if(numbers.begin(), numbers.end(), back_inserter(filteredNumbers), [lineIndex, voiceIndex](FiguredBassNumber* num) { - return num->lineIndex == lineIndex && num->voiceIndex == voiceIndex; - }); - - sort(filteredNumbers.begin(), filteredNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { - return a->voiceIndex > b->voiceIndex; - }); - - return filteredNumbers; -}; - -string Tool_figuredbass::formatFiguredBassNumbers(vector numbers) { - - vector normalizededNumbers; - - if(normalizeQ) { - bool aQ = accidentalsQ; - copy_if(numbers.begin(), numbers.end(), back_inserter(normalizededNumbers), [aQ](FiguredBassNumber* num) { - return (num->getNumberB7() != 8 && num->getNumberB7() != 1) || (aQ && num->showAccidentals); - }); - sort(normalizededNumbers.begin(), normalizededNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { - return a->getNumberB7() < b->getNumberB7(); - }); - normalizededNumbers.erase(unique(normalizededNumbers.begin(), normalizededNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) { - return a->getNumberB7() == b->getNumberB7(); - }), normalizededNumbers.end()); - } else { - normalizededNumbers = numbers; - } - - if(intervallsatzQ && attackQ) { - vector attackNumbers; - copy_if(normalizededNumbers.begin(), normalizededNumbers.end(), back_inserter(attackNumbers), [](FiguredBassNumber* num) { - return num->isAttack || num->currAttackNumberDidChange; - }); - normalizededNumbers = attackNumbers; - } - - if(sortQ) { - bool cQ = compoundQ; - sort(normalizededNumbers.begin(), normalizededNumbers.end(), [cQ](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { - return (cQ) ? a->getNumberB7() > b->getNumberB7() : a->number > b->number; - }); - } - - if(abbrQ) { - normalizededNumbers = getAbbrNumbers(normalizededNumbers); - } - - string str = ""; - bool first = true; - for (FiguredBassNumber* number: normalizededNumbers) { - string num = number->toString(compoundQ, accidentalsQ); - if(num.length() > 0) { - if (!first) str += " "; - first = false; - str += num; - } - } - return str; -}; - -vector Tool_figuredbass::getAbbrNumbers(vector numbers) { - - vector abbrNumbers; - - vector figuredBassAbbrs = { - new FiguredBassAbbr("3", {}), - new FiguredBassAbbr("5", {}), - new FiguredBassAbbr("5 3", {}), - new FiguredBassAbbr("6 3", {6}), - new FiguredBassAbbr("5 4", {4}), - new FiguredBassAbbr("7 5 3", {7}), - new FiguredBassAbbr("7 3", {7}), - new FiguredBassAbbr("7 5", {7}), - new FiguredBassAbbr("6 5 3", {6, 5}), - new FiguredBassAbbr("6 4 3", {4, 3}), - new FiguredBassAbbr("6 4 2", {4, 2}), - new FiguredBassAbbr("9 5 3", {9}), - new FiguredBassAbbr("9 5", {9}), - new FiguredBassAbbr("9 3", {9}), - }; - - string numberString = getNumberString(numbers); - - auto it = find_if(figuredBassAbbrs.begin(), figuredBassAbbrs.end(), [numberString](FiguredBassAbbr* abbr) { - return abbr->str == numberString; - }); - - if (it != figuredBassAbbrs.end()) { - int index = it - figuredBassAbbrs.begin(); - FiguredBassAbbr* abbr = figuredBassAbbrs[index]; - bool aQ = accidentalsQ; - copy_if(numbers.begin(), numbers.end(), back_inserter(abbrNumbers), [abbr, aQ](FiguredBassNumber* num) { - vector nums = abbr->numbers; - return find(nums.begin(), nums.end(), num->getNumberB7()) != nums.end() || (num->showAccidentals && aQ); - }); - - return abbrNumbers; - } - - return numbers; -}; - -string Tool_figuredbass::getNumberString(vector numbers) { - sort(numbers.begin(), numbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { - return a->getNumberB7() > b->getNumberB7(); - }); - string str = ""; - bool first = true; - for (FiguredBassNumber* nr: numbers) { - int num = nr->getNumberB7(); - if(num > 0) { - if (!first) str += " "; - first = false; - str += to_string(num); - } - } - return str; -}; - -string Tool_figuredbass::getKeySignature(HumdrumFile& infile, int lineIndex) { - string keySignature = ""; - [&] { - for (int i = 0; i < infile.getLineCount(); i++) { - if(i > lineIndex) { - return; - } - HLp line = infile.getLine(i); - for (int j = 0; j < line->getFieldCount(); j++) { - if (line->token(j)->isKeySignature()) { - keySignature = line->getTokenString(j); - } - } - } - }(); - return keySignature; -}; - -FiguredBassNumber::FiguredBassNumber(int num, string accid, bool showAccid, int voiceIdx, int lineIdx, bool isAtk) { - number = num; - accidentals = accid; - voiceIndex = voiceIdx; - lineIndex = lineIdx; - showAccidentals = showAccid; - isAttack = isAtk; -}; - -string FiguredBassNumber::toString(bool compoundQ, bool accidentalsQ) { - int num = (compoundQ) ? getNumberB7() : number; - string accid = (accidentalsQ && showAccidentals) ? accidentals : ""; - return num > 0 ? to_string(num) + accid : ""; -}; - -int FiguredBassNumber::getNumberB7() { - int num = (number > 9) ? number % 7 : number; - if(number > 9 && number % 7 == 0) { - num = 7; - } - return (number > 8 && num == 1) ? 8 : num; -}; - -FiguredBassAbbr::FiguredBassAbbr(string s, vector n) { - str = s; - numbers = n; -}; - -// END_MERGE - -} // end namespace hum diff --git a/src/tool-filter.cpp b/src/tool-filter.cpp index 58b5f60d..128c39e7 100644 --- a/src/tool-filter.cpp +++ b/src/tool-filter.cpp @@ -28,7 +28,7 @@ #include "tool-dissonant.h" #include "tool-double.h" #include "tool-extract.h" -#include "tool-figuredbass.h" +#include "tool-fb.h" #include "tool-flipper.h" #include "tool-gasparize.h" #include "tool-half.h" @@ -231,8 +231,8 @@ bool Tool_filter::run(HumdrumFileSet& infiles) { RUNTOOL(dissonant, infile, commands[i].second, status); } else if (commands[i].first == "double") { RUNTOOL(double, infile, commands[i].second, status); - } else if (commands[i].first == "figuredbass") { - RUNTOOL(figuredbass, infile, commands[i].second, status); + } else if (commands[i].first == "fb") { + RUNTOOL(fb, infile, commands[i].second, status); } else if (commands[i].first == "half") { RUNTOOL(half, infile, commands[i].second, status); } else if (commands[i].first == "homorhythm") { From 4cce120ef050465346faf1373c4a95dd5739698c Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Wed, 11 Jan 2023 11:32:56 +0100 Subject: [PATCH 028/109] Rename var normalizededNumbers with formattedNumbers --- src/tool-fb.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 60f817d8..a2ee7df7 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -223,45 +223,45 @@ vector Tool_fb::filterFiguredBassNumbersForLineAndVoice(vect string Tool_fb::formatFiguredBassNumbers(vector numbers) { - vector normalizededNumbers; + vector formattedNumbers; if(normalizeQ) { bool aQ = accidentalsQ; - copy_if(numbers.begin(), numbers.end(), back_inserter(normalizededNumbers), [aQ](FiguredBassNumber* num) { + copy_if(numbers.begin(), numbers.end(), back_inserter(formattedNumbers), [aQ](FiguredBassNumber* num) { return (num->getNumberB7() != 8 && num->getNumberB7() != 1) || (aQ && num->showAccidentals); }); - sort(normalizededNumbers.begin(), normalizededNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { + sort(formattedNumbers.begin(), formattedNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { return a->getNumberB7() < b->getNumberB7(); }); - normalizededNumbers.erase(unique(normalizededNumbers.begin(), normalizededNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) { + formattedNumbers.erase(unique(formattedNumbers.begin(), formattedNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) { return a->getNumberB7() == b->getNumberB7(); - }), normalizededNumbers.end()); + }), formattedNumbers.end()); } else { - normalizededNumbers = numbers; + formattedNumbers = numbers; } if(intervallsatzQ && attackQ) { vector attackNumbers; - copy_if(normalizededNumbers.begin(), normalizededNumbers.end(), back_inserter(attackNumbers), [](FiguredBassNumber* num) { + copy_if(formattedNumbers.begin(), formattedNumbers.end(), back_inserter(attackNumbers), [](FiguredBassNumber* num) { return num->isAttack || num->currAttackNumberDidChange; }); - normalizededNumbers = attackNumbers; + formattedNumbers = attackNumbers; } if(sortQ) { bool cQ = compoundQ; - sort(normalizededNumbers.begin(), normalizededNumbers.end(), [cQ](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { + sort(formattedNumbers.begin(), formattedNumbers.end(), [cQ](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { return (cQ) ? a->getNumberB7() > b->getNumberB7() : a->number > b->number; }); } if(abbrQ) { - normalizededNumbers = getAbbrNumbers(normalizededNumbers); + formattedNumbers = getAbbrNumbers(formattedNumbers); } string str = ""; bool first = true; - for (FiguredBassNumber* number: normalizededNumbers) { + for (FiguredBassNumber* number: formattedNumbers) { string num = number->toString(compoundQ, accidentalsQ); if(num.length() > 0) { if (!first) str += " "; From 7897d5938030c2077055aae8630a1b79bee8b3d7 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Wed, 11 Jan 2023 12:03:48 +0100 Subject: [PATCH 029/109] Fix lastNumbers and currentNumbers size --- src/tool-fb.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index a2ee7df7..5ecba4ff 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -78,12 +78,12 @@ bool Tool_fb::run(HumdrumFile &infile) { vector kernspines = infile.getKernSpineStartList(); vector lastNumbers = {}; - lastNumbers.resize(3); + lastNumbers.resize((int)grid.getVoiceCount()); vector currentNumbers = {}; for (int i=0; i<(int)grid.getSliceCount(); i++) { currentNumbers.clear(); - currentNumbers.resize(3); + currentNumbers.resize((int)grid.getVoiceCount()); int usedBaseVoiceIndex = baseQ; if(lowestQ) { int lowestNotePitch = 99999; From a4e32ce39d94de11820a45764a1edbccd6139115 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Wed, 11 Jan 2023 12:11:31 +0100 Subject: [PATCH 030/109] Remove unused trackIndex --- src/tool-fb.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 5ecba4ff..0bca9683 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -120,7 +120,6 @@ bool Tool_fb::run(HumdrumFile &infile) { int trackIndex = kernspines[voiceIndex + 1]->getTrack(); infile.insertDataSpineBefore(trackIndex, trackData, ".", "**fb"); } else { - int trackIndex = kernspines[voiceIndex]->getTrack(); infile.appendDataSpine(trackData, ".", "**fb"); } } From 15a13d865db819c66a418435490a44d46f5e7e28 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Wed, 11 Jan 2023 12:16:49 +0100 Subject: [PATCH 031/109] Add comments --- include/tool-fb.h | 20 +++++- src/tool-fb.cpp | 162 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 180 insertions(+), 2 deletions(-) diff --git a/include/tool-fb.h b/include/tool-fb.h index 6df81eeb..7a5af636 100644 --- a/include/tool-fb.h +++ b/include/tool-fb.h @@ -1,3 +1,14 @@ +// +// Programmer: Wolfgang Drescher +// Creation Date: Sun Nov 27 2022 00:25:34 CET +// Filename: tool-fb.h +// URL: https://github.com/craigsapp/humlib/blob/master/include/tool-fb.h +// Syntax: C++11; humlib +// vim: syntax=cpp ts=3 noexpandtab nowrap +// +// Description: Interface for fb tool, which automatically adds figured bass numbers. +// + #ifndef _TOOL_FB_H #define _TOOL_FB_H @@ -15,9 +26,10 @@ class FiguredBassNumber { int lineIndex; int number; string accidentals; - bool showAccidentals; + bool showAccidentals; // Force shoing figured base numbers when they need an accidental bool currAttackNumberDidChange; bool isAttack; + FiguredBassNumber(int num, string accid, bool showAccid, int voiceIndex, int lineIndex, bool isAttack); string toString(bool nonCompoundIntervalsQ, bool noAccidentalsQ); int getNumberB7(); @@ -25,8 +37,14 @@ class FiguredBassNumber { class FiguredBassAbbr { public: + // String to compare the numbers with + // e.g. "6 4 3" + // Sorted by size, larger numbers first string str; + + // Figured bass number as int vector numbers; + FiguredBassAbbr(string s, vector n); }; diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 0bca9683..9ead5efa 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -1,3 +1,14 @@ +// +// Programmer: Wolfgang Drescher +// Creation Date: Sun Nov 27 2022 00:25:34 CET +// Filename: tool-fb.cpp +// URL: https://github.com/craigsapp/humlib/blob/master/src/tool-fb.cpp +// Syntax: C++11; humlib +// vim: syntax=cpp ts=3 noexpandtab nowrap +// +// Description: Add figured bass numbers from **kern spines. +// + #include "tool-fb.h" #include "Convert.h" #include "HumRegex.h" @@ -9,6 +20,11 @@ namespace hum { // START_MERGE +////////////////////////////// +// +// Tool_fb::Tool_fb -- Set the recognized options for the tool. +// + Tool_fb::Tool_fb(void) { define("c|compound=b", "output compound intervals for intervals bigger than 9"); define("a|accidentals=b", "display accidentals in figured bass output"); @@ -21,6 +37,13 @@ Tool_fb::Tool_fb(void) { define("t|attack=b", "hide intervalls with no attack and when base does not change"); } + + +////////////////////////////// +// +// Tool_fb::run -- Do the main work of the tool. +// + bool Tool_fb::run(HumdrumFileSet &infiles) { bool status = true; for (int i = 0; i < infiles.getCount(); i++) { @@ -81,10 +104,17 @@ bool Tool_fb::run(HumdrumFile &infile) { lastNumbers.resize((int)grid.getVoiceCount()); vector currentNumbers = {}; + // Interate through the NoteGrid and fill the numbers vector with + // all generated FiguredBassNumbers for (int i=0; i<(int)grid.getSliceCount(); i++) { currentNumbers.clear(); currentNumbers.resize((int)grid.getVoiceCount()); + + // Reset usedBaseVoiceIndex int usedBaseVoiceIndex = baseQ; + + // Overwrite usedBaseVoiceIndex with the lowest voice index of the lowest pitched note + // TODO: check if this still works for chords if(lowestQ) { int lowestNotePitch = 99999; for (int k=0; k<(int)grid.getVoiceCount(); k++) { @@ -96,24 +126,33 @@ bool Tool_fb::run(HumdrumFile &infile) { } } } + NoteCell* baseCell = grid.cell(usedBaseVoiceIndex, i); string keySignature = getKeySignature(infile, baseCell->getLineIndex()); + + // Interate through each voice for (int j=0; j<(int)grid.getVoiceCount(); j++) { if(j == usedBaseVoiceIndex) { + // Ignore base voice continue; } NoteCell* targetCell = grid.cell(j, i); + // Create FiguredBassNumber FiguredBassNumber* number = createFiguredBassNumber(baseCell, targetCell, keySignature); if(lastNumbers[j] != 0) { + // Set currAttackNumberDidChange number->currAttackNumberDidChange = targetCell->isSustained() && lastNumbers[j] != number->number; } currentNumbers[j] = number->number; numbers.push_back(number); } + + // Set current numbers as the new last numbers lastNumbers = currentNumbers; } if(intervallsatzQ) { + // Create **fb spine for each voice for (int voiceIndex = 0; voiceIndex < grid.getVoiceCount(); voiceIndex++) { vector trackData = getTrackDataForVoice(voiceIndex, numbers, infile.getLineCount()); if(voiceIndex + 1 < grid.getVoiceCount()) { @@ -124,6 +163,7 @@ bool Tool_fb::run(HumdrumFile &infile) { } } } else { + // Create **fb spine and bind it to the base voice vector trackData = getTrackData(numbers, infile.getLineCount()); if(baseQ + 1 < grid.getVoiceCount()) { int trackIndex = kernspines[baseQ + 1]->getTrack(); @@ -136,6 +176,13 @@ bool Tool_fb::run(HumdrumFile &infile) { return true; }; + + +////////////////////////////// +// +// Tool_fb::getTrackData -- Create **fb spine data with formatted numbers for all voices +// + vector Tool_fb::getTrackData(vector numbers, int lineCount) { vector trackData; trackData.resize(lineCount); @@ -150,6 +197,13 @@ vector Tool_fb::getTrackData(vector numbers, int lin return trackData; }; + + +////////////////////////////// +// +// Tool_fb::getTrackDataForVoice -- Create **fb spine data with formatted numbers for passed voiceIndex +// + vector Tool_fb::getTrackDataForVoice(int voiceIndex, vector numbers, int lineCount) { vector trackData; trackData.resize(lineCount); @@ -164,16 +218,29 @@ vector Tool_fb::getTrackDataForVoice(int voiceIndex, vectorgetSgnDiatonicPitch(); int targetPitch = target->getSgnDiatonicPitch(); int num = (basePitch == 0 || targetPitch == 0) ? 0 : abs(abs(targetPitch) - abs(basePitch)) + 1; - bool showAccid = false; regex accidRegex("^\\(?(\\w)+([^\\w\\)]*)\\)?$"); + + // Parse accidental from getSgnKernPitch() string accid = regex_replace(target->getSgnKernPitch(), accidRegex, "$2"); + // Make sure accidWithPitch and keySignature are both lowercase for better comparison string accidWithPitch = regex_replace(target->getSgnKernPitch(), accidRegex, "$1$2"); transform(accidWithPitch.begin(), accidWithPitch.end(), accidWithPitch.begin(), [](unsigned char c) { return tolower(c); @@ -181,6 +248,9 @@ FiguredBassNumber* Tool_fb::createFiguredBassNumber(NoteCell* base, NoteCell* ta transform(keySignature.begin(), keySignature.end(), keySignature.begin(), [](unsigned char c) { return tolower(c); }); + + // Only show accidentals when they are not included in the key signature + bool showAccid = false; if(accid.length() && keySignature.find(accidWithPitch) == std::string::npos) { showAccid = true; } @@ -190,14 +260,23 @@ FiguredBassNumber* Tool_fb::createFiguredBassNumber(NoteCell* base, NoteCell* ta return number; }; + + +////////////////////////////// +// +// Tool_fb::filterFiguredBassNumbersForLine -- Find all FiguredBassNumber objects for a slice (line index) of the music. +// + vector Tool_fb::filterFiguredBassNumbersForLine(vector numbers, int lineIndex) { vector filteredNumbers; + // filter numbers with passed lineIndex copy_if(numbers.begin(), numbers.end(), back_inserter(filteredNumbers), [lineIndex](FiguredBassNumber* num) { return num->lineIndex == lineIndex; }); + // sort by voiceIndex sort(filteredNumbers.begin(), filteredNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { return a->voiceIndex > b->voiceIndex; }); @@ -205,14 +284,23 @@ vector Tool_fb::filterFiguredBassNumbersForLine(vector Tool_fb::filterFiguredBassNumbersForLineAndVoice(vector numbers, int lineIndex, int voiceIndex) { vector filteredNumbers; + // filter numbers with passed lineIndex and passed voiceIndex copy_if(numbers.begin(), numbers.end(), back_inserter(filteredNumbers), [lineIndex, voiceIndex](FiguredBassNumber* num) { return num->lineIndex == lineIndex && num->voiceIndex == voiceIndex; }); + // sort by voiceIndex (probably not needed here) sort(filteredNumbers.begin(), filteredNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { return a->voiceIndex > b->voiceIndex; }); @@ -220,18 +308,29 @@ vector Tool_fb::filterFiguredBassNumbersForLineAndVoice(vect return filteredNumbers; }; + + +////////////////////////////// +// +// Tool_fb::formatFiguredBassNumbers -- Create a **fb data record string out of the passed FiguredBassNumber objects +// + string Tool_fb::formatFiguredBassNumbers(vector numbers) { vector formattedNumbers; + // Normalize numbers (remove 8 and 1, sort by size, remove duplicate numbers) if(normalizeQ) { bool aQ = accidentalsQ; + // remove 8 and 1 but keep them if they have an accidental copy_if(numbers.begin(), numbers.end(), back_inserter(formattedNumbers), [aQ](FiguredBassNumber* num) { return (num->getNumberB7() != 8 && num->getNumberB7() != 1) || (aQ && num->showAccidentals); }); + // sort by size sort(formattedNumbers.begin(), formattedNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { return a->getNumberB7() < b->getNumberB7(); }); + // remove duplicate numbers formattedNumbers.erase(unique(formattedNumbers.begin(), formattedNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) { return a->getNumberB7() == b->getNumberB7(); }), formattedNumbers.end()); @@ -239,6 +338,7 @@ string Tool_fb::formatFiguredBassNumbers(vector numbers) { formattedNumbers = numbers; } + // Hide numbers if they have no attack if(intervallsatzQ && attackQ) { vector attackNumbers; copy_if(formattedNumbers.begin(), formattedNumbers.end(), back_inserter(attackNumbers), [](FiguredBassNumber* num) { @@ -247,17 +347,21 @@ string Tool_fb::formatFiguredBassNumbers(vector numbers) { formattedNumbers = attackNumbers; } + // Sort numbers by size if(sortQ) { bool cQ = compoundQ; sort(formattedNumbers.begin(), formattedNumbers.end(), [cQ](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { + // sort by getNumberB7 if compoundQ is true otherwise sort by number return (cQ) ? a->getNumberB7() > b->getNumberB7() : a->number > b->number; }); } if(abbrQ) { + // Overwrite formattedNumbers with abbreviated numbers formattedNumbers = getAbbrNumbers(formattedNumbers); } + // join numbers string str = ""; bool first = true; for (FiguredBassNumber* number: formattedNumbers) { @@ -271,10 +375,18 @@ string Tool_fb::formatFiguredBassNumbers(vector numbers) { return str; }; + + +////////////////////////////// +// +// Tool_fb::getAbbrNumbers -- Get abbreviated figured bass numbers +// If no abbreviation is found all numbers will be shown + vector Tool_fb::getAbbrNumbers(vector numbers) { vector abbrNumbers; + // Mapping to abbreviate figured bass numbers vector figuredBassAbbrs = { new FiguredBassAbbr("3", {}), new FiguredBassAbbr("5", {}), @@ -294,6 +406,7 @@ vector Tool_fb::getAbbrNumbers(vector nu string numberString = getNumberString(numbers); + // Check if an abbreviation exists for passed numbers auto it = find_if(figuredBassAbbrs.begin(), figuredBassAbbrs.end(), [numberString](FiguredBassAbbr* abbr) { return abbr->str == numberString; }); @@ -302,8 +415,10 @@ vector Tool_fb::getAbbrNumbers(vector nu int index = it - figuredBassAbbrs.begin(); FiguredBassAbbr* abbr = figuredBassAbbrs[index]; bool aQ = accidentalsQ; + // Store numbers to display by the abbreviation mapping in abbrNumbers copy_if(numbers.begin(), numbers.end(), back_inserter(abbrNumbers), [abbr, aQ](FiguredBassNumber* num) { vector nums = abbr->numbers; + // Show numbers if they are part of the abbreviation mapping or if they have an accidental return find(nums.begin(), nums.end(), num->getNumberB7()) != nums.end() || (num->showAccidentals && aQ); }); @@ -313,10 +428,19 @@ vector Tool_fb::getAbbrNumbers(vector nu return numbers; }; + + +////////////////////////////// +// +// Tool_fb::getNumberString -- Get only the numbers (without accidentals) of passed FiguredBassNumbers +// + string Tool_fb::getNumberString(vector numbers) { + // Sort numbers by size sort(numbers.begin(), numbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { return a->getNumberB7() > b->getNumberB7(); }); + // join numbers string str = ""; bool first = true; for (FiguredBassNumber* nr: numbers) { @@ -330,6 +454,13 @@ string Tool_fb::getNumberString(vector numbers) { return str; }; + + +////////////////////////////// +// +// Tool_fb::getKeySignature -- Get the key signature for a line index of the input file +// + string Tool_fb::getKeySignature(HumdrumFile& infile, int lineIndex) { string keySignature = ""; [&] { @@ -348,6 +479,13 @@ string Tool_fb::getKeySignature(HumdrumFile& infile, int lineIndex) { return keySignature; }; + + +////////////////////////////// +// +// FiguredBassNumber::FiguredBassNumber -- Constructor +// + FiguredBassNumber::FiguredBassNumber(int num, string accid, bool showAccid, int voiceIdx, int lineIdx, bool isAtk) { number = num; accidentals = accid; @@ -357,12 +495,26 @@ FiguredBassNumber::FiguredBassNumber(int num, string accid, bool showAccid, int isAttack = isAtk; }; + + +////////////////////////////// +// +// FiguredBassNumber::toString -- Convert FiguredBassNumber to a string (accidental + number) +// + string FiguredBassNumber::toString(bool compoundQ, bool accidentalsQ) { int num = (compoundQ) ? getNumberB7() : number; string accid = (accidentalsQ && showAccidentals) ? accidentals : ""; return num > 0 ? to_string(num) + accid : ""; }; + + +////////////////////////////// +// +// FiguredBassNumber::getNumberB7 -- Get figured bass number as non compound interval (base 7) +// + int FiguredBassNumber::getNumberB7() { int num = (number > 9) ? number % 7 : number; if(number > 9 && number % 7 == 0) { @@ -371,6 +523,14 @@ int FiguredBassNumber::getNumberB7() { return (number > 8 && num == 1) ? 8 : num; }; + + +////////////////////////////// +// +// FiguredBassAbbr::FiguredBassAbbr -- Constructor +// Helper class to store the mappings for abbreviate figured bass numbers +// + FiguredBassAbbr::FiguredBassAbbr(string s, vector n) { str = s; numbers = n; From 6db97807be009509482674a9f4936e86a7d5c14b Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Wed, 11 Jan 2023 13:41:25 +0100 Subject: [PATCH 032/109] Add missing numbers variable --- include/tool-fb.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/tool-fb.h b/include/tool-fb.h index 7a5af636..838e5b0d 100644 --- a/include/tool-fb.h +++ b/include/tool-fb.h @@ -65,13 +65,13 @@ class Tool_fb : public HumTool { FiguredBassNumber* createFiguredBassNumber(NoteCell* base, NoteCell* target, string keySignature); - vector filterFiguredBassNumbersForLine(vector, int lineIndex); + vector filterFiguredBassNumbersForLine(vector numbers, int lineIndex); - vector filterFiguredBassNumbersForLineAndVoice(vector, int lineIndex, int voiceIndex); + vector filterFiguredBassNumbersForLineAndVoice(vector numbers, int lineIndex, int voiceIndex); string formatFiguredBassNumbers(vector numbers); - vector getAbbrNumbers(vector); + vector getAbbrNumbers(vector numbers); string getNumberString(vector numbers); From a907db40c0d30a82996820ecd81484fdf9fc7ff4 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Wed, 11 Jan 2023 13:50:31 +0100 Subject: [PATCH 033/109] Fix indentation --- include/tool-fb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/tool-fb.h b/include/tool-fb.h index 838e5b0d..c12912e8 100644 --- a/include/tool-fb.h +++ b/include/tool-fb.h @@ -29,7 +29,7 @@ class FiguredBassNumber { bool showAccidentals; // Force shoing figured base numbers when they need an accidental bool currAttackNumberDidChange; bool isAttack; - + FiguredBassNumber(int num, string accid, bool showAccid, int voiceIndex, int lineIndex, bool isAttack); string toString(bool nonCompoundIntervalsQ, bool noAccidentalsQ); int getNumberB7(); From d307809b9f6342445dad42eaf07e44eb4bb8074b Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Wed, 11 Jan 2023 13:59:10 +0100 Subject: [PATCH 034/109] Use constant pass-by-reference for vectors --- include/tool-fb.h | 8 ++++---- src/tool-fb.cpp | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/tool-fb.h b/include/tool-fb.h index c12912e8..c74f3a86 100644 --- a/include/tool-fb.h +++ b/include/tool-fb.h @@ -59,9 +59,9 @@ class Tool_fb : public HumTool { bool run (const string& indata, ostream& out); bool run (HumdrumFile& infile, ostream& out); - vector getTrackData(vector numbers, int lineCount); + vector getTrackData(const vector& numbers, int lineCount); - vector getTrackDataForVoice(int voiceIndex, vector numbers, int lineCount); + vector getTrackDataForVoice(int voiceIndex, const vector& numbers, int lineCount); FiguredBassNumber* createFiguredBassNumber(NoteCell* base, NoteCell* target, string keySignature); @@ -69,9 +69,9 @@ class Tool_fb : public HumTool { vector filterFiguredBassNumbersForLineAndVoice(vector numbers, int lineIndex, int voiceIndex); - string formatFiguredBassNumbers(vector numbers); + string formatFiguredBassNumbers(const vector& numbers); - vector getAbbrNumbers(vector numbers); + vector getAbbrNumbers(const vector& numbers); string getNumberString(vector numbers); diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 9ead5efa..4126f3ee 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -183,7 +183,7 @@ bool Tool_fb::run(HumdrumFile &infile) { // Tool_fb::getTrackData -- Create **fb spine data with formatted numbers for all voices // -vector Tool_fb::getTrackData(vector numbers, int lineCount) { +vector Tool_fb::getTrackData(const vector& numbers, int lineCount) { vector trackData; trackData.resize(lineCount); @@ -204,7 +204,7 @@ vector Tool_fb::getTrackData(vector numbers, int lin // Tool_fb::getTrackDataForVoice -- Create **fb spine data with formatted numbers for passed voiceIndex // -vector Tool_fb::getTrackDataForVoice(int voiceIndex, vector numbers, int lineCount) { +vector Tool_fb::getTrackDataForVoice(int voiceIndex, const vector& numbers, int lineCount) { vector trackData; trackData.resize(lineCount); @@ -315,7 +315,7 @@ vector Tool_fb::filterFiguredBassNumbersForLineAndVoice(vect // Tool_fb::formatFiguredBassNumbers -- Create a **fb data record string out of the passed FiguredBassNumber objects // -string Tool_fb::formatFiguredBassNumbers(vector numbers) { +string Tool_fb::formatFiguredBassNumbers(const vector& numbers) { vector formattedNumbers; @@ -382,7 +382,7 @@ string Tool_fb::formatFiguredBassNumbers(vector numbers) { // Tool_fb::getAbbrNumbers -- Get abbreviated figured bass numbers // If no abbreviation is found all numbers will be shown -vector Tool_fb::getAbbrNumbers(vector numbers) { +vector Tool_fb::getAbbrNumbers(const vector& numbers) { vector abbrNumbers; From e972e2e16324ea42123b4dedda2552529fff87f2 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Wed, 11 Jan 2023 17:46:50 +0100 Subject: [PATCH 035/109] Add space after reserved words (if) --- src/tool-fb.cpp | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 4126f3ee..712ca8b8 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -85,11 +85,11 @@ bool Tool_fb::run(HumdrumFile &infile) { abbrQ = getBoolean("abbr"); attackQ = getBoolean("attack"); - if(abbrQ) { + if (abbrQ) { normalizeQ = true; } - if(normalizeQ) { + if (normalizeQ) { compoundQ = true; sortQ = true; } @@ -115,12 +115,12 @@ bool Tool_fb::run(HumdrumFile &infile) { // Overwrite usedBaseVoiceIndex with the lowest voice index of the lowest pitched note // TODO: check if this still works for chords - if(lowestQ) { + if (lowestQ) { int lowestNotePitch = 99999; for (int k=0; k<(int)grid.getVoiceCount(); k++) { NoteCell* checkCell = grid.cell(k, i); int checkCellPitch = abs(checkCell->getSgnDiatonicPitch()); - if(checkCellPitch > 0 && checkCellPitch < lowestNotePitch) { + if (checkCellPitch > 0 && checkCellPitch < lowestNotePitch) { lowestNotePitch = checkCellPitch; usedBaseVoiceIndex = k; } @@ -132,14 +132,14 @@ bool Tool_fb::run(HumdrumFile &infile) { // Interate through each voice for (int j=0; j<(int)grid.getVoiceCount(); j++) { - if(j == usedBaseVoiceIndex) { + if (j == usedBaseVoiceIndex) { // Ignore base voice continue; } NoteCell* targetCell = grid.cell(j, i); // Create FiguredBassNumber FiguredBassNumber* number = createFiguredBassNumber(baseCell, targetCell, keySignature); - if(lastNumbers[j] != 0) { + if (lastNumbers[j] != 0) { // Set currAttackNumberDidChange number->currAttackNumberDidChange = targetCell->isSustained() && lastNumbers[j] != number->number; } @@ -151,11 +151,11 @@ bool Tool_fb::run(HumdrumFile &infile) { lastNumbers = currentNumbers; } - if(intervallsatzQ) { + if (intervallsatzQ) { // Create **fb spine for each voice for (int voiceIndex = 0; voiceIndex < grid.getVoiceCount(); voiceIndex++) { vector trackData = getTrackDataForVoice(voiceIndex, numbers, infile.getLineCount()); - if(voiceIndex + 1 < grid.getVoiceCount()) { + if (voiceIndex + 1 < grid.getVoiceCount()) { int trackIndex = kernspines[voiceIndex + 1]->getTrack(); infile.insertDataSpineBefore(trackIndex, trackData, ".", "**fb"); } else { @@ -165,7 +165,7 @@ bool Tool_fb::run(HumdrumFile &infile) { } else { // Create **fb spine and bind it to the base voice vector trackData = getTrackData(numbers, infile.getLineCount()); - if(baseQ + 1 < grid.getVoiceCount()) { + if (baseQ + 1 < grid.getVoiceCount()) { int trackIndex = kernspines[baseQ + 1]->getTrack(); infile.insertDataSpineBefore(trackIndex, trackData, ".", "**fb"); } else { @@ -189,7 +189,7 @@ vector Tool_fb::getTrackData(const vector& numbers, for (int i = 0; i < lineCount; i++) { vector sliceNumbers = filterFiguredBassNumbersForLine(numbers, i); - if(sliceNumbers.size() > 0) { + if (sliceNumbers.size() > 0) { trackData[i] = formatFiguredBassNumbers(sliceNumbers); } } @@ -210,7 +210,7 @@ vector Tool_fb::getTrackDataForVoice(int voiceIndex, const vector
sliceNumbers = filterFiguredBassNumbersForLineAndVoice(numbers, i, voiceIndex); - if(sliceNumbers.size() > 0) { + if (sliceNumbers.size() > 0) { trackData[i] = formatFiguredBassNumbers(sliceNumbers); } } @@ -251,7 +251,7 @@ FiguredBassNumber* Tool_fb::createFiguredBassNumber(NoteCell* base, NoteCell* ta // Only show accidentals when they are not included in the key signature bool showAccid = false; - if(accid.length() && keySignature.find(accidWithPitch) == std::string::npos) { + if (accid.length() && keySignature.find(accidWithPitch) == std::string::npos) { showAccid = true; } @@ -320,7 +320,7 @@ string Tool_fb::formatFiguredBassNumbers(const vector& numbe vector formattedNumbers; // Normalize numbers (remove 8 and 1, sort by size, remove duplicate numbers) - if(normalizeQ) { + if (normalizeQ) { bool aQ = accidentalsQ; // remove 8 and 1 but keep them if they have an accidental copy_if(numbers.begin(), numbers.end(), back_inserter(formattedNumbers), [aQ](FiguredBassNumber* num) { @@ -339,7 +339,7 @@ string Tool_fb::formatFiguredBassNumbers(const vector& numbe } // Hide numbers if they have no attack - if(intervallsatzQ && attackQ) { + if (intervallsatzQ && attackQ) { vector attackNumbers; copy_if(formattedNumbers.begin(), formattedNumbers.end(), back_inserter(attackNumbers), [](FiguredBassNumber* num) { return num->isAttack || num->currAttackNumberDidChange; @@ -348,7 +348,7 @@ string Tool_fb::formatFiguredBassNumbers(const vector& numbe } // Sort numbers by size - if(sortQ) { + if (sortQ) { bool cQ = compoundQ; sort(formattedNumbers.begin(), formattedNumbers.end(), [cQ](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { // sort by getNumberB7 if compoundQ is true otherwise sort by number @@ -356,7 +356,7 @@ string Tool_fb::formatFiguredBassNumbers(const vector& numbe }); } - if(abbrQ) { + if (abbrQ) { // Overwrite formattedNumbers with abbreviated numbers formattedNumbers = getAbbrNumbers(formattedNumbers); } @@ -366,7 +366,7 @@ string Tool_fb::formatFiguredBassNumbers(const vector& numbe bool first = true; for (FiguredBassNumber* number: formattedNumbers) { string num = number->toString(compoundQ, accidentalsQ); - if(num.length() > 0) { + if (num.length() > 0) { if (!first) str += " "; first = false; str += num; @@ -445,7 +445,7 @@ string Tool_fb::getNumberString(vector numbers) { bool first = true; for (FiguredBassNumber* nr: numbers) { int num = nr->getNumberB7(); - if(num > 0) { + if (num > 0) { if (!first) str += " "; first = false; str += to_string(num); @@ -465,7 +465,7 @@ string Tool_fb::getKeySignature(HumdrumFile& infile, int lineIndex) { string keySignature = ""; [&] { for (int i = 0; i < infile.getLineCount(); i++) { - if(i > lineIndex) { + if (i > lineIndex) { return; } HLp line = infile.getLine(i); @@ -517,7 +517,7 @@ string FiguredBassNumber::toString(bool compoundQ, bool accidentalsQ) { int FiguredBassNumber::getNumberB7() { int num = (number > 9) ? number % 7 : number; - if(number > 9 && number % 7 == 0) { + if (number > 9 && number % 7 == 0) { num = 7; } return (number > 8 && num == 1) ? 8 : num; From 96814302a6b5a7673715f97cf633c801d50b7484 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Wed, 11 Jan 2023 17:53:23 +0100 Subject: [PATCH 036/109] Add parentheses around statements in conditions --- src/tool-fb.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 712ca8b8..8bac082a 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -120,7 +120,7 @@ bool Tool_fb::run(HumdrumFile &infile) { for (int k=0; k<(int)grid.getVoiceCount(); k++) { NoteCell* checkCell = grid.cell(k, i); int checkCellPitch = abs(checkCell->getSgnDiatonicPitch()); - if (checkCellPitch > 0 && checkCellPitch < lowestNotePitch) { + if ((checkCellPitch > 0) && (checkCellPitch < lowestNotePitch)) { lowestNotePitch = checkCellPitch; usedBaseVoiceIndex = k; } @@ -141,7 +141,7 @@ bool Tool_fb::run(HumdrumFile &infile) { FiguredBassNumber* number = createFiguredBassNumber(baseCell, targetCell, keySignature); if (lastNumbers[j] != 0) { // Set currAttackNumberDidChange - number->currAttackNumberDidChange = targetCell->isSustained() && lastNumbers[j] != number->number; + number->currAttackNumberDidChange = (targetCell->isSustained()) && (lastNumbers[j] != number->number); } currentNumbers[j] = number->number; numbers.push_back(number); @@ -233,7 +233,7 @@ FiguredBassNumber* Tool_fb::createFiguredBassNumber(NoteCell* base, NoteCell* ta // There is currenlty no support for negative numbers (e.g. with intervallsatz) int basePitch = base->getSgnDiatonicPitch(); int targetPitch = target->getSgnDiatonicPitch(); - int num = (basePitch == 0 || targetPitch == 0) ? 0 : abs(abs(targetPitch) - abs(basePitch)) + 1; + int num = ((basePitch == 0) || (targetPitch == 0)) ? 0 : abs(abs(targetPitch) - abs(basePitch)) + 1; regex accidRegex("^\\(?(\\w)+([^\\w\\)]*)\\)?$"); @@ -251,7 +251,7 @@ FiguredBassNumber* Tool_fb::createFiguredBassNumber(NoteCell* base, NoteCell* ta // Only show accidentals when they are not included in the key signature bool showAccid = false; - if (accid.length() && keySignature.find(accidWithPitch) == std::string::npos) { + if (accid.length() && (keySignature.find(accidWithPitch) == std::string::npos)) { showAccid = true; } @@ -297,7 +297,7 @@ vector Tool_fb::filterFiguredBassNumbersForLineAndVoice(vect // filter numbers with passed lineIndex and passed voiceIndex copy_if(numbers.begin(), numbers.end(), back_inserter(filteredNumbers), [lineIndex, voiceIndex](FiguredBassNumber* num) { - return num->lineIndex == lineIndex && num->voiceIndex == voiceIndex; + return (num->lineIndex == lineIndex) && (num->voiceIndex == voiceIndex); }); // sort by voiceIndex (probably not needed here) @@ -324,7 +324,7 @@ string Tool_fb::formatFiguredBassNumbers(const vector& numbe bool aQ = accidentalsQ; // remove 8 and 1 but keep them if they have an accidental copy_if(numbers.begin(), numbers.end(), back_inserter(formattedNumbers), [aQ](FiguredBassNumber* num) { - return (num->getNumberB7() != 8 && num->getNumberB7() != 1) || (aQ && num->showAccidentals); + return ((num->getNumberB7() != 8) && (num->getNumberB7() != 1)) || (aQ && num->showAccidentals); }); // sort by size sort(formattedNumbers.begin(), formattedNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { @@ -419,7 +419,7 @@ vector Tool_fb::getAbbrNumbers(const vector nums = abbr->numbers; // Show numbers if they are part of the abbreviation mapping or if they have an accidental - return find(nums.begin(), nums.end(), num->getNumberB7()) != nums.end() || (num->showAccidentals && aQ); + return (find(nums.begin(), nums.end(), num->getNumberB7()) != nums.end()) || (num->showAccidentals && aQ); }); return abbrNumbers; @@ -517,10 +517,10 @@ string FiguredBassNumber::toString(bool compoundQ, bool accidentalsQ) { int FiguredBassNumber::getNumberB7() { int num = (number > 9) ? number % 7 : number; - if (number > 9 && number % 7 == 0) { + if ((number > 9) && (number % 7 == 0)) { num = 7; } - return (number > 8 && num == 1) ? 8 : num; + return ((number > 8) && (num == 1)) ? 8 : num; }; From 06472718cb0389ef4ff4eceec703f47dd5381f69 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Wed, 11 Jan 2023 17:57:47 +0100 Subject: [PATCH 037/109] Add void to method declaration and definition --- include/tool-fb.h | 2 +- src/tool-fb.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/tool-fb.h b/include/tool-fb.h index c74f3a86..ecc93787 100644 --- a/include/tool-fb.h +++ b/include/tool-fb.h @@ -32,7 +32,7 @@ class FiguredBassNumber { FiguredBassNumber(int num, string accid, bool showAccid, int voiceIndex, int lineIndex, bool isAttack); string toString(bool nonCompoundIntervalsQ, bool noAccidentalsQ); - int getNumberB7(); + int getNumberB7(void); }; class FiguredBassAbbr { diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 8bac082a..597c2013 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -515,7 +515,7 @@ string FiguredBassNumber::toString(bool compoundQ, bool accidentalsQ) { // FiguredBassNumber::getNumberB7 -- Get figured bass number as non compound interval (base 7) // -int FiguredBassNumber::getNumberB7() { +int FiguredBassNumber::getNumberB7(void) { int num = (number > 9) ? number % 7 : number; if ((number > 9) && (number % 7 == 0)) { num = 7; From 74568d81b389419ae1d4e2b55584cdd5117c3331 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Wed, 11 Jan 2023 18:00:08 +0100 Subject: [PATCH 038/109] Remove semicolon from end of function definitions --- src/tool-fb.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 597c2013..6f2488e4 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -174,7 +174,7 @@ bool Tool_fb::run(HumdrumFile &infile) { } return true; -}; +} @@ -195,7 +195,7 @@ vector Tool_fb::getTrackData(const vector& numbers, } return trackData; -}; +} @@ -216,7 +216,7 @@ vector Tool_fb::getTrackDataForVoice(int voiceIndex, const vector
getVoiceIndex(), target->getLineIndex(), target->isAttack()); return number; -}; +} @@ -282,7 +282,7 @@ vector Tool_fb::filterFiguredBassNumbersForLine(vector Tool_fb::filterFiguredBassNumbersForLineAndVoice(vect }); return filteredNumbers; -}; +} @@ -373,7 +373,7 @@ string Tool_fb::formatFiguredBassNumbers(const vector& numbe } } return str; -}; +} @@ -426,7 +426,7 @@ vector Tool_fb::getAbbrNumbers(const vector numbers) { } } return str; -}; +} @@ -477,7 +477,7 @@ string Tool_fb::getKeySignature(HumdrumFile& infile, int lineIndex) { } }(); return keySignature; -}; +} @@ -493,7 +493,7 @@ FiguredBassNumber::FiguredBassNumber(int num, string accid, bool showAccid, int lineIndex = lineIdx; showAccidentals = showAccid; isAttack = isAtk; -}; +} @@ -506,7 +506,7 @@ string FiguredBassNumber::toString(bool compoundQ, bool accidentalsQ) { int num = (compoundQ) ? getNumberB7() : number; string accid = (accidentalsQ && showAccidentals) ? accidentals : ""; return num > 0 ? to_string(num) + accid : ""; -}; +} @@ -521,7 +521,7 @@ int FiguredBassNumber::getNumberB7(void) { num = 7; } return ((number > 8) && (num == 1)) ? 8 : num; -}; +} @@ -534,7 +534,7 @@ int FiguredBassNumber::getNumberB7(void) { FiguredBassAbbr::FiguredBassAbbr(string s, vector n) { str = s; numbers = n; -}; +} // END_MERGE From ce9855d3902a5a3be0a8abfeb250abe4e705b39c Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Wed, 11 Jan 2023 18:03:24 +0100 Subject: [PATCH 039/109] Rename getNumberB7 to getNumberWithinOctave --- include/tool-fb.h | 2 +- src/tool-fb.cpp | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/include/tool-fb.h b/include/tool-fb.h index ecc93787..088aa193 100644 --- a/include/tool-fb.h +++ b/include/tool-fb.h @@ -32,7 +32,7 @@ class FiguredBassNumber { FiguredBassNumber(int num, string accid, bool showAccid, int voiceIndex, int lineIndex, bool isAttack); string toString(bool nonCompoundIntervalsQ, bool noAccidentalsQ); - int getNumberB7(void); + int getNumberWithinOctave(void); }; class FiguredBassAbbr { diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 6f2488e4..9eb24b36 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -324,15 +324,15 @@ string Tool_fb::formatFiguredBassNumbers(const vector& numbe bool aQ = accidentalsQ; // remove 8 and 1 but keep them if they have an accidental copy_if(numbers.begin(), numbers.end(), back_inserter(formattedNumbers), [aQ](FiguredBassNumber* num) { - return ((num->getNumberB7() != 8) && (num->getNumberB7() != 1)) || (aQ && num->showAccidentals); + return ((num->getNumberWithinOctave() != 8) && (num->getNumberWithinOctave() != 1)) || (aQ && num->showAccidentals); }); // sort by size sort(formattedNumbers.begin(), formattedNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { - return a->getNumberB7() < b->getNumberB7(); + return a->getNumberWithinOctave() < b->getNumberWithinOctave(); }); // remove duplicate numbers formattedNumbers.erase(unique(formattedNumbers.begin(), formattedNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) { - return a->getNumberB7() == b->getNumberB7(); + return a->getNumberWithinOctave() == b->getNumberWithinOctave(); }), formattedNumbers.end()); } else { formattedNumbers = numbers; @@ -351,8 +351,8 @@ string Tool_fb::formatFiguredBassNumbers(const vector& numbe if (sortQ) { bool cQ = compoundQ; sort(formattedNumbers.begin(), formattedNumbers.end(), [cQ](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { - // sort by getNumberB7 if compoundQ is true otherwise sort by number - return (cQ) ? a->getNumberB7() > b->getNumberB7() : a->number > b->number; + // sort by getNumberWithinOctave if compoundQ is true otherwise sort by number + return (cQ) ? a->getNumberWithinOctave() > b->getNumberWithinOctave() : a->number > b->number; }); } @@ -419,7 +419,7 @@ vector Tool_fb::getAbbrNumbers(const vector nums = abbr->numbers; // Show numbers if they are part of the abbreviation mapping or if they have an accidental - return (find(nums.begin(), nums.end(), num->getNumberB7()) != nums.end()) || (num->showAccidentals && aQ); + return (find(nums.begin(), nums.end(), num->getNumberWithinOctave()) != nums.end()) || (num->showAccidentals && aQ); }); return abbrNumbers; @@ -438,13 +438,13 @@ vector Tool_fb::getAbbrNumbers(const vector numbers) { // Sort numbers by size sort(numbers.begin(), numbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { - return a->getNumberB7() > b->getNumberB7(); + return a->getNumberWithinOctave() > b->getNumberWithinOctave(); }); // join numbers string str = ""; bool first = true; for (FiguredBassNumber* nr: numbers) { - int num = nr->getNumberB7(); + int num = nr->getNumberWithinOctave(); if (num > 0) { if (!first) str += " "; first = false; @@ -503,7 +503,7 @@ FiguredBassNumber::FiguredBassNumber(int num, string accid, bool showAccid, int // string FiguredBassNumber::toString(bool compoundQ, bool accidentalsQ) { - int num = (compoundQ) ? getNumberB7() : number; + int num = (compoundQ) ? getNumberWithinOctave() : number; string accid = (accidentalsQ && showAccidentals) ? accidentals : ""; return num > 0 ? to_string(num) + accid : ""; } @@ -512,10 +512,10 @@ string FiguredBassNumber::toString(bool compoundQ, bool accidentalsQ) { ////////////////////////////// // -// FiguredBassNumber::getNumberB7 -- Get figured bass number as non compound interval (base 7) +// FiguredBassNumber::getNumberWithinOctave -- Get figured bass number as non compound interval (base 7) // -int FiguredBassNumber::getNumberB7(void) { +int FiguredBassNumber::getNumberWithinOctave(void) { int num = (number > 9) ? number % 7 : number; if ((number > 9) && (number % 7 == 0)) { num = 7; From df239cc931a10e53430547a19ad317fd2211e5b3 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Wed, 11 Jan 2023 18:05:58 +0100 Subject: [PATCH 040/109] Rename getAbbrNumbers to getAbbreviatedNumbers --- include/tool-fb.h | 2 +- src/tool-fb.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/tool-fb.h b/include/tool-fb.h index 088aa193..656c0955 100644 --- a/include/tool-fb.h +++ b/include/tool-fb.h @@ -71,7 +71,7 @@ class Tool_fb : public HumTool { string formatFiguredBassNumbers(const vector& numbers); - vector getAbbrNumbers(const vector& numbers); + vector getAbbreviatedNumbers(const vector& numbers); string getNumberString(vector numbers); diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 9eb24b36..59e5bc90 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -358,7 +358,7 @@ string Tool_fb::formatFiguredBassNumbers(const vector& numbe if (abbrQ) { // Overwrite formattedNumbers with abbreviated numbers - formattedNumbers = getAbbrNumbers(formattedNumbers); + formattedNumbers = getAbbreviatedNumbers(formattedNumbers); } // join numbers @@ -379,10 +379,10 @@ string Tool_fb::formatFiguredBassNumbers(const vector& numbe ////////////////////////////// // -// Tool_fb::getAbbrNumbers -- Get abbreviated figured bass numbers +// Tool_fb::getAbbreviatedNumbers -- Get abbreviated figured bass numbers // If no abbreviation is found all numbers will be shown -vector Tool_fb::getAbbrNumbers(const vector& numbers) { +vector Tool_fb::getAbbreviatedNumbers(const vector& numbers) { vector abbrNumbers; From 558debf53e554a20872b969d9d4c13bb1e7adbc7 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Wed, 11 Jan 2023 18:35:29 +0100 Subject: [PATCH 041/109] Improve names --- include/tool-fb.h | 4 ++-- src/tool-fb.cpp | 53 +++++++++++++++++++++++------------------------ 2 files changed, 28 insertions(+), 29 deletions(-) diff --git a/include/tool-fb.h b/include/tool-fb.h index 656c0955..50617c3a 100644 --- a/include/tool-fb.h +++ b/include/tool-fb.h @@ -35,7 +35,7 @@ class FiguredBassNumber { int getNumberWithinOctave(void); }; -class FiguredBassAbbr { +class FiguredBassAbbreviationMapping { public: // String to compare the numbers with // e.g. "6 4 3" @@ -45,7 +45,7 @@ class FiguredBassAbbr { // Figured bass number as int vector numbers; - FiguredBassAbbr(string s, vector n); + FiguredBassAbbreviationMapping(string s, vector n); }; class Tool_fb : public HumTool { diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 59e5bc90..bab8d0a0 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -384,45 +384,44 @@ string Tool_fb::formatFiguredBassNumbers(const vector& numbe vector Tool_fb::getAbbreviatedNumbers(const vector& numbers) { - vector abbrNumbers; - - // Mapping to abbreviate figured bass numbers - vector figuredBassAbbrs = { - new FiguredBassAbbr("3", {}), - new FiguredBassAbbr("5", {}), - new FiguredBassAbbr("5 3", {}), - new FiguredBassAbbr("6 3", {6}), - new FiguredBassAbbr("5 4", {4}), - new FiguredBassAbbr("7 5 3", {7}), - new FiguredBassAbbr("7 3", {7}), - new FiguredBassAbbr("7 5", {7}), - new FiguredBassAbbr("6 5 3", {6, 5}), - new FiguredBassAbbr("6 4 3", {4, 3}), - new FiguredBassAbbr("6 4 2", {4, 2}), - new FiguredBassAbbr("9 5 3", {9}), - new FiguredBassAbbr("9 5", {9}), - new FiguredBassAbbr("9 3", {9}), + vector abbreviatedNumbers; + + vector mappings = { + new FiguredBassAbbreviationMapping("3", {}), + new FiguredBassAbbreviationMapping("5", {}), + new FiguredBassAbbreviationMapping("5 3", {}), + new FiguredBassAbbreviationMapping("6 3", {6}), + new FiguredBassAbbreviationMapping("5 4", {4}), + new FiguredBassAbbreviationMapping("7 5 3", {7}), + new FiguredBassAbbreviationMapping("7 3", {7}), + new FiguredBassAbbreviationMapping("7 5", {7}), + new FiguredBassAbbreviationMapping("6 5 3", {6, 5}), + new FiguredBassAbbreviationMapping("6 4 3", {4, 3}), + new FiguredBassAbbreviationMapping("6 4 2", {4, 2}), + new FiguredBassAbbreviationMapping("9 5 3", {9}), + new FiguredBassAbbreviationMapping("9 5", {9}), + new FiguredBassAbbreviationMapping("9 3", {9}), }; string numberString = getNumberString(numbers); // Check if an abbreviation exists for passed numbers - auto it = find_if(figuredBassAbbrs.begin(), figuredBassAbbrs.end(), [numberString](FiguredBassAbbr* abbr) { + auto it = find_if(mappings.begin(), mappings.end(), [numberString](FiguredBassAbbreviationMapping* abbr) { return abbr->str == numberString; }); - if (it != figuredBassAbbrs.end()) { - int index = it - figuredBassAbbrs.begin(); - FiguredBassAbbr* abbr = figuredBassAbbrs[index]; + if (it != mappings.end()) { + int index = it - mappings.begin(); + FiguredBassAbbreviationMapping* abbr = mappings[index]; bool aQ = accidentalsQ; - // Store numbers to display by the abbreviation mapping in abbrNumbers - copy_if(numbers.begin(), numbers.end(), back_inserter(abbrNumbers), [abbr, aQ](FiguredBassNumber* num) { + // Store numbers to display by the abbreviation mapping in abbreviatedNumbers + copy_if(numbers.begin(), numbers.end(), back_inserter(abbreviatedNumbers), [abbr, aQ](FiguredBassNumber* num) { vector nums = abbr->numbers; // Show numbers if they are part of the abbreviation mapping or if they have an accidental return (find(nums.begin(), nums.end(), num->getNumberWithinOctave()) != nums.end()) || (num->showAccidentals && aQ); }); - return abbrNumbers; + return abbreviatedNumbers; } return numbers; @@ -527,11 +526,11 @@ int FiguredBassNumber::getNumberWithinOctave(void) { ////////////////////////////// // -// FiguredBassAbbr::FiguredBassAbbr -- Constructor +// FiguredBassAbbreviationMapping::FiguredBassAbbreviationMapping -- Constructor // Helper class to store the mappings for abbreviate figured bass numbers // -FiguredBassAbbr::FiguredBassAbbr(string s, vector n) { +FiguredBassAbbreviationMapping::FiguredBassAbbreviationMapping(string s, vector n) { str = s; numbers = n; } From 7f389bb4c7f483e42907762dd4db778e41f7fc33 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Wed, 11 Jan 2023 18:37:55 +0100 Subject: [PATCH 042/109] Use static variable for mappings --- include/tool-fb.h | 2 ++ src/tool-fb.cpp | 41 +++++++++++++++++++++++++---------------- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/include/tool-fb.h b/include/tool-fb.h index 50617c3a..1ac0fc19 100644 --- a/include/tool-fb.h +++ b/include/tool-fb.h @@ -37,6 +37,8 @@ class FiguredBassNumber { class FiguredBassAbbreviationMapping { public: + static vector s_mappings; + // String to compare the numbers with // e.g. "6 4 3" // Sorted by size, larger numbers first diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index bab8d0a0..7ed93abf 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -386,22 +386,7 @@ vector Tool_fb::getAbbreviatedNumbers(const vector abbreviatedNumbers; - vector mappings = { - new FiguredBassAbbreviationMapping("3", {}), - new FiguredBassAbbreviationMapping("5", {}), - new FiguredBassAbbreviationMapping("5 3", {}), - new FiguredBassAbbreviationMapping("6 3", {6}), - new FiguredBassAbbreviationMapping("5 4", {4}), - new FiguredBassAbbreviationMapping("7 5 3", {7}), - new FiguredBassAbbreviationMapping("7 3", {7}), - new FiguredBassAbbreviationMapping("7 5", {7}), - new FiguredBassAbbreviationMapping("6 5 3", {6, 5}), - new FiguredBassAbbreviationMapping("6 4 3", {4, 3}), - new FiguredBassAbbreviationMapping("6 4 2", {4, 2}), - new FiguredBassAbbreviationMapping("9 5 3", {9}), - new FiguredBassAbbreviationMapping("9 5", {9}), - new FiguredBassAbbreviationMapping("9 3", {9}), - }; + vector mappings = FiguredBassAbbreviationMapping::s_mappings; string numberString = getNumberString(numbers); @@ -535,6 +520,30 @@ FiguredBassAbbreviationMapping::FiguredBassAbbreviationMapping(string s, vector< numbers = n; } + + +////////////////////////////// +// +// FiguredBassAbbreviationMapping::s_mappings -- Mapping to abbreviate figured bass numbers +// + +vector FiguredBassAbbreviationMapping::s_mappings = { + new FiguredBassAbbreviationMapping("3", {}), + new FiguredBassAbbreviationMapping("5", {}), + new FiguredBassAbbreviationMapping("5 3", {}), + new FiguredBassAbbreviationMapping("6 3", {6}), + new FiguredBassAbbreviationMapping("5 4", {4}), + new FiguredBassAbbreviationMapping("7 5 3", {7}), + new FiguredBassAbbreviationMapping("7 3", {7}), + new FiguredBassAbbreviationMapping("7 5", {7}), + new FiguredBassAbbreviationMapping("6 5 3", {6, 5}), + new FiguredBassAbbreviationMapping("6 4 3", {4, 3}), + new FiguredBassAbbreviationMapping("6 4 2", {4, 2}), + new FiguredBassAbbreviationMapping("9 5 3", {9}), + new FiguredBassAbbreviationMapping("9 5", {9}), + new FiguredBassAbbreviationMapping("9 3", {9}), +}; + // END_MERGE } // end namespace hum From a99b7bcb400d8d79dcacd9e91c3e998d6c608a3a Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Wed, 11 Jan 2023 18:47:06 +0100 Subject: [PATCH 043/109] Prefix member variables and format FiguredBassNumber declaration --- include/tool-fb.h | 23 ++++++++++++----------- src/tool-fb.cpp | 42 +++++++++++++++++++++--------------------- 2 files changed, 33 insertions(+), 32 deletions(-) diff --git a/include/tool-fb.h b/include/tool-fb.h index 1ac0fc19..9f0abe8e 100644 --- a/include/tool-fb.h +++ b/include/tool-fb.h @@ -22,17 +22,18 @@ namespace hum { class FiguredBassNumber { public: - int voiceIndex; - int lineIndex; - int number; - string accidentals; - bool showAccidentals; // Force shoing figured base numbers when they need an accidental - bool currAttackNumberDidChange; - bool isAttack; - - FiguredBassNumber(int num, string accid, bool showAccid, int voiceIndex, int lineIndex, bool isAttack); - string toString(bool nonCompoundIntervalsQ, bool noAccidentalsQ); - int getNumberWithinOctave(void); + FiguredBassNumber(int num, string accid, bool showAccid, int voiceIndex, int lineIndex, bool isAttack); + std::string toString(bool nonCompoundIntervalsQ, bool noAccidentalsQ); + int getNumberWithinOctave(void); + + int m_voiceIndex; + int m_lineIndex; + int m_number; + std::string m_accidentals; + bool m_showAccidentals; // Force shoing figured base numbers when they need an accidental + bool m_currAttackNumberDidChange; + bool m_isAttack; + }; class FiguredBassAbbreviationMapping { diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 7ed93abf..9cbd5da2 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -141,9 +141,9 @@ bool Tool_fb::run(HumdrumFile &infile) { FiguredBassNumber* number = createFiguredBassNumber(baseCell, targetCell, keySignature); if (lastNumbers[j] != 0) { // Set currAttackNumberDidChange - number->currAttackNumberDidChange = (targetCell->isSustained()) && (lastNumbers[j] != number->number); + number->m_currAttackNumberDidChange = (targetCell->isSustained()) && (lastNumbers[j] != number->m_number); } - currentNumbers[j] = number->number; + currentNumbers[j] = number->m_number; numbers.push_back(number); } @@ -273,12 +273,12 @@ vector Tool_fb::filterFiguredBassNumbersForLine(vectorlineIndex == lineIndex; + return num->m_lineIndex == lineIndex; }); // sort by voiceIndex sort(filteredNumbers.begin(), filteredNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { - return a->voiceIndex > b->voiceIndex; + return a->m_voiceIndex > b->m_voiceIndex; }); return filteredNumbers; @@ -297,12 +297,12 @@ vector Tool_fb::filterFiguredBassNumbersForLineAndVoice(vect // filter numbers with passed lineIndex and passed voiceIndex copy_if(numbers.begin(), numbers.end(), back_inserter(filteredNumbers), [lineIndex, voiceIndex](FiguredBassNumber* num) { - return (num->lineIndex == lineIndex) && (num->voiceIndex == voiceIndex); + return (num->m_lineIndex == lineIndex) && (num->m_voiceIndex == voiceIndex); }); // sort by voiceIndex (probably not needed here) sort(filteredNumbers.begin(), filteredNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { - return a->voiceIndex > b->voiceIndex; + return a->m_voiceIndex > b->m_voiceIndex; }); return filteredNumbers; @@ -324,7 +324,7 @@ string Tool_fb::formatFiguredBassNumbers(const vector& numbe bool aQ = accidentalsQ; // remove 8 and 1 but keep them if they have an accidental copy_if(numbers.begin(), numbers.end(), back_inserter(formattedNumbers), [aQ](FiguredBassNumber* num) { - return ((num->getNumberWithinOctave() != 8) && (num->getNumberWithinOctave() != 1)) || (aQ && num->showAccidentals); + return ((num->getNumberWithinOctave() != 8) && (num->getNumberWithinOctave() != 1)) || (aQ && num->m_showAccidentals); }); // sort by size sort(formattedNumbers.begin(), formattedNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { @@ -342,7 +342,7 @@ string Tool_fb::formatFiguredBassNumbers(const vector& numbe if (intervallsatzQ && attackQ) { vector attackNumbers; copy_if(formattedNumbers.begin(), formattedNumbers.end(), back_inserter(attackNumbers), [](FiguredBassNumber* num) { - return num->isAttack || num->currAttackNumberDidChange; + return num->m_isAttack || num->m_currAttackNumberDidChange; }); formattedNumbers = attackNumbers; } @@ -352,7 +352,7 @@ string Tool_fb::formatFiguredBassNumbers(const vector& numbe bool cQ = compoundQ; sort(formattedNumbers.begin(), formattedNumbers.end(), [cQ](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { // sort by getNumberWithinOctave if compoundQ is true otherwise sort by number - return (cQ) ? a->getNumberWithinOctave() > b->getNumberWithinOctave() : a->number > b->number; + return (cQ) ? a->getNumberWithinOctave() > b->getNumberWithinOctave() : a->m_number > b->m_number; }); } @@ -403,7 +403,7 @@ vector Tool_fb::getAbbreviatedNumbers(const vector nums = abbr->numbers; // Show numbers if they are part of the abbreviation mapping or if they have an accidental - return (find(nums.begin(), nums.end(), num->getNumberWithinOctave()) != nums.end()) || (num->showAccidentals && aQ); + return (find(nums.begin(), nums.end(), num->getNumberWithinOctave()) != nums.end()) || (num->m_showAccidentals && aQ); }); return abbreviatedNumbers; @@ -471,12 +471,12 @@ string Tool_fb::getKeySignature(HumdrumFile& infile, int lineIndex) { // FiguredBassNumber::FiguredBassNumber(int num, string accid, bool showAccid, int voiceIdx, int lineIdx, bool isAtk) { - number = num; - accidentals = accid; - voiceIndex = voiceIdx; - lineIndex = lineIdx; - showAccidentals = showAccid; - isAttack = isAtk; + m_number = num; + m_accidentals = accid; + m_voiceIndex = voiceIdx; + m_lineIndex = lineIdx; + m_showAccidentals = showAccid; + m_isAttack = isAtk; } @@ -487,8 +487,8 @@ FiguredBassNumber::FiguredBassNumber(int num, string accid, bool showAccid, int // string FiguredBassNumber::toString(bool compoundQ, bool accidentalsQ) { - int num = (compoundQ) ? getNumberWithinOctave() : number; - string accid = (accidentalsQ && showAccidentals) ? accidentals : ""; + int num = (compoundQ) ? getNumberWithinOctave() : m_number; + string accid = (accidentalsQ && m_showAccidentals) ? m_accidentals : ""; return num > 0 ? to_string(num) + accid : ""; } @@ -500,11 +500,11 @@ string FiguredBassNumber::toString(bool compoundQ, bool accidentalsQ) { // int FiguredBassNumber::getNumberWithinOctave(void) { - int num = (number > 9) ? number % 7 : number; - if ((number > 9) && (number % 7 == 0)) { + int num = (m_number > 9) ? m_number % 7 : m_number; + if ((m_number > 9) && (m_number % 7 == 0)) { num = 7; } - return ((number > 8) && (num == 1)) ? 8 : num; + return ((m_number > 8) && (num == 1)) ? 8 : num; } From da7f9a76e33a3715ff16be80e2ea28615cb2bbfe Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Wed, 11 Jan 2023 18:56:05 +0100 Subject: [PATCH 044/109] Format Tool_fb declaration --- include/tool-fb.h | 57 ++++++++++++++++++++--------------------------- 1 file changed, 24 insertions(+), 33 deletions(-) diff --git a/include/tool-fb.h b/include/tool-fb.h index 9f0abe8e..1a97c139 100644 --- a/include/tool-fb.h +++ b/include/tool-fb.h @@ -54,44 +54,35 @@ class FiguredBassAbbreviationMapping { class Tool_fb : public HumTool { public: - Tool_fb(void); - ~Tool_fb(){}; - - bool run (HumdrumFileSet& infiles); - bool run (HumdrumFile& infile); - bool run (const string& indata, ostream& out); - bool run (HumdrumFile& infile, ostream& out); - - vector getTrackData(const vector& numbers, int lineCount); - - vector getTrackDataForVoice(int voiceIndex, const vector& numbers, int lineCount); - - FiguredBassNumber* createFiguredBassNumber(NoteCell* base, NoteCell* target, string keySignature); - - vector filterFiguredBassNumbersForLine(vector numbers, int lineIndex); - + Tool_fb (void); + ~Tool_fb() {}; + bool run (HumdrumFileSet& infiles); + bool run (HumdrumFile& infile); + bool run (const string& indata, ostream& out); + bool run (HumdrumFile& infile, ostream& out); + + protected: + vector getTrackData (const vector& numbers, int lineCount); + vector getTrackDataForVoice (int voiceIndex, const vector& numbers, int lineCount); + FiguredBassNumber* createFiguredBassNumber (NoteCell* base, NoteCell* target, string keySignature); + vector filterFiguredBassNumbersForLine (vector numbers, int lineIndex); vector filterFiguredBassNumbersForLineAndVoice(vector numbers, int lineIndex, int voiceIndex); + string formatFiguredBassNumbers (const vector& numbers); + vector getAbbreviatedNumbers (const vector& numbers); + string getNumberString (vector numbers); + string getKeySignature (HumdrumFile& infile, int lineIndex); - string formatFiguredBassNumbers(const vector& numbers); - - vector getAbbreviatedNumbers(const vector& numbers); - - string getNumberString(vector numbers); - - string getKeySignature(HumdrumFile& infile, int lineIndex); - - // protected: private: - bool compoundQ = false; - bool accidentalsQ = false; - int baseQ = 0; + bool compoundQ = false; + bool accidentalsQ = false; + int baseQ = 0; bool intervallsatzQ = false; - bool sortQ = false; - bool lowestQ = false; - bool normalizeQ = false; - bool abbrQ = false; - bool attackQ = false; + bool sortQ = false; + bool lowestQ = false; + bool normalizeQ = false; + bool abbrQ = false; + bool attackQ = false; }; From ee8b5b9f68d592c0d091c99e78fd85d59f3cde97 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Wed, 11 Jan 2023 18:58:54 +0100 Subject: [PATCH 045/109] Add m_ prefix to Tool_fb class properties --- include/tool-fb.h | 18 +++++++-------- src/tool-fb.cpp | 56 +++++++++++++++++++++++------------------------ 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/include/tool-fb.h b/include/tool-fb.h index 1a97c139..7e03948b 100644 --- a/include/tool-fb.h +++ b/include/tool-fb.h @@ -74,15 +74,15 @@ class Tool_fb : public HumTool { private: - bool compoundQ = false; - bool accidentalsQ = false; - int baseQ = 0; - bool intervallsatzQ = false; - bool sortQ = false; - bool lowestQ = false; - bool normalizeQ = false; - bool abbrQ = false; - bool attackQ = false; + bool m_compoundQ = false; + bool m_accidentalsQ = false; + int m_baseQ = 0; + bool m_intervallsatzQ = false; + bool m_sortQ = false; + bool m_lowestQ = false; + bool m_normalizeQ = false; + bool m_abbrQ = false; + bool m_attackQ = false; }; diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 9cbd5da2..37dd62a2 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -75,23 +75,23 @@ bool Tool_fb::run(HumdrumFile &infile, ostream &out) { bool Tool_fb::run(HumdrumFile &infile) { - compoundQ = getBoolean("compound"); - accidentalsQ = getBoolean("accidentals"); - baseQ = getInteger("base"); - intervallsatzQ = getBoolean("intervallsatz"); - sortQ = getBoolean("sort"); - lowestQ = getBoolean("lowest"); - normalizeQ = getBoolean("normalize"); - abbrQ = getBoolean("abbr"); - attackQ = getBoolean("attack"); - - if (abbrQ) { - normalizeQ = true; + m_compoundQ = getBoolean("compound"); + m_accidentalsQ = getBoolean("accidentals"); + m_baseQ = getInteger("base"); + m_intervallsatzQ = getBoolean("intervallsatz"); + m_sortQ = getBoolean("sort"); + m_lowestQ = getBoolean("lowest"); + m_normalizeQ = getBoolean("normalize"); + m_abbrQ = getBoolean("abbr"); + m_attackQ = getBoolean("attack"); + + if (m_abbrQ) { + m_normalizeQ = true; } - if (normalizeQ) { - compoundQ = true; - sortQ = true; + if (m_normalizeQ) { + m_compoundQ = true; + m_sortQ = true; } NoteGrid grid(infile); @@ -111,11 +111,11 @@ bool Tool_fb::run(HumdrumFile &infile) { currentNumbers.resize((int)grid.getVoiceCount()); // Reset usedBaseVoiceIndex - int usedBaseVoiceIndex = baseQ; + int usedBaseVoiceIndex = m_baseQ; // Overwrite usedBaseVoiceIndex with the lowest voice index of the lowest pitched note // TODO: check if this still works for chords - if (lowestQ) { + if (m_lowestQ) { int lowestNotePitch = 99999; for (int k=0; k<(int)grid.getVoiceCount(); k++) { NoteCell* checkCell = grid.cell(k, i); @@ -151,7 +151,7 @@ bool Tool_fb::run(HumdrumFile &infile) { lastNumbers = currentNumbers; } - if (intervallsatzQ) { + if (m_intervallsatzQ) { // Create **fb spine for each voice for (int voiceIndex = 0; voiceIndex < grid.getVoiceCount(); voiceIndex++) { vector trackData = getTrackDataForVoice(voiceIndex, numbers, infile.getLineCount()); @@ -165,8 +165,8 @@ bool Tool_fb::run(HumdrumFile &infile) { } else { // Create **fb spine and bind it to the base voice vector trackData = getTrackData(numbers, infile.getLineCount()); - if (baseQ + 1 < grid.getVoiceCount()) { - int trackIndex = kernspines[baseQ + 1]->getTrack(); + if (m_baseQ + 1 < grid.getVoiceCount()) { + int trackIndex = kernspines[m_baseQ + 1]->getTrack(); infile.insertDataSpineBefore(trackIndex, trackData, ".", "**fb"); } else { infile.appendDataSpine(trackData, ".", "**fb"); @@ -320,8 +320,8 @@ string Tool_fb::formatFiguredBassNumbers(const vector& numbe vector formattedNumbers; // Normalize numbers (remove 8 and 1, sort by size, remove duplicate numbers) - if (normalizeQ) { - bool aQ = accidentalsQ; + if (m_normalizeQ) { + bool aQ = m_accidentalsQ; // remove 8 and 1 but keep them if they have an accidental copy_if(numbers.begin(), numbers.end(), back_inserter(formattedNumbers), [aQ](FiguredBassNumber* num) { return ((num->getNumberWithinOctave() != 8) && (num->getNumberWithinOctave() != 1)) || (aQ && num->m_showAccidentals); @@ -339,7 +339,7 @@ string Tool_fb::formatFiguredBassNumbers(const vector& numbe } // Hide numbers if they have no attack - if (intervallsatzQ && attackQ) { + if (m_intervallsatzQ && m_attackQ) { vector attackNumbers; copy_if(formattedNumbers.begin(), formattedNumbers.end(), back_inserter(attackNumbers), [](FiguredBassNumber* num) { return num->m_isAttack || num->m_currAttackNumberDidChange; @@ -348,15 +348,15 @@ string Tool_fb::formatFiguredBassNumbers(const vector& numbe } // Sort numbers by size - if (sortQ) { - bool cQ = compoundQ; + if (m_sortQ) { + bool cQ = m_compoundQ; sort(formattedNumbers.begin(), formattedNumbers.end(), [cQ](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { // sort by getNumberWithinOctave if compoundQ is true otherwise sort by number return (cQ) ? a->getNumberWithinOctave() > b->getNumberWithinOctave() : a->m_number > b->m_number; }); } - if (abbrQ) { + if (m_abbrQ) { // Overwrite formattedNumbers with abbreviated numbers formattedNumbers = getAbbreviatedNumbers(formattedNumbers); } @@ -365,7 +365,7 @@ string Tool_fb::formatFiguredBassNumbers(const vector& numbe string str = ""; bool first = true; for (FiguredBassNumber* number: formattedNumbers) { - string num = number->toString(compoundQ, accidentalsQ); + string num = number->toString(m_compoundQ, m_accidentalsQ); if (num.length() > 0) { if (!first) str += " "; first = false; @@ -398,7 +398,7 @@ vector Tool_fb::getAbbreviatedNumbers(const vector nums = abbr->numbers; From dfd991c2194065aca673519297429e33077ad22c Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Wed, 11 Jan 2023 19:02:16 +0100 Subject: [PATCH 046/109] Format FiguredBassAbbreviationMapping declaration --- include/tool-fb.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/tool-fb.h b/include/tool-fb.h index 7e03948b..0ac5b775 100644 --- a/include/tool-fb.h +++ b/include/tool-fb.h @@ -38,17 +38,18 @@ class FiguredBassNumber { class FiguredBassAbbreviationMapping { public: + FiguredBassAbbreviationMapping(string s, vector n); + static vector s_mappings; - + // String to compare the numbers with // e.g. "6 4 3" // Sorted by size, larger numbers first - string str; + string str; // Figured bass number as int vector numbers; - FiguredBassAbbreviationMapping(string s, vector n); }; class Tool_fb : public HumTool { From 3d129ee55c3f0daeb7a8693cf179adb860e57f01 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Wed, 11 Jan 2023 19:03:09 +0100 Subject: [PATCH 047/109] Add m_ prefix to FiguredBassAbbreviationMapping --- include/tool-fb.h | 4 ++-- src/tool-fb.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/tool-fb.h b/include/tool-fb.h index 0ac5b775..1a6883b8 100644 --- a/include/tool-fb.h +++ b/include/tool-fb.h @@ -45,10 +45,10 @@ class FiguredBassAbbreviationMapping { // String to compare the numbers with // e.g. "6 4 3" // Sorted by size, larger numbers first - string str; + string m_str; // Figured bass number as int - vector numbers; + vector m_numbers; }; diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 37dd62a2..1b6b834e 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -392,7 +392,7 @@ vector Tool_fb::getAbbreviatedNumbers(const vectorstr == numberString; + return abbr->m_str == numberString; }); if (it != mappings.end()) { @@ -401,7 +401,7 @@ vector Tool_fb::getAbbreviatedNumbers(const vector nums = abbr->numbers; + vector nums = abbr->m_numbers; // Show numbers if they are part of the abbreviation mapping or if they have an accidental return (find(nums.begin(), nums.end(), num->getNumberWithinOctave()) != nums.end()) || (num->m_showAccidentals && aQ); }); @@ -516,8 +516,8 @@ int FiguredBassNumber::getNumberWithinOctave(void) { // FiguredBassAbbreviationMapping::FiguredBassAbbreviationMapping(string s, vector n) { - str = s; - numbers = n; + m_str = s; + m_numbers = n; } From d56fe04c7cc33f22072fd1abcacac102063fb617 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Wed, 11 Jan 2023 21:04:24 +0100 Subject: [PATCH 048/109] Fix ordering of accid and number --- src/tool-fb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 1b6b834e..ce520cb0 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -489,7 +489,7 @@ FiguredBassNumber::FiguredBassNumber(int num, string accid, bool showAccid, int string FiguredBassNumber::toString(bool compoundQ, bool accidentalsQ) { int num = (compoundQ) ? getNumberWithinOctave() : m_number; string accid = (accidentalsQ && m_showAccidentals) ? m_accidentals : ""; - return num > 0 ? to_string(num) + accid : ""; + return num > 0 ? accid + to_string(num) : ""; } From 7eeb1c8e83560b4fcac5799e2b8c0a43a100e6e1 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Wed, 11 Jan 2023 21:32:05 +0100 Subject: [PATCH 049/109] Add figuredbass (-f) cli option as shortcut for -c -a -s -l -n -r --- include/tool-fb.h | 1 + src/tool-fb.cpp | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/include/tool-fb.h b/include/tool-fb.h index 1a6883b8..7b7ab093 100644 --- a/include/tool-fb.h +++ b/include/tool-fb.h @@ -84,6 +84,7 @@ class Tool_fb : public HumTool { bool m_normalizeQ = false; bool m_abbrQ = false; bool m_attackQ = false; + bool m_figuredbassQ = false; }; diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index ce520cb0..11e312c8 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -35,6 +35,7 @@ Tool_fb::Tool_fb(void) { define("n|normalize=b", "remove octave and doubled intervals, use compound interval, sort intervals"); define("r|abbr=b", "use abbreviated figures"); define("t|attack=b", "hide intervalls with no attack and when base does not change"); + define("f|figuredbass=b", "Shortcut for -c -a -s -l -n -r -3"); } @@ -84,6 +85,7 @@ bool Tool_fb::run(HumdrumFile &infile) { m_normalizeQ = getBoolean("normalize"); m_abbrQ = getBoolean("abbr"); m_attackQ = getBoolean("attack"); + m_figuredbassQ = getBoolean("figuredbass"); if (m_abbrQ) { m_normalizeQ = true; @@ -94,6 +96,15 @@ bool Tool_fb::run(HumdrumFile &infile) { m_sortQ = true; } + if (m_figuredbassQ) { + m_compoundQ = true; + m_accidentalsQ = true; + m_sortQ = true; + m_lowestQ = true; + m_normalizeQ = true; + m_abbrQ = true; + } + NoteGrid grid(infile); vector numbers; From c5d95582af3605c66848ed93d387a3ff93bee31f Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Wed, 11 Jan 2023 21:34:25 +0100 Subject: [PATCH 050/109] Add hide-three cli option --- include/tool-fb.h | 3 ++- src/tool-fb.cpp | 10 ++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/include/tool-fb.h b/include/tool-fb.h index 7b7ab093..39232ec1 100644 --- a/include/tool-fb.h +++ b/include/tool-fb.h @@ -23,7 +23,7 @@ namespace hum { class FiguredBassNumber { public: FiguredBassNumber(int num, string accid, bool showAccid, int voiceIndex, int lineIndex, bool isAttack); - std::string toString(bool nonCompoundIntervalsQ, bool noAccidentalsQ); + std::string toString(bool nonCompoundIntervalsQ, bool noAccidentalsQ, bool hideThreeQ); int getNumberWithinOctave(void); int m_voiceIndex; @@ -85,6 +85,7 @@ class Tool_fb : public HumTool { bool m_abbrQ = false; bool m_attackQ = false; bool m_figuredbassQ = false; + bool m_hideThreeQ = false; }; diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 11e312c8..a666d410 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -36,6 +36,7 @@ Tool_fb::Tool_fb(void) { define("r|abbr=b", "use abbreviated figures"); define("t|attack=b", "hide intervalls with no attack and when base does not change"); define("f|figuredbass=b", "Shortcut for -c -a -s -l -n -r -3"); + define("3|hide-three=b", "Hide number 3 if it has an accidental (e.g.: #3 => #)"); } @@ -86,6 +87,7 @@ bool Tool_fb::run(HumdrumFile &infile) { m_abbrQ = getBoolean("abbr"); m_attackQ = getBoolean("attack"); m_figuredbassQ = getBoolean("figuredbass"); + m_hideThreeQ = getBoolean("hide-three"); if (m_abbrQ) { m_normalizeQ = true; @@ -103,6 +105,7 @@ bool Tool_fb::run(HumdrumFile &infile) { m_lowestQ = true; m_normalizeQ = true; m_abbrQ = true; + m_hideThreeQ = true; } NoteGrid grid(infile); @@ -376,7 +379,7 @@ string Tool_fb::formatFiguredBassNumbers(const vector& numbe string str = ""; bool first = true; for (FiguredBassNumber* number: formattedNumbers) { - string num = number->toString(m_compoundQ, m_accidentalsQ); + string num = number->toString(m_compoundQ, m_accidentalsQ, m_hideThreeQ); if (num.length() > 0) { if (!first) str += " "; first = false; @@ -497,9 +500,12 @@ FiguredBassNumber::FiguredBassNumber(int num, string accid, bool showAccid, int // FiguredBassNumber::toString -- Convert FiguredBassNumber to a string (accidental + number) // -string FiguredBassNumber::toString(bool compoundQ, bool accidentalsQ) { +string FiguredBassNumber::toString(bool compoundQ, bool accidentalsQ, bool hideThreeQ) { int num = (compoundQ) ? getNumberWithinOctave() : m_number; string accid = (accidentalsQ && m_showAccidentals) ? m_accidentals : ""; + if ((num == 3) && accidentalsQ && m_showAccidentals && hideThreeQ) { + return accid; + } return num > 0 ? accid + to_string(num) : ""; } From cb28bb3102677b3c787162a1304543eaaa189af8 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Wed, 11 Jan 2023 21:34:37 +0100 Subject: [PATCH 051/109] Import cmath for abs function --- src/tool-fb.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index a666d410..20fa9e0a 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -13,6 +13,7 @@ #include "Convert.h" #include "HumRegex.h" #include +#include using namespace std; From 32bfef508d85186b204ac37193101427b31fd4ff Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Wed, 11 Jan 2023 21:49:07 +0100 Subject: [PATCH 052/109] Use lowercase --- src/tool-fb.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 20fa9e0a..f0b284a4 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -36,8 +36,8 @@ Tool_fb::Tool_fb(void) { define("n|normalize=b", "remove octave and doubled intervals, use compound interval, sort intervals"); define("r|abbr=b", "use abbreviated figures"); define("t|attack=b", "hide intervalls with no attack and when base does not change"); - define("f|figuredbass=b", "Shortcut for -c -a -s -l -n -r -3"); - define("3|hide-three=b", "Hide number 3 if it has an accidental (e.g.: #3 => #)"); + define("f|figuredbass=b", "shortcut for -c -a -s -l -n -r -3"); + define("3|hide-three=b", "hide number 3 if it has an accidental (e.g.: #3 => #)"); } From c7eed01cdd259ce846e109ea5502707fbc49009b Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Thu, 12 Jan 2023 17:41:23 +0100 Subject: [PATCH 053/109] Fix accidentals display --- src/tool-fb.cpp | 42 +++++++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index f0b284a4..457ce70a 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -255,21 +255,49 @@ FiguredBassNumber* Tool_fb::createFiguredBassNumber(NoteCell* base, NoteCell* ta // Parse accidental from getSgnKernPitch() string accid = regex_replace(target->getSgnKernPitch(), accidRegex, "$2"); - // Make sure accidWithPitch and keySignature are both lowercase for better comparison - string accidWithPitch = regex_replace(target->getSgnKernPitch(), accidRegex, "$1$2"); - transform(accidWithPitch.begin(), accidWithPitch.end(), accidWithPitch.begin(), [](unsigned char c) { - return tolower(c); - }); + // Transform key signature to lower case transform(keySignature.begin(), keySignature.end(), keySignature.begin(), [](unsigned char c) { return tolower(c); }); - // Only show accidentals when they are not included in the key signature + char targetPitchClass = Convert::kernToDiatonicLC(target->getSgnKernPitch()); + int targetAccidNr = Convert::base40ToAccidental(target->getSgnBase40Pitch()); + string targetAccid; + for (int i=0; igetSgnKernPitch()); + int baseAccidNr = Convert::base40ToAccidental(base->getSgnBase40Pitch()); + string baseAccid; + for (int i=0; igetVoiceIndex(), target->getLineIndex(), target->isAttack()); return number; From 1ef9bd4c55e2a1b5cb37cfbfcfcbe161c46e68cf Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Thu, 12 Jan 2023 17:41:35 +0100 Subject: [PATCH 054/109] Add new line --- include/tool-fb.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/tool-fb.h b/include/tool-fb.h index 39232ec1..1d4724ac 100644 --- a/include/tool-fb.h +++ b/include/tool-fb.h @@ -57,6 +57,7 @@ class Tool_fb : public HumTool { public: Tool_fb (void); ~Tool_fb() {}; + bool run (HumdrumFileSet& infiles); bool run (HumdrumFile& infile); bool run (const string& indata, ostream& out); From 00c51a91104f77557a0f92f7aefe359dffe0dade Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Thu, 12 Jan 2023 17:43:05 +0100 Subject: [PATCH 055/109] Remove lines --- src/tool-fb.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 457ce70a..db0726af 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -250,11 +250,6 @@ FiguredBassNumber* Tool_fb::createFiguredBassNumber(NoteCell* base, NoteCell* ta int targetPitch = target->getSgnDiatonicPitch(); int num = ((basePitch == 0) || (targetPitch == 0)) ? 0 : abs(abs(targetPitch) - abs(basePitch)) + 1; - regex accidRegex("^\\(?(\\w)+([^\\w\\)]*)\\)?$"); - - // Parse accidental from getSgnKernPitch() - string accid = regex_replace(target->getSgnKernPitch(), accidRegex, "$2"); - // Transform key signature to lower case transform(keySignature.begin(), keySignature.end(), keySignature.begin(), [](unsigned char c) { return tolower(c); From 94c30bc3e8fb69adbc43061dc2ac53bcad13201a Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Thu, 12 Jan 2023 18:48:07 +0100 Subject: [PATCH 056/109] Add support for negative numbers --- include/tool-fb.h | 2 ++ src/tool-fb.cpp | 53 +++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 46 insertions(+), 9 deletions(-) diff --git a/include/tool-fb.h b/include/tool-fb.h index 1d4724ac..d8161c83 100644 --- a/include/tool-fb.h +++ b/include/tool-fb.h @@ -67,6 +67,7 @@ class Tool_fb : public HumTool { vector getTrackData (const vector& numbers, int lineCount); vector getTrackDataForVoice (int voiceIndex, const vector& numbers, int lineCount); FiguredBassNumber* createFiguredBassNumber (NoteCell* base, NoteCell* target, string keySignature); + vector filterNegativeNumbers (vector numbers); vector filterFiguredBassNumbersForLine (vector numbers, int lineIndex); vector filterFiguredBassNumbersForLineAndVoice(vector numbers, int lineIndex, int voiceIndex); string formatFiguredBassNumbers (const vector& numbers); @@ -87,6 +88,7 @@ class Tool_fb : public HumTool { bool m_attackQ = false; bool m_figuredbassQ = false; bool m_hideThreeQ = false; + bool m_showNegativeQ = false; }; diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index db0726af..85ad7c3c 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -38,6 +38,7 @@ Tool_fb::Tool_fb(void) { define("t|attack=b", "hide intervalls with no attack and when base does not change"); define("f|figuredbass=b", "shortcut for -c -a -s -l -n -r -3"); define("3|hide-three=b", "hide number 3 if it has an accidental (e.g.: #3 => #)"); + define("m|negative=b", "show negative numbers"); } @@ -89,6 +90,7 @@ bool Tool_fb::run(HumdrumFile &infile) { m_attackQ = getBoolean("attack"); m_figuredbassQ = getBoolean("figuredbass"); m_hideThreeQ = getBoolean("hide-three"); + m_showNegativeQ = getBoolean("negative"); if (m_abbrQ) { m_normalizeQ = true; @@ -248,7 +250,15 @@ FiguredBassNumber* Tool_fb::createFiguredBassNumber(NoteCell* base, NoteCell* ta // There is currenlty no support for negative numbers (e.g. with intervallsatz) int basePitch = base->getSgnDiatonicPitch(); int targetPitch = target->getSgnDiatonicPitch(); - int num = ((basePitch == 0) || (targetPitch == 0)) ? 0 : abs(abs(targetPitch) - abs(basePitch)) + 1; + int diff = ((basePitch == 0) || (targetPitch == 0)) ? 0 : abs(targetPitch) - abs(basePitch); + int num; + if (diff == 0) { + num = 1; + } else if (diff > 0) { + num = diff + 1; + } else { + num = diff - 1; + } // Transform key signature to lower case transform(keySignature.begin(), keySignature.end(), keySignature.begin(), [](unsigned char c) { @@ -300,6 +310,25 @@ FiguredBassNumber* Tool_fb::createFiguredBassNumber(NoteCell* base, NoteCell* ta +////////////////////////////// +// +// Tool_fb::filterNegativeNumbers -- Hide negative numbers if m_showNegativeQ if not true +// + +vector Tool_fb::filterNegativeNumbers(vector numbers) { + + vector filteredNumbers; + + bool mQ = m_showNegativeQ; + copy_if(numbers.begin(), numbers.end(), back_inserter(filteredNumbers), [mQ](FiguredBassNumber* num) { + return mQ ? true : (num->m_number > 0); + }); + + return filteredNumbers; +} + + + ////////////////////////////// // // Tool_fb::filterFiguredBassNumbersForLine -- Find all FiguredBassNumber objects for a slice (line index) of the music. @@ -319,7 +348,7 @@ vector Tool_fb::filterFiguredBassNumbersForLine(vectorm_voiceIndex > b->m_voiceIndex; }); - return filteredNumbers; + return filterNegativeNumbers(filteredNumbers); } @@ -343,7 +372,7 @@ vector Tool_fb::filterFiguredBassNumbersForLineAndVoice(vect return a->m_voiceIndex > b->m_voiceIndex; }); - return filteredNumbers; + return filterNegativeNumbers(filteredNumbers); } @@ -527,10 +556,16 @@ FiguredBassNumber::FiguredBassNumber(int num, string accid, bool showAccid, int string FiguredBassNumber::toString(bool compoundQ, bool accidentalsQ, bool hideThreeQ) { int num = (compoundQ) ? getNumberWithinOctave() : m_number; string accid = (accidentalsQ && m_showAccidentals) ? m_accidentals : ""; - if ((num == 3) && accidentalsQ && m_showAccidentals && hideThreeQ) { + if (((num == 3) || (num == -3)) && accidentalsQ && m_showAccidentals && hideThreeQ) { return accid; } - return num > 0 ? accid + to_string(num) : ""; + if (num > 0) { + return accid + to_string(num); + } + if (num < 0) { + return accid + "m" + to_string(abs(num)); + } + return ""; } @@ -541,11 +576,11 @@ string FiguredBassNumber::toString(bool compoundQ, bool accidentalsQ, bool hideT // int FiguredBassNumber::getNumberWithinOctave(void) { - int num = (m_number > 9) ? m_number % 7 : m_number; - if ((m_number > 9) && (m_number % 7 == 0)) { - num = 7; + int num = ((m_number > 9) || (m_number < -9)) ? m_number % 7 : m_number; + if (((m_number > 9) || m_number < -9) && (m_number % 7 == 0)) { + num = m_number < 0 ? -7 : 7; } - return ((m_number > 8) && (num == 1)) ? 8 : num; + return (((m_number > 8) || (m_number < -8)) && (num == 1)) ? (m_number < 0 ? -8 : 8) : num; } From bfb1be953bcccfeb0e98951a0e279f8b467f91b0 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Thu, 12 Jan 2023 18:59:36 +0100 Subject: [PATCH 057/109] Add cli option --fba to display numbers above the staff --- include/tool-fb.h | 1 + src/tool-fb.cpp | 12 ++++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/include/tool-fb.h b/include/tool-fb.h index d8161c83..d787eb18 100644 --- a/include/tool-fb.h +++ b/include/tool-fb.h @@ -89,6 +89,7 @@ class Tool_fb : public HumTool { bool m_figuredbassQ = false; bool m_hideThreeQ = false; bool m_showNegativeQ = false; + bool m_fbaQ = false; }; diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 85ad7c3c..cab70410 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -39,6 +39,7 @@ Tool_fb::Tool_fb(void) { define("f|figuredbass=b", "shortcut for -c -a -s -l -n -r -3"); define("3|hide-three=b", "hide number 3 if it has an accidental (e.g.: #3 => #)"); define("m|negative=b", "show negative numbers"); + define("fba=b", "use **fba spines instead of **fb spines"); } @@ -91,6 +92,7 @@ bool Tool_fb::run(HumdrumFile &infile) { m_figuredbassQ = getBoolean("figuredbass"); m_hideThreeQ = getBoolean("hide-three"); m_showNegativeQ = getBoolean("negative"); + m_fbaQ = getBoolean("fba"); if (m_abbrQ) { m_normalizeQ = true; @@ -168,15 +170,17 @@ bool Tool_fb::run(HumdrumFile &infile) { lastNumbers = currentNumbers; } + string exinterp = m_fbaQ ? "**fba" : "**fb"; + if (m_intervallsatzQ) { // Create **fb spine for each voice for (int voiceIndex = 0; voiceIndex < grid.getVoiceCount(); voiceIndex++) { vector trackData = getTrackDataForVoice(voiceIndex, numbers, infile.getLineCount()); if (voiceIndex + 1 < grid.getVoiceCount()) { int trackIndex = kernspines[voiceIndex + 1]->getTrack(); - infile.insertDataSpineBefore(trackIndex, trackData, ".", "**fb"); + infile.insertDataSpineBefore(trackIndex, trackData, ".", exinterp); } else { - infile.appendDataSpine(trackData, ".", "**fb"); + infile.appendDataSpine(trackData, ".", exinterp); } } } else { @@ -184,9 +188,9 @@ bool Tool_fb::run(HumdrumFile &infile) { vector trackData = getTrackData(numbers, infile.getLineCount()); if (m_baseQ + 1 < grid.getVoiceCount()) { int trackIndex = kernspines[m_baseQ + 1]->getTrack(); - infile.insertDataSpineBefore(trackIndex, trackData, ".", "**fb"); + infile.insertDataSpineBefore(trackIndex, trackData, ".", exinterp); } else { - infile.appendDataSpine(trackData, ".", "**fb"); + infile.appendDataSpine(trackData, ".", exinterp); } } From efd737a822cad1be48c6e6ac247b3a2e22b704d7 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Thu, 12 Jan 2023 19:16:07 +0100 Subject: [PATCH 058/109] Fix num for rests --- src/tool-fb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index cab70410..727c3ac5 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -257,7 +257,7 @@ FiguredBassNumber* Tool_fb::createFiguredBassNumber(NoteCell* base, NoteCell* ta int diff = ((basePitch == 0) || (targetPitch == 0)) ? 0 : abs(targetPitch) - abs(basePitch); int num; if (diff == 0) { - num = 1; + num = 0; } else if (diff > 0) { num = diff + 1; } else { From 58f10498417fb2b0f1607a71648436b65c7e807d Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Thu, 12 Jan 2023 19:41:24 +0100 Subject: [PATCH 059/109] Replace single quotes with double quotes --- src/tool-fb.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 727c3ac5..45f3bbc1 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -273,14 +273,14 @@ FiguredBassNumber* Tool_fb::createFiguredBassNumber(NoteCell* base, NoteCell* ta int targetAccidNr = Convert::base40ToAccidental(target->getSgnBase40Pitch()); string targetAccid; for (int i=0; igetSgnKernPitch()); int baseAccidNr = Convert::base40ToAccidental(base->getSgnBase40Pitch()); string baseAccid; for (int i=0; i Date: Thu, 12 Jan 2023 19:43:19 +0100 Subject: [PATCH 060/109] Fix num calculation for rests and unisono --- src/tool-fb.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 45f3bbc1..e1af6a9c 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -250,14 +250,16 @@ vector Tool_fb::getTrackDataForVoice(int voiceIndex, const vector
getSgnDiatonicPitch(); int targetPitch = target->getSgnDiatonicPitch(); - int diff = ((basePitch == 0) || (targetPitch == 0)) ? 0 : abs(targetPitch) - abs(basePitch); + int diff = abs(targetPitch) - abs(basePitch); int num; - if (diff == 0) { + + if ((basePitch == 0) || (targetPitch == 0)) { num = 0; + } else if (diff == 0) { + num = 1; } else if (diff > 0) { num = diff + 1; } else { From 29452088f359e2876c5b34a9962025c3a487bf01 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Thu, 12 Jan 2023 20:29:07 +0100 Subject: [PATCH 061/109] Fix accidentals for sustained notes --- src/tool-fb.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index e1af6a9c..514e009c 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -271,15 +271,15 @@ FiguredBassNumber* Tool_fb::createFiguredBassNumber(NoteCell* base, NoteCell* ta return tolower(c); }); - char targetPitchClass = Convert::kernToDiatonicLC(target->getSgnKernPitch()); - int targetAccidNr = Convert::base40ToAccidental(target->getSgnBase40Pitch()); + char targetPitchClass = Convert::kernToDiatonicLC(Convert::base40ToKern((int)target->getAbsBase40Pitch())); + int targetAccidNr = Convert::base40ToAccidental(target->getAbsBase40Pitch()); string targetAccid; for (int i=0; igetSgnKernPitch()); - int baseAccidNr = Convert::base40ToAccidental(base->getSgnBase40Pitch()); + char basePitchClass = Convert::kernToDiatonicLC(Convert::base40ToKern((int)base->getAbsBase40Pitch())); + int baseAccidNr = Convert::base40ToAccidental(base->getAbsBase40Pitch()); string baseAccid; for (int i=0; i Date: Thu, 12 Jan 2023 23:36:53 +0100 Subject: [PATCH 062/109] Simplify getNumberWithinOctave --- src/tool-fb.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 514e009c..343ab48a 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -578,15 +578,24 @@ string FiguredBassNumber::toString(bool compoundQ, bool accidentalsQ, bool hideT ////////////////////////////// // -// FiguredBassNumber::getNumberWithinOctave -- Get figured bass number as non compound interval (base 7) -// +// FiguredBassNumber::getNumberWithinOctave -- Get a reasonable figured bass number +// Replace 0 with 7 and -7 +// Replace 1 with 8 and -8 int FiguredBassNumber::getNumberWithinOctave(void) { - int num = ((m_number > 9) || (m_number < -9)) ? m_number % 7 : m_number; - if (((m_number > 9) || m_number < -9) && (m_number % 7 == 0)) { - num = m_number < 0 ? -7 : 7; + int num = m_number % 7; + + // Replace 0 with 7 and -7 + if (abs(num) == 0) { + return m_number < 0 ? -7 : 7; } - return (((m_number > 8) || (m_number < -8)) && (num == 1)) ? (m_number < 0 ? -8 : 8) : num; + + // Replace 1 with 8 and -8 + if (abs(num) == 1) { + return m_number < 0 ? -8 : 8; + } + + return num; } From 8406ffa362d894126c4445397ad489ee7925d943 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Thu, 12 Jan 2023 23:48:38 +0100 Subject: [PATCH 063/109] Replace 2 with 9 if a 3 is included in the chord numbers --- include/tool-fb.h | 2 ++ src/tool-fb.cpp | 37 ++++++++++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/include/tool-fb.h b/include/tool-fb.h index d787eb18..a6221549 100644 --- a/include/tool-fb.h +++ b/include/tool-fb.h @@ -33,6 +33,7 @@ class FiguredBassNumber { bool m_showAccidentals; // Force shoing figured base numbers when they need an accidental bool m_currAttackNumberDidChange; bool m_isAttack; + bool m_convert2To9 = false; }; @@ -71,6 +72,7 @@ class Tool_fb : public HumTool { vector filterFiguredBassNumbersForLine (vector numbers, int lineIndex); vector filterFiguredBassNumbersForLineAndVoice(vector numbers, int lineIndex, int voiceIndex); string formatFiguredBassNumbers (const vector& numbers); + vector analyzeChordNumbers (const vector& numbers); vector getAbbreviatedNumbers (const vector& numbers); string getNumberString (vector numbers); string getKeySignature (HumdrumFile& infile, int lineIndex); diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 343ab48a..a5281945 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -27,7 +27,7 @@ namespace hum { // Tool_fb::Tool_fb(void) { - define("c|compound=b", "output compound intervals for intervals bigger than 9"); + define("c|compound=b", "output reasonable figured bass numbers within octave"); define("a|accidentals=b", "display accidentals in figured bass output"); define("b|base=i:0", "number of the base voice/spine"); define("i|intervallsatz=b", "display intervals under their voice and not under the lowest staff"); @@ -420,6 +420,11 @@ string Tool_fb::formatFiguredBassNumbers(const vector& numbe formattedNumbers = attackNumbers; } + // Analysze before sorting + if (m_compoundQ) { + formattedNumbers = analyzeChordNumbers(formattedNumbers); + } + // Sort numbers by size if (m_sortQ) { bool cQ = m_compoundQ; @@ -487,6 +492,30 @@ vector Tool_fb::getAbbreviatedNumbers(const vector Tool_fb::analyzeChordNumbers(const vector& numbers) { + + vector analyzedNumbers = numbers; + + // Check if compound numbers 3 is withing passed numbers (chord) + auto it = find_if(analyzedNumbers.begin(), analyzedNumbers.end(), [](FiguredBassNumber* number) { + return number->getNumberWithinOctave() == 3; + }); + if (it != analyzedNumbers.end()) { + for (auto &number : analyzedNumbers) { + number->m_convert2To9 = true; + } + } + + return analyzedNumbers; +} + + + ////////////////////////////// // // Tool_fb::getNumberString -- Get only the numbers (without accidentals) of passed FiguredBassNumbers @@ -581,6 +610,7 @@ string FiguredBassNumber::toString(bool compoundQ, bool accidentalsQ, bool hideT // FiguredBassNumber::getNumberWithinOctave -- Get a reasonable figured bass number // Replace 0 with 7 and -7 // Replace 1 with 8 and -8 +// Replace 2 with 9 if it is a suspension of the ninth int FiguredBassNumber::getNumberWithinOctave(void) { int num = m_number % 7; @@ -595,6 +625,11 @@ int FiguredBassNumber::getNumberWithinOctave(void) { return m_number < 0 ? -8 : 8; } + // Replace 2 with 9 if m_convert2To9 is true (e.g. when a 3 is included in the chord numbers) + if (m_convert2To9 && (num == 2)) { + return 9; + } + return num; } From f942d632eb5ec2c0390f5cb5bae50c064287d563 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Thu, 12 Jan 2023 23:49:05 +0100 Subject: [PATCH 064/109] Remove -l from --figuredbass --- src/tool-fb.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index a5281945..2e60f8b7 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -36,7 +36,7 @@ Tool_fb::Tool_fb(void) { define("n|normalize=b", "remove octave and doubled intervals, use compound interval, sort intervals"); define("r|abbr=b", "use abbreviated figures"); define("t|attack=b", "hide intervalls with no attack and when base does not change"); - define("f|figuredbass=b", "shortcut for -c -a -s -l -n -r -3"); + define("f|figuredbass=b", "shortcut for -c -a -s -n -r -3"); define("3|hide-three=b", "hide number 3 if it has an accidental (e.g.: #3 => #)"); define("m|negative=b", "show negative numbers"); define("fba=b", "use **fba spines instead of **fb spines"); @@ -107,7 +107,6 @@ bool Tool_fb::run(HumdrumFile &infile) { m_compoundQ = true; m_accidentalsQ = true; m_sortQ = true; - m_lowestQ = true; m_normalizeQ = true; m_abbrQ = true; m_hideThreeQ = true; From b59747f5adefb7dc403a5a3b5ade5136a32778e6 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Thu, 12 Jan 2023 23:51:39 +0100 Subject: [PATCH 065/109] Improve description for --normalize and --abbr --- src/tool-fb.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 2e60f8b7..e29b8ea2 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -33,8 +33,8 @@ Tool_fb::Tool_fb(void) { define("i|intervallsatz=b", "display intervals under their voice and not under the lowest staff"); define("s|sort=b", "sort figured bass numbers by interval size and not by voice index"); define("l|lowest=b", "use lowest note as base note; -b flag will be ignored"); - define("n|normalize=b", "remove octave and doubled intervals, use compound interval, sort intervals"); - define("r|abbr=b", "use abbreviated figures"); + define("n|normalize=b", "remove octave and doubled intervals; adds: --compound --sort"); + define("r|abbr=b", "use abbreviated figures; adds: --normalize --compound --sort"); define("t|attack=b", "hide intervalls with no attack and when base does not change"); define("f|figuredbass=b", "shortcut for -c -a -s -n -r -3"); define("3|hide-three=b", "hide number 3 if it has an accidental (e.g.: #3 => #)"); @@ -94,21 +94,23 @@ bool Tool_fb::run(HumdrumFile &infile) { m_showNegativeQ = getBoolean("negative"); m_fbaQ = getBoolean("fba"); - if (m_abbrQ) { - m_normalizeQ = true; + if (m_normalizeQ) { + m_compoundQ = true; + m_sortQ = true; } - if (m_normalizeQ) { + if (m_abbrQ) { + m_normalizeQ = true; m_compoundQ = true; m_sortQ = true; } if (m_figuredbassQ) { + m_abbrQ = true; + m_normalizeQ = true; m_compoundQ = true; - m_accidentalsQ = true; m_sortQ = true; - m_normalizeQ = true; - m_abbrQ = true; + m_accidentalsQ = true; m_hideThreeQ = true; } From 9eadefb61d708ee9fe3a6a754bd9bf3e4d666701 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Fri, 13 Jan 2023 00:07:26 +0100 Subject: [PATCH 066/109] Fix shown 7 at rests again --- src/tool-fb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index e29b8ea2..9593e893 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -617,7 +617,7 @@ int FiguredBassNumber::getNumberWithinOctave(void) { int num = m_number % 7; // Replace 0 with 7 and -7 - if (abs(num) == 0) { + if ((abs(m_number) == 0) && (m_number != 0)) { return m_number < 0 ? -7 : 7; } From bdee55eb7ac76b10957310641520065c6a2074fc Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Fri, 13 Jan 2023 15:20:31 +0100 Subject: [PATCH 067/109] Add support for display numbers on certain rhythmic positions --- include/tool-fb.h | 28 +++++++++++++++------------- src/tool-fb.cpp | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 13 deletions(-) diff --git a/include/tool-fb.h b/include/tool-fb.h index a6221549..9e679b84 100644 --- a/include/tool-fb.h +++ b/include/tool-fb.h @@ -65,6 +65,7 @@ class Tool_fb : public HumTool { bool run (HumdrumFile& infile, ostream& out); protected: + bool hideNumbersForTokenLine (HTp token, pair timeSig); vector getTrackData (const vector& numbers, int lineCount); vector getTrackDataForVoice (int voiceIndex, const vector& numbers, int lineCount); FiguredBassNumber* createFiguredBassNumber (NoteCell* base, NoteCell* target, string keySignature); @@ -79,19 +80,20 @@ class Tool_fb : public HumTool { private: - bool m_compoundQ = false; - bool m_accidentalsQ = false; - int m_baseQ = 0; - bool m_intervallsatzQ = false; - bool m_sortQ = false; - bool m_lowestQ = false; - bool m_normalizeQ = false; - bool m_abbrQ = false; - bool m_attackQ = false; - bool m_figuredbassQ = false; - bool m_hideThreeQ = false; - bool m_showNegativeQ = false; - bool m_fbaQ = false; + bool m_compoundQ = false; + bool m_accidentalsQ = false; + int m_baseQ = 0; + bool m_intervallsatzQ = false; + bool m_sortQ = false; + bool m_lowestQ = false; + bool m_normalizeQ = false; + bool m_abbrQ = false; + bool m_attackQ = false; + bool m_figuredbassQ = false; + bool m_hideThreeQ = false; + bool m_showNegativeQ = false; + bool m_fbaQ = false; + string m_recipQ = ""; }; diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 9593e893..fef47bb7 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -40,6 +40,7 @@ Tool_fb::Tool_fb(void) { define("3|hide-three=b", "hide number 3 if it has an accidental (e.g.: #3 => #)"); define("m|negative=b", "show negative numbers"); define("fba=b", "use **fba spines instead of **fb spines"); + define("recip=s:", "only show numbers if they are divisible by this **recip value (e.g. 2, 4, 8, 4.)"); } @@ -93,6 +94,7 @@ bool Tool_fb::run(HumdrumFile &infile) { m_hideThreeQ = getBoolean("hide-three"); m_showNegativeQ = getBoolean("negative"); m_fbaQ = getBoolean("fba"); + m_recipQ = getString("recip"); if (m_normalizeQ) { m_compoundQ = true; @@ -150,6 +152,17 @@ bool Tool_fb::run(HumdrumFile &infile) { NoteCell* baseCell = grid.cell(usedBaseVoiceIndex, i); string keySignature = getKeySignature(infile, baseCell->getLineIndex()); + // Hide numbers if they do not match rhythmic position of --recip + if (!m_recipQ.empty()) { + // Get time signatures + vector> timeSigs; + infile.getTimeSigs(timeSigs, baseCell->getToken()->getTrack()); + // Ignore numbers if they don't fit + if (hideNumbersForTokenLine(baseCell->getToken(), timeSigs[baseCell->getLineIndex()])) { + continue; + } + } + // Interate through each voice for (int j=0; j<(int)grid.getVoiceCount(); j++) { if (j == usedBaseVoiceIndex) { @@ -200,6 +213,31 @@ bool Tool_fb::run(HumdrumFile &infile) { +////////////////////////////// +// +// Tool_fb::hideNumbersForTokenLine -- Checks if rhythmic position of line should display numbers +// + +bool Tool_fb::hideNumbersForTokenLine(HTp token, pair timeSig) { + // Get note duration from --recip option + HumNum recip = Convert::recipToDuration(m_recipQ); + if (recip.toFloat() != 0) { + float timeSigBarDuration = timeSig.first * Convert::recipToDuration(to_string(timeSig.second.getInteger())).toFloat(); + float durationFromBarline = token->getDurationFromBarline().toFloat(); + // Handle upbeats + if (token->getBarlineDuration().toFloat() < timeSigBarDuration) { + // Fix durationFromBarline when current bar duration is shorter than + // the bar duration of the time signature + durationFromBarline = timeSigBarDuration - token->getDurationToBarline().toFloat(); + } + // Checks if rhythmic position is divisible by recip duration + return fmod(durationFromBarline, recip.toFloat()) != 0; + } + return false; +} + + + ////////////////////////////// // // Tool_fb::getTrackData -- Create **fb spine data with formatted numbers for all voices From 9e6ae2cfa1ccba45a8fec9efe1e0bfd36622f056 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Fri, 13 Jan 2023 15:21:35 +0100 Subject: [PATCH 068/109] Rename option --fba to --above --- include/tool-fb.h | 2 +- src/tool-fb.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/tool-fb.h b/include/tool-fb.h index 9e679b84..b60adbd3 100644 --- a/include/tool-fb.h +++ b/include/tool-fb.h @@ -92,7 +92,7 @@ class Tool_fb : public HumTool { bool m_figuredbassQ = false; bool m_hideThreeQ = false; bool m_showNegativeQ = false; - bool m_fbaQ = false; + bool m_aboveQ = false; string m_recipQ = ""; }; diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index fef47bb7..638e0e06 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -39,7 +39,7 @@ Tool_fb::Tool_fb(void) { define("f|figuredbass=b", "shortcut for -c -a -s -n -r -3"); define("3|hide-three=b", "hide number 3 if it has an accidental (e.g.: #3 => #)"); define("m|negative=b", "show negative numbers"); - define("fba=b", "use **fba spines instead of **fb spines"); + define("above=b", "place figured bass numbers above staff (**fba)"); define("recip=s:", "only show numbers if they are divisible by this **recip value (e.g. 2, 4, 8, 4.)"); } @@ -93,7 +93,7 @@ bool Tool_fb::run(HumdrumFile &infile) { m_figuredbassQ = getBoolean("figuredbass"); m_hideThreeQ = getBoolean("hide-three"); m_showNegativeQ = getBoolean("negative"); - m_fbaQ = getBoolean("fba"); + m_aboveQ = getBoolean("above"); m_recipQ = getString("recip"); if (m_normalizeQ) { @@ -184,7 +184,7 @@ bool Tool_fb::run(HumdrumFile &infile) { lastNumbers = currentNumbers; } - string exinterp = m_fbaQ ? "**fba" : "**fb"; + string exinterp = m_aboveQ ? "**fba" : "**fb"; if (m_intervallsatzQ) { // Create **fb spine for each voice From 2c35952952100c84f1820bf60d3b822ebdbcf69d Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Fri, 13 Jan 2023 15:41:28 +0100 Subject: [PATCH 069/109] Change signifier for negative numbers to v --- src/tool-fb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 638e0e06..20c6e07b 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -637,7 +637,7 @@ string FiguredBassNumber::toString(bool compoundQ, bool accidentalsQ, bool hideT return accid + to_string(num); } if (num < 0) { - return accid + "m" + to_string(abs(num)); + return accid + "v" + to_string(abs(num)); } return ""; } From bd337ebe1e0d7acd53b3252a86b440dc5efeb652 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Fri, 13 Jan 2023 19:39:45 +0100 Subject: [PATCH 070/109] Change signifier for negative figured bass numbers to `~` --- src/tool-fb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 20c6e07b..559fe317 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -637,7 +637,7 @@ string FiguredBassNumber::toString(bool compoundQ, bool accidentalsQ, bool hideT return accid + to_string(num); } if (num < 0) { - return accid + "v" + to_string(abs(num)); + return accid + "~" + to_string(abs(num)); } return ""; } From 7aad91ace52c689f2e1c32f3857ba3d6886d8302 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Fri, 13 Jan 2023 23:12:36 +0100 Subject: [PATCH 071/109] Fix typo --- src/tool-fb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 559fe317..09a197d1 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -533,7 +533,7 @@ vector Tool_fb::getAbbreviatedNumbers(const vector Tool_fb::analyzeChordNumbers(const vector& numbers) { From 728fd0b338f8d8670c0ccf3b958771e8a0b792ea Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Fri, 13 Jan 2023 23:13:14 +0100 Subject: [PATCH 072/109] Allow unisono in intervallsatz if --compound --- include/tool-fb.h | 3 ++- src/tool-fb.cpp | 12 ++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/include/tool-fb.h b/include/tool-fb.h index b60adbd3..1e58dc1d 100644 --- a/include/tool-fb.h +++ b/include/tool-fb.h @@ -22,7 +22,7 @@ namespace hum { class FiguredBassNumber { public: - FiguredBassNumber(int num, string accid, bool showAccid, int voiceIndex, int lineIndex, bool isAttack); + FiguredBassNumber(int num, string accid, bool showAccid, int voiceIndex, int lineIndex, bool isAttack, bool intervallsatz); std::string toString(bool nonCompoundIntervalsQ, bool noAccidentalsQ, bool hideThreeQ); int getNumberWithinOctave(void); @@ -34,6 +34,7 @@ class FiguredBassNumber { bool m_currAttackNumberDidChange; bool m_isAttack; bool m_convert2To9 = false; + bool m_intervallsatz = false; }; diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 09a197d1..3ecf4764 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -348,7 +348,7 @@ FiguredBassNumber* Tool_fb::createFiguredBassNumber(NoteCell* base, NoteCell* ta } } - FiguredBassNumber* number = new FiguredBassNumber(num, accid, showAccid, target->getVoiceIndex(), target->getLineIndex(), target->isAttack()); + FiguredBassNumber* number = new FiguredBassNumber(num, accid, showAccid, target->getVoiceIndex(), target->getLineIndex(), target->isAttack(), m_intervallsatzQ); return number; } @@ -611,13 +611,14 @@ string Tool_fb::getKeySignature(HumdrumFile& infile, int lineIndex) { // FiguredBassNumber::FiguredBassNumber -- Constructor // -FiguredBassNumber::FiguredBassNumber(int num, string accid, bool showAccid, int voiceIdx, int lineIdx, bool isAtk) { +FiguredBassNumber::FiguredBassNumber(int num, string accid, bool showAccid, int voiceIdx, int lineIdx, bool isAtk, bool intervallsatz) { m_number = num; m_accidentals = accid; m_voiceIndex = voiceIdx; m_lineIndex = lineIdx; m_showAccidentals = showAccid; m_isAttack = isAtk; + m_intervallsatz = intervallsatz; } @@ -650,6 +651,7 @@ string FiguredBassNumber::toString(bool compoundQ, bool accidentalsQ, bool hideT // Replace 0 with 7 and -7 // Replace 1 with 8 and -8 // Replace 2 with 9 if it is a suspension of the ninth +// Allow 1 (unisono) in intervallsatz int FiguredBassNumber::getNumberWithinOctave(void) { int num = m_number % 7; @@ -661,6 +663,12 @@ int FiguredBassNumber::getNumberWithinOctave(void) { // Replace 1 with 8 and -8 if (abs(num) == 1) { + // Allow unisono in intervallsatz + if (m_intervallsatz) { + if (abs(m_number) == 1) { + return 1; + } + } return m_number < 0 ? -8 : 8; } From cc65cd23bfa0f959e0d1cd1a7dd9b78fda377bfb Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Fri, 13 Jan 2023 23:16:27 +0100 Subject: [PATCH 073/109] Ignore number if either base or target is a rest or silent note --- src/tool-fb.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 3ecf4764..5e343958 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -170,6 +170,13 @@ bool Tool_fb::run(HumdrumFile &infile) { continue; } NoteCell* targetCell = grid.cell(j, i); + + // Ignore if either base or target is a rest or silent note + if (targetCell->getSgnBase40Pitch() == -1000 || targetCell->getSgnBase40Pitch() == -2000 || + baseCell->getSgnBase40Pitch() == -1000 || baseCell->getSgnBase40Pitch() == -2000) { + continue; + } + // Create FiguredBassNumber FiguredBassNumber* number = createFiguredBassNumber(baseCell, targetCell, keySignature); if (lastNumbers[j] != 0) { From bcfc1d935296dfc15cd6b50b4d8fdac29c77dd4b Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Sat, 14 Jan 2023 18:30:16 +0100 Subject: [PATCH 074/109] Add initialize and processFile methods --- include/tool-fb.h | 2 ++ src/tool-fb.cpp | 24 ++++++++++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/include/tool-fb.h b/include/tool-fb.h index 1e58dc1d..33e6b1b3 100644 --- a/include/tool-fb.h +++ b/include/tool-fb.h @@ -66,6 +66,8 @@ class Tool_fb : public HumTool { bool run (HumdrumFile& infile, ostream& out); protected: + void initialize (void); + void processFile (HumdrumFile& infile); bool hideNumbersForTokenLine (HTp token, pair timeSig); vector getTrackData (const vector& numbers, int lineCount); vector getTrackDataForVoice (int voiceIndex, const vector& numbers, int lineCount); diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 5e343958..405aba7c 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -80,7 +80,19 @@ bool Tool_fb::run(HumdrumFile &infile, ostream &out) { } bool Tool_fb::run(HumdrumFile &infile) { + initialize(); + processFile(infile); + return true; +} + + +////////////////////////////// +// +// Tool_fb::initialize -- +// + +void Tool_fb::initialize(void) { m_compoundQ = getBoolean("compound"); m_accidentalsQ = getBoolean("accidentals"); m_baseQ = getInteger("base"); @@ -115,6 +127,16 @@ bool Tool_fb::run(HumdrumFile &infile) { m_accidentalsQ = true; m_hideThreeQ = true; } +} + + + +////////////////////////////// +// +// Tool_fb::processFile -- +// + +void Tool_fb::processFile(HumdrumFile& infile) { NoteGrid grid(infile); @@ -214,8 +236,6 @@ bool Tool_fb::run(HumdrumFile &infile) { infile.appendDataSpine(trackData, ".", exinterp); } } - - return true; } From 7f849bdc93044ecb520f00a7844f5f54b888b135 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Sat, 14 Jan 2023 18:37:53 +0100 Subject: [PATCH 075/109] Make createFiguredBassNumber independent of NoteGrid --- include/tool-fb.h | 2 +- src/tool-fb.cpp | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/include/tool-fb.h b/include/tool-fb.h index 33e6b1b3..ec909fd0 100644 --- a/include/tool-fb.h +++ b/include/tool-fb.h @@ -71,7 +71,7 @@ class Tool_fb : public HumTool { bool hideNumbersForTokenLine (HTp token, pair timeSig); vector getTrackData (const vector& numbers, int lineCount); vector getTrackDataForVoice (int voiceIndex, const vector& numbers, int lineCount); - FiguredBassNumber* createFiguredBassNumber (NoteCell* base, NoteCell* target, string keySignature); + FiguredBassNumber* createFiguredBassNumber (int basePitchBase40, int targetPitchBase40, int voiceIndex, int lineIndex, bool isAttack, string keySignature); vector filterNegativeNumbers (vector numbers); vector filterFiguredBassNumbersForLine (vector numbers, int lineIndex); vector filterFiguredBassNumbersForLineAndVoice(vector numbers, int lineIndex, int voiceIndex); diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 405aba7c..b9276e32 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -200,7 +200,7 @@ void Tool_fb::processFile(HumdrumFile& infile) { } // Create FiguredBassNumber - FiguredBassNumber* number = createFiguredBassNumber(baseCell, targetCell, keySignature); + FiguredBassNumber* number = createFiguredBassNumber(baseCell->getAbsBase40Pitch(), targetCell->getAbsBase40Pitch(), targetCell->getVoiceIndex(), targetCell->getLineIndex(), targetCell->isAttack(), keySignature); if (lastNumbers[j] != 0) { // Set currAttackNumberDidChange number->m_currAttackNumberDidChange = (targetCell->isSustained()) && (lastNumbers[j] != number->m_number); @@ -314,15 +314,15 @@ vector Tool_fb::getTrackDataForVoice(int voiceIndex, const vector
getSgnDiatonicPitch(); - int targetPitch = target->getSgnDiatonicPitch(); - int diff = abs(targetPitch) - abs(basePitch); + int baseDiatonicPitch = Convert::base40ToDiatonic(basePitchBase40); + int targetDiatonicPitch = Convert::base40ToDiatonic(targetPitchBase40); + int diff = abs(targetDiatonicPitch) - abs(baseDiatonicPitch); int num; - if ((basePitch == 0) || (targetPitch == 0)) { + if ((baseDiatonicPitch == 0) || (targetDiatonicPitch == 0)) { num = 0; } else if (diff == 0) { num = 1; @@ -337,15 +337,15 @@ FiguredBassNumber* Tool_fb::createFiguredBassNumber(NoteCell* base, NoteCell* ta return tolower(c); }); - char targetPitchClass = Convert::kernToDiatonicLC(Convert::base40ToKern((int)target->getAbsBase40Pitch())); - int targetAccidNr = Convert::base40ToAccidental(target->getAbsBase40Pitch()); + char targetPitchName = Convert::kernToDiatonicLC(Convert::base40ToKern(targetPitchBase40)); + int targetAccidNr = Convert::base40ToAccidental(targetPitchBase40); string targetAccid; for (int i=0; igetAbsBase40Pitch())); - int baseAccidNr = Convert::base40ToAccidental(base->getAbsBase40Pitch()); + char basePitchName = Convert::kernToDiatonicLC(Convert::base40ToKern(basePitchBase40)); + int baseAccidNr = Convert::base40ToAccidental(basePitchBase40); string baseAccid; for (int i=0; igetVoiceIndex(), target->getLineIndex(), target->isAttack(), m_intervallsatzQ); + FiguredBassNumber* number = new FiguredBassNumber(num, accid, showAccid, voiceIndex, lineIndex, isAttack, m_intervallsatzQ); return number; } From 2ac8da89e9bf65a44391d0b901e371b5a8f650f6 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Sat, 14 Jan 2023 22:33:01 +0100 Subject: [PATCH 076/109] Fix display for 7 when --compound flag is set --- src/tool-fb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index b9276e32..cb2df7b2 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -684,7 +684,7 @@ int FiguredBassNumber::getNumberWithinOctave(void) { int num = m_number % 7; // Replace 0 with 7 and -7 - if ((abs(m_number) == 0) && (m_number != 0)) { + if ((abs(m_number) > 0) && (m_number % 7 == 0)) { return m_number < 0 ? -7 : 7; } From 54d82e06c06d62b5932dd03a00d39abb042b8000 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Sat, 14 Jan 2023 22:43:18 +0100 Subject: [PATCH 077/109] Add support for chords --- src/tool-fb.cpp | 42 +++++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index cb2df7b2..76b2588a 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -144,9 +144,9 @@ void Tool_fb::processFile(HumdrumFile& infile) { vector kernspines = infile.getKernSpineStartList(); - vector lastNumbers = {}; + vector> lastNumbers = {}; lastNumbers.resize((int)grid.getVoiceCount()); - vector currentNumbers = {}; + vector> currentNumbers = {}; // Interate through the NoteGrid and fill the numbers vector with // all generated FiguredBassNumbers @@ -185,6 +185,11 @@ void Tool_fb::processFile(HumdrumFile& infile) { } } + // Ignore if base is a rest or silent note + if (baseCell->getSgnBase40Pitch() == -1000 || baseCell->getSgnBase40Pitch() == -2000) { + continue; + } + // Interate through each voice for (int j=0; j<(int)grid.getVoiceCount(); j++) { if (j == usedBaseVoiceIndex) { @@ -192,21 +197,28 @@ void Tool_fb::processFile(HumdrumFile& infile) { continue; } NoteCell* targetCell = grid.cell(j, i); + HTp resolvedToken = targetCell->getToken()->resolveNull(); - // Ignore if either base or target is a rest or silent note - if (targetCell->getSgnBase40Pitch() == -1000 || targetCell->getSgnBase40Pitch() == -2000 || - baseCell->getSgnBase40Pitch() == -1000 || baseCell->getSgnBase40Pitch() == -2000) { - continue; - } - - // Create FiguredBassNumber - FiguredBassNumber* number = createFiguredBassNumber(baseCell->getAbsBase40Pitch(), targetCell->getAbsBase40Pitch(), targetCell->getVoiceIndex(), targetCell->getLineIndex(), targetCell->isAttack(), keySignature); - if (lastNumbers[j] != 0) { - // Set currAttackNumberDidChange - number->m_currAttackNumberDidChange = (targetCell->isSustained()) && (lastNumbers[j] != number->m_number); + // TODO: handle spine splits + + for (int subtokenBase40: resolvedToken->getBase40Pitches()) { + + // Ignore if target is a rest or silent note + if (subtokenBase40 == -1000 || subtokenBase40 == -2000) { + continue; + } + + // Create FiguredBassNumber + FiguredBassNumber* number = createFiguredBassNumber(baseCell->getAbsBase40Pitch(), abs(subtokenBase40), targetCell->getVoiceIndex(), targetCell->getLineIndex(), targetCell->isAttack(), keySignature); + if (lastNumbers[j].size() != 0) { + // If a number belongs to a sustained note but the base note did change + // the new numbers need to be displayable + number->m_currAttackNumberDidChange = (targetCell->isSustained()) && (std::find(lastNumbers[j].begin(), lastNumbers[j].end(), number->m_number) != lastNumbers[j].end()); + } + + currentNumbers[j].push_back(number->m_number); + numbers.push_back(number); } - currentNumbers[j] = number->m_number; - numbers.push_back(number); } // Set current numbers as the new last numbers From 0cde52bd598ad8820e8093a1850c954dd7239d34 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Sat, 14 Jan 2023 22:43:42 +0100 Subject: [PATCH 078/109] Include chord notes of base voice --- src/tool-fb.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 76b2588a..f6026935 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -192,10 +192,6 @@ void Tool_fb::processFile(HumdrumFile& infile) { // Interate through each voice for (int j=0; j<(int)grid.getVoiceCount(); j++) { - if (j == usedBaseVoiceIndex) { - // Ignore base voice - continue; - } NoteCell* targetCell = grid.cell(j, i); HTp resolvedToken = targetCell->getToken()->resolveNull(); @@ -207,6 +203,11 @@ void Tool_fb::processFile(HumdrumFile& infile) { if (subtokenBase40 == -1000 || subtokenBase40 == -2000) { continue; } + + // Ignore if same pitch as base voice + if (baseCell->getAbsBase40Pitch() == abs(subtokenBase40)) { + continue; + } // Create FiguredBassNumber FiguredBassNumber* number = createFiguredBassNumber(baseCell->getAbsBase40Pitch(), abs(subtokenBase40), targetCell->getVoiceIndex(), targetCell->getLineIndex(), targetCell->isAttack(), keySignature); From 5c6dfb990f5faf807fc4064b20bf5abb47b96b72 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Sat, 14 Jan 2023 22:51:12 +0100 Subject: [PATCH 079/109] Sort numbers for unordered chord pitches --- src/tool-fb.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index f6026935..a91be822 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -197,6 +197,8 @@ void Tool_fb::processFile(HumdrumFile& infile) { // TODO: handle spine splits + vector chordNumbers = {}; + for (int subtokenBase40: resolvedToken->getBase40Pitches()) { // Ignore if target is a rest or silent note @@ -218,9 +220,18 @@ void Tool_fb::processFile(HumdrumFile& infile) { } currentNumbers[j].push_back(number->m_number); - numbers.push_back(number); + chordNumbers.push_back(number); + } + + // Sort chord numbers by size + sort(chordNumbers.begin(), chordNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { + return a->m_number > b->m_number; + }); + + // Then add to numbers vector + for (FiguredBassNumber* num: chordNumbers) + numbers.push_back(num); } - } // Set current numbers as the new last numbers lastNumbers = currentNumbers; From c410410bbe65b54df00f9afaf7d13b1ee78d7e3e Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Sun, 15 Jan 2023 11:14:11 +0100 Subject: [PATCH 080/109] Improve readability --- src/tool-fb.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index a91be822..20e0e592 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -229,9 +229,10 @@ void Tool_fb::processFile(HumdrumFile& infile) { }); // Then add to numbers vector - for (FiguredBassNumber* num: chordNumbers) + for (FiguredBassNumber* num: chordNumbers) { numbers.push_back(num); } + } // Set current numbers as the new last numbers lastNumbers = currentNumbers; From df8be2011661d2b4a1cf665b5b55601f7a1fe43e Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Sun, 15 Jan 2023 11:19:17 +0100 Subject: [PATCH 081/109] Handle spine splits --- src/tool-fb.cpp | 57 +++++++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 20e0e592..d0f84e46 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -193,35 +193,46 @@ void Tool_fb::processFile(HumdrumFile& infile) { // Interate through each voice for (int j=0; j<(int)grid.getVoiceCount(); j++) { NoteCell* targetCell = grid.cell(j, i); - HTp resolvedToken = targetCell->getToken()->resolveNull(); - - // TODO: handle spine splits - + HTp currentToken = targetCell->getToken(); + int initialTokenTrack = targetCell->getToken()->getTrack(); vector chordNumbers = {}; - for (int subtokenBase40: resolvedToken->getBase40Pitches()) { - - // Ignore if target is a rest or silent note - if (subtokenBase40 == -1000 || subtokenBase40 == -2000) { - continue; - } + // Handle spine splits + do { + HTp resolvedToken = currentToken->resolveNull(); - // Ignore if same pitch as base voice - if (baseCell->getAbsBase40Pitch() == abs(subtokenBase40)) { - continue; + for (int subtokenBase40: resolvedToken->getBase40Pitches()) { + + // Ignore if target is a rest or silent note + if (subtokenBase40 == -1000 || subtokenBase40 == -2000) { + continue; + } + + // Ignore if same pitch as base voice + if (baseCell->getAbsBase40Pitch() == abs(subtokenBase40)) { + continue; + } + + // Create FiguredBassNumber + FiguredBassNumber* number = createFiguredBassNumber(baseCell->getAbsBase40Pitch(), abs(subtokenBase40), targetCell->getVoiceIndex(), targetCell->getLineIndex(), targetCell->isAttack(), keySignature); + if (lastNumbers[j].size() != 0) { + // If a number belongs to a sustained note but the base note did change + // the new numbers need to be displayable + number->m_currAttackNumberDidChange = (targetCell->isSustained()) && (std::find(lastNumbers[j].begin(), lastNumbers[j].end(), number->m_number) != lastNumbers[j].end()); + } + + currentNumbers[j].push_back(number->m_number); + chordNumbers.push_back(number); } - // Create FiguredBassNumber - FiguredBassNumber* number = createFiguredBassNumber(baseCell->getAbsBase40Pitch(), abs(subtokenBase40), targetCell->getVoiceIndex(), targetCell->getLineIndex(), targetCell->isAttack(), keySignature); - if (lastNumbers[j].size() != 0) { - // If a number belongs to a sustained note but the base note did change - // the new numbers need to be displayable - number->m_currAttackNumberDidChange = (targetCell->isSustained()) && (std::find(lastNumbers[j].begin(), lastNumbers[j].end(), number->m_number) != lastNumbers[j].end()); + HTp nextToken = currentToken->getNextField(); + if (nextToken && (initialTokenTrack == nextToken->getTrack())) { + currentToken = nextToken; + } else { + // Break loop if nextToken is not the same track as initialTokenTrack + break; } - - currentNumbers[j].push_back(number->m_number); - chordNumbers.push_back(number); - } + } while (currentToken); // Sort chord numbers by size sort(chordNumbers.begin(), chordNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { From 4ae1d0e0651313d9bf57cce8db78aebc1cc30b57 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Sun, 15 Jan 2023 16:23:34 +0100 Subject: [PATCH 082/109] Improvements for chords in base voice --- include/tool-fb.h | 1 + src/tool-fb.cpp | 30 ++++++++++++++++++++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/include/tool-fb.h b/include/tool-fb.h index ec909fd0..d00ed970 100644 --- a/include/tool-fb.h +++ b/include/tool-fb.h @@ -80,6 +80,7 @@ class Tool_fb : public HumTool { vector getAbbreviatedNumbers (const vector& numbers); string getNumberString (vector numbers); string getKeySignature (HumdrumFile& infile, int lineIndex); + int getLowestBase40Pitch (vector base40Pitches); private: diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index d0f84e46..568fca2c 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -185,8 +185,10 @@ void Tool_fb::processFile(HumdrumFile& infile) { } } + int lowestBaseNoteBase40Pitch = getLowestBase40Pitch(baseCell->getToken()->resolveNull()->getBase40Pitches()); + // Ignore if base is a rest or silent note - if (baseCell->getSgnBase40Pitch() == -1000 || baseCell->getSgnBase40Pitch() == -2000) { + if (lowestBaseNoteBase40Pitch == 0 || lowestBaseNoteBase40Pitch == -1000 || lowestBaseNoteBase40Pitch == -2000) { continue; } @@ -204,17 +206,17 @@ void Tool_fb::processFile(HumdrumFile& infile) { for (int subtokenBase40: resolvedToken->getBase40Pitches()) { // Ignore if target is a rest or silent note - if (subtokenBase40 == -1000 || subtokenBase40 == -2000) { + if (subtokenBase40 == 0 || subtokenBase40 == -1000 || subtokenBase40 == -2000) { continue; } // Ignore if same pitch as base voice - if (baseCell->getAbsBase40Pitch() == abs(subtokenBase40)) { + if (abs(lowestBaseNoteBase40Pitch) == abs(subtokenBase40)) { continue; } // Create FiguredBassNumber - FiguredBassNumber* number = createFiguredBassNumber(baseCell->getAbsBase40Pitch(), abs(subtokenBase40), targetCell->getVoiceIndex(), targetCell->getLineIndex(), targetCell->isAttack(), keySignature); + FiguredBassNumber* number = createFiguredBassNumber(abs(lowestBaseNoteBase40Pitch), abs(subtokenBase40), targetCell->getVoiceIndex(), targetCell->getLineIndex(), targetCell->isAttack(), keySignature); if (lastNumbers[j].size() != 0) { // If a number belongs to a sustained note but the base note did change // the new numbers need to be displayable @@ -669,6 +671,26 @@ string Tool_fb::getKeySignature(HumdrumFile& infile, int lineIndex) { +////////////////////////////// +// +// Tool_fb::getLowestBase40Pitch -- Get lowest base 40 pitch that is not a rest or silent +// + +int Tool_fb::getLowestBase40Pitch(vector base40Pitches) { + vector filteredBase40Pitches; + copy_if(base40Pitches.begin(), base40Pitches.end(), std::back_inserter(filteredBase40Pitches), [](int base40Pitch) { + // Ignore if base is a rest or silent note + return base40Pitch != -1000 && base40Pitch != -2000 && base40Pitch != 0; + }); + + if (filteredBase40Pitches.size() == 0) { + return -2000; + } + + return *min_element(begin(filteredBase40Pitches), end(filteredBase40Pitches)); +} + + ////////////////////////////// // // FiguredBassNumber::FiguredBassNumber -- Constructor From 6d441f94d835db9669dc9ceedf311fcb6c671f07 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Sun, 15 Jan 2023 16:29:55 +0100 Subject: [PATCH 083/109] Improve --lowest for chords --- src/tool-fb.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 568fca2c..439cde8a 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -158,15 +158,17 @@ void Tool_fb::processFile(HumdrumFile& infile) { int usedBaseVoiceIndex = m_baseQ; // Overwrite usedBaseVoiceIndex with the lowest voice index of the lowest pitched note - // TODO: check if this still works for chords if (m_lowestQ) { int lowestNotePitch = 99999; for (int k=0; k<(int)grid.getVoiceCount(); k++) { NoteCell* checkCell = grid.cell(k, i); - int checkCellPitch = abs(checkCell->getSgnDiatonicPitch()); - if ((checkCellPitch > 0) && (checkCellPitch < lowestNotePitch)) { - lowestNotePitch = checkCellPitch; - usedBaseVoiceIndex = k; + int checkCellPitch = getLowestBase40Pitch(checkCell->getToken()->resolveNull()->getBase40Pitches()); + // Ignore if base is a rest or silent note + if (checkCellPitch != 0 && checkCellPitch != -1000 && checkCellPitch != -2000) { + if ((checkCellPitch > 0) && (checkCellPitch < lowestNotePitch)) { + lowestNotePitch = checkCellPitch; + usedBaseVoiceIndex = k; + } } } } From c06151148429c2845687ac81d731e9f4f37afff4 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Sun, 15 Jan 2023 16:32:15 +0100 Subject: [PATCH 084/109] Add todos --- src/tool-fb.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 439cde8a..e1333769 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -162,6 +162,7 @@ void Tool_fb::processFile(HumdrumFile& infile) { int lowestNotePitch = 99999; for (int k=0; k<(int)grid.getVoiceCount(); k++) { NoteCell* checkCell = grid.cell(k, i); + // TODO: Handle spine splits int checkCellPitch = getLowestBase40Pitch(checkCell->getToken()->resolveNull()->getBase40Pitches()); // Ignore if base is a rest or silent note if (checkCellPitch != 0 && checkCellPitch != -1000 && checkCellPitch != -2000) { @@ -676,6 +677,7 @@ string Tool_fb::getKeySignature(HumdrumFile& infile, int lineIndex) { ////////////////////////////// // // Tool_fb::getLowestBase40Pitch -- Get lowest base 40 pitch that is not a rest or silent +// TODO: Handle negative values and sustained notes // int Tool_fb::getLowestBase40Pitch(vector base40Pitches) { From e95ba8fbea28a4198acb56334226982e5e602f38 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Mon, 16 Jan 2023 00:27:49 +0100 Subject: [PATCH 085/109] Ignore voices if track is not active by --kern-tracks or --spine-tracks --- include/tool-fb.h | 4 ++++ src/tool-fb.cpp | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/include/tool-fb.h b/include/tool-fb.h index d00ed970..8a99db06 100644 --- a/include/tool-fb.h +++ b/include/tool-fb.h @@ -99,6 +99,10 @@ class Tool_fb : public HumTool { bool m_aboveQ = false; string m_recipQ = ""; + string m_spineTracks = ""; // used with -s option + string m_kernTracks = ""; // used with -k option + vector m_processTrack; // used with -k and -s option + }; // END_MERGE diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index e1333769..93a616ca 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -41,6 +41,8 @@ Tool_fb::Tool_fb(void) { define("m|negative=b", "show negative numbers"); define("above=b", "place figured bass numbers above staff (**fba)"); define("recip=s:", "only show numbers if they are divisible by this **recip value (e.g. 2, 4, 8, 4.)"); + define("k|kern-tracks=s", "Process only the specified kern spines"); + define("s|spine-tracks|spine|spines|track|tracks=s", "Process only the specified spines"); } @@ -108,6 +110,12 @@ void Tool_fb::initialize(void) { m_aboveQ = getBoolean("above"); m_recipQ = getString("recip"); + if (getBoolean("spine-tracks")) { + m_spineTracks = getString("spine-tracks"); + } else if (getBoolean("kern-tracks")) { + m_kernTracks = getString("kern-tracks"); + } + if (m_normalizeQ) { m_compoundQ = true; m_sortQ = true; @@ -144,6 +152,27 @@ void Tool_fb::processFile(HumdrumFile& infile) { vector kernspines = infile.getKernSpineStartList(); + // Calculate which input spines to process based on -s or -k option: + int maxTrack = infile.getMaxTrack(); + m_processTrack.resize(maxTrack + 1); // +1 is needed since track=0 is not used + // By default, process all tracks: + fill(m_processTrack.begin(), m_processTrack.end(), true); + // Otherwise, select which **kern track, or spine tracks to process selectively: + if (!m_kernTracks.empty()) { + vector ktracks = Convert::extractIntegerList(m_kernTracks, maxTrack); + fill(m_processTrack.begin(), m_processTrack.end(), false); + for (int i=0; i<(int)ktracks.size(); i++) { + int index = ktracks[i] - 1; + if ((index < 0) || (index >= (int)kernspines.size())) { + continue; + } + int track = kernspines.at(ktracks[i] - 1)->getTrack(); + m_processTrack.at(track) = true; + } + } else if (!m_spineTracks.empty()) { + infile.makeBooleanTrackList(m_processTrack, m_spineTracks); + } + vector> lastNumbers = {}; lastNumbers.resize((int)grid.getVoiceCount()); vector> currentNumbers = {}; @@ -198,6 +227,12 @@ void Tool_fb::processFile(HumdrumFile& infile) { // Interate through each voice for (int j=0; j<(int)grid.getVoiceCount(); j++) { NoteCell* targetCell = grid.cell(j, i); + + // Ignore voice if track is not active by --kern-tracks or --spine-tracks + if (m_processTrack.at(targetCell->getToken()->getTrack()) == false) { + continue; + } + HTp currentToken = targetCell->getToken(); int initialTokenTrack = targetCell->getToken()->getTrack(); vector chordNumbers = {}; From c069fc795bc987504d25a526a8c7081d03da6495 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Mon, 16 Jan 2023 00:28:29 +0100 Subject: [PATCH 086/109] Rename -s to -o --- src/tool-fb.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 93a616ca..ef02a89c 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -31,12 +31,12 @@ Tool_fb::Tool_fb(void) { define("a|accidentals=b", "display accidentals in figured bass output"); define("b|base=i:0", "number of the base voice/spine"); define("i|intervallsatz=b", "display intervals under their voice and not under the lowest staff"); - define("s|sort=b", "sort figured bass numbers by interval size and not by voice index"); + define("o|sort|order=b", "sort figured bass numbers by interval size and not by voice index"); define("l|lowest=b", "use lowest note as base note; -b flag will be ignored"); define("n|normalize=b", "remove octave and doubled intervals; adds: --compound --sort"); define("r|abbr=b", "use abbreviated figures; adds: --normalize --compound --sort"); define("t|attack=b", "hide intervalls with no attack and when base does not change"); - define("f|figuredbass=b", "shortcut for -c -a -s -n -r -3"); + define("f|figuredbass=b", "shortcut for -c -a -o -n -r -3"); define("3|hide-three=b", "hide number 3 if it has an accidental (e.g.: #3 => #)"); define("m|negative=b", "show negative numbers"); define("above=b", "place figured bass numbers above staff (**fba)"); From a2a98134c6f63506b152725fd36e760266c48df7 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Mon, 16 Jan 2023 00:33:33 +0100 Subject: [PATCH 087/109] Commit humlib.h and humlib.cpp --- include/humlib.h | 101 ++++-- src/humlib.cpp | 879 ++++++++++++++++++++++++++++++++++++----------- 2 files changed, 745 insertions(+), 235 deletions(-) diff --git a/include/humlib.h b/include/humlib.h index 59d63647..81f1529b 100644 --- a/include/humlib.h +++ b/include/humlib.h @@ -1,7 +1,7 @@ // // Programmer: Craig Stuart Sapp // Creation Date: Sat Aug 8 12:24:49 PDT 2015 -// Last Modified: Mon Jan 9 10:19:01 PST 2023 +// Last Modified: Mo 16 Jan 2023 00:32:57 CET // Filename: humlib.h // URL: https://github.com/craigsapp/humlib/blob/master/include/humlib.h // Syntax: C++11 @@ -7107,37 +7107,88 @@ class Tool_extract : public HumTool { +class FiguredBassNumber { + public: + FiguredBassNumber(int num, string accid, bool showAccid, int voiceIndex, int lineIndex, bool isAttack, bool intervallsatz); + std::string toString(bool nonCompoundIntervalsQ, bool noAccidentalsQ, bool hideThreeQ); + int getNumberWithinOctave(void); + + int m_voiceIndex; + int m_lineIndex; + int m_number; + std::string m_accidentals; + bool m_showAccidentals; // Force shoing figured base numbers when they need an accidental + bool m_currAttackNumberDidChange; + bool m_isAttack; + bool m_convert2To9 = false; + bool m_intervallsatz = false; + +}; + +class FiguredBassAbbreviationMapping { + public: + FiguredBassAbbreviationMapping(string s, vector n); + + static vector s_mappings; + + // String to compare the numbers with + // e.g. "6 4 3" + // Sorted by size, larger numbers first + string m_str; + + // Figured bass number as int + vector m_numbers; + +}; + class Tool_fb : public HumTool { + public: - Tool_fb (void); - ~Tool_fb () {}; + Tool_fb (void); + ~Tool_fb() {}; - bool run (HumdrumFileSet& infiles); - bool run (HumdrumFile& infile); - bool run (const string& indata, ostream& out); - bool run (HumdrumFile& infile, ostream& out); + bool run (HumdrumFileSet& infiles); + bool run (HumdrumFile& infile); + bool run (const string& indata, ostream& out); + bool run (HumdrumFile& infile, ostream& out); protected: - void processFile (HumdrumFile& infile); - void initialize (void); - void processLine (HumdrumFile& infile, int index); - void setupScoreData (HumdrumFile& infile); - void getAnalyses (HumdrumFile& infile); - void getHarmonicIntervals(HumdrumFile& infile); - void calculateIntervals(vector& intervals, vector& tokens, int bassIndex); - void printOutput (HumdrumFile& infile); - void printLineStyle3 (HumdrumFile& infile, int line); - std::string getAnalysisTokenStyle3(HumdrumFile& infile, int line, int field); + void initialize (void); + void processFile (HumdrumFile& infile); + bool hideNumbersForTokenLine (HTp token, pair timeSig); + vector getTrackData (const vector& numbers, int lineCount); + vector getTrackDataForVoice (int voiceIndex, const vector& numbers, int lineCount); + FiguredBassNumber* createFiguredBassNumber (int basePitchBase40, int targetPitchBase40, int voiceIndex, int lineIndex, bool isAttack, string keySignature); + vector filterNegativeNumbers (vector numbers); + vector filterFiguredBassNumbersForLine (vector numbers, int lineIndex); + vector filterFiguredBassNumbersForLineAndVoice(vector numbers, int lineIndex, int voiceIndex); + string formatFiguredBassNumbers (const vector& numbers); + vector analyzeChordNumbers (const vector& numbers); + vector getAbbreviatedNumbers (const vector& numbers); + string getNumberString (vector numbers); + string getKeySignature (HumdrumFile& infile, int lineIndex); + int getLowestBase40Pitch (vector base40Pitches); + private: - std::vector m_kernspines; - std::vector m_kerntracks; - std::vector m_track2index; - std::vector> m_keyaccid; - std::vector> m_intervals; - const int m_rest = -1000; - int m_reference = 0; // currently fixed to bass - int m_debugQ = false; + bool m_compoundQ = false; + bool m_accidentalsQ = false; + int m_baseQ = 0; + bool m_intervallsatzQ = false; + bool m_sortQ = false; + bool m_lowestQ = false; + bool m_normalizeQ = false; + bool m_abbrQ = false; + bool m_attackQ = false; + bool m_figuredbassQ = false; + bool m_hideThreeQ = false; + bool m_showNegativeQ = false; + bool m_aboveQ = false; + string m_recipQ = ""; + + string m_spineTracks = ""; // used with -s option + string m_kernTracks = ""; // used with -k option + vector m_processTrack; // used with -k and -s option }; diff --git a/src/humlib.cpp b/src/humlib.cpp index abff3a96..cf5a744f 100644 --- a/src/humlib.cpp +++ b/src/humlib.cpp @@ -1,7 +1,7 @@ // // Programmer: Craig Stuart Sapp // Creation Date: Sat Aug 8 12:24:49 PDT 2015 -// Last Modified: Mon Jan 9 10:19:01 PST 2023 +// Last Modified: Mo 16 Jan 2023 00:32:57 CET // Filename: /include/humlib.cpp // URL: https://github.com/craigsapp/humlib/blob/master/src/humlib.cpp // Syntax: C++11 @@ -76610,34 +76610,46 @@ void Tool_extract::initialize(HumdrumFile& infile) { - -///////////////////////////////// +////////////////////////////// // // Tool_fb::Tool_fb -- Set the recognized options for the tool. // Tool_fb::Tool_fb(void) { - define("d|debug=b", "Print debug information"); - define("r|reference=i:0", "Reference kern spine (1 indexed)"); + define("c|compound=b", "output reasonable figured bass numbers within octave"); + define("a|accidentals=b", "display accidentals in figured bass output"); + define("b|base=i:0", "number of the base voice/spine"); + define("i|intervallsatz=b", "display intervals under their voice and not under the lowest staff"); + define("o|sort|order=b", "sort figured bass numbers by interval size and not by voice index"); + define("l|lowest=b", "use lowest note as base note; -b flag will be ignored"); + define("n|normalize=b", "remove octave and doubled intervals; adds: --compound --sort"); + define("r|abbr=b", "use abbreviated figures; adds: --normalize --compound --sort"); + define("t|attack=b", "hide intervalls with no attack and when base does not change"); + define("f|figuredbass=b", "shortcut for -c -a -o -n -r -3"); + define("3|hide-three=b", "hide number 3 if it has an accidental (e.g.: #3 => #)"); + define("m|negative=b", "show negative numbers"); + define("above=b", "place figured bass numbers above staff (**fba)"); + define("recip=s:", "only show numbers if they are divisible by this **recip value (e.g. 2, 4, 8, 4.)"); + define("k|kern-tracks=s", "Process only the specified kern spines"); + define("s|spine-tracks|spine|spines|track|tracks=s", "Process only the specified spines"); } -///////////////////////////////// +////////////////////////////// // // Tool_fb::run -- Do the main work of the tool. // -bool Tool_fb::run(HumdrumFileSet& infiles) { +bool Tool_fb::run(HumdrumFileSet &infiles) { bool status = true; - for (int i=0; i numbers; -////////////////////////////// -// -// Tool_fb::getHarmonicIntervals -- Fill in -// + vector kernspines = infile.getKernSpineStartList(); + + // Calculate which input spines to process based on -s or -k option: + int maxTrack = infile.getMaxTrack(); + m_processTrack.resize(maxTrack + 1); // +1 is needed since track=0 is not used + // By default, process all tracks: + fill(m_processTrack.begin(), m_processTrack.end(), true); + // Otherwise, select which **kern track, or spine tracks to process selectively: + if (!m_kernTracks.empty()) { + vector ktracks = Convert::extractIntegerList(m_kernTracks, maxTrack); + fill(m_processTrack.begin(), m_processTrack.end(), false); + for (int i=0; i<(int)ktracks.size(); i++) { + int index = ktracks[i] - 1; + if ((index < 0) || (index >= (int)kernspines.size())) { + continue; + } + int track = kernspines.at(ktracks[i] - 1)->getTrack(); + m_processTrack.at(track) = true; + } + } else if (!m_spineTracks.empty()) { + infile.makeBooleanTrackList(m_processTrack, m_spineTracks); + } + + vector> lastNumbers = {}; + lastNumbers.resize((int)grid.getVoiceCount()); + vector> currentNumbers = {}; + + // Interate through the NoteGrid and fill the numbers vector with + // all generated FiguredBassNumbers + for (int i=0; i<(int)grid.getSliceCount(); i++) { + currentNumbers.clear(); + currentNumbers.resize((int)grid.getVoiceCount()); + + // Reset usedBaseVoiceIndex + int usedBaseVoiceIndex = m_baseQ; + + // Overwrite usedBaseVoiceIndex with the lowest voice index of the lowest pitched note + if (m_lowestQ) { + int lowestNotePitch = 99999; + for (int k=0; k<(int)grid.getVoiceCount(); k++) { + NoteCell* checkCell = grid.cell(k, i); + // TODO: Handle spine splits + int checkCellPitch = getLowestBase40Pitch(checkCell->getToken()->resolveNull()->getBase40Pitches()); + // Ignore if base is a rest or silent note + if (checkCellPitch != 0 && checkCellPitch != -1000 && checkCellPitch != -2000) { + if ((checkCellPitch > 0) && (checkCellPitch < lowestNotePitch)) { + lowestNotePitch = checkCellPitch; + usedBaseVoiceIndex = k; + } + } + } + } -void Tool_fb::getHarmonicIntervals(HumdrumFile& infile) { - m_intervals.resize(infile.getLineCount()); + NoteCell* baseCell = grid.cell(usedBaseVoiceIndex, i); + string keySignature = getKeySignature(infile, baseCell->getLineIndex()); - vector tokens(m_kernspines.size(), NULL); - for (int i=0; i> timeSigs; + infile.getTimeSigs(timeSigs, baseCell->getToken()->getTrack()); + // Ignore numbers if they don't fit + if (hideNumbersForTokenLine(baseCell->getToken(), timeSigs[baseCell->getLineIndex()])) { + continue; + } + } + + int lowestBaseNoteBase40Pitch = getLowestBase40Pitch(baseCell->getToken()->resolveNull()->getBase40Pitches()); + + // Ignore if base is a rest or silent note + if (lowestBaseNoteBase40Pitch == 0 || lowestBaseNoteBase40Pitch == -1000 || lowestBaseNoteBase40Pitch == -2000) { continue; } - fill(tokens.begin(), tokens.end(), (HTp)NULL); - for (int j=0; jisKern()) { + + // Interate through each voice + for (int j=0; j<(int)grid.getVoiceCount(); j++) { + NoteCell* targetCell = grid.cell(j, i); + + // Ignore voice if track is not active by --kern-tracks or --spine-tracks + if (m_processTrack.at(targetCell->getToken()->getTrack()) == false) { continue; } - int track = token->getTrack(); - int index = m_track2index.at(track); - tokens[index] = token; - // cerr << token << "\t"; - } - m_intervals[i].resize(m_kernspines.size()); - calculateIntervals(m_intervals[i], tokens, m_reference); - // cerr << endl; - - if (m_debugQ) { - for (int j=0; j<(int)m_intervals[i].size(); j++) { - m_free_text << tokens[j] << "\t("; - if (m_intervals[i][j] == m_rest) { - m_free_text << "R"; - } else { - m_free_text << m_intervals[i][j]; + + HTp currentToken = targetCell->getToken(); + int initialTokenTrack = targetCell->getToken()->getTrack(); + vector chordNumbers = {}; + + // Handle spine splits + do { + HTp resolvedToken = currentToken->resolveNull(); + + for (int subtokenBase40: resolvedToken->getBase40Pitches()) { + + // Ignore if target is a rest or silent note + if (subtokenBase40 == 0 || subtokenBase40 == -1000 || subtokenBase40 == -2000) { + continue; + } + + // Ignore if same pitch as base voice + if (abs(lowestBaseNoteBase40Pitch) == abs(subtokenBase40)) { + continue; + } + + // Create FiguredBassNumber + FiguredBassNumber* number = createFiguredBassNumber(abs(lowestBaseNoteBase40Pitch), abs(subtokenBase40), targetCell->getVoiceIndex(), targetCell->getLineIndex(), targetCell->isAttack(), keySignature); + if (lastNumbers[j].size() != 0) { + // If a number belongs to a sustained note but the base note did change + // the new numbers need to be displayable + number->m_currAttackNumberDidChange = (targetCell->isSustained()) && (std::find(lastNumbers[j].begin(), lastNumbers[j].end(), number->m_number) != lastNumbers[j].end()); + } + + currentNumbers[j].push_back(number->m_number); + chordNumbers.push_back(number); } - m_free_text << ")"; - if (j < (int)m_intervals[i].size() - 1) { - m_free_text << "\t"; + + HTp nextToken = currentToken->getNextField(); + if (nextToken && (initialTokenTrack == nextToken->getTrack())) { + currentToken = nextToken; + } else { + // Break loop if nextToken is not the same track as initialTokenTrack + break; } + } while (currentToken); + + // Sort chord numbers by size + sort(chordNumbers.begin(), chordNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { + return a->m_number > b->m_number; + }); + + // Then add to numbers vector + for (FiguredBassNumber* num: chordNumbers) { + numbers.push_back(num); + } + } + + // Set current numbers as the new last numbers + lastNumbers = currentNumbers; + } + + string exinterp = m_aboveQ ? "**fba" : "**fb"; + + if (m_intervallsatzQ) { + // Create **fb spine for each voice + for (int voiceIndex = 0; voiceIndex < grid.getVoiceCount(); voiceIndex++) { + vector trackData = getTrackDataForVoice(voiceIndex, numbers, infile.getLineCount()); + if (voiceIndex + 1 < grid.getVoiceCount()) { + int trackIndex = kernspines[voiceIndex + 1]->getTrack(); + infile.insertDataSpineBefore(trackIndex, trackData, ".", exinterp); + } else { + infile.appendDataSpine(trackData, ".", exinterp); } - m_free_text << endl; + } + } else { + // Create **fb spine and bind it to the base voice + vector trackData = getTrackData(numbers, infile.getLineCount()); + if (m_baseQ + 1 < grid.getVoiceCount()) { + int trackIndex = kernspines[m_baseQ + 1]->getTrack(); + infile.insertDataSpineBefore(trackIndex, trackData, ".", exinterp); + } else { + infile.appendDataSpine(trackData, ".", exinterp); } } } @@ -76745,235 +76907,530 @@ void Tool_fb::getHarmonicIntervals(HumdrumFile& infile) { ////////////////////////////// // -// Tool_fb::calculateIntervals -- +// Tool_fb::hideNumbersForTokenLine -- Checks if rhythmic position of line should display numbers // -void Tool_fb::calculateIntervals(vector& intervals, - vector& tokens, int bassIndex) { - if (intervals.size() != tokens.size()) { - cerr << "ERROR: Size if vectors do not match" << endl; - return; +bool Tool_fb::hideNumbersForTokenLine(HTp token, pair timeSig) { + // Get note duration from --recip option + HumNum recip = Convert::recipToDuration(m_recipQ); + if (recip.toFloat() != 0) { + float timeSigBarDuration = timeSig.first * Convert::recipToDuration(to_string(timeSig.second.getInteger())).toFloat(); + float durationFromBarline = token->getDurationFromBarline().toFloat(); + // Handle upbeats + if (token->getBarlineDuration().toFloat() < timeSigBarDuration) { + // Fix durationFromBarline when current bar duration is shorter than + // the bar duration of the time signature + durationFromBarline = timeSigBarDuration - token->getDurationToBarline().toFloat(); + } + // Checks if rhythmic position is divisible by recip duration + return fmod(durationFromBarline, recip.toFloat()) != 0; } + return false; +} - HTp reftok = tokens[m_reference]; - if (reftok->isNull()) { - reftok = reftok->resolveNull(); - } - if (!reftok || reftok->isRest()) { - for (int i=0; i<(int)tokens.size(); i++) { - intervals[i] = m_rest; + +////////////////////////////// +// +// Tool_fb::getTrackData -- Create **fb spine data with formatted numbers for all voices +// + +vector Tool_fb::getTrackData(const vector& numbers, int lineCount) { + vector trackData; + trackData.resize(lineCount); + + for (int i = 0; i < lineCount; i++) { + vector sliceNumbers = filterFiguredBassNumbersForLine(numbers, i); + if (sliceNumbers.size() > 0) { + trackData[i] = formatFiguredBassNumbers(sliceNumbers); } - return; } - int base40ref = Convert::kernToBase40(reftok); + return trackData; +} - for (int i=0; i<(int)tokens.size(); i++) { - if (i == m_reference) { - intervals[i] = m_rest; - continue; - } - if (tokens[i]->isRest()) { - intervals[i] = m_rest; - continue; - } - if (tokens[m_reference]->isRest()) { - intervals[i] = m_rest; - continue; - } - if (tokens[i]->isNull()) { - continue; + + +////////////////////////////// +// +// Tool_fb::getTrackDataForVoice -- Create **fb spine data with formatted numbers for passed voiceIndex +// + +vector Tool_fb::getTrackDataForVoice(int voiceIndex, const vector& numbers, int lineCount) { + vector trackData; + trackData.resize(lineCount); + + for (int i = 0; i < lineCount; i++) { + vector sliceNumbers = filterFiguredBassNumbersForLineAndVoice(numbers, i, voiceIndex); + if (sliceNumbers.size() > 0) { + trackData[i] = formatFiguredBassNumbers(sliceNumbers); } - int base40 = Convert::kernToBase40(tokens[i]); - int interval = base40 - base40ref; - intervals[i] = interval; } + + return trackData; } ////////////////////////////// // -// Tool_fb::setupScoreData -- +// Tool_fb::createFiguredBassNumber -- Create FiguredBassNumber from a NoteCell. +// The figured bass number (num) is calculated with a base and target NoteCell +// as well as a passed key signature. // -void Tool_fb::setupScoreData(HumdrumFile& infile) { - infile.getKernSpineStartList(m_kernspines); - m_kerntracks.resize(m_kernspines.size()); - for (int i=0; i<(int)m_kernspines.size(); i++) { - m_kerntracks[i] = m_kernspines[i]->getTrack(); +FiguredBassNumber* Tool_fb::createFiguredBassNumber(int basePitchBase40, int targetPitchBase40, int voiceIndex, int lineIndex, bool isAttack, string keySignature) { + + // Calculate figured bass number + int baseDiatonicPitch = Convert::base40ToDiatonic(basePitchBase40); + int targetDiatonicPitch = Convert::base40ToDiatonic(targetPitchBase40); + int diff = abs(targetDiatonicPitch) - abs(baseDiatonicPitch); + int num; + + if ((baseDiatonicPitch == 0) || (targetDiatonicPitch == 0)) { + num = 0; + } else if (diff == 0) { + num = 1; + } else if (diff > 0) { + num = diff + 1; + } else { + num = diff - 1; } - int maxtrack = infile.getMaxTrack(); - m_track2index.resize(maxtrack + 1); - fill(m_track2index.begin(), m_track2index.end(), -1); - for (int i=0; i<(int)m_kerntracks.size(); i++) { - m_track2index.at(m_kerntracks[i]) = i; + // Transform key signature to lower case + transform(keySignature.begin(), keySignature.end(), keySignature.begin(), [](unsigned char c) { + return tolower(c); + }); + + char targetPitchName = Convert::kernToDiatonicLC(Convert::base40ToKern(targetPitchBase40)); + int targetAccidNr = Convert::base40ToAccidental(targetPitchBase40); + string targetAccid; + for (int i=0; i= (int)m_kernspines.size()) { - m_reference = (int)m_kernspines.size() - 1; + char basePitchName = Convert::kernToDiatonicLC(Convert::base40ToKern(basePitchBase40)); + int baseAccidNr = Convert::base40ToAccidental(basePitchBase40); + string baseAccid; + for (int i=0; i pcs(7, 0); + // Show natural accidentals when they are alterations of the key signature + if ((targetAccidNr == 0) && (keySignature.find(targetPitchName + targetAccid) != std::string::npos)) { + accid = "n"; + showAccid = true; + } - m_keyaccid.resize(infile.getLineCount()); - for (int i=0; iisKern()) { - continue; - } - if (token->isKeySignature()) { - fill(pcs.begin(), pcs.end(), 0); - HumRegex hre; - if (hre.search(token, "c#")) { pcs[0] = +1;} - if (hre.search(token, "d#")) { pcs[1] = +1;} - if (hre.search(token, "e#")) { pcs[2] = +1;} - if (hre.search(token, "f#")) { pcs[3] = +1;} - if (hre.search(token, "g#")) { pcs[4] = +1;} - if (hre.search(token, "a#")) { pcs[5] = +1;} - if (hre.search(token, "b#")) { pcs[6] = +1;} - if (hre.search(token, "c-")) { pcs[0] = -1;} - if (hre.search(token, "d-")) { pcs[1] = -1;} - if (hre.search(token, "e-")) { pcs[2] = -1;} - if (hre.search(token, "f-")) { pcs[3] = -1;} - if (hre.search(token, "g-")) { pcs[4] = -1;} - if (hre.search(token, "a-")) { pcs[5] = -1;} - if (hre.search(token, "b-")) { pcs[6] = -1;} - m_keyaccid[i] = pcs; - } + // Show accidentlas when pitch class of base and target is equal but alteration is different + if (basePitchName == targetPitchName) { + if (baseAccidNr == targetAccidNr) { + showAccid = false; + } else { + accid = (targetAccidNr == 0) ? "n" : targetAccid; + showAccid = true; } } - for (int i=1; i Tool_fb::filterNegativeNumbers(vector numbers) { + + vector filteredNumbers; + + bool mQ = m_showNegativeQ; + copy_if(numbers.begin(), numbers.end(), back_inserter(filteredNumbers), [mQ](FiguredBassNumber* num) { + return mQ ? true : (num->m_number > 0); + }); + + return filteredNumbers; +} + + + +////////////////////////////// +// +// Tool_fb::filterFiguredBassNumbersForLine -- Find all FiguredBassNumber objects for a slice (line index) of the music. +// + +vector Tool_fb::filterFiguredBassNumbersForLine(vector numbers, int lineIndex) { + + vector filteredNumbers; + + // filter numbers with passed lineIndex + copy_if(numbers.begin(), numbers.end(), back_inserter(filteredNumbers), [lineIndex](FiguredBassNumber* num) { + return num->m_lineIndex == lineIndex; + }); + + // sort by voiceIndex + sort(filteredNumbers.begin(), filteredNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { + return a->m_voiceIndex > b->m_voiceIndex; + }); + + return filterNegativeNumbers(filteredNumbers); +} + + + +////////////////////////////// +// +// Tool_fb::filterFiguredBassNumbersForLineAndVoice -- +// + +vector Tool_fb::filterFiguredBassNumbersForLineAndVoice(vector numbers, int lineIndex, int voiceIndex) { + + vector filteredNumbers; + + // filter numbers with passed lineIndex and passed voiceIndex + copy_if(numbers.begin(), numbers.end(), back_inserter(filteredNumbers), [lineIndex, voiceIndex](FiguredBassNumber* num) { + return (num->m_lineIndex == lineIndex) && (num->m_voiceIndex == voiceIndex); + }); + + // sort by voiceIndex (probably not needed here) + sort(filteredNumbers.begin(), filteredNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { + return a->m_voiceIndex > b->m_voiceIndex; + }); + + return filterNegativeNumbers(filteredNumbers); +} + + + +////////////////////////////// +// +// Tool_fb::formatFiguredBassNumbers -- Create a **fb data record string out of the passed FiguredBassNumber objects +// + +string Tool_fb::formatFiguredBassNumbers(const vector& numbers) { + + vector formattedNumbers; + + // Normalize numbers (remove 8 and 1, sort by size, remove duplicate numbers) + if (m_normalizeQ) { + bool aQ = m_accidentalsQ; + // remove 8 and 1 but keep them if they have an accidental + copy_if(numbers.begin(), numbers.end(), back_inserter(formattedNumbers), [aQ](FiguredBassNumber* num) { + return ((num->getNumberWithinOctave() != 8) && (num->getNumberWithinOctave() != 1)) || (aQ && num->m_showAccidentals); + }); + // sort by size + sort(formattedNumbers.begin(), formattedNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { + return a->getNumberWithinOctave() < b->getNumberWithinOctave(); + }); + // remove duplicate numbers + formattedNumbers.erase(unique(formattedNumbers.begin(), formattedNumbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) { + return a->getNumberWithinOctave() == b->getNumberWithinOctave(); + }), formattedNumbers.end()); + } else { + formattedNumbers = numbers; + } + + // Hide numbers if they have no attack + if (m_intervallsatzQ && m_attackQ) { + vector attackNumbers; + copy_if(formattedNumbers.begin(), formattedNumbers.end(), back_inserter(attackNumbers), [](FiguredBassNumber* num) { + return num->m_isAttack || num->m_currAttackNumberDidChange; + }); + formattedNumbers = attackNumbers; + } + + // Analysze before sorting + if (m_compoundQ) { + formattedNumbers = analyzeChordNumbers(formattedNumbers); + } + + // Sort numbers by size + if (m_sortQ) { + bool cQ = m_compoundQ; + sort(formattedNumbers.begin(), formattedNumbers.end(), [cQ](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { + // sort by getNumberWithinOctave if compoundQ is true otherwise sort by number + return (cQ) ? a->getNumberWithinOctave() > b->getNumberWithinOctave() : a->m_number > b->m_number; + }); + } + + if (m_abbrQ) { + // Overwrite formattedNumbers with abbreviated numbers + formattedNumbers = getAbbreviatedNumbers(formattedNumbers); } - for (int i=infile.getLineCount() - 2; i>=0; i--) { - if (m_keyaccid[i].empty()) { - m_keyaccid[i] = m_keyaccid[i+1]; + + // join numbers + string str = ""; + bool first = true; + for (FiguredBassNumber* number: formattedNumbers) { + string num = number->toString(m_compoundQ, m_accidentalsQ, m_hideThreeQ); + if (num.length() > 0) { + if (!first) str += " "; + first = false; + str += num; } } + return str; } ////////////////////////////// // -// Tool_fb:printOutput -- +// Tool_fb::getAbbreviatedNumbers -- Get abbreviated figured bass numbers +// If no abbreviation is found all numbers will be shown + +vector Tool_fb::getAbbreviatedNumbers(const vector& numbers) { + + vector abbreviatedNumbers; + + vector mappings = FiguredBassAbbreviationMapping::s_mappings; + + string numberString = getNumberString(numbers); + + // Check if an abbreviation exists for passed numbers + auto it = find_if(mappings.begin(), mappings.end(), [numberString](FiguredBassAbbreviationMapping* abbr) { + return abbr->m_str == numberString; + }); + + if (it != mappings.end()) { + int index = it - mappings.begin(); + FiguredBassAbbreviationMapping* abbr = mappings[index]; + bool aQ = m_accidentalsQ; + // Store numbers to display by the abbreviation mapping in abbreviatedNumbers + copy_if(numbers.begin(), numbers.end(), back_inserter(abbreviatedNumbers), [abbr, aQ](FiguredBassNumber* num) { + vector nums = abbr->m_numbers; + // Show numbers if they are part of the abbreviation mapping or if they have an accidental + return (find(nums.begin(), nums.end(), num->getNumberWithinOctave()) != nums.end()) || (num->m_showAccidentals && aQ); + }); + + return abbreviatedNumbers; + } + + return numbers; +} + + + +////////////////////////////// // +// Tool_fb::analyzeChordNumbers -- Analyze chord numbers and improve them +// Set m_convert2To9 to true when a 3 is included in the chord numbers. -void Tool_fb::printOutput(HumdrumFile& infile) { - for (int i=0; i Tool_fb::analyzeChordNumbers(const vector& numbers) { + + vector analyzedNumbers = numbers; + + // Check if compound numbers 3 is withing passed numbers (chord) + auto it = find_if(analyzedNumbers.begin(), analyzedNumbers.end(), [](FiguredBassNumber* number) { + return number->getNumberWithinOctave() == 3; + }); + if (it != analyzedNumbers.end()) { + for (auto &number : analyzedNumbers) { + number->m_convert2To9 = true; } - printLineStyle3(infile, i); } + + return analyzedNumbers; } ////////////////////////////// // -// Tool_fb::printLineStyle3 -- +// Tool_fb::getNumberString -- Get only the numbers (without accidentals) of passed FiguredBassNumbers // -void Tool_fb::printLineStyle3(HumdrumFile& infile, int line) { - bool printed = false; - int reftrack = m_kerntracks[m_reference]; - bool tab = false; +string Tool_fb::getNumberString(vector numbers) { + // Sort numbers by size + sort(numbers.begin(), numbers.end(), [](FiguredBassNumber* a, FiguredBassNumber* b) -> bool { + return a->getNumberWithinOctave() > b->getNumberWithinOctave(); + }); + // join numbers + string str = ""; + bool first = true; + for (FiguredBassNumber* nr: numbers) { + int num = nr->getNumberWithinOctave(); + if (num > 0) { + if (!first) str += " "; + first = false; + str += to_string(num); + } + } + return str; +} - for (int i=0; igetTrack(); - if (printed || (track != reftrack + 1)) { - if (tab) { - m_humdrum_text << "\t" << token; - } else { - tab = true; - m_humdrum_text << token; + + +////////////////////////////// +// +// Tool_fb::getKeySignature -- Get the key signature for a line index of the input file +// + +string Tool_fb::getKeySignature(HumdrumFile& infile, int lineIndex) { + string keySignature = ""; + [&] { + for (int i = 0; i < infile.getLineCount(); i++) { + if (i > lineIndex) { + return; + } + HLp line = infile.getLine(i); + for (int j = 0; j < line->getFieldCount(); j++) { + if (line->token(j)->isKeySignature()) { + keySignature = line->getTokenString(j); + } } - continue; - } - // print analysis spine and then next spine - if (tab) { - m_humdrum_text << "\t"; - } else { - tab = true; } - m_humdrum_text << getAnalysisTokenStyle3(infile, line, i); - printed = true; - m_humdrum_text << "\t" << token; + }(); + return keySignature; +} + + + +////////////////////////////// +// +// Tool_fb::getLowestBase40Pitch -- Get lowest base 40 pitch that is not a rest or silent +// TODO: Handle negative values and sustained notes +// + +int Tool_fb::getLowestBase40Pitch(vector base40Pitches) { + vector filteredBase40Pitches; + copy_if(base40Pitches.begin(), base40Pitches.end(), std::back_inserter(filteredBase40Pitches), [](int base40Pitch) { + // Ignore if base is a rest or silent note + return base40Pitch != -1000 && base40Pitch != -2000 && base40Pitch != 0; + }); + + if (filteredBase40Pitches.size() == 0) { + return -2000; } - m_humdrum_text << "\n"; + + return *min_element(begin(filteredBase40Pitches), end(filteredBase40Pitches)); +} + + +////////////////////////////// +// +// FiguredBassNumber::FiguredBassNumber -- Constructor +// + +FiguredBassNumber::FiguredBassNumber(int num, string accid, bool showAccid, int voiceIdx, int lineIdx, bool isAtk, bool intervallsatz) { + m_number = num; + m_accidentals = accid; + m_voiceIndex = voiceIdx; + m_lineIndex = lineIdx; + m_showAccidentals = showAccid; + m_isAttack = isAtk; + m_intervallsatz = intervallsatz; } ////////////////////////////// // -// Tool_fb::getAnalysisTokenStyle3 -- +// FiguredBassNumber::toString -- Convert FiguredBassNumber to a string (accidental + number) // -string Tool_fb::getAnalysisTokenStyle3(HumdrumFile& infile, int line, int field) { - if (infile[line].isCommentLocal()) { - return "!"; +string FiguredBassNumber::toString(bool compoundQ, bool accidentalsQ, bool hideThreeQ) { + int num = (compoundQ) ? getNumberWithinOctave() : m_number; + string accid = (accidentalsQ && m_showAccidentals) ? m_accidentals : ""; + if (((num == 3) || (num == -3)) && accidentalsQ && m_showAccidentals && hideThreeQ) { + return accid; } - if (infile[line].isInterpretation()) { - HTp token = infile.token(line, 0); - if (token->compare(0, 2, "**") == 0) { - return "**fb"; - } else if (*token == "*-") { - return "*-"; - } else if (token->isLabel()) { - return *token; - } else if (token->isExpansionList()) { - return *token; - } else if (token->isKeySignature()) { - return *token; - } else if (token->isKeyDesignation()) { - return *token; - } else { - return "*"; - } + if (num > 0) { + return accid + to_string(num); } - if (infile[line].isBarline()) { - HTp token = infile.token(line, 0); - return *token; + if (num < 0) { + return accid + "~" + to_string(abs(num)); } + return ""; +} - // create data token - string output; - for (int i=(int)m_intervals[line].size()-1; i>=0; i--) { - if (i == m_reference) { - continue; + +////////////////////////////// +// +// FiguredBassNumber::getNumberWithinOctave -- Get a reasonable figured bass number +// Replace 0 with 7 and -7 +// Replace 1 with 8 and -8 +// Replace 2 with 9 if it is a suspension of the ninth +// Allow 1 (unisono) in intervallsatz + +int FiguredBassNumber::getNumberWithinOctave(void) { + int num = m_number % 7; + + // Replace 0 with 7 and -7 + if ((abs(m_number) > 0) && (m_number % 7 == 0)) { + return m_number < 0 ? -7 : 7; + } + + // Replace 1 with 8 and -8 + if (abs(num) == 1) { + // Allow unisono in intervallsatz + if (m_intervallsatz) { + if (abs(m_number) == 1) { + return 1; + } } - int base40int = m_intervals[line][i]; - string iname = Convert::base40ToIntervalAbbr(base40int); - output += iname; - output += " "; + return m_number < 0 ? -8 : 8; } - if (!output.empty()) { - output.resize((int)output.size() - 1); + + // Replace 2 with 9 if m_convert2To9 is true (e.g. when a 3 is included in the chord numbers) + if (m_convert2To9 && (num == 2)) { + return 9; } - return output; + return num; +} + + + +////////////////////////////// +// +// FiguredBassAbbreviationMapping::FiguredBassAbbreviationMapping -- Constructor +// Helper class to store the mappings for abbreviate figured bass numbers +// + +FiguredBassAbbreviationMapping::FiguredBassAbbreviationMapping(string s, vector n) { + m_str = s; + m_numbers = n; } +////////////////////////////// +// +// FiguredBassAbbreviationMapping::s_mappings -- Mapping to abbreviate figured bass numbers +// + +vector FiguredBassAbbreviationMapping::s_mappings = { + new FiguredBassAbbreviationMapping("3", {}), + new FiguredBassAbbreviationMapping("5", {}), + new FiguredBassAbbreviationMapping("5 3", {}), + new FiguredBassAbbreviationMapping("6 3", {6}), + new FiguredBassAbbreviationMapping("5 4", {4}), + new FiguredBassAbbreviationMapping("7 5 3", {7}), + new FiguredBassAbbreviationMapping("7 3", {7}), + new FiguredBassAbbreviationMapping("7 5", {7}), + new FiguredBassAbbreviationMapping("6 5 3", {6, 5}), + new FiguredBassAbbreviationMapping("6 4 3", {4, 3}), + new FiguredBassAbbreviationMapping("6 4 2", {4, 2}), + new FiguredBassAbbreviationMapping("9 5 3", {9}), + new FiguredBassAbbreviationMapping("9 5", {9}), + new FiguredBassAbbreviationMapping("9 3", {9}), +}; + + #define RUNTOOL(NAME, INFILE, COMMAND, STATUS) \ Tool_##NAME *tool = new Tool_##NAME; \ @@ -77125,6 +77582,8 @@ bool Tool_filter::run(HumdrumFileSet& infiles) { RUNTOOL(dissonant, infile, commands[i].second, status); } else if (commands[i].first == "double") { RUNTOOL(double, infile, commands[i].second, status); + } else if (commands[i].first == "fb") { + RUNTOOL(fb, infile, commands[i].second, status); } else if (commands[i].first == "flipper") { RUNTOOL(flipper, infile, commands[i].second, status); } else if (commands[i].first == "filter") { From ce550c2fa1d15a2f7b75aa948e1aee1dda3e4c6a Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Mon, 16 Jan 2023 00:59:55 +0100 Subject: [PATCH 088/109] Use kern track numbering for --base instead of voice index --- include/humlib.h | 4 ++-- include/tool-fb.h | 2 +- src/humlib.cpp | 18 +++++++++--------- src/tool-fb.cpp | 46 +++++++++++++++++++++++----------------------- 4 files changed, 35 insertions(+), 35 deletions(-) diff --git a/include/humlib.h b/include/humlib.h index 99f0e13f..9a4fa4a7 100644 --- a/include/humlib.h +++ b/include/humlib.h @@ -1,7 +1,7 @@ // // Programmer: Craig Stuart Sapp // Creation Date: Sat Aug 8 12:24:49 PDT 2015 -// Last Modified: Mo 16 Jan 2023 00:43:21 CET +// Last Modified: Mo 16 Jan 2023 00:58:36 CET // Filename: humlib.h // URL: https://github.com/craigsapp/humlib/blob/master/include/humlib.h // Syntax: C++11 @@ -7233,7 +7233,7 @@ class Tool_fb : public HumTool { private: bool m_compoundQ = false; bool m_accidentalsQ = false; - int m_baseQ = 0; + int m_baseTrackQ = 1; bool m_intervallsatzQ = false; bool m_sortQ = false; bool m_lowestQ = false; diff --git a/include/tool-fb.h b/include/tool-fb.h index 8a99db06..ad5d54cb 100644 --- a/include/tool-fb.h +++ b/include/tool-fb.h @@ -86,7 +86,7 @@ class Tool_fb : public HumTool { private: bool m_compoundQ = false; bool m_accidentalsQ = false; - int m_baseQ = 0; + int m_baseTrackQ = 1; bool m_intervallsatzQ = false; bool m_sortQ = false; bool m_lowestQ = false; diff --git a/src/humlib.cpp b/src/humlib.cpp index 5ba63c7c..5d10dc38 100644 --- a/src/humlib.cpp +++ b/src/humlib.cpp @@ -1,7 +1,7 @@ // // Programmer: Craig Stuart Sapp // Creation Date: Sat Aug 8 12:24:49 PDT 2015 -// Last Modified: Mo 16 Jan 2023 00:43:21 CET +// Last Modified: Mo 16 Jan 2023 00:58:36 CET // Filename: /include/humlib.cpp // URL: https://github.com/craigsapp/humlib/blob/master/src/humlib.cpp // Syntax: C++11 @@ -77459,7 +77459,7 @@ bool Tool_fb::run(HumdrumFile &infile) { void Tool_fb::initialize(void) { m_compoundQ = getBoolean("compound"); m_accidentalsQ = getBoolean("accidentals"); - m_baseQ = getInteger("base"); + m_baseTrackQ = getInteger("base"); m_intervallsatzQ = getBoolean("intervallsatz"); m_sortQ = getBoolean("sort"); m_lowestQ = getBoolean("lowest"); @@ -77545,10 +77545,10 @@ void Tool_fb::processFile(HumdrumFile& infile) { currentNumbers.clear(); currentNumbers.resize((int)grid.getVoiceCount()); - // Reset usedBaseVoiceIndex - int usedBaseVoiceIndex = m_baseQ; + // Reset usedBaseTrack + int usedBaseTrack = m_baseTrackQ; - // Overwrite usedBaseVoiceIndex with the lowest voice index of the lowest pitched note + // Overwrite usedBaseTrack with the lowest voice index of the lowest pitched note if (m_lowestQ) { int lowestNotePitch = 99999; for (int k=0; k<(int)grid.getVoiceCount(); k++) { @@ -77559,13 +77559,13 @@ void Tool_fb::processFile(HumdrumFile& infile) { if (checkCellPitch != 0 && checkCellPitch != -1000 && checkCellPitch != -2000) { if ((checkCellPitch > 0) && (checkCellPitch < lowestNotePitch)) { lowestNotePitch = checkCellPitch; - usedBaseVoiceIndex = k; + usedBaseTrack = checkCell->getToken()->getTrack(); } } } } - NoteCell* baseCell = grid.cell(usedBaseVoiceIndex, i); + NoteCell* baseCell = grid.cell(usedBaseTrack - 1, i); string keySignature = getKeySignature(infile, baseCell->getLineIndex()); // Hide numbers if they do not match rhythmic position of --recip @@ -77667,8 +77667,8 @@ void Tool_fb::processFile(HumdrumFile& infile) { } else { // Create **fb spine and bind it to the base voice vector trackData = getTrackData(numbers, infile.getLineCount()); - if (m_baseQ + 1 < grid.getVoiceCount()) { - int trackIndex = kernspines[m_baseQ + 1]->getTrack(); + if (m_baseTrackQ < grid.getVoiceCount()) { + int trackIndex = kernspines[m_baseTrackQ]->getTrack(); infile.insertDataSpineBefore(trackIndex, trackData, ".", exinterp); } else { infile.appendDataSpine(trackData, ".", exinterp); diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index ef02a89c..80ff47ce 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -27,21 +27,21 @@ namespace hum { // Tool_fb::Tool_fb(void) { - define("c|compound=b", "output reasonable figured bass numbers within octave"); - define("a|accidentals=b", "display accidentals in figured bass output"); - define("b|base=i:0", "number of the base voice/spine"); - define("i|intervallsatz=b", "display intervals under their voice and not under the lowest staff"); - define("o|sort|order=b", "sort figured bass numbers by interval size and not by voice index"); - define("l|lowest=b", "use lowest note as base note; -b flag will be ignored"); - define("n|normalize=b", "remove octave and doubled intervals; adds: --compound --sort"); - define("r|abbr=b", "use abbreviated figures; adds: --normalize --compound --sort"); - define("t|attack=b", "hide intervalls with no attack and when base does not change"); - define("f|figuredbass=b", "shortcut for -c -a -o -n -r -3"); - define("3|hide-three=b", "hide number 3 if it has an accidental (e.g.: #3 => #)"); - define("m|negative=b", "show negative numbers"); - define("above=b", "place figured bass numbers above staff (**fba)"); - define("recip=s:", "only show numbers if they are divisible by this **recip value (e.g. 2, 4, 8, 4.)"); - define("k|kern-tracks=s", "Process only the specified kern spines"); + define("c|compound=b", "output reasonable figured bass numbers within octave"); + define("a|accidentals=b", "display accidentals in figured bass output"); + define("b|base|base-track=i:1", "number of the base kern track (compare with -k)"); + define("i|intervallsatz=b", "display intervals under their voice and not under the lowest staff"); + define("o|sort|order=b", "sort figured bass numbers by interval size and not by voice index"); + define("l|lowest=b", "use lowest note as base note; -b flag will be ignored"); + define("n|normalize=b", "remove octave and doubled intervals; adds: --compound --sort"); + define("r|abbr=b", "use abbreviated figures; adds: --normalize --compound --sort"); + define("t|attack=b", "hide intervalls with no attack and when base does not change"); + define("f|figuredbass=b", "shortcut for -c -a -o -n -r -3"); + define("3|hide-three=b", "hide number 3 if it has an accidental (e.g.: #3 => #)"); + define("m|negative=b", "show negative numbers"); + define("above=b", "place figured bass numbers above staff (**fba)"); + define("recip=s:", "only show numbers if they are divisible by this **recip value (e.g. 2, 4, 8, 4.)"); + define("k|kern-tracks=s", "Process only the specified kern spines"); define("s|spine-tracks|spine|spines|track|tracks=s", "Process only the specified spines"); } @@ -97,7 +97,7 @@ bool Tool_fb::run(HumdrumFile &infile) { void Tool_fb::initialize(void) { m_compoundQ = getBoolean("compound"); m_accidentalsQ = getBoolean("accidentals"); - m_baseQ = getInteger("base"); + m_baseTrackQ = getInteger("base"); m_intervallsatzQ = getBoolean("intervallsatz"); m_sortQ = getBoolean("sort"); m_lowestQ = getBoolean("lowest"); @@ -183,10 +183,10 @@ void Tool_fb::processFile(HumdrumFile& infile) { currentNumbers.clear(); currentNumbers.resize((int)grid.getVoiceCount()); - // Reset usedBaseVoiceIndex - int usedBaseVoiceIndex = m_baseQ; + // Reset usedBaseTrack + int usedBaseTrack = m_baseTrackQ; - // Overwrite usedBaseVoiceIndex with the lowest voice index of the lowest pitched note + // Overwrite usedBaseTrack with the lowest voice index of the lowest pitched note if (m_lowestQ) { int lowestNotePitch = 99999; for (int k=0; k<(int)grid.getVoiceCount(); k++) { @@ -197,13 +197,13 @@ void Tool_fb::processFile(HumdrumFile& infile) { if (checkCellPitch != 0 && checkCellPitch != -1000 && checkCellPitch != -2000) { if ((checkCellPitch > 0) && (checkCellPitch < lowestNotePitch)) { lowestNotePitch = checkCellPitch; - usedBaseVoiceIndex = k; + usedBaseTrack = checkCell->getToken()->getTrack(); } } } } - NoteCell* baseCell = grid.cell(usedBaseVoiceIndex, i); + NoteCell* baseCell = grid.cell(usedBaseTrack - 1, i); string keySignature = getKeySignature(infile, baseCell->getLineIndex()); // Hide numbers if they do not match rhythmic position of --recip @@ -305,8 +305,8 @@ void Tool_fb::processFile(HumdrumFile& infile) { } else { // Create **fb spine and bind it to the base voice vector trackData = getTrackData(numbers, infile.getLineCount()); - if (m_baseQ + 1 < grid.getVoiceCount()) { - int trackIndex = kernspines[m_baseQ + 1]->getTrack(); + if (m_baseTrackQ < grid.getVoiceCount()) { + int trackIndex = kernspines[m_baseTrackQ]->getTrack(); infile.insertDataSpineBefore(trackIndex, trackData, ".", exinterp); } else { infile.appendDataSpine(trackData, ".", exinterp); From 6b3f97dcaccdde568babcecadd681f45c4e696ff Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Mon, 16 Jan 2023 01:10:04 +0100 Subject: [PATCH 089/109] Add brackets --- src/humlib.cpp | 2 +- src/tool-fb.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/humlib.cpp b/src/humlib.cpp index 5d10dc38..a55ce9b7 100644 --- a/src/humlib.cpp +++ b/src/humlib.cpp @@ -78081,7 +78081,7 @@ int Tool_fb::getLowestBase40Pitch(vector base40Pitches) { vector filteredBase40Pitches; copy_if(base40Pitches.begin(), base40Pitches.end(), std::back_inserter(filteredBase40Pitches), [](int base40Pitch) { // Ignore if base is a rest or silent note - return base40Pitch != -1000 && base40Pitch != -2000 && base40Pitch != 0; + return (base40Pitch != -1000) && (base40Pitch != -2000) && (base40Pitch != 0); }); if (filteredBase40Pitches.size() == 0) { diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 80ff47ce..e87c64c5 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -719,7 +719,7 @@ int Tool_fb::getLowestBase40Pitch(vector base40Pitches) { vector filteredBase40Pitches; copy_if(base40Pitches.begin(), base40Pitches.end(), std::back_inserter(filteredBase40Pitches), [](int base40Pitch) { // Ignore if base is a rest or silent note - return base40Pitch != -1000 && base40Pitch != -2000 && base40Pitch != 0; + return (base40Pitch != -1000) && (base40Pitch != -2000) && (base40Pitch != 0); }); if (filteredBase40Pitches.size() == 0) { From fd3923a506e03f8fafb530684cb43d5f96a863b3 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Mon, 16 Jan 2023 01:14:50 +0100 Subject: [PATCH 090/109] Handle wrong base track input --- src/tool-fb.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index e87c64c5..dccdc99b 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -152,12 +152,19 @@ void Tool_fb::processFile(HumdrumFile& infile) { vector kernspines = infile.getKernSpineStartList(); - // Calculate which input spines to process based on -s or -k option: int maxTrack = infile.getMaxTrack(); + + // Do nothing if base track not withing kern track range + if (m_baseTrackQ < 1 || m_baseTrackQ > maxTrack) { + return; + } + m_processTrack.resize(maxTrack + 1); // +1 is needed since track=0 is not used // By default, process all tracks: fill(m_processTrack.begin(), m_processTrack.end(), true); // Otherwise, select which **kern track, or spine tracks to process selectively: + + // Calculate which input spines to process based on -s or -k option: if (!m_kernTracks.empty()) { vector ktracks = Convert::extractIntegerList(m_kernTracks, maxTrack); fill(m_processTrack.begin(), m_processTrack.end(), false); From 1a357050de57dd1bd55965df469aa264b1a4652d Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Mon, 16 Jan 2023 01:15:10 +0100 Subject: [PATCH 091/109] Build humlib --- include/humlib.h | 2 +- src/humlib.cpp | 41 ++++++++++++++++++++++++----------------- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/include/humlib.h b/include/humlib.h index 9a4fa4a7..b8c62a0f 100644 --- a/include/humlib.h +++ b/include/humlib.h @@ -1,7 +1,7 @@ // // Programmer: Craig Stuart Sapp // Creation Date: Sat Aug 8 12:24:49 PDT 2015 -// Last Modified: Mo 16 Jan 2023 00:58:36 CET +// Last Modified: Mo 16 Jan 2023 01:14:53 CET // Filename: humlib.h // URL: https://github.com/craigsapp/humlib/blob/master/include/humlib.h // Syntax: C++11 diff --git a/src/humlib.cpp b/src/humlib.cpp index a55ce9b7..eea6a8e6 100644 --- a/src/humlib.cpp +++ b/src/humlib.cpp @@ -1,7 +1,7 @@ // // Programmer: Craig Stuart Sapp // Creation Date: Sat Aug 8 12:24:49 PDT 2015 -// Last Modified: Mo 16 Jan 2023 00:58:36 CET +// Last Modified: Mo 16 Jan 2023 01:14:53 CET // Filename: /include/humlib.cpp // URL: https://github.com/craigsapp/humlib/blob/master/src/humlib.cpp // Syntax: C++11 @@ -77389,21 +77389,21 @@ void Tool_extract::initialize(HumdrumFile& infile) { // Tool_fb::Tool_fb(void) { - define("c|compound=b", "output reasonable figured bass numbers within octave"); - define("a|accidentals=b", "display accidentals in figured bass output"); - define("b|base=i:0", "number of the base voice/spine"); - define("i|intervallsatz=b", "display intervals under their voice and not under the lowest staff"); - define("o|sort|order=b", "sort figured bass numbers by interval size and not by voice index"); - define("l|lowest=b", "use lowest note as base note; -b flag will be ignored"); - define("n|normalize=b", "remove octave and doubled intervals; adds: --compound --sort"); - define("r|abbr=b", "use abbreviated figures; adds: --normalize --compound --sort"); - define("t|attack=b", "hide intervalls with no attack and when base does not change"); - define("f|figuredbass=b", "shortcut for -c -a -o -n -r -3"); - define("3|hide-three=b", "hide number 3 if it has an accidental (e.g.: #3 => #)"); - define("m|negative=b", "show negative numbers"); - define("above=b", "place figured bass numbers above staff (**fba)"); - define("recip=s:", "only show numbers if they are divisible by this **recip value (e.g. 2, 4, 8, 4.)"); - define("k|kern-tracks=s", "Process only the specified kern spines"); + define("c|compound=b", "output reasonable figured bass numbers within octave"); + define("a|accidentals=b", "display accidentals in figured bass output"); + define("b|base|base-track=i:1", "number of the base kern track (compare with -k)"); + define("i|intervallsatz=b", "display intervals under their voice and not under the lowest staff"); + define("o|sort|order=b", "sort figured bass numbers by interval size and not by voice index"); + define("l|lowest=b", "use lowest note as base note; -b flag will be ignored"); + define("n|normalize=b", "remove octave and doubled intervals; adds: --compound --sort"); + define("r|abbr=b", "use abbreviated figures; adds: --normalize --compound --sort"); + define("t|attack=b", "hide intervalls with no attack and when base does not change"); + define("f|figuredbass=b", "shortcut for -c -a -o -n -r -3"); + define("3|hide-three=b", "hide number 3 if it has an accidental (e.g.: #3 => #)"); + define("m|negative=b", "show negative numbers"); + define("above=b", "place figured bass numbers above staff (**fba)"); + define("recip=s:", "only show numbers if they are divisible by this **recip value (e.g. 2, 4, 8, 4.)"); + define("k|kern-tracks=s", "Process only the specified kern spines"); define("s|spine-tracks|spine|spines|track|tracks=s", "Process only the specified spines"); } @@ -77514,12 +77514,19 @@ void Tool_fb::processFile(HumdrumFile& infile) { vector kernspines = infile.getKernSpineStartList(); - // Calculate which input spines to process based on -s or -k option: int maxTrack = infile.getMaxTrack(); + + // Do nothing if base track not withing kern track range + if (m_baseTrackQ < 1 || m_baseTrackQ > maxTrack) { + return; + } + m_processTrack.resize(maxTrack + 1); // +1 is needed since track=0 is not used // By default, process all tracks: fill(m_processTrack.begin(), m_processTrack.end(), true); // Otherwise, select which **kern track, or spine tracks to process selectively: + + // Calculate which input spines to process based on -s or -k option: if (!m_kernTracks.empty()) { vector ktracks = Convert::extractIntegerList(m_kernTracks, maxTrack); fill(m_processTrack.begin(), m_processTrack.end(), false); From 6c3a5761571c01e0b89c0e69bb6f6cba5269f430 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Mon, 16 Jan 2023 10:09:11 +0100 Subject: [PATCH 092/109] Add --frequency as alternative to --recip --- include/humlib.h | 2 +- src/humlib.cpp | 4 ++-- src/tool-fb.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/humlib.h b/include/humlib.h index b8c62a0f..c4e7d9eb 100644 --- a/include/humlib.h +++ b/include/humlib.h @@ -1,7 +1,7 @@ // // Programmer: Craig Stuart Sapp // Creation Date: Sat Aug 8 12:24:49 PDT 2015 -// Last Modified: Mo 16 Jan 2023 01:14:53 CET +// Last Modified: Mo 16 Jan 2023 10:08:28 CET // Filename: humlib.h // URL: https://github.com/craigsapp/humlib/blob/master/include/humlib.h // Syntax: C++11 diff --git a/src/humlib.cpp b/src/humlib.cpp index eea6a8e6..d91f2fa8 100644 --- a/src/humlib.cpp +++ b/src/humlib.cpp @@ -1,7 +1,7 @@ // // Programmer: Craig Stuart Sapp // Creation Date: Sat Aug 8 12:24:49 PDT 2015 -// Last Modified: Mo 16 Jan 2023 01:14:53 CET +// Last Modified: Mo 16 Jan 2023 10:08:28 CET // Filename: /include/humlib.cpp // URL: https://github.com/craigsapp/humlib/blob/master/src/humlib.cpp // Syntax: C++11 @@ -77402,7 +77402,7 @@ Tool_fb::Tool_fb(void) { define("3|hide-three=b", "hide number 3 if it has an accidental (e.g.: #3 => #)"); define("m|negative=b", "show negative numbers"); define("above=b", "place figured bass numbers above staff (**fba)"); - define("recip=s:", "only show numbers if they are divisible by this **recip value (e.g. 2, 4, 8, 4.)"); + define("frequency|recip=s:", "frequency to display the numbers (set a **recip value, e.g. 2, 4, 8, 4.)"); define("k|kern-tracks=s", "Process only the specified kern spines"); define("s|spine-tracks|spine|spines|track|tracks=s", "Process only the specified spines"); } diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index dccdc99b..e98ceb50 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -40,7 +40,7 @@ Tool_fb::Tool_fb(void) { define("3|hide-three=b", "hide number 3 if it has an accidental (e.g.: #3 => #)"); define("m|negative=b", "show negative numbers"); define("above=b", "place figured bass numbers above staff (**fba)"); - define("recip=s:", "only show numbers if they are divisible by this **recip value (e.g. 2, 4, 8, 4.)"); + define("frequency|recip=s:", "frequency to display the numbers (set a **recip value, e.g. 2, 4, 8, 4.)"); define("k|kern-tracks=s", "Process only the specified kern spines"); define("s|spine-tracks|spine|spines|track|tracks=s", "Process only the specified spines"); } From 404b43381aa07c464717cf503c8d5ade1706cf4f Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Mon, 16 Jan 2023 12:39:52 +0100 Subject: [PATCH 093/109] Fix getString to frequency --- src/tool-fb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index e98ceb50..b0355ed9 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -108,7 +108,7 @@ void Tool_fb::initialize(void) { m_hideThreeQ = getBoolean("hide-three"); m_showNegativeQ = getBoolean("negative"); m_aboveQ = getBoolean("above"); - m_recipQ = getString("recip"); + m_recipQ = getString("frequency"); if (getBoolean("spine-tracks")) { m_spineTracks = getString("spine-tracks"); From 6273e0feeec15e34848bcb1ffb6630aae7ae3135 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Mon, 16 Jan 2023 12:42:23 +0100 Subject: [PATCH 094/109] Fix --lowest option --- src/tool-fb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index b0355ed9..3ad8b9df 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -204,7 +204,7 @@ void Tool_fb::processFile(HumdrumFile& infile) { if (checkCellPitch != 0 && checkCellPitch != -1000 && checkCellPitch != -2000) { if ((checkCellPitch > 0) && (checkCellPitch < lowestNotePitch)) { lowestNotePitch = checkCellPitch; - usedBaseTrack = checkCell->getToken()->getTrack(); + usedBaseTrack = k + 1; } } } From bda171c3a36fc2d13ab19ad1fdf1f9d97380a673 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Mon, 16 Jan 2023 12:43:03 +0100 Subject: [PATCH 095/109] Improve variable name for usedBaseKernTrack --- src/tool-fb.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 3ad8b9df..30185412 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -190,10 +190,10 @@ void Tool_fb::processFile(HumdrumFile& infile) { currentNumbers.clear(); currentNumbers.resize((int)grid.getVoiceCount()); - // Reset usedBaseTrack - int usedBaseTrack = m_baseTrackQ; + // Reset usedBaseKernTrack + int usedBaseKernTrack = m_baseTrackQ; - // Overwrite usedBaseTrack with the lowest voice index of the lowest pitched note + // Overwrite usedBaseKernTrack with the lowest voice index of the lowest pitched note if (m_lowestQ) { int lowestNotePitch = 99999; for (int k=0; k<(int)grid.getVoiceCount(); k++) { @@ -204,13 +204,13 @@ void Tool_fb::processFile(HumdrumFile& infile) { if (checkCellPitch != 0 && checkCellPitch != -1000 && checkCellPitch != -2000) { if ((checkCellPitch > 0) && (checkCellPitch < lowestNotePitch)) { lowestNotePitch = checkCellPitch; - usedBaseTrack = k + 1; + usedBaseKernTrack = k + 1; } } } } - NoteCell* baseCell = grid.cell(usedBaseTrack - 1, i); + NoteCell* baseCell = grid.cell(usedBaseKernTrack - 1, i); string keySignature = getKeySignature(infile, baseCell->getLineIndex()); // Hide numbers if they do not match rhythmic position of --recip From 75e09b49386140cb2e08505e2880a3156172521a Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Mon, 16 Jan 2023 12:43:50 +0100 Subject: [PATCH 096/109] Improvements for sustained notes --- src/tool-fb.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 30185412..d36cb353 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -202,8 +202,8 @@ void Tool_fb::processFile(HumdrumFile& infile) { int checkCellPitch = getLowestBase40Pitch(checkCell->getToken()->resolveNull()->getBase40Pitches()); // Ignore if base is a rest or silent note if (checkCellPitch != 0 && checkCellPitch != -1000 && checkCellPitch != -2000) { - if ((checkCellPitch > 0) && (checkCellPitch < lowestNotePitch)) { - lowestNotePitch = checkCellPitch; + if (abs(checkCellPitch) < lowestNotePitch) { + lowestNotePitch = abs(checkCellPitch); usedBaseKernTrack = k + 1; } } From 834cc9302e7623897e68384a3adaa9e187594d36 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Mon, 16 Jan 2023 17:10:39 +0100 Subject: [PATCH 097/109] Fix -t for chords --- include/tool-fb.h | 2 +- src/tool-fb.cpp | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/tool-fb.h b/include/tool-fb.h index ad5d54cb..cc24bb7f 100644 --- a/include/tool-fb.h +++ b/include/tool-fb.h @@ -31,7 +31,7 @@ class FiguredBassNumber { int m_number; std::string m_accidentals; bool m_showAccidentals; // Force shoing figured base numbers when they need an accidental - bool m_currAttackNumberDidChange; + bool m_baseOfSustainedNoteDidChange; bool m_isAttack; bool m_convert2To9 = false; bool m_intervallsatz = false; diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index d36cb353..51e2e6c3 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -262,11 +262,6 @@ void Tool_fb::processFile(HumdrumFile& infile) { // Create FiguredBassNumber FiguredBassNumber* number = createFiguredBassNumber(abs(lowestBaseNoteBase40Pitch), abs(subtokenBase40), targetCell->getVoiceIndex(), targetCell->getLineIndex(), targetCell->isAttack(), keySignature); - if (lastNumbers[j].size() != 0) { - // If a number belongs to a sustained note but the base note did change - // the new numbers need to be displayable - number->m_currAttackNumberDidChange = (targetCell->isSustained()) && (std::find(lastNumbers[j].begin(), lastNumbers[j].end(), number->m_number) != lastNumbers[j].end()); - } currentNumbers[j].push_back(number->m_number); chordNumbers.push_back(number); @@ -288,6 +283,11 @@ void Tool_fb::processFile(HumdrumFile& infile) { // Then add to numbers vector for (FiguredBassNumber* num: chordNumbers) { + if (lastNumbers[j].size() != 0) { + // If a number belongs to a sustained note but the base note did change + // the new numbers need to be displayable + num->m_baseOfSustainedNoteDidChange = !num->m_isAttack && std::find(lastNumbers[j].begin(), lastNumbers[j].end(), num->m_number) == lastNumbers[j].end(); + } numbers.push_back(num); } } @@ -564,7 +564,7 @@ string Tool_fb::formatFiguredBassNumbers(const vector& numbe if (m_intervallsatzQ && m_attackQ) { vector attackNumbers; copy_if(formattedNumbers.begin(), formattedNumbers.end(), back_inserter(attackNumbers), [](FiguredBassNumber* num) { - return num->m_isAttack || num->m_currAttackNumberDidChange; + return num->m_isAttack || num->m_baseOfSustainedNoteDidChange; }); formattedNumbers = attackNumbers; } From 357c786383499f3c97f50f80eed1fef2d92bdb4b Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Mon, 16 Jan 2023 17:15:15 +0100 Subject: [PATCH 098/109] Rename -t option to ties --- src/tool-fb.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 51e2e6c3..6841f4dd 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -35,7 +35,7 @@ Tool_fb::Tool_fb(void) { define("l|lowest=b", "use lowest note as base note; -b flag will be ignored"); define("n|normalize=b", "remove octave and doubled intervals; adds: --compound --sort"); define("r|abbr=b", "use abbreviated figures; adds: --normalize --compound --sort"); - define("t|attack=b", "hide intervalls with no attack and when base does not change"); + define("t|ties=b", "hide repeated numbers for sustained notes when base does not change"); define("f|figuredbass=b", "shortcut for -c -a -o -n -r -3"); define("3|hide-three=b", "hide number 3 if it has an accidental (e.g.: #3 => #)"); define("m|negative=b", "show negative numbers"); @@ -103,7 +103,7 @@ void Tool_fb::initialize(void) { m_lowestQ = getBoolean("lowest"); m_normalizeQ = getBoolean("normalize"); m_abbrQ = getBoolean("abbr"); - m_attackQ = getBoolean("attack"); + m_attackQ = getBoolean("ties"); m_figuredbassQ = getBoolean("figuredbass"); m_hideThreeQ = getBoolean("hide-three"); m_showNegativeQ = getBoolean("negative"); From 5ce097819f95414fcf277b5c9050d5db72a34469 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Mon, 16 Jan 2023 17:15:42 +0100 Subject: [PATCH 099/109] Update humlib.h and humlib.cpp --- include/humlib.h | 4 ++-- src/humlib.cpp | 34 +++++++++++++++++----------------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/include/humlib.h b/include/humlib.h index c4e7d9eb..aea03c6e 100644 --- a/include/humlib.h +++ b/include/humlib.h @@ -1,7 +1,7 @@ // // Programmer: Craig Stuart Sapp // Creation Date: Sat Aug 8 12:24:49 PDT 2015 -// Last Modified: Mo 16 Jan 2023 10:08:28 CET +// Last Modified: Mo 16 Jan 2023 17:15:27 CET // Filename: humlib.h // URL: https://github.com/craigsapp/humlib/blob/master/include/humlib.h // Syntax: C++11 @@ -7178,7 +7178,7 @@ class FiguredBassNumber { int m_number; std::string m_accidentals; bool m_showAccidentals; // Force shoing figured base numbers when they need an accidental - bool m_currAttackNumberDidChange; + bool m_baseOfSustainedNoteDidChange; bool m_isAttack; bool m_convert2To9 = false; bool m_intervallsatz = false; diff --git a/src/humlib.cpp b/src/humlib.cpp index d91f2fa8..1780dfc5 100644 --- a/src/humlib.cpp +++ b/src/humlib.cpp @@ -1,7 +1,7 @@ // // Programmer: Craig Stuart Sapp // Creation Date: Sat Aug 8 12:24:49 PDT 2015 -// Last Modified: Mo 16 Jan 2023 10:08:28 CET +// Last Modified: Mo 16 Jan 2023 17:15:27 CET // Filename: /include/humlib.cpp // URL: https://github.com/craigsapp/humlib/blob/master/src/humlib.cpp // Syntax: C++11 @@ -77397,7 +77397,7 @@ Tool_fb::Tool_fb(void) { define("l|lowest=b", "use lowest note as base note; -b flag will be ignored"); define("n|normalize=b", "remove octave and doubled intervals; adds: --compound --sort"); define("r|abbr=b", "use abbreviated figures; adds: --normalize --compound --sort"); - define("t|attack=b", "hide intervalls with no attack and when base does not change"); + define("t|ties=b", "hide repeated numbers for sustained notes when base does not change"); define("f|figuredbass=b", "shortcut for -c -a -o -n -r -3"); define("3|hide-three=b", "hide number 3 if it has an accidental (e.g.: #3 => #)"); define("m|negative=b", "show negative numbers"); @@ -77465,12 +77465,12 @@ void Tool_fb::initialize(void) { m_lowestQ = getBoolean("lowest"); m_normalizeQ = getBoolean("normalize"); m_abbrQ = getBoolean("abbr"); - m_attackQ = getBoolean("attack"); + m_attackQ = getBoolean("ties"); m_figuredbassQ = getBoolean("figuredbass"); m_hideThreeQ = getBoolean("hide-three"); m_showNegativeQ = getBoolean("negative"); m_aboveQ = getBoolean("above"); - m_recipQ = getString("recip"); + m_recipQ = getString("frequency"); if (getBoolean("spine-tracks")) { m_spineTracks = getString("spine-tracks"); @@ -77552,10 +77552,10 @@ void Tool_fb::processFile(HumdrumFile& infile) { currentNumbers.clear(); currentNumbers.resize((int)grid.getVoiceCount()); - // Reset usedBaseTrack - int usedBaseTrack = m_baseTrackQ; + // Reset usedBaseKernTrack + int usedBaseKernTrack = m_baseTrackQ; - // Overwrite usedBaseTrack with the lowest voice index of the lowest pitched note + // Overwrite usedBaseKernTrack with the lowest voice index of the lowest pitched note if (m_lowestQ) { int lowestNotePitch = 99999; for (int k=0; k<(int)grid.getVoiceCount(); k++) { @@ -77564,15 +77564,15 @@ void Tool_fb::processFile(HumdrumFile& infile) { int checkCellPitch = getLowestBase40Pitch(checkCell->getToken()->resolveNull()->getBase40Pitches()); // Ignore if base is a rest or silent note if (checkCellPitch != 0 && checkCellPitch != -1000 && checkCellPitch != -2000) { - if ((checkCellPitch > 0) && (checkCellPitch < lowestNotePitch)) { - lowestNotePitch = checkCellPitch; - usedBaseTrack = checkCell->getToken()->getTrack(); + if (abs(checkCellPitch) < lowestNotePitch) { + lowestNotePitch = abs(checkCellPitch); + usedBaseKernTrack = k + 1; } } } } - NoteCell* baseCell = grid.cell(usedBaseTrack - 1, i); + NoteCell* baseCell = grid.cell(usedBaseKernTrack - 1, i); string keySignature = getKeySignature(infile, baseCell->getLineIndex()); // Hide numbers if they do not match rhythmic position of --recip @@ -77624,11 +77624,6 @@ void Tool_fb::processFile(HumdrumFile& infile) { // Create FiguredBassNumber FiguredBassNumber* number = createFiguredBassNumber(abs(lowestBaseNoteBase40Pitch), abs(subtokenBase40), targetCell->getVoiceIndex(), targetCell->getLineIndex(), targetCell->isAttack(), keySignature); - if (lastNumbers[j].size() != 0) { - // If a number belongs to a sustained note but the base note did change - // the new numbers need to be displayable - number->m_currAttackNumberDidChange = (targetCell->isSustained()) && (std::find(lastNumbers[j].begin(), lastNumbers[j].end(), number->m_number) != lastNumbers[j].end()); - } currentNumbers[j].push_back(number->m_number); chordNumbers.push_back(number); @@ -77650,6 +77645,11 @@ void Tool_fb::processFile(HumdrumFile& infile) { // Then add to numbers vector for (FiguredBassNumber* num: chordNumbers) { + if (lastNumbers[j].size() != 0) { + // If a number belongs to a sustained note but the base note did change + // the new numbers need to be displayable + num->m_baseOfSustainedNoteDidChange = !num->m_isAttack && std::find(lastNumbers[j].begin(), lastNumbers[j].end(), num->m_number) == lastNumbers[j].end(); + } numbers.push_back(num); } } @@ -77926,7 +77926,7 @@ string Tool_fb::formatFiguredBassNumbers(const vector& numbe if (m_intervallsatzQ && m_attackQ) { vector attackNumbers; copy_if(formattedNumbers.begin(), formattedNumbers.end(), back_inserter(attackNumbers), [](FiguredBassNumber* num) { - return num->m_isAttack || num->m_currAttackNumberDidChange; + return num->m_isAttack || num->m_baseOfSustainedNoteDidChange; }); formattedNumbers = attackNumbers; } From 46a1c9331095dee61bff620586e4e413b2994980 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Mon, 16 Jan 2023 19:51:47 +0100 Subject: [PATCH 100/109] Fix missing 1 in unisono Fixes https://github.com/craigsapp/humlib/issues/58 --- include/humlib.h | 2 +- src/humlib.cpp | 4 ++-- src/tool-fb.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/humlib.h b/include/humlib.h index aea03c6e..6db8d8d7 100644 --- a/include/humlib.h +++ b/include/humlib.h @@ -1,7 +1,7 @@ // // Programmer: Craig Stuart Sapp // Creation Date: Sat Aug 8 12:24:49 PDT 2015 -// Last Modified: Mo 16 Jan 2023 17:15:27 CET +// Last Modified: Mo 16 Jan 2023 19:44:50 CET // Filename: humlib.h // URL: https://github.com/craigsapp/humlib/blob/master/include/humlib.h // Syntax: C++11 diff --git a/src/humlib.cpp b/src/humlib.cpp index 1780dfc5..404c25f8 100644 --- a/src/humlib.cpp +++ b/src/humlib.cpp @@ -1,7 +1,7 @@ // // Programmer: Craig Stuart Sapp // Creation Date: Sat Aug 8 12:24:49 PDT 2015 -// Last Modified: Mo 16 Jan 2023 17:15:27 CET +// Last Modified: Mo 16 Jan 2023 19:44:50 CET // Filename: /include/humlib.cpp // URL: https://github.com/craigsapp/humlib/blob/master/src/humlib.cpp // Syntax: C++11 @@ -77618,7 +77618,7 @@ void Tool_fb::processFile(HumdrumFile& infile) { } // Ignore if same pitch as base voice - if (abs(lowestBaseNoteBase40Pitch) == abs(subtokenBase40)) { + if ((abs(lowestBaseNoteBase40Pitch) == abs(subtokenBase40)) && (baseCell->getToken()->getTrack() == initialTokenTrack)) { continue; } diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 6841f4dd..141cadd9 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -256,7 +256,7 @@ void Tool_fb::processFile(HumdrumFile& infile) { } // Ignore if same pitch as base voice - if (abs(lowestBaseNoteBase40Pitch) == abs(subtokenBase40)) { + if ((abs(lowestBaseNoteBase40Pitch) == abs(subtokenBase40)) && (baseCell->getToken()->getTrack() == initialTokenTrack)) { continue; } From bd097682fea417c2c7cfed1b32f8a758a4f7d624 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Tue, 17 Jan 2023 00:43:14 +0100 Subject: [PATCH 101/109] Ignore grace notes Closes https://github.com/craigsapp/humlib/issues/56 --- include/humlib.h | 2 +- src/humlib.cpp | 8 +++++++- src/tool-fb.cpp | 6 ++++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/include/humlib.h b/include/humlib.h index 6db8d8d7..86e870bd 100644 --- a/include/humlib.h +++ b/include/humlib.h @@ -1,7 +1,7 @@ // // Programmer: Craig Stuart Sapp // Creation Date: Sat Aug 8 12:24:49 PDT 2015 -// Last Modified: Mo 16 Jan 2023 19:44:50 CET +// Last Modified: Di 17 Jan 2023 00:38:37 CET // Filename: humlib.h // URL: https://github.com/craigsapp/humlib/blob/master/include/humlib.h // Syntax: C++11 diff --git a/src/humlib.cpp b/src/humlib.cpp index 404c25f8..502d58ff 100644 --- a/src/humlib.cpp +++ b/src/humlib.cpp @@ -1,7 +1,7 @@ // // Programmer: Craig Stuart Sapp // Creation Date: Sat Aug 8 12:24:49 PDT 2015 -// Last Modified: Mo 16 Jan 2023 19:44:50 CET +// Last Modified: Di 17 Jan 2023 00:38:37 CET // Filename: /include/humlib.cpp // URL: https://github.com/craigsapp/humlib/blob/master/src/humlib.cpp // Syntax: C++11 @@ -77573,6 +77573,12 @@ void Tool_fb::processFile(HumdrumFile& infile) { } NoteCell* baseCell = grid.cell(usedBaseKernTrack - 1, i); + + // Ignore grace notes + if (baseCell->getToken()->getOwner()->getDuration() == 0) { + continue; + } + string keySignature = getKeySignature(infile, baseCell->getLineIndex()); // Hide numbers if they do not match rhythmic position of --recip diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 141cadd9..053316cf 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -211,6 +211,12 @@ void Tool_fb::processFile(HumdrumFile& infile) { } NoteCell* baseCell = grid.cell(usedBaseKernTrack - 1, i); + + // Ignore grace notes + if (baseCell->getToken()->getOwner()->getDuration() == 0) { + continue; + } + string keySignature = getKeySignature(infile, baseCell->getLineIndex()); // Hide numbers if they do not match rhythmic position of --recip From d7f1db719e27e997b85a8a70e98a2d2c73fb6f92 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Tue, 17 Jan 2023 21:04:14 +0100 Subject: [PATCH 102/109] Handle spine splits to get lowest pitch for base track --- include/humlib.h | 2 +- src/humlib.cpp | 25 ++++++++++++++++++++++++- src/tool-fb.cpp | 23 +++++++++++++++++++++++ 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/include/humlib.h b/include/humlib.h index 86e870bd..af6c3043 100644 --- a/include/humlib.h +++ b/include/humlib.h @@ -1,7 +1,7 @@ // // Programmer: Craig Stuart Sapp // Creation Date: Sat Aug 8 12:24:49 PDT 2015 -// Last Modified: Di 17 Jan 2023 00:38:37 CET +// Last Modified: Di 17 Jan 2023 21:03:33 CET // Filename: humlib.h // URL: https://github.com/craigsapp/humlib/blob/master/include/humlib.h // Syntax: C++11 diff --git a/src/humlib.cpp b/src/humlib.cpp index 502d58ff..6ca650fb 100644 --- a/src/humlib.cpp +++ b/src/humlib.cpp @@ -1,7 +1,7 @@ // // Programmer: Craig Stuart Sapp // Creation Date: Sat Aug 8 12:24:49 PDT 2015 -// Last Modified: Di 17 Jan 2023 00:38:37 CET +// Last Modified: Di 17 Jan 2023 21:03:33 CET // Filename: /include/humlib.cpp // URL: https://github.com/craigsapp/humlib/blob/master/src/humlib.cpp // Syntax: C++11 @@ -77592,8 +77592,31 @@ void Tool_fb::processFile(HumdrumFile& infile) { } } + + HTp currentToken = baseCell->getToken(); + int initialTokenTrack = baseCell->getToken()->getTrack(); int lowestBaseNoteBase40Pitch = getLowestBase40Pitch(baseCell->getToken()->resolveNull()->getBase40Pitches()); + // Handle spine splits + do { + HTp resolvedToken = currentToken->resolveNull(); + + int lowest = getLowestBase40Pitch(resolvedToken->getBase40Pitches()); + + if(lowest < lowestBaseNoteBase40Pitch) { + lowestBaseNoteBase40Pitch = lowest; + } + + HTp nextToken = currentToken->getNextField(); + if (nextToken && (initialTokenTrack == nextToken->getTrack())) { + cerr << nextToken->getText(); + currentToken = nextToken; + } else { + // Break loop if nextToken is not the same track as initialTokenTrack + break; + } + } while (currentToken); + // Ignore if base is a rest or silent note if (lowestBaseNoteBase40Pitch == 0 || lowestBaseNoteBase40Pitch == -1000 || lowestBaseNoteBase40Pitch == -2000) { continue; diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 053316cf..75ce4e87 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -230,8 +230,31 @@ void Tool_fb::processFile(HumdrumFile& infile) { } } + + HTp currentToken = baseCell->getToken(); + int initialTokenTrack = baseCell->getToken()->getTrack(); int lowestBaseNoteBase40Pitch = getLowestBase40Pitch(baseCell->getToken()->resolveNull()->getBase40Pitches()); + // Handle spine splits + do { + HTp resolvedToken = currentToken->resolveNull(); + + int lowest = getLowestBase40Pitch(resolvedToken->getBase40Pitches()); + + if(lowest < lowestBaseNoteBase40Pitch) { + lowestBaseNoteBase40Pitch = lowest; + } + + HTp nextToken = currentToken->getNextField(); + if (nextToken && (initialTokenTrack == nextToken->getTrack())) { + cerr << nextToken->getText(); + currentToken = nextToken; + } else { + // Break loop if nextToken is not the same track as initialTokenTrack + break; + } + } while (currentToken); + // Ignore if base is a rest or silent note if (lowestBaseNoteBase40Pitch == 0 || lowestBaseNoteBase40Pitch == -1000 || lowestBaseNoteBase40Pitch == -2000) { continue; From e71c45bdb186a41ed497f01569f13a1fd7f7d8b5 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Tue, 17 Jan 2023 21:09:38 +0100 Subject: [PATCH 103/109] Remove cerr Closes https://github.com/craigsapp/humlib/issues/57 in d7f1db7 --- include/humlib.h | 2 +- src/humlib.cpp | 5 ++--- src/tool-fb.cpp | 3 +-- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/include/humlib.h b/include/humlib.h index 10f0ce75..18c5332c 100644 --- a/include/humlib.h +++ b/include/humlib.h @@ -1,7 +1,7 @@ // // Programmer: Craig Stuart Sapp // Creation Date: Sat Aug 8 12:24:49 PDT 2015 -// Last Modified: Di 17 Jan 2023 21:06:51 CET +// Last Modified: Di 17 Jan 2023 21:09:28 CET // Filename: humlib.h // URL: https://github.com/craigsapp/humlib/blob/master/include/humlib.h // Syntax: C++11 diff --git a/src/humlib.cpp b/src/humlib.cpp index 3f75d829..e686cdb0 100644 --- a/src/humlib.cpp +++ b/src/humlib.cpp @@ -1,7 +1,7 @@ // // Programmer: Craig Stuart Sapp // Creation Date: Sat Aug 8 12:24:49 PDT 2015 -// Last Modified: Di 17 Jan 2023 21:06:51 CET +// Last Modified: Di 17 Jan 2023 21:09:28 CET // Filename: /include/humlib.cpp // URL: https://github.com/craigsapp/humlib/blob/master/src/humlib.cpp // Syntax: C++11 @@ -78045,8 +78045,7 @@ void Tool_fb::processFile(HumdrumFile& infile) { HTp nextToken = currentToken->getNextField(); if (nextToken && (initialTokenTrack == nextToken->getTrack())) { - cerr << nextToken->getText(); - currentToken = nextToken; + currentToken = nextToken; } else { // Break loop if nextToken is not the same track as initialTokenTrack break; diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 75ce4e87..4df9aa20 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -247,8 +247,7 @@ void Tool_fb::processFile(HumdrumFile& infile) { HTp nextToken = currentToken->getNextField(); if (nextToken && (initialTokenTrack == nextToken->getTrack())) { - cerr << nextToken->getText(); - currentToken = nextToken; + currentToken = nextToken; } else { // Break loop if nextToken is not the same track as initialTokenTrack break; From 8fa386b9faf9a5d13a3dc3e55d48bcf6daab58a9 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Tue, 17 Jan 2023 21:53:14 +0100 Subject: [PATCH 104/109] Add braces --- src/tool-fb.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 4df9aa20..10f771ab 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -201,7 +201,7 @@ void Tool_fb::processFile(HumdrumFile& infile) { // TODO: Handle spine splits int checkCellPitch = getLowestBase40Pitch(checkCell->getToken()->resolveNull()->getBase40Pitches()); // Ignore if base is a rest or silent note - if (checkCellPitch != 0 && checkCellPitch != -1000 && checkCellPitch != -2000) { + if ((checkCellPitch != 0) && (checkCellPitch != -1000) && (checkCellPitch != -2000)) { if (abs(checkCellPitch) < lowestNotePitch) { lowestNotePitch = abs(checkCellPitch); usedBaseKernTrack = k + 1; @@ -255,7 +255,7 @@ void Tool_fb::processFile(HumdrumFile& infile) { } while (currentToken); // Ignore if base is a rest or silent note - if (lowestBaseNoteBase40Pitch == 0 || lowestBaseNoteBase40Pitch == -1000 || lowestBaseNoteBase40Pitch == -2000) { + if ((lowestBaseNoteBase40Pitch == 0) || (lowestBaseNoteBase40Pitch == -1000) || (lowestBaseNoteBase40Pitch == -2000)) { continue; } @@ -279,7 +279,7 @@ void Tool_fb::processFile(HumdrumFile& infile) { for (int subtokenBase40: resolvedToken->getBase40Pitches()) { // Ignore if target is a rest or silent note - if (subtokenBase40 == 0 || subtokenBase40 == -1000 || subtokenBase40 == -2000) { + if ((subtokenBase40 == 0) || (subtokenBase40 == -1000) || (subtokenBase40 == -2000)) { continue; } From f79f52ce2ed2d2ae719529b4444dfc42beabefe7 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Tue, 17 Jan 2023 21:54:22 +0100 Subject: [PATCH 105/109] Fix spine split when there is a rest in primary token See https://github.com/craigsapp/humlib/issues/57 --- src/tool-fb.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 10f771ab..4a1acba7 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -233,7 +233,7 @@ void Tool_fb::processFile(HumdrumFile& infile) { HTp currentToken = baseCell->getToken(); int initialTokenTrack = baseCell->getToken()->getTrack(); - int lowestBaseNoteBase40Pitch = getLowestBase40Pitch(baseCell->getToken()->resolveNull()->getBase40Pitches()); + int lowestBaseNoteBase40Pitch = 9999; // Handle spine splits do { @@ -241,8 +241,11 @@ void Tool_fb::processFile(HumdrumFile& infile) { int lowest = getLowestBase40Pitch(resolvedToken->getBase40Pitches()); - if(lowest < lowestBaseNoteBase40Pitch) { - lowestBaseNoteBase40Pitch = lowest; + // Ignore if base is a rest or silent note + if ((lowest != 0) && (lowest != -1000) && (lowest != -2000)) { + if(abs(lowest) < lowestBaseNoteBase40Pitch) { + lowestBaseNoteBase40Pitch = abs(lowest); + } } HTp nextToken = currentToken->getNextField(); @@ -255,7 +258,7 @@ void Tool_fb::processFile(HumdrumFile& infile) { } while (currentToken); // Ignore if base is a rest or silent note - if ((lowestBaseNoteBase40Pitch == 0) || (lowestBaseNoteBase40Pitch == -1000) || (lowestBaseNoteBase40Pitch == -2000)) { + if ((lowestBaseNoteBase40Pitch == 0) || (lowestBaseNoteBase40Pitch == -1000) || (lowestBaseNoteBase40Pitch == -2000) || (lowestBaseNoteBase40Pitch == 9999)) { continue; } From bc7d0d71aba6e2f8d31ffaf627a4df9b5f25d106 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Tue, 17 Jan 2023 22:03:39 +0100 Subject: [PATCH 106/109] Handle spine splits with --lowest flag --- src/tool-fb.cpp | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 4a1acba7..6596dcb3 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -198,15 +198,28 @@ void Tool_fb::processFile(HumdrumFile& infile) { int lowestNotePitch = 99999; for (int k=0; k<(int)grid.getVoiceCount(); k++) { NoteCell* checkCell = grid.cell(k, i); - // TODO: Handle spine splits - int checkCellPitch = getLowestBase40Pitch(checkCell->getToken()->resolveNull()->getBase40Pitches()); - // Ignore if base is a rest or silent note - if ((checkCellPitch != 0) && (checkCellPitch != -1000) && (checkCellPitch != -2000)) { - if (abs(checkCellPitch) < lowestNotePitch) { - lowestNotePitch = abs(checkCellPitch); + HTp currentToken = checkCell->getToken(); + int initialTokenTrack = currentToken->getTrack(); + + // Handle spine splits + do { + HTp resolvedToken = currentToken->resolveNull(); + + int lowest = getLowestBase40Pitch(resolvedToken->getBase40Pitches()); + + if (abs(lowest) < lowestNotePitch) { + lowestNotePitch = abs(lowest); usedBaseKernTrack = k + 1; } - } + + HTp nextToken = currentToken->getNextField(); + if (nextToken && (initialTokenTrack == nextToken->getTrack())) { + currentToken = nextToken; + } else { + // Break loop if nextToken is not the same track as initialTokenTrack + break; + } + } while (currentToken); } } From 5b4442945da960d9cec85c268c6381110b7a4588 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Tue, 17 Jan 2023 22:04:08 +0100 Subject: [PATCH 107/109] Update humlib.h and humlib.cpp --- include/humlib.h | 2 +- src/humlib.cpp | 42 +++++++++++++++++++++++++++++------------- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/include/humlib.h b/include/humlib.h index 18c5332c..aa2cf9ef 100644 --- a/include/humlib.h +++ b/include/humlib.h @@ -1,7 +1,7 @@ // // Programmer: Craig Stuart Sapp // Creation Date: Sat Aug 8 12:24:49 PDT 2015 -// Last Modified: Di 17 Jan 2023 21:09:28 CET +// Last Modified: Di 17 Jan 2023 22:03:55 CET // Filename: humlib.h // URL: https://github.com/craigsapp/humlib/blob/master/include/humlib.h // Syntax: C++11 diff --git a/src/humlib.cpp b/src/humlib.cpp index e686cdb0..1def32aa 100644 --- a/src/humlib.cpp +++ b/src/humlib.cpp @@ -1,7 +1,7 @@ // // Programmer: Craig Stuart Sapp // Creation Date: Sat Aug 8 12:24:49 PDT 2015 -// Last Modified: Di 17 Jan 2023 21:09:28 CET +// Last Modified: Di 17 Jan 2023 22:03:55 CET // Filename: /include/humlib.cpp // URL: https://github.com/craigsapp/humlib/blob/master/src/humlib.cpp // Syntax: C++11 @@ -77996,15 +77996,28 @@ void Tool_fb::processFile(HumdrumFile& infile) { int lowestNotePitch = 99999; for (int k=0; k<(int)grid.getVoiceCount(); k++) { NoteCell* checkCell = grid.cell(k, i); - // TODO: Handle spine splits - int checkCellPitch = getLowestBase40Pitch(checkCell->getToken()->resolveNull()->getBase40Pitches()); - // Ignore if base is a rest or silent note - if (checkCellPitch != 0 && checkCellPitch != -1000 && checkCellPitch != -2000) { - if (abs(checkCellPitch) < lowestNotePitch) { - lowestNotePitch = abs(checkCellPitch); + HTp currentToken = checkCell->getToken(); + int initialTokenTrack = currentToken->getTrack(); + + // Handle spine splits + do { + HTp resolvedToken = currentToken->resolveNull(); + + int lowest = getLowestBase40Pitch(resolvedToken->getBase40Pitches()); + + if (abs(lowest) < lowestNotePitch) { + lowestNotePitch = abs(lowest); usedBaseKernTrack = k + 1; } - } + + HTp nextToken = currentToken->getNextField(); + if (nextToken && (initialTokenTrack == nextToken->getTrack())) { + currentToken = nextToken; + } else { + // Break loop if nextToken is not the same track as initialTokenTrack + break; + } + } while (currentToken); } } @@ -78031,7 +78044,7 @@ void Tool_fb::processFile(HumdrumFile& infile) { HTp currentToken = baseCell->getToken(); int initialTokenTrack = baseCell->getToken()->getTrack(); - int lowestBaseNoteBase40Pitch = getLowestBase40Pitch(baseCell->getToken()->resolveNull()->getBase40Pitches()); + int lowestBaseNoteBase40Pitch = 9999; // Handle spine splits do { @@ -78039,8 +78052,11 @@ void Tool_fb::processFile(HumdrumFile& infile) { int lowest = getLowestBase40Pitch(resolvedToken->getBase40Pitches()); - if(lowest < lowestBaseNoteBase40Pitch) { - lowestBaseNoteBase40Pitch = lowest; + // Ignore if base is a rest or silent note + if ((lowest != 0) && (lowest != -1000) && (lowest != -2000)) { + if(abs(lowest) < lowestBaseNoteBase40Pitch) { + lowestBaseNoteBase40Pitch = abs(lowest); + } } HTp nextToken = currentToken->getNextField(); @@ -78053,7 +78069,7 @@ void Tool_fb::processFile(HumdrumFile& infile) { } while (currentToken); // Ignore if base is a rest or silent note - if (lowestBaseNoteBase40Pitch == 0 || lowestBaseNoteBase40Pitch == -1000 || lowestBaseNoteBase40Pitch == -2000) { + if ((lowestBaseNoteBase40Pitch == 0) || (lowestBaseNoteBase40Pitch == -1000) || (lowestBaseNoteBase40Pitch == -2000) || (lowestBaseNoteBase40Pitch == 9999)) { continue; } @@ -78077,7 +78093,7 @@ void Tool_fb::processFile(HumdrumFile& infile) { for (int subtokenBase40: resolvedToken->getBase40Pitches()) { // Ignore if target is a rest or silent note - if (subtokenBase40 == 0 || subtokenBase40 == -1000 || subtokenBase40 == -2000) { + if ((subtokenBase40 == 0) || (subtokenBase40 == -1000) || (subtokenBase40 == -2000)) { continue; } From eff50569355264d4b29947fbe9693ba1fcdec4ca Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Sat, 21 Jan 2023 09:34:59 +0100 Subject: [PATCH 108/109] Rename m_processTrack with m_selectedKernSpines --- include/tool-fb.h | 2 +- src/tool-fb.cpp | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/tool-fb.h b/include/tool-fb.h index cc24bb7f..ac10913f 100644 --- a/include/tool-fb.h +++ b/include/tool-fb.h @@ -101,7 +101,7 @@ class Tool_fb : public HumTool { string m_spineTracks = ""; // used with -s option string m_kernTracks = ""; // used with -k option - vector m_processTrack; // used with -k and -s option + vector m_selectedKernSpines; // used with -k and -s option }; diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index 6596dcb3..b3e8a40e 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -159,25 +159,25 @@ void Tool_fb::processFile(HumdrumFile& infile) { return; } - m_processTrack.resize(maxTrack + 1); // +1 is needed since track=0 is not used + m_selectedKernSpines.resize(maxTrack + 1); // +1 is needed since track=0 is not used // By default, process all tracks: - fill(m_processTrack.begin(), m_processTrack.end(), true); + fill(m_selectedKernSpines.begin(), m_selectedKernSpines.end(), true); // Otherwise, select which **kern track, or spine tracks to process selectively: // Calculate which input spines to process based on -s or -k option: if (!m_kernTracks.empty()) { vector ktracks = Convert::extractIntegerList(m_kernTracks, maxTrack); - fill(m_processTrack.begin(), m_processTrack.end(), false); + fill(m_selectedKernSpines.begin(), m_selectedKernSpines.end(), false); for (int i=0; i<(int)ktracks.size(); i++) { int index = ktracks[i] - 1; if ((index < 0) || (index >= (int)kernspines.size())) { continue; } int track = kernspines.at(ktracks[i] - 1)->getTrack(); - m_processTrack.at(track) = true; + m_selectedKernSpines.at(track) = true; } } else if (!m_spineTracks.empty()) { - infile.makeBooleanTrackList(m_processTrack, m_spineTracks); + infile.makeBooleanTrackList(m_selectedKernSpines, m_spineTracks); } vector> lastNumbers = {}; @@ -280,7 +280,7 @@ void Tool_fb::processFile(HumdrumFile& infile) { NoteCell* targetCell = grid.cell(j, i); // Ignore voice if track is not active by --kern-tracks or --spine-tracks - if (m_processTrack.at(targetCell->getToken()->getTrack()) == false) { + if (m_selectedKernSpines.at(targetCell->getToken()->getTrack()) == false) { continue; } From 8e1c055e9a33ee040a4b1fb5c40aa525d70bb6d7 Mon Sep 17 00:00:00 2001 From: Wolfgang Drescher Date: Sat, 21 Jan 2023 09:35:32 +0100 Subject: [PATCH 109/109] Add infile content to m_humdrum_text --- src/tool-fb.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tool-fb.cpp b/src/tool-fb.cpp index b3e8a40e..3a96e5c5 100644 --- a/src/tool-fb.cpp +++ b/src/tool-fb.cpp @@ -363,6 +363,9 @@ void Tool_fb::processFile(HumdrumFile& infile) { infile.appendDataSpine(trackData, ".", exinterp); } } + + // Enables usage in verovio (`!!!filter: fb`) + m_humdrum_text << infile; }