Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Q] Mixing ::core and ::api structures. #44

Closed
p-groarke opened this issue Jan 25, 2020 · 6 comments
Closed

[Q] Mixing ::core and ::api structures. #44

p-groarke opened this issue Jan 25, 2020 · 6 comments
Labels

Comments

@p-groarke
Copy link
Contributor

Is it possible to mix core and api data structures? From what I can tell, I don't believe it is. At least I couldn't find it quickly.

My use case :
I must add a theoretical key signature to an mx::api::Measure (d flat minor). As such, I cannot use the mx::api::KeyData, since it cuts off values not present in the signature circle. I think mx::core::NonTraditionalKey is meant to build just that.

I really like the mx::api workflow, so I'm hoping I don't need to change my whole project to use mx::core. Is there a way to retro-fit the NonTraditionalKey into an api::measure?

Thanks!

@webern
Copy link
Owner

webern commented Jan 25, 2020

So, the backstory is that mx::core is an exact(ish) representation of the MusicXML. As such it is quite difficult to use because it supports so many features. The MusicXML spec is a beast.

The easier mx:api structure was meant to simplify everything by restricting features.

The MusicXML document lives in memory as an mx::core data structure and is converted to-and-from mx:api through the DocumentManager such that mx::core is never exposed to the user of mx::api.

Currently I don't think you can easily get the mx::core representation from the DocumentManager. The only way I can think of to do this would be to return some sort of void* and say, "don't use this function unless you know what you're doing", then that void star could be "downcasted" to a DocumentPtr.

Alterations to that DocumentPtr that are not 'supported' by mx:api would be lost when round-tripping mx::core->mx::api->mx::core. But you could conceivable make alterations when you are done with mx::api and then serialize the DocumentPtr.

Anyway, if it's just for the Db Minor, it might not be necessary. I'm wondering what happens if you specify keyData.fifths = -8; keyData.mode = KeyMode::minor;

Can you show me the musicxml representation that you want as your output?

@webern
Copy link
Owner

webern commented Jan 25, 2020

I created #45 because I think that you will bump up against other places where you need more features than mx::api exposes, even if the key signature turns out to be a non-issue.

@webern
Copy link
Owner

webern commented Jan 26, 2020

I did a little research. This program:

    mx::api::ScoreData score;
    score.workTitle = "Db Minor";
    mx::api::PartData part;
    part.displayName = "Flute";
    part.instrumentData.uniqueId = "FLUTE1";
    part.instrumentData.soloOrEnsemble = SoloOrEnsemble::solo;
    part.instrumentData.soundID = SoundID::windFlutesFlute;
    part.measures.emplace_back();
    auto& measure = part.measures.back();
    mx::api::KeyData dbMinor;
    dbMinor.fifths = -8;
    dbMinor.mode = KeyMode::minor;
    measure.keys.push_back( dbMinor );
    score.parts.push_back( std::move(part));
    auto& docMgr = mx::api::DocumentManager::getInstance();
    const auto id = docMgr.createFromScore( score );
    std::cout << std::endl;
    docMgr.writeToStream(id, std::cout);
    std::cout << std::endl;

Produces this xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 3.0 Partwise//EN" "http://www.musicxml.org/dtds/partwise.dtd">
<score-partwise>
  <work>
    <work-title>Db Minor</work-title>
  </work>
  <part-list>
    <score-part id="ID">
      <part-name print-object="no" />
      <part-name-display>
        <display-text>Flute</display-text>
      </part-name-display>
      <score-instrument id="FLUTE1">
        <instrument-name />
        <instrument-sound>wind.flutes.flute</instrument-sound>
        <solo />
      </score-instrument>
    </score-part>
  </part-list>
  <part id="ID">
    <measure number="1">
      <attributes>
        <divisions>420</divisions>
        <key>
          <fifths>-8</fifths>
          <mode>minor</mode>
        </key>
      </attributes>
    </measure>
  </part>
</score-partwise>

