The midi channels should now be 0-based everywhere
This commit is contained in:
parent
aba9c15e50
commit
194816ef58
12 changed files with 133 additions and 150 deletions
|
|
@ -61,6 +61,7 @@ namespace Default
|
|||
|
||||
// Region logic: MIDI conditions
|
||||
constexpr Range<uint8_t> channelRange { 1, 16 };
|
||||
constexpr Range<uint8_t> midiChannelRange { 0, 15 };
|
||||
constexpr Range<uint8_t> ccRange { 0, 127 };
|
||||
constexpr uint8_t cc { 0 };
|
||||
constexpr Range<int> bendRange { -8192, 8192 };
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@ sfz::MidiState::MidiState()
|
|||
|
||||
void sfz::MidiState::noteOnEvent(int channel, int noteNumber, uint8_t velocity) noexcept
|
||||
{
|
||||
ASSERT(channel >= 1 && channel <= 16);
|
||||
ASSERT(channel >= 0 && channel < 16);
|
||||
ASSERT(noteNumber >= 0 && noteNumber <= 127);
|
||||
ASSERT(velocity >= 0 && velocity <= 127);
|
||||
channel = translateSfzChannelToMidi(channel);
|
||||
|
||||
if (noteNumber >= 0 && noteNumber < 128) {
|
||||
lastNoteVelocities[channel][noteNumber] = velocity;
|
||||
noteOnTimes[channel][noteNumber] = std::chrono::steady_clock::now();
|
||||
|
|
@ -20,9 +20,9 @@ void sfz::MidiState::noteOnEvent(int channel, int noteNumber, uint8_t velocity)
|
|||
|
||||
float sfz::MidiState::getNoteDuration(int channel, int noteNumber) const
|
||||
{
|
||||
ASSERT(channel >= 1 && channel <= 16);
|
||||
ASSERT(channel >= 0 && channel < 16);
|
||||
ASSERT(noteNumber >= 0 && noteNumber <= 127);
|
||||
channel = translateSfzChannelToMidi(channel);
|
||||
|
||||
if (noteNumber >= 0 && noteNumber < 128) {
|
||||
const auto noteOffTime = std::chrono::steady_clock::now();
|
||||
const auto duration = std::chrono::duration_cast<std::chrono::duration<float>>(noteOffTime - noteOnTimes[channel][noteNumber]);
|
||||
|
|
@ -34,48 +34,48 @@ float sfz::MidiState::getNoteDuration(int channel, int noteNumber) const
|
|||
|
||||
uint8_t sfz::MidiState::getNoteVelocity(int channel, int noteNumber) const noexcept
|
||||
{
|
||||
ASSERT(channel >= 1 && channel <= 16);
|
||||
ASSERT(channel >= 0 && channel < 16);
|
||||
ASSERT(noteNumber >= 0 && noteNumber <= 127);
|
||||
channel = translateSfzChannelToMidi(channel);
|
||||
|
||||
return lastNoteVelocities[channel][noteNumber];
|
||||
}
|
||||
|
||||
void sfz::MidiState::pitchBendEvent(int channel, int pitchBendValue) noexcept
|
||||
{
|
||||
ASSERT(channel >= 1 && channel <= 16);
|
||||
ASSERT(channel >= 0 && channel < 16);
|
||||
ASSERT(pitchBendValue >= -8192 && pitchBendValue <= 8192);
|
||||
channel = translateSfzChannelToMidi(channel);
|
||||
|
||||
pitchBends[channel] = pitchBendValue;
|
||||
}
|
||||
|
||||
int sfz::MidiState::getPitchBend(int channel) const noexcept
|
||||
{
|
||||
ASSERT(channel >= 1 && channel <= 16);
|
||||
channel = translateSfzChannelToMidi(channel);
|
||||
ASSERT(channel >= 0 && channel < 16);
|
||||
|
||||
return pitchBends[channel];
|
||||
}
|
||||
|
||||
void sfz::MidiState::ccEvent(int channel, int ccNumber, uint8_t ccValue) noexcept
|
||||
{
|
||||
ASSERT(channel >= 1 && channel <= 16);
|
||||
ASSERT(channel >= 0 && channel < 16);
|
||||
ASSERT(ccNumber >= 0 && ccNumber <= 127);
|
||||
ASSERT(ccValue >= 0 && ccValue <= 127);
|
||||
channel = translateSfzChannelToMidi(channel);
|
||||
|
||||
cc[channel][ccNumber] = ccValue;
|
||||
}
|
||||
|
||||
uint8_t sfz::MidiState::getCCValue(int channel, int ccNumber) const noexcept
|
||||
{
|
||||
ASSERT(channel >= 1 && channel <= 16);
|
||||
ASSERT(channel >= 0 && channel < 16);
|
||||
ASSERT(ccNumber >= 0 && ccNumber <= 127);
|
||||
channel = translateSfzChannelToMidi(channel);
|
||||
|
||||
return cc[channel][ccNumber];
|
||||
}
|
||||
|
||||
const sfz::CCValueArray& sfz::MidiState::getCCArray(int channel) const noexcept
|
||||
{
|
||||
ASSERT(channel >= 1 && channel <= 16);
|
||||
channel = translateSfzChannelToMidi(channel);
|
||||
ASSERT(channel >= 0 && channel < 16);
|
||||
|
||||
return cc[channel];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ public:
|
|||
/**
|
||||
* @brief Update the state after a note on event
|
||||
*
|
||||
* @param channel (1-based)
|
||||
* @param channel (0-based)
|
||||
* @param noteNumber
|
||||
* @param velocity
|
||||
*/
|
||||
|
|
@ -27,7 +27,7 @@ public:
|
|||
/**
|
||||
* @brief Register a note off and get the note duration
|
||||
*
|
||||
* @param channel (1-based)
|
||||
* @param channel (0-based)
|
||||
* @param noteNumber
|
||||
* @return float
|
||||
*/
|
||||
|
|
@ -36,7 +36,7 @@ public:
|
|||
/**
|
||||
* @brief Get the note on velocity for a given note
|
||||
*
|
||||
* @param channel (1-based)
|
||||
* @param channel (0-based)
|
||||
* @param noteNumber
|
||||
* @return uint8_t
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -134,10 +134,18 @@ bool sfz::Region::parseOpcode(const Opcode& opcode)
|
|||
|
||||
// Region logic: MIDI conditions
|
||||
case hash("lochan"):
|
||||
setRangeStartFromOpcode(opcode, channelRange, Default::channelRange);
|
||||
{
|
||||
const auto value = readOpcode(opcode.value, Default::channelRange);
|
||||
if (value)
|
||||
channelRange.setStart(*value - 1);
|
||||
}
|
||||
break;
|
||||
case hash("hichan"):
|
||||
setRangeEndFromOpcode(opcode, channelRange, Default::channelRange);
|
||||
{
|
||||
const auto value = readOpcode(opcode.value, Default::channelRange);
|
||||
if (value)
|
||||
channelRange.setEnd(*value - 1);
|
||||
}
|
||||
break;
|
||||
case hash("lobend"):
|
||||
setRangeStartFromOpcode(opcode, bendRange, Default::bendRange);
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ struct Region {
|
|||
* @brief Register a new note on event. The region may be switched on or off using keys so
|
||||
* this function updates the keyswitches state.
|
||||
*
|
||||
* @param channel MIDI channel (1-based)
|
||||
* @param channel MIDI channel (0-based)
|
||||
* @param noteNumber
|
||||
* @param velocity
|
||||
* @param randValue a random value between 0 and 1 used to randomize a bit the region activations
|
||||
|
|
@ -106,7 +106,7 @@ struct Region {
|
|||
* @brief Register a new note off event. The region may be switched on or off using keys so
|
||||
* this function updates the keyswitches state.
|
||||
*
|
||||
* @param channel MIDI channel (1-based)
|
||||
* @param channel MIDI channel (0-based)
|
||||
* @param noteNumber
|
||||
* @param velocity
|
||||
* @param randValue a random value between 0 and 1 used to randomize a bit the region activations
|
||||
|
|
@ -119,7 +119,7 @@ struct Region {
|
|||
* @brief Register a new CC event. The region may be switched on or off using CCs so
|
||||
* this function checks if it indeeds need to activate or not.
|
||||
*
|
||||
* @param channel MIDI channel (1-based)
|
||||
* @param channel MIDI channel (0-based)
|
||||
* @param ccNumber
|
||||
* @param ccValue
|
||||
* @return true if the region should trigger on this event
|
||||
|
|
@ -129,14 +129,14 @@ struct Region {
|
|||
/**
|
||||
* @brief Register a new pitch wheel event.
|
||||
*
|
||||
* @param channel MIDI channel (1-based)
|
||||
* @param channel MIDI channel (0-based)
|
||||
* @param pitch
|
||||
*/
|
||||
void registerPitchWheel(int channel, int pitch) noexcept;
|
||||
/**
|
||||
* @brief Register a new aftertouch event.
|
||||
*
|
||||
* @param channel MIDI channel (1-based)
|
||||
* @param channel MIDI channel (0-based)
|
||||
* @param aftertouch
|
||||
*/
|
||||
void registerAftertouch(int channel, uint8_t aftertouch) noexcept;
|
||||
|
|
@ -177,7 +177,7 @@ struct Region {
|
|||
* @brief Get the base volume of the region depending on which note has been
|
||||
* pressed to trigger the region.
|
||||
*
|
||||
* @param channel (1-based)
|
||||
* @param channel (0-based)
|
||||
* @param noteNumber
|
||||
* @return float
|
||||
*/
|
||||
|
|
@ -247,7 +247,7 @@ struct Region {
|
|||
Range<uint8_t> velocityRange { Default::velocityRange }; // hivel and lovel
|
||||
|
||||
// Region logic: MIDI conditions
|
||||
Range<uint8_t> channelRange { Default::channelRange }; //lochan and hichan
|
||||
Range<uint8_t> channelRange { Default::midiChannelRange }; //lochan and hichan
|
||||
Range<int> bendRange { Default::bendRange }; // hibend and lobend
|
||||
CCMap<Range<uint8_t>> ccConditions { Default::ccRange };
|
||||
Range<uint8_t> keyswitchRange { Default::keyRange }; // sw_hikey and sw_lokey
|
||||
|
|
|
|||
|
|
@ -35,28 +35,6 @@ using CCValueArray = std::array<uint8_t, 128>;
|
|||
using CCValuePair = std::pair<uint8_t, float> ;
|
||||
using CCNamePair = std::pair<uint8_t, std::string>;
|
||||
|
||||
/**
|
||||
* @brief Translates the zero-based MIDI channel to the 1-based SFZ channel
|
||||
*
|
||||
* @param zeroBasedChannel
|
||||
* @return constexpr int
|
||||
*/
|
||||
constexpr int translateMidiChannelToSfz(int zeroBasedChannel)
|
||||
{
|
||||
return zeroBasedChannel + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Translates the 1-based SFZ channel to the 0-based MIDI channel
|
||||
*
|
||||
* @param zeroBasedChannel
|
||||
* @return constexpr int
|
||||
*/
|
||||
constexpr int translateSfzChannelToMidi(int oneBasedChannel)
|
||||
{
|
||||
return oneBasedChannel - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Converts cents to a pitch ratio
|
||||
*
|
||||
|
|
|
|||
|
|
@ -380,7 +380,6 @@ void sfz::Synth::noteOn(int delay, int channel, int noteNumber, uint8_t velocity
|
|||
ASSERT(noteNumber < 128);
|
||||
ASSERT(noteNumber >= 0);
|
||||
|
||||
channel = translateMidiChannelToSfz(channel);
|
||||
midiState.noteOnEvent(channel, noteNumber, velocity);
|
||||
|
||||
AtomicGuard callbackGuard { inCallback };
|
||||
|
|
@ -410,7 +409,6 @@ void sfz::Synth::noteOff(int delay, int channel, int noteNumber, uint8_t velocit
|
|||
ASSERT(noteNumber < 128);
|
||||
ASSERT(noteNumber >= 0);
|
||||
|
||||
channel = translateMidiChannelToSfz(channel);
|
||||
AtomicGuard callbackGuard { inCallback };
|
||||
if (!canEnterCallback)
|
||||
return;
|
||||
|
|
@ -440,7 +438,6 @@ void sfz::Synth::cc(int delay, int channel, int ccNumber, uint8_t ccValue) noexc
|
|||
ASSERT(ccNumber < 128);
|
||||
ASSERT(ccNumber >= 0);
|
||||
|
||||
channel = translateMidiChannelToSfz(channel);
|
||||
|
||||
AtomicGuard callbackGuard { inCallback };
|
||||
if (!canEnterCallback)
|
||||
|
|
@ -466,15 +463,14 @@ void sfz::Synth::pitchWheel(int delay, int channel, int pitch) noexcept
|
|||
{
|
||||
ASSERT(pitch <= 8192);
|
||||
ASSERT(pitch >= -8192);
|
||||
channel = translateMidiChannelToSfz(channel);
|
||||
|
||||
midiState.pitchBendEvent(channel, pitch);
|
||||
for (auto& voice: voices) {
|
||||
voice->registerPitchWheel(delay, channel, pitch);
|
||||
}
|
||||
}
|
||||
void sfz::Synth::aftertouch(int /* delay */, int channel, uint8_t /* aftertouch */) noexcept
|
||||
void sfz::Synth::aftertouch(int /* delay */, int /*channel*/, uint8_t /* aftertouch */) noexcept
|
||||
{
|
||||
channel = translateMidiChannelToSfz(channel);
|
||||
}
|
||||
void sfz::Synth::tempo(int /* delay */, float /* secondsPerQuarter */) noexcept
|
||||
{
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ public:
|
|||
*
|
||||
* @param region
|
||||
* @param delay
|
||||
* @param channel
|
||||
* @param channel (0-based)
|
||||
* @param number
|
||||
* @param value
|
||||
* @param triggerType
|
||||
|
|
@ -103,7 +103,7 @@ public:
|
|||
* @brief Register a note-off event; this may trigger a release.
|
||||
*
|
||||
* @param delay
|
||||
* @param channel
|
||||
* @param channel (0-based)
|
||||
* @param noteNumber
|
||||
* @param velocity
|
||||
*/
|
||||
|
|
@ -114,7 +114,7 @@ public:
|
|||
* parameter.
|
||||
*
|
||||
* @param delay
|
||||
* @param channel
|
||||
* @param channel (0-based)
|
||||
* @param ccNumber
|
||||
* @param ccValue
|
||||
*/
|
||||
|
|
@ -123,7 +123,7 @@ public:
|
|||
* @brief Register a pitch wheel event; for now this does nothing
|
||||
*
|
||||
* @param delay
|
||||
* @param channel
|
||||
* @param channel (0-based)
|
||||
* @param pitch
|
||||
*/
|
||||
void registerPitchWheel(int delay, int channel, int pitch) noexcept;
|
||||
|
|
@ -131,7 +131,7 @@ public:
|
|||
* @brief Register an aftertouch event; for now this does nothing
|
||||
*
|
||||
* @param delay
|
||||
* @param channel
|
||||
* @param channel (0-based)
|
||||
* @param aftertouch
|
||||
*/
|
||||
void registerAftertouch(int delay, int channel, uint8_t aftertouch) noexcept;
|
||||
|
|
@ -139,7 +139,7 @@ public:
|
|||
* @brief Register a tempo event; for now this does nothing
|
||||
*
|
||||
* @param delay
|
||||
* @param channel
|
||||
* @param channel (0-based)
|
||||
* @param pitch
|
||||
*/
|
||||
void registerTempo(int delay, float secondsPerQuarter) noexcept;
|
||||
|
|
@ -243,7 +243,7 @@ private:
|
|||
/**
|
||||
* @brief Computes the values for the envelope depending on the note or CC number and the velocity/cc value
|
||||
*
|
||||
* @param channel
|
||||
* @param channel (0-based)
|
||||
* @param delay
|
||||
* @param velocity
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ TEST_CASE("[Files] Basic opcodes (regions_opcodes.sfz)")
|
|||
sfz::Synth synth;
|
||||
synth.loadSfzFile(fs::current_path() / "tests/TestFiles/Regions/regions_opcodes.sfz");
|
||||
REQUIRE(synth.getNumRegions() == 1);
|
||||
REQUIRE(synth.getRegionView(0)->channelRange == sfz::Range<uint8_t>(2, 14));
|
||||
REQUIRE(synth.getRegionView(0)->channelRange == sfz::Range<uint8_t>(1, 13));
|
||||
}
|
||||
|
||||
TEST_CASE("[Files] Underscore opcodes (underscore_opcodes.sfz)")
|
||||
|
|
|
|||
|
|
@ -39,20 +39,20 @@ TEST_CASE("[MidiState] Initial values")
|
|||
REQUIRE( cc == 0 );
|
||||
for (auto& cc: state.getCCArray(6))
|
||||
REQUIRE( cc == 0 );
|
||||
for (int channel = 1; channel <= 16; ++channel)
|
||||
for (int channel = 0; channel < 16; ++channel)
|
||||
REQUIRE( state.getPitchBend(channel) == 0 );
|
||||
}
|
||||
|
||||
TEST_CASE("[MidiState] Set and get CCs")
|
||||
{
|
||||
sfz::MidiState state;
|
||||
const auto& cc1 = state.getCCArray(1);
|
||||
const auto& cc0 = state.getCCArray(0);
|
||||
const auto& cc6 = state.getCCArray(6);
|
||||
const auto& cc12 = state.getCCArray(12);
|
||||
state.ccEvent(1, 24, 23);
|
||||
state.ccEvent(0, 24, 23);
|
||||
state.ccEvent(6, 123, 124);
|
||||
REQUIRE(state.getCCValue(1, 24) == 23);
|
||||
REQUIRE(cc1[24] == 23);
|
||||
REQUIRE(state.getCCValue(0, 24) == 23);
|
||||
REQUIRE(cc0[24] == 23);
|
||||
REQUIRE(state.getCCValue(6, 123) == 124);
|
||||
REQUIRE(cc6[123] == 124);
|
||||
REQUIRE(+state.getCCValue(12, 24) == 0);
|
||||
|
|
@ -64,33 +64,33 @@ TEST_CASE("[MidiState] Set and get CCs")
|
|||
TEST_CASE("[MidiState] Set and get pitch bends")
|
||||
{
|
||||
sfz::MidiState state;
|
||||
state.pitchBendEvent(1, 894);
|
||||
REQUIRE(state.getPitchBend(1) == 894);
|
||||
state.pitchBendEvent(0, 894);
|
||||
REQUIRE(state.getPitchBend(0) == 894);
|
||||
REQUIRE(state.getPitchBend(6) == 0);
|
||||
state.pitchBendEvent(1, 0);
|
||||
REQUIRE(state.getPitchBend(1) == 0);
|
||||
state.pitchBendEvent(0, 0);
|
||||
REQUIRE(state.getPitchBend(0) == 0);
|
||||
REQUIRE(state.getPitchBend(6) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("[MidiState] Reset")
|
||||
{
|
||||
sfz::MidiState state;
|
||||
state.pitchBendEvent(1, 894);
|
||||
state.pitchBendEvent(0, 894);
|
||||
state.noteOnEvent(6, 64, 24);
|
||||
state.ccEvent(16, 123, 124);
|
||||
state.ccEvent(15, 123, 124);
|
||||
state.reset();
|
||||
REQUIRE(state.getPitchBend(1) == 0);
|
||||
REQUIRE(state.getPitchBend(0) == 0);
|
||||
REQUIRE(state.getNoteVelocity(6, 64) == 0);
|
||||
REQUIRE(state.getCCValue(16, 123) == 0);
|
||||
REQUIRE(state.getCCValue(15, 123) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("[MidiState] Set and get note velocities")
|
||||
{
|
||||
sfz::MidiState state;
|
||||
state.noteOnEvent(1, 64, 24);
|
||||
REQUIRE(+state.getNoteVelocity(1, 64) == 24);
|
||||
REQUIRE(+state.getNoteVelocity(2, 64) == 0);
|
||||
state.noteOnEvent(1, 64, 123);
|
||||
REQUIRE(+state.getNoteVelocity(1, 64) == 123);
|
||||
REQUIRE(+state.getNoteVelocity(16, 64) == 0);
|
||||
state.noteOnEvent(0, 64, 24);
|
||||
REQUIRE(+state.getNoteVelocity(0, 64) == 24);
|
||||
REQUIRE(+state.getNoteVelocity(1, 64) == 0);
|
||||
state.noteOnEvent(0, 64, 123);
|
||||
REQUIRE(+state.getNoteVelocity(0, 64) == 123);
|
||||
REQUIRE(+state.getNoteVelocity(15, 64) == 0);
|
||||
}
|
||||
|
|
@ -238,19 +238,19 @@ TEST_CASE("[Region] Parsing opcodes")
|
|||
|
||||
SECTION("lochan, hichan")
|
||||
{
|
||||
REQUIRE(region.channelRange == sfz::Range<uint8_t>(1, 16));
|
||||
REQUIRE(region.channelRange == sfz::Range<uint8_t>(0, 15));
|
||||
region.parseOpcode({ "lochan", "4" });
|
||||
REQUIRE(region.channelRange == sfz::Range<uint8_t>(4, 16));
|
||||
REQUIRE(region.channelRange == sfz::Range<uint8_t>(3, 15));
|
||||
region.parseOpcode({ "lochan", "128" });
|
||||
REQUIRE(region.channelRange == sfz::Range<uint8_t>(16, 16));
|
||||
REQUIRE(region.channelRange == sfz::Range<uint8_t>(15, 15));
|
||||
region.parseOpcode({ "lochan", "-3" });
|
||||
REQUIRE(region.channelRange == sfz::Range<uint8_t>(1, 16));
|
||||
REQUIRE(region.channelRange == sfz::Range<uint8_t>(0, 15));
|
||||
region.parseOpcode({ "hichan", "13" });
|
||||
REQUIRE(region.channelRange == sfz::Range<uint8_t>(1, 13));
|
||||
REQUIRE(region.channelRange == sfz::Range<uint8_t>(0, 12));
|
||||
region.parseOpcode({ "hichan", "-1" });
|
||||
REQUIRE(region.channelRange == sfz::Range<uint8_t>(1, 1));
|
||||
REQUIRE(region.channelRange == sfz::Range<uint8_t>(0, 0));
|
||||
region.parseOpcode({ "hichan", "128" });
|
||||
REQUIRE(region.channelRange == sfz::Range<uint8_t>(1, 16));
|
||||
REQUIRE(region.channelRange == sfz::Range<uint8_t>(0, 15));
|
||||
}
|
||||
|
||||
SECTION("lobend, hibend")
|
||||
|
|
|
|||
|
|
@ -34,44 +34,44 @@ TEST_CASE("Basic triggers", "Region triggers")
|
|||
SECTION("key")
|
||||
{
|
||||
region.parseOpcode({ "key", "40" });
|
||||
REQUIRE(region.registerNoteOn(1, 40, 64, 0.5f));
|
||||
REQUIRE(!region.registerNoteOff(1, 40, 64, 0.5f));
|
||||
REQUIRE(!region.registerNoteOn(1, 41, 64, 0.5f));
|
||||
REQUIRE(!region.registerCC(1, 63, 64));
|
||||
REQUIRE(region.registerNoteOn(0, 40, 64, 0.5f));
|
||||
REQUIRE(!region.registerNoteOff(0, 40, 64, 0.5f));
|
||||
REQUIRE(!region.registerNoteOn(0, 41, 64, 0.5f));
|
||||
REQUIRE(!region.registerCC(0, 63, 64));
|
||||
}
|
||||
SECTION("lokey and hikey")
|
||||
{
|
||||
region.parseOpcode({ "lokey", "40" });
|
||||
region.parseOpcode({ "hikey", "42" });
|
||||
REQUIRE(!region.registerNoteOn(1, 39, 64, 0.5f));
|
||||
REQUIRE(region.registerNoteOn(1, 40, 64, 0.5f));
|
||||
REQUIRE(!region.registerNoteOff(1, 40, 64, 0.5f));
|
||||
REQUIRE(region.registerNoteOn(1, 41, 64, 0.5f));
|
||||
REQUIRE(region.registerNoteOn(1, 42, 64, 0.5f));
|
||||
REQUIRE(!region.registerNoteOn(1, 43, 64, 0.5f));
|
||||
REQUIRE(!region.registerNoteOff(1, 42, 64, 0.5f));
|
||||
REQUIRE(!region.registerNoteOff(1, 42, 64, 0.5f));
|
||||
REQUIRE(!region.registerCC(1, 63, 64));
|
||||
REQUIRE(!region.registerNoteOn(0, 39, 64, 0.5f));
|
||||
REQUIRE(region.registerNoteOn(0, 40, 64, 0.5f));
|
||||
REQUIRE(!region.registerNoteOff(0, 40, 64, 0.5f));
|
||||
REQUIRE(region.registerNoteOn(0, 41, 64, 0.5f));
|
||||
REQUIRE(region.registerNoteOn(0, 42, 64, 0.5f));
|
||||
REQUIRE(!region.registerNoteOn(0, 43, 64, 0.5f));
|
||||
REQUIRE(!region.registerNoteOff(0, 42, 64, 0.5f));
|
||||
REQUIRE(!region.registerNoteOff(0, 42, 64, 0.5f));
|
||||
REQUIRE(!region.registerCC(0, 63, 64));
|
||||
}
|
||||
SECTION("key and release trigger")
|
||||
{
|
||||
region.parseOpcode({ "key", "40" });
|
||||
region.parseOpcode({ "trigger", "release" });
|
||||
REQUIRE(!region.registerNoteOn(1, 40, 64, 0.5f));
|
||||
REQUIRE(region.registerNoteOff(1, 40, 64, 0.5f));
|
||||
REQUIRE(!region.registerNoteOn(1, 41, 64, 0.5f));
|
||||
REQUIRE(!region.registerNoteOff(1, 41, 64, 0.5f));
|
||||
REQUIRE(!region.registerCC(1, 63, 64));
|
||||
REQUIRE(!region.registerNoteOn(0, 40, 64, 0.5f));
|
||||
REQUIRE(region.registerNoteOff(0, 40, 64, 0.5f));
|
||||
REQUIRE(!region.registerNoteOn(0, 41, 64, 0.5f));
|
||||
REQUIRE(!region.registerNoteOff(0, 41, 64, 0.5f));
|
||||
REQUIRE(!region.registerCC(0, 63, 64));
|
||||
}
|
||||
SECTION("key and release_key trigger")
|
||||
{
|
||||
region.parseOpcode({ "key", "40" });
|
||||
region.parseOpcode({ "trigger", "release_key" });
|
||||
REQUIRE(!region.registerNoteOn(1, 40, 64, 0.5f));
|
||||
REQUIRE(region.registerNoteOff(1, 40, 64, 0.5f));
|
||||
REQUIRE(!region.registerNoteOn(1, 41, 64, 0.5f));
|
||||
REQUIRE(!region.registerNoteOff(1, 41, 64, 0.5f));
|
||||
REQUIRE(!region.registerCC(1, 63, 64));
|
||||
REQUIRE(!region.registerNoteOn(0, 40, 64, 0.5f));
|
||||
REQUIRE(region.registerNoteOff(0, 40, 64, 0.5f));
|
||||
REQUIRE(!region.registerNoteOn(0, 41, 64, 0.5f));
|
||||
REQUIRE(!region.registerNoteOff(0, 41, 64, 0.5f));
|
||||
REQUIRE(!region.registerCC(0, 63, 64));
|
||||
}
|
||||
// TODO: first and legato triggers
|
||||
SECTION("lovel and hivel")
|
||||
|
|
@ -79,22 +79,22 @@ TEST_CASE("Basic triggers", "Region triggers")
|
|||
region.parseOpcode({ "key", "40" });
|
||||
region.parseOpcode({ "lovel", "60" });
|
||||
region.parseOpcode({ "hivel", "70" });
|
||||
REQUIRE(region.registerNoteOn(1, 40, 64, 0.5f));
|
||||
REQUIRE(region.registerNoteOn(1, 40, 60, 0.5f));
|
||||
REQUIRE(region.registerNoteOn(1, 40, 70, 0.5f));
|
||||
REQUIRE(!region.registerNoteOn(1, 41, 71, 0.5f));
|
||||
REQUIRE(!region.registerNoteOn(1, 41, 59, 0.5f));
|
||||
REQUIRE(region.registerNoteOn(0, 40, 64, 0.5f));
|
||||
REQUIRE(region.registerNoteOn(0, 40, 60, 0.5f));
|
||||
REQUIRE(region.registerNoteOn(0, 40, 70, 0.5f));
|
||||
REQUIRE(!region.registerNoteOn(0, 41, 71, 0.5f));
|
||||
REQUIRE(!region.registerNoteOn(0, 41, 59, 0.5f));
|
||||
}
|
||||
SECTION("lochan and hichan")
|
||||
{
|
||||
region.parseOpcode({ "key", "40" });
|
||||
region.parseOpcode({ "lochan", "2" });
|
||||
region.parseOpcode({ "hichan", "4" });
|
||||
REQUIRE(!region.registerNoteOn(1, 40, 64, 0.5f));
|
||||
REQUIRE(!region.registerNoteOn(0, 40, 64, 0.5f));
|
||||
REQUIRE(region.registerNoteOn(1, 40, 64, 0.5f));
|
||||
REQUIRE(region.registerNoteOn(2, 40, 64, 0.5f));
|
||||
REQUIRE(region.registerNoteOn(3, 40, 64, 0.5f));
|
||||
REQUIRE(region.registerNoteOn(4, 40, 64, 0.5f));
|
||||
REQUIRE(!region.registerNoteOn(5, 40, 64, 0.5f));
|
||||
REQUIRE(!region.registerNoteOn(4, 40, 64, 0.5f));
|
||||
}
|
||||
|
||||
SECTION("lorand and hirand")
|
||||
|
|
@ -102,37 +102,37 @@ TEST_CASE("Basic triggers", "Region triggers")
|
|||
region.parseOpcode({ "key", "40" });
|
||||
region.parseOpcode({ "lorand", "0.35" });
|
||||
region.parseOpcode({ "hirand", "0.40" });
|
||||
REQUIRE(!region.registerNoteOn(1, 40, 64, 0.34f));
|
||||
REQUIRE(region.registerNoteOn(1, 40, 64, 0.35f));
|
||||
REQUIRE(region.registerNoteOn(1, 40, 64, 0.36f));
|
||||
REQUIRE(region.registerNoteOn(1, 40, 64, 0.37f));
|
||||
REQUIRE(region.registerNoteOn(1, 40, 64, 0.38f));
|
||||
REQUIRE(region.registerNoteOn(1, 40, 64, 0.39f));
|
||||
REQUIRE(!region.registerNoteOn(1, 40, 64, 0.40f));
|
||||
REQUIRE(!region.registerNoteOn(1, 40, 64, 0.41f));
|
||||
REQUIRE(!region.registerNoteOn(0, 40, 64, 0.34f));
|
||||
REQUIRE(region.registerNoteOn(0, 40, 64, 0.35f));
|
||||
REQUIRE(region.registerNoteOn(0, 40, 64, 0.36f));
|
||||
REQUIRE(region.registerNoteOn(0, 40, 64, 0.37f));
|
||||
REQUIRE(region.registerNoteOn(0, 40, 64, 0.38f));
|
||||
REQUIRE(region.registerNoteOn(0, 40, 64, 0.39f));
|
||||
REQUIRE(!region.registerNoteOn(0, 40, 64, 0.40f));
|
||||
REQUIRE(!region.registerNoteOn(0, 40, 64, 0.41f));
|
||||
}
|
||||
|
||||
SECTION("lorand and hirand on 1.0f")
|
||||
{
|
||||
region.parseOpcode({ "key", "40" });
|
||||
region.parseOpcode({ "lorand", "0.35" });
|
||||
REQUIRE(!region.registerNoteOn(1, 40, 64, 0.34f));
|
||||
REQUIRE(region.registerNoteOn(1, 40, 64, 0.35f));
|
||||
REQUIRE(region.registerNoteOn(1, 40, 64, 1.0f));
|
||||
REQUIRE(!region.registerNoteOn(0, 40, 64, 0.34f));
|
||||
REQUIRE(region.registerNoteOn(0, 40, 64, 0.35f));
|
||||
REQUIRE(region.registerNoteOn(0, 40, 64, 1.0f));
|
||||
}
|
||||
|
||||
SECTION("on_loccN, on_hiccN")
|
||||
{
|
||||
region.parseOpcode({ "on_locc47", "64" });
|
||||
region.parseOpcode({ "on_hicc47", "68" });
|
||||
REQUIRE(!region.registerCC(1, 47, 63));
|
||||
REQUIRE(region.registerCC(1, 47, 64));
|
||||
REQUIRE(region.registerCC(1, 47, 65));
|
||||
REQUIRE(region.registerCC(1, 47, 66));
|
||||
REQUIRE(region.registerCC(1, 47, 67));
|
||||
REQUIRE(region.registerCC(1, 47, 68));
|
||||
REQUIRE(!region.registerCC(1, 47, 69));
|
||||
REQUIRE(!region.registerCC(1, 40, 64));
|
||||
REQUIRE(!region.registerCC(0, 47, 63));
|
||||
REQUIRE(region.registerCC(0, 47, 64));
|
||||
REQUIRE(region.registerCC(0, 47, 65));
|
||||
REQUIRE(region.registerCC(0, 47, 66));
|
||||
REQUIRE(region.registerCC(0, 47, 67));
|
||||
REQUIRE(region.registerCC(0, 47, 68));
|
||||
REQUIRE(!region.registerCC(0, 47, 69));
|
||||
REQUIRE(!region.registerCC(0, 40, 64));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -146,11 +146,11 @@ TEST_CASE("Legato triggers", "Region triggers")
|
|||
region.parseOpcode({ "lokey", "40" });
|
||||
region.parseOpcode({ "hikey", "50" });
|
||||
region.parseOpcode({ "trigger", "first" });
|
||||
REQUIRE(region.registerNoteOn(1, 40, 64, 0.5f));
|
||||
REQUIRE(!region.registerNoteOn(1, 41, 64, 0.5f));
|
||||
region.registerNoteOff(1, 40, 0, 0.5f);
|
||||
region.registerNoteOff(1, 41, 0, 0.5f);
|
||||
REQUIRE(region.registerNoteOn(1, 42, 64, 0.5f));
|
||||
REQUIRE(region.registerNoteOn(0, 40, 64, 0.5f));
|
||||
REQUIRE(!region.registerNoteOn(0, 41, 64, 0.5f));
|
||||
region.registerNoteOff(0, 40, 0, 0.5f);
|
||||
region.registerNoteOff(0, 41, 0, 0.5f);
|
||||
REQUIRE(region.registerNoteOn(0, 42, 64, 0.5f));
|
||||
}
|
||||
|
||||
SECTION("Second note playing")
|
||||
|
|
@ -158,10 +158,10 @@ TEST_CASE("Legato triggers", "Region triggers")
|
|||
region.parseOpcode({ "lokey", "40" });
|
||||
region.parseOpcode({ "hikey", "50" });
|
||||
region.parseOpcode({ "trigger", "legato" });
|
||||
REQUIRE(!region.registerNoteOn(1, 40, 64, 0.5f));
|
||||
REQUIRE(region.registerNoteOn(1, 41, 64, 0.5f));
|
||||
region.registerNoteOff(1, 40, 0, 0.5f);
|
||||
region.registerNoteOff(1, 41, 0, 0.5f);
|
||||
REQUIRE(!region.registerNoteOn(1, 42, 64, 0.5f));
|
||||
REQUIRE(!region.registerNoteOn(0, 40, 64, 0.5f));
|
||||
REQUIRE(region.registerNoteOn(0, 41, 64, 0.5f));
|
||||
region.registerNoteOff(0, 40, 0, 0.5f);
|
||||
region.registerNoteOff(0, 41, 0, 0.5f);
|
||||
REQUIRE(!region.registerNoteOn(0, 42, 64, 0.5f));
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue