Merge pull request #20229 from Eism/string_tunings_flats

fixed #19959: Alternate tuning presets need refining
This commit is contained in:
Elnur Ismailzada 2023-11-29 13:49:35 +02:00 committed by GitHub
commit fbf16ab1e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 110 additions and 45 deletions

View File

@ -24,28 +24,40 @@
"presets": [
{
"name": "Standard",
"value": [40, 45, 50, 55, 59, 64]
"value": [40, 45, 50, 55, 59, 64],
"useFlats": true
},{
"name": "Tune down 1/2 step",
"value": [39, 44, 49, 54, 58, 63]
"value": [39, 44, 49, 54, 58, 63],
"useFlats": true
},{
"name": "Tune down 1 step",
"value": [38, 43, 48, 53, 57, 62]
"value": [38, 43, 48, 53, 57, 62],
"useFlats": true
},{
"name": "Tune down 2 step",
"value": [36, 41, 46, 51, 55, 60]
"value": [36, 41, 46, 51, 55, 60],
"useFlats": true
},{
"name": "Dropped D",
"value": [38, 45, 50, 55, 59, 64],
"useFlats": true
},{
"name": "Dropped D tune down 1/2 step",
"value": [37, 44, 49, 54, 58, 63]
"value": [37, 44, 49, 54, 58, 63],
"useFlats": true
},{
"name": "Dropped D Variant",
"value": [38, 45, 50, 55, 57, 64]
"value": [38, 45, 50, 55, 57, 64],
"useFlats": true
},{
"name": "Double Dropped D",
"value": [38, 45, 50, 55, 59, 62]
"value": [38, 45, 50, 55, 59, 62],
"useFlats": true
},{
"name": "Dropped C",
"value": [36, 43, 48, 53, 57, 62]
"value": [36, 43, 48, 53, 57, 62],
"useFlats": true
},{
"name": "Dropped E",
"value": [40, 47, 52, 57, 61, 66]
@ -305,4 +317,4 @@
}
]
}
]
]

View File

@ -45,6 +45,7 @@ struct instrString {
int pitch = 0; // the pitch of the string
bool open = false; // true: string is open | false: string is fretted
int startFret = 0; // banjo 5th string starts on 5th fret
bool useFlat = false;
bool operator==(const instrString& d) const { return d.pitch == pitch && d.open == open; }
};

View File

@ -164,9 +164,10 @@ String StringTunings::accessibleInfo() const
for (int i = 0; i < numOfStrings; ++i) {
string_idx_t index = numOfStrings - i - 1;
if (mu::contains(m_visibleStrings, index)) {
String pitchStr = pitch2string(stringList[index].pitch);
const instrString str = stringList[index];
String pitchStr = pitch2string(str.pitch, str.useFlat);
if (pitchStr.empty()) {
LOGE() << "Invalid get pitch name for " << stringList[index].pitch;
LOGE() << "Invalid get pitch name for " << str.pitch;
continue;
}
@ -252,9 +253,10 @@ String StringTunings::generateText() const
for (int i = 0; i < numOfStrings; ++i) {
string_idx_t index = numOfStrings - i - 1;
if (mu::contains(m_visibleStrings, index)) {
String pitchStr = pitch2string(stringList[index].pitch);
const instrString str = stringList[index];
String pitchStr = pitch2string(str.pitch, str.useFlat);
if (pitchStr.empty()) {
LOGE() << "Invalid get pitch name for " << stringList[index].pitch;
LOGE() << "Invalid get pitch name for " << str.pitch;
continue;
}

View File

@ -485,7 +485,7 @@ int quantizeLen(int len, int raster)
return int(((float)len / raster) + 0.5) * raster; //round to the closest multiple of raster
}
static const char16_t* vall[] = {
static const char16_t* valSharp[] = {
u"c",
u"c♯",
u"d",
@ -499,19 +499,19 @@ static const char16_t* vall[] = {
u"a♯",
u"b"
};
static const char16_t* valu[] = {
u"C",
u"C♯",
u"D",
u"D♯",
u"E",
u"F",
u"F♯",
u"G",
u"G♯",
u"A",
u"A♯",
u"B"
static const char16_t* valFlat[] = {
u"c",
u"d♭",
u"d",
u"e♭",
u"e",
u"f",
u"g♭",
u"g",
u"a♭",
u"a",
u"b♭",
u"b"
};
/*!
@ -526,7 +526,7 @@ static const char16_t* valu[] = {
* @return
* The string representation of the note.
*/
String pitch2string(int v)
String pitch2string(int v, bool useFlats)
{
if (v < 0 || v > 127) {
return String(u"----");
@ -535,7 +535,13 @@ String pitch2string(int v)
String o;
o = String::number(octave);
int i = v % PITCH_DELTA_OCTAVE;
return (octave < 0 ? valu[i] : vall[i]) + o;
String pitchStr = useFlats ? valFlat[i] : valSharp[i];
if (octave < 0) {
pitchStr = pitchStr.toUpper();
}
return pitchStr + o;
}
/*!
@ -553,7 +559,7 @@ int string2pitch(const String& s)
return -1;
}
String origin = s;
String value = s;
bool negative = s.contains(u'-');
int octave = String(s[s.size() - 1]).toInt() * (negative ? -1 : 1);
@ -561,11 +567,12 @@ int string2pitch(const String& s)
return -1;
}
origin = origin.mid(0, origin.size() - (negative ? 2 : 1));
value = value.mid(0, value.size() - (negative ? 2 : 1));
value = value.toLower();
int pitchIndex = -1;
for (int i = 0; i < PITCH_DELTA_OCTAVE; ++i) {
if (origin.toLower() == String(octave < 0 ? valu[i] : vall[i]).toLower()) {
if (value == valFlat[i] || value == valSharp[i]) {
pitchIndex = i;
break;
}

View File

@ -48,7 +48,7 @@ extern int pitchKeyAdjust(int note, Key);
extern int line2pitch(int line, ClefType clef, Key);
extern int y2pitch(double y, ClefType clef, double spatium);
extern int quantizeLen(int, int);
extern String pitch2string(int v);
extern String pitch2string(int v, bool useFlats = false);
extern int string2pitch(const String& s);
extern void transposeInterval(int pitch, int tpc, int* rpitch, int* rtpc, Interval, bool useDoubleSharpsFlats);
extern int transposeTpc(int tpc, Interval interval, bool useDoubleSharpsFlats);

View File

@ -3972,6 +3972,7 @@ void TRead::read(StringData* item, XmlReader& e)
} else if (tag == "string") {
instrString strg;
strg.open = e.intAttribute("open", 0);
strg.useFlat = e.intAttribute("useFlat", 0);
strg.pitch = e.readInt();
item->stringList().push_back(strg);
} else {

View File

@ -2609,11 +2609,17 @@ void TWrite::write(const StringData* item, XmlWriter& xml)
xml.startElement("StringData");
xml.tag("frets", item->frets());
for (const instrString& strg : item->stringList()) {
XmlWriter::Attributes attrs;
if (strg.open) {
xml.tag("string", { { "open", "1" } }, strg.pitch);
} else {
xml.tag("string", strg.pitch);
attrs.push_back({ "open", "1" });
}
if (strg.useFlat) {
attrs.push_back({ "useFlat", "1" });
}
xml.tag("string", attrs, strg.pitch);
}
xml.endElement();
}

View File

@ -192,11 +192,15 @@ bool InstrumentsRepository::loadStringTuningsPresets(const io::path_t& path)
preset.value.push_back(valueVal.toInt());
}
if (info.number != static_cast<int>(preset.value.size())) {
if (info.number != preset.value.size()) {
LOGE() << "Invalid preset " << preset.name;
continue;
}
if (presetObj.contains("useFlats")) {
preset.useFlats = presetObj.value("useFlats").toBool();
}
info.presets.emplace_back(std::move(preset));
}

View File

@ -686,6 +686,7 @@ struct StringTuningPreset
{
std::string name;
std::vector<int> value;
bool useFlats = false;
};
struct StringTuningsInfo

View File

@ -88,6 +88,7 @@ void StringTuningsSettingsModel::init()
item->setShow(contains(visibleStrings, instrStringIndex));
item->setNumber(QString::number(i + 1));
item->setValue(string.pitch);
item->setUseFlat(string.useFlat);
item->blockSignals(false);
m_strings.push_back(item);
@ -134,6 +135,9 @@ bool StringTuningsSettingsModel::setStringValue(int stringIndex, const QString&
item->setValue(value);
bool useFlat = _stringValue.contains("");
item->setUseFlat(useFlat);
beginMultiCommands();
updateCurrentPreset();
@ -153,7 +157,7 @@ bool StringTuningsSettingsModel::canIncreaseStringValue(const QString& stringVal
QString StringTuningsSettingsModel::increaseStringValue(const QString& stringValue)
{
QString value = convertToUnicode(stringValue);
return engraving::pitch2string(engraving::string2pitch(value) + 1);
return engraving::pitch2string(engraving::string2pitch(value) + 1, false /* useFlats */);
}
bool StringTuningsSettingsModel::canDecreaseStringValue(const QString& stringValue) const
@ -165,7 +169,7 @@ bool StringTuningsSettingsModel::canDecreaseStringValue(const QString& stringVal
QString StringTuningsSettingsModel::decreaseStringValue(const QString& stringValue)
{
QString value = convertToUnicode(stringValue);
return engraving::pitch2string(engraving::string2pitch(value) - 1);
return engraving::pitch2string(engraving::string2pitch(value) - 1, true /* useFlats */);
}
QVariantList StringTuningsSettingsModel::presets(bool withCustom) const
@ -184,8 +188,9 @@ QVariantList StringTuningsSettingsModel::presets(bool withCustom) const
customMap.insert("text", custom);
QVariantList valueList;
for (const StringTuningsItem* item : m_strings) {
valueList << item->value();
int numOfStrings = static_cast<int>(m_strings.size());
for (int i = 0; i < numOfStrings; ++i) {
valueList << m_strings.at(numOfStrings - i - 1)->value();
}
customMap.insert("value", valueList);
@ -210,6 +215,7 @@ QVariantList StringTuningsSettingsModel::presets(bool withCustom) const
}
presetMap.insert("value", valueList);
presetMap.insert("useFlats", preset.useFlats);
presetsList.push_back(presetMap);
}
@ -313,6 +319,7 @@ void StringTuningsSettingsModel::updateStrings()
for (const QVariant& _preset : presets) {
if (_preset.toMap()["text"].toString() == currentPreset) {
QVariantList valueList = _preset.toMap()["value"].toList();
bool useFlats = _preset.toMap()["useFlats"].toBool();
int numOfStrings = valueList.size();
for (int i = 0; i < numOfStrings; ++i) {
int valueIndex = numOfStrings - i - 1;
@ -322,6 +329,7 @@ void StringTuningsSettingsModel::updateStrings()
item->setShow(true);
item->setNumber(QString::number(i + 1));
item->setValue(valueList[valueIndex].toInt());
item->setUseFlat(useFlats);
item->blockSignals(false);
m_strings.push_back(item);
@ -348,7 +356,9 @@ void StringTuningsSettingsModel::saveStrings()
int numOfStrings = m_strings.size();
for (int i = 0; i < numOfStrings; ++i) {
stringList[i].pitch = m_strings[numOfStrings - i - 1]->value();
const StringTuningsItem* item = m_strings.at(numOfStrings - i - 1);
stringList[i].pitch = item->value();
stringList[i].useFlat = item->useFlat();
}
beginCommand();
@ -378,8 +388,9 @@ void StringTuningsSettingsModel::saveStringsVisibleState()
void StringTuningsSettingsModel::updateCurrentPreset()
{
QVariantList currentValueList;
for (int i = 0; i < m_strings.size(); ++i) {
currentValueList << m_strings[i]->value();
int numOfStrings = static_cast<int>(m_strings.size());
for (int i = 0; i < numOfStrings; ++i) {
currentValueList << m_strings.at(numOfStrings - i - 1)->value();
}
const QVariantList presets = this->presets(false /*withCustom*/);
@ -471,7 +482,7 @@ int StringTuningsItem::value() const
QString StringTuningsItem::valueStr() const
{
return engraving::pitch2string(m_value).toUpper();
return engraving::pitch2string(m_value, m_useFlat).toUpper();
}
void StringTuningsItem::setValue(int value)
@ -483,3 +494,18 @@ void StringTuningsItem::setValue(int value)
m_value = value;
emit valueChanged();
}
bool StringTuningsItem::useFlat() const
{
return m_useFlat;
}
void StringTuningsItem::setUseFlat(bool use)
{
if (m_useFlat == use) {
return;
}
m_useFlat = use;
emit valueChanged();
}

View File

@ -107,6 +107,7 @@ class StringTuningsItem : public QObject
Q_PROPERTY(QString number READ number NOTIFY numberChanged)
Q_PROPERTY(int value READ value NOTIFY valueChanged)
Q_PROPERTY(QString valueStr READ valueStr NOTIFY valueChanged)
Q_PROPERTY(bool useFlat READ useFlat WRITE setUseFlat NOTIFY valueChanged)
public:
explicit StringTuningsItem(QObject* parent = nullptr);
@ -121,6 +122,9 @@ public:
QString valueStr() const;
void setValue(int value);
bool useFlat() const;
void setUseFlat(bool use);
signals:
void showChanged();
void numberChanged();
@ -130,6 +134,7 @@ private:
bool m_show = false;
QString m_number;
int m_value = 0;
bool m_useFlat = false;
};
} //namespace mu::notation