mirror of
https://github.com/ZDoom/fluidsynth.git
synced 2024-11-10 06:51:54 +00:00
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:
parent
00580d43ba
commit
f89377de88
12 changed files with 134 additions and 32 deletions
|
@ -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
|
||||
|
|
|
@ -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!"
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in a new issue