I opened this in Finale, Dorico and MuseScore. None of them produce precisely the key signature that you linked to on wikipedia. MuseScore gets it wrong, Finale and Dorico produce the right flats but they have the Bbb on the left instead of the right.

Finale

image

Dorico

image

MuseScore

image

How do they Represent Db Minor?

Neither MuseScore nor Finale has a way of creating Db Minor through the easy path, both would require the user to construct a custom key signature. With Dorico, you can create Db Minor through the usual interface, and it again places the B double-flat on the left.

What if I need the Bbb on the Right

If you absolutely need the Bbb on the right instead of the left, as it is pictured in the Wiki link, then I discovered by creating a custom key signature with MuseScore and exporting... MusicXML can specify it like this:

<key>
          <key-step>E</key-step>
          <key-alter>-1</key-alter>
          <key-accidental>flat</key-accidental>
          <key-step>A</key-step>
          <key-alter>-1</key-alter>
          <key-accidental>flat</key-accidental>
          <key-step>D</key-step>
          <key-alter>-1</key-alter>
          <key-accidental>flat</key-accidental>
          <key-step>G</key-step>
          <key-alter>-1</key-alter>
          <key-accidental>flat</key-accidental>
          <key-step>D</key-step>
          <key-alter>-1</key-alter>
          <key-accidental>flat</key-accidental>
          <key-step>F</key-step>
          <key-alter>-1</key-alter>
          <key-accidental>flat</key-accidental>
          <key-step>B</key-step>
          <key-alter>-2</key-alter>
          <key-accidental>flat-flat</key-accidental>
</key>

Conclusion

I think the best way to represent Db Minor semantically in MusicXML is probably like this (which can be done using mx::api.):

        <key>
          <fifths>-8</fifths>
          <mode>minor</mode>
        </key>

But if you want to represent it the other way (key-alter, key-accidental) then we will have to come up with a solution either by adding this to mx::api or otherwise.

@p-groarke
Copy link
Contributor Author

p-groarke commented Jan 26, 2020

Thanks for the research! I did try using the -8 value previously. I use musescore and it doesn't display the correct key signature (you can see no Bbb in your screenshot). I thought the problem was with Mx/musicxml, but it seems to be musescore after all. Reading the musicxml manual doesn't specify the min/max of that element.

In musescore, if you create a custom key for d flat minor and save to music xml, you'll get this output. Which is what I believe the core apis can do.

        <key>
          <key-step>E</key-step>
          <key-alter>-1</key-alter>
          <key-accidental>flat</key-accidental>
          <key-step>A</key-step>
          <key-alter>-1</key-alter>
          <key-accidental>flat</key-accidental>
          <key-step>D</key-step>
          <key-alter>-1</key-alter>
          <key-accidental>flat</key-accidental>
          <key-step>G</key-step>
          <key-alter>-1</key-alter>
          <key-accidental>flat</key-accidental>
          <key-step>C</key-step>
          <key-alter>-1</key-alter>
          <key-accidental>flat</key-accidental>
          <key-step>F</key-step>
          <key-alter>-1</key-alter>
          <key-accidental>flat</key-accidental>
          <key-step>B</key-step>
          <key-alter>-2</key-alter>
          <key-accidental>flat-flat</key-accidental>
          </key>

(The order is wrong, but it's "good enough").

I also think the best solution is to use <fifths> element. I'll send a feature request to musescore for it, but I doubt it'll be supported anytime soon.

In how this applies to Mx, if I can get the mx::core DocumentPtr like you mention in issue #45, than I'm all good. I have no issue doing the conversion from -8 to NonTraditionalKey myself before serializing. Of course, if you feel like adding custom key support to mx::api, I won't complain ;)

Cheers.

edit : I can't post a feature request for it since you need a paying subscription to do so.

@webern
Copy link
Owner

webern commented Jan 26, 2020

BTW, it is possible to poke into the mx::core data structure with this;
#45 (comment)

@p-groarke
Copy link
Contributor Author

Perfect, I'll let you know if I hit any roadblocks with it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants