Applied patches from S. Christian Collins to improve EMU10K1 synthesis

compatibility, other synthesis fixes and a modulator related crash bug;
Pedro Lopez-Cabanillas for midi.winmidi.device setting
and Nicolas Boulicault for ALSA sequencer midi.portname setting.  Also 
a fix to properly attempt a load of percussion instruments during 
program change.
This commit is contained in:
Josh Green 2008-09-15 04:17:24 +00:00
parent 00580d43ba
commit f89377de88
12 changed files with 134 additions and 32 deletions

View file

@ -12,25 +12,24 @@ author. Josh Green is the current maintainer. Below you'll find a
summary of contributions.
* Peter Hanappe. Initiated the project. files: sticked his nose in all
* Peter Hanappe. Initiated the project. files: stuck his nose in all
files.
* Josh Green is the current maintainer and contributed a lot of code
directly or indirectly through the Swami and Smurf code base.
The SoundFont loader is completely based on his code. He also wrote
the alsa sequencer driver. He made many changes and bug fixes,
but above all, he's one of the driver forces behind the synthesizer.
but above all, he's one of the driving forces behind the synthesizer.
He also created the current FluidSynth graphic logo with Blender
(the blue waves with FluidSynth letters partially submerged).
files: iiwu_defsfont.{c,h}, iiwu_alsa{c,h} and others.
* Markus Nentwig (re-)designed the resonant filter, the chorus, the
LADSPA subsystem, the MIDI router, optimized for SSE, made many
changes and bug fixes and got the synthesizer to actually work. Most
importantly, he used it on stage to make music. files:
iiwu_ladspa.{c,h}, iiwu_cmd.{c,h}, iiwu_voice.{c,h}, iiwu_synth.c,
iiwu_sse.h, iiwu_dsp_core.h, iiwu_rev.{c,h}, and basically all the
other files.
importantly, he used it on stage to make music.
* S. Christian Collins did much testing of FluidSynth in regards to
EMU10K1 compatibility and provided many synthesis fixes in that regard.
* Stephane Letz from Grame wrote most of the MidiShare driver, all of
the PortAudio driver, ported iiwusynth to MacOS X, and sent in many
@ -98,7 +97,9 @@ summary of contributions.
signed integer type). Mozilla NSPR library, www.mozilla.org. file:
iiwu_phase.h
* Growing list of individuals who contributed bug fixes and corrections:
* Growing list of individuals who contributed bug fixes, corrections and minor features:
Pedro Lopez-Cabanillas for midi.winmidi.device setting.
Nicolas Boulicault for ALSA sequencer midi.portname setting.
Werner Schweer
Dave Philips
Anthony Green

View file

@ -1,3 +1,34 @@
2008-09-07 Josh Green <jgreen@users.sourceforge.net>
* src/fluid_alsa.c (new_fluid_alsa_seq_driver): Patch from
Nicolas Boulicault to add ALSA sequencer midi.portname setting.
* src/fluid_conv.h: S. Christian Collins' patch - changed
FLUID_ATTEN_POWER_FACTOR from -531.509 to -200.0.
* src/fluid_defsfont.c (fluid_defpreset_noteon): S. Christian Collins'
patch - crash bug fix related to using certain modulators in a preset.
* src/fluid_mdriver.c: Pedro Lopez-Cabanillas' patch which adds a
midi.winmidi.device setting.
* src/fluid_mod.c: S. Christian Collins' patch - Stop forcing velocity
based filtering and a couple of calculation fixes to transform functions.
* src/fluid_synth.c: Nicolas Boulicault's patch to add midi.portname
setting.
(fluid_synth_program_change): added fix to properly search for a
percussion instrument
* src/fluid_synth.h: Changed FLUID_NUM_PROGRAMS to 128 and set
DRUM_INST_BANK to 128.
* src/fluid_voice.c (fluid_voice_write): S. Christian Collins' patch -
force velocity envelope value to be that of the previous stage when
switching from decay to sustain and filter calculation now uses
synthesizer baud rate rather than fixed at 44100.
(fluid_voice_update_param): S. Christian Collins' patch - Use multiplier
for GEN_ATTENUATION to be compatible with EMU10K1 cards.
* src/fluid_winmidi.c: Pedro Lopez-Cabanillas' patch which adds a
midi.winmidi.device option.
* src/fluidsynth.c: Nicolas Boulicault's patch which adds midi.portname
setting. Pedro Lopez-Cabanillas' patch which breaks out of argument
processing loop for non getopt option argument handling when a non
option is encountered.
2007-11-17 Josh Green <jgreen@users.sourceforge.net>
* FluidSynth release 1.0.8 "Its about funky time!"

