Implement feature to have a minimum note length for all notes

This commit is contained in:
David Henningsson 2009-10-13 01:08:10 +00:00
parent 3bc6d961a6
commit e86df648a9
5 changed files with 34 additions and 8 deletions

View file

@ -169,6 +169,9 @@
/* Define to the one symbol short name of this package. */ /* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME #undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */ /* Define to the version of this package. */
#undef PACKAGE_VERSION #undef PACKAGE_VERSION

View file

@ -253,6 +253,8 @@ void fluid_synth_settings(fluid_settings_t* settings)
fluid_settings_register_str(settings, "synth.midi-mode-lock", "no", 0, NULL, NULL); fluid_settings_register_str(settings, "synth.midi-mode-lock", "no", 0, NULL, NULL);
fluid_settings_add_option(settings, "synth.midi-mode-lock", "no"); fluid_settings_add_option(settings, "synth.midi-mode-lock", "no");
fluid_settings_add_option(settings, "synth.midi-mode-lock", "yes"); fluid_settings_add_option(settings, "synth.midi-mode-lock", "yes");
fluid_settings_register_int(settings, "synth.min-note-length", 0, 0, 65536, 0, NULL, NULL);
} }
/* /*
@ -576,6 +578,9 @@ new_fluid_synth(fluid_settings_t *settings)
fluid_settings_getint(settings, "synth.device-id", &synth->device_id); fluid_settings_getint(settings, "synth.device-id", &synth->device_id);
fluid_settings_getint(settings, "synth.cpu-cores", &synth->cores); fluid_settings_getint(settings, "synth.cpu-cores", &synth->cores);
fluid_settings_getint(settings, "synth.min-note-length", &i);
synth->min_note_length_ticks = (unsigned int) (i*synth->sample_rate/1000.0f);
/* register the callbacks */ /* register the callbacks */
fluid_settings_register_num(settings, "synth.gain", fluid_settings_register_num(settings, "synth.gain",
0.2f, 0.0f, 10.0f, 0, 0.2f, 0.0f, 10.0f, 0,
@ -1406,7 +1411,7 @@ fluid_synth_noteoff_LOCAL(fluid_synth_t* synth, int chan, int key)
used_voices); used_voices);
} /* if verbose */ } /* if verbose */
fluid_voice_noteoff(voice); fluid_voice_noteoff(voice, synth->min_note_length_ticks);
status = FLUID_OK; status = FLUID_OK;
} /* if voice on */ } /* if voice on */
} /* for all voices */ } /* for all voices */
@ -1424,7 +1429,7 @@ fluid_synth_damp_voices_LOCAL(fluid_synth_t* synth, int chan)
voice = synth->voice[i]; voice = synth->voice[i];
if ((voice->chan == chan) && _SUSTAINED(voice)) if ((voice->chan == chan) && _SUSTAINED(voice))
fluid_voice_noteoff(voice); fluid_voice_noteoff(voice, synth->min_note_length_ticks);
} }
return FLUID_OK; return FLUID_OK;
@ -2008,7 +2013,7 @@ fluid_synth_all_notes_off_LOCAL(fluid_synth_t* synth, int chan)
voice = synth->voice[i]; voice = synth->voice[i];
if (_PLAYING(voice) && (voice->chan == chan)) if (_PLAYING(voice) && (voice->chan == chan))
fluid_voice_noteoff(voice); fluid_voice_noteoff(voice, synth->min_note_length_ticks);
} }
return FLUID_OK; return FLUID_OK;
} }
@ -4687,7 +4692,7 @@ fluid_synth_release_voice_on_same_note_LOCAL(fluid_synth_t* synth, int chan,
&& (voice->chan == chan) && (voice->chan == chan)
&& (voice->key == key) && (voice->key == key)
&& (fluid_voice_get_id(voice) != synth->noteid)) { && (fluid_voice_get_id(voice) != synth->noteid)) {
fluid_voice_noteoff(voice); fluid_voice_noteoff(voice, synth->min_note_length_ticks);
} }
} }
} }
@ -5745,7 +5750,7 @@ fluid_synth_stop_LOCAL (fluid_synth_t *synth, unsigned int id)
voice = synth->voice[i]; voice = synth->voice[i];
if (_ON(voice) && (fluid_voice_get_id (voice) == id)) if (_ON(voice) && (fluid_voice_get_id (voice) == id))
fluid_voice_noteoff(voice); fluid_voice_noteoff(voice, synth->min_note_length_ticks);
} }
} }

View file

