Git Product home page Git Product logo

Comments (9)

webern avatar webern commented on June 21, 2024

That feature has not been added to the mx::api structs. It should be easy to add it. As a workaround, it is also possible to obtain the mx::core representation and manipulate it.

mx::core::DocumentPtr getDocument( int documentId ) const;

This requires using the 'private' includes, e.g. #include "mx/core/Document.h" and dealing with the unwieldy interface to the elements themselves.

I will add this feature to mx::api as soon as possible (unfortunately that might be 2-3 weeks from now due to some circumstances). You can try adding it to mx::api before then if you wish. I should be able to respond within 24-hours to questions.

from mx.

TassieBruce avatar TassieBruce commented on June 21, 2024

I will have a go at seeing if I can add it to mx::api but it will take me a while to get my head around the mx::core stuff. After a preliminary look, it looks like I'd have to do something similar to how divisions is handled. Will probably have real questions later.

from mx.

webern avatar webern commented on June 21, 2024

I started looking at this and wrote the following thinking that transposition would be an attribute of a Part

A new struct, e.g. TranspositionData added to this file before PartData:

An optional instance of that struct added to PartData, e.g. std::optional<TranspositionData> transposition.

There's a macro pattern to remember: https://github.com/webern/mx/blob/03a9b3254b853c04fb069cacc79281800215a0d4/Sourcecode/include/mx/api/PartData.h#L169..L210

During 'serialization', functionality has to be added to PartWriter.cpp to 'serialize' the mx::api version into mx::core version, probably in this function:

core::ScorePartPtr PartWriter::getScorePart() const

During deserialization, functionality has to be added to

api::PartData PartReader::getPartData()

However, not as simple as that

Your original statement says that transposition exists in the attributes of the first measure. Uh oh, this is more complicated. If mx::api should support the changing of transpositions in arbitrary locations throughout the music, then it adds more complexity to mx::api than I like. i.e. if mx::api supported all features of MusicXML then it would just be MusicXML and not an 'API'!

Anyway, if we stick with the idea of placing the transposition in the part, such that one can only specify the transposition once, at the beginning, then we could still create the struct and add it to PartData.h like I suggested above, but we would need to write it to the first measure of music, and detect it in the first measure of music instead of what I showed above.

There are precedents for this, anyway it will be these files:

MeasureReader::MeasureReader( const core::PartwiseMeasure& inPartwiseMeasureRef, const MeasureCursor& cursor, const MeasureCursor& previousMeasureCursor )

MeasureWriter::MeasureWriter( const api::MeasureData& inMeasureData, const MeasureCursor& inCursor, const ScoreWriter& inScoreWriter )

Unfortunately much of the code in mx::impl is really stupidly written and painful for me to look at... I mean it works, but this was one of my first projects. Anyway, I hope these links help a little.

Testing

If we go with putting this in PartData.h then probably clone a test file, e.g. https://github.com/webern/mx/blob/master/Sourcecode/private/mxtest/api/DirectionDataTest.cpp and name the copy of it PartDataTest.cpp as the starting point.

from mx.

TassieBruce avatar TassieBruce commented on June 21, 2024

My only experience of musicxml is as something that can be read and written by musescore (i.e., I am definitely no expert on the intricacies of musicxml!). In musescore, each staff is a part in partwise musicxml and has an associated instrument, e.g., Flute, Clarinet, Trumpet, etc. Part of the details of each instrument includes its transposition. When the score is exported to musicxml, some of the instrument information ends up in the <part-list> specification (in <part-name>, <score-instrument>, <midi-instrument>, etc.) but the transposition information ends up as a <transpose> element in the <attributes> of the first <measure> of the <part>.

I don't know if there is any other valid use case where there could be a <transpose> later in a <part> (oops! seems like there is - see below). The description of <transpose> at https://usermanuals.musicxml.com/MusicXML/Content/EL-MusicXML-transpose.htm says

If the part is being encoded for a transposing instrument in written vs. concert pitch, the transposition must be encoded in the transpose element using the transpose type.

