Actualized MPE tests

This commit is contained in:
vpereverzev 2021-12-27 13:46:46 +02:00 committed by pereverzev+v
parent e09337b712
commit 7fa60baa58
3 changed files with 140 additions and 74 deletions

View file

@ -9,9 +9,9 @@
<file>qml/MuseScore/Mpe/ArticulationPatternsTab.qml</file>
<file>qml/MuseScore/Mpe/ArticulationPatternsList.qml</file>
<file>qml/MuseScore/Mpe/ArticulationPatternSegmentsList.qml</file>
<file>resources/general_keyboard_articulations_profile.json</file>
<file>resources/general_strings_articulations_profile.json</file>
<file>resources/general_winds_articulations_profile.json</file>
<file>resources/general_percussion_articulations_profile.json</file>
<file alias="mpe/general_keyboard_articulations_profile.json">resources/general_keyboard_articulations_profile.json</file>
<file alias="mpe/general_strings_articulations_profile.json">resources/general_strings_articulations_profile.json</file>
<file alias="mpe/general_winds_articulations_profile.json">resources/general_winds_articulations_profile.json</file>
<file alias="mpe/general_percussion_articulations_profile.json">resources/general_percussion_articulations_profile.json</file>
</qresource>
</RCC>

View file

@ -40,8 +40,7 @@ protected:
firstNoteData.nominalTimestamp = 0;
firstNoteData.nominalDuration = 500;
firstNoteData.voiceIdx = 0; // first voice
firstNoteData.pitchClass = PitchClass::A;
firstNoteData.octave = 3;
firstNoteData.nominalPitchLevel = pitchLevel(PitchClass::A, 3);
firstNoteData.nominalDynamicLevel = dynamicLevelFromType(DynamicType::f);
// [GIVEN] Rendering data of the second quarter note on the score, with the 120BPM tempo and 4/4 time signature
@ -49,8 +48,7 @@ protected:
secondNoteData.nominalTimestamp = 500;
secondNoteData.nominalDuration = 500;
secondNoteData.voiceIdx = 0; // first voice
secondNoteData.pitchClass = PitchClass::C;
secondNoteData.octave = 4;
secondNoteData.nominalPitchLevel = pitchLevel(PitchClass::C, 4);
secondNoteData.nominalDynamicLevel = dynamicLevelFromType(DynamicType::f);
// [GIVEN] Rendering data of the second quarter note on the score, with the 120BPM tempo and 4/4 time signature
@ -58,8 +56,7 @@ protected:
thirdNoteData.nominalTimestamp = 1000;
thirdNoteData.nominalDuration = 500;
thirdNoteData.voiceIdx = 0; // first voice
thirdNoteData.pitchClass = PitchClass::A;
thirdNoteData.octave = 3;
thirdNoteData.nominalPitchLevel = pitchLevel(PitchClass::A, 3);
thirdNoteData.nominalDynamicLevel = dynamicLevelFromType(DynamicType::f);
// [GIVEN] Rendering data of the second quarter note on the score, with the 120BPM tempo and 4/4 time signature
@ -67,8 +64,7 @@ protected:
fourthNoteData.nominalTimestamp = 1500;
fourthNoteData.nominalDuration = 500;
fourthNoteData.voiceIdx = 0; // first voice
fourthNoteData.pitchClass = PitchClass::C;
fourthNoteData.octave = 4;
fourthNoteData.nominalPitchLevel = pitchLevel(PitchClass::C, 4);
fourthNoteData.nominalDynamicLevel = dynamicLevelFromType(DynamicType::f);
// [GIVEN] Articulation pattern "Standard", which means that note should be played without any modifications
@ -82,8 +78,7 @@ protected:
duration_t nominalDuration = 0;
voice_layer_idx_t voiceIdx = 0;
PitchClass pitchClass = PitchClass::Undefined;
octave_t octave = 0;
pitch_level_t nominalPitchLevel = 0;
dynamic_level_t nominalDynamicLevel = 0;
};
@ -102,13 +97,19 @@ protected:
TEST_F(MultiNoteArticulationsTest, StandardPattern)
{
// [GIVEN] No articulations applied on the top of the note
ArticulationPattern scope;
scope.emplace(0, m_standardPattern);
ArticulationPattern pattern;
pattern.emplace(0, m_standardPattern);
ArticulationData standardArticulationApplied(ArticulationType::Standard, scope, 0, HUNDRED_PERCENTS);
ArticulationMeta meta;
meta.type = ArticulationType::Standard;
meta.pattern = std::move(pattern);
meta.timestamp = m_initialData.at(0).nominalTimestamp;
meta.overallDuration = m_initialData.at(0).nominalDuration;
ArticulationAppliedData standardArticulationApplied(std::move(meta), 0, HUNDRED_PERCENTS);
ArticulationMap appliedArticulations;
appliedArticulations.emplace(ArticulationType::Standard, standardArticulationApplied);
appliedArticulations.emplace(ArticulationType::Standard, std::move(standardArticulationApplied));
// [WHEN] Notes sequence with given parameters being built
std::map<size_t, NoteEvent> noteEvents;
@ -117,8 +118,7 @@ TEST_F(MultiNoteArticulationsTest, StandardPattern)
NoteEvent noteEvent(pair.second.nominalTimestamp,
pair.second.nominalDuration,
pair.second.voiceIdx,
pair.second.pitchClass,
pair.second.octave,
pair.second.nominalPitchLevel,
pair.second.nominalDynamicLevel,
appliedArticulations);
@ -156,8 +156,7 @@ TEST_F(MultiNoteArticulationsTest, GlissandoPattern)
// [GIVEN] Articulation pattern "Glissando", which instructs a performer to start on the pitch/rhythm
// and slide the pitch up/down to land on the next pitch/rhythm
pitch_level_t pitchDiff = pitchLevelDiff(m_initialData[0].pitchClass, m_initialData[0].octave,
m_initialData[1].pitchClass, m_initialData[1].octave);
pitch_level_t pitchDiff = m_initialData[0].nominalPitchLevel - m_initialData[1].nominalPitchLevel;
ArticulationPatternSegment glissandoPattern;
glissandoPattern.arrangementPattern = createArrangementPattern(HUNDRED_PERCENTS /*duration_factor*/, 0 /*timestamp_offset*/);
@ -168,24 +167,42 @@ TEST_F(MultiNoteArticulationsTest, GlissandoPattern)
ArticulationPattern glissandoScope;
glissandoScope.emplace(0, glissandoPattern);
ArticulationMeta glissandoMeta;
glissandoMeta.type = ArticulationType::DiscreteGlissando;
glissandoMeta.pattern = glissandoScope;
glissandoMeta.timestamp = m_initialData.at(0).nominalTimestamp;
glissandoMeta.overallDuration = m_initialData.at(0).nominalDuration + m_initialData.at(1).nominalDuration;
ArticulationPattern standardScope;
standardScope.emplace(0, m_standardPattern);
ArticulationMeta thirdNoteStandardMeta;
thirdNoteStandardMeta.type = ArticulationType::Standard;
thirdNoteStandardMeta.pattern = standardScope;
thirdNoteStandardMeta.timestamp = m_initialData.at(2).nominalTimestamp;
thirdNoteStandardMeta.overallDuration = m_initialData.at(0).nominalDuration;
ArticulationMeta fourthNoteStandardMeta;
fourthNoteStandardMeta.type = ArticulationType::Standard;
fourthNoteStandardMeta.pattern = standardScope;
fourthNoteStandardMeta.timestamp = m_initialData.at(3).nominalTimestamp;
fourthNoteStandardMeta.overallDuration = m_initialData.at(0).nominalDuration;
// [GIVEN] Glissando articulation applied on the first note, occupied range is from 0% to 50% of the entire articulation range
ArticulationData glissandoAppliedOnTheFirstNote(ArticulationType::Glissando, glissandoScope, 0, 5 * TEN_PERCENTS);
appliedArticulations[0].emplace(ArticulationType::Glissando, glissandoAppliedOnTheFirstNote);
ArticulationAppliedData glissandoAppliedOnTheFirstNote(glissandoMeta, 0, 5 * TEN_PERCENTS);
appliedArticulations[0].emplace(ArticulationType::DiscreteGlissando, std::move(glissandoAppliedOnTheFirstNote));
// [GIVEN] Glissando articulation applied on the second note, occupied range is from 50% to 100% of the entire articulation range
ArticulationData glissandoAppliedOnTheSecondNote(ArticulationType::Glissando, glissandoScope, 50, HUNDRED_PERCENTS);
appliedArticulations[1].emplace(ArticulationType::Glissando, glissandoAppliedOnTheSecondNote);
ArticulationAppliedData glissandoAppliedOnTheSecondNote(glissandoMeta, 50, HUNDRED_PERCENTS);
appliedArticulations[1].emplace(ArticulationType::DiscreteGlissando, std::move(glissandoAppliedOnTheSecondNote));
// [GIVEN] No articulations applied on the third note, occupied range is from 0% to 100% of the entire articulation range
ArticulationData thirdNoteStandardArticulation(ArticulationType::Standard, standardScope, 0, HUNDRED_PERCENTS);
appliedArticulations[2].emplace(ArticulationType::Standard, thirdNoteStandardArticulation);
ArticulationAppliedData thirdNoteStandardArticulation(thirdNoteStandardMeta, 0, HUNDRED_PERCENTS);
appliedArticulations[2].emplace(ArticulationType::Standard, std::move(thirdNoteStandardArticulation));
// [GIVEN] No articulations applied on the third note, occupied range is from 0% to 100% of the entire articulation range
ArticulationData fourthNoteStandardArticulation(ArticulationType::Standard, standardScope, 0, HUNDRED_PERCENTS);
appliedArticulations[3].emplace(ArticulationType::Standard, thirdNoteStandardArticulation);
ArticulationAppliedData fourthNoteStandardArticulation(fourthNoteStandardMeta, 0, HUNDRED_PERCENTS);
appliedArticulations[3].emplace(ArticulationType::Standard, std::move(fourthNoteStandardArticulation));
// [WHEN] Notes sequence with given parameters being built
std::map<size_t, NoteEvent> noteEvents;
@ -194,8 +211,7 @@ TEST_F(MultiNoteArticulationsTest, GlissandoPattern)
NoteEvent noteEvent(pair.second.nominalTimestamp,
pair.second.nominalDuration,
pair.second.voiceIdx,
pair.second.pitchClass,
pair.second.octave,
pair.second.nominalPitchLevel,
pair.second.nominalDynamicLevel,
appliedArticulations[pair.first]);
@ -252,11 +268,21 @@ TEST_F(MultiNoteArticulationsTest, CrescendoPattern)
crescendoScope.emplace(25 * ONE_PERCENT * static_cast<int>(i), std::move(crescendoPattern));
}
ArticulationMeta crescendoMeta;
crescendoMeta.type = ArticulationType::DiscreteGlissando;
crescendoMeta.pattern = crescendoScope;
crescendoMeta.timestamp = m_initialData.at(0).nominalTimestamp;
crescendoMeta.overallDuration = m_initialData.at(1).nominalTimestamp + m_initialData.at(1).nominalDuration;
crescendoMeta.overallDynamicChangesRange = dynamicLevelDiff;
for (const auto& pair : m_initialData) {
crescendoMeta.overallDuration += pair.second.nominalDuration;
}
for (size_t i = 0; i < noteCount; ++i) {
// [GIVEN] Crescendo articulation applied on the note
ArticulationData crescendoApplied(ArticulationType::Crescendo, crescendoScope, 25 * ONE_PERCENT * static_cast<int>(i),
25 * ONE_PERCENT * (static_cast<int>(i) + 1), 0, dynamicLevelDiff);
appliedArticulations[i].emplace(ArticulationType::Crescendo, crescendoApplied);
ArticulationAppliedData crescendoApplied(crescendoMeta, 25 * ONE_PERCENT * i, 25 * ONE_PERCENT * (i + 1));
appliedArticulations[i].emplace(ArticulationType::Crescendo, std::move(crescendoApplied));
}
// [WHEN] Notes sequence with given parameters being built
@ -266,8 +292,7 @@ TEST_F(MultiNoteArticulationsTest, CrescendoPattern)
NoteEvent noteEvent(pair.second.nominalTimestamp,
pair.second.nominalDuration,
pair.second.voiceIdx,
pair.second.pitchClass,
pair.second.octave,
pair.second.nominalPitchLevel,
pair.second.nominalDynamicLevel,
appliedArticulations[pair.first]);

