diff --git a/clients/jack_client.cpp b/clients/jack_client.cpp index ff09b483..12344e22 100644 --- a/clients/jack_client.cpp +++ b/clients/jack_client.cpp @@ -94,18 +94,18 @@ int process(jack_nframes_t numFrames, void* arg [[maybe_unused]]) switch (midi::status(event.buffer[0])) { case midi::noteOff: // DBG("[MIDI] Note " << +event.buffer[1] << " OFF at time " << event.time); - synth->noteOff(event.time, midi::channel(event.buffer[0]), event.buffer[1], event.buffer[2]); + synth->noteOff(event.time, event.buffer[1], event.buffer[2]); break; case midi::noteOn: // DBG("[MIDI] Note " << +event.buffer[1] << " ON at time " << event.time); - synth->noteOn(event.time, midi::channel(event.buffer[0]), event.buffer[1], event.buffer[2]); + synth->noteOn(event.time, event.buffer[1], event.buffer[2]); break; case midi::polyphonicPressure: // DBG("[MIDI] Polyphonic pressure on at time " << event.time); break; case midi::controlChange: // DBG("[MIDI] CC " << +event.buffer[1] << " at time " << event.time); - synth->cc(event.time, midi::channel(event.buffer[0]), event.buffer[1], event.buffer[2]); + synth->cc(event.time, event.buffer[1], event.buffer[2]); break; case midi::programChange: // DBG("[MIDI] Program change at time " << event.time); @@ -114,7 +114,7 @@ int process(jack_nframes_t numFrames, void* arg [[maybe_unused]]) // DBG("[MIDI] Channel pressure at time " << event.time); break; case midi::pitchBend: - synth->pitchWheel(event.time, midi::channel(event.buffer[0]), midi::buildAndCenterPitch(event.buffer[1], event.buffer[2])); + synth->pitchWheel(event.time, midi::buildAndCenterPitch(event.buffer[1], event.buffer[2])); // DBG("[MIDI] Pitch bend at time " << event.time); break; case midi::systemMessage: @@ -163,7 +163,7 @@ static void done(int sig [[maybe_unused]]) // exit(0); } -ABSL_FLAG(std::string, oversampling, "1x", "Internal oversampling factor (value values are 1x, 2x, 4x, 8x)"); +ABSL_FLAG(std::string, oversampling, "1x", "Internal oversampling factor (value values are x1, x2, x4, x8)"); ABSL_FLAG(uint32_t, preload_size, 8192, "Preloaded value"); int main(int argc, char** argv) diff --git a/lv2/sfizz.c b/lv2/sfizz.c index 7e8e9083..f31c38f3 100644 --- a/lv2/sfizz.c +++ b/lv2/sfizz.c @@ -495,7 +495,6 @@ sfizz_lv2_process_midi_event(sfizz_plugin_t *self, const LV2_Atom_Event *ev) // LV2_DEBUG("[process_midi] Received note on %d/%d at time %ld\n", msg[0], msg[1], ev->time.frames); sfizz_send_note_on(self->synth, (int)ev->time.frames, - (int)MIDI_CHANNEL(msg[0]), (int)msg[1], msg[2]); break; @@ -503,7 +502,6 @@ sfizz_lv2_process_midi_event(sfizz_plugin_t *self, const LV2_Atom_Event *ev) // LV2_DEBUG("[process_midi] Received note off %d/%d at time %ld\n", msg[0], msg[1], ev->time.frames); sfizz_send_note_off(self->synth, (int)ev->time.frames, - (int)MIDI_CHANNEL(msg[0]), (int)msg[1], msg[2]); break; @@ -511,7 +509,6 @@ sfizz_lv2_process_midi_event(sfizz_plugin_t *self, const LV2_Atom_Event *ev) // LV2_DEBUG("[process_midi] Received CC %d/%d at time %ld\n", msg[0], msg[1], ev->time.frames); sfizz_send_cc(self->synth, (int)ev->time.frames, - (int)MIDI_CHANNEL(msg[0]), (int)msg[1], msg[2]); break; @@ -519,7 +516,6 @@ sfizz_lv2_process_midi_event(sfizz_plugin_t *self, const LV2_Atom_Event *ev) // LV2_DEBUG("[process_midi] Received pitch bend %d on channel %d at time %ld\n", PITCH_BUILD_AND_CENTER(msg[1], msg[2]), MIDI_CHANNEL(msg[0]), ev->time.frames); sfizz_send_pitch_wheel(self->synth, (int)ev->time.frames, - (int)MIDI_CHANNEL(msg[0]), PITCH_BUILD_AND_CENTER(msg[1], msg[2])); break; default: @@ -697,7 +693,7 @@ lv2_get_options(LV2_Handle instance, LV2_Options_Option *options) for (LV2_Options_Option *opt = options; opt->value; ++opt) { if (self->unmap) { - LV2_DEBUG("[DEBUG] Called for an option with key (subject): %s (%s) \n", + LV2_DEBUG("[DEBUG] Called for an option with key (subject): %s (%s) \n", self->unmap->unmap(self->unmap->handle, opt->key), self->unmap->unmap(self->unmap->handle, opt->subject)); } @@ -963,7 +959,7 @@ work_response(LV2_Handle instance, const LV2_Atom *atom = (const LV2_Atom *)data; if (atom->type == self->sfizz_sfz_file_uri) - { + { self->changing_state = false; } else if (atom->type == self->sfizz_num_voices_uri) diff --git a/src/sfizz.h b/src/sfizz.h index 02190061..acc6c61a 100644 --- a/src/sfizz.h +++ b/src/sfizz.h @@ -141,64 +141,59 @@ void sfizz_set_sample_rate(sfizz_synth_t* synth, float sample_rate); /** * @brief Send a note on event to the synth. As with all MIDI events, this * needs to happen before the call to sfizz_render_block in each - * block and should appear in order of the delays, at least within a channel. + * block and should appear in order of the delays. * * @param synth The synth * @param delay the delay of the event in the block, in samples. - * @param channel the MIDI channel (starting at 0 for the first channel) * @param note_number the MIDI note number * @param velocity the MIDI velocity */ -void sfizz_send_note_on(sfizz_synth_t* synth, int delay, int channel, int note_number, char velocity); +void sfizz_send_note_on(sfizz_synth_t* synth, int delay, int note_number, char velocity); /** * @brief Send a note off event to the synth. As with all MIDI events, this * needs to happen before the call to sfizz_render_block in each - * block and should appear in order of the delays, at least within a channel. - * As per the SFZ spec the velocity of note-off events is usually replaced by + * block and should appear in order of the delays. + * As per the SFZ spec the velocity of note-off events is usually replaced by * the note-on velocity. * * @param synth The synth * @param delay the delay of the event in the block, in samples. - * @param channel the MIDI channel (starting at 0 for the first channel) * @param note_number the MIDI note number * @param velocity the MIDI velocity */ -void sfizz_send_note_off(sfizz_synth_t* synth, int delay, int channel, int note_number, char velocity); +void sfizz_send_note_off(sfizz_synth_t* synth, int delay, int note_number, char velocity); /** * @brief Send a CC event to the synth. As with all MIDI events, this needs - * to happen before the call to sfizz_render_block in each block and - * should appear in order of the delays, at least within a channel. + * to happen before the call to sfizz_render_block in each block and + * should appear in order of the delays. * * @param synth The synth * @param delay the delay of the event in the block, in samples. - * @param channel the MIDI channel (starting at 0 for the first channel) * @param cc_number the MIDI CC number * @param cc_value the MIDI CC value */ -void sfizz_send_cc(sfizz_synth_t* synth, int delay, int channel, int cc_number, char cc_value); +void sfizz_send_cc(sfizz_synth_t* synth, int delay, int cc_number, char cc_value); /** * @brief Send a pitch wheel event. As with all MIDI events, this needs - * to happen before the call to sfizz_render_block in each block and - * should appear in order of the delays, at least within a channel. + * to happen before the call to sfizz_render_block in each block and + * should appear in order of the delays. * * @param synth The synth * @param delay The delay - * @param channel The channel * @param pitch The pitch */ -void sfizz_send_pitch_wheel(sfizz_synth_t* synth, int delay, int channel, int pitch); +void sfizz_send_pitch_wheel(sfizz_synth_t* synth, int delay, int pitch); /** * @brief Send an aftertouch event. (CURRENTLY UNIMPLEMENTED) * * @param synth * @param delay - * @param channel * @param aftertouch */ -void sfizz_send_aftertouch(sfizz_synth_t* synth, int delay, int channel, char aftertouch); +void sfizz_send_aftertouch(sfizz_synth_t* synth, int delay, char aftertouch); /** * @brief Send a tempo event. (CURRENTLY UNIMPLEMENTED) diff --git a/src/sfizz/MidiState.cpp b/src/sfizz/MidiState.cpp index f46167cd..bbee8ef6 100644 --- a/src/sfizz/MidiState.cpp +++ b/src/sfizz/MidiState.cpp @@ -6,99 +6,84 @@ sfz::MidiState::MidiState() reset(); } -void sfz::MidiState::noteOnEvent(int channel, int noteNumber, uint8_t velocity) noexcept +void sfz::MidiState::noteOnEvent(int noteNumber, uint8_t velocity) noexcept { - ASSERT(channel >= 0 && channel < 16); ASSERT(noteNumber >= 0 && noteNumber <= 127); ASSERT(velocity >= 0 && velocity <= 127); - + if (noteNumber >= 0 && noteNumber < 128) { - lastNoteVelocities[channel][noteNumber] = velocity; - noteOnTimes[channel][noteNumber] = std::chrono::steady_clock::now(); + lastNoteVelocities[noteNumber] = velocity; + noteOnTimes[noteNumber] = std::chrono::steady_clock::now(); } } -float sfz::MidiState::getNoteDuration(int channel, int noteNumber) const +float sfz::MidiState::getNoteDuration(int noteNumber) const { - ASSERT(channel >= 0 && channel < 16); ASSERT(noteNumber >= 0 && noteNumber <= 127); - + if (noteNumber >= 0 && noteNumber < 128) { const auto noteOffTime = std::chrono::steady_clock::now(); - const auto duration = std::chrono::duration_cast>(noteOffTime - noteOnTimes[channel][noteNumber]); + const auto duration = std::chrono::duration_cast>(noteOffTime - noteOnTimes[noteNumber]); return duration.count(); } return 0.0f; } -uint8_t sfz::MidiState::getNoteVelocity(int channel, int noteNumber) const noexcept +uint8_t sfz::MidiState::getNoteVelocity(int noteNumber) const noexcept { - ASSERT(channel >= 0 && channel < 16); ASSERT(noteNumber >= 0 && noteNumber <= 127); - - return lastNoteVelocities[channel][noteNumber]; + + return lastNoteVelocities[noteNumber]; } -void sfz::MidiState::pitchBendEvent(int channel, int pitchBendValue) noexcept +void sfz::MidiState::pitchBendEvent(int pitchBendValue) noexcept { - ASSERT(channel >= 0 && channel < 16); ASSERT(pitchBendValue >= -8192 && pitchBendValue <= 8192); - - pitchBends[channel] = pitchBendValue; + + pitchBend = pitchBendValue; } -int sfz::MidiState::getPitchBend(int channel) const noexcept +int sfz::MidiState::getPitchBend() const noexcept { - ASSERT(channel >= 0 && channel < 16); - - return pitchBends[channel]; + return pitchBend; } -void sfz::MidiState::ccEvent(int channel, int ccNumber, uint8_t ccValue) noexcept +void sfz::MidiState::ccEvent(int ccNumber, uint8_t ccValue) noexcept { - ASSERT(channel >= 0 && channel < 16); ASSERT(ccNumber >= 0 && ccNumber < config::numCCs); ASSERT(ccValue >= 0 && ccValue <= 127); - - cc[channel][ccNumber] = ccValue; + + cc[ccNumber] = ccValue; } -uint8_t sfz::MidiState::getCCValue(int channel, int ccNumber) const noexcept +uint8_t sfz::MidiState::getCCValue(int ccNumber) const noexcept { - ASSERT(channel >= 0 && channel < 16); ASSERT(ccNumber >= 0 && ccNumber < config::numCCs); - - return cc[channel][ccNumber]; + + return cc[ccNumber]; } -const sfz::SfzCCArray& sfz::MidiState::getCCArray(int channel) const noexcept +const sfz::SfzCCArray& sfz::MidiState::getCCArray() const noexcept { - ASSERT(channel >= 0 && channel < 16); - - return cc[channel]; + return cc; } void sfz::MidiState::reset() noexcept { - for (auto& channelArray: lastNoteVelocities) - for (auto& velocity: channelArray) - velocity = 0; + for (auto& velocity: lastNoteVelocities) + velocity = 0; - for (auto& channelArray: cc) - for (auto& ccValue: channelArray) - ccValue = 0; + for (auto& ccValue: cc) + ccValue = 0; - for (auto& bendValue: pitchBends) - bendValue = 0; + pitchBend = 0; } -void sfz::MidiState::resetAllControllers(int channel) noexcept +void sfz::MidiState::resetAllControllers() noexcept { - ASSERT(channel >= 0 && channel < 16); - for (int idx = 0; idx < config::numCCs; idx++) - cc[channel][idx] = 0; + cc[idx] = 0; - pitchBends[channel] = 0; -} \ No newline at end of file + pitchBend = 0; +} diff --git a/src/sfizz/MidiState.h b/src/sfizz/MidiState.h index f23449ee..97ed5c91 100644 --- a/src/sfizz/MidiState.h +++ b/src/sfizz/MidiState.h @@ -18,88 +18,76 @@ public: /** * @brief Update the state after a note on event * - * @param channel (0-based) * @param noteNumber * @param velocity */ - void noteOnEvent(int channel, int noteNumber, uint8_t velocity) noexcept; + void noteOnEvent(int noteNumber, uint8_t velocity) noexcept; /** * @brief Register a note off and get the note duration * - * @param channel (0-based) * @param noteNumber * @return float */ - float getNoteDuration(int channel, int noteNumber) const; + float getNoteDuration(int noteNumber) const; /** * @brief Get the note on velocity for a given note * - * @param channel (0-based) * @param noteNumber * @return uint8_t */ - uint8_t getNoteVelocity(int channel, int noteNumber) const noexcept; + uint8_t getNoteVelocity(int noteNumber) const noexcept; /** * @brief Register a pitch bend event - * - * @param channel - * @param pitchBendValue + * + * @param pitchBendValue */ - void pitchBendEvent(int channel, int pitchBendValue) noexcept; + void pitchBendEvent(int pitchBendValue) noexcept; /** - * @brief Get the pitch bend status on a channel - * - * @param channel - * @return int + * @brief Get the pitch bend status + + * @return int */ - int getPitchBend(int channel) const noexcept; + int getPitchBend() const noexcept; /** * @brief Register a CC event - * - * @param channel - * @param ccNumber - * @param ccValue + * + * @param ccNumber + * @param ccValue */ - void ccEvent(int channel, int ccNumber, uint8_t ccValue) noexcept; + void ccEvent(int ccNumber, uint8_t ccValue) noexcept; /** - * @brief Get the CC value for a specific channel and cc number - * - * @param channel - * @param ccNumber - * @return uint8_t + * @brief Get the CC value for CC number + * + * @param ccNumber + * @return uint8_t */ - uint8_t getCCValue(int channel, int ccNumber) const noexcept; + uint8_t getCCValue(int ccNumber) const noexcept; /** - * @brief Get the full CC status for a specific channel - * - * @param channel - * @return const SfzCCArray& + * @brief Get the full CC status + * + * @return const SfzCCArray& */ - const SfzCCArray& getCCArray(int channel) const noexcept; + const SfzCCArray& getCCArray() const noexcept; /** * @brief Reset the midi state (does not impact the last note on time) - * + * */ void reset() noexcept; /** - * @brief Res - * - * @param channel + * @brief Reset all the controllers */ - void resetAllControllers(int channel) noexcept; + void resetAllControllers() noexcept; private: - template - using ChannelArray = std::array; template using MidiNoteArray = std::array; using NoteOnTime = std::chrono::steady_clock::time_point; @@ -107,21 +95,21 @@ private: * @brief Stores the note on times. * */ - ChannelArray> noteOnTimes { }; + MidiNoteArray noteOnTimes { }; /** * @brief Stores the velocity of the note ons for currently * depressed notes. * */ - ChannelArray> lastNoteVelocities { }; + MidiNoteArray lastNoteVelocities { }; /** * @brief Current known values for the CCs. * */ - ChannelArray cc; + SfzCCArray cc; /** * Pitch bend status */ - ChannelArray pitchBends { 0 }; + int pitchBend { 0 }; }; } diff --git a/src/sfizz/Region.cpp b/src/sfizz/Region.cpp index 1893d67a..42bc0d08 100644 --- a/src/sfizz/Region.cpp +++ b/src/sfizz/Region.cpp @@ -144,20 +144,6 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) break; // Region logic: MIDI conditions - case hash("lochan"): - { - const auto value = readOpcode(opcode.value, Default::channelRange); - if (value) - channelRange.setStart(*value - 1); - } - break; - case hash("hichan"): - { - const auto value = readOpcode(opcode.value, Default::channelRange); - if (value) - channelRange.setEnd(*value - 1); - } - break; case hash("lobend"): setRangeStartFromOpcode(opcode, bendRange, Default::bendRange); break; @@ -500,6 +486,8 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) break; // Ignored opcodes + case hash("hichan"): + case hash("lochan"): case hash("ampeg_depth"): case hash("ampeg_vel2depth"): break; @@ -515,12 +503,8 @@ bool sfz::Region::isSwitchedOn() const noexcept return keySwitched && previousKeySwitched && sequenceSwitched && pitchSwitched && bpmSwitched && aftertouchSwitched && ccSwitched.all(); } -bool sfz::Region::registerNoteOn(int channel, int noteNumber, uint8_t velocity, float randValue) noexcept +bool sfz::Region::registerNoteOn(int noteNumber, uint8_t velocity, float randValue) noexcept { - const bool chanOk = channelRange.containsWithEnd(channel); - if (!chanOk) - return false; - if (keyswitchRange.containsWithEnd(noteNumber)) { if (keyswitch) { if (*keyswitch == noteNumber) @@ -571,15 +555,11 @@ bool sfz::Region::registerNoteOn(int channel, int noteNumber, uint8_t velocity, const bool attackTrigger = (trigger == SfzTrigger::attack); const bool notFirstLegatoNote = (trigger == SfzTrigger::legato && activeNotesInRange > 0); - return keyOk && velOk && chanOk && randOk && (attackTrigger || firstLegatoNote || notFirstLegatoNote); + return keyOk && velOk && randOk && (attackTrigger || firstLegatoNote || notFirstLegatoNote); } -bool sfz::Region::registerNoteOff(int channel, int noteNumber, uint8_t velocity [[maybe_unused]], float randValue) noexcept +bool sfz::Region::registerNoteOff(int noteNumber, uint8_t velocity [[maybe_unused]], float randValue) noexcept { - const bool chanOk = channelRange.containsWithEnd(channel); - if (!chanOk) - return false; - if (keyswitchRange.containsWithEnd(noteNumber)) { if (keyswitchDown && *keyswitchDown == noteNumber) keySwitched = false; @@ -603,14 +583,11 @@ bool sfz::Region::registerNoteOff(int channel, int noteNumber, uint8_t velocity const bool velOk = velocityRange.containsWithEnd(velocity); const bool randOk = randRange.contains(randValue); const bool releaseTrigger = (trigger == SfzTrigger::release || trigger == SfzTrigger::release_key); - return keyOk && velOk && chanOk && randOk && releaseTrigger; + return keyOk && velOk && randOk && releaseTrigger; } -bool sfz::Region::registerCC(int channel, int ccNumber, uint8_t ccValue) noexcept +bool sfz::Region::registerCC(int ccNumber, uint8_t ccValue) noexcept { - if (!channelRange.containsWithEnd(channel)) - return false; - if (ccConditions.getWithDefault(ccNumber).containsWithEnd(ccValue)) ccSwitched.set(ccNumber, true); else @@ -628,22 +605,16 @@ bool sfz::Region::registerCC(int channel, int ccNumber, uint8_t ccValue) noexcep return false; } -void sfz::Region::registerPitchWheel(int channel, int pitch) noexcept +void sfz::Region::registerPitchWheel(int pitch) noexcept { - if (!channelRange.containsWithEnd(channel)) - return; - if (bendRange.containsWithEnd(pitch)) pitchSwitched = true; else pitchSwitched = false; } -void sfz::Region::registerAftertouch(int channel, uint8_t aftertouch) noexcept +void sfz::Region::registerAftertouch(uint8_t aftertouch) noexcept { - if (!channelRange.containsWithEnd(channel)) - return; - if (aftertouchRange.containsWithEnd(aftertouch)) aftertouchSwitched = true; else @@ -669,11 +640,11 @@ float sfz::Region::getBasePitchVariation(int noteNumber, uint8_t velocity) noexc return centsFactor(pitchVariationInCents); } -float sfz::Region::getBaseVolumedB(int channel, int noteNumber) noexcept +float sfz::Region::getBaseVolumedB(int noteNumber) noexcept { auto baseVolumedB = volume + volumeDistribution(Random::randomGenerator); if (trigger == SfzTrigger::release || trigger == SfzTrigger::release_key) - baseVolumedB -= rtDecay * midiState.getNoteDuration(channel, noteNumber); + baseVolumedB -= rtDecay * midiState.getNoteDuration(noteNumber); return baseVolumedB; } diff --git a/src/sfizz/Region.h b/src/sfizz/Region.h index c2b0c6cc..3d1a3bae 100644 --- a/src/sfizz/Region.h +++ b/src/sfizz/Region.h @@ -90,7 +90,6 @@ 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 (0-based) * @param noteNumber * @param velocity * @param randValue a random value between 0 and 1 used to randomize a bit the region activations @@ -98,12 +97,11 @@ struct Region { * @return true if the region should trigger on this event. * @return false */ - bool registerNoteOn(int channel, int noteNumber, uint8_t velocity, float randValue) noexcept; + bool registerNoteOn(int noteNumber, uint8_t velocity, float randValue) noexcept; /** * @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 (0-based) * @param noteNumber * @param velocity * @param randValue a random value between 0 and 1 used to randomize a bit the region activations @@ -111,32 +109,29 @@ struct Region { * @return true if the region should trigger on this event. * @return false */ - bool registerNoteOff(int channel, int noteNumber, uint8_t velocity, float randValue) noexcept; + bool registerNoteOff(int noteNumber, uint8_t velocity, float randValue) noexcept; /** * @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 (0-based) * @param ccNumber * @param ccValue * @return true if the region should trigger on this event * @return false */ - bool registerCC(int channel, int ccNumber, uint8_t ccValue) noexcept; + bool registerCC(int ccNumber, uint8_t ccValue) noexcept; /** * @brief Register a new pitch wheel event. * - * @param channel MIDI channel (0-based) * @param pitch */ - void registerPitchWheel(int channel, int pitch) noexcept; + void registerPitchWheel(int pitch) noexcept; /** * @brief Register a new aftertouch event. * - * @param channel MIDI channel (0-based) * @param aftertouch */ - void registerAftertouch(int channel, uint8_t aftertouch) noexcept; + void registerAftertouch(uint8_t aftertouch) noexcept; /** * @brief Register tempo * @@ -174,11 +169,10 @@ struct Region { * @brief Get the base volume of the region depending on which note has been * pressed to trigger the region. * - * @param channel (0-based) * @param noteNumber * @return float */ - float getBaseVolumedB(int channel, int noteNumber) noexcept; + float getBaseVolumedB(int noteNumber) noexcept; /** * @brief Get the base gain of the region. * @@ -246,7 +240,6 @@ struct Region { Range velocityRange { Default::velocityRange }; // hivel and lovel // Region logic: MIDI conditions - Range channelRange { Default::midiChannelRange }; //lochan and hichan Range bendRange { Default::bendRange }; // hibend and lobend CCMap> ccConditions { Default::ccValueRange }; Range keyswitchRange { Default::keyRange }; // sw_hikey and sw_lokey diff --git a/src/sfizz/Synth.cpp b/src/sfizz/Synth.cpp index a0a0e3a3..8bee185c 100644 --- a/src/sfizz/Synth.cpp +++ b/src/sfizz/Synth.cpp @@ -173,8 +173,7 @@ void sfz::Synth::handleControlOpcodes(const std::vector& members) case hash("set_cc"): if (member.parameter && Default::ccNumberRange.containsWithEnd(*member.parameter)) { const auto ccValue = readOpcode(member.value, Default::ccValueRange).value_or(0); - for (int channel = 0; channel < 16; channel++) - midiState.ccEvent(channel, *member.parameter, ccValue); + midiState.ccEvent(*member.parameter, ccValue); } break; case hash("Label_cc"): @@ -272,18 +271,17 @@ bool sfz::Synth::loadSfzFile(const fs::path& filename) // Defaults for (int ccIndex = 0; ccIndex < config::numCCs; ccIndex++) { - const auto channel = region->channelRange.getStart(); - region->registerCC(channel, ccIndex, midiState.getCCValue(channel, ccIndex)); + region->registerCC(ccIndex, midiState.getCCValue(ccIndex)); } if (defaultSwitch) { - region->registerNoteOn(region->channelRange.getStart(), *defaultSwitch, 127, 1.0); - region->registerNoteOff(region->channelRange.getStart(), *defaultSwitch, 0, 1.0); + region->registerNoteOn(*defaultSwitch, 127, 1.0); + region->registerNoteOff(*defaultSwitch, 0, 1.0); } addEndpointsToVelocityCurve(*region); - region->registerPitchWheel(region->channelRange.getStart(), 0); - region->registerAftertouch(region->channelRange.getStart(), 0); + region->registerPitchWheel(0); + region->registerAftertouch(0); region->registerTempo(2.0f); currentRegion++; @@ -386,12 +384,12 @@ void sfz::Synth::renderBlock(AudioSpan buffer) noexcept buffer.applyGain(db2mag(volume)); } -void sfz::Synth::noteOn(int delay, int channel, int noteNumber, uint8_t velocity) noexcept +void sfz::Synth::noteOn(int delay, int noteNumber, uint8_t velocity) noexcept { ASSERT(noteNumber < 128); ASSERT(noteNumber >= 0); - midiState.noteOnEvent(channel, noteNumber, velocity); + midiState.noteOnEvent(noteNumber, velocity); AtomicGuard callbackGuard { inCallback }; if (!canEnterCallback) @@ -400,22 +398,22 @@ void sfz::Synth::noteOn(int delay, int channel, int noteNumber, uint8_t velocity auto randValue = randNoteDistribution(Random::randomGenerator); for (auto& region : noteActivationLists[noteNumber]) { - if (region->registerNoteOn(channel, noteNumber, velocity, randValue)) { + if (region->registerNoteOn(noteNumber, velocity, randValue)) { for (auto& voice : voices) { if (voice->checkOffGroup(delay, region->group)) - noteOff(delay, voice->getTriggerChannel(), voice->getTriggerNumber(), 0); + noteOff(delay, voice->getTriggerNumber(), 0); } auto voice = findFreeVoice(); if (voice == nullptr) continue; - voice->startVoice(region, delay, channel, noteNumber, velocity, Voice::TriggerType::NoteOn); + voice->startVoice(region, delay, noteNumber, velocity, Voice::TriggerType::NoteOn); } } } -void sfz::Synth::noteOff(int delay, int channel, int noteNumber, uint8_t velocity [[maybe_unused]]) noexcept +void sfz::Synth::noteOff(int delay, int noteNumber, uint8_t velocity [[maybe_unused]]) noexcept { ASSERT(noteNumber < 128); ASSERT(noteNumber >= 0); @@ -427,24 +425,24 @@ void sfz::Synth::noteOff(int delay, int channel, int noteNumber, uint8_t velocit // FIXME: Some keyboards (e.g. Casio PX5S) can send a real note-off velocity. In this case, do we have a // way in sfz to specify that a release trigger should NOT use the note-on velocity? // auto replacedVelocity = (velocity == 0 ? sfz::getNoteVelocity(noteNumber) : velocity); - auto replacedVelocity = midiState.getNoteVelocity(channel, noteNumber); + auto replacedVelocity = midiState.getNoteVelocity(noteNumber); auto randValue = randNoteDistribution(Random::randomGenerator); for (auto& voice : voices) - voice->registerNoteOff(delay, channel, noteNumber, replacedVelocity); + voice->registerNoteOff(delay, noteNumber, replacedVelocity); for (auto& region : noteActivationLists[noteNumber]) { - if (region->registerNoteOff(channel, noteNumber, replacedVelocity, randValue)) { + if (region->registerNoteOff(noteNumber, replacedVelocity, randValue)) { auto voice = findFreeVoice(); if (voice == nullptr) continue; - voice->startVoice(region, delay, channel, noteNumber, replacedVelocity, Voice::TriggerType::NoteOff); + voice->startVoice(region, delay, noteNumber, replacedVelocity, Voice::TriggerType::NoteOff); } } } -void sfz::Synth::cc(int delay, int channel, int ccNumber, uint8_t ccValue) noexcept +void sfz::Synth::cc(int delay, int ccNumber, uint8_t ccValue) noexcept { ASSERT(ccNumber < config::numCCs); ASSERT(ccNumber >= 0); @@ -454,36 +452,36 @@ void sfz::Synth::cc(int delay, int channel, int ccNumber, uint8_t ccValue) noexc return; if (ccNumber == config::resetCC) { - resetAllControllers(delay, channel); + resetAllControllers(delay); return; } - midiState.ccEvent(channel, ccNumber, ccValue); + midiState.ccEvent(ccNumber, ccValue); for (auto& voice : voices) - voice->registerCC(delay, channel, ccNumber, ccValue); + voice->registerCC(delay, ccNumber, ccValue); for (auto& region : ccActivationLists[ccNumber]) { - if (region->registerCC(channel, ccNumber, ccValue)) { + if (region->registerCC(ccNumber, ccValue)) { auto voice = findFreeVoice(); if (voice == nullptr) continue; - voice->startVoice(region, delay, channel, ccNumber, ccValue, Voice::TriggerType::CC); + voice->startVoice(region, delay, ccNumber, ccValue, Voice::TriggerType::CC); } } } -void sfz::Synth::pitchWheel(int delay, int channel, int pitch) noexcept +void sfz::Synth::pitchWheel(int delay, int pitch) noexcept { ASSERT(pitch <= 8192); ASSERT(pitch >= -8192); - midiState.pitchBendEvent(channel, pitch); + midiState.pitchBendEvent(pitch); for (auto& voice: voices) { - voice->registerPitchWheel(delay, channel, pitch); + voice->registerPitchWheel(delay, pitch); } } -void sfz::Synth::aftertouch(int /* delay */, int /*channel*/, uint8_t /* aftertouch */) noexcept +void sfz::Synth::aftertouch(int /* delay */, uint8_t /* aftertouch */) noexcept { } void sfz::Synth::tempo(int /* delay */, float /* secondsPerQuarter */) noexcept @@ -617,21 +615,21 @@ void sfz::Synth::disableFreeWheeling() noexcept } } -void sfz::Synth::resetAllControllers(int delay, int channel) noexcept +void sfz::Synth::resetAllControllers(int delay) noexcept { AtomicGuard callbackGuard { inCallback }; if (!canEnterCallback) return; - midiState.resetAllControllers(channel); + midiState.resetAllControllers(); for (auto& voice: voices) { - voice->registerPitchWheel(delay, channel, 0); + voice->registerPitchWheel(delay, 0); for (int cc = 0; cc < config::numCCs; ++cc) - voice->registerCC(delay, channel, cc, 0); + voice->registerCC(delay, cc, 0); } for (auto& region: regions) { for (int cc = 0; cc < config::numCCs; ++cc) - region->registerCC(channel, cc, 0); + region->registerCC(cc, 0); } } diff --git a/src/sfizz/Synth.h b/src/sfizz/Synth.h index 5dca692f..1ef07d09 100644 --- a/src/sfizz/Synth.h +++ b/src/sfizz/Synth.h @@ -69,7 +69,7 @@ namespace sfz { * synth should have a delay parameter strictly lower than 256. Events beyond 256 * may be completely ignored by the synth as the incoming event buffer is cleared * during the renderBlock() call. You SHOULD also feed the midi events in the correct - * order, at least within a channel. + * order. * * The jack_client.cpp file contains examples of the most classical usage of the * synth and can be used as a reference. @@ -196,50 +196,45 @@ public: * * @param delay the delay at which the event occurs; this should be lower * than the size of the block in the next call to renderBlock(). - * @param channel the midi channel for the event (0-based) * @param noteNumber the midi note number * @param velocity the midi note velocity */ - void noteOn(int delay, int channel, int noteNumber, uint8_t velocity) noexcept; + void noteOn(int delay, int noteNumber, uint8_t velocity) noexcept; /** * @brief Send a note off event to the synth * * @param delay the delay at which the event occurs; this should be lower * than the size of the block in the next call to renderBlock(). - * @param channel the midi channel for the event (0-based) * @param noteNumber the midi note number * @param velocity the midi note velocity */ - void noteOff(int delay, int channel, int noteNumber, uint8_t velocity) noexcept; + void noteOff(int delay, int noteNumber, uint8_t velocity) noexcept; /** * @brief Send a CC event to the synth * * @param delay the delay at which the event occurs; this should be lower than the size of * the block in the next call to renderBlock(). - * @param channel the midi channel for the event (0-based) * @param ccNumber the cc number * @param ccValue the cc value */ - void cc(int delay, int channel, int ccNumber, uint8_t ccValue) noexcept; + void cc(int delay, int ccNumber, uint8_t ccValue) noexcept; /** * @brief Send a pitch bend event to the synth * * @param delay the delay at which the event occurs; this should be lower * than the size of the block in the next call to * renderBlock(). - * @param channel the midi channel for the event (0-based) * @param pitch the pitch value centered between -8192 and 8192 */ - void pitchWheel(int delay, int channel, int pitch) noexcept; + void pitchWheel(int delay, int pitch) noexcept; /** * @brief Send a aftertouch event to the synth * * @param delay the delay at which the event occurs; this should be lower than the size of * the block in the next call to renderBlock(). - * @param channel the midi channel for the event (0-based) * @param aftertouch the aftertouch value */ - void aftertouch(int delay, int channel, uint8_t aftertouch) noexcept; + void aftertouch(int delay, uint8_t aftertouch) noexcept; /** * @brief Send a tempo event to the synth * @@ -363,10 +358,9 @@ private: * @brief Reset all CCs; to be used on CC 121 * * @param delay the delay for the controller reset - * @param channel the channel on which to reset the controller * */ - void resetAllControllers(int delay, int channel) noexcept; + void resetAllControllers(int delay) noexcept; int numGroups { 0 }; int numMasters { 0 }; diff --git a/src/sfizz/Voice.cpp b/src/sfizz/Voice.cpp index 227dc2e3..d7800a8f 100644 --- a/src/sfizz/Voice.cpp +++ b/src/sfizz/Voice.cpp @@ -36,11 +36,10 @@ sfz::Voice::Voice(const sfz::MidiState& midiState, sfz::Resources& resources) { } -void sfz::Voice::startVoice(Region* region, int delay, int channel, int number, uint8_t value, sfz::Voice::TriggerType triggerType) noexcept +void sfz::Voice::startVoice(Region* region, int delay, int number, uint8_t value, sfz::Voice::TriggerType triggerType) noexcept { this->triggerType = triggerType; triggerNumber = number; - triggerChannel = channel; triggerValue = value; this->region = region; @@ -60,39 +59,39 @@ void sfz::Voice::startVoice(Region* region, int delay, int channel, int number, } pitchRatio = region->getBasePitchVariation(number, value); - baseVolumedB = region->getBaseVolumedB(channel, number); + baseVolumedB = region->getBaseVolumedB(number); auto volumedB { baseVolumedB }; if (region->volumeCC) - volumedB += normalizeCC(midiState.getCCValue(channel, region->volumeCC->first)) * region->volumeCC->second; + volumedB += normalizeCC(midiState.getCCValue(region->volumeCC->first)) * region->volumeCC->second; volumeEnvelope.reset(db2mag(volumedB)); baseGain = region->getBaseGain(); - baseGain *= region->getCrossfadeGain(midiState.getCCArray(channel)); + baseGain *= region->getCrossfadeGain(midiState.getCCArray()); if (triggerType != TriggerType::CC) baseGain *= region->getNoteGain(number, value); float gain { baseGain }; if (region->amplitudeCC) - gain *= normalizeCC(midiState.getCCValue(channel, region->amplitudeCC->first)) * normalizePercents(region->amplitudeCC->second); + gain *= normalizeCC(midiState.getCCValue(region->amplitudeCC->first)) * normalizePercents(region->amplitudeCC->second); amplitudeEnvelope.reset(gain); basePan = normalizeNegativePercents(region->pan); auto pan { basePan }; if (region->panCC) - pan += normalizeCC(midiState.getCCValue(channel, region->panCC->first)) * normalizeNegativePercents(region->panCC->second); + pan += normalizeCC(midiState.getCCValue(region->panCC->first)) * normalizeNegativePercents(region->panCC->second); panEnvelope.reset(pan); basePosition = normalizeNegativePercents(region->position); auto position { basePosition }; if (region->positionCC) - position += normalizeCC(midiState.getCCValue(channel, region->positionCC->first)) * normalizeNegativePercents(region->positionCC->second); + position += normalizeCC(midiState.getCCValue(region->positionCC->first)) * normalizeNegativePercents(region->positionCC->second); positionEnvelope.reset(position); baseWidth = normalizeNegativePercents(region->width); auto width { baseWidth }; if (region->widthCC) - width += normalizeCC(midiState.getCCValue(channel, region->widthCC->first)) * normalizeNegativePercents(region->widthCC->second); + width += normalizeCC(midiState.getCCValue(region->widthCC->first)) * normalizeNegativePercents(region->widthCC->second); widthEnvelope.reset(width); pitchBendEnvelope.setFunction([region](float pitchValue){ @@ -100,21 +99,21 @@ void sfz::Voice::startVoice(Region* region, int delay, int channel, int number, const auto bendInCents = normalizedBend > 0 ? normalizedBend * region->bendUp : -normalizedBend * region->bendDown; return centsFactor(bendInCents); }); - pitchBendEnvelope.reset(midiState.getPitchBend(channel)); + pitchBendEnvelope.reset(midiState.getPitchBend()); sourcePosition = region->getOffset(); initialDelay = delay + static_cast(region->getDelay() * sampleRate); baseFrequency = midiNoteFrequency(number); bendStepFactor = centsFactor(region->bendStep); - prepareEGEnvelope(channel, initialDelay, value); + prepareEGEnvelope(initialDelay, value); } -void sfz::Voice::prepareEGEnvelope(int channel, int delay, uint8_t velocity) noexcept +void sfz::Voice::prepareEGEnvelope(int delay, uint8_t velocity) noexcept { auto secondsToSamples = [this](auto timeInSeconds) { return static_cast(timeInSeconds * sampleRate); }; - const auto& ccArray = midiState.getCCArray(channel); + const auto& ccArray = midiState.getCCArray(); egEnvelope.reset( secondsToSamples(region->amplitudeEG.getAttack(ccArray, velocity)), secondsToSamples(region->amplitudeEG.getRelease(ccArray, velocity)), @@ -143,7 +142,7 @@ void sfz::Voice::release(int delay, bool fastRelease) noexcept } } -void sfz::Voice::registerNoteOff(int delay, int channel, int noteNumber, uint8_t velocity [[maybe_unused]]) noexcept +void sfz::Voice::registerNoteOff(int delay, int noteNumber, uint8_t velocity [[maybe_unused]]) noexcept { if (region == nullptr) return; @@ -151,18 +150,18 @@ void sfz::Voice::registerNoteOff(int delay, int channel, int noteNumber, uint8_t if (state != State::playing) return; - if (triggerChannel == channel && triggerNumber == noteNumber) { + if (triggerNumber == noteNumber) { noteIsOff = true; if (region->loopMode == SfzLoopMode::one_shot) return; - if (!region->checkSustain || midiState.getCCValue(channel, config::sustainCC) < config::halfCCThreshold) + if (!region->checkSustain || midiState.getCCValue(config::sustainCC) < config::halfCCThreshold) release(delay); } } -void sfz::Voice::registerCC(int delay, int channel, int ccNumber, uint8_t ccValue) noexcept +void sfz::Voice::registerCC(int delay, int ccNumber, uint8_t ccValue) noexcept { if (region == nullptr) return; @@ -170,9 +169,6 @@ void sfz::Voice::registerCC(int delay, int channel, int ccNumber, uint8_t ccValu if (state == State::idle) return; - if (triggerChannel != channel) - return; - if (ccNumber == config::allNotesOffCC || ccNumber == config::allSoundOffCC) { reset(); return; @@ -207,21 +203,15 @@ void sfz::Voice::registerCC(int delay, int channel, int ccNumber, uint8_t ccValu } } -void sfz::Voice::registerPitchWheel(int delay, int channel, int pitch) noexcept +void sfz::Voice::registerPitchWheel(int delay, int pitch) noexcept { - if (channel != triggerChannel) - return; - if (state == State::idle) return; - if (triggerChannel != channel) - return; - pitchBendEnvelope.registerEvent(delay, pitch); } -void sfz::Voice::registerAftertouch(int delay [[maybe_unused]], int channel [[maybe_unused]], uint8_t aftertouch [[maybe_unused]]) noexcept +void sfz::Voice::registerAftertouch(int delay [[maybe_unused]], uint8_t aftertouch [[maybe_unused]]) noexcept { // TODO } @@ -511,11 +501,6 @@ int sfz::Voice::getTriggerNumber() const noexcept return triggerNumber; } -int sfz::Voice::getTriggerChannel() const noexcept -{ - return triggerChannel; -} - uint8_t sfz::Voice::getTriggerValue() const noexcept { return triggerValue; diff --git a/src/sfizz/Voice.h b/src/sfizz/Voice.h index 289a6cf1..89bec831 100644 --- a/src/sfizz/Voice.h +++ b/src/sfizz/Voice.h @@ -92,54 +92,48 @@ public: * * @param region * @param delay - * @param channel (0-based) * @param number * @param value * @param triggerType */ - void startVoice(Region* region, int delay, int channel, int number, uint8_t value, TriggerType triggerType) noexcept; + void startVoice(Region* region, int delay, int number, uint8_t value, TriggerType triggerType) noexcept; /** * @brief Register a note-off event; this may trigger a release. * * @param delay - * @param channel (0-based) * @param noteNumber * @param velocity */ - void registerNoteOff(int delay, int channel, int noteNumber, uint8_t velocity) noexcept; + void registerNoteOff(int delay, int noteNumber, uint8_t velocity) noexcept; /** * @brief Register a CC event; this may trigger a release. If the voice is playing and its * region has CC modifiers, it will use this value to compute the CC envelope to apply to the * parameter. * * @param delay - * @param channel (0-based) * @param ccNumber * @param ccValue */ - void registerCC(int delay, int channel, int ccNumber, uint8_t ccValue) noexcept; + void registerCC(int delay, int ccNumber, uint8_t ccValue) noexcept; /** * @brief Register a pitch wheel event; for now this does nothing * * @param delay - * @param channel (0-based) * @param pitch */ - void registerPitchWheel(int delay, int channel, int pitch) noexcept; + void registerPitchWheel(int delay, int pitch) noexcept; /** * @brief Register an aftertouch event; for now this does nothing * * @param delay - * @param channel (0-based) * @param aftertouch */ - void registerAftertouch(int delay, int channel, uint8_t aftertouch) noexcept; + void registerAftertouch(int delay, uint8_t aftertouch) noexcept; /** * @brief Register a tempo event; for now this does nothing * * @param delay - * @param channel (0-based) * @param pitch */ void registerTempo(int delay, float secondsPerQuarter) noexcept; @@ -181,12 +175,6 @@ public: * @return int */ int getTriggerNumber() const noexcept; - /** - * @brief Get the channel that triggered the voice - * - * @return int - */ - int getTriggerChannel() const noexcept; /** * @brief Get the value that triggered the voice (note velocity or cc value) * @@ -243,11 +231,10 @@ private: /** * @brief Computes the values for the envelope depending on the note or CC number and the velocity/cc value * - * @param channel (0-based) * @param delay * @param velocity */ - void prepareEGEnvelope(int channel, int delay, uint8_t velocity) noexcept; + void prepareEGEnvelope(int delay, uint8_t velocity) noexcept; /** * @brief The function processing a mono sample source * @@ -279,7 +266,6 @@ private: TriggerType triggerType; int triggerNumber; - int triggerChannel; uint8_t triggerValue; float speedRatio { 1.0 }; diff --git a/src/sfizz/sfizz_wrapper.cpp b/src/sfizz/sfizz_wrapper.cpp index 9306cbda..0423e8ca 100644 --- a/src/sfizz/sfizz_wrapper.cpp +++ b/src/sfizz/sfizz_wrapper.cpp @@ -88,30 +88,30 @@ void sfizz_set_sample_rate(sfizz_synth_t* synth, float sample_rate) self->setSampleRate(sample_rate); } -void sfizz_send_note_on(sfizz_synth_t* synth, int delay, int channel, int note_number, char velocity) +void sfizz_send_note_on(sfizz_synth_t* synth, int delay, int note_number, char velocity) { auto self = reinterpret_cast(synth); - self->noteOn(delay, channel, note_number, velocity); + self->noteOn(delay, note_number, velocity); } -void sfizz_send_note_off(sfizz_synth_t* synth, int delay, int channel, int note_number, char velocity) +void sfizz_send_note_off(sfizz_synth_t* synth, int delay, int note_number, char velocity) { auto self = reinterpret_cast(synth); - self->noteOff(delay, channel, note_number, velocity); + self->noteOff(delay, note_number, velocity); } -void sfizz_send_cc(sfizz_synth_t* synth, int delay, int channel, int cc_number, char cc_value) +void sfizz_send_cc(sfizz_synth_t* synth, int delay, int cc_number, char cc_value) { auto self = reinterpret_cast(synth); - self->cc(delay, channel, cc_number, cc_value); + self->cc(delay, cc_number, cc_value); } -void sfizz_send_pitch_wheel(sfizz_synth_t* synth, int delay, int channel, int pitch) +void sfizz_send_pitch_wheel(sfizz_synth_t* synth, int delay, int pitch) { auto self = reinterpret_cast(synth); - self->pitchWheel(delay, channel, pitch); + self->pitchWheel(delay, pitch); } -void sfizz_send_aftertouch(sfizz_synth_t* synth, int delay, int channel, char aftertouch) +void sfizz_send_aftertouch(sfizz_synth_t* synth, int delay, char aftertouch) { auto self = reinterpret_cast(synth); - self->aftertouch(delay, channel, aftertouch); + self->aftertouch(delay, aftertouch); } void sfizz_send_tempo(sfizz_synth_t* synth, int delay, float seconds_per_quarter) { diff --git a/tests/FilesT.cpp b/tests/FilesT.cpp index 7e0cec84..c528d4c4 100644 --- a/tests/FilesT.cpp +++ b/tests/FilesT.cpp @@ -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(1, 13)); + REQUIRE(synth.getRegionView(0)->keyRange == sfz::Range(2, 14)); } TEST_CASE("[Files] Underscore opcodes (underscore_opcodes.sfz)") @@ -283,20 +283,20 @@ TEST_CASE("[Files] sw_default and playing with switches") REQUIRE( synth.getRegionView(1)->isSwitchedOn() ); REQUIRE( !synth.getRegionView(2)->isSwitchedOn() ); REQUIRE( synth.getRegionView(3)->isSwitchedOn() ); - synth.noteOn(0, 1, 41, 64); - synth.noteOff(0, 1, 41, 0); + synth.noteOn(0, 41, 64); + synth.noteOff(0, 41, 0); REQUIRE( synth.getRegionView(0)->isSwitchedOn() ); REQUIRE( !synth.getRegionView(1)->isSwitchedOn() ); REQUIRE( synth.getRegionView(2)->isSwitchedOn() ); REQUIRE( !synth.getRegionView(3)->isSwitchedOn() ); - synth.noteOn(0, 1, 42, 64); - synth.noteOff(0, 1, 42, 0); + synth.noteOn(0, 42, 64); + synth.noteOff(0, 42, 0); REQUIRE( !synth.getRegionView(0)->isSwitchedOn() ); REQUIRE( !synth.getRegionView(1)->isSwitchedOn() ); REQUIRE( !synth.getRegionView(2)->isSwitchedOn() ); REQUIRE( !synth.getRegionView(3)->isSwitchedOn() ); - synth.noteOn(0, 1, 40, 64); - synth.noteOff(0, 1, 40, 64); + synth.noteOn(0, 40, 64); + synth.noteOff(0, 40, 64); REQUIRE( !synth.getRegionView(0)->isSwitchedOn() ); REQUIRE( synth.getRegionView(1)->isSwitchedOn() ); REQUIRE( !synth.getRegionView(2)->isSwitchedOn() ); @@ -355,14 +355,12 @@ TEST_CASE("[Files] Default path is ignored for generators") REQUIRE(synth.getRegionView(0)->sample == R"(*sine)"); } -TEST_CASE("[Files] Set CC applies properly to all channels") +TEST_CASE("[Files] Set CC applies properly") { sfz::Synth synth; synth.loadSfzFile(fs::current_path() / "tests/TestFiles/set_cc.sfz"); - for (int channel = 0; channel < 16; channel++) { - REQUIRE(synth.getMidiState().getCCValue(channel, 142) == 63); - REQUIRE(synth.getMidiState().getCCValue(channel, 61) == 122); - } + REQUIRE(synth.getMidiState().getCCValue(142) == 63); + REQUIRE(synth.getMidiState().getCCValue(61) == 122); } TEST_CASE("[Files] Note and octave offsets") @@ -412,7 +410,7 @@ TEST_CASE("[Files] Off modes") synth.setSamplesPerBlock(256); synth.loadSfzFile(fs::current_path() / "tests/TestFiles/off_mode.sfz"); REQUIRE( synth.getNumRegions() == 3 ); - synth.noteOn(0, 0, 64, 63); + synth.noteOn(0, 64, 63); REQUIRE( synth.getNumActiveVoices() == 2 ); const auto* fastVoice = synth.getVoiceView(0)->getRegion()->offMode == SfzOffMode::fast ? @@ -422,7 +420,7 @@ TEST_CASE("[Files] Off modes") synth.getVoiceView(0)->getRegion()->offMode == SfzOffMode::fast ? synth.getVoiceView(1) : synth.getVoiceView(0) ; - synth.noteOn(100, 0, 63, 63); + synth.noteOn(100, 63, 63); REQUIRE( synth.getNumActiveVoices() == 3 ); sfz::AudioBuffer buffer { 2, 256 }; synth.renderBlock(buffer); diff --git a/tests/MidiStateT.cpp b/tests/MidiStateT.cpp index dba6fffc..2104bfed 100644 --- a/tests/MidiStateT.cpp +++ b/tests/MidiStateT.cpp @@ -35,69 +35,56 @@ using namespace Catch::literals; TEST_CASE("[MidiState] Initial values") { sfz::MidiState state; - for (auto& cc: state.getCCArray(1)) + for (auto& cc: state.getCCArray()) REQUIRE( cc == 0 ); - for (auto& cc: state.getCCArray(6)) - REQUIRE( cc == 0 ); - for (int channel = 0; channel < 16; ++channel) - REQUIRE( state.getPitchBend(channel) == 0 ); + REQUIRE( state.getPitchBend() == 0 ); } TEST_CASE("[MidiState] Set and get CCs") { sfz::MidiState state; - const auto& cc0 = state.getCCArray(0); - const auto& cc6 = state.getCCArray(6); - const auto& cc12 = state.getCCArray(12); - state.ccEvent(0, 24, 23); - state.ccEvent(6, 123, 124); - 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); - REQUIRE(+state.getCCValue(12, 123) == 0); - REQUIRE(cc12[24] == 0); - REQUIRE(cc12[123] == 0); + const auto& cc = state.getCCArray(); + state.ccEvent(24, 23); + state.ccEvent(123, 124); + REQUIRE(state.getCCValue(24) == 23); + REQUIRE(cc[24] == 23); + REQUIRE(state.getCCValue(123) == 124); + REQUIRE(cc[123] == 124); } TEST_CASE("[MidiState] Set and get pitch bends") { sfz::MidiState state; - state.pitchBendEvent(0, 894); - REQUIRE(state.getPitchBend(0) == 894); - REQUIRE(state.getPitchBend(6) == 0); - state.pitchBendEvent(0, 0); - REQUIRE(state.getPitchBend(0) == 0); - REQUIRE(state.getPitchBend(6) == 0); + state.pitchBendEvent(894); + REQUIRE(state.getPitchBend() == 894); + state.pitchBendEvent(0); + REQUIRE(state.getPitchBend() == 0); } TEST_CASE("[MidiState] Reset") { sfz::MidiState state; - state.pitchBendEvent(0, 894); - state.noteOnEvent(6, 64, 24); - state.ccEvent(15, 123, 124); + state.pitchBendEvent(894); + state.noteOnEvent(64, 24); + state.ccEvent(123, 124); state.reset(); - REQUIRE(state.getPitchBend(0) == 0); - REQUIRE(state.getNoteVelocity(6, 64) == 0); - REQUIRE(state.getCCValue(15, 123) == 0); + REQUIRE(state.getPitchBend() == 0); + REQUIRE(state.getNoteVelocity(64) == 0); + REQUIRE(state.getCCValue(123) == 0); } TEST_CASE("[MidiState] Set and get note velocities") { sfz::MidiState state; - 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); + state.noteOnEvent(64, 24); + REQUIRE(+state.getNoteVelocity(64) == 24); + state.noteOnEvent(64, 123); + REQUIRE(+state.getNoteVelocity(64) == 123); } TEST_CASE("[MidiState] Extended CCs") { sfz::MidiState state; - REQUIRE(state.getCCArray(1).size() >= 142); - state.ccEvent(6, 142, 64); // should not trap -} \ No newline at end of file + REQUIRE(state.getCCArray().size() >= 142); + state.ccEvent(142, 64); // should not trap +} diff --git a/tests/RegionActivationT.cpp b/tests/RegionActivationT.cpp index 259cd399..b37398cd 100644 --- a/tests/RegionActivationT.cpp +++ b/tests/RegionActivationT.cpp @@ -29,11 +29,11 @@ TEST_CASE("Region activation", "Region tests") { sfz::MidiState midiState; sfz::Region region { midiState }; - + region.parseOpcode({ "sample", "*sine" }); SECTION("Basic state") { - region.registerCC(1, 4, 0); + region.registerCC(4, 0); REQUIRE(region.isSwitchedOn()); } @@ -41,19 +41,19 @@ TEST_CASE("Region activation", "Region tests") { region.parseOpcode({ "locc4", "56" }); region.parseOpcode({ "hicc4", "59" }); - region.registerCC(1, 4, 0); + region.registerCC(4, 0); REQUIRE(!region.isSwitchedOn()); - region.registerCC(1, 4, 57); + region.registerCC(4, 57); REQUIRE(region.isSwitchedOn()); - region.registerCC(1, 4, 56); + region.registerCC(4, 56); REQUIRE(region.isSwitchedOn()); - region.registerCC(1, 4, 59); + region.registerCC(4, 59); REQUIRE(region.isSwitchedOn()); - region.registerCC(1, 4, 43); + region.registerCC(4, 43); REQUIRE(!region.isSwitchedOn()); - region.registerCC(1, 4, 65); + region.registerCC(4, 65); REQUIRE(!region.isSwitchedOn()); - region.registerCC(1, 6, 57); + region.registerCC(6, 57); REQUIRE(!region.isSwitchedOn()); } @@ -63,26 +63,26 @@ TEST_CASE("Region activation", "Region tests") region.parseOpcode({ "hicc4", "59" }); region.parseOpcode({ "locc54", "18" }); region.parseOpcode({ "hicc54", "27" }); - region.registerCC(1, 4, 0); - region.registerCC(1, 54, 0); + region.registerCC(4, 0); + region.registerCC(54, 0); REQUIRE(!region.isSwitchedOn()); - region.registerCC(1, 4, 57); + region.registerCC(4, 57); REQUIRE(!region.isSwitchedOn()); - region.registerCC(1, 54, 19); + region.registerCC(54, 19); REQUIRE(region.isSwitchedOn()); - region.registerCC(1, 54, 18); + region.registerCC(54, 18); REQUIRE(region.isSwitchedOn()); - region.registerCC(1, 54, 27); + region.registerCC(54, 27); REQUIRE(region.isSwitchedOn()); - region.registerCC(1, 4, 56); + region.registerCC(4, 56); REQUIRE(region.isSwitchedOn()); - region.registerCC(1, 4, 59); + region.registerCC(4, 59); REQUIRE(region.isSwitchedOn()); - region.registerCC(1, 54, 2); + region.registerCC(54, 2); REQUIRE(!region.isSwitchedOn()); - region.registerCC(1, 54, 26); + region.registerCC(54, 26); REQUIRE(region.isSwitchedOn()); - region.registerCC(1, 4, 65); + region.registerCC(4, 65); REQUIRE(!region.isSwitchedOn()); } @@ -90,13 +90,13 @@ TEST_CASE("Region activation", "Region tests") { region.parseOpcode({ "lobend", "56" }); region.parseOpcode({ "hibend", "243" }); - region.registerPitchWheel(1, 0); + region.registerPitchWheel(0); REQUIRE(!region.isSwitchedOn()); - region.registerPitchWheel(1, 56); + region.registerPitchWheel(56); REQUIRE(region.isSwitchedOn()); - region.registerPitchWheel(1, 243); + region.registerPitchWheel(243); REQUIRE(region.isSwitchedOn()); - region.registerPitchWheel(1, 245); + region.registerPitchWheel(245); REQUIRE(!region.isSwitchedOn()); } @@ -104,13 +104,13 @@ TEST_CASE("Region activation", "Region tests") { region.parseOpcode({ "lochanaft", "56" }); region.parseOpcode({ "hichanaft", "68" }); - region.registerAftertouch(1, 0); + region.registerAftertouch(0); REQUIRE(!region.isSwitchedOn()); - region.registerAftertouch(1, 56); + region.registerAftertouch(56); REQUIRE(region.isSwitchedOn()); - region.registerAftertouch(1, 68); + region.registerAftertouch(68); REQUIRE(region.isSwitchedOn()); - region.registerAftertouch(1, 98); + region.registerAftertouch(98); REQUIRE(!region.isSwitchedOn()); } @@ -133,13 +133,13 @@ TEST_CASE("Region activation", "Region tests") { region.parseOpcode({ "sw_last", "40" }); REQUIRE(!region.isSwitchedOn()); - region.registerNoteOn(1, 40, 64, 0.5f); + region.registerNoteOn(40, 64, 0.5f); REQUIRE(region.isSwitchedOn()); - region.registerNoteOff(1, 40, 64, 0.5f); + region.registerNoteOff(40, 64, 0.5f); REQUIRE(region.isSwitchedOn()); - region.registerNoteOn(1, 41, 64, 0.5f); + region.registerNoteOn(41, 64, 0.5f); REQUIRE(!region.isSwitchedOn()); - region.registerNoteOff(1, 41, 0, 0.5f); + region.registerNoteOff(41, 0, 0.5f); } SECTION("Keyswitches: sw_last with non-default keyswitch range") @@ -148,20 +148,20 @@ TEST_CASE("Region activation", "Region tests") region.parseOpcode({ "sw_hikey", "50" }); region.parseOpcode({ "sw_last", "40" }); REQUIRE(!region.isSwitchedOn()); - region.registerNoteOn(1, 60, 64, 0.5f); + region.registerNoteOn(60, 64, 0.5f); REQUIRE(!region.isSwitchedOn()); - region.registerNoteOff(1, 60, 0, 0.5f); + region.registerNoteOff(60, 0, 0.5f); REQUIRE(!region.isSwitchedOn()); - region.registerNoteOn(1, 40, 64, 0.5f); + region.registerNoteOn(40, 64, 0.5f); REQUIRE(region.isSwitchedOn()); - region.registerNoteOff(1, 40, 0, 0.5f); + region.registerNoteOff(40, 0, 0.5f); REQUIRE(region.isSwitchedOn()); - region.registerNoteOn(1, 60, 64, 0.5f); + region.registerNoteOn(60, 64, 0.5f); REQUIRE(region.isSwitchedOn()); - region.registerNoteOff(1, 60, 0, 0.5f); - region.registerNoteOn(1, 41, 64, 0.5f); + region.registerNoteOff(60, 0, 0.5f); + region.registerNoteOn(41, 64, 0.5f); REQUIRE(!region.isSwitchedOn()); - region.registerNoteOff(1, 41, 0, 0.5f); + region.registerNoteOff(41, 0, 0.5f); } SECTION("Keyswitches: sw_down with non-default keyswitch range") @@ -170,20 +170,20 @@ TEST_CASE("Region activation", "Region tests") region.parseOpcode({ "sw_hikey", "50" }); region.parseOpcode({ "sw_down", "40" }); REQUIRE(!region.isSwitchedOn()); - region.registerNoteOn(1, 60, 64, 0.5f); + region.registerNoteOn(60, 64, 0.5f); REQUIRE(!region.isSwitchedOn()); - region.registerNoteOff(1, 60, 0, 0.5f); + region.registerNoteOff(60, 0, 0.5f); REQUIRE(!region.isSwitchedOn()); - region.registerNoteOn(1, 40, 64, 0.5f); + region.registerNoteOn(40, 64, 0.5f); REQUIRE(region.isSwitchedOn()); - region.registerNoteOff(1, 40, 0, 0.5f); + region.registerNoteOff(40, 0, 0.5f); REQUIRE(!region.isSwitchedOn()); - region.registerNoteOn(1, 60, 64, 0.5f); + region.registerNoteOn(60, 64, 0.5f); REQUIRE(!region.isSwitchedOn()); - region.registerNoteOff(1, 60, 0, 0.5f); - region.registerNoteOn(1, 41, 64, 0.5f); + region.registerNoteOff(60, 0, 0.5f); + region.registerNoteOn(41, 64, 0.5f); REQUIRE(!region.isSwitchedOn()); - region.registerNoteOff(1, 41, 0, 0.5f); + region.registerNoteOff(41, 0, 0.5f); } SECTION("Keyswitches: sw_up with non-default keyswitch range") @@ -192,16 +192,16 @@ TEST_CASE("Region activation", "Region tests") region.parseOpcode({ "sw_hikey", "50" }); region.parseOpcode({ "sw_up", "40" }); REQUIRE(region.isSwitchedOn()); - region.registerNoteOn(1, 40, 64, 0.5f); + region.registerNoteOn(40, 64, 0.5f); REQUIRE(!region.isSwitchedOn()); - region.registerNoteOff(1, 40, 0, 0.5f); + region.registerNoteOff(40, 0, 0.5f); REQUIRE(region.isSwitchedOn()); - region.registerNoteOn(1, 41, 64, 0.5f); + region.registerNoteOn(41, 64, 0.5f); REQUIRE(region.isSwitchedOn()); - region.registerNoteOn(1, 40, 64, 0.5f); + region.registerNoteOn(40, 64, 0.5f); REQUIRE(!region.isSwitchedOn()); - region.registerNoteOff(1, 40, 0, 0.5f); - region.registerNoteOff(1, 41, 0, 0.5f); + region.registerNoteOff(40, 0, 0.5f); + region.registerNoteOff(41, 0, 0.5f); REQUIRE(region.isSwitchedOn()); } @@ -209,20 +209,20 @@ TEST_CASE("Region activation", "Region tests") { region.parseOpcode({ "sw_previous", "40" }); REQUIRE(!region.isSwitchedOn()); - region.registerNoteOn(1, 40, 64, 0.5f); + region.registerNoteOn(40, 64, 0.5f); REQUIRE(region.isSwitchedOn()); - region.registerNoteOff(1, 40, 0, 0.5f); + region.registerNoteOff(40, 0, 0.5f); REQUIRE(region.isSwitchedOn()); - region.registerNoteOn(1, 41, 64, 0.5f); + region.registerNoteOn(41, 64, 0.5f); REQUIRE(!region.isSwitchedOn()); - region.registerNoteOn(1, 40, 64, 0.5f); + region.registerNoteOn(40, 64, 0.5f); REQUIRE(region.isSwitchedOn()); - region.registerNoteOff(1, 40, 0, 0.5f); - region.registerNoteOff(1, 41, 0, 0.5f); + region.registerNoteOff(40, 0, 0.5f); + region.registerNoteOff(41, 0, 0.5f); REQUIRE(region.isSwitchedOn()); - region.registerNoteOn(1, 41, 64, 0.5f); + region.registerNoteOn(41, 64, 0.5f); REQUIRE(!region.isSwitchedOn()); - region.registerNoteOff(1, 41, 0, 0.5f); + region.registerNoteOff(41, 0, 0.5f); REQUIRE(!region.isSwitchedOn()); } @@ -232,17 +232,17 @@ TEST_CASE("Region activation", "Region tests") region.parseOpcode({ "seq_position", "1" }); region.parseOpcode({ "key", "40" }); REQUIRE(region.isSwitchedOn()); - region.registerNoteOn(1, 40, 64, 0.5f); + region.registerNoteOn(40, 64, 0.5f); REQUIRE(!region.isSwitchedOn()); - region.registerNoteOff(1, 40, 0, 0.5f); + region.registerNoteOff(40, 0, 0.5f); REQUIRE(!region.isSwitchedOn()); - region.registerNoteOn(1, 40, 64, 0.5f); + region.registerNoteOn(40, 64, 0.5f); REQUIRE(region.isSwitchedOn()); - region.registerNoteOff(1, 40, 0, 0.5f); + region.registerNoteOff(40, 0, 0.5f); REQUIRE(region.isSwitchedOn()); - region.registerNoteOn(1, 40, 64, 0.5f); + region.registerNoteOn(40, 64, 0.5f); REQUIRE(!region.isSwitchedOn()); - region.registerNoteOff(1, 40, 0, 0.5f); + region.registerNoteOff(40, 0, 0.5f); REQUIRE(!region.isSwitchedOn()); } SECTION("Sequences: length 2, position 2") @@ -251,17 +251,17 @@ TEST_CASE("Region activation", "Region tests") region.parseOpcode({ "seq_position", "2" }); region.parseOpcode({ "key", "40" }); REQUIRE(!region.isSwitchedOn()); - region.registerNoteOn(1, 40, 64, 0.5f); + region.registerNoteOn(40, 64, 0.5f); REQUIRE(region.isSwitchedOn()); - region.registerNoteOff(1, 40, 0, 0.5f); + region.registerNoteOff(40, 0, 0.5f); REQUIRE(region.isSwitchedOn()); - region.registerNoteOn(1, 40, 64, 0.5f); + region.registerNoteOn(40, 64, 0.5f); REQUIRE(!region.isSwitchedOn()); - region.registerNoteOff(1, 40, 0, 0.5f); + region.registerNoteOff(40, 0, 0.5f); REQUIRE(!region.isSwitchedOn()); - region.registerNoteOn(1, 40, 64, 0.5f); + region.registerNoteOn(40, 64, 0.5f); REQUIRE(region.isSwitchedOn()); - region.registerNoteOff(1, 40, 0, 0.5f); + region.registerNoteOff(40, 0, 0.5f); REQUIRE(region.isSwitchedOn()); } SECTION("Sequences: length 3, position 2") @@ -270,21 +270,21 @@ TEST_CASE("Region activation", "Region tests") region.parseOpcode({ "seq_position", "2" }); region.parseOpcode({ "key", "40" }); REQUIRE(!region.isSwitchedOn()); - region.registerNoteOn(1, 40, 64, 0.5f); + region.registerNoteOn(40, 64, 0.5f); REQUIRE(region.isSwitchedOn()); - region.registerNoteOff(1, 40, 0, 0.5f); + region.registerNoteOff(40, 0, 0.5f); REQUIRE(region.isSwitchedOn()); - region.registerNoteOn(1, 40, 64, 0.5f); + region.registerNoteOn(40, 64, 0.5f); REQUIRE(!region.isSwitchedOn()); - region.registerNoteOff(1, 40, 0, 0.5f); + region.registerNoteOff(40, 0, 0.5f); REQUIRE(!region.isSwitchedOn()); - region.registerNoteOn(1, 40, 64, 0.5f); + region.registerNoteOn(40, 64, 0.5f); REQUIRE(!region.isSwitchedOn()); - region.registerNoteOff(1, 40, 0, 0.5f); + region.registerNoteOff(40, 0, 0.5f); REQUIRE(!region.isSwitchedOn()); - region.registerNoteOn(1, 40, 64, 0.5f); + region.registerNoteOn(40, 64, 0.5f); REQUIRE(region.isSwitchedOn()); - region.registerNoteOff(1, 40, 0, 0.5f); + region.registerNoteOff(40, 0, 0.5f); REQUIRE(region.isSwitchedOn()); } } diff --git a/tests/RegionT.cpp b/tests/RegionT.cpp index c4fd94a8..6bae7cd9 100644 --- a/tests/RegionT.cpp +++ b/tests/RegionT.cpp @@ -236,23 +236,6 @@ TEST_CASE("[Region] Parsing opcodes") REQUIRE(region.velocityRange == sfz::Range(0, 127)); } - SECTION("lochan, hichan") - { - REQUIRE(region.channelRange == sfz::Range(0, 15)); - region.parseOpcode({ "lochan", "4" }); - REQUIRE(region.channelRange == sfz::Range(3, 15)); - region.parseOpcode({ "lochan", "128" }); - REQUIRE(region.channelRange == sfz::Range(15, 15)); - region.parseOpcode({ "lochan", "-3" }); - REQUIRE(region.channelRange == sfz::Range(0, 15)); - region.parseOpcode({ "hichan", "13" }); - REQUIRE(region.channelRange == sfz::Range(0, 12)); - region.parseOpcode({ "hichan", "-1" }); - REQUIRE(region.channelRange == sfz::Range(0, 0)); - region.parseOpcode({ "hichan", "128" }); - REQUIRE(region.channelRange == sfz::Range(0, 15)); - } - SECTION("lobend, hibend") { REQUIRE(region.bendRange == sfz::Range(-8192, 8192)); diff --git a/tests/RegionTriggersT.cpp b/tests/RegionTriggersT.cpp index 9f963974..11f1cb33 100644 --- a/tests/RegionTriggersT.cpp +++ b/tests/RegionTriggersT.cpp @@ -34,44 +34,44 @@ TEST_CASE("Basic triggers", "Region triggers") SECTION("key") { region.parseOpcode({ "key", "40" }); - 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)); + REQUIRE(region.registerNoteOn(40, 64, 0.5f)); + REQUIRE(!region.registerNoteOff(40, 64, 0.5f)); + REQUIRE(!region.registerNoteOn(41, 64, 0.5f)); + REQUIRE(!region.registerCC(63, 64)); } SECTION("lokey and hikey") { region.parseOpcode({ "lokey", "40" }); region.parseOpcode({ "hikey", "42" }); - 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)); + REQUIRE(!region.registerNoteOn(39, 64, 0.5f)); + REQUIRE(region.registerNoteOn(40, 64, 0.5f)); + REQUIRE(!region.registerNoteOff(40, 64, 0.5f)); + REQUIRE(region.registerNoteOn(41, 64, 0.5f)); + REQUIRE(region.registerNoteOn(42, 64, 0.5f)); + REQUIRE(!region.registerNoteOn(43, 64, 0.5f)); + REQUIRE(!region.registerNoteOff(42, 64, 0.5f)); + REQUIRE(!region.registerNoteOff(42, 64, 0.5f)); + REQUIRE(!region.registerCC(63, 64)); } SECTION("key and release trigger") { region.parseOpcode({ "key", "40" }); region.parseOpcode({ "trigger", "release" }); - 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)); + REQUIRE(!region.registerNoteOn(40, 64, 0.5f)); + REQUIRE(region.registerNoteOff(40, 64, 0.5f)); + REQUIRE(!region.registerNoteOn(41, 64, 0.5f)); + REQUIRE(!region.registerNoteOff(41, 64, 0.5f)); + REQUIRE(!region.registerCC(63, 64)); } SECTION("key and release_key trigger") { region.parseOpcode({ "key", "40" }); region.parseOpcode({ "trigger", "release_key" }); - 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)); + REQUIRE(!region.registerNoteOn(40, 64, 0.5f)); + REQUIRE(region.registerNoteOff(40, 64, 0.5f)); + REQUIRE(!region.registerNoteOn(41, 64, 0.5f)); + REQUIRE(!region.registerNoteOff(41, 64, 0.5f)); + REQUIRE(!region.registerCC(63, 64)); } // TODO: first and legato triggers SECTION("lovel and hivel") @@ -79,22 +79,11 @@ TEST_CASE("Basic triggers", "Region triggers") region.parseOpcode({ "key", "40" }); region.parseOpcode({ "lovel", "60" }); region.parseOpcode({ "hivel", "70" }); - 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(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(40, 64, 0.5f)); + REQUIRE(region.registerNoteOn(40, 60, 0.5f)); + REQUIRE(region.registerNoteOn(40, 70, 0.5f)); + REQUIRE(!region.registerNoteOn(41, 71, 0.5f)); + REQUIRE(!region.registerNoteOn(41, 59, 0.5f)); } SECTION("lorand and hirand") @@ -102,54 +91,54 @@ TEST_CASE("Basic triggers", "Region triggers") region.parseOpcode({ "key", "40" }); region.parseOpcode({ "lorand", "0.35" }); region.parseOpcode({ "hirand", "0.40" }); - 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)); + REQUIRE(!region.registerNoteOn(40, 64, 0.34f)); + REQUIRE(region.registerNoteOn(40, 64, 0.35f)); + REQUIRE(region.registerNoteOn(40, 64, 0.36f)); + REQUIRE(region.registerNoteOn(40, 64, 0.37f)); + REQUIRE(region.registerNoteOn(40, 64, 0.38f)); + REQUIRE(region.registerNoteOn(40, 64, 0.39f)); + REQUIRE(!region.registerNoteOn(40, 64, 0.40f)); + REQUIRE(!region.registerNoteOn(40, 64, 0.41f)); } SECTION("lorand and hirand on 1.0f") { region.parseOpcode({ "key", "40" }); region.parseOpcode({ "lorand", "0.35" }); - REQUIRE(!region.registerNoteOn(0, 40, 64, 0.34f)); - REQUIRE(region.registerNoteOn(0, 40, 64, 0.35f)); - REQUIRE(region.registerNoteOn(0, 40, 64, 1.0f)); + REQUIRE(!region.registerNoteOn(40, 64, 0.34f)); + REQUIRE(region.registerNoteOn(40, 64, 0.35f)); + REQUIRE(region.registerNoteOn(40, 64, 1.0f)); } SECTION("Disable key trigger") { region.parseOpcode({ "key", "40" }); - REQUIRE(region.registerNoteOn(0, 40, 64, 1.0f)); + REQUIRE(region.registerNoteOn(40, 64, 1.0f)); region.parseOpcode({ "hikey", "-1" }); - REQUIRE(!region.registerNoteOn(0, 40, 64, 1.0f)); + REQUIRE(!region.registerNoteOn(40, 64, 1.0f)); region.parseOpcode({ "hikey", "40" }); - REQUIRE(region.registerNoteOn(0, 40, 64, 1.0f)); + REQUIRE(region.registerNoteOn(40, 64, 1.0f)); region.parseOpcode({ "key", "-1" }); - REQUIRE(!region.registerNoteOn(0, 40, 64, 1.0f)); + REQUIRE(!region.registerNoteOn(40, 64, 1.0f)); region.parseOpcode({ "key", "40" }); - REQUIRE(region.registerNoteOn(0, 40, 64, 1.0f)); + REQUIRE(region.registerNoteOn(40, 64, 1.0f)); } SECTION("on_loccN, on_hiccN") { region.parseOpcode({ "on_locc47", "64" }); region.parseOpcode({ "on_hicc47", "68" }); - REQUIRE(!region.registerCC(0, 47, 63)); - REQUIRE(!region.registerCC(0, 47, 64)); - REQUIRE(!region.registerCC(0, 47, 65)); + REQUIRE(!region.registerCC(47, 63)); + REQUIRE(!region.registerCC(47, 64)); + REQUIRE(!region.registerCC(47, 65)); region.parseOpcode({ "hikey", "-1" }); - 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)); + REQUIRE(region.registerCC(47, 64)); + REQUIRE(region.registerCC(47, 65)); + REQUIRE(region.registerCC(47, 66)); + REQUIRE(region.registerCC(47, 67)); + REQUIRE(region.registerCC(47, 68)); + REQUIRE(!region.registerCC(47, 69)); + REQUIRE(!region.registerCC(40, 64)); } } @@ -163,11 +152,11 @@ TEST_CASE("Legato triggers", "Region triggers") region.parseOpcode({ "lokey", "40" }); region.parseOpcode({ "hikey", "50" }); region.parseOpcode({ "trigger", "first" }); - 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)); + REQUIRE(region.registerNoteOn(40, 64, 0.5f)); + REQUIRE(!region.registerNoteOn(41, 64, 0.5f)); + region.registerNoteOff(40, 0, 0.5f); + region.registerNoteOff(41, 0, 0.5f); + REQUIRE(region.registerNoteOn(42, 64, 0.5f)); } SECTION("Second note playing") @@ -175,10 +164,10 @@ TEST_CASE("Legato triggers", "Region triggers") region.parseOpcode({ "lokey", "40" }); region.parseOpcode({ "hikey", "50" }); region.parseOpcode({ "trigger", "legato" }); - 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)); + REQUIRE(!region.registerNoteOn(40, 64, 0.5f)); + REQUIRE(region.registerNoteOn(41, 64, 0.5f)); + region.registerNoteOff(40, 0, 0.5f); + region.registerNoteOff(41, 0, 0.5f); + REQUIRE(!region.registerNoteOn(42, 64, 0.5f)); } } diff --git a/tests/RegionValueComputationsT.cpp b/tests/RegionValueComputationsT.cpp index 50ef6c86..617ea1d6 100644 --- a/tests/RegionValueComputationsT.cpp +++ b/tests/RegionValueComputationsT.cpp @@ -183,13 +183,13 @@ TEST_CASE("[Region] Crossfade in on CC") region.parseOpcode({ "xfin_locc24", "20" }); region.parseOpcode({ "xfin_hicc24", "24" }); region.parseOpcode({ "amp_veltrack", "0" }); - midiState.ccEvent(1, 24, 19); REQUIRE( region.getCrossfadeGain(midiState.getCCArray(1)) == 0.0_a ); - midiState.ccEvent(1, 24, 20); REQUIRE( region.getCrossfadeGain(midiState.getCCArray(1)) == 0.0_a ); - midiState.ccEvent(1, 24, 21); REQUIRE( region.getCrossfadeGain(midiState.getCCArray(1)) == 0.5_a ); - midiState.ccEvent(1, 24, 22); REQUIRE( region.getCrossfadeGain(midiState.getCCArray(1)) == 0.70711_a ); - midiState.ccEvent(1, 24, 23); REQUIRE( region.getCrossfadeGain(midiState.getCCArray(1)) == 0.86603_a ); - midiState.ccEvent(1, 24, 24); REQUIRE( region.getCrossfadeGain(midiState.getCCArray(1)) == 1.0_a ); - midiState.ccEvent(1, 24, 25); REQUIRE( region.getCrossfadeGain(midiState.getCCArray(1)) == 1.0_a ); + midiState.ccEvent(24, 19); REQUIRE( region.getCrossfadeGain(midiState.getCCArray()) == 0.0_a ); + midiState.ccEvent(24, 20); REQUIRE( region.getCrossfadeGain(midiState.getCCArray()) == 0.0_a ); + midiState.ccEvent(24, 21); REQUIRE( region.getCrossfadeGain(midiState.getCCArray()) == 0.5_a ); + midiState.ccEvent(24, 22); REQUIRE( region.getCrossfadeGain(midiState.getCCArray()) == 0.70711_a ); + midiState.ccEvent(24, 23); REQUIRE( region.getCrossfadeGain(midiState.getCCArray()) == 0.86603_a ); + midiState.ccEvent(24, 24); REQUIRE( region.getCrossfadeGain(midiState.getCCArray()) == 1.0_a ); + midiState.ccEvent(24, 25); REQUIRE( region.getCrossfadeGain(midiState.getCCArray()) == 1.0_a ); } TEST_CASE("[Region] Crossfade in on CC - gain") @@ -201,13 +201,13 @@ TEST_CASE("[Region] Crossfade in on CC - gain") region.parseOpcode({ "xfin_hicc24", "24" }); region.parseOpcode({ "amp_veltrack", "0" }); region.parseOpcode({ "xf_cccurve", "gain" }); - midiState.ccEvent(1, 24, 19); REQUIRE( region.getCrossfadeGain(midiState.getCCArray(1)) == 0.0_a ); - midiState.ccEvent(1, 24, 20); REQUIRE( region.getCrossfadeGain(midiState.getCCArray(1)) == 0.0_a ); - midiState.ccEvent(1, 24, 21); REQUIRE( region.getCrossfadeGain(midiState.getCCArray(1)) == 0.25_a ); - midiState.ccEvent(1, 24, 22); REQUIRE( region.getCrossfadeGain(midiState.getCCArray(1)) == 0.5_a ); - midiState.ccEvent(1, 24, 23); REQUIRE( region.getCrossfadeGain(midiState.getCCArray(1)) == 0.75_a ); - midiState.ccEvent(1, 24, 24); REQUIRE( region.getCrossfadeGain(midiState.getCCArray(1)) == 1.0_a ); - midiState.ccEvent(1, 24, 25); REQUIRE( region.getCrossfadeGain(midiState.getCCArray(1)) == 1.0_a ); + midiState.ccEvent(24, 19); REQUIRE( region.getCrossfadeGain(midiState.getCCArray()) == 0.0_a ); + midiState.ccEvent(24, 20); REQUIRE( region.getCrossfadeGain(midiState.getCCArray()) == 0.0_a ); + midiState.ccEvent(24, 21); REQUIRE( region.getCrossfadeGain(midiState.getCCArray()) == 0.25_a ); + midiState.ccEvent(24, 22); REQUIRE( region.getCrossfadeGain(midiState.getCCArray()) == 0.5_a ); + midiState.ccEvent(24, 23); REQUIRE( region.getCrossfadeGain(midiState.getCCArray()) == 0.75_a ); + midiState.ccEvent(24, 24); REQUIRE( region.getCrossfadeGain(midiState.getCCArray()) == 1.0_a ); + midiState.ccEvent(24, 25); REQUIRE( region.getCrossfadeGain(midiState.getCCArray()) == 1.0_a ); } TEST_CASE("[Region] Crossfade out on CC") { @@ -217,13 +217,13 @@ TEST_CASE("[Region] Crossfade out on CC") region.parseOpcode({ "xfout_locc24", "20" }); region.parseOpcode({ "xfout_hicc24", "24" }); region.parseOpcode({ "amp_veltrack", "0" }); - midiState.ccEvent(1, 24, 19); REQUIRE( region.getCrossfadeGain(midiState.getCCArray(1)) == 1.0_a ); - midiState.ccEvent(1, 24, 20); REQUIRE( region.getCrossfadeGain(midiState.getCCArray(1)) == 1.0_a ); - midiState.ccEvent(1, 24, 21); REQUIRE( region.getCrossfadeGain(midiState.getCCArray(1)) == 0.86603_a ); - midiState.ccEvent(1, 24, 22); REQUIRE( region.getCrossfadeGain(midiState.getCCArray(1)) == 0.70711_a ); - midiState.ccEvent(1, 24, 23); REQUIRE( region.getCrossfadeGain(midiState.getCCArray(1)) == 0.5_a ); - midiState.ccEvent(1, 24, 24); REQUIRE( region.getCrossfadeGain(midiState.getCCArray(1)) == 0.0_a ); - midiState.ccEvent(1, 24, 25); REQUIRE( region.getCrossfadeGain(midiState.getCCArray(1)) == 0.0_a ); + midiState.ccEvent(24, 19); REQUIRE( region.getCrossfadeGain(midiState.getCCArray()) == 1.0_a ); + midiState.ccEvent(24, 20); REQUIRE( region.getCrossfadeGain(midiState.getCCArray()) == 1.0_a ); + midiState.ccEvent(24, 21); REQUIRE( region.getCrossfadeGain(midiState.getCCArray()) == 0.86603_a ); + midiState.ccEvent(24, 22); REQUIRE( region.getCrossfadeGain(midiState.getCCArray()) == 0.70711_a ); + midiState.ccEvent(24, 23); REQUIRE( region.getCrossfadeGain(midiState.getCCArray()) == 0.5_a ); + midiState.ccEvent(24, 24); REQUIRE( region.getCrossfadeGain(midiState.getCCArray()) == 0.0_a ); + midiState.ccEvent(24, 25); REQUIRE( region.getCrossfadeGain(midiState.getCCArray()) == 0.0_a ); } TEST_CASE("[Region] Crossfade out on CC - gain") @@ -235,13 +235,13 @@ TEST_CASE("[Region] Crossfade out on CC - gain") region.parseOpcode({ "xfout_hicc24", "24" }); region.parseOpcode({ "amp_veltrack", "0" }); region.parseOpcode({ "xf_cccurve", "gain" }); - midiState.ccEvent(1, 24, 19); REQUIRE( region.getCrossfadeGain(midiState.getCCArray(1)) == 1.0_a ); - midiState.ccEvent(1, 24, 20); REQUIRE( region.getCrossfadeGain(midiState.getCCArray(1)) == 1.0_a ); - midiState.ccEvent(1, 24, 21); REQUIRE( region.getCrossfadeGain(midiState.getCCArray(1)) == 0.75_a ); - midiState.ccEvent(1, 24, 22); REQUIRE( region.getCrossfadeGain(midiState.getCCArray(1)) == 0.5_a ); - midiState.ccEvent(1, 24, 23); REQUIRE( region.getCrossfadeGain(midiState.getCCArray(1)) == 0.25_a ); - midiState.ccEvent(1, 24, 24); REQUIRE( region.getCrossfadeGain(midiState.getCCArray(1)) == 0.0_a ); - midiState.ccEvent(1, 24, 25); REQUIRE( region.getCrossfadeGain(midiState.getCCArray(1)) == 0.0_a ); + midiState.ccEvent(24, 19); REQUIRE( region.getCrossfadeGain(midiState.getCCArray()) == 1.0_a ); + midiState.ccEvent(24, 20); REQUIRE( region.getCrossfadeGain(midiState.getCCArray()) == 1.0_a ); + midiState.ccEvent(24, 21); REQUIRE( region.getCrossfadeGain(midiState.getCCArray()) == 0.75_a ); + midiState.ccEvent(24, 22); REQUIRE( region.getCrossfadeGain(midiState.getCCArray()) == 0.5_a ); + midiState.ccEvent(24, 23); REQUIRE( region.getCrossfadeGain(midiState.getCCArray()) == 0.25_a ); + midiState.ccEvent(24, 24); REQUIRE( region.getCrossfadeGain(midiState.getCCArray()) == 0.0_a ); + midiState.ccEvent(24, 25); REQUIRE( region.getCrossfadeGain(midiState.getCCArray()) == 0.0_a ); } TEST_CASE("[Region] Velocity bug for extreme values - veltrack at 0") @@ -282,17 +282,17 @@ TEST_CASE("[Region] rt_decay") region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "trigger", "release" }); region.parseOpcode({ "rt_decay", "10" }); - midiState.noteOnEvent(1, 64, 64); + midiState.noteOnEvent(64, 64); std::this_thread::sleep_for(std::chrono::milliseconds(100)); - REQUIRE( region.getBaseVolumedB(1, 64) == Approx(sfz::Default::volume - 1.0f).margin(0.1) ); + REQUIRE( region.getBaseVolumedB(64) == Approx(sfz::Default::volume - 1.0f).margin(0.1) ); region.parseOpcode({ "rt_decay", "20" }); - midiState.noteOnEvent(1, 64, 64); + midiState.noteOnEvent(64, 64); std::this_thread::sleep_for(std::chrono::milliseconds(100)); - REQUIRE( region.getBaseVolumedB(1, 64) == Approx(sfz::Default::volume - 2.0f).margin(0.1) ); + REQUIRE( region.getBaseVolumedB(64) == Approx(sfz::Default::volume - 2.0f).margin(0.1) ); region.parseOpcode({ "trigger", "attack" }); - midiState.noteOnEvent(1, 64, 64); + midiState.noteOnEvent(64, 64); std::this_thread::sleep_for(std::chrono::milliseconds(100)); - REQUIRE( region.getBaseVolumedB(1, 64) == Approx(sfz::Default::volume).margin(0.1) ); + REQUIRE( region.getBaseVolumedB(64) == Approx(sfz::Default::volume).margin(0.1) ); } TEST_CASE("[Region] Base delay") diff --git a/tests/SynthT.cpp b/tests/SynthT.cpp index 4ccb27c6..999cf58c 100644 --- a/tests/SynthT.cpp +++ b/tests/SynthT.cpp @@ -35,8 +35,8 @@ TEST_CASE("[Synth] Play and check active voices") sfz::AudioBuffer buffer { 2, blockSize }; synth.loadSfzFile(fs::current_path() / "tests/TestFiles/groups_avl.sfz"); - synth.noteOn(0, 1, 36, 24); - synth.noteOn(0, 1, 36, 89); + synth.noteOn(0, 36, 24); + synth.noteOn(0, 36, 89); REQUIRE(synth.getNumActiveVoices() == 2); // Render for a while for (int i = 0; i < 200; ++i) @@ -51,8 +51,8 @@ TEST_CASE("[Synth] Change the number of voice while playing") sfz::AudioBuffer buffer { 2, blockSize }; synth.loadSfzFile(fs::current_path() / "tests/TestFiles/groups_avl.sfz"); - synth.noteOn(0, 1, 36, 24); - synth.noteOn(0, 1, 36, 89); + synth.noteOn(0, 36, 24); + synth.noteOn(0, 36, 89); synth.renderBlock(buffer); REQUIRE(synth.getNumActiveVoices() == 2); synth.setNumVoices(8); @@ -99,8 +99,8 @@ TEST_CASE("[Synth] Check that we can change the size of the preload before and a synth.loadSfzFile(fs::current_path() / "tests/TestFiles/groups_avl.sfz"); synth.setPreloadSize(1024); - synth.noteOn(0, 1, 36, 24); - synth.noteOn(0, 1, 36, 89); + synth.noteOn(0, 36, 24); + synth.noteOn(0, 36, 89); synth.renderBlock(buffer); synth.setPreloadSize(2048); synth.renderBlock(buffer); @@ -114,95 +114,39 @@ TEST_CASE("[Synth] Check that we can change the oversampling factor before and a synth.loadSfzFile(fs::current_path() / "tests/TestFiles/groups_avl.sfz"); synth.setOversamplingFactor(sfz::Oversampling::x4); - synth.noteOn(0, 1, 36, 24); - synth.noteOn(0, 1, 36, 89); + synth.noteOn(0, 36, 24); + synth.noteOn(0, 36, 89); synth.renderBlock(buffer); synth.setOversamplingFactor(sfz::Oversampling::x2); synth.renderBlock(buffer); } -TEST_CASE("[Synth] Testing channel 1") -{ - sfz::Synth synth; - synth.setNumVoices(1); - synth.loadSfzFile(fs::current_path() / "tests/TestFiles/midi_channels.sfz"); - synth.noteOn(0, 0, 60, 63); - const auto* region = synth.getVoiceView(0)->getRegion(); - REQUIRE( region != nullptr ); - REQUIRE( region->sample == "dummy1.wav" ); -} - -TEST_CASE("[Synth] Testing channel 2") -{ - sfz::Synth synth; - synth.setNumVoices(1); - synth.loadSfzFile(fs::current_path() / "tests/TestFiles/midi_channels.sfz"); - synth.noteOn(0, 1, 60, 63); - const auto* region = synth.getVoiceView(0)->getRegion(); - REQUIRE( region != nullptr ); - REQUIRE( region->sample == "dummy2.wav" ); -} - - - -TEST_CASE("[Synth] Testing channel 16") -{ - sfz::Synth synth; - synth.setNumVoices(1); - synth.loadSfzFile(fs::current_path() / "tests/TestFiles/midi_channels.sfz"); - synth.noteOn(0, 15, 60, 63); - const auto* region = synth.getVoiceView(0)->getRegion(); - REQUIRE( region != nullptr ); - REQUIRE( region->sample == "dummy16.wav" ); -} - -TEST_CASE("[Synth] All notes offs/all sounds off (single channel)") +TEST_CASE("[Synth] All notes offs/all sounds off") { sfz::Synth synth; synth.setNumVoices(8); - synth.loadSfzFile(fs::current_path() / "tests/TestFiles/midi_channels.sfz"); - synth.noteOn(0, 0, 60, 63); - synth.noteOn(1, 0, 60, 63); + synth.loadSfzFile(fs::current_path() / "tests/TestFiles/sound_off.sfz"); + synth.noteOn(0, 60, 63); + synth.noteOn(0, 62, 63); REQUIRE( synth.getNumActiveVoices() == 2 ); - synth.cc(0, 0, 120, 63); + synth.cc(0, 120, 63); REQUIRE( synth.getNumActiveVoices() == 0 ); - synth.noteOn(0, 0, 60, 63); - synth.noteOn(1, 0, 60, 63); + synth.noteOn(0, 62, 63); + synth.noteOn(0, 60, 63); REQUIRE( synth.getNumActiveVoices() == 2 ); - synth.cc(0, 0, 123, 63); - REQUIRE( synth.getNumActiveVoices() == 0 ); -} - -TEST_CASE("[Synth] All notes offs/all sounds off (multi channel)") -{ - sfz::Synth synth; - synth.setNumVoices(8); - synth.loadSfzFile(fs::current_path() / "tests/TestFiles/midi_channels.sfz"); - synth.noteOn(0, 0, 60, 63); - synth.noteOn(1, 1, 60, 63); - REQUIRE( synth.getNumActiveVoices() == 2 ); - synth.cc(0, 0, 120, 63); - REQUIRE( synth.getNumActiveVoices() == 1 ); - - synth.noteOn(0, 0, 60, 63); - REQUIRE( synth.getNumActiveVoices() == 2 ); - synth.cc(0, 0, 123, 63); - REQUIRE( synth.getNumActiveVoices() == 1 ); - synth.cc(0, 1, 123, 63); + synth.cc(0, 123, 63); REQUIRE( synth.getNumActiveVoices() == 0 ); } TEST_CASE("[Synth] Reset all controllers") { sfz::Synth synth; - synth.cc(0, 0, 12, 64); - synth.cc(0, 1, 12, 64); - REQUIRE( synth.getMidiState().getCCValue(0, 12) == 64 ); - synth.cc(0, 0, 121, 64); - REQUIRE( synth.getMidiState().getCCValue(0, 12) == 0 ); - REQUIRE( synth.getMidiState().getCCValue(1, 12) == 64 ); + synth.cc(0, 12, 64); + REQUIRE( synth.getMidiState().getCCValue(12) == 64 ); + synth.cc(0, 121, 64); + REQUIRE( synth.getMidiState().getCCValue(12) == 0 ); } TEST_CASE("[Synth] Releasing before the EG started smoothing (initial delay) kills the voice") @@ -211,13 +155,13 @@ TEST_CASE("[Synth] Releasing before the EG started smoothing (initial delay) kil synth.setSamplesPerBlock(1024); synth.setNumVoices(1); synth.loadSfzFile(fs::current_path() / "tests/TestFiles/delay_release.sfz"); - synth.noteOn(0, 1, 60, 63); + synth.noteOn(0, 60, 63); REQUIRE( !synth.getVoiceView(0)->isFree() ); - synth.noteOff(100, 1, 60, 63); + synth.noteOff(100, 60, 63); REQUIRE( synth.getVoiceView(0)->isFree() ); - synth.noteOn(200, 1, 60, 63); + synth.noteOn(200, 60, 63); REQUIRE( !synth.getVoiceView(0)->isFree() ); - synth.noteOff(1000, 1, 60, 63); + synth.noteOff(1000, 60, 63); REQUIRE( !synth.getVoiceView(0)->isFree() ); } @@ -228,11 +172,11 @@ TEST_CASE("[Synth] Releasing after the initial and normal mode does not trigger sfz::AudioBuffer buffer(2, 1024); synth.setNumVoices(1); synth.loadSfzFile(fs::current_path() / "tests/TestFiles/delay_release.sfz"); - synth.noteOn(200, 1, 60, 63); + synth.noteOn(200, 60, 63); REQUIRE( !synth.getVoiceView(0)->isFree() ); synth.renderBlock(buffer); REQUIRE( !synth.getVoiceView(0)->isFree() ); - synth.noteOff(0, 1, 60, 63); + synth.noteOff(0, 60, 63); synth.renderBlock(buffer); REQUIRE( !synth.getVoiceView(0)->isFree() ); } diff --git a/tests/TestFiles/Regions/regions_opcodes.sfz b/tests/TestFiles/Regions/regions_opcodes.sfz index a301981b..91b5aab3 100644 --- a/tests/TestFiles/Regions/regions_opcodes.sfz +++ b/tests/TestFiles/Regions/regions_opcodes.sfz @@ -1 +1 @@ - lochan=2 hichan=14 sample=dummy.wav \ No newline at end of file + lokey=2 hikey=14 sample=dummy.wav diff --git a/tests/TestFiles/midi_channels.sfz b/tests/TestFiles/midi_channels.sfz deleted file mode 100644 index 16f174b8..00000000 --- a/tests/TestFiles/midi_channels.sfz +++ /dev/null @@ -1,3 +0,0 @@ - lochan=1 hichan=1 sample=dummy1.wav - lochan=2 hichan=2 sample=dummy2.wav - lochan=16 hichan=16 sample=dummy16.wav diff --git a/tests/TestFiles/sound_off.sfz b/tests/TestFiles/sound_off.sfz new file mode 100644 index 00000000..b7b09c95 --- /dev/null +++ b/tests/TestFiles/sound_off.sfz @@ -0,0 +1,2 @@ + key=60 sample=dummy1.wav + key=62 sample=dummy2.wav