diff --git a/source/formats/gp7/document.cpp b/source/formats/gp7/document.cpp index d90e3288..6af32b34 100644 --- a/source/formats/gp7/document.cpp +++ b/source/formats/gp7/document.cpp @@ -20,6 +20,7 @@ #include using Ottavia = Gp7::Beat::Ottavia; +using Accidental = Gp7::ChordName::Note::Accidental; using Alteration = Gp7::ChordName::Degree::Alteration; using DirectionTarget = Gp7::MasterBar::DirectionTarget; using DirectionJump = Gp7::MasterBar::DirectionJump; @@ -34,6 +35,13 @@ UTIL_DEFINE_ENUMTOSTRING(Ottavia, { { Ottavia::O8va, "8va"s }, { Ottavia::O15ma, "15ma"s }, { Ottavia::O15mb, "15mb"s } }) +UTIL_DEFINE_ENUMTOSTRING(Accidental, + { { Accidental::DoubleFlat, "DoubleFlat"s }, + { Accidental::Flat, "Flat"s }, + { Accidental::Natural, "Natural"s }, + { Accidental::Sharp, "Sharp"s }, + { Accidental::DoubleSharp, "DoubleSharp"s } }) + UTIL_DEFINE_ENUMTOSTRING(Alteration, { { Alteration::Perfect, "Perfect"s }, { Alteration::Diminished, "Diminished"s }, diff --git a/source/formats/gp7/document.h b/source/formats/gp7/document.h index 523b13c3..a82332a5 100644 --- a/source/formats/gp7/document.h +++ b/source/formats/gp7/document.h @@ -102,8 +102,17 @@ struct ChordName { struct Note { + enum class Accidental: int + { + DoubleFlat = -2, + Flat = -1, + Natural = 0, + Sharp = 1, + DoubleSharp = 2 + }; + std::string myStep; - int myAccidental = 0; + Accidental myAccidental = Accidental::Natural; }; struct Degree @@ -117,6 +126,11 @@ struct ChordName Minor }; + Degree() = default; + Degree(Alteration alt) : myAlteration(alt) + { + } + Alteration myAlteration = Alteration::Perfect; bool myOmitted = false; }; @@ -143,6 +157,7 @@ struct ChordDiagram struct Chord { + std::string myDescription; ChordName myName; ChordDiagram myDiagram; }; @@ -452,6 +467,7 @@ struct std::hash // Enum to string conversions UTIL_DECLARE_ENUMTOSTRING(Gp7::Beat::Ottavia) +UTIL_DECLARE_ENUMTOSTRING(Gp7::ChordName::Note::Accidental) UTIL_DECLARE_ENUMTOSTRING(Gp7::ChordName::Degree::Alteration) UTIL_DECLARE_ENUMTOSTRING(Gp7::MasterBar::DirectionTarget) UTIL_DECLARE_ENUMTOSTRING(Gp7::MasterBar::DirectionJump) diff --git a/source/formats/gp7/from_pt2.cpp b/source/formats/gp7/from_pt2.cpp index bc2fa844..a1cfd6f5 100644 --- a/source/formats/gp7/from_pt2.cpp +++ b/source/formats/gp7/from_pt2.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -80,6 +81,216 @@ convertScoreInfo(const Score &score) return gp_info; } +static Gp7::ChordName +convertChordName(const ChordName &name) +{ + Gp7::ChordName gp_name; + using Accidental = Gp7::ChordName::Note::Accidental; + using Degree = Gp7::ChordName::Degree; + using Alteration = Degree::Alteration; + + static const std::string theKeys[] = { "C", "D", "E", "F", "G", "A", "B" }; + gp_name.myKeyNote.myStep = theKeys[name.getTonicKey()]; + gp_name.myKeyNote.myAccidental = + static_cast(name.getTonicVariation()); + + gp_name.myBassNote.myStep = theKeys[name.getBassKey()]; + gp_name.myBassNote.myAccidental = + static_cast(name.getBassVariation()); + + // Fifth + switch (name.getFormula()) + { + case ChordName::Augmented: + case ChordName::Augmented7th: + gp_name.myFifth = Alteration::Augmented; + break; + case ChordName::Diminished: + case ChordName::Diminished7th: + case ChordName::Minor7thFlatted5th: + gp_name.myFifth = Alteration::Diminished; + break; + default: + if (name.hasModification(ChordName::Flatted5th)) + gp_name.myFifth = Alteration::Diminished; + else if (name.hasModification(ChordName::Raised5th)) + gp_name.myFifth = Alteration::Augmented; + else + gp_name.myFifth = Alteration::Perfect; + break; + } + + // Third + switch (name.getFormula()) + { + case ChordName::Major: + case ChordName::Augmented: + case ChordName::Major6th: + case ChordName::Dominant7th: + case ChordName::Major7th: + case ChordName::Augmented7th: + gp_name.myThird = Alteration::Major; + break; + case ChordName::Minor: + case ChordName::Diminished: + case ChordName::Minor6th: + case ChordName::Minor7th: + case ChordName::Diminished7th: + case ChordName::MinorMajor7th: + case ChordName::Minor7thFlatted5th: + gp_name.myThird = Alteration::Minor; + break; + default: + break; + } + + // Second + if (name.hasModification(ChordName::Added2nd) || + name.hasModification(ChordName::Suspended2nd)) + { + gp_name.mySecond = Alteration::Perfect; + } + + // Fourth + if (name.hasModification(ChordName::Added4th) || + name.hasModification(ChordName::Suspended4th)) + { + gp_name.myFourth = Alteration::Perfect; + } + + // Clear out the third for sus chords. + if (name.hasModification(ChordName::Suspended2nd) || + name.hasModification(ChordName::Suspended4th)) + { + gp_name.myThird.reset(); + } + + // Sixth + switch (name.getFormula()) + { + case ChordName::Major6th: + case ChordName::Minor6th: + gp_name.mySixth = Alteration::Major; + break; + default: + if (name.hasModification(ChordName::Added6th)) + gp_name.mySixth = Alteration::Major; + break; + } + + // Seventh + switch (name.getFormula()) + { + case ChordName::Dominant7th: + case ChordName::Minor7th: + case ChordName::Augmented7th: + case ChordName::Minor7thFlatted5th: + gp_name.mySeventh = Alteration::Minor; + break; + case ChordName::Major7th: + case ChordName::MinorMajor7th: + gp_name.mySeventh = Alteration::Major; + break; + case ChordName::Diminished7th: + gp_name.mySeventh = Alteration::Diminished; + break; + default: + break; + } + + // 9th + if (name.hasModification(ChordName::Extended9th) || + name.hasModification(ChordName::Added9th)) + { + gp_name.myNinth = Alteration::Perfect; + } + else if (name.hasModification(ChordName::Flatted9th)) + gp_name.myNinth = Alteration::Diminished; + else if (name.hasModification(ChordName::Raised9th)) + gp_name.myNinth = Alteration::Augmented; + + // 11th + if (name.hasModification(ChordName::Extended11th) || + name.hasModification(ChordName::Added11th)) + { + gp_name.myEleventh = Alteration::Perfect; + } + else if (name.hasModification(ChordName::Raised11th)) + gp_name.myEleventh = Alteration::Augmented; + + // 13th + if (name.hasModification(ChordName::Extended13th)) + gp_name.myThirteenth = Alteration::Perfect; + else if (name.hasModification(ChordName::Flatted13th)) + gp_name.myThirteenth = Alteration::Diminished; + + return gp_name; +} + +static Gp7::ChordDiagram +convertChordDiagram(const ChordDiagram &diagram) +{ + Gp7::ChordDiagram gp_diagram; + gp_diagram.myBaseFret = diagram.getTopFret(); + + gp_diagram.myFrets = diagram.getFretNumbers(); + // Strings are in the opposite order, and frets are relative to the top + // fret. + std::reverse(gp_diagram.myFrets.begin(), gp_diagram.myFrets.end()); + for (int &fret : gp_diagram.myFrets) + { + if (fret > 0) + fret -= diagram.getTopFret(); + } + + return gp_diagram; +} + +using GpChordsMap = std::unordered_map; +using ChordNameIdMap = std::unordered_map; + +static GpChordsMap +convertChords(const Score &score, ChordNameIdMap &chord_name_ids) +{ + GpChordsMap chords; + + // Add all chord diagrams. Note that their chord names may not be unique + // (same chord but different fingering). + for (const ChordDiagram &diagram : score.getChordDiagrams()) + { + const int chord_id = chords.size(); + chord_name_ids[diagram.getChordName()] = chord_id; + + Gp7::Chord gp_chord; + gp_chord.myDescription = Util::toString(diagram.getChordName()); + gp_chord.myName = convertChordName(diagram.getChordName()); + gp_chord.myDiagram = convertChordDiagram(diagram); + chords.emplace(chord_id, gp_chord); + } + + // Add all unique chord text items. + for (const System &system : score.getSystems()) + { + for (const ChordText &text : system.getChords()) + { + const ChordName &name = text.getChordName(); + + if (chord_name_ids.find(name) != chord_name_ids.end()) + continue; + + const int chord_id = chords.size(); + chord_name_ids[name] = chord_id; + + Gp7::Chord gp_chord; + gp_chord.myDescription = Util::toString(name); + gp_chord.myName = convertChordName(name); + chords.emplace(chord_id, gp_chord); + } + } + + return chords; +} + using PlayerInstrumentMap = std::unordered_map>; /// Find all of the instruments assigned to each player in the score. @@ -109,10 +320,12 @@ findPlayerInstruments(const Score &score) } static std::vector -convertTracks(const Score &score) +convertTracks(const Score &score, ChordNameIdMap &chord_name_ids) { std::vector tracks; + GpChordsMap chords = convertChords(score, chord_name_ids); + PlayerInstrumentMap player_instruments = findPlayerInstruments(score); int player_idx = 0; for (const Player &player : score.getPlayers()) @@ -141,7 +354,10 @@ convertTracks(const Score &score) staff.myTuning.assign(notes.rbegin(), notes.rend()); track.myStaves.push_back(staff); - // TODO - export chords + // Chords are the same for all players. In the future we could trim + // this based on which chord names are used while the player is active, + // but the chord diagrams apply to all players anyways + track.myChords = chords; // TODO - export player changes as sound automations // For now we just assign an initial instrument @@ -345,9 +561,9 @@ convertFingering(LeftHandFingering::Finger f) static void convertBeat(Gp7::Document &doc, Gp7::MasterBar &master_bar, Gp7::Beat &beat, - const System &system, const Voice &voice, const Tuning &tuning, - const KeySignature &key, const boost::rational &bar_time, - const Position &pos) + const ChordNameIdMap &chord_name_ids, const System &system, + const Voice &voice, const Tuning &tuning, const KeySignature &key, + const boost::rational &bar_time, const Position &pos) { beat.myGraceNote = pos.hasProperty(Position::Acciaccatura); beat.myTremoloPicking = pos.hasProperty(Position::TremoloPicking); @@ -369,6 +585,12 @@ convertBeat(Gp7::Document &doc, Gp7::MasterBar &master_bar, Gp7::Beat &beat, beat.myFreeText = text->getContents(); } + if (const ChordText *text = + ScoreUtils::findByPosition(system.getChords(), pos.getPosition())) + { + beat.myChordId = chord_name_ids.at(text->getChordName()); + } + for (const Note ¬e: pos.getNotes()) { Gp7::Note gp_note; @@ -490,7 +712,7 @@ convertBeat(Gp7::Document &doc, Gp7::MasterBar &master_bar, Gp7::Beat &beat, } static void -convertBar(Gp7::Document &doc, +convertBar(Gp7::Document &doc, const ChordNameIdMap &chord_name_ids, std::unordered_map &unique_rhythms, Gp7::MasterBar &master_bar, Gp7::Bar &bar, const System &system, const Staff &staff, const Tuning &tuning, const KeySignature &key, @@ -515,8 +737,8 @@ convertBar(Gp7::Document &doc, ScoreUtils::findInRange(voice.getPositions(), start_idx, end_idx)) { Gp7::Beat beat; - convertBeat(doc, master_bar, beat, system, voice, tuning, key, - bar_time, pos); + convertBeat(doc, master_bar, beat, chord_name_ids, system, voice, + tuning, key, bar_time, pos); bar_time += VoiceUtils::getDurationTime(voice, pos); Gp7::Rhythm rhythm = convertRhythm(voice, pos); @@ -743,7 +965,8 @@ convertMasterBar(const Gp7::Document &doc, const System &system, } static void -convertScore(const Score &score, Gp7::Document &doc) +convertScore(const Score &score, const ChordNameIdMap &chord_name_ids, + Gp7::Document &doc) { std::unordered_map unique_rhythms; @@ -779,8 +1002,8 @@ convertScore(const Score &score, Gp7::Document &doc) continue; // Something is incorrect in the file... Gp7::Bar bar; - convertBar(doc, unique_rhythms, master_bar, bar, system, staff, - tuning, current_bar.getKeySignature(), + convertBar(doc, chord_name_ids, unique_rhythms, master_bar, bar, + system, staff, tuning, current_bar.getKeySignature(), current_bar.getPosition(), next_bar.getPosition()); const int bar_id = doc.myBars.size(); @@ -815,8 +1038,9 @@ Gp7::convert(const Score &score) Gp7::Document gp_doc; gp_doc.myScoreInfo = convertScoreInfo(score); - gp_doc.myTracks = convertTracks(score); - convertScore(score, gp_doc); + ChordNameIdMap chord_name_ids; + gp_doc.myTracks = convertTracks(score, chord_name_ids); + convertScore(score, chord_name_ids, gp_doc); return gp_doc; } diff --git a/source/formats/gp7/from_xml.cpp b/source/formats/gp7/from_xml.cpp index 195a4d7a..d10e830a 100644 --- a/source/formats/gp7/from_xml.cpp +++ b/source/formats/gp7/from_xml.cpp @@ -160,19 +160,16 @@ parseChordNote(const pugi::xml_node &node) Gp7::ChordName::Note note; note.myStep = node.attribute("step").as_string(); - static const std::unordered_map theAccidentals = { - { "Natural"s, 0 }, - { "Sharp"s, 1 }, - { "DoubleSharp"s, 2 }, - { "Flat"s, -1 }, - { "DoubleFlat"s, -2 } - }; - - auto it = theAccidentals.find(node.attribute("accidental").as_string()); - if (it == theAccidentals.end()) - throw FileFormatException("Unknown accidental type"); + using Accidental = Gp7::ChordName::Note::Accidental; + std::string accidental_text = node.attribute("accidental").as_string(); - note.myAccidental = it->second; + if (auto accidental = Util::toEnum(accidental_text)) + note.myAccidental = *accidental; + else + { + std::cerr << "Unknown accidental type: " << accidental_text + << std::endl; + } return note; } diff --git a/source/formats/gp7/to_pt2.cpp b/source/formats/gp7/to_pt2.cpp index b3e9c210..2f7bd84b 100644 --- a/source/formats/gp7/to_pt2.cpp +++ b/source/formats/gp7/to_pt2.cpp @@ -37,8 +37,10 @@ #include #include #include +#include #include +#include /// Convert the Guitar Pro file metadata. static void @@ -987,16 +989,25 @@ convertChordDiagram(const Gp7::Chord &gp_chord) static void convertChordDiagrams(const Gp7::Document &doc, Score &score) { - // TODO - consolidate identical diagrams from different tracks? + std::unordered_set unique_diagrams; for (const Gp7::Track &track : doc.myTracks) { - // Sort by id to insert in a deterministic order.. - std::map ordered_chords(track.myChords.begin(), - track.myChords.end()); - - for (auto &&[_, chord] : ordered_chords) - score.insertChordDiagram(convertChordDiagram(chord)); + for (auto &&[_, chord] : track.myChords) + unique_diagrams.insert(convertChordDiagram(chord)); } + + // Sort by chord name to insert in a deterministic order. + std::vector diagrams(unique_diagrams.begin(), + unique_diagrams.end()); + std::sort(diagrams.begin(), diagrams.end(), + [](const ChordDiagram &d1, const ChordDiagram &d2) + { + return Util::toString(d1.getChordName()) < + Util::toString(d2.getChordName()); + }); + + for (const ChordDiagram &diagram : diagrams) + score.insertChordDiagram(diagram); } static void @@ -1090,7 +1101,14 @@ convertSystem(const Gp7::Document &doc, Score &score, int bar_begin, doc.myTracks[track_idx].myChords.at(*gp_beat.myChordId); ChordName chord_name = convertChordName(gp_chord.myName); - system.insertChord(ChordText(voice_pos, chord_name)); + // Avoid inserting duplicates since many tracks may + // have the same chord name. + if (!ScoreUtils::findByPosition(system.getChords(), + voice_pos)) + { + system.insertChord( + ChordText(voice_pos, chord_name)); + } } Position pos = convertPosition(gp_beat, gp_rhythm); diff --git a/source/formats/gp7/to_xml.cpp b/source/formats/gp7/to_xml.cpp index 4a20eb86..28cfd72d 100644 --- a/source/formats/gp7/to_xml.cpp +++ b/source/formats/gp7/to_xml.cpp @@ -63,6 +63,14 @@ listToString(const std::vector &items, char sep = ' ') return s; } +static pugi::xml_node +addPropertyNode(pugi::xml_node &props_node, const char *name) +{ + auto prop_node = props_node.append_child("Property"); + prop_node.append_attribute("name").set_value(name); + return prop_node; +} + namespace Gp7 { static void @@ -118,6 +126,100 @@ saveMasterTrack(pugi::xml_node &gpif, const std::vector &tracks, } } +static void +saveChordNote(pugi::xml_node chord_node, const char *name, + const ChordName::Note ¬e) +{ + auto node = chord_node.append_child(name); + node.append_attribute("step").set_value(note.myStep.c_str()); + node.append_attribute("accidental") + .set_value(Util::toString(note.myAccidental).c_str()); +} + +static void +saveChordDegree(pugi::xml_node chord_node, const char *interval, + const std::optional °ree) +{ + if (!degree) + return; + + auto node = chord_node.append_child("Degree"); + node.append_attribute("interval").set_value(interval); + node.append_attribute("alteration") + .set_value(Util::toString(degree->myAlteration).c_str()); + node.append_attribute("omitted").set_value(degree->myOmitted); +} + +static void +saveDiagram(pugi::xml_node diagram_node, const ChordDiagram &diagram) +{ + diagram_node.append_attribute("baseFret").set_value(diagram.myBaseFret); + diagram_node.append_attribute("stringCount") + .set_value(diagram.myFrets.size()); + + int num_frets = 0; + for (size_t string = 0; string < diagram.myFrets.size(); ++string) + { + int fret = diagram.myFrets[string]; + if (fret < 0) + continue; + + ++num_frets; + auto fret_node = diagram_node.append_child("Fret"); + fret_node.append_attribute("string").set_value(string); + fret_node.append_attribute("fret").set_value(fret); + } + + diagram_node.append_attribute("fretCount").set_value(num_frets); + + auto addDiagramProperty = + [](pugi::xml_node &diagram_node, const char *name, bool val) + { + auto prop = addPropertyNode(diagram_node, name); + prop.append_attribute("type").set_value("bool"); + prop.append_attribute("value").set_value(val); + }; + + addDiagramProperty(diagram_node, "ShowName", true); + addDiagramProperty(diagram_node, "ShowDiagram", true); + addDiagramProperty(diagram_node, "ShowFingering", false); +} + +static void +saveChordDiagrams(pugi::xml_node chords_node, const Track &track) +{ + auto items_node = chords_node.append_child("Items"); + + for (auto &&[chord_id, chord] : track.myChords) + { + auto item = items_node.append_child("Item"); + item.append_attribute("id").set_value(chord_id); + item.append_attribute("name").set_value(chord.myDescription.c_str()); + + // Chord diagram + auto diagram_node = item.append_child("Diagram"); + const ChordDiagram &diagram = chord.myDiagram; + saveDiagram(diagram_node, diagram); + + // Chord name + auto chord_node = item.append_child("Chord"); + const ChordName &chord_name = chord.myName; + + saveChordNote(chord_node, "KeyNote", chord_name.myKeyNote); + saveChordNote(chord_node, "BassNote", chord_name.myBassNote); + + saveChordDegree(chord_node, "Second", chord_name.mySecond); + saveChordDegree(chord_node, "Third", chord_name.myThird); + saveChordDegree(chord_node, "Fourth", chord_name.myFourth); + saveChordDegree(chord_node, "Fifth", chord_name.myFifth); + saveChordDegree(chord_node, "Sixth", chord_name.mySixth); + saveChordDegree(chord_node, "Seventh", chord_name.mySeventh); + saveChordDegree(chord_node, "Ninth", chord_name.myNinth); + saveChordDegree(chord_node, "Eleventh", chord_name.myEleventh); + saveChordDegree(chord_node, "Thirteenth", chord_name.myThirteenth); + } +} + static void saveTracks(pugi::xml_node &gpif, const std::vector &tracks) { @@ -196,6 +298,9 @@ saveTracks(pugi::xml_node &gpif, const std::vector &tracks) auto tuning = props_node.append_child("Property"); tuning.append_attribute("name").set_value("Tuning"); addValueNode(tuning, "Pitches", listToString(staff.myTuning)); + + auto chords_node = addPropertyNode(props_node, "DiagramCollection"); + saveChordDiagrams(chords_node, track); } // In Power Tab the notes are implicitly transposed down in the @@ -220,8 +325,6 @@ saveTracks(pugi::xml_node &gpif, const std::vector &tracks) sound.myPath + ";" + sound.myName + ";" + sound.myRole); } - // TODO - export chords - ++track_idx; } } @@ -340,14 +443,6 @@ saveVoices(pugi::xml_node &gpif, } } -static pugi::xml_node -addPropertyNode(pugi::xml_node &props_node, const char *name) -{ - auto prop_node = props_node.append_child("Property"); - prop_node.append_attribute("name").set_value(name); - return prop_node; -} - static void saveBeats(pugi::xml_node &gpif, const std::unordered_map &beats_map) { @@ -403,8 +498,8 @@ saveBeats(pugi::xml_node &gpif, const std::unordered_map &beats_map) node.append_attribute("destinationOffset").set_value(whammy.myDestOffset); } - // TODO - // - chord ids + if (beat.myChordId) + addCDataNode(beat_node, "Chord", std::to_string(*beat.myChordId)); } } diff --git a/source/score/chorddiagram.cpp b/source/score/chorddiagram.cpp index 30409706..5dfc8817 100644 --- a/source/score/chorddiagram.cpp +++ b/source/score/chorddiagram.cpp @@ -18,6 +18,7 @@ #include "chorddiagram.h" #include "tuning.h" +#include #include ChordDiagram::ChordDiagram() @@ -67,3 +68,13 @@ operator<<(std::ostream &os, const ChordDiagram &diagram) return os; } + +size_t +std::hash::operator()(const ChordDiagram &diagram) const +{ + size_t seed = std::hash()(diagram.getChordName()); + boost::hash_combine(seed, diagram.getTopFret()); + boost::hash_range(seed, diagram.getFretNumbers().begin(), + diagram.getFretNumbers().end()); + return seed; +} diff --git a/source/score/chorddiagram.h b/source/score/chorddiagram.h index 2d25e8aa..ff3a88bb 100644 --- a/source/score/chorddiagram.h +++ b/source/score/chorddiagram.h @@ -68,4 +68,11 @@ void ChordDiagram::serialize(Archive &ar, const FileVersion /*version*/) std::ostream &operator<<(std::ostream &os, const ChordDiagram &diagram); +/// Enable use as a key for std::unordered_map, etc. +template<> +struct std::hash +{ + size_t operator()(const ChordDiagram &diagram) const; +}; + #endif diff --git a/test/formats/gp7/data/chord_diagrams.gp b/test/formats/gp7/data/chord_diagrams.gp index 5db2e655..9eeda712 100644 Binary files a/test/formats/gp7/data/chord_diagrams.gp and b/test/formats/gp7/data/chord_diagrams.gp differ diff --git a/test/formats/gp7/test_gp7.cpp b/test/formats/gp7/test_gp7.cpp index 64dfe591..3a5bb423 100644 --- a/test/formats/gp7/test_gp7.cpp +++ b/test/formats/gp7/test_gp7.cpp @@ -924,18 +924,16 @@ TEST_CASE("Formats/Gp7Import/ChordDiagrams") Gp7Importer importer; importer.load(Paths::getAppDirPath("data/chord_diagrams.gp"), score); - REQUIRE(score.getChordDiagrams().size() == 5); + REQUIRE(score.getChordDiagrams().size() == 4); REQUIRE(Util::toString(score.getChordDiagrams()[0]) == - "E: 0 2 2 1 0 0"); + "Asus2: x 0 2 2 0 0"); REQUIRE(Util::toString(score.getChordDiagrams()[1]) == "Bb: 6 8 8 7 6 x (6)"); REQUIRE(Util::toString(score.getChordDiagrams()[2]) == + "E: 0 2 2 1 0 0"); + REQUIRE(Util::toString(score.getChordDiagrams()[3]) == "F#: x 2 4 4 3 x x"); - REQUIRE(Util::toString(score.getChordDiagrams()[4]) == - "Asus2: x 0 2 2 0 0"); - // Duplicates aren't detected currently. - REQUIRE(score.getChordDiagrams()[3] == score.getChordDiagrams()[0]); } TEST_CASE("Formats/Gp7Export") @@ -944,16 +942,14 @@ TEST_CASE("Formats/Gp7Export") "data/alternate_endings.gp", "data/bars.gp", //"data/bends.gp", + "data/chord_diagrams.gp", "data/directions.gp", "data/fermatas.gp", "data/harmonics.gp", "data/irregular_groups.gp", "data/notes.gp", //"data/score_info.gp", - // - // has chord names / diagrams - // "data/chord_diagrams.gp", - // "data/text.gp", + "data/text.gp", // // multi-staff tracks become separate tracks and get unique instruments // "data/tracks.gp" diff --git a/test/formats/gpx/test_gpx.cpp b/test/formats/gpx/test_gpx.cpp index ef5b86de..12d11751 100644 --- a/test/formats/gpx/test_gpx.cpp +++ b/test/formats/gpx/test_gpx.cpp @@ -87,16 +87,14 @@ TEST_CASE("Formats/GpxImport/ChordDiagrams") GpxImporter importer; importer.load(Paths::getAppDirPath("data/chord_diagrams.gpx"), score); - REQUIRE(score.getChordDiagrams().size() == 5); + REQUIRE(score.getChordDiagrams().size() == 4); REQUIRE(Util::toString(score.getChordDiagrams()[0]) == - "E: 0 2 2 1 0 0"); + "Asus2: x 0 2 2 0 0"); REQUIRE(Util::toString(score.getChordDiagrams()[1]) == "Bb: 6 8 8 7 6 x (6)"); REQUIRE(Util::toString(score.getChordDiagrams()[2]) == + "E: 0 2 2 1 0 0"); + REQUIRE(Util::toString(score.getChordDiagrams()[3]) == "F#: x 2 4 4 3 x x"); - REQUIRE(Util::toString(score.getChordDiagrams()[4]) == - "Asus2: x 0 2 2 0 0"); - // Duplicates aren't detected currently. - REQUIRE(score.getChordDiagrams()[3] == score.getChordDiagrams()[0]); }