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

Add NonTraditional support to KeyData. #77

Closed
wants to merge 1 commit into from
Closed

Add NonTraditional support to KeyData. #77

wants to merge 1 commit into from

Conversation

p-groarke
Copy link
Contributor

@p-groarke p-groarke commented Mar 28, 2020

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

  • Using a vector of PitchData. Maybe you'd rather I add a new "Data" type which only contains step, alter and accidental? NonTraditionalData maybe?
  • Minor tweaks to cmake.
  • No tests yet! PR will stay Draft until I can add some good tests.

@@ -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})
Copy link
Contributor Author

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.

Copy link
Owner

@webern webern Mar 29, 2020

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.

Copy link
Contributor Author

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)
Copy link
Contributor Author

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.

Copy link
Owner

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;
Copy link
Contributor Author

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"?

Copy link
Owner

@webern webern Mar 29, 2020

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,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:)

Copy link
Owner

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{}
Copy link
Contributor Author

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?
Copy link
Contributor Author

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:/ ?

Copy link
Owner

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) }));
Copy link
Contributor Author

@p-groarke p-groarke Mar 28, 2020

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"?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to adapt the int alter and double cents pattern wherever we convert to/from alter double. See #50
Probably what we should do is move the calculations that I did in #50 to the MxConverter thing and use it in both places.

Copy link
Contributor Author

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)
Copy link
Contributor Author

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{} );
Copy link
Contributor Author

@p-groarke p-groarke Mar 28, 2020

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.

Copy link
Owner

@webern webern Mar 29, 2020

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.

Copy link
Owner

@webern webern left a 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) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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());
Copy link
Owner

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?
Copy link
Owner

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{} );
Copy link
Owner

@webern webern Mar 29, 2020

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) }));
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to adapt the int alter and double cents pattern wherever we convert to/from alter double. See #50
Probably what we should do is move the calculations that I did in #50 to the MxConverter thing and use it in both places.

@@ -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)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@p-groarke
Copy link
Contributor Author

closed, fixed by #81

@p-groarke p-groarke closed this Apr 4, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[feature] mx::api NonTraditionalKey equivalent
2 participants