-
Notifications
You must be signed in to change notification settings - Fork 35
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
Add NonTraditional support to KeyData. #77
Conversation
@@ -38,7 +38,7 @@ file(GLOB_RECURSE SRC_MX_TEST_UTILITY ${PRIVATE_DIR}/mxtest/utility/*.cpp ${PRIV | |||
file(GLOB_RECURSE SRC_CPUL ${PRIVATE_DIR}/cpul/*.cpp ${SOURCE}/cpul/*.h) | |||
|
|||
# Mx Library | |||
add_library(${PROJECT_NAME} STATIC ${SRC_MX_API} ${SRC_MX_CORE} ${SRC_MX_IMPL} ${SRC_MX_PUGIXML} ${SRC_MX_UTILITY}) | |||
add_library(${PROJECT_NAME} STATIC ${HEADERS_MX_API} ${SRC_MX_API} ${SRC_MX_CORE} ${SRC_MX_IMPL} ${SRC_MX_PUGIXML} ${SRC_MX_UTILITY}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the headers show up in IDE. Makes it much easier to navigate for new devs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will probably conflict when #79 lands but just reapply this change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good, I'll rebase once everything is settled for the cmake stuff.
@@ -103,6 +103,7 @@ if(MX_BUILD_TESTS) | |||
target_link_libraries(MxTest ${PROJECT_NAME}) | |||
target_link_libraries(MxTest ${CMAKE_THREAD_LIBS_INIT}) | |||
set_property(TARGET MxTest PROPERTY CXX_STANDARD 14) | |||
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT MxTest) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes MxTest the default target in MSVC.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
bool nonTraditionalKey; | ||
// The non-tradional accidentals. | ||
// Fill this with your custom accidentals and alters. | ||
std::vector<PitchData> nonTraditionalPitchData; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe create a new "Data" struct. "NonTraditionalData"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had started, or maybe completed this here https://github.com/webern/mx/master/develop...feature/custom-key-signatures
As a reference to how I was thinking about it. Or you could check it out, kick the tires. The main difference is...
Maybe create a new "Data" struct. "NonTraditionalData"?
Yes, I think that would be better than using PitchData.
Some xsd for reference:
<xs:complexType name="key">
<xs:annotation>
<xs:documentation>The key type represents a key signature. Both traditional and non-traditional key signatures are supported. The optional number attribute refers to staff numbers. If absent, the key signature applies to all staves in the part. Key signatures appear at the start of each system unless the print-object attribute has been set to "no".</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:choice>
<xs:group ref="traditional-key"/>
<xs:group ref="non-traditional-key" minOccurs="0" maxOccurs="unbounded"/>
</xs:choice>
<xs:element name="key-octave" type="key-octave" minOccurs="0" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>The optional list of key-octave elements is used to specify in which octave each element of the key signature appears.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
<xs:attribute name="number" type="staff-number"/>
<xs:attributeGroup ref="print-style"/>
<xs:attributeGroup ref="print-object"/>
</xs:complexType>
<xs:group name="non-traditional-key">
<xs:annotation>
<xs:documentation>The non-traditional-key group represents a single alteration within a non-traditional key signature. A sequence of these groups makes up a non-traditional key signature</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="key-step" type="step">
<xs:annotation>
<xs:documentation>Non-traditional key signatures can be represented using the Humdrum/Scot concept of a list of altered tones. The key-step element indicates the pitch step to be altered, represented using the same names as in the step element.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="key-alter" type="semitones">
<xs:annotation>
<xs:documentation>Non-traditional key signatures can be represented using the Humdrum/Scot concept of a list of altered tones. The key-alter element represents the alteration for a given pitch step, represented with semitones in the same manner as the alter element.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="key-accidental" type="accidental-value" minOccurs="0">
<xs:annotation>
<xs:documentation>Non-traditional key signatures can be represented using the Humdrum/Scot concept of a list of altered tones. The key-accidental element indicates the accidental to be displayed in the key signature, represented in the same manner as the accidental element. It is used for disambiguating microtonal accidentals.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:group>
g = 4, | ||
a = 5, | ||
b = 6, | ||
count, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fine, whatever. :)
@@ -109,6 +113,7 @@ namespace mx | |||
PropertiesWriter::PropertiesWriter( const core::PartwiseMeasurePtr& inPartwiseMeasure ) | |||
: myProperties{ nullptr } | |||
, myPartwiseMeasure{ inPartwiseMeasure } | |||
, myConverter{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added converter because its nice.
core::NonTraditionalKeyPtr k = core::makeNonTraditionalKey(); | ||
if (p.step == api::Step::count || p.step == api::Step::unspecified) | ||
{ | ||
// Would you prefer throw? assert? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what is your standard in terms of "bad things reporting". Continue, throw, assert, format c:/ ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think just silently fall back to Step::c
. If I remember right I only use exceptions/assertions for bugs in the library, not for bad input.
} | ||
|
||
if (p.alter != 0) { | ||
k->setKeyAlter(std::make_shared<core::KeyAlter>(core::Semitones{ double(p.alter) })); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Drops support for float semitones :/ Maybe should use doubles in "NonTraditionalData"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And by using a custom data struct instead of pitchdata, I'll use a double so it doesn't conflict.
myProperties->addKey( key ); | ||
} | ||
|
||
|
||
void PropertiesWriter::writeTime( const api::TimeSignatureData& value ) | ||
void PropertiesWriter::writeTime(const api::TimeSignatureData& value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oops
@@ -91,8 +91,19 @@ namespace mxtest | |||
measure->timeSignature.beatType = 4; | |||
measure->timeSignature.isImplicit = true; | |||
measure->staves.emplace_back( StaffData{} ); | |||
measure->keys.emplace_back( KeyData{} ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I tried adding a test. But this doesn't do anything. I found 2 test files which test KeyData
, this and ApiLy43eScoreData. I don't get what this tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just add a new test for this api/KeyDataTest.cpp
.
A lot of the really funky names you see in the tests are related to specific test files. ApiLy43eScoreData is probably related to a test file by that name from the Lilypond MusicXML test suite.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good job figuring out how things work!
const auto coreMode = traditionalKey.getMode()->getValue().getValue(); | ||
if( coreMode == core::ModeEnum::major ) | ||
|
||
if (keyType == core::KeyChoice::Choice::traditionalKey) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (keyType == core::KeyChoice::Choice::traditionalKey) { | |
if( keyType == core::KeyChoice::Choice::traditionalKey ) | |
{ |
Just a note on the existing style, for better or worse.
keyData.mode = api::KeyMode::unsupported; | ||
api::PitchData p; | ||
p.step = myConverter.convert(k->getKeyStep()->getValue()); | ||
p.alter = int(k->getKeyAlter()->getValue().getValue()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Microtones will need to be handled in semitones (int) and cents (double).
core::NonTraditionalKeyPtr k = core::makeNonTraditionalKey(); | ||
if (p.step == api::Step::count || p.step == api::Step::unspecified) | ||
{ | ||
// Would you prefer throw? assert? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think just silently fall back to Step::c
. If I remember right I only use exceptions/assertions for bugs in the library, not for bad input.
@@ -91,8 +91,19 @@ namespace mxtest | |||
measure->timeSignature.beatType = 4; | |||
measure->timeSignature.isImplicit = true; | |||
measure->staves.emplace_back( StaffData{} ); | |||
measure->keys.emplace_back( KeyData{} ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just add a new test for this api/KeyDataTest.cpp
.
A lot of the really funky names you see in the tests are related to specific test files. ApiLy43eScoreData is probably related to a test file by that name from the Lilypond MusicXML test suite.
} | ||
|
||
if (p.alter != 0) { | ||
k->setKeyAlter(std::make_shared<core::KeyAlter>(core::Semitones{ double(p.alter) })); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -103,6 +103,7 @@ if(MX_BUILD_TESTS) | |||
target_link_libraries(MxTest ${PROJECT_NAME}) | |||
target_link_libraries(MxTest ${CMAKE_THREAD_LIBS_INIT}) | |||
set_property(TARGET MxTest PROPERTY CXX_STANDARD 14) | |||
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT MxTest) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
closed, fixed by #81 |
Fixes #70
As far as I could tell, this should be enough to support non-traditional keys in
api
.However, I couldn't for the life of me figure out your unit test framework :) Could you explain to me how to add some tests for this? ty
Of note
PitchData
. Maybe you'd rather I add a new "Data" type which only contains step, alter and accidental?NonTraditionalData
maybe?