mirror of
https://github.com/ZDoom/fluidsynth.git
synced 2025-04-08 00:31:11 +00:00
Select soundfont samples by frequency instead of midi note numbers (#932)
For detuned channels it might be better to use another key for Soundfont sample selection giving better approximations for the pitch than the original key. Example: play key 60 on 6370 Hz => use tuned key 64 for sample selection This feature is only enabled for melodic channels. For drum channels we always select Soundfont samples by key numbers.
This commit is contained in:
parent
7ff164d8ab
commit
e096919477
5 changed files with 48 additions and 3 deletions
1
AUTHORS
1
AUTHORS
|
@ -151,3 +151,4 @@ Sven Meier
|
|||
Marcus Weseloh
|
||||
Jean-jacques Ceresa
|
||||
Vladimir Davidovich
|
||||
Tamás Korodi
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "fluid_sys.h"
|
||||
#include "fluid_synth.h"
|
||||
#include "fluid_samplecache.h"
|
||||
#include "fluid_chan.h"
|
||||
|
||||
/* EMU8k/10k hardware applies this factor to initial attenuation generator values set at preset and
|
||||
* instrument level in a soundfont. We apply this factor when loading the generator values to stay
|
||||
|
@ -867,8 +868,26 @@ fluid_defpreset_noteon(fluid_defpreset_t *defpreset, fluid_synth_t *synth, int c
|
|||
fluid_voice_zone_t *voice_zone;
|
||||
fluid_list_t *list;
|
||||
fluid_voice_t *voice;
|
||||
int tuned_key;
|
||||
int i;
|
||||
|
||||
/* For detuned channels it might be better to use another key for Soundfont sample selection
|
||||
* giving better approximations for the pitch than the original key.
|
||||
* Example: play key 60 on 6370 Hz => use tuned key 64 for sample selection
|
||||
*
|
||||
* This feature is only enabled for melodic channels.
|
||||
* For drum channels we always select Soundfont samples by key numbers.
|
||||
*/
|
||||
|
||||
if(synth->channel[chan]->channel_type == CHANNEL_TYPE_MELODIC)
|
||||
{
|
||||
tuned_key = (int)(fluid_channel_get_key_pitch(synth->channel[chan], key) / 100.0f + 0.5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
tuned_key = key;
|
||||
}
|
||||
|
||||
global_preset_zone = fluid_defpreset_get_global_zone(defpreset);
|
||||
|
||||
/* run thru all the zones of this preset */
|
||||
|
@ -879,7 +898,7 @@ fluid_defpreset_noteon(fluid_defpreset_t *defpreset, fluid_synth_t *synth, int c
|
|||
|
||||
/* check if the note falls into the key and velocity range of this
|
||||
preset */
|
||||
if(fluid_zone_inside_range(&preset_zone->range, key, vel))
|
||||
if(fluid_zone_inside_range(&preset_zone->range, tuned_key, vel))
|
||||
{
|
||||
|
||||
inst = fluid_preset_zone_get_inst(preset_zone);
|
||||
|
@ -894,7 +913,7 @@ fluid_defpreset_noteon(fluid_defpreset_t *defpreset, fluid_synth_t *synth, int c
|
|||
the key and velocity range of this instrument zone.
|
||||
An instrument zone must be ignored when its voice is already running
|
||||
played by a legato passage (see fluid_synth_noteon_monopoly_legato()) */
|
||||
if(fluid_zone_inside_range(&voice_zone->range, key, vel))
|
||||
if(fluid_zone_inside_range(&voice_zone->range, tuned_key, vel))
|
||||
{
|
||||
|
||||
inst_zone = voice_zone->inst_zone;
|
||||
|
|
|
@ -374,6 +374,27 @@ fluid_channel_get_sfont_bank_prog(fluid_channel_t *chan, int *sfont,
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the pitch for a key after applying Fluidsynth's tuning functionality
|
||||
* and channel coarse/fine tunings.
|
||||
* @param chan fluid_channel_t
|
||||
* @param key MIDI note number (0-127)
|
||||
* @return the pitch of the key
|
||||
*/
|
||||
fluid_real_t fluid_channel_get_key_pitch(fluid_channel_t *chan, int key)
|
||||
{
|
||||
if(chan->tuning)
|
||||
{
|
||||
return fluid_tuning_get_pitch(chan->tuning, key)
|
||||
+ 100.0f * fluid_channel_get_gen(chan, GEN_COARSETUNE)
|
||||
+ fluid_channel_get_gen(chan, GEN_FINETUNE);
|
||||
}
|
||||
else
|
||||
{
|
||||
return key * 100.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates legato/ staccato playing state
|
||||
* The function is called:
|
||||
|
|
|
@ -142,6 +142,7 @@ void fluid_channel_set_bank_lsb(fluid_channel_t *chan, int banklsb);
|
|||
void fluid_channel_set_bank_msb(fluid_channel_t *chan, int bankmsb);
|
||||
void fluid_channel_get_sfont_bank_prog(fluid_channel_t *chan, int *sfont,
|
||||
int *bank, int *prog);
|
||||
fluid_real_t fluid_channel_get_key_pitch(fluid_channel_t *chan, int key);
|
||||
|
||||
#define fluid_channel_get_preset(chan) ((chan)->preset)
|
||||
#define fluid_channel_set_cc(chan, num, val) \
|
||||
|
|
|
@ -670,6 +670,7 @@ calculate_hold_decay_buffers(fluid_voice_t *voice, int gen_base,
|
|||
* GEN_KEYTOVOLENVDECAY, GEN_KEYTOMODENVHOLD, GEN_KEYTOMODENVDECAY
|
||||
*/
|
||||
|
||||
fluid_real_t keysteps;
|
||||
fluid_real_t timecents;
|
||||
fluid_real_t seconds;
|
||||
int buffers;
|
||||
|
@ -681,7 +682,9 @@ calculate_hold_decay_buffers(fluid_voice_t *voice, int gen_base,
|
|||
* will cause (60-72)*100=-1200 timecents of time variation.
|
||||
* The time is cut in half.
|
||||
*/
|
||||
timecents = (fluid_voice_gen_value(voice, gen_base) + fluid_voice_gen_value(voice, gen_key2base) * (fluid_real_t)(60 - fluid_voice_get_actual_key(voice)));
|
||||
|
||||
keysteps = 60.0f - fluid_channel_get_key_pitch(voice->channel, fluid_voice_get_actual_key(voice)) / 100.0f;
|
||||
timecents = fluid_voice_gen_value(voice, gen_base) + fluid_voice_gen_value(voice, gen_key2base) * keysteps;
|
||||
|
||||
/* Range checking */
|
||||
if(is_decay)
|
||||
|
|
Loading…
Reference in a new issue