View file

@ -897,8 +897,9 @@ new_fluid_alsa_seq_driver(fluid_settings_t* settings,
struct sched_param priority;
int count;
struct pollfd *pfd = NULL;
char* device = NULL;
char* id;
char * device = NULL;
char * id;
char * portname;
char full_id[64];
char full_name[64];
char id_pid[16];
@ -934,6 +935,11 @@ new_fluid_alsa_seq_driver(fluid_settings_t* settings,
id = id_pid;
}
/* get the midi portname */
fluid_settings_getstr(settings, "midi.portname", &portname);
if (!strcmp(portname, ""))
portname = NULL;
/* open the sequencer INPUT only */
err = snd_seq_open(&dev->seq_handle, device, SND_SEQ_OPEN_INPUT, 0);
if (err < 0) {
@ -962,7 +968,12 @@ new_fluid_alsa_seq_driver(fluid_settings_t* settings,
FLUID_FREE(pfd);
/* set the client name */
snd_seq_set_client_name(dev->seq_handle, fluid_alsa_seq_full_id(id, full_id, 64));
if (!portname) {
snd_seq_set_client_name(dev->seq_handle, fluid_alsa_seq_full_id(id, full_id, 64));
}
else {
snd_seq_set_client_name(dev->seq_handle, portname);
}
/* create the ports */
@ -982,7 +993,12 @@ new_fluid_alsa_seq_driver(fluid_settings_t* settings,
for (i = 0; i < dev->port_count; i++) {
snd_seq_port_info_set_name(port_info, fluid_alsa_seq_full_name(id, i, full_name, 64));
if (!portname) {
snd_seq_port_info_set_name(port_info, fluid_alsa_seq_full_name(id, i, full_name, 64));
}
else {
snd_seq_port_info_set_name(port_info, portname);
}
snd_seq_port_info_set_port(port_info, i);
err = snd_seq_create_port(dev->seq_handle, port_info);

View file

@ -32,7 +32,8 @@
/* EMU 8k/10k don't follow spec in regards to volume attenuation.
* This factor is used in the equation pow (10.0, cb / FLUID_ATTEN_POWER_FACTOR).
* By the standard this should be -200.0. */
#define FLUID_ATTEN_POWER_FACTOR (-531.509)
/* 07/11/2008 modified by S. Christian Collins for increased velocity sensitivity. Now it equals the response of EMU10K1 programming.*/
#define FLUID_ATTEN_POWER_FACTOR (-200.0) /* was (-531.509)*/
void fluid_conversion_config(void);

View file

@ -689,7 +689,7 @@ fluid_defpreset_noteon(fluid_defpreset_t* preset, fluid_synth_t* synth, int chan
* page 69, 'bullet' 3 defines 'identical'. */
for (i = 0; i < mod_list_count; i++){
if (fluid_mod_test_identity(mod,mod_list[i])){
if (mod_list[i] && fluid_mod_test_identity(mod,mod_list[i])){
mod_list[i] = NULL;
}
}
@ -768,7 +768,7 @@ fluid_defpreset_noteon(fluid_defpreset_t* preset, fluid_synth_t* synth, int chan
mod = preset_zone->mod;
while (mod){
for (i = 0; i < mod_list_count; i++){
if (fluid_mod_test_identity(mod,mod_list[i])){
if (mod_list[i] && fluid_mod_test_identity(mod,mod_list[i])){
mod_list[i] = NULL;
}
}

View file

@ -52,6 +52,7 @@ fluid_midi_driver_t* new_fluid_winmidi_driver(fluid_settings_t* settings,
handle_midi_event_func_t handler,
void* event_handler_data);
int delete_fluid_winmidi_driver(fluid_midi_driver_t* p);
void fluid_winmidi_midi_driver_settings(fluid_settings_t* settings);
#endif
/* definitions for the MidiShare driver */
@ -98,7 +99,7 @@ struct fluid_mdriver_definition_t fluid_midi_drivers[] = {
{ "winmidi",
new_fluid_winmidi_driver,
delete_fluid_winmidi_driver,
NULL },
fluid_winmidi_midi_driver_settings },
#endif
#if MIDISHARE_SUPPORT
{ "midishare",

View file

@ -146,12 +146,17 @@ fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voic
(mod->flags2 == (FLUID_MOD_GC | FLUID_MOD_UNIPOLAR
| FLUID_MOD_POSITIVE | FLUID_MOD_SWITCH)) &&
(mod->dest == GEN_FILTERFC)) {
// S. Christian Collins' mod, to stop forcing velocity based filtering
/*
if (voice->vel < 64){
return (fluid_real_t) mod->amount / 2.0;
} else {
return (fluid_real_t) mod->amount * (127 - voice->vel) / 127;
}
*/
return 0; // (fluid_real_t) mod->amount / 2.0;
}
// end S. Christian Collins' mod
/* get the initial value of the first source */
if (mod->src1 > 0) {
@ -198,7 +203,7 @@ fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voic
v1 = -1.0f + 2.0f * v1 / range1;
break;
case 3: /* linear, bipolar, negative */
v1 = -1.0f + 2.0f * v1 / range1;
v1 = 1.0f - 2.0f * v1 / range1;
break;
case 4: /* concave, unipolar, positive */
v1 = fluid_concave(v1);
@ -219,7 +224,7 @@ fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voic
v1 = fluid_convex(127 - v1);
break;
case 10: /* convex, bipolar, positive */
v1 = (v1 > 64)? -fluid_convex(2 * (v1 - 64)) : fluid_convex(2 * (64 - v1));
v1 = (v1 > 64)? fluid_convex(2 * (v1 - 64)) : -fluid_convex(2 * (64 - v1));
break;
case 11: /* convex, bipolar, negative */
v1 = (v1 > 64)? -fluid_convex(2 * (v1 - 64)) : fluid_convex(2 * (64 - v1));

View file

@ -112,6 +112,7 @@ void fluid_synth_settings(fluid_settings_t* settings)
fluid_settings_register_str(settings, "synth.reverb.active", "yes", 0, NULL, NULL);
fluid_settings_register_str(settings, "synth.chorus.active", "yes", 0, NULL, NULL);
fluid_settings_register_str(settings, "synth.ladspa.active", "no", 0, NULL, NULL);
fluid_settings_register_str(settings, "midi.portname", "", 0, NULL, NULL);
fluid_settings_register_int(settings, "synth.polyphony",
256, 16, 4096, 0, NULL, NULL);
@ -1170,9 +1171,6 @@ fluid_synth_program_change(fluid_synth_t* synth, int chan, int prognum)
unsigned int banknum;
unsigned int sfont_id;
/* fluid_mutex_lock(synth->busy); /\* Don't interfere with the audio thread *\/ */
/* fluid_mutex_unlock(synth->busy); */
if ((prognum >= 0) && (prognum < FLUID_NUM_PROGRAMS) &&
(chan >= 0) && (chan < synth->midi_channels)) {
@ -1190,8 +1188,8 @@ fluid_synth_program_change(fluid_synth_t* synth, int chan, int prognum)
10 is the percussion channel. */
if (channel->channum == 9) {
/* try to search the drum instrument first */
preset = fluid_synth_find_preset(synth, banknum | DRUM_INST_MASK, prognum);
/* try to search the drum bank first for the given program # */
preset = fluid_synth_find_preset(synth, DRUM_INST_BANK, prognum);
/* if that fails try to search the melodic instrument */
if (preset == NULL) {

View file

@ -44,8 +44,8 @@
*
* DEFINES
*/
#define FLUID_NUM_PROGRAMS 129
#define DRUM_INST_MASK ((unsigned int)0x80000000)
#define FLUID_NUM_PROGRAMS 128
#define DRUM_INST_BANK 128
#if defined(WITH_FLOAT)
#define FLUID_SAMPLE_FORMAT FLUID_SAMPLE_FLOAT

View file

@ -283,6 +283,10 @@ fluid_voice_write(fluid_voice_t* voice,
/* skip to the next section of the envelope if necessary */
while (voice->volenv_count >= env_data->count)
{
// If we're switching envelope stages from decay to sustain, force the value to be the end value of the previous stage
if (env_data && voice->volenv_section == FLUID_VOICE_ENVDECAY)
voice->volenv_val = env_data->min * env_data->coeff;
env_data = &voice->volenv_data[++voice->volenv_section];
voice->volenv_count = 0;
}
@ -515,7 +519,7 @@ fluid_voice_write(fluid_voice_t* voice,
* into account for both significant frequency relocation and for
* bandwidth readjustment'. */
fluid_real_t omega = (fluid_real_t) (2.0 * M_PI * (fres / 44100.0f));
fluid_real_t omega = (fluid_real_t) (2.0 * M_PI * (fres / ((float) voice->output_rate)));
fluid_real_t sin_coeff = (fluid_real_t) sin(omega);
fluid_real_t cos_coeff = (fluid_real_t) cos(omega);
fluid_real_t alpha_coeff = sin_coeff / (2.0f * voice->q_lin);
@ -1031,6 +1035,8 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen)
fluid_real_t x;
fluid_real_t y;
unsigned int count;
// Alternate attenuation scale used by EMU10K1 cards when setting the attenuation at the preset or instrument level within the SoundFont bank.
static const float ALT_ATTENUATION_SCALE = 0.4;
switch (gen) {
@ -1042,7 +1048,8 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen)
break;
case GEN_ATTENUATION:
voice->attenuation = _GEN(voice, GEN_ATTENUATION);
voice->attenuation = ((fluid_real_t)(voice)->gen[GEN_ATTENUATION].val*ALT_ATTENUATION_SCALE) +
(fluid_real_t)(voice)->gen[GEN_ATTENUATION].mod + (fluid_real_t)(voice)->gen[GEN_ATTENUATION].nrpn;
/* Range: SF2.01 section 8.1.3 # 48
* Motivation for range checking:

View file

@ -57,6 +57,24 @@ void CALLBACK fluid_winmidi_callback(HMIDIIN hmi, UINT wMsg, DWORD dwInstance,
static char* fluid_winmidi_input_error(int no);
int fluid_winmidi_driver_status(fluid_midi_driver_t* p);
void fluid_winmidi_midi_driver_settings(fluid_settings_t* settings)
{
MMRESULT res;
MIDIINCAPS in_caps;
UINT i, num;
fluid_settings_register_str(settings, "midi.winmidi.device", "default", 0, NULL, NULL);
num = midiInGetNumDevs();
if (num > 0) {
fluid_settings_add_option(settings, "midi.winmidi.device", "default");
for (i = 0; i < num; i++) {
res = midiInGetDevCaps(i, &in_caps, sizeof(MIDIINCAPS));
if (res == MMSYSERR_NOERROR) {
fluid_settings_add_option(settings, "midi.winmidi.device", in_caps.szPname);
}
}
}
}
/*
* new_fluid_winmidi_driver
*/
@ -69,6 +87,7 @@ new_fluid_winmidi_driver(fluid_settings_t* settings,
UINT i, err, num;
MIDIINCAPS in_caps;
int midi_num = 0;
char* devname = NULL;
/* not much use doing anything */
if (handler == NULL) {
@ -85,6 +104,11 @@ new_fluid_winmidi_driver(fluid_settings_t* settings,
dev->driver.handler = handler;
dev->driver.data = data;
/* get the device name. if none is specified, use the default device. */
if(!fluid_settings_getstr(settings, "midi.winmidi.device", &devname)) {
devname = "default";
}
/* check if there any midi devices installed */
num = midiInGetNumDevs();
if (num == 0) {
@ -93,9 +117,21 @@ new_fluid_winmidi_driver(fluid_settings_t* settings,
}
/* find the device */
for (i = 0; i < num; i++) {
res = midiInGetDevCaps(i, &in_caps, sizeof(LPMIDIINCAPS));
if (res == MMSYSERR_NOERROR) {
if (strcasecmp("default", devname) != 0) {
for (i = 0; i < num; i++) {
res = midiInGetDevCaps(i, &in_caps, sizeof(MIDIINCAPS));
if (res == MMSYSERR_NOERROR) {
FLUID_LOG(FLUID_DBG, "Testing midi device: %s\n", in_caps.szPname);
if (strcasecmp(devname, in_caps.szPname) == 0) {
FLUID_LOG(FLUID_DBG, "Selected midi device number: %d\n", i);
midi_num = i;
break;
}
}
}
if (midi_num != i) {
FLUID_LOG(FLUID_ERR, "Device <%s> does not exists", devname);
goto error_recovery;
}
}

View file

@ -213,7 +213,7 @@ int main(int argc, char** argv)
int with_server = 0;
int dump = 0;
int connect_lash = 1;
char *optchars = "a:C:c:df:G:g:hijK:L:lm:no:R:r:sVvz:";
char *optchars = "a:C:c:df:G:g:hijK:L:lm:no:p:R:r:sVvz:";
#ifdef LASH_ENABLED
int enabled_lash = 0; /* set to TRUE if lash gets enabled */
fluid_lash_args_t *lash_args;
@ -247,6 +247,7 @@ int main(int argc, char** argv)
{"no-midi-in", 0, 0, 'n'},
{"no-shell", 0, 0, 'i'},
{"option", 1, 0, 'o'},
{"portname", 1, 0, 'p'},
{"reverb", 1, 0, 'R'},
{"sample-rate", 1, 0, 'r'},
{"server", 0, 0, 's'},
@ -264,7 +265,7 @@ int main(int argc, char** argv)
char *optarg;
/* Skip non switch arguments (assume they are file names) */
if ((argv[i][0] != '-') || (argv[i][1] == '\0')) continue;
if ((argv[i][0] != '-') || (argv[i][1] == '\0')) break;
c = argv[i][1];
@ -355,6 +356,9 @@ int main(int argc, char** argv)
case 'o':
process_o_cmd_line_option(settings, optarg);
break;
case 'p' :
fluid_settings_setstr(settings, "midi.portname", optarg);
break;
case 'R':
if ((optarg != NULL) && ((strcmp(optarg, "0") == 0) || (strcmp(optarg, "no") == 0))) {
fluid_settings_setstr(settings, "synth.reverb.active", "no");
@ -688,6 +692,8 @@ print_help()
" The name of the midi driver to use [oss,alsa,alsa_seq,...]\n");
printf(" -n, --no-midi-in\n"
" Don't create a midi driver to read MIDI input events [default = yes]\n");
printf(" -p, --portname=[label]\n"
" Set alsa midi port name\n");
printf(" -o\n"
" Define a setting, -o name=value (\"-o help\" to dump current values)\n");
printf(" -R, --reverb\n"