diff --git a/fluidsynth/src/fluid_midi.c b/fluidsynth/src/fluid_midi.c index dc0b8eb0..e012474c 100644 --- a/fluidsynth/src/fluid_midi.c +++ b/fluidsynth/src/fluid_midi.c @@ -1098,7 +1098,6 @@ fluid_track_send_events(fluid_track_t* track, fluid_player_t* new_fluid_player(fluid_synth_t* synth) { int i; - char* timing_source; fluid_player_t* player; player = FLUID_NEW(fluid_player_t); if (player == NULL) { @@ -1121,12 +1120,10 @@ fluid_player_t* new_fluid_player(fluid_synth_t* synth) player->miditempo = 480000; player->deltatime = 4.0; - player->use_system_timer = 0; - if (fluid_settings_getstr(synth->settings, "player.timing-source", &timing_source) != 0) { - if (strcmp(timing_source, "system") == 0) { - player->use_system_timer = 1; - } - } + player->use_system_timer = + fluid_settings_str_equal(synth->settings, "player.timing-source", "system"); + player->reset_synth_between_songs = + fluid_settings_str_equal(synth->settings, "player.reset-synth", "yes"); return player; } @@ -1165,6 +1162,9 @@ void fluid_player_settings(fluid_settings_t* settings) /* player.timing-source can be either "system" (use system timer) or "sample" (use timer based on number of written samples) */ fluid_settings_register_str(settings, "player.timing-source", "sample", 0, NULL, NULL); + /* Selects whether the player should reset the synth between + songs, or not. */ + fluid_settings_register_str(settings, "player.reset-synth", "yes", 0, NULL, NULL); } @@ -1295,6 +1295,10 @@ void fluid_player_playlist_load(fluid_player_t* player, unsigned int msec) player->start_ticks = 0; player->cur_ticks = 0; + if (player->reset_synth_between_songs) { + fluid_synth_system_reset(player->synth); + } + for (i = 0; i < player->ntracks; i++) { if (player->track[i] != NULL) { fluid_track_reset(player->track[i]); diff --git a/fluidsynth/src/fluid_midi.h b/fluidsynth/src/fluid_midi.h index fa268b42..b4b47da7 100644 --- a/fluidsynth/src/fluid_midi.h +++ b/fluidsynth/src/fluid_midi.h @@ -250,6 +250,7 @@ struct _fluid_player_t { char send_program_change; /* should we ignore the program changes? */ char use_system_timer; /* if zero, use sample timers, otherwise use system clock timer */ + char reset_synth_between_songs; /* 1 if system reset should be sent to the synth between songs. */ int start_ticks; /* the number of tempo ticks passed at the last tempo change */ int cur_ticks; /* the number of tempo ticks passed */ int begin_msec; /* the time (msec) of the beginning of the file */ diff --git a/fluidsynth/src/fluid_voice.c b/fluidsynth/src/fluid_voice.c index cc8d48ce..f17faadb 100644 --- a/fluidsynth/src/fluid_voice.c +++ b/fluidsynth/src/fluid_voice.c @@ -475,7 +475,7 @@ fluid_voice_write(fluid_voice_t* voice, voice->phase_incr = fluid_ct2hz_real (voice->pitch + voice->modlfo_val * voice->modlfo_to_pitch + voice->viblfo_val * voice->viblfo_to_pitch - + voice->modenv_val * voice->modenv_to_pitch) / voice->root_pitch; + + voice->modenv_val * voice->modenv_to_pitch) / voice->root_pitch_hz; fluid_check_fpe ("voice_write phase calculation"); @@ -813,6 +813,33 @@ void fluid_voice_start(fluid_voice_t* voice) voice->status = FLUID_VOICE_ON; } +static void +fluid_voice_calculate_gen_pitch(fluid_voice_t* voice) +{ + fluid_real_t x; + + /* The GEN_PITCH is a hack to fit the pitch bend controller into the + * modulator paradigm. Now the nominal pitch of the key is set. + * Note about SCALETUNE: SF2.01 8.1.3 says, that this generator is a + * non-realtime parameter. So we don't allow modulation (as opposed + * to _GEN(voice, GEN_SCALETUNE) When the scale tuning is varied, + * one key remains fixed. Here C3 (MIDI number 60) is used. + */ + if (fluid_channel_has_tuning(voice->channel)) { + /* pitch(scalekey) + scale * (pitch(key) - pitch(scalekey)) */ + #define __pitch(_k) fluid_tuning_get_pitch(tuning, _k) + fluid_tuning_t* tuning = fluid_channel_get_tuning(voice->channel); + x = __pitch((int) (voice->root_pitch / 100.0f)); + voice->gen[GEN_PITCH].val = (x + (voice->gen[GEN_SCALETUNE].val / 100.0f * + (__pitch(voice->key) - x))); + } else { + voice->gen[GEN_PITCH].val = (voice->gen[GEN_SCALETUNE].val * (voice->key - voice->root_pitch / 100.0f) + + voice->root_pitch); + } + fprintf(stderr, "%d: %f %f\n", voice->id, voice->gen[GEN_PITCH].val, voice->root_pitch); + +} + /* * fluid_voice_calculate_runtime_synthesis_parameters * @@ -911,24 +938,6 @@ fluid_voice_calculate_runtime_synthesis_parameters(fluid_voice_t* voice) /* fluid_dump_modulator(mod); */ } - /* The GEN_PITCH is a hack to fit the pitch bend controller into the - * modulator paradigm. Now the nominal pitch of the key is set. - * Note about SCALETUNE: SF2.01 8.1.3 says, that this generator is a - * non-realtime parameter. So we don't allow modulation (as opposed - * to _GEN(voice, GEN_SCALETUNE) When the scale tuning is varied, - * one key remains fixed. Here C3 (MIDI number 60) is used. - */ - if (fluid_channel_has_tuning(voice->channel)) { - /* pitch(60) + scale * (pitch(key) - pitch(60)) */ - #define __pitch(_k) fluid_tuning_get_pitch(tuning, _k) - fluid_tuning_t* tuning = fluid_channel_get_tuning(voice->channel); - voice->gen[GEN_PITCH].val = (__pitch(60) + (voice->gen[GEN_SCALETUNE].val / 100.0f * - (__pitch(voice->key) - __pitch(60)))); - } else { - voice->gen[GEN_PITCH].val = (voice->gen[GEN_SCALETUNE].val * (voice->key - 60.0f) - + 100.0f * 60.0f); - } - /* Now the generators are initialized, nominal and modulation value. * The voice parameters (which depend on generators) are calculated * with fluid_voice_update_param. Processing the list of generator @@ -1103,10 +1112,13 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen) } else { voice->root_pitch = voice->sample->origpitch * 100.0f - voice->sample->pitchadj; } - voice->root_pitch = fluid_ct2hz(voice->root_pitch); + fprintf(stderr, "%d: %f\n", voice->id, voice->root_pitch); + voice->root_pitch_hz = fluid_ct2hz(voice->root_pitch); if (voice->sample != NULL) { - voice->root_pitch *= (fluid_real_t) voice->output_rate / voice->sample->samplerate; + voice->root_pitch_hz *= (fluid_real_t) voice->output_rate / voice->sample->samplerate; } + /* voice->pitch depends on voice->root_pitch, so calculate voice->pitch now */ + fluid_voice_calculate_gen_pitch(voice); break; case GEN_FILTERFC: diff --git a/fluidsynth/src/fluid_voice.h b/fluidsynth/src/fluid_voice.h index b509e1c8..4de645a9 100644 --- a/fluidsynth/src/fluid_voice.h +++ b/fluidsynth/src/fluid_voice.h @@ -124,7 +124,8 @@ struct _fluid_voice_t fluid_real_t attenuation; /* the attenuation in centibels */ fluid_real_t min_attenuation_cB; /* Estimate on the smallest possible attenuation * during the lifetime of the voice */ - fluid_real_t root_pitch; + fluid_real_t root_pitch, root_pitch_hz; + /* sample and loop start and end points (offset in sample memory). */ int start;