diff --git a/include/humlib.h b/include/humlib.h index aa2cf9ef..e87ba87f 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 22:03:55 CET +// Last Modified: Sa 21 Jan 2023 09:48:51 CET // Filename: humlib.h // URL: https://github.com/craigsapp/humlib/blob/master/include/humlib.h // Syntax: C++11 @@ -6613,8 +6613,10 @@ class Tool_deg : public HumTool { int getSubtokenCount (void) const; // output options: - static void setShowTies (bool state) { m_showTiesQ = state; } - static void setShowZeros (bool state) { m_showZerosQ = state; } + static void setShowTies (bool state) { m_showTiesQ = state; } + static void setShowZeros (bool state) { m_showZerosQ = state; } + static void setShowOctaves (bool state) { m_octaveQ = state; } + static void setForcedKey (const string& key) { m_forcedKey = key; } protected: // ScaleDegree class std::string generateDegDataToken (void) const; @@ -6694,6 +6696,8 @@ class Tool_deg : public HumTool { // ScaleDegree rendering options: static bool m_showTiesQ; static bool m_showZerosQ; + static bool m_octaveQ; + static std::string m_forcedKey; }; @@ -6729,16 +6733,20 @@ class Tool_deg : public HumTool { bool isDegAboveLine (HumdrumFile& infile, int lineIndex); bool isDegArrowLine (HumdrumFile& infile, int lineIndex); + bool isDegBoxLine (HumdrumFile& infile, int lineIndex); bool isDegCircleLine (HumdrumFile& infile, int lineIndex); bool isDegColorLine (HumdrumFile& infile, int lineIndex); bool isDegHatLine (HumdrumFile& infile, int lineIndex); + bool isDegSolfegeLine (HumdrumFile& infile, int lineIndex); bool isKeyDesignationLine (HumdrumFile& infile, int lineIndex); void checkAboveStatus (string& value, bool arrowStatus); void checkArrowStatus (string& value, bool arrowStatus); + void checkBoxStatus (string& value, bool arrowStatus); void checkCircleStatus (string& value, bool arrowStatus); void checkColorStatus (string& value, bool arrowStatus); void checkHatStatus (string& value, bool arrowStatus); + void checkSolfegeStatus (string& value, bool arrowStatus); void checkKeyDesignationStatus(string& value, int keyDesignationStatus); @@ -6775,10 +6783,12 @@ class Tool_deg : public HumTool { bool m_aboveQ = false; // used with --above option bool m_arrowQ = false; // used with --arrow option + bool m_boxQ = false; // used with --box option bool m_circleQ = false; // used with --circle option bool m_hatQ = false; // used with --hat option bool m_colorQ = false; // used with --color option std::string m_color; // used with --color option + bool m_solfegeQ = false; // used with --solfege option bool m_degOnlyQ = false; // used with -I option bool m_recipQ = false; // used with -r option @@ -6800,10 +6810,12 @@ class Tool_deg : public HumTool { bool hasDegSpines; bool foundAboveLine; bool foundArrowLine; + bool foundBoxLine; bool foundCircleLine; bool foundColorLine; bool foundHatLine; bool foundKeyDesignationLine; + bool foundSolfegeLine; InterleavedPrintVariables(void) { clear(); } void clear(void) { @@ -6811,10 +6823,12 @@ class Tool_deg : public HumTool { hasDegSpines = true; foundAboveLine = false; foundArrowLine = false; + foundBoxLine = false; foundCircleLine = false; foundColorLine = false; foundHatLine = false; foundKeyDesignationLine = false; + foundSolfegeLine = false; } }; InterleavedPrintVariables m_ipv; @@ -7298,7 +7312,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/include/tool-deg.h b/include/tool-deg.h index cc8c9edd..e3d92f49 100644 --- a/include/tool-deg.h +++ b/include/tool-deg.h @@ -65,8 +65,10 @@ class Tool_deg : public HumTool { int getSubtokenCount (void) const; // output options: - static void setShowTies (bool state) { m_showTiesQ = state; } - static void setShowZeros (bool state) { m_showZerosQ = state; } + static void setShowTies (bool state) { m_showTiesQ = state; } + static void setShowZeros (bool state) { m_showZerosQ = state; } + static void setShowOctaves (bool state) { m_octaveQ = state; } + static void setForcedKey (const string& key) { m_forcedKey = key; } protected: // ScaleDegree class std::string generateDegDataToken (void) const; @@ -146,6 +148,8 @@ class Tool_deg : public HumTool { // ScaleDegree rendering options: static bool m_showTiesQ; static bool m_showZerosQ; + static bool m_octaveQ; + static std::string m_forcedKey; }; @@ -181,16 +185,20 @@ class Tool_deg : public HumTool { bool isDegAboveLine (HumdrumFile& infile, int lineIndex); bool isDegArrowLine (HumdrumFile& infile, int lineIndex); + bool isDegBoxLine (HumdrumFile& infile, int lineIndex); bool isDegCircleLine (HumdrumFile& infile, int lineIndex); bool isDegColorLine (HumdrumFile& infile, int lineIndex); bool isDegHatLine (HumdrumFile& infile, int lineIndex); + bool isDegSolfegeLine (HumdrumFile& infile, int lineIndex); bool isKeyDesignationLine (HumdrumFile& infile, int lineIndex); void checkAboveStatus (string& value, bool arrowStatus); void checkArrowStatus (string& value, bool arrowStatus); + void checkBoxStatus (string& value, bool arrowStatus); void checkCircleStatus (string& value, bool arrowStatus); void checkColorStatus (string& value, bool arrowStatus); void checkHatStatus (string& value, bool arrowStatus); + void checkSolfegeStatus (string& value, bool arrowStatus); void checkKeyDesignationStatus(string& value, int keyDesignationStatus); @@ -227,10 +235,12 @@ class Tool_deg : public HumTool { bool m_aboveQ = false; // used with --above option bool m_arrowQ = false; // used with --arrow option + bool m_boxQ = false; // used with --box option bool m_circleQ = false; // used with --circle option bool m_hatQ = false; // used with --hat option bool m_colorQ = false; // used with --color option std::string m_color; // used with --color option + bool m_solfegeQ = false; // used with --solfege option bool m_degOnlyQ = false; // used with -I option bool m_recipQ = false; // used with -r option @@ -252,10 +262,12 @@ class Tool_deg : public HumTool { bool hasDegSpines; bool foundAboveLine; bool foundArrowLine; + bool foundBoxLine; bool foundCircleLine; bool foundColorLine; bool foundHatLine; bool foundKeyDesignationLine; + bool foundSolfegeLine; InterleavedPrintVariables(void) { clear(); } void clear(void) { @@ -263,10 +275,12 @@ class Tool_deg : public HumTool { hasDegSpines = true; foundAboveLine = false; foundArrowLine = false; + foundBoxLine = false; foundCircleLine = false; foundColorLine = false; foundHatLine = false; foundKeyDesignationLine = false; + foundSolfegeLine = false; } }; InterleavedPrintVariables m_ipv; diff --git a/src/humlib.cpp b/src/humlib.cpp index 1def32aa..1972b55c 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 22:03:55 CET +// Last Modified: Sa 21 Jan 2023 09:48:51 CET // Filename: /include/humlib.cpp // URL: https://github.com/craigsapp/humlib/blob/master/src/humlib.cpp // Syntax: C++11 @@ -68920,6 +68920,8 @@ void Tool_compositeold::addVerseLabels2(HumdrumFile& infile, HTp spinestart) { bool Tool_deg::ScaleDegree::m_showTiesQ = false; bool Tool_deg::ScaleDegree::m_showZerosQ = false; +bool Tool_deg::ScaleDegree::m_octaveQ = false; +string Tool_deg::ScaleDegree::m_forcedKey = ""; @@ -68931,19 +68933,21 @@ bool Tool_deg::ScaleDegree::m_showZerosQ = false; Tool_deg::Tool_deg(void) { define("above=b", "Display scale degrees above analyzed staff"); define("arr|arrow|arrows=b", "Display scale degree alterations as arrows"); - define("b|boxes|box=b", "Display scale degrees in boxes"); - define("color=s", "Display color for scale degrees"); - define("c|circ|circles|circle=b", "Display scale degrees in circles"); - define("hat|caret|circumflex=b", "Display hats on scale degrees"); + define("b|boxes|box=b", "Display scale degrees in boxes"); + define("color=s", "Display color for scale degrees"); + define("c|circ|circles|circle=b", "Display scale degrees in circles"); + define("hat|caret|circumflex=b", "Display hats on scale degrees"); + define("solf|solfege=b", "Display (relative) solfege syllables instead of scale degree numbers"); define("I|no-input=b", "Do not interleave **deg data with input score in output"); define("kern=b", "Prefix composite rhythm **kern spine with -I option"); define("k|kern-tracks=s", "Process only the specified kern spines"); - define("kd|dk|key-default|default-key=s", "Default key if none specified in data"); - define("kf|fk|key-force|force-key=s", "Use the given key for analysing deg data (ignore modulations)"); + define("kd|dk|key-default|default-key=s", "Default (initial) key if none specified in data"); + define("kf|fk|key-force|force-key|forced-key|key-forced=s", "Use the given key for analysing deg data (ignore modulations)"); + define("o|octave|octaves|degree=b", "Encode octave information int **degree spines"); define("r|recip=b", "Prefix output data with **recip spine with -I option"); define("t|ties=b", "Include scale degrees for tied notes"); define("s|spine-tracks|spine|spines|track|tracks=s", "Process only the specified spines"); - define("0|z|zero|zeros=b", "Show rests as scale degree 0"); + define("0|O|z|zero|zeros=b", "Show rests as scale degree 0"); } @@ -69002,9 +69006,11 @@ bool Tool_deg::run(HumdrumFile& infile) { void Tool_deg::initialize(void) { m_aboveQ = getBoolean("above"); m_arrowQ = getBoolean("arrow"); + m_boxQ = getBoolean("box"); m_circleQ = getBoolean("circle"); m_colorQ = getBoolean("color"); m_hatQ = getBoolean("hat"); + m_solfegeQ = getBoolean("solfege"); if (m_colorQ) { m_color = getString("color"); @@ -69017,6 +69023,7 @@ void Tool_deg::initialize(void) { m_recipQ = true; } m_degTiesQ = getBoolean("ties"); + Tool_deg::ScaleDegree::setShowOctaves(getBoolean("octave")); if (getBoolean("spine-tracks")) { m_spineTracks = getString("spine-tracks"); @@ -69026,6 +69033,29 @@ void Tool_deg::initialize(void) { if (getBoolean("default-key")) { m_defaultKey = getString("default-key"); + if (!m_defaultKey.empty()) { + if (m_defaultKey[0] != '*') { + m_defaultKey = "*" + m_defaultKey; + } + if (m_defaultKey.find(":") == string::npos) { + m_defaultKey += ":"; + } + } + } + + if (getBoolean("forced-key")) { + m_defaultKey.clear(); // override --default-key option + + m_forcedKey = getString("forced-key"); + if (!m_forcedKey.empty()) { + if (m_forcedKey[0] != '*') { + m_forcedKey = "*" + m_forcedKey; + } + if (m_forcedKey.find(":") == string::npos) { + m_forcedKey += ":"; + } + Tool_deg::ScaleDegree::setForcedKey(m_forcedKey); + } } Tool_deg::ScaleDegree::setShowTies(m_degTiesQ); @@ -69186,10 +69216,12 @@ string Tool_deg::createOutputHumdrumLine(HumdrumFile& infile, int lineIndex) { // Styling interpretation tracking variables: bool aboveStatus = false; bool arrowStatus = false; + bool boxStatus = false; bool circleStatus = false; bool colorStatus = false; bool hatStatus = false; bool keyDesignationStatus = false; + bool solfegeStatus = false; // Keep track of an existing styling line and if such a line is found, // then insert a styling interpretation for the new **deg spines here @@ -69198,12 +69230,18 @@ string Tool_deg::createOutputHumdrumLine(HumdrumFile& infile, int lineIndex) { if (!m_defaultKey.empty() && !keyDesignationStatus && !m_ipv.foundKeyDesignationLine) { keyDesignationStatus = isKeyDesignationLine(infile, lineIndex); } + if (!m_forcedKey.empty() && !keyDesignationStatus && !m_ipv.foundKeyDesignationLine) { + keyDesignationStatus = isKeyDesignationLine(infile, lineIndex); + } if (m_aboveQ && !m_ipv.foundAboveLine) { aboveStatus = isDegAboveLine(infile, lineIndex); } if (m_arrowQ && !m_ipv.foundArrowLine) { arrowStatus = isDegArrowLine(infile, lineIndex); } + if (m_boxQ && !m_ipv.foundBoxLine) { + boxStatus = isDegBoxLine(infile, lineIndex); + } if (m_circleQ && !m_ipv.foundCircleLine) { circleStatus = isDegCircleLine(infile, lineIndex); } @@ -69213,6 +69251,9 @@ string Tool_deg::createOutputHumdrumLine(HumdrumFile& infile, int lineIndex) { if (m_hatQ && !m_ipv.foundHatLine) { hatStatus = isDegHatLine(infile, lineIndex); } + if (m_solfegeQ && !m_ipv.foundSolfegeLine) { + solfegeStatus = isDegSolfegeLine(infile, lineIndex); + } } // spineData: The output Humdrum data line stored in a 2D vector. @@ -69248,9 +69289,11 @@ string Tool_deg::createOutputHumdrumLine(HumdrumFile& infile, int lineIndex) { checkKeyDesignationStatus(value, keyDesignationStatus); checkAboveStatus(value, aboveStatus); checkArrowStatus(value, arrowStatus); + checkBoxStatus(value, boxStatus); checkCircleStatus(value, circleStatus); checkColorStatus(value, colorStatus); checkHatStatus(value, hatStatus); + checkSolfegeStatus(value, hatStatus); spineData.back().push_back(value); if (value == "*v") { hasDegMerger = true; @@ -69274,9 +69317,11 @@ string Tool_deg::createOutputHumdrumLine(HumdrumFile& infile, int lineIndex) { checkKeyDesignationStatus(value, keyDesignationStatus); checkAboveStatus(value, aboveStatus); checkArrowStatus(value, arrowStatus); + checkBoxStatus(value, boxStatus); checkCircleStatus(value, circleStatus); checkColorStatus(value, colorStatus); checkHatStatus(value, hatStatus); + checkSolfegeStatus(value, hatStatus); spineData.back().push_back(value); if (value == "*v") { hasDegMerger = true; @@ -69297,6 +69342,9 @@ string Tool_deg::createOutputHumdrumLine(HumdrumFile& infile, int lineIndex) { if (arrowStatus) { m_ipv.foundArrowLine = true; } + if (boxStatus) { + m_ipv.foundBoxLine = true; + } if (circleStatus) { m_ipv.foundCircleLine = true; } @@ -69306,6 +69354,9 @@ string Tool_deg::createOutputHumdrumLine(HumdrumFile& infile, int lineIndex) { if (hatStatus) { m_ipv.foundHatLine = true; } + if (solfegeStatus) { + m_ipv.foundSolfegeLine = true; + } // if styling interpretation lines were not found before the data, @@ -69336,6 +69387,15 @@ string Tool_deg::createOutputHumdrumLine(HumdrumFile& infile, int lineIndex) { } } + if (!m_ipv.foundBoxLine) { + if (m_boxQ && !m_ipv.foundBoxLine) { + string line = printDegInterpretation("*box", infile, lineIndex); + if (!line.empty()) { + extraLines.push_back(line); + } + } + } + if (!m_ipv.foundCircleLine) { if (m_circleQ && !m_ipv.foundCircleLine) { string line = printDegInterpretation("*circ", infile, lineIndex); @@ -69363,9 +69423,27 @@ string Tool_deg::createOutputHumdrumLine(HumdrumFile& infile, int lineIndex) { } } + if (!m_ipv.foundSolfegeLine) { + if (m_solfegeQ && !m_ipv.foundSolfegeLine) { + string line = printDegInterpretation("*solf", infile, lineIndex); + if (!line.empty()) { + extraLines.push_back(line); + } + } + } + if (!m_ipv.foundKeyDesignationLine) { if (!m_defaultKey.empty() && !m_ipv.foundKeyDesignationLine) { - string line = printDegInterpretation("*XXX", infile, lineIndex); + string line = printDegInterpretation(m_defaultKey, infile, lineIndex); + if (!line.empty()) { + extraLines.push_back(line); + } + } + } + + if (!m_ipv.foundKeyDesignationLine) { + if (!m_forcedKey.empty() && !m_ipv.foundKeyDesignationLine) { + string line = printDegInterpretation(m_forcedKey, infile, lineIndex); if (!line.empty()) { extraLines.push_back(line); } @@ -69417,15 +69495,9 @@ void Tool_deg::checkKeyDesignationStatus(string& value, int keyDesignationStatus if (keyDesignationStatus && (!m_ipv.foundKeyDesignationLine) && (!m_ipv.foundData)) { if (value == "*") { if (!m_defaultKey.empty()) { - if (m_defaultKey[0] == '*') { - value = m_defaultKey; - } else { - value = "*"; - value += m_defaultKey; - } - if (value.find(":") == string::npos) { - value += ":"; - } + value = m_defaultKey; + } else if (!m_forcedKey.empty()) { + value = m_forcedKey; } } } @@ -69435,7 +69507,7 @@ void Tool_deg::checkKeyDesignationStatus(string& value, int keyDesignationStatus ////////////////////////////// // -// Tool_deg::checkAboveStatus -- Add *arr interpretation to spine if needed. +// Tool_deg::checkAboveStatus -- Add *above interpretation to spine if needed. // void Tool_deg::checkAboveStatus(string& value, bool aboveStatus) { @@ -69463,6 +69535,21 @@ void Tool_deg::checkArrowStatus(string& value, bool arrowStatus) { +////////////////////////////// +// +// Tool_deg::checkBoxStatus -- Add *box interpretation to spine if needed. +// + +void Tool_deg::checkBoxStatus(string& value, bool boxStatus) { + if (boxStatus && m_boxQ && (!m_ipv.foundBoxLine) && (!m_ipv.foundData)) { + if (value == "*") { + value = "*box"; + } + } +} + + + ////////////////////////////// // // Tool_deg::checkCircleStatus -- Add *circ interpretation to spine if needed. @@ -69479,7 +69566,7 @@ void Tool_deg::checkCircleStatus(string& value, bool circleStatus) { ////////////////////////////// // -// Tool_deg::checkColorStatus -- Add *arr interpretation to spine if needed. +// Tool_deg::checkColorStatus -- Add *color interpretation to spine if needed. // void Tool_deg::checkColorStatus(string& value, bool colorStatus) { @@ -69507,6 +69594,21 @@ void Tool_deg::checkHatStatus(string& value, bool hatStatus) { +////////////////////////////// +// +// Tool_deg::checkSolfegeStatus -- Add *solfege interpretation to spine if needed. +// + +void Tool_deg::checkSolfegeStatus(string& value, bool hatStatus) { + if (hatStatus && m_solfegeQ && (!m_ipv.foundSolfegeLine) && (!m_ipv.foundData)) { + if (value == "*") { + value = "*solf"; + } + } +} + + + ////////////////////////////// // // Tool_deg::isKeyDesignationLine -- Returns true if any spine on the line @@ -69534,8 +69636,7 @@ bool Tool_deg::isKeyDesignationLine(HumdrumFile& infile, int lineIndex) { ////////////////////////////// // // Tool_deg::isDegAboveLine -- Return true if **deg spines only -// include *arr, *Xarr, *acc, *Xacc interpretations -// and "*" (but not all "*"). +// include *above, *below, interpretations and "*" (but not all "*"). // bool Tool_deg::isDegAboveLine(HumdrumFile& infile, int lineIndex) { @@ -69552,7 +69653,7 @@ bool Tool_deg::isDegAboveLine(HumdrumFile& infile, int lineIndex) { int degCount = 0; for (int i=0; iisDataType("**deg")) { + if (!(token->isDataType("**deg") || token->isDataType("**degree"))) { continue; } degCount++; @@ -69589,7 +69690,7 @@ bool Tool_deg::isDegArrowLine(HumdrumFile& infile, int lineIndex) { int degCount = 0; for (int i=0; iisDataType("**deg")) { + if (!(token->isDataType("**deg") || token->isDataType("**degree"))) { continue; } degCount++; @@ -69607,6 +69708,42 @@ bool Tool_deg::isDegArrowLine(HumdrumFile& infile, int lineIndex) { +////////////////////////////// +// +// Tool_deg::isDegBoxLine -- Return true if **deg spines includes +// any *box, or *Xbox, interpretations and "*" (but not all "*"). +// + +bool Tool_deg::isDegBoxLine(HumdrumFile& infile, int lineIndex) { + // If there are no **deg spines, then don't bother searching for them. + if (!m_ipv.hasDegSpines) { + return false; + } + if (!infile[lineIndex].isInterpretation()) { + return false; + } if (infile[lineIndex].isManipulator()) { + return false; + } + + int degCount = 0; + for (int i=0; iisDataType("**deg") || token->isDataType("**degree"))) { + continue; + } + degCount++; + if (*token == "*box") { return true; } + if (*token == "*Xbox") { return true; } + } + if (degCount == 0) { + m_ipv.hasDegSpines = false; + } + + return false; +} + + + ////////////////////////////// // // Tool_deg::isDegCircleLine -- Return true if **deg spines includes @@ -69627,7 +69764,7 @@ bool Tool_deg::isDegCircleLine(HumdrumFile& infile, int lineIndex) { int degCount = 0; for (int i=0; iisDataType("**deg")) { + if (!(token->isDataType("**deg") || token->isDataType("**degree"))) { continue; } degCount++; @@ -69646,8 +69783,7 @@ bool Tool_deg::isDegCircleLine(HumdrumFile& infile, int lineIndex) { ////////////////////////////// // // Tool_deg::isDegColorLine -- Return true if **deg spines only -// include *arr, *Xarr, *acc, *Xacc interpretations -// and "*" (but not all "*"). +// include *color interpretations and "*" (but not all "*"). // bool Tool_deg::isDegColorLine(HumdrumFile& infile, int lineIndex) { @@ -69664,7 +69800,7 @@ bool Tool_deg::isDegColorLine(HumdrumFile& infile, int lineIndex) { int degCount = 0; for (int i=0; iisDataType("**deg")) { + if (!(token->isDataType("**deg") || token->isDataType("**degree"))) { continue; } degCount++; @@ -69699,7 +69835,7 @@ bool Tool_deg::isDegHatLine(HumdrumFile& infile, int lineIndex) { int degCount = 0; for (int i=0; iisDataType("**deg")) { + if (!(token->isDataType("**deg") || token->isDataType("**degree"))) { continue; } degCount++; @@ -69715,6 +69851,42 @@ bool Tool_deg::isDegHatLine(HumdrumFile& infile, int lineIndex) { +////////////////////////////// +// +// Tool_deg::isDegSolfegeLine -- Return true if **deg spines includes +// any *solf, or *Xsolf, interpretations and "*" (but not all "*"). +// + +bool Tool_deg::isDegSolfegeLine(HumdrumFile& infile, int lineIndex) { + // If there are no **deg spines, then don't bother searching for them. + if (!m_ipv.hasDegSpines) { + return false; + } + if (!infile[lineIndex].isInterpretation()) { + return false; + } if (infile[lineIndex].isManipulator()) { + return false; + } + + int degCount = 0; + for (int i=0; iisDataType("**deg")) { + continue; + } + degCount++; + if (*token == "*solf") { return true; } + if (*token == "*Xsolf") { return true; } + } + if (degCount == 0) { + m_ipv.hasDegSpines = false; + } + + return false; +} + + + ////////////////////////////// // // Tool_deg::printDegInterpretation -- @@ -69872,7 +70044,7 @@ string Tool_deg::prepareMergerLine(vector>& merge) { ////////////////////////////// // -// Tool_deg::calculateManipulatorOutput -- Deal with *^ *v *- *+ manipulators +// Tool_deg::calculateManipulatorOutputForSpine -- Deal with *^ *v *- *+ manipulators // void Tool_deg::calculateManipulatorOutputForSpine(vector& lineout, @@ -69928,9 +70100,11 @@ void Tool_deg::printDegScore(HumdrumFile& infile) { // input styling options bool printAbove = !m_aboveQ; bool printArrow = !m_arrowQ; + bool printBox = !m_boxQ; bool printCircle = !m_circleQ; bool printColor = !m_colorQ; bool printHat = !m_hatQ; + bool printSolfege = !m_solfegeQ; int lineCount = (int)m_degSpines[0].size(); int spineCount = (int)m_degSpines.size(); @@ -69984,6 +70158,12 @@ void Tool_deg::printDegScore(HumdrumFile& infile) { printArrow = true; } + if (!printBox) { + string line = createDegInterpretation("*box", i, m_recipQ); + m_humdrum_text << line << endl; + printBox = true; + } + if (!printCircle) { string line = createDegInterpretation("*circ", i, m_recipQ); m_humdrum_text << line << endl; @@ -69999,11 +70179,17 @@ void Tool_deg::printDegScore(HumdrumFile& infile) { } if (!printHat) { - string line = createDegInterpretation("*arr", i, m_recipQ); + string line = createDegInterpretation("*hat", i, m_recipQ); m_humdrum_text << line << endl; printHat = true; } + if (!printSolfege) { + string line = createDegInterpretation("*solf", i, m_recipQ); + m_humdrum_text << line << endl; + printSolfege = true; + } + } for (int j=0; j>& degspine, HTp kernst if (!m_defaultKey.empty()) { getModeAndTonic(mode, b40tonic, m_defaultKey); + } else if (!m_forcedKey.empty()) { + getModeAndTonic(mode, b40tonic, m_forcedKey); } int lineCount = infile.getLineCount(); @@ -70245,8 +70433,12 @@ void Tool_deg::prepareDegSpine(vector>& degspine, HTp kernst // void Tool_deg::getModeAndTonic(string& mode, int& b40tonic, const string& token) { + string newtoken = token; + if (!m_forcedKey.empty()) { + newtoken = m_forcedKey; + } HumRegex hre; - if (hre.search(token, "^\\*?([A-Ga-g][-#]*):?(.*)$")) { + if (hre.search(newtoken, "^\\*?([A-Ga-g][-#]*):?(.*)$")) { string key = hre.getMatch(1); string kmode = hre.getMatch(2); b40tonic = Convert::kernToBase40(key); @@ -70521,7 +70713,7 @@ HTp Tool_deg::ScaleDegree::getLinkedKernToken(void) const { ////////////////////////////// // // Tool_deg::ScaleDegree:getDegToken -- Convert the ScaleDegre -// to a **deg token string. +// to a **deg token string (or **degree token if including an octave). // string Tool_deg::ScaleDegree::getDegToken(void) const { @@ -70535,12 +70727,20 @@ string Tool_deg::ScaleDegree::getDegToken(void) const { } if (isExclusiveInterpretation()) { - return "**deg"; + if (m_octaveQ) { + return "**degree"; + } else { + return "**deg"; + } } else if (isManipulator()) { return getManipulator(); } else if (isInterpretation()) { if (isKeyDesignation()) { - return *token; + if (m_forcedKey.empty()) { + return *token; + } else{ + return "*"; + } } else { return "*"; } @@ -70633,7 +70833,7 @@ string Tool_deg::ScaleDegree::generateDegDataToken(void) const { ////////////////////////////// // -// Tool_deg::ScaleDegree::createDegDataSubToken -- Convert the ScaleDegree +// Tool_deg::ScaleDegree::generateDegDataSubtoken -- Convert the ScaleDegree // subtoken (chord note) into **deg data. // @@ -70680,6 +70880,12 @@ string Tool_deg::ScaleDegree::generateDegDataSubtoken(int index) const { } } + // Add octave information if requested: + if (m_octaveQ && (degree != 0)) { + output += "/"; + output += to_string(m_octaves.at(index)); + } + return output; } @@ -77957,25 +78163,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 = {}; @@ -78078,7 +78284,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; } @@ -78161,6 +78367,9 @@ void Tool_fb::processFile(HumdrumFile& infile) { infile.appendDataSpine(trackData, ".", exinterp); } } + + // Enables usage in verovio (`!!!filter: fb`) + m_humdrum_text << infile; } diff --git a/src/tool-deg.cpp b/src/tool-deg.cpp index 524f1712..a6826b57 100644 --- a/src/tool-deg.cpp +++ b/src/tool-deg.cpp @@ -1,7 +1,7 @@ // // Programmer: Craig Stuart Sapp // Creation Date: Fri Jan 6 13:03:22 PST 2023 -// Last Modified: Sun Jan 15 20:24:59 PST 2023 +// Last Modified: Tue Jan 17 16:24:39 PST 2023 // Filename: tool-deg.cpp // URL: https://github.com/craigsapp/humlib/blob/master/src/tool-deg.cpp // Syntax: C++11; humlib @@ -28,6 +28,8 @@ namespace hum { bool Tool_deg::ScaleDegree::m_showTiesQ = false; bool Tool_deg::ScaleDegree::m_showZerosQ = false; +bool Tool_deg::ScaleDegree::m_octaveQ = false; +string Tool_deg::ScaleDegree::m_forcedKey = ""; @@ -39,19 +41,21 @@ bool Tool_deg::ScaleDegree::m_showZerosQ = false; Tool_deg::Tool_deg(void) { define("above=b", "Display scale degrees above analyzed staff"); define("arr|arrow|arrows=b", "Display scale degree alterations as arrows"); - define("b|boxes|box=b", "Display scale degrees in boxes"); - define("color=s", "Display color for scale degrees"); - define("c|circ|circles|circle=b", "Display scale degrees in circles"); - define("hat|caret|circumflex=b", "Display hats on scale degrees"); + define("b|boxes|box=b", "Display scale degrees in boxes"); + define("color=s", "Display color for scale degrees"); + define("c|circ|circles|circle=b", "Display scale degrees in circles"); + define("hat|caret|circumflex=b", "Display hats on scale degrees"); + define("solf|solfege=b", "Display (relative) solfege syllables instead of scale degree numbers"); define("I|no-input=b", "Do not interleave **deg data with input score in output"); define("kern=b", "Prefix composite rhythm **kern spine with -I option"); define("k|kern-tracks=s", "Process only the specified kern spines"); - define("kd|dk|key-default|default-key=s", "Default key if none specified in data"); - define("kf|fk|key-force|force-key=s", "Use the given key for analysing deg data (ignore modulations)"); + define("kd|dk|key-default|default-key=s", "Default (initial) key if none specified in data"); + define("kf|fk|key-force|force-key|forced-key|key-forced=s", "Use the given key for analysing deg data (ignore modulations)"); + define("o|octave|octaves|degree=b", "Encode octave information int **degree spines"); define("r|recip=b", "Prefix output data with **recip spine with -I option"); define("t|ties=b", "Include scale degrees for tied notes"); define("s|spine-tracks|spine|spines|track|tracks=s", "Process only the specified spines"); - define("0|z|zero|zeros=b", "Show rests as scale degree 0"); + define("0|O|z|zero|zeros=b", "Show rests as scale degree 0"); } @@ -110,9 +114,11 @@ bool Tool_deg::run(HumdrumFile& infile) { void Tool_deg::initialize(void) { m_aboveQ = getBoolean("above"); m_arrowQ = getBoolean("arrow"); + m_boxQ = getBoolean("box"); m_circleQ = getBoolean("circle"); m_colorQ = getBoolean("color"); m_hatQ = getBoolean("hat"); + m_solfegeQ = getBoolean("solfege"); if (m_colorQ) { m_color = getString("color"); @@ -125,6 +131,7 @@ void Tool_deg::initialize(void) { m_recipQ = true; } m_degTiesQ = getBoolean("ties"); + Tool_deg::ScaleDegree::setShowOctaves(getBoolean("octave")); if (getBoolean("spine-tracks")) { m_spineTracks = getString("spine-tracks"); @@ -134,6 +141,29 @@ void Tool_deg::initialize(void) { if (getBoolean("default-key")) { m_defaultKey = getString("default-key"); + if (!m_defaultKey.empty()) { + if (m_defaultKey[0] != '*') { + m_defaultKey = "*" + m_defaultKey; + } + if (m_defaultKey.find(":") == string::npos) { + m_defaultKey += ":"; + } + } + } + + if (getBoolean("forced-key")) { + m_defaultKey.clear(); // override --default-key option + + m_forcedKey = getString("forced-key"); + if (!m_forcedKey.empty()) { + if (m_forcedKey[0] != '*') { + m_forcedKey = "*" + m_forcedKey; + } + if (m_forcedKey.find(":") == string::npos) { + m_forcedKey += ":"; + } + Tool_deg::ScaleDegree::setForcedKey(m_forcedKey); + } } Tool_deg::ScaleDegree::setShowTies(m_degTiesQ); @@ -294,10 +324,12 @@ string Tool_deg::createOutputHumdrumLine(HumdrumFile& infile, int lineIndex) { // Styling interpretation tracking variables: bool aboveStatus = false; bool arrowStatus = false; + bool boxStatus = false; bool circleStatus = false; bool colorStatus = false; bool hatStatus = false; bool keyDesignationStatus = false; + bool solfegeStatus = false; // Keep track of an existing styling line and if such a line is found, // then insert a styling interpretation for the new **deg spines here @@ -306,12 +338,18 @@ string Tool_deg::createOutputHumdrumLine(HumdrumFile& infile, int lineIndex) { if (!m_defaultKey.empty() && !keyDesignationStatus && !m_ipv.foundKeyDesignationLine) { keyDesignationStatus = isKeyDesignationLine(infile, lineIndex); } + if (!m_forcedKey.empty() && !keyDesignationStatus && !m_ipv.foundKeyDesignationLine) { + keyDesignationStatus = isKeyDesignationLine(infile, lineIndex); + } if (m_aboveQ && !m_ipv.foundAboveLine) { aboveStatus = isDegAboveLine(infile, lineIndex); } if (m_arrowQ && !m_ipv.foundArrowLine) { arrowStatus = isDegArrowLine(infile, lineIndex); } + if (m_boxQ && !m_ipv.foundBoxLine) { + boxStatus = isDegBoxLine(infile, lineIndex); + } if (m_circleQ && !m_ipv.foundCircleLine) { circleStatus = isDegCircleLine(infile, lineIndex); } @@ -321,6 +359,9 @@ string Tool_deg::createOutputHumdrumLine(HumdrumFile& infile, int lineIndex) { if (m_hatQ && !m_ipv.foundHatLine) { hatStatus = isDegHatLine(infile, lineIndex); } + if (m_solfegeQ && !m_ipv.foundSolfegeLine) { + solfegeStatus = isDegSolfegeLine(infile, lineIndex); + } } // spineData: The output Humdrum data line stored in a 2D vector. @@ -356,9 +397,11 @@ string Tool_deg::createOutputHumdrumLine(HumdrumFile& infile, int lineIndex) { checkKeyDesignationStatus(value, keyDesignationStatus); checkAboveStatus(value, aboveStatus); checkArrowStatus(value, arrowStatus); + checkBoxStatus(value, boxStatus); checkCircleStatus(value, circleStatus); checkColorStatus(value, colorStatus); checkHatStatus(value, hatStatus); + checkSolfegeStatus(value, hatStatus); spineData.back().push_back(value); if (value == "*v") { hasDegMerger = true; @@ -382,9 +425,11 @@ string Tool_deg::createOutputHumdrumLine(HumdrumFile& infile, int lineIndex) { checkKeyDesignationStatus(value, keyDesignationStatus); checkAboveStatus(value, aboveStatus); checkArrowStatus(value, arrowStatus); + checkBoxStatus(value, boxStatus); checkCircleStatus(value, circleStatus); checkColorStatus(value, colorStatus); checkHatStatus(value, hatStatus); + checkSolfegeStatus(value, hatStatus); spineData.back().push_back(value); if (value == "*v") { hasDegMerger = true; @@ -405,6 +450,9 @@ string Tool_deg::createOutputHumdrumLine(HumdrumFile& infile, int lineIndex) { if (arrowStatus) { m_ipv.foundArrowLine = true; } + if (boxStatus) { + m_ipv.foundBoxLine = true; + } if (circleStatus) { m_ipv.foundCircleLine = true; } @@ -414,6 +462,9 @@ string Tool_deg::createOutputHumdrumLine(HumdrumFile& infile, int lineIndex) { if (hatStatus) { m_ipv.foundHatLine = true; } + if (solfegeStatus) { + m_ipv.foundSolfegeLine = true; + } // if styling interpretation lines were not found before the data, @@ -444,6 +495,15 @@ string Tool_deg::createOutputHumdrumLine(HumdrumFile& infile, int lineIndex) { } } + if (!m_ipv.foundBoxLine) { + if (m_boxQ && !m_ipv.foundBoxLine) { + string line = printDegInterpretation("*box", infile, lineIndex); + if (!line.empty()) { + extraLines.push_back(line); + } + } + } + if (!m_ipv.foundCircleLine) { if (m_circleQ && !m_ipv.foundCircleLine) { string line = printDegInterpretation("*circ", infile, lineIndex); @@ -471,9 +531,27 @@ string Tool_deg::createOutputHumdrumLine(HumdrumFile& infile, int lineIndex) { } } + if (!m_ipv.foundSolfegeLine) { + if (m_solfegeQ && !m_ipv.foundSolfegeLine) { + string line = printDegInterpretation("*solf", infile, lineIndex); + if (!line.empty()) { + extraLines.push_back(line); + } + } + } + if (!m_ipv.foundKeyDesignationLine) { if (!m_defaultKey.empty() && !m_ipv.foundKeyDesignationLine) { - string line = printDegInterpretation("*XXX", infile, lineIndex); + string line = printDegInterpretation(m_defaultKey, infile, lineIndex); + if (!line.empty()) { + extraLines.push_back(line); + } + } + } + + if (!m_ipv.foundKeyDesignationLine) { + if (!m_forcedKey.empty() && !m_ipv.foundKeyDesignationLine) { + string line = printDegInterpretation(m_forcedKey, infile, lineIndex); if (!line.empty()) { extraLines.push_back(line); } @@ -525,15 +603,9 @@ void Tool_deg::checkKeyDesignationStatus(string& value, int keyDesignationStatus if (keyDesignationStatus && (!m_ipv.foundKeyDesignationLine) && (!m_ipv.foundData)) { if (value == "*") { if (!m_defaultKey.empty()) { - if (m_defaultKey[0] == '*') { - value = m_defaultKey; - } else { - value = "*"; - value += m_defaultKey; - } - if (value.find(":") == string::npos) { - value += ":"; - } + value = m_defaultKey; + } else if (!m_forcedKey.empty()) { + value = m_forcedKey; } } } @@ -543,7 +615,7 @@ void Tool_deg::checkKeyDesignationStatus(string& value, int keyDesignationStatus ////////////////////////////// // -// Tool_deg::checkAboveStatus -- Add *arr interpretation to spine if needed. +// Tool_deg::checkAboveStatus -- Add *above interpretation to spine if needed. // void Tool_deg::checkAboveStatus(string& value, bool aboveStatus) { @@ -571,6 +643,21 @@ void Tool_deg::checkArrowStatus(string& value, bool arrowStatus) { +////////////////////////////// +// +// Tool_deg::checkBoxStatus -- Add *box interpretation to spine if needed. +// + +void Tool_deg::checkBoxStatus(string& value, bool boxStatus) { + if (boxStatus && m_boxQ && (!m_ipv.foundBoxLine) && (!m_ipv.foundData)) { + if (value == "*") { + value = "*box"; + } + } +} + + + ////////////////////////////// // // Tool_deg::checkCircleStatus -- Add *circ interpretation to spine if needed. @@ -587,7 +674,7 @@ void Tool_deg::checkCircleStatus(string& value, bool circleStatus) { ////////////////////////////// // -// Tool_deg::checkColorStatus -- Add *arr interpretation to spine if needed. +// Tool_deg::checkColorStatus -- Add *color interpretation to spine if needed. // void Tool_deg::checkColorStatus(string& value, bool colorStatus) { @@ -615,6 +702,21 @@ void Tool_deg::checkHatStatus(string& value, bool hatStatus) { +////////////////////////////// +// +// Tool_deg::checkSolfegeStatus -- Add *solfege interpretation to spine if needed. +// + +void Tool_deg::checkSolfegeStatus(string& value, bool hatStatus) { + if (hatStatus && m_solfegeQ && (!m_ipv.foundSolfegeLine) && (!m_ipv.foundData)) { + if (value == "*") { + value = "*solf"; + } + } +} + + + ////////////////////////////// // // Tool_deg::isKeyDesignationLine -- Returns true if any spine on the line @@ -642,8 +744,7 @@ bool Tool_deg::isKeyDesignationLine(HumdrumFile& infile, int lineIndex) { ////////////////////////////// // // Tool_deg::isDegAboveLine -- Return true if **deg spines only -// include *arr, *Xarr, *acc, *Xacc interpretations -// and "*" (but not all "*"). +// include *above, *below, interpretations and "*" (but not all "*"). // bool Tool_deg::isDegAboveLine(HumdrumFile& infile, int lineIndex) { @@ -660,7 +761,7 @@ bool Tool_deg::isDegAboveLine(HumdrumFile& infile, int lineIndex) { int degCount = 0; for (int i=0; iisDataType("**deg")) { + if (!(token->isDataType("**deg") || token->isDataType("**degree"))) { continue; } degCount++; @@ -697,7 +798,7 @@ bool Tool_deg::isDegArrowLine(HumdrumFile& infile, int lineIndex) { int degCount = 0; for (int i=0; iisDataType("**deg")) { + if (!(token->isDataType("**deg") || token->isDataType("**degree"))) { continue; } degCount++; @@ -715,6 +816,42 @@ bool Tool_deg::isDegArrowLine(HumdrumFile& infile, int lineIndex) { +////////////////////////////// +// +// Tool_deg::isDegBoxLine -- Return true if **deg spines includes +// any *box, or *Xbox, interpretations and "*" (but not all "*"). +// + +bool Tool_deg::isDegBoxLine(HumdrumFile& infile, int lineIndex) { + // If there are no **deg spines, then don't bother searching for them. + if (!m_ipv.hasDegSpines) { + return false; + } + if (!infile[lineIndex].isInterpretation()) { + return false; + } if (infile[lineIndex].isManipulator()) { + return false; + } + + int degCount = 0; + for (int i=0; iisDataType("**deg") || token->isDataType("**degree"))) { + continue; + } + degCount++; + if (*token == "*box") { return true; } + if (*token == "*Xbox") { return true; } + } + if (degCount == 0) { + m_ipv.hasDegSpines = false; + } + + return false; +} + + + ////////////////////////////// // // Tool_deg::isDegCircleLine -- Return true if **deg spines includes @@ -735,7 +872,7 @@ bool Tool_deg::isDegCircleLine(HumdrumFile& infile, int lineIndex) { int degCount = 0; for (int i=0; iisDataType("**deg")) { + if (!(token->isDataType("**deg") || token->isDataType("**degree"))) { continue; } degCount++; @@ -754,8 +891,7 @@ bool Tool_deg::isDegCircleLine(HumdrumFile& infile, int lineIndex) { ////////////////////////////// // // Tool_deg::isDegColorLine -- Return true if **deg spines only -// include *arr, *Xarr, *acc, *Xacc interpretations -// and "*" (but not all "*"). +// include *color interpretations and "*" (but not all "*"). // bool Tool_deg::isDegColorLine(HumdrumFile& infile, int lineIndex) { @@ -772,7 +908,7 @@ bool Tool_deg::isDegColorLine(HumdrumFile& infile, int lineIndex) { int degCount = 0; for (int i=0; iisDataType("**deg")) { + if (!(token->isDataType("**deg") || token->isDataType("**degree"))) { continue; } degCount++; @@ -807,7 +943,7 @@ bool Tool_deg::isDegHatLine(HumdrumFile& infile, int lineIndex) { int degCount = 0; for (int i=0; iisDataType("**deg")) { + if (!(token->isDataType("**deg") || token->isDataType("**degree"))) { continue; } degCount++; @@ -823,6 +959,42 @@ bool Tool_deg::isDegHatLine(HumdrumFile& infile, int lineIndex) { +////////////////////////////// +// +// Tool_deg::isDegSolfegeLine -- Return true if **deg spines includes +// any *solf, or *Xsolf, interpretations and "*" (but not all "*"). +// + +bool Tool_deg::isDegSolfegeLine(HumdrumFile& infile, int lineIndex) { + // If there are no **deg spines, then don't bother searching for them. + if (!m_ipv.hasDegSpines) { + return false; + } + if (!infile[lineIndex].isInterpretation()) { + return false; + } if (infile[lineIndex].isManipulator()) { + return false; + } + + int degCount = 0; + for (int i=0; iisDataType("**deg")) { + continue; + } + degCount++; + if (*token == "*solf") { return true; } + if (*token == "*Xsolf") { return true; } + } + if (degCount == 0) { + m_ipv.hasDegSpines = false; + } + + return false; +} + + + ////////////////////////////// // // Tool_deg::printDegInterpretation -- @@ -980,7 +1152,7 @@ string Tool_deg::prepareMergerLine(vector>& merge) { ////////////////////////////// // -// Tool_deg::calculateManipulatorOutput -- Deal with *^ *v *- *+ manipulators +// Tool_deg::calculateManipulatorOutputForSpine -- Deal with *^ *v *- *+ manipulators // void Tool_deg::calculateManipulatorOutputForSpine(vector& lineout, @@ -1036,9 +1208,11 @@ void Tool_deg::printDegScore(HumdrumFile& infile) { // input styling options bool printAbove = !m_aboveQ; bool printArrow = !m_arrowQ; + bool printBox = !m_boxQ; bool printCircle = !m_circleQ; bool printColor = !m_colorQ; bool printHat = !m_hatQ; + bool printSolfege = !m_solfegeQ; int lineCount = (int)m_degSpines[0].size(); int spineCount = (int)m_degSpines.size(); @@ -1092,6 +1266,12 @@ void Tool_deg::printDegScore(HumdrumFile& infile) { printArrow = true; } + if (!printBox) { + string line = createDegInterpretation("*box", i, m_recipQ); + m_humdrum_text << line << endl; + printBox = true; + } + if (!printCircle) { string line = createDegInterpretation("*circ", i, m_recipQ); m_humdrum_text << line << endl; @@ -1107,11 +1287,17 @@ void Tool_deg::printDegScore(HumdrumFile& infile) { } if (!printHat) { - string line = createDegInterpretation("*arr", i, m_recipQ); + string line = createDegInterpretation("*hat", i, m_recipQ); m_humdrum_text << line << endl; printHat = true; } + if (!printSolfege) { + string line = createDegInterpretation("*solf", i, m_recipQ); + m_humdrum_text << line << endl; + printSolfege = true; + } + } for (int j=0; j>& degspine, HTp kernst if (!m_defaultKey.empty()) { getModeAndTonic(mode, b40tonic, m_defaultKey); + } else if (!m_forcedKey.empty()) { + getModeAndTonic(mode, b40tonic, m_forcedKey); } int lineCount = infile.getLineCount(); @@ -1353,8 +1541,12 @@ void Tool_deg::prepareDegSpine(vector>& degspine, HTp kernst // void Tool_deg::getModeAndTonic(string& mode, int& b40tonic, const string& token) { + string newtoken = token; + if (!m_forcedKey.empty()) { + newtoken = m_forcedKey; + } HumRegex hre; - if (hre.search(token, "^\\*?([A-Ga-g][-#]*):?(.*)$")) { + if (hre.search(newtoken, "^\\*?([A-Ga-g][-#]*):?(.*)$")) { string key = hre.getMatch(1); string kmode = hre.getMatch(2); b40tonic = Convert::kernToBase40(key); @@ -1629,7 +1821,7 @@ HTp Tool_deg::ScaleDegree::getLinkedKernToken(void) const { ////////////////////////////// // // Tool_deg::ScaleDegree:getDegToken -- Convert the ScaleDegre -// to a **deg token string. +// to a **deg token string (or **degree token if including an octave). // string Tool_deg::ScaleDegree::getDegToken(void) const { @@ -1643,12 +1835,20 @@ string Tool_deg::ScaleDegree::getDegToken(void) const { } if (isExclusiveInterpretation()) { - return "**deg"; + if (m_octaveQ) { + return "**degree"; + } else { + return "**deg"; + } } else if (isManipulator()) { return getManipulator(); } else if (isInterpretation()) { if (isKeyDesignation()) { - return *token; + if (m_forcedKey.empty()) { + return *token; + } else{ + return "*"; + } } else { return "*"; } @@ -1741,7 +1941,7 @@ string Tool_deg::ScaleDegree::generateDegDataToken(void) const { ////////////////////////////// // -// Tool_deg::ScaleDegree::createDegDataSubToken -- Convert the ScaleDegree +// Tool_deg::ScaleDegree::generateDegDataSubtoken -- Convert the ScaleDegree // subtoken (chord note) into **deg data. // @@ -1788,6 +1988,12 @@ string Tool_deg::ScaleDegree::generateDegDataSubtoken(int index) const { } } + // Add octave information if requested: + if (m_octaveQ && (degree != 0)) { + output += "/"; + output += to_string(m_octaves.at(index)); + } + return output; }