diff --git a/modules/juce_audio_basics/mpe/juce_MPEInstrument.cpp b/modules/juce_audio_basics/mpe/juce_MPEInstrument.cpp index fb45807575..df7ff80474 100644 --- a/modules/juce_audio_basics/mpe/juce_MPEInstrument.cpp +++ b/modules/juce_audio_basics/mpe/juce_MPEInstrument.cpp @@ -39,6 +39,9 @@ MPEInstrument::MPEInstrument() noexcept pressureDimension.value = &MPENote::pressure; timbreDimension.value = &MPENote::timbre; + // the default value for pressure is 0, for all other dimension it is centre (= default MPEValue) + std::fill_n (pressureDimension.lastValueReceivedOnChannel, 16, MPEValue::minValue()); + legacyMode.isEnabled = false; legacyMode.pitchbendRange = 2; legacyMode.channelRange = Range (1, 17); @@ -271,22 +274,6 @@ void MPEInstrument::handleTimbreLSB (int midiChannel, int value) noexcept lastTimbreLowerBitReceivedOnChannel[midiChannel - 1] = uint8 (value); } -//============================================================================== -MPEValue MPEInstrument::getInitialPitchbendForNoteOn (int midiChannel, int /*midiNoteNumber*/, MPEValue /*midiNoteOnVelocity*/) const -{ - return pitchbendDimension.lastValueReceivedOnChannel[midiChannel - 1]; -} - -MPEValue MPEInstrument::getInitialPressureForNoteOn (int /*midiChannel*/, int /*midiNoteNumber*/, MPEValue midiNoteOnVelocity) const -{ - return midiNoteOnVelocity; -} - -MPEValue MPEInstrument::getInitialTimbreForNoteOn (int midiChannel, int /*midiNoteNumber*/, MPEValue /*midiNoteOnVelocity*/) const -{ - return timbreDimension.lastValueReceivedOnChannel[midiChannel - 1]; -} - //============================================================================== void MPEInstrument::noteOn (int midiChannel, int midiNoteNumber, @@ -298,9 +285,9 @@ void MPEInstrument::noteOn (int midiChannel, MPENote newNote (midiChannel, midiNoteNumber, midiNoteOnVelocity, - getInitialPitchbendForNoteOn (midiChannel, midiNoteNumber, midiNoteOnVelocity), - getInitialPressureForNoteOn (midiChannel, midiNoteNumber, midiNoteOnVelocity), - getInitialTimbreForNoteOn (midiChannel, midiNoteNumber, midiNoteOnVelocity), + getInitialValueForNewNote (midiChannel, pitchbendDimension), + getInitialValueForNewNote (midiChannel, pressureDimension), + getInitialValueForNewNote (midiChannel, timbreDimension), isNoteChannelSustained[midiChannel - 1] ? MPENote::keyDownAndSustained : MPENote::keyDown); const ScopedLock sl (lock); @@ -334,10 +321,11 @@ void MPEInstrument::noteOff (int midiChannel, note->keyState = (note->keyState == MPENote::keyDownAndSustained) ? MPENote::sustained : MPENote::off; note->noteOffVelocity = midiNoteOffVelocity; - // last pitchbend and timbre values received for this note should not be re-used for + // last dimension values received for this note should not be re-used for // any new notes, so reset them: - pitchbendDimension.lastValueReceivedOnChannel[midiChannel - 1] = MPEValue(); - timbreDimension.lastValueReceivedOnChannel[midiChannel - 1] = MPEValue(); + pressureDimension.lastValueReceivedOnChannel[midiChannel - 1] = MPEValue::minValue(); + pitchbendDimension.lastValueReceivedOnChannel[midiChannel - 1] = MPEValue::centreValue(); + timbreDimension.lastValueReceivedOnChannel[midiChannel - 1] = MPEValue::centreValue(); if (note->keyState == MPENote::off) { @@ -370,6 +358,14 @@ void MPEInstrument::timbre (int midiChannel, MPEValue value) updateDimension (midiChannel, timbreDimension, value); } +MPEValue MPEInstrument::getInitialValueForNewNote (int midiChannel, MPEDimension& dimension) const +{ + if (getLastNotePlayedPtr (midiChannel) != nullptr) + return &dimension == &pressureDimension ? MPEValue::minValue() : MPEValue::centreValue(); + + return dimension.lastValueReceivedOnChannel[midiChannel - 1]; +} + //============================================================================== void MPEInstrument::updateDimension (int midiChannel, MPEDimension& dimension, MPEValue value) { @@ -758,7 +754,7 @@ public: test.noteOn (3, 60, MPEValue::from7BitInt (100)); expectEquals (test.getNumPlayingNotes(), 1); expectEquals (test.noteAddedCallCounter, 1); - expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown); // note-off test.noteOff (3, 60, MPEValue::from7BitInt (33)); @@ -774,13 +770,13 @@ public: // note off with non-matching note number shouldn't do anything test.noteOff (3, 61, MPEValue::from7BitInt (33)); expectEquals (test.getNumPlayingNotes(), 1); - expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown); expectEquals (test.noteReleasedCallCounter, 0); // note off with non-matching midi channel shouldn't do anything test.noteOff (2, 60, MPEValue::from7BitInt (33)); expectEquals (test.getNumPlayingNotes(), 1); - expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown); expectEquals (test.noteReleasedCallCounter, 0); } { @@ -791,9 +787,9 @@ public: test.noteOn (3, 1, MPEValue::from7BitInt (100)); test.noteOn (3, 2, MPEValue::from7BitInt (100)); expectEquals (test.getNumPlayingNotes(), 3); - expectNote (test.getNote (3, 0), 100, 100, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (3, 1), 100, 100, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (3, 2), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 0), 100, 0, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 1), 100, 0, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 2), 100, 0, 8192, 64, MPENote::keyDown); } { // pathological case: second note-on for same note should retrigger it. @@ -802,7 +798,7 @@ public: test.noteOn (3, 0, MPEValue::from7BitInt (100)); test.noteOn (3, 0, MPEValue::from7BitInt (60)); expectEquals (test.getNumPlayingNotes(), 1); - expectNote (test.getNote (3, 0), 60, 60, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 0), 60, 0, 8192, 64, MPENote::keyDown); } } @@ -844,42 +840,42 @@ public: // sustain pedal on per-note channel shouldn't do anything. test.sustainPedal (3, true); - expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown); expectEquals (test.noteKeyStateChangedCallCounter, 0); // sustain pedal on non-zone channel shouldn't do anything either. test.sustainPedal (1, true); - expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown); expectEquals (test.noteKeyStateChangedCallCounter, 0); // sustain pedal on master channel should sustain notes on *that* zone. test.sustainPedal (2, true); - expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDownAndSustained); - expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDownAndSustained); + expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown); expectEquals (test.noteKeyStateChangedCallCounter, 1); // release test.sustainPedal (2, false); - expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown); expectEquals (test.noteKeyStateChangedCallCounter, 2); // should also sustain new notes added after the press test.sustainPedal (2, true); expectEquals (test.noteKeyStateChangedCallCounter, 3); test.noteOn (4, 51, MPEValue::from7BitInt (100)); - expectNote (test.getNote (4, 51), 100, 100, 8192, 64, MPENote::keyDownAndSustained); + expectNote (test.getNote (4, 51), 100, 0, 8192, 64, MPENote::keyDownAndSustained); expectEquals (test.noteKeyStateChangedCallCounter, 3); // ...but only if that sustain came on the master channel of that zone! test.sustainPedal (11, true); test.noteOn (11, 52, MPEValue::from7BitInt (100)); - expectNote (test.getNote (11, 52), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (11, 52), 100, 0, 8192, 64, MPENote::keyDown); test.noteOff (11, 52, MPEValue::from7BitInt (100)); expectEquals (test.noteReleasedCallCounter, 1); @@ -890,8 +886,8 @@ public: expectEquals (test.getNumPlayingNotes(), 2); expectEquals (test.noteReleasedCallCounter, 2); expectEquals (test.noteKeyStateChangedCallCounter, 5); - expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::sustained); - expectNote (test.getNote (4, 51), 100, 100, 8192, 64, MPENote::sustained); + expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::sustained); + expectNote (test.getNote (4, 51), 100, 0, 8192, 64, MPENote::sustained); // notes should be turned off when pedal is released test.sustainPedal (2, false); @@ -908,26 +904,26 @@ public: // sostenuto pedal on per-note channel shouldn't do anything. test.sostenutoPedal (3, true); - expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown); expectEquals (test.noteKeyStateChangedCallCounter, 0); // sostenuto pedal on non-zone channel shouldn't do anything either. test.sostenutoPedal (1, true); - expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown); expectEquals (test.noteKeyStateChangedCallCounter, 0); // sostenuto pedal on master channel should sustain notes on *that* zone. test.sostenutoPedal (2, true); - expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDownAndSustained); - expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDownAndSustained); + expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown); expectEquals (test.noteKeyStateChangedCallCounter, 1); // release test.sostenutoPedal (2, false); - expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown); expectEquals (test.noteKeyStateChangedCallCounter, 2); // should only sustain notes turned on *before* the press (difference to sustain pedal) @@ -935,9 +931,9 @@ public: expectEquals (test.noteKeyStateChangedCallCounter, 3); test.noteOn (4, 51, MPEValue::from7BitInt (100)); expectEquals (test.getNumPlayingNotes(), 3); - expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDownAndSustained); - expectNote (test.getNote (4, 51), 100, 100, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDownAndSustained); + expectNote (test.getNote (4, 51), 100, 0, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown); expectEquals (test.noteKeyStateChangedCallCounter, 3); // note-off should not turn off sustained notes inside the same zone, @@ -946,7 +942,7 @@ public: test.noteOff (4, 51, MPEValue::from7BitInt (100)); test.noteOff (10, 60, MPEValue::from7BitInt (100)); // not affected! expectEquals (test.getNumPlayingNotes(), 1); - expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::sustained); + expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::sustained); expectEquals (test.noteReleasedCallCounter, 2); expectEquals (test.noteKeyStateChangedCallCounter, 4); @@ -1047,22 +1043,22 @@ public: // applying pressure on a per-note channel should modulate one note test.pressure (3, MPEValue::from7BitInt (33)); expectNote (test.getNote (3, 60), 100, 33, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (4, 60), 100, 100, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (4, 60), 100, 0, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown); expectEquals (test.notePressureChangedCallCounter, 1); // applying pressure on a master channel should modulate all notes in this zone test.pressure (2, MPEValue::from7BitInt (44)); expectNote (test.getNote (3, 60), 100, 44, 8192, 64, MPENote::keyDown); expectNote (test.getNote (4, 60), 100, 44, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown); expectEquals (test.notePressureChangedCallCounter, 3); // applying pressure on an unrelated channel should be ignored test.pressure (1, MPEValue::from7BitInt (55)); expectNote (test.getNote (3, 60), 100, 44, 8192, 64, MPENote::keyDown); expectNote (test.getNote (4, 60), 100, 44, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown); expectEquals (test.notePressureChangedCallCounter, 3); } { @@ -1073,7 +1069,7 @@ public: test.noteOn (3, 60, MPEValue::from7BitInt (100)); test.noteOn (3, 61, MPEValue::from7BitInt (100)); test.pressure (3, MPEValue::from7BitInt (66)); - expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown); expectNote (test.getNote (3, 61), 100, 66, 8192, 64, MPENote::keyDown); expectEquals (test.notePressureChangedCallCounter, 1); } @@ -1091,6 +1087,49 @@ public: expectNote (test.getNote (3, 60), 100, 77, 8192, 64, MPENote::keyDown); expectEquals (test.notePressureChangedCallCounter, 1); } + { + UnitTestInstrument test; + test.setZoneLayout (testLayout); + + // if no pressure is sent before note-on, default = 0 should be used + test.noteOn (3, 60, MPEValue::from7BitInt (100)); + expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown); + } + { + UnitTestInstrument test; + test.setZoneLayout (testLayout); + + // if pressure is sent before note-on, use that + test.pressure (3, MPEValue::from7BitInt (77)); + test.noteOn (3, 60, MPEValue::from7BitInt (100)); + expectNote (test.getNote (3, 60), 100, 77, 8192, 64, MPENote::keyDown); + } + { + UnitTestInstrument test; + test.setZoneLayout (testLayout); + + // if pressure is sent before note-on, but it belonged to another note + // on the same channel that has since been turned off, use default = 0 + test.noteOn (3, 61, MPEValue::from7BitInt (100)); + test.pressure (3, MPEValue::from7BitInt (77)); + test.noteOff (3, 61, MPEValue::from7BitInt (100)); + test.noteOn (3, 60, MPEValue::from7BitInt (100)); + expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown); + } + { + UnitTestInstrument test; + test.setZoneLayout (testLayout); + + // edge case: two notes on the same channel simultaneously. the second one should use + // pressure = 0 initially but then react to additional pressure messages + test.noteOn (3, 61, MPEValue::from7BitInt (100)); + test.pressure (3, MPEValue::from7BitInt (77)); + test.noteOn (3, 60, MPEValue::from7BitInt (100)); + expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown); + test.pressure (3, MPEValue::from7BitInt (78)); + expectNote (test.getNote (3, 60), 100, 78, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 61), 100, 77, 8192, 64, MPENote::keyDown); + } } beginTest ("pitchbend"); @@ -1105,9 +1144,9 @@ public: // applying pitchbend on a per-note channel should modulate one note test.pitchbend (3, MPEValue::from14BitInt (1111)); - expectNote (test.getNote (3, 60), 100, 100, 1111, 64, MPENote::keyDown); - expectNote (test.getNote (4, 60), 100, 100, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 1111, 64, MPENote::keyDown); + expectNote (test.getNote (4, 60), 100, 0, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown); expectEquals (test.notePitchbendChangedCallCounter, 1); // applying pitchbend on a master channel should be ignored for the @@ -1115,16 +1154,16 @@ public: // Note: noteChanged will be called anyway for notes in that zone // because the total pitchbend for those notes has changed test.pitchbend (2, MPEValue::from14BitInt (2222)); - expectNote (test.getNote (3, 60), 100, 100, 1111, 64, MPENote::keyDown); - expectNote (test.getNote (4, 60), 100, 100, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 1111, 64, MPENote::keyDown); + expectNote (test.getNote (4, 60), 100, 0, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown); expectEquals (test.notePitchbendChangedCallCounter, 3); // applying pitchbend on an unrelated channel should do nothing. test.pitchbend (1, MPEValue::from14BitInt (3333)); - expectNote (test.getNote (3, 60), 100, 100, 1111, 64, MPENote::keyDown); - expectNote (test.getNote (4, 60), 100, 100, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 1111, 64, MPENote::keyDown); + expectNote (test.getNote (4, 60), 100, 0, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown); expectEquals (test.notePitchbendChangedCallCounter, 3); } { @@ -1135,8 +1174,8 @@ public: test.noteOn (3, 60, MPEValue::from7BitInt (100)); test.noteOn (3, 61, MPEValue::from7BitInt (100)); test.pitchbend (3, MPEValue::from14BitInt (4444)); - expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (3, 61), 100, 100, 4444, 64, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 61), 100, 0, 4444, 64, MPENote::keyDown); expectEquals (test.notePitchbendChangedCallCounter, 1); } { @@ -1150,7 +1189,7 @@ public: test.noteOff (3, 61, MPEValue::from7BitInt (100)); test.pitchbend (3, MPEValue::from14BitInt (5555)); expectEquals (test.getNumPlayingNotes(), 1); - expectNote (test.getNote (3, 60), 100, 100, 5555, 64, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 5555, 64, MPENote::keyDown); expectEquals (test.notePitchbendChangedCallCounter, 1); } { @@ -1169,14 +1208,14 @@ public: test.sustainPedal (2, true); test.noteOff (3, 60, MPEValue::from7BitInt (64)); expectEquals (test.getNumPlayingNotes(), 1); - expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::sustained); + expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::sustained); expectEquals (test.noteKeyStateChangedCallCounter, 2); test.noteOn (3, 61, MPEValue::from7BitInt (100)); test.pitchbend (3, MPEValue::from14BitInt (6666)); expectEquals (test.getNumPlayingNotes(), 2); - expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::sustained); - expectNote (test.getNote (3, 61), 100, 100, 6666, 64, MPENote::keyDownAndSustained); + expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::sustained); + expectNote (test.getNote (3, 61), 100, 0, 6666, 64, MPENote::keyDownAndSustained); expectEquals (test.notePitchbendChangedCallCounter, 1); } { @@ -1193,11 +1232,11 @@ public: test.noteOn (3, 60, MPEValue::from7BitInt (100)); test.pitchbend (3, MPEValue::from14BitInt (5555)); - expectNote (test.getNote (3, 60), 100, 100, 5555, 64, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 5555, 64, MPENote::keyDown); test.noteOff (3, 60, MPEValue::from7BitInt (100)); test.noteOn (3, 60, MPEValue::from7BitInt (100)); - expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown); } { // applying per-note pitchbend should set the note's totalPitchbendInSemitones @@ -1289,23 +1328,23 @@ public: // modulating timbre on a per-note channel should modulate one note test.timbre (3, MPEValue::from7BitInt (33)); - expectNote (test.getNote (3, 60), 100, 100, 8192, 33, MPENote::keyDown); - expectNote (test.getNote (4, 60), 100, 100, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 8192, 33, MPENote::keyDown); + expectNote (test.getNote (4, 60), 100, 0, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown); expectEquals (test.noteTimbreChangedCallCounter, 1); // modulating timbre on a master channel should modulate all notes in this zone test.timbre (2, MPEValue::from7BitInt (44)); - expectNote (test.getNote (3, 60), 100, 100, 8192, 44, MPENote::keyDown); - expectNote (test.getNote (4, 60), 100, 100, 8192, 44, MPENote::keyDown); - expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 8192, 44, MPENote::keyDown); + expectNote (test.getNote (4, 60), 100, 0, 8192, 44, MPENote::keyDown); + expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown); expectEquals (test.noteTimbreChangedCallCounter, 3); // modulating timbre on an unrelated channel should be ignored test.timbre (1, MPEValue::from7BitInt (55)); - expectNote (test.getNote (3, 60), 100, 100, 8192, 44, MPENote::keyDown); - expectNote (test.getNote (4, 60), 100, 100, 8192, 44, MPENote::keyDown); - expectNote (test.getNote (10, 60), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 8192, 44, MPENote::keyDown); + expectNote (test.getNote (4, 60), 100, 0, 8192, 44, MPENote::keyDown); + expectNote (test.getNote (10, 60), 100, 0, 8192, 64, MPENote::keyDown); expectEquals (test.noteTimbreChangedCallCounter, 3); } { @@ -1316,8 +1355,8 @@ public: test.noteOn (3, 60, MPEValue::from7BitInt (100)); test.noteOn (3, 61, MPEValue::from7BitInt (100)); test.timbre (3, MPEValue::from7BitInt (66)); - expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (3, 61), 100, 100, 8192, 66, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 61), 100, 0, 8192, 66, MPENote::keyDown); expectEquals (test.noteTimbreChangedCallCounter, 1); } { @@ -1331,7 +1370,7 @@ public: test.noteOff (3, 61, MPEValue::from7BitInt (100)); test.timbre (3, MPEValue::from7BitInt (77)); expectEquals (test.getNumPlayingNotes(), 1); - expectNote (test.getNote (3, 60), 100, 100, 8192, 77, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 8192, 77, MPENote::keyDown); expectEquals (test.noteTimbreChangedCallCounter, 1); } { @@ -1341,11 +1380,11 @@ public: // Zsolt's edge case for timbre test.noteOn (3, 60, MPEValue::from7BitInt (100)); test.timbre (3, MPEValue::from7BitInt (42)); - expectNote (test.getNote (3, 60), 100, 100, 8192, 42, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 8192, 42, MPENote::keyDown); test.noteOff (3, 60, MPEValue::from7BitInt (100)); test.noteOn (3, 60, MPEValue::from7BitInt (100)); - expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown); } } @@ -1361,8 +1400,8 @@ public: test.noteOn (3, 62, MPEValue::from7BitInt (100)); test.noteOn (3, 61, MPEValue::from7BitInt (100)); test.pressure (3, MPEValue::from7BitInt (99)); - expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (3, 62), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 62), 100, 0, 8192, 64, MPENote::keyDown); expectNote (test.getNote (3, 61), 100, 99, 8192, 64, MPENote::keyDown); expectEquals (test.notePressureChangedCallCounter, 1); } @@ -1377,8 +1416,8 @@ public: test.noteOn (3, 61, MPEValue::from7BitInt (100)); test.pressure (3, MPEValue::from7BitInt (99)); expectNote (test.getNote (3, 60), 100, 99, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (3, 62), 100, 100, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (3, 61), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 62), 100, 0, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 61), 100, 0, 8192, 64, MPENote::keyDown); expectEquals (test.notePressureChangedCallCounter, 1); } { @@ -1391,9 +1430,9 @@ public: test.noteOn (3, 62, MPEValue::from7BitInt (100)); test.noteOn (3, 61, MPEValue::from7BitInt (100)); test.pressure (3, MPEValue::from7BitInt (99)); - expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown); expectNote (test.getNote (3, 62), 100, 99, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (3, 61), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 61), 100, 0, 8192, 64, MPENote::keyDown); expectEquals (test.notePressureChangedCallCounter, 1); } { @@ -1425,9 +1464,9 @@ public: test.noteOn (3, 62, MPEValue::from7BitInt (100)); test.noteOn (3, 61, MPEValue::from7BitInt (100)); test.pitchbend (3, MPEValue::from14BitInt (9999)); - expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (3, 62), 100, 100, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (3, 61), 100, 100, 9999, 64, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 62), 100, 0, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 61), 100, 0, 9999, 64, MPENote::keyDown); expectEquals (test.notePitchbendChangedCallCounter, 1); } { @@ -1440,9 +1479,9 @@ public: test.noteOn (3, 62, MPEValue::from7BitInt (100)); test.noteOn (3, 61, MPEValue::from7BitInt (100)); test.pitchbend (3, MPEValue::from14BitInt (9999)); - expectNote (test.getNote (3, 60), 100, 100, 9999, 64, MPENote::keyDown); - expectNote (test.getNote (3, 62), 100, 100, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (3, 61), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 9999, 64, MPENote::keyDown); + expectNote (test.getNote (3, 62), 100, 0, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 61), 100, 0, 8192, 64, MPENote::keyDown); expectEquals (test.notePitchbendChangedCallCounter, 1); } { @@ -1455,9 +1494,9 @@ public: test.noteOn (3, 62, MPEValue::from7BitInt (100)); test.noteOn (3, 61, MPEValue::from7BitInt (100)); test.pitchbend (3, MPEValue::from14BitInt (9999)); - expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (3, 62), 100, 100, 9999, 64, MPENote::keyDown); - expectNote (test.getNote (3, 61), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 62), 100, 0, 9999, 64, MPENote::keyDown); + expectNote (test.getNote (3, 61), 100, 0, 8192, 64, MPENote::keyDown); expectEquals (test.notePitchbendChangedCallCounter, 1); } { @@ -1470,9 +1509,9 @@ public: test.noteOn (3, 62, MPEValue::from7BitInt (100)); test.noteOn (3, 61, MPEValue::from7BitInt (100)); test.pitchbend (3, MPEValue::from14BitInt (9999)); - expectNote (test.getNote (3, 60), 100, 100, 9999, 64, MPENote::keyDown); - expectNote (test.getNote (3, 62), 100, 100, 9999, 64, MPENote::keyDown); - expectNote (test.getNote (3, 61), 100, 100, 9999, 64, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 9999, 64, MPENote::keyDown); + expectNote (test.getNote (3, 62), 100, 0, 9999, 64, MPENote::keyDown); + expectNote (test.getNote (3, 61), 100, 0, 9999, 64, MPENote::keyDown); expectEquals (test.notePitchbendChangedCallCounter, 3); } } @@ -1489,9 +1528,9 @@ public: test.noteOn (3, 62, MPEValue::from7BitInt (100)); test.noteOn (3, 61, MPEValue::from7BitInt (100)); test.timbre (3, MPEValue::from7BitInt (99)); - expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (3, 62), 100, 100, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (3, 61), 100, 100, 8192, 99, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 62), 100, 0, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 61), 100, 0, 8192, 99, MPENote::keyDown); expectEquals (test.noteTimbreChangedCallCounter, 1); } { @@ -1504,9 +1543,9 @@ public: test.noteOn (3, 62, MPEValue::from7BitInt (100)); test.noteOn (3, 61, MPEValue::from7BitInt (100)); test.timbre (3, MPEValue::from7BitInt (99)); - expectNote (test.getNote (3, 60), 100, 100, 8192, 99, MPENote::keyDown); - expectNote (test.getNote (3, 62), 100, 100, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (3, 61), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 8192, 99, MPENote::keyDown); + expectNote (test.getNote (3, 62), 100, 0, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 61), 100, 0, 8192, 64, MPENote::keyDown); expectEquals (test.noteTimbreChangedCallCounter, 1); } { @@ -1519,9 +1558,9 @@ public: test.noteOn (3, 62, MPEValue::from7BitInt (100)); test.noteOn (3, 61, MPEValue::from7BitInt (100)); test.timbre (3, MPEValue::from7BitInt (99)); - expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (3, 62), 100, 100, 8192, 99, MPENote::keyDown); - expectNote (test.getNote (3, 61), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 62), 100, 0, 8192, 99, MPENote::keyDown); + expectNote (test.getNote (3, 61), 100, 0, 8192, 64, MPENote::keyDown); expectEquals (test.noteTimbreChangedCallCounter, 1); } { @@ -1534,9 +1573,9 @@ public: test.noteOn (3, 62, MPEValue::from7BitInt (100)); test.noteOn (3, 61, MPEValue::from7BitInt (100)); test.timbre (3, MPEValue::from7BitInt (99)); - expectNote (test.getNote (3, 60), 100, 100, 8192, 99, MPENote::keyDown); - expectNote (test.getNote (3, 62), 100, 100, 8192, 99, MPENote::keyDown); - expectNote (test.getNote (3, 61), 100, 100, 8192, 99, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 8192, 99, MPENote::keyDown); + expectNote (test.getNote (3, 62), 100, 0, 8192, 99, MPENote::keyDown); + expectNote (test.getNote (3, 61), 100, 0, 8192, 99, MPENote::keyDown); expectEquals (test.noteTimbreChangedCallCounter, 3); } } @@ -1724,7 +1763,7 @@ public: expectEquals (test.getNumPlayingNotes(), 0); } - beginTest ("default getInitial...ForNoteOn"); + beginTest ("default initial values for pitchbend and timbre"); { MPEInstrument test; test.setZoneLayout (testLayout); @@ -1739,16 +1778,7 @@ public: test.noteOn (3, 60, MPEValue::from7BitInt (100)); - expectNote (test.getMostRecentNote (3), 100, 100, 3333, 66, MPENote::keyDown); - } - - beginTest ("overriding getInitial...ForNoteOn"); - { - CustomInitialValuesTest<33, 4444, 55> test; - test.setZoneLayout (testLayout); - - test.noteOn (3, 61, MPEValue::from7BitInt (100)); - expectNote (test.getMostRecentNote (3), 100, 33, 4444, 55, MPENote::keyDown); + expectNote (test.getMostRecentNote (3), 100, 0, 3333, 66, MPENote::keyDown); } beginTest ("Legacy mode"); @@ -1806,10 +1836,10 @@ public: test.pressure (2, MPEValue::from7BitInt (88)); test.timbre (15, MPEValue::from7BitInt (77)); - expectNote (test.getNote (1, 60), 100, 100, 9999, 64, MPENote::keyDown); + expectNote (test.getNote (1, 60), 100, 0, 9999, 64, MPENote::keyDown); expectNote (test.getNote (2, 60), 100, 88, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (15, 60), 100, 100, 8192, 77, MPENote::keyDown); - expectNote (test.getNote (16, 60), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (15, 60), 100, 0, 8192, 77, MPENote::keyDown); + expectNote (test.getNote (16, 60), 100, 0, 8192, 64, MPENote::keyDown); // note off should work in legacy mode @@ -1835,10 +1865,10 @@ public: test.noteOn (16, 60, MPEValue::from7BitInt (100)); expectEquals (test.getNumPlayingNotes(), 4); - expectNote (test.getNote (3, 60), 100, 100, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (4, 60), 100, 100, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (6, 60), 100, 100, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (7, 60), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (3, 60), 100, 0, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (4, 60), 100, 0, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (6, 60), 100, 0, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (7, 60), 100, 0, 8192, 64, MPENote::keyDown); } { // tracking mode in legacy mode @@ -1851,9 +1881,9 @@ public: test.noteOn (1, 62, MPEValue::from7BitInt (100)); test.noteOn (1, 61, MPEValue::from7BitInt (100)); test.pitchbend (1, MPEValue::from14BitInt (9999)); - expectNote (test.getNote (1, 60), 100, 100, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (1, 61), 100, 100, 9999, 64, MPENote::keyDown); - expectNote (test.getNote (1, 62), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (1, 60), 100, 0, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (1, 61), 100, 0, 9999, 64, MPENote::keyDown); + expectNote (test.getNote (1, 62), 100, 0, 8192, 64, MPENote::keyDown); } { UnitTestInstrument test; @@ -1864,9 +1894,9 @@ public: test.noteOn (1, 62, MPEValue::from7BitInt (100)); test.noteOn (1, 61, MPEValue::from7BitInt (100)); test.pitchbend (1, MPEValue::from14BitInt (9999)); - expectNote (test.getNote (1, 60), 100, 100, 9999, 64, MPENote::keyDown); - expectNote (test.getNote (1, 61), 100, 100, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (1, 62), 100, 100, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (1, 60), 100, 0, 9999, 64, MPENote::keyDown); + expectNote (test.getNote (1, 61), 100, 0, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (1, 62), 100, 0, 8192, 64, MPENote::keyDown); } { UnitTestInstrument test; @@ -1877,9 +1907,9 @@ public: test.noteOn (1, 62, MPEValue::from7BitInt (100)); test.noteOn (1, 61, MPEValue::from7BitInt (100)); test.pitchbend (1, MPEValue::from14BitInt (9999)); - expectNote (test.getNote (1, 60), 100, 100, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (1, 61), 100, 100, 8192, 64, MPENote::keyDown); - expectNote (test.getNote (1, 62), 100, 100, 9999, 64, MPENote::keyDown); + expectNote (test.getNote (1, 60), 100, 0, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (1, 61), 100, 0, 8192, 64, MPENote::keyDown); + expectNote (test.getNote (1, 62), 100, 0, 9999, 64, MPENote::keyDown); } { UnitTestInstrument test; @@ -1890,9 +1920,9 @@ public: test.noteOn (1, 62, MPEValue::from7BitInt (100)); test.noteOn (1, 61, MPEValue::from7BitInt (100)); test.pitchbend (1, MPEValue::from14BitInt (9999)); - expectNote (test.getNote (1, 60), 100, 100, 9999, 64, MPENote::keyDown); - expectNote (test.getNote (1, 61), 100, 100, 9999, 64, MPENote::keyDown); - expectNote (test.getNote (1, 62), 100, 100, 9999, 64, MPENote::keyDown); + expectNote (test.getNote (1, 60), 100, 0, 9999, 64, MPENote::keyDown); + expectNote (test.getNote (1, 61), 100, 0, 9999, 64, MPENote::keyDown); + expectNote (test.getNote (1, 62), 100, 0, 9999, 64, MPENote::keyDown); } } { @@ -1916,7 +1946,7 @@ public: test.noteOff (1, 60, MPEValue::from7BitInt (100)); expectEquals (test.getNumPlayingNotes(), 1); - expectNote (test.getNote (1, 60), 100, 100, 8192, 64, MPENote::sustained); + expectNote (test.getNote (1, 60), 100, 0, 8192, 64, MPENote::sustained); test.sustainPedal (1, false); expectEquals (test.getNumPlayingNotes(), 0); @@ -1939,7 +1969,7 @@ public: test.noteOff (2, 61, MPEValue::from7BitInt (100)); expectEquals (test.getNumPlayingNotes(), 1); - expectNote (test.getNote (1, 60), 100, 100, 8192, 64, MPENote::sustained); + expectNote (test.getNote (1, 60), 100, 0, 8192, 64, MPENote::sustained); test.sostenutoPedal (1, false); expectEquals (test.getNumPlayingNotes(), 0); @@ -2081,26 +2111,6 @@ private: } }; - //============================================================================== - template - class CustomInitialValuesTest : public MPEInstrument - { - MPEValue getInitialPitchbendForNoteOn (int, int, MPEValue) const override - { - return MPEValue::from14BitInt (initial14BitPitchbend); - } - - MPEValue getInitialPressureForNoteOn (int, int, MPEValue) const override - { - return MPEValue::from7BitInt (initial7BitPressure); - } - - MPEValue getInitialTimbreForNoteOn (int, int, MPEValue) const override - { - return MPEValue::from7BitInt (initial7BitTimbre); - } - }; - //============================================================================== void expectNote (MPENote noteToTest, int noteOnVelocity7Bit, diff --git a/modules/juce_audio_basics/mpe/juce_MPEInstrument.h b/modules/juce_audio_basics/mpe/juce_MPEInstrument.h index ea895baabb..6303f22c98 100644 --- a/modules/juce_audio_basics/mpe/juce_MPEInstrument.h +++ b/modules/juce_audio_basics/mpe/juce_MPEInstrument.h @@ -320,36 +320,6 @@ public: /** Re-sets the pitchbend range in semitones (0-96) to be used for notes when in legacy mode. */ void setLegacyModePitchbendRange (int pitchbendRange); -protected: - //============================================================================== - /** This method defines what initial pitchbend value should be used for newly - triggered notes. The default is to use the last pitchbend value - that has been received on the same MIDI channel (or no pitchbend - if no pitchbend messages have been received so far). - Override this method if you need different behaviour. - */ - virtual MPEValue getInitialPitchbendForNoteOn (int midiChannel, - int midiNoteNumber, - MPEValue midiNoteOnVelocity) const; - - /** This method defines what initial pressure value should be used for newly - triggered notes. The default is to re-use the note-on velocity value. - Override this method if you need different behaviour. - */ - virtual MPEValue getInitialPressureForNoteOn (int midiChannel, - int midiNoteNumber, - MPEValue midiNoteOnVelocity) const; - - /** This method defines what initial timbre value should be used for newly - triggered notes. The default is to use the last timbre value that has - that has been received on the same MIDI channel (or a neutral centred value - if no pitchbend messages have been received so far). - Override this method if you need different behaviour. - */ - virtual MPEValue getInitialTimbreForNoteOn (int midiChannel, - int midiNoteNumber, - MPEValue midiNoteOnVelocity) const; - private: //============================================================================== CriticalSection lock; @@ -384,6 +354,7 @@ private: void updateDimensionMaster (MPEZone&, MPEDimension&, MPEValue); void updateDimensionForNote (MPENote&, MPEDimension&, MPEValue); void callListenersDimensionChanged (MPENote&, MPEDimension&); + MPEValue getInitialValueForNewNote (int midiChannel, MPEDimension&) const; void processMidiNoteOnMessage (const MidiMessage&); void processMidiNoteOffMessage (const MidiMessage&);