@ -108,6 +108,7 @@ typedef struct _fluid_sfont_info_t {
* verbose * verbose
* dump * dump
* sample_rate (will be runtime change-able in the future) * sample_rate (will be runtime change-able in the future)
* min_note_length_ticks
* midi_channels * midi_channels
* audio_channels * audio_channels
* audio_groups * audio_groups
@ -233,7 +234,8 @@ struct _fluid_synth_t
fluid_private_t tuning_iter; /**< Tuning iterators per each thread */ fluid_private_t tuning_iter; /**< Tuning iterators per each thread */
fluid_midi_router_t* midi_router; /**< The midi router. Could be done nicer. */ fluid_midi_router_t* midi_router; /**< The midi router. Could be done nicer. */
fluid_sample_timer_t* sample_timers; /**< List of timers triggered after a block has been processed */ fluid_sample_timer_t* sample_timers; /**< List of timers triggered before a block is processed */
unsigned int min_note_length_ticks; /**< If note-offs are triggered just after a note-on, they will be delayed */
int cores; /**< Number of CPU cores (1 by default) */ int cores; /**< Number of CPU cores (1 by default) */
fluid_thread_t **core_threads; /**< Array of core threads (cores - 1 in length) */ fluid_thread_t **core_threads; /**< Array of core threads (cores - 1 in length) */

View file

@ -142,6 +142,7 @@ fluid_voice_init(fluid_voice_t* voice, fluid_sample_t* sample,
voice->sample = sample; voice->sample = sample;
voice->start_time = start_time; voice->start_time = start_time;
voice->ticks = 0; voice->ticks = 0;
voice->noteoff_ticks = 0;
voice->debug = 0; voice->debug = 0;
voice->has_looped = 0; /* Will be set during voice_write when the 2nd loop point is reached */ voice->has_looped = 0; /* Will be set during voice_write when the 2nd loop point is reached */
voice->last_fres = -1; /* The filter coefficients have to be calculated later in the DSP loop. */ voice->last_fres = -1; /* The filter coefficients have to be calculated later in the DSP loop. */
@ -263,6 +264,11 @@ fluid_voice_write (fluid_voice_t* voice, fluid_real_t *dsp_buf)
return 0; return 0;
} }
if (voice->noteoff_ticks != 0 && voice->ticks >= voice->noteoff_ticks)
{
fluid_voice_noteoff(voice, 0);
}
fluid_check_fpe ("voice_write startup"); fluid_check_fpe ("voice_write startup");
/* Range checking for sample- and loop-related parameters /* Range checking for sample- and loop-related parameters
@ -1551,12 +1557,21 @@ int fluid_voice_modulate_all(fluid_voice_t* voice)
/* /*
* fluid_voice_noteoff * fluid_voice_noteoff
* @param at_tick minimum amount of ticks (samples) when the note
* is turned off.
*/ */
int int
fluid_voice_noteoff(fluid_voice_t* voice) fluid_voice_noteoff(fluid_voice_t* voice, unsigned int at_tick)
{ {
fluid_profile(FLUID_PROF_VOICE_NOTE, voice->ref); fluid_profile(FLUID_PROF_VOICE_NOTE, voice->ref);
if (at_tick > voice->ticks) {
/* Delay noteoff */
voice->noteoff_ticks = at_tick;
return FLUID_OK;
}
voice->noteoff_ticks = 0;
if (voice->channel && fluid_channel_sustained(voice->channel)) { if (voice->channel && fluid_channel_sustained(voice->channel)) {
voice->status = FLUID_VOICE_SUSTAINED; voice->status = FLUID_VOICE_SUSTAINED;
} else { } else {

View file

@ -107,6 +107,7 @@ struct _fluid_voice_t
unsigned int start_time; unsigned int start_time;
unsigned int ticks; unsigned int ticks;
unsigned int noteoff_ticks; /* Delay note-off until this tick */
fluid_real_t amp; /* current linear amplitude */ fluid_real_t amp; /* current linear amplitude */
fluid_phase_t phase; /* the phase of the sample wave */ fluid_phase_t phase; /* the phase of the sample wave */
@ -243,7 +244,7 @@ int fluid_voice_set_gain(fluid_voice_t* voice, fluid_real_t gain);
function.*/ function.*/
void fluid_voice_update_param(fluid_voice_t* voice, int gen); void fluid_voice_update_param(fluid_voice_t* voice, int gen);
int fluid_voice_noteoff(fluid_voice_t* voice); int fluid_voice_noteoff(fluid_voice_t* voice, unsigned int at_tick);
int fluid_voice_off(fluid_voice_t* voice); int fluid_voice_off(fluid_voice_t* voice);
void fluid_voice_mix (fluid_voice_t *voice, void fluid_voice_mix (fluid_voice_t *voice,
fluid_real_t* left_buf, fluid_real_t* right_buf, fluid_real_t* left_buf, fluid_real_t* right_buf,