View file

@ -75,19 +75,24 @@ TEST_F(SingleNoteArticulationsTest, StandardPattern)
ArticulationPattern scope;
scope.emplace(0, m_standardPattern);
ArticulationData standardArticulationApplied(ArticulationType::Standard, scope, 0, HUNDRED_PERCENTS);
ArticulationMeta standardMeta;
standardMeta.type = ArticulationType::Staccato;
standardMeta.pattern = scope;
standardMeta.timestamp = m_nominalTimestamp;
standardMeta.overallDuration = m_nominalDuration;
ArticulationAppliedData standardArticulationApplied(std::move(standardMeta), 0, HUNDRED_PERCENTS);
ArticulationMap appliedArticulations;
appliedArticulations.emplace(ArticulationType::Standard, standardArticulationApplied);
appliedArticulations.emplace(ArticulationType::Standard, std::move(standardArticulationApplied));
// [WHEN] Note event with given parameters being built
NoteEvent event(m_nominalTimestamp,
m_nominalDuration,
m_voiceIdx,
m_pitchClass,
m_octave,
pitchLevel(m_pitchClass, m_octave),
m_nominalDynamic,
appliedArticulations);
std::move(appliedArticulations));
// [THEN] We expect that expression curve will be using default curve from standard patterns
EXPECT_EQ(event.expressionCtx().expressionCurve,
@ -118,19 +123,24 @@ TEST_F(SingleNoteArticulationsTest, StaccatoPattern)
// [GIVEN] Staccato articulation applied on the note, since staccato is a single-note articulation
// occupied range is from 0% to 100%
ArticulationData staccatoApplied(ArticulationType::Staccato, scope, 0, HUNDRED_PERCENTS);
ArticulationMeta staccatoMeta;
staccatoMeta.type = ArticulationType::Staccato;
staccatoMeta.pattern = scope;
staccatoMeta.timestamp = m_nominalTimestamp;
staccatoMeta.overallDuration = m_nominalDuration;
ArticulationAppliedData staccatoApplied(std::move(staccatoMeta), 0, HUNDRED_PERCENTS);
ArticulationMap appliedArticulations = {};
appliedArticulations.emplace(ArticulationType::Staccato, staccatoApplied);
appliedArticulations.emplace(ArticulationType::Staccato, std::move(staccatoApplied));
// [WHEN] Note event with given parameters being built
NoteEvent event(m_nominalTimestamp,
m_nominalDuration,
m_voiceIdx,
m_pitchClass,
m_octave,
pitchLevel(m_pitchClass, m_octave),
m_nominalDynamic,
appliedArticulations);
std::move(appliedArticulations));
// [THEN] We expect the nominal duration of a note to be unchanged
EXPECT_EQ(event.arrangementCtx().nominalDuration, m_nominalDuration);
@ -158,19 +168,24 @@ TEST_F(SingleNoteArticulationsTest, AccentPattern)
// [GIVEN] Staccato articulation applied on the note, since staccato is a single-note articulation
// occupied range is from 0% to 100%
ArticulationData accentApplied(ArticulationType::Accent, scope, 0, HUNDRED_PERCENTS);
ArticulationMeta accentMeta;
accentMeta.type = ArticulationType::Accent;
accentMeta.pattern = scope;
accentMeta.timestamp = m_nominalTimestamp;
accentMeta.overallDuration = m_nominalDuration;
ArticulationAppliedData accentApplied(std::move(accentMeta), 0, HUNDRED_PERCENTS);
ArticulationMap appliedArticulations = {};
appliedArticulations.emplace(ArticulationType::Accent, accentApplied);
appliedArticulations.emplace(ArticulationType::Accent, std::move(accentApplied));
// [WHEN] Note event with given parameters being built
NoteEvent event(m_nominalTimestamp,
m_nominalDuration,
m_voiceIdx,
m_pitchClass,
m_octave,
pitchLevel(m_pitchClass, m_octave),
m_nominalDynamic,
appliedArticulations);
std::move(appliedArticulations));
// [THEN] We expect the nominal duration of a note to be unchanged,
// since accent doesn't affect any arrangement data
@ -207,19 +222,24 @@ TEST_F(SingleNoteArticulationsTest, AccentPattern_Nominal_MezzoForte)
// [GIVEN] Staccato articulation applied on the note, since staccato is a single-note articulation
// occupied range is from 0% to 100%
ArticulationData accentApplied(ArticulationType::Accent, scope, 0, HUNDRED_PERCENTS);
ArticulationMeta accentMeta;
accentMeta.type = ArticulationType::Accent;
accentMeta.pattern = scope;
accentMeta.timestamp = m_nominalTimestamp;
accentMeta.overallDuration = m_nominalDuration;
ArticulationAppliedData accentApplied(std::move(accentMeta), 0, HUNDRED_PERCENTS);
ArticulationMap appliedArticulations = {};
appliedArticulations.emplace(ArticulationType::Accent, accentApplied);
appliedArticulations.emplace(ArticulationType::Accent, std::move(accentApplied));
// [WHEN] Note event with given parameters being built
NoteEvent event(m_nominalTimestamp,
m_nominalDuration,
m_voiceIdx,
m_pitchClass,
m_octave,
pitchLevel(m_pitchClass, m_octave),
m_nominalDynamic,
appliedArticulations);
std::move(appliedArticulations));
// [THEN] We expect the nominal duration of a note to be unchanged,
// since accent doesn't affect any arrangement data
@ -263,21 +283,32 @@ TEST_F(SingleNoteArticulationsTest, PocoTenuto)
// [GIVEN] Staccato articulation applied on the note, since staccato is a single-note articulation
// occupied range is from 0% to 100%
ArticulationData staccatoApplied(ArticulationType::Staccato, staccatoScope, 0, HUNDRED_PERCENTS);
appliedArticulations.emplace(ArticulationType::Staccato, staccatoApplied);
ArticulationMeta staccatoMeta;
staccatoMeta.type = ArticulationType::Staccato;
staccatoMeta.pattern = staccatoScope;
staccatoMeta.timestamp = m_nominalTimestamp;
staccatoMeta.overallDuration = m_nominalDuration;
ArticulationAppliedData staccatoApplied(std::move(staccatoMeta), 0, HUNDRED_PERCENTS);
appliedArticulations.emplace(ArticulationType::Staccato, std::move(staccatoApplied));
ArticulationMeta tenutoMeta;
tenutoMeta.type = ArticulationType::Tenuto;
tenutoMeta.pattern = tenutoScope;
tenutoMeta.timestamp = m_nominalTimestamp;
tenutoMeta.overallDuration = m_nominalDuration;
// [GIVEN] Tenuto articulation applied on the note
ArticulationData tenutoApplied(ArticulationType::Tenuto, tenutoScope, 0, HUNDRED_PERCENTS);
appliedArticulations.emplace(ArticulationType::Tenuto, tenutoApplied);
ArticulationAppliedData tenutoApplied(std::move(tenutoMeta), 0, HUNDRED_PERCENTS);
appliedArticulations.emplace(ArticulationType::Tenuto, std::move(tenutoApplied));
// [WHEN] Note event with given parameters being built
NoteEvent event(m_nominalTimestamp,
m_nominalDuration,
m_voiceIdx,
m_pitchClass,
m_octave,
pitchLevel(m_pitchClass, m_octave),
m_nominalDynamic,
appliedArticulations);
std::move(appliedArticulations));
// [THEN] We expect the nominal duration of a note to be unchanged
EXPECT_EQ(event.arrangementCtx().nominalDuration, m_nominalDuration);
@ -309,19 +340,24 @@ TEST_F(SingleNoteArticulationsTest, QuickFall)
// [GIVEN] Staccato articulation applied on the note, since staccato is a single-note articulation
// occupied range is from 0% to 100%
ArticulationData quickFallApplied(ArticulationType::QuickFall, quickFallScope, 0, HUNDRED_PERCENTS);
ArticulationMeta quickFallMeta;
quickFallMeta.type = ArticulationType::QuickFall;
quickFallMeta.pattern = quickFallScope;
quickFallMeta.timestamp = m_nominalTimestamp;
quickFallMeta.overallDuration = m_nominalDuration;
ArticulationAppliedData quickFallApplied(std::move(quickFallMeta), 0, HUNDRED_PERCENTS);
ArticulationMap appliedArticulations = {};
appliedArticulations.emplace(ArticulationType::QuickFall, quickFallApplied);
appliedArticulations.emplace(ArticulationType::QuickFall, std::move(quickFallApplied));
// [WHEN] Note event with given parameters being built
NoteEvent event(m_nominalTimestamp,
m_nominalDuration,
m_voiceIdx,
m_pitchClass,
m_octave,
pitchLevel(m_pitchClass, m_octave),
m_nominalDynamic,
appliedArticulations);
std::move(appliedArticulations));
// [THEN] We expect the pitch curve of the note marked by quick fall articulation to be equal to the pitch curve from corresponding pattern
EXPECT_EQ(event.pitchCtx().pitchCurve, quickFallPattern.pitchPattern.pitchOffsetMap);
@ -353,19 +389,24 @@ TEST_F(SingleNoteArticulationsTest, Scoop)
// [GIVEN] Staccato articulation applied on the note, since staccato is a single-note articulation
// occupied range is from 0% to 100%
ArticulationData scoopApplied(ArticulationType::Scoop, scope, 0, HUNDRED_PERCENTS);
ArticulationMeta scoopMeta;
scoopMeta.type = ArticulationType::Scoop;
scoopMeta.pattern = scope;
scoopMeta.timestamp = m_nominalTimestamp;
scoopMeta.overallDuration = m_nominalDuration;
ArticulationAppliedData scoopApplied(std::move(scoopMeta), 0, HUNDRED_PERCENTS);
ArticulationMap appliedArticulations = {};
appliedArticulations.emplace(ArticulationType::Scoop, scoopApplied);
appliedArticulations.emplace(ArticulationType::Scoop, std::move(scoopApplied));
// [WHEN] Note event with given parameters being built
NoteEvent event(m_nominalTimestamp,
m_nominalDuration,
m_voiceIdx,
m_pitchClass,
m_octave,
pitchLevel(m_pitchClass, m_octave),
m_nominalDynamic,
appliedArticulations);
std::move(appliedArticulations));
// [THEN] We expect the pitch curve of the note marked by scoop articulation to be equal to the pitch curve from corresponding pattern
EXPECT_EQ(event.pitchCtx().pitchCurve, scoopPattern.pitchPattern.pitchOffsetMap);