which makes it sound like it is envisaged to be used as part of the description of the instrument that should be the same for the entire part. In a saner world, maybe <transpose> should have been part of the instrument description in <part-list>.

But, to counter that view, the description of the <semitones> element of <transpose> at https://usermanuals.musicxml.com/MusicXML/Content/EL-MusicXML-chromatic.htm has an example where transposition changes mid-part.

The question is, do you want mx::api to accommodate such uses?

I would argue not to. As it is, mx::api::PartData holds an InstrumentData attribute. To me, this implies that the entire part represents a particular instrument (as does the presence of <score-instrument> etc., in <part-list>). Part of the description of that instrument should surely be its transposition.

Rather than create a new struct TranspositionData, why not just add an int chromaticTranspose attribute to the InstrumentData struct? The <chromatic> element is then chromaticTranspose % 12 while <octave-change> is chromaticTranspose / 12. I am not a musician so don't really understand the significance of the <diatonic> element. Can it be computed from <chromatic>?

The situation seems similar to <divisions>. Does mx::api allow changing <divisions> in the middle of a score or is it always set in the first measure of each part from the ScoreData.ticksPerQuarter?

from mx.

webern avatar webern commented on June 21, 2024

I would argue not to. As it is, mx::api::PartData holds an InstrumentData attribute. To me, this implies that the entire part represents a particular instrument (as does the presence of etc., in ). Part of the description of that instrument should surely be its transposition.

I agree, if someone needs to change transposition later in a piece, then a different feature could be added for that more advanced use-case.

The example you provided

<transpose>
  <diatonic>-1</diatonic>
  <chromatic>-2</chromatic>
</transpose>

Does seem non-ambiguous, but I'm thinking there are probably some ambiguous cases where the ability to set both diatonic and chromatic might be necessary. I asked a question about it just now: w3c/musicxml#333

from mx.

TassieBruce avatar TassieBruce commented on June 21, 2024

My problem is I don't know much musical theory and assume all one needs to know about music is that frequency is proportional to 2**(n/12)!

The purpose of <transpose> is to define the interval from written pitch to sounding pitch and is usually expressed as the note that sounds when a C4 is written. Hence a Bb clarinet, etc.

I gather the <diatonic> term part of <transpose> is the change in the base note name ignoring sharps or flats. So C to F# has diatonic=3 while C to Gb has diatonic=4 but both have chromatic=6. But if I look at Wikipedia's list of transposing instruments https://en.wikipedia.org/wiki/List_of_transposing_instruments I notice that, where necessary, the sound of written C4 is always expressed as a flat, never a sharp. I assume this is some sort of convention.

So, if we associate int chromaticTranspose with an instrument, then on reading we set chromaticTranspose from the <chromatic> element (and <octave-change> if present) and ignore <diatonic> while on writing we lookup <diatonic> from chromaticTranspose using a table like

Note C Db D Eb E F Gb G Ab A Bb B
Chromatic 0 1 2 3 4 5 6 7 8 9 10 11
Diatonic 0 1 1 2 2 3 4 4 5 5 6 6

from mx.

TassieBruce avatar TassieBruce commented on June 21, 2024

I think I've changed my mind. Mostly because of this quote from wikipedia

The transposition is not a property of the instrument, but rather a convention of musical notation. Instruments whose music is typically notated in this way are called transposing instruments.

This makes sense with the way musicxml places <transpose> in the <attributes> of a <measure>. So I'm creating a new type TransposeData used in a similar way as the keys attribute of MeasureData that should handle a <transpose> wherever it occurs.

from mx.

webern avatar webern commented on June 21, 2024

Yeah that's fine. I think it's disappointing for the user to have to interact with transposition in that way (when the most common use-case is to set it once at the beginning of the piece when setting the instrument), but your approach will work and will support additional use cases.

from mx.

webern avatar webern commented on June 21, 2024

I've started working on this. Let me know if you want me to get it done or if you want to collaborate in some way...

from mx.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.