mirror of
https://github.com/ZDoom/fluidsynth.git
synced 2024-11-10 06:51:54 +00:00
Merge pull request #1055 from FluidSynth/reset-cc
Fix some broken behaviour around ALL_CTRL_OFF
This commit is contained in:
commit
bf23f7a2a5
5 changed files with 161 additions and 4 deletions
|
@ -162,9 +162,10 @@ fluid_channel_init_ctrl(fluid_channel_t *chan, int is_all_ctrl_off)
|
|||
fluid_channel_set_cc(chan, i, 0);
|
||||
}
|
||||
|
||||
fluid_channel_clear_portamento(chan); /* Clear PTC receive */
|
||||
chan->previous_cc_breath = 0;/* Reset previous breath */
|
||||
}
|
||||
/* Unconditionally clear PTC receive (issue #1050) */
|
||||
fluid_channel_clear_portamento(chan);
|
||||
|
||||
/* Reset polyphonic key pressure on all voices */
|
||||
for(i = 0; i < 128; i++)
|
||||
|
|
|
@ -184,6 +184,8 @@ fluid_mod_get_source_value(const unsigned char mod_src,
|
|||
|
||||
if(mod_flags & FLUID_MOD_CC)
|
||||
{
|
||||
val = fluid_channel_get_cc(chan, mod_src);
|
||||
|
||||
/* From MIDI Recommended Practice (RP-036) Default Pan Formula:
|
||||
* "Since MIDI controller values range from 0 to 127, the exact center
|
||||
* of the range, 63.5, cannot be represented. Therefore, the effective
|
||||
|
@ -197,16 +199,20 @@ fluid_mod_get_source_value(const unsigned char mod_src,
|
|||
if(mod_src == PAN_MSB || mod_src == BALANCE_MSB)
|
||||
{
|
||||
*range = 126;
|
||||
val = fluid_channel_get_cc(chan, mod_src) - 1;
|
||||
val -= 1;
|
||||
|
||||
if(val < 0)
|
||||
{
|
||||
val = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
else if(mod_src == PORTAMENTO_CTRL)
|
||||
{
|
||||
val = fluid_channel_get_cc(chan, mod_src);
|
||||
// an invalid portamento fromkey should be treated as 0 when it's actually used for moulating
|
||||
if(!fluid_channel_is_valid_note(val))
|
||||
{
|
||||
val = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -1794,6 +1794,9 @@ fluid_synth_cc_LOCAL(fluid_synth_t *synth, int channum, int num)
|
|||
|
||||
case ALL_CTRL_OFF: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
|
||||
fluid_channel_init_ctrl(chan, 1);
|
||||
// the hold pedals have been reset, we maybe need to release voices
|
||||
fluid_synth_damp_voices_by_sustain_LOCAL(synth, channum);
|
||||
fluid_synth_damp_voices_by_sostenuto_LOCAL(synth, channum);
|
||||
fluid_synth_modulate_voices_all_LOCAL(synth, channum);
|
||||
break;
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIG> --output-on
|
|||
|
||||
|
||||
## add unit tests here ##
|
||||
ADD_FLUID_TEST(test_synth_reset_cc)
|
||||
ADD_FLUID_TEST(test_sample_cache)
|
||||
ADD_FLUID_TEST(test_sfont_loading)
|
||||
ADD_FLUID_TEST(test_sample_rate_change)
|
||||
|
|
146
test/test_synth_reset_cc.c
Normal file
146
test/test_synth_reset_cc.c
Normal file
|
@ -0,0 +1,146 @@
|
|||
|
||||
#include "test.h"
|
||||
#include "fluidsynth.h"
|
||||
#include "fluidsynth_priv.h"
|
||||
#include "fluid_synth.h"
|
||||
#include "fluid_midi.h"
|
||||
#include "fluid_chan.h"
|
||||
#include <string.h>
|
||||
|
||||
// render enough samples to go past the release phase of the voice
|
||||
enum { SAMPLES=100*1024 };
|
||||
|
||||
static void test_sustain(fluid_synth_t* synth, int chan)
|
||||
{
|
||||
// depress sustain pedal
|
||||
TEST_SUCCESS(fluid_synth_cc(synth, chan, SUSTAIN_SWITCH, 127));
|
||||
TEST_SUCCESS(fluid_synth_process(synth, SAMPLES, 0, NULL, 0, NULL));
|
||||
|
||||
// hit a note, after some (render-)time has passed
|
||||
TEST_SUCCESS(fluid_synth_noteon(synth, chan, 60, 127));
|
||||
|
||||
// trigger the dsp loop to force rvoice creation
|
||||
TEST_SUCCESS(fluid_synth_process(synth, SAMPLES, 0, NULL, 0, NULL));
|
||||
|
||||
// one voice must be playing by now
|
||||
TEST_ASSERT(fluid_synth_get_active_voice_count(synth) == 2);
|
||||
|
||||
// send noteoff
|
||||
TEST_SUCCESS(fluid_synth_noteoff(synth, chan, 60));
|
||||
|
||||
// voice stays on
|
||||
TEST_SUCCESS(fluid_synth_process(synth, SAMPLES, 0, NULL, 0, NULL));
|
||||
TEST_ASSERT(fluid_synth_get_active_voice_count(synth) == 2);
|
||||
|
||||
// reset controllers
|
||||
TEST_SUCCESS(fluid_synth_cc(synth, chan, ALL_CTRL_OFF, 0));
|
||||
|
||||
// voice should be off now
|
||||
TEST_SUCCESS(fluid_synth_process(synth, SAMPLES, 0, NULL, 0, NULL));
|
||||
TEST_ASSERT(fluid_synth_get_active_voice_count(synth) == 0);
|
||||
}
|
||||
|
||||
static void test_sostenuto(fluid_synth_t *synth, int chan)
|
||||
{
|
||||
// play a note
|
||||
TEST_SUCCESS(fluid_synth_noteon(synth, chan, 60, 127));
|
||||
TEST_SUCCESS(fluid_synth_process(synth, SAMPLES, 0, NULL, 0, NULL));
|
||||
|
||||
// depress sostenuto pedal
|
||||
TEST_ASSERT(fluid_synth_get_active_voice_count(synth) == 2);
|
||||
TEST_SUCCESS(fluid_synth_cc(synth, chan, SOSTENUTO_SWITCH, 127));
|
||||
|
||||
// send noteoff right afterwards
|
||||
TEST_SUCCESS(fluid_synth_noteoff(synth, chan, 60));
|
||||
|
||||
// voice stays on after rendering
|
||||
TEST_SUCCESS(fluid_synth_process(synth, SAMPLES, 0, NULL, 0, NULL));
|
||||
TEST_ASSERT(fluid_synth_get_active_voice_count(synth) == 2);
|
||||
|
||||
// reset controllers
|
||||
TEST_SUCCESS(fluid_synth_cc(synth, chan, ALL_CTRL_OFF, 0));
|
||||
|
||||
// voice should be off now
|
||||
TEST_SUCCESS(fluid_synth_process(synth, SAMPLES, 0, NULL, 0, NULL));
|
||||
TEST_ASSERT(fluid_synth_get_active_voice_count(synth) == 0);
|
||||
}
|
||||
|
||||
static void test_portamento_fromkey(fluid_synth_t* synth, int chan)
|
||||
{
|
||||
int ptc;
|
||||
|
||||
// Portamento is disabled
|
||||
TEST_SUCCESS(fluid_synth_cc(synth, chan, PORTAMENTO_CTRL, 127));
|
||||
TEST_SUCCESS(fluid_synth_get_cc(synth, chan, PORTAMENTO_CTRL, &ptc));
|
||||
TEST_ASSERT(ptc == 127);
|
||||
|
||||
TEST_SUCCESS(fluid_synth_cc(synth, chan, ALL_CTRL_OFF, 0));
|
||||
|
||||
// Because PTC is used for modulating, it should be reset to zero
|
||||
TEST_SUCCESS(fluid_synth_get_cc(synth, chan, PORTAMENTO_CTRL, &ptc));
|
||||
TEST_ASSERT(!fluid_channel_is_valid_note(ptc));
|
||||
|
||||
// Enable Portamento
|
||||
TEST_SUCCESS(fluid_synth_cc(synth, chan, PORTAMENTO_SWITCH, 64));
|
||||
TEST_SUCCESS(fluid_synth_cc(synth, chan, PORTAMENTO_TIME_MSB, 10));
|
||||
TEST_SUCCESS(fluid_synth_get_cc(synth, chan, PORTAMENTO_SWITCH, &ptc));
|
||||
TEST_ASSERT(ptc == 64);
|
||||
TEST_SUCCESS(fluid_synth_get_cc(synth, chan, PORTAMENTO_TIME_MSB, &ptc));
|
||||
TEST_ASSERT(ptc == 10);
|
||||
|
||||
TEST_SUCCESS(fluid_synth_cc(synth, chan, ALL_CTRL_OFF, 0));
|
||||
TEST_SUCCESS(fluid_synth_get_cc(synth, chan, PORTAMENTO_CTRL, &ptc));
|
||||
TEST_ASSERT(!fluid_channel_is_valid_note(ptc));
|
||||
TEST_SUCCESS(fluid_synth_get_cc(synth, chan, PORTAMENTO_SWITCH, &ptc));
|
||||
TEST_ASSERT(ptc == 0);
|
||||
TEST_SUCCESS(fluid_synth_get_cc(synth, chan, PORTAMENTO_TIME_MSB, &ptc));
|
||||
TEST_ASSERT(ptc == 0);
|
||||
|
||||
// Portamento is disabled
|
||||
TEST_SUCCESS(fluid_synth_cc(synth, chan, PORTAMENTO_CTRL, 127));
|
||||
TEST_SUCCESS(fluid_synth_get_cc(synth, chan, PORTAMENTO_CTRL, &ptc));
|
||||
TEST_ASSERT(ptc == 127);
|
||||
|
||||
TEST_SUCCESS(fluid_synth_cc(synth, chan, ALL_CTRL_OFF, 0));
|
||||
|
||||
// Because PTC is used for modulating, it should be reset to zero
|
||||
TEST_SUCCESS(fluid_synth_get_cc(synth, chan, PORTAMENTO_CTRL, &ptc));
|
||||
TEST_ASSERT(!fluid_channel_is_valid_note(ptc));
|
||||
}
|
||||
|
||||
// this test should make sure that sample rate changed are handled correctly
|
||||
int main(void)
|
||||
{
|
||||
int chan;
|
||||
fluid_synth_t *synth;
|
||||
fluid_settings_t *settings = new_fluid_settings();
|
||||
TEST_ASSERT(settings != NULL);
|
||||
|
||||
synth = new_fluid_synth(settings);
|
||||
TEST_ASSERT(synth != NULL);
|
||||
TEST_SUCCESS(fluid_synth_sfload(synth, TEST_SOUNDFONT, 1));
|
||||
|
||||
for (chan = 0; chan < fluid_synth_count_midi_channels(synth); chan++)
|
||||
{
|
||||
const fluid_channel_t* channel = synth->channel[chan];
|
||||
if(channel->channel_type == CHANNEL_TYPE_DRUM)
|
||||
{
|
||||
// drum channels won't spawn voices
|
||||
continue;
|
||||
}
|
||||
|
||||
test_portamento_fromkey(synth, chan);
|
||||
fluid_synth_system_reset(synth);
|
||||
|
||||
test_sustain(synth, chan);
|
||||
fluid_synth_system_reset(synth);
|
||||
|
||||
test_sostenuto(synth, chan);
|
||||
fluid_synth_system_reset(synth);
|
||||
}
|
||||
|
||||
delete_fluid_synth(synth);
|
||||
delete_fluid_settings(settings);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
Loading…
Reference in a new issue