updated fluidsynth to 1.0.9

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32586 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Jérôme Duval 2009-08-21 21:27:45 +00:00
parent 1a7d0f796b
commit dd0edf1f7c
18 changed files with 626 additions and 128 deletions

View File

@ -26,10 +26,10 @@
extern "C" {
#endif
#define FLUIDSYNTH_VERSION "1.0.8"
#define FLUIDSYNTH_VERSION "1.0.9"
#define FLUIDSYNTH_VERSION_MAJOR 1
#define FLUIDSYNTH_VERSION_MINOR 0
#define FLUIDSYNTH_VERSION_MICRO 8
#define FLUIDSYNTH_VERSION_MICRO 9
FLUIDSYNTH_API void fluid_version(int *major, int *minor, int *micro);

View File

@ -1,3 +1,10 @@
[:Team:]
Current development team
Josh Green
Bernat Arlandis i Mañó
Pedro Lopez-Cabanillas
[:Idea:]
@ -12,25 +19,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 +104,11 @@ 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:
* KO Myung-Hun for OS/2 support with Dart audio driver.
* 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

@ -160,11 +160,8 @@
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define to use long long type, where appropriate */
/* #undef USE_LONGLONG */
/* Version number of package */
#define VERSION "1.0.7"
#define VERSION "1.0.9"
/* Define to do all DSP in single floating point precision */
#define WITH_FLOAT 1

View File

@ -37,6 +37,14 @@ typedef struct _fluid_audriver_definition_t
} fluid_audriver_definition_t;
#if PULSE_SUPPORT
fluid_audio_driver_t* new_fluid_pulse_audio_driver(fluid_settings_t* settings,
fluid_synth_t* synth);
fluid_audio_driver_t* new_fluid_pulse_audio_driver2(fluid_settings_t* settings,
fluid_audio_func_t func, void* data);
int delete_fluid_pulse_audio_driver(fluid_audio_driver_t* p);
void fluid_pulse_audio_driver_settings(fluid_settings_t* settings);
#endif
#if ALSA_SUPPORT
fluid_audio_driver_t* new_fluid_alsa_audio_driver(fluid_settings_t* settings,
@ -74,6 +82,7 @@ void fluid_dsound_audio_driver_settings(fluid_settings_t* settings);
#endif
#if PORTAUDIO_SUPPORT
void fluid_portaudio_driver_settings (fluid_settings_t *settings);
fluid_audio_driver_t* new_fluid_portaudio_driver(fluid_settings_t* settings,
fluid_synth_t* synth);
int delete_fluid_portaudio_driver(fluid_audio_driver_t* p);
@ -96,6 +105,13 @@ fluid_audio_driver_t* new_fluid_sndmgr_audio_driver2(fluid_settings_t* settings,
int delete_fluid_sndmgr_audio_driver(fluid_audio_driver_t* p);
#endif
#if DART_SUPPORT
fluid_audio_driver_t* new_fluid_dart_audio_driver(fluid_settings_t* settings,
fluid_synth_t* synth);
int delete_fluid_dart_audio_driver(fluid_audio_driver_t* p);
void fluid_dart_audio_driver_settings(fluid_settings_t* settings);
#endif
#define AUFILE_SUPPORT 1
#if AUFILE_SUPPORT
fluid_audio_driver_t* new_fluid_file_audio_driver(fluid_settings_t* settings,
@ -104,13 +120,14 @@ int delete_fluid_file_audio_driver(fluid_audio_driver_t* p);
void fluid_file_audio_driver_settings(fluid_settings_t* settings);
#endif
/* Available audio drivers, listed in order of preference */
fluid_audriver_definition_t fluid_audio_drivers[] = {
#if OSS_SUPPORT
{ "oss",
new_fluid_oss_audio_driver,
new_fluid_oss_audio_driver2,
delete_fluid_oss_audio_driver,
fluid_oss_audio_driver_settings },
#if JACK_SUPPORT
{ "jack",
new_fluid_jack_audio_driver,
new_fluid_jack_audio_driver2,
delete_fluid_jack_audio_driver,
fluid_jack_audio_driver_settings },
#endif
#if ALSA_SUPPORT
{ "alsa",
@ -119,6 +136,20 @@ fluid_audriver_definition_t fluid_audio_drivers[] = {
delete_fluid_alsa_audio_driver,
fluid_alsa_audio_driver_settings },
#endif
#if OSS_SUPPORT
{ "oss",
new_fluid_oss_audio_driver,
new_fluid_oss_audio_driver2,
delete_fluid_oss_audio_driver,
fluid_oss_audio_driver_settings },
#endif
#if PULSE_SUPPORT
{ "pulseaudio",
new_fluid_pulse_audio_driver,
new_fluid_pulse_audio_driver2,
delete_fluid_pulse_audio_driver,
fluid_pulse_audio_driver_settings },
#endif
#if COREAUDIO_SUPPORT
{ "coreaudio",
new_fluid_core_audio_driver,
@ -138,7 +169,7 @@ fluid_audriver_definition_t fluid_audio_drivers[] = {
new_fluid_portaudio_driver,
NULL,
delete_fluid_portaudio_driver,
NULL },
fluid_portaudio_driver_settings },
#endif
#if SNDMAN_SUPPORT
{ "sndman",
@ -147,12 +178,12 @@ fluid_audriver_definition_t fluid_audio_drivers[] = {
delete_fluid_sndmgr_audio_driver,
NULL },
#endif
#if JACK_SUPPORT
{ "jack",
new_fluid_jack_audio_driver,
new_fluid_jack_audio_driver2,
delete_fluid_jack_audio_driver,
fluid_jack_audio_driver_settings },
#if DART_SUPPORT
{ "dart",
new_fluid_dart_audio_driver,
NULL,
delete_fluid_dart_audio_driver,
fluid_dart_audio_driver_settings },
#endif
#if AUFILE_SUPPORT
{ "file",
@ -191,8 +222,12 @@ void fluid_audio_driver_settings(fluid_settings_t* settings)
#endif
/* Set the default driver */
#if ALSA_SUPPORT
#if JACK_SUPPORT
fluid_settings_register_str(settings, "audio.driver", "jack", 0, NULL, NULL);
#elif ALSA_SUPPORT
fluid_settings_register_str(settings, "audio.driver", "alsa", 0, NULL, NULL);
#elif PULSE_SUPPORT
fluid_settings_register_str(settings, "audio.driver", "pulseaudio", 0, NULL, NULL);
#elif OSS_SUPPORT
fluid_settings_register_str(settings, "audio.driver", "oss", 0, NULL, NULL);
#elif COREAUDIO_SUPPORT
@ -203,8 +238,8 @@ void fluid_audio_driver_settings(fluid_settings_t* settings)
fluid_settings_register_str(settings, "audio.driver", "sndman", 0, NULL, NULL);
#elif PORTAUDIO_SUPPORT
fluid_settings_register_str(settings, "audio.driver", "portaudio", 0, NULL, NULL);
#elif JACK_SUPPORT
fluid_settings_register_str(settings, "audio.driver", "jack", 0, NULL, NULL);
#elif DART_SUPPORT
fluid_settings_register_str(settings, "audio.driver", "dart", 0, NULL, NULL);
#elif AUFILE_SUPPORT
fluid_settings_register_str(settings, "audio.driver", "file", 0, NULL, NULL);
#else
@ -212,6 +247,9 @@ void fluid_audio_driver_settings(fluid_settings_t* settings)
#endif
/* Add all drivers to the list of options */
#if PULSE_SUPPORT
fluid_settings_add_option(settings, "audio.driver", "pulseaudio");
#endif
#if ALSA_SUPPORT
fluid_settings_add_option(settings, "audio.driver", "alsa");
#endif
@ -233,6 +271,9 @@ void fluid_audio_driver_settings(fluid_settings_t* settings)
#if JACK_SUPPORT
fluid_settings_add_option(settings, "audio.driver", "jack");
#endif
#if DART_SUPPORT
fluid_settings_add_option(settings, "audio.driver", "dart");
#endif
#if AUFILE_SUPPORT
fluid_settings_add_option(settings, "audio.driver", "file");
#endif

View File

@ -62,6 +62,7 @@ fluid_channel_init(fluid_channel_t* chan)
chan->interp_method = FLUID_INTERP_DEFAULT;
chan->tuning = NULL;
chan->nrpn_select = 0;
chan->nrpn_active = 0;
}
void
@ -85,16 +86,20 @@ fluid_channel_init_ctrl(fluid_channel_t* chan)
}
/* Volume / initial attenuation (MSB & LSB) */
SETCC(chan, 7, 127);
SETCC(chan, 39, 0);
SETCC(chan, VOLUME_MSB, 127);
SETCC(chan, VOLUME_LSB, 0);
/* Pan (MSB & LSB) */
SETCC(chan, 10, 64);
SETCC(chan, 10, 64);
SETCC(chan, PAN_MSB, 64);
SETCC(chan, PAN_LSB, 0);
/* Expression (MSB & LSB) */
SETCC(chan, 11, 127);
SETCC(chan, 43, 127);
SETCC(chan, EXPRESSION_MSB, 127);
SETCC(chan, EXPRESSION_LSB, 127);
/* Set RPN controllers to NULL state */
SETCC(chan, RPN_LSB, 127);
SETCC(chan, RPN_MSB, 127);
}
void
@ -241,18 +246,52 @@ fluid_channel_cc(fluid_channel_t* chan, int num, int value)
{
int data = (value << 7) + chan->cc[DATA_ENTRY_LSB];
/* SontFont 2.01 NRPN Message (Sect. 9.6, p. 74) */
if ((chan->cc[NRPN_MSB] == 120) && (chan->cc[NRPN_LSB] < 100)) {
float val = fluid_gen_scale_nrpn(chan->nrpn_select, data);
FLUID_LOG(FLUID_WARN, "%s: %d: Data = %d, value = %f", __FILE__, __LINE__, data, val);
fluid_synth_set_gen(chan->synth, chan->channum, chan->nrpn_select, val);
if (chan->nrpn_active) /* NRPN is active? */
{
/* SontFont 2.01 NRPN Message (Sect. 9.6, p. 74) */
if ((chan->cc[NRPN_MSB] == 120) && (chan->cc[NRPN_LSB] < 100))
{
if (chan->nrpn_select < GEN_LAST)
{
float val = fluid_gen_scale_nrpn(chan->nrpn_select, data);
fluid_synth_set_gen(chan->synth, chan->channum, chan->nrpn_select, val);
}
chan->nrpn_select = 0; /* Reset to 0 */
}
}
else if (chan->cc[RPN_MSB] == 0) /* RPN is active: MSB = 0? */
{
switch (chan->cc[RPN_LSB])
{
case RPN_PITCH_BEND_RANGE:
fluid_channel_pitch_wheel_sens (chan, value); /* Set bend range in semitones */
/* FIXME - Handle LSB? (Fine bend range in cents) */
break;
case RPN_CHANNEL_FINE_TUNE: /* Fine tune is 14 bit over 1 semitone (+/- 50 cents, 8192 = center) */
fluid_synth_set_gen(chan->synth, chan->channum, GEN_FINETUNE,
(data - 8192) / 8192.0 * 50.0);
break;
case RPN_CHANNEL_COARSE_TUNE: /* Coarse tune is 7 bit and in semitones (64 is center) */
fluid_synth_set_gen(chan->synth, chan->channum, GEN_COARSETUNE,
value - 64);
break;
case RPN_TUNING_PROGRAM_CHANGE:
break;
case RPN_TUNING_BANK_SELECT:
break;
case RPN_MODULATION_DEPTH_RANGE:
break;
}
}
break;
}
case NRPN_MSB:
chan->cc[NRPN_LSB] = 0;
chan->nrpn_select = 0;
chan->nrpn_active = 1;
break;
case NRPN_LSB:
@ -266,19 +305,15 @@ fluid_channel_cc(fluid_channel_t* chan, int num, int value)
chan->nrpn_select += 10000;
} else if (value < 100) {
chan->nrpn_select += value;
FLUID_LOG(FLUID_WARN, "%s: %d: NRPN Select = %d", __FILE__, __LINE__, chan->nrpn_select);
}
}
chan->nrpn_active = 1;
break;
case RPN_MSB:
break;
case RPN_LSB:
/* erase any previously received NRPN message */
chan->cc[NRPN_MSB] = 0;
chan->cc[NRPN_LSB] = 0;
chan->nrpn_select = 0;
chan->nrpn_active = 0;
break;
default:
@ -297,6 +332,17 @@ fluid_channel_get_cc(fluid_channel_t* chan, int num)
return ((num >= 0) && (num < 128))? chan->cc[num] : 0;
}
/*
* fluid_channel_pressure
*/
int
fluid_channel_pressure(fluid_channel_t* chan, int val)
{
chan->channel_pressure = val;
fluid_synth_modulate_voices(chan->synth, chan->channum, 0, FLUID_MOD_CHANNELPRESSURE);
return FLUID_OK;
}
/*
* fluid_channel_pitch_bend
*/

View File

@ -53,6 +53,7 @@ struct _fluid_channel_t
/* NRPN system */
short nrpn_select;
short nrpn_active; /* 1 if data entry CCs are for NRPN, 0 if RPN */
/* The values of the generators, set by NRPN messages, or by
* fluid_synth_set_gen(), are cached in the channel so they can be
@ -87,6 +88,7 @@ int fluid_channel_set_banknum(fluid_channel_t* chan, unsigned int bank);
int fluid_channel_set_prognum(fluid_channel_t* chan, int prognum);
int fluid_channel_get_prognum(fluid_channel_t* chan);
int fluid_channel_cc(fluid_channel_t* chan, int ctrl, int val);
int fluid_channel_pressure(fluid_channel_t* chan, int val);
int fluid_channel_pitch_bend(fluid_channel_t* chan, int val);
int fluid_channel_pitch_wheel_sens(fluid_channel_t* chan, int val);
int fluid_channel_get_cc(fluid_channel_t* chan, int num);

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

@ -37,6 +37,15 @@ int delete_fluid_alsa_seq_driver(fluid_midi_driver_t* p);
void fluid_alsa_seq_driver_settings(fluid_settings_t* settings);
#endif
/* JACK */
#if JACK_SUPPORT
void fluid_jack_midi_driver_settings (fluid_settings_t *settings);
fluid_midi_driver_t *new_fluid_jack_midi_driver (fluid_settings_t *settings,
handle_midi_event_func_t handler,
void *data);
int delete_fluid_jack_midi_driver(fluid_midi_driver_t *p);
#endif
/* OSS */
#if OSS_SUPPORT
fluid_midi_driver_t* new_fluid_oss_midi_driver(fluid_settings_t* settings,
@ -52,6 +61,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 */
@ -62,6 +72,14 @@ fluid_midi_driver_t* new_fluid_midishare_midi_driver(fluid_settings_t* settings,
int delete_fluid_midishare_midi_driver(fluid_midi_driver_t* p);
#endif
/* definitions for the CoreMidi driver */
#if COREMIDI_SUPPORT
fluid_midi_driver_t* new_fluid_coremidi_driver(fluid_settings_t* settings,
void* event_handler_data,
handle_midi_event_func_t handler);
int delete_fluid_coremidi_driver(fluid_midi_driver_t* p);
void fluid_coremidi_driver_settings(fluid_settings_t* settings);
#endif
/*
@ -78,6 +96,12 @@ struct fluid_mdriver_definition_t {
struct fluid_mdriver_definition_t fluid_midi_drivers[] = {
#if JACK_SUPPORT
{ "jack",
new_fluid_jack_midi_driver,
delete_fluid_jack_midi_driver,
fluid_jack_midi_driver_settings },
#endif
#if OSS_SUPPORT
{ "oss",
new_fluid_oss_midi_driver,
@ -98,13 +122,19 @@ 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",
new_fluid_midishare_midi_driver,
delete_fluid_midishare_midi_driver,
NULL },
#endif
#if COREMIDI_SUPPORT
{ "coremidi",
new_fluid_coremidi_driver,
delete_fluid_coremidi_driver,
fluid_coremidi_driver_settings },
#endif
{ NULL, NULL, NULL, NULL }
};
@ -118,12 +148,16 @@ void fluid_midi_driver_settings(fluid_settings_t* settings)
/* Set the default driver */
#if ALSA_SUPPORT
fluid_settings_register_str(settings, "midi.driver", "alsa_seq", 0, NULL, NULL);
#elif JACK_SUPPORT
fluid_settings_register_str(settings, "midi.driver", "jack", 0, NULL, NULL);
#elif OSS_SUPPORT
fluid_settings_register_str(settings, "midi.driver", "oss", 0, NULL, NULL);
#elif WINMIDI_SUPPORT
fluid_settings_register_str(settings, "midi.driver", "winmidi", 0, NULL, NULL);
#elif MIDISHARE_SUPPORT
fluid_settings_register_str(settings, "midi.driver", "midishare", 0, NULL, NULL);
#elif COREMIDI_SUPPORT
fluid_settings_register_str(settings, "midi.driver", "coremidi", 0, NULL, NULL);
#else
fluid_settings_register_str(settings, "midi.driver", "", 0, NULL, NULL);
#endif
@ -133,6 +167,9 @@ void fluid_midi_driver_settings(fluid_settings_t* settings)
fluid_settings_add_option(settings, "midi.driver", "alsa_seq");
fluid_settings_add_option(settings, "midi.driver", "alsa_raw");
#endif
#if JACK_SUPPORT
fluid_settings_add_option(settings, "midi.driver", "jack");
#endif
#if OSS_SUPPORT
fluid_settings_add_option(settings, "midi.driver", "oss");
#endif
@ -142,6 +179,9 @@ void fluid_midi_driver_settings(fluid_settings_t* settings)
#if MIDISHARE_SUPPORT
fluid_settings_add_option(settings, "midi.driver", "midishare");
#endif
#if COREMIDI_SUPPORT
fluid_settings_add_option(settings, "midi.driver", "coremidi");
#endif
for (i = 0; fluid_midi_drivers[i].name != NULL; i++) {
if (fluid_midi_drivers[i].settings != NULL) {
@ -168,7 +208,7 @@ fluid_midi_driver_t* new_fluid_midi_driver(fluid_settings_t* settings, handle_mi
FLUID_LOG(FLUID_DBG, "Using '%s' midi driver", fluid_midi_drivers[i].name);
driver = fluid_midi_drivers[i].new(settings, handler, event_handler_data);
if (driver) {
driver->name = fluid_midi_drivers[i].name;
driver->name = fluid_midi_drivers[i].name;
}
return driver;
}

View File

@ -272,6 +272,7 @@ int fluid_midi_file_read_track(fluid_midi_file* mf, fluid_player_t* player, int
return FLUID_FAILED;
}
id[4]='\0';
mf->dtime = 0;
while (!found_track){
@ -354,7 +355,6 @@ int fluid_midi_file_read_varlen(fluid_midi_file* mf)
*/
int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track)
{
int dtime;
int status;
int type;
int tempo;
@ -371,7 +371,7 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track)
if (fluid_midi_file_read_varlen(mf) != FLUID_OK) {
return FLUID_FAILED;
}
dtime = mf->varlen;
mf->dtime += mf->varlen;
/* read the status byte */
status = fluid_midi_file_getc(mf);
@ -519,12 +519,13 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track)
result = FLUID_FAILED;
break;
}
evt->dtime = dtime;
evt->dtime = mf->dtime;
evt->type = MIDI_SET_TEMPO;
evt->channel = 0;
evt->param1 = tempo;
evt->param2 = 0;
fluid_track_add_event(track, evt);
mf->dtime = 0;
break;
case MIDI_SMPTE_OFFSET:
@ -642,12 +643,13 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track)
FLUID_LOG(FLUID_ERR, "Out of memory");
return FLUID_FAILED;
}
evt->dtime = dtime;
evt->dtime = mf->dtime;
evt->type = type;
evt->channel = channel;
evt->param1 = param1;
evt->param2 = param2;
fluid_track_add_event(track, evt);
mf->dtime = 0;
}
}
return FLUID_OK;

View File

@ -146,6 +146,16 @@ enum fluid_midi_control_change {
POLY_ON = 0x7F
};
/* General MIDI RPN event numbers (LSB, MSB = 0) */
enum midi_rpn_event {
RPN_PITCH_BEND_RANGE = 0x00,
RPN_CHANNEL_FINE_TUNE = 0x01,
RPN_CHANNEL_COARSE_TUNE = 0x02,
RPN_TUNING_PROGRAM_CHANGE = 0x03,
RPN_TUNING_BANK_SELECT = 0x04,
RPN_MODULATION_DEPTH_RANGE = 0x05
};
enum midi_meta_event {
MIDI_COPYRIGHT = 0x02,
MIDI_TRACK_NAME = 0x03,
@ -280,6 +290,7 @@ typedef struct {
int trackpos;
int eot;
int varlen;
int dtime;
} fluid_midi_file;
fluid_midi_file* new_fluid_midi_file(char* filename);

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);
@ -996,8 +997,48 @@ fluid_synth_modulate_voices_all(fluid_synth_t* synth, int chan)
return FLUID_OK;
}
/*
* fluid_synth_pitch_bend
/**
* Set the MIDI channel pressure controller value.
* @param synth FluidSynth instance
* @param chan MIDI channel number
* @param val MIDI channel pressure value (7 bit, 0-127)
* @return FLUID_OK on success
*
* Assign to the MIDI channel pressure controller value on a specific MIDI channel
* in real time.
*/
int
fluid_synth_channel_pressure(fluid_synth_t* synth, int chan, int val)
{
/* fluid_mutex_lock(synth->busy); /\* Don't interfere with the audio thread *\/ */
/* fluid_mutex_unlock(synth->busy); */
/* check the ranges of the arguments */
if ((chan < 0) || (chan >= synth->midi_channels)) {
FLUID_LOG(FLUID_WARN, "Channel out of range");
return FLUID_FAILED;
}
if (synth->verbose) {
FLUID_LOG(FLUID_INFO, "channelpressure\t%d\t%d", chan, val);
}
/* set the channel pressure value in the channel */
fluid_channel_pressure(synth->channel[chan], val);
return FLUID_OK;
}
/**
* Set the MIDI pitch bend controller value.
* @param synth FluidSynth instance
* @param chan MIDI channel number
* @param val MIDI pitch bend value (14 bit, 0-16383 with 8192 being center)
* @return FLUID_OK on success
*
* Assign to the MIDI pitch bend controller value on a specific MIDI channel
* in real time.
*/
int
fluid_synth_pitch_bend(fluid_synth_t* synth, int chan, int val)
@ -1169,48 +1210,72 @@ fluid_synth_program_change(fluid_synth_t* synth, int chan, int prognum)
fluid_channel_t* channel;
unsigned int banknum;
unsigned int sfont_id;
int subst_bank, subst_prog;
/* 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)) {
channel = synth->channel[chan];
banknum = fluid_channel_get_banknum(channel);
/* inform the channel of the new program number */
fluid_channel_set_prognum(channel, prognum);
if (synth->verbose) {
FLUID_LOG(FLUID_INFO, "prog\t%d\t%d\t%d", chan, banknum, prognum);
}
/* special handling of channel 10 (or 9 counting from 0). channel
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);
/* if that fails try to search the melodic instrument */
if (preset == NULL) {
preset = fluid_synth_find_preset(synth, banknum, prognum);
}
} else {
preset = fluid_synth_find_preset(synth, banknum, prognum);
}
sfont_id = preset? fluid_sfont_get_id(preset->sfont) : 0;
fluid_channel_set_sfontnum(channel, sfont_id);
fluid_channel_set_preset(channel, preset);
return FLUID_OK;
if ((prognum < 0) || (prognum >= FLUID_NUM_PROGRAMS) ||
(chan < 0) || (chan >= synth->midi_channels))
{
FLUID_LOG(FLUID_ERR, "Index out of range (chan=%d, prog=%d)", chan, prognum);
return FLUID_FAILED;
}
FLUID_LOG(FLUID_ERR, "Index out of range (chan=%d, prog=%d)", chan, prognum);
return FLUID_FAILED;
channel = synth->channel[chan];
banknum = fluid_channel_get_banknum(channel);
/* inform the channel of the new program number */
fluid_channel_set_prognum(channel, prognum);
if (synth->verbose)
FLUID_LOG(FLUID_INFO, "prog\t%d\t%d\t%d", chan, banknum, prognum);
/* Special handling of channel 10 (or 9 counting from 0). channel
* 10 is the percussion channel.
*
* FIXME - Shouldn't hard code bank selection for channel 10. I think this
* is a hack for MIDI files that do bank changes in GM mode. Proper way to
* handle this would probably be to ignore bank changes when in GM mode.
*/
if (channel->channum == 9)
preset = fluid_synth_find_preset(synth, DRUM_INST_BANK, prognum);
else preset = fluid_synth_find_preset(synth, banknum, prognum);
/* Fallback to another preset if not found */
if (!preset)
{
subst_bank = banknum;
subst_prog = prognum;
/* Melodic instrument? */
if (channel->channum != 9 && banknum != DRUM_INST_BANK)
{
subst_bank = 0;
/* Fallback first to bank 0:prognum */
preset = fluid_synth_find_preset(synth, 0, prognum);
/* Fallback to first preset in bank 0 */
if (!preset && prognum != 0)
{
preset = fluid_synth_find_preset(synth, 0, 0);
subst_prog = 0;
}
}
else /* Percussion: Fallback to preset 0 in percussion bank */
{
preset = fluid_synth_find_preset(synth, DRUM_INST_BANK, 0);
subst_prog = 0;
}
if (preset)
FLUID_LOG(FLUID_WARN, "Instrument not found on channel %d [bank=%d prog=%d], substituted [bank=%d prog=%d]",
chan, banknum, prognum, subst_bank, subst_prog);
}
sfont_id = preset? fluid_sfont_get_id(preset->sfont) : 0;
fluid_channel_set_sfontnum(channel, sfont_id);
fluid_channel_set_preset(channel, preset);
return FLUID_OK;
}
/*
@ -1562,13 +1627,11 @@ void fluid_synth_set_chorus(fluid_synth_t* synth, int nr, double level,
*/
int
fluid_synth_nwrite_float(fluid_synth_t* synth, int len,
float** left, float** right,
float** fx_left, float** fx_right)
float** left, float** right,
float** fx_left, float** fx_right)
{
fluid_real_t** left_in = synth->left_buf;
fluid_real_t** right_in = synth->right_buf;
fluid_real_t** fx_left_in = synth->fx_left_buf;
fluid_real_t** fx_right_in = synth->fx_right_buf;
double time = fluid_utime();
int i, num, available, count, bytes;
@ -1590,10 +1653,6 @@ fluid_synth_nwrite_float(fluid_synth_t* synth, int len,
FLUID_MEMCPY(left[i], left_in[i] + synth->cur, bytes);
FLUID_MEMCPY(right[i], right_in[i] + synth->cur, bytes);
}
for (i = 0; i < synth->effects_channels; i++) {
FLUID_MEMCPY(fx_left[i], fx_left_in[i] + synth->cur, bytes);
FLUID_MEMCPY(fx_right[i], fx_right_in[i] + synth->cur, bytes);
}
count += num;
num += synth->cur; /* if we're now done, num becomes the new synth->cur below */
}
@ -1609,10 +1668,6 @@ fluid_synth_nwrite_float(fluid_synth_t* synth, int len,
FLUID_MEMCPY(left[i] + count, left_in[i], bytes);
FLUID_MEMCPY(right[i] + count, right_in[i], bytes);
}
for (i = 0; i < synth->effects_channels; i++) {
FLUID_MEMCPY(fx_left[i] + count, fx_left_in[i], bytes);
FLUID_MEMCPY(fx_right[i] + count, fx_right_in[i], bytes);
}
count += num;
}
@ -1628,11 +1683,28 @@ fluid_synth_nwrite_float(fluid_synth_t* synth, int len,
return 0;
}
int fluid_synth_process(fluid_synth_t* synth, int len,
int nin, float** in,
int nout, float** out)
{
return fluid_synth_write_float(synth, len, out[0], 0, 1, out[1], 0, 1);
if (nout==2) {
return fluid_synth_write_float(synth, len, out[0], 0, 1, out[1], 0, 1);
}
else {
float **left, **right;
int i;
left = FLUID_ARRAY(float*, nout/2);
right = FLUID_ARRAY(float*, nout/2);
for(i=0; i<nout/2; i++) {
left[i] = out[2*i];
right[i] = out[2*i+1];
}
fluid_synth_nwrite_float(synth, len, left, right, NULL, NULL);
FLUID_FREE(left);
FLUID_FREE(right);
return 0;
}
}
@ -3028,6 +3100,9 @@ int fluid_synth_handle_midi_event(void* data, fluid_midi_event_t* event)
case PROGRAM_CHANGE:
return fluid_synth_program_change(synth, chan, fluid_midi_event_get_program(event));
case CHANNEL_PRESSURE:
return fluid_synth_channel_pressure(synth, chan, fluid_midi_event_get_program(event));
case PITCH_BEND:
return fluid_synth_pitch_bend(synth, chan, fluid_midi_event_get_pitch(event));

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

@ -635,6 +635,185 @@ unsigned int fluid_curtime()
}
#elif defined(__OS2__)
/*=============================================================*/
/* */
/* OS2 */
/* */
/*=============================================================*/
/***************************************************************
*
* Timer
*
*/
struct _fluid_timer_t
{
long msec;
fluid_timer_callback_t callback;
void* data;
int thread_id;
int cont;
int auto_destroy;
};
static int fluid_timer_count = 0;
void fluid_timer_run(void *data);
fluid_timer_t*
new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data,
int new_thread, int auto_destroy)
{
fluid_timer_t* timer = FLUID_NEW(fluid_timer_t);
if (timer == NULL) {
FLUID_LOG(FLUID_ERR, "Out of memory");
return NULL;
}
timer->cont = 1;
timer->msec = msec;
timer->callback = callback;
timer->data = data;
timer->thread_id =-1;
timer->auto_destroy = auto_destroy;
if (new_thread) {
timer->thread_id = _beginthread( fluid_timer_run, NULL, 256 * 1024, ( void * )timer );
if (timer->thread_id == -1) {
FLUID_LOG(FLUID_ERR, "Couldn't create timer thread");
FLUID_FREE(timer);
return NULL;
}
DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, PRTYD_MAXIMUM, timer->thread_id);
} else {
fluid_timer_run(( void * )timer);
}
return timer;
}
void
fluid_timer_run(void *data)
{
int count = 0;
int cont = 1;
long start;
long delay;
fluid_timer_t* timer;
timer = (fluid_timer_t*) data;
if ((timer == NULL) || (timer->callback == NULL)) {
return;
}
DosSetPriority( PRTYS_THREAD, PRTYC_REGULAR, PRTYD_MAXIMUM, 0 );
/* keep track of the start time for absolute positioning */
start = fluid_curtime();
while (cont) {
/* do whatever we have to do */
cont = (*timer->callback)(timer->data, fluid_curtime() - start);
count++;
/* to avoid incremental time errors, I calculate the delay between
two callbacks bringing in the "absolute" time (count *
timer->msec) */
delay = (count * timer->msec) - (fluid_curtime() - start);
if (delay > 0) {
DosSleep(delay);
}
cont &= timer->cont;
}
FLUID_LOG(FLUID_DBG, "Timer thread finished");
if (timer->auto_destroy) {
FLUID_FREE(timer);
}
return;
}
int
delete_fluid_timer(fluid_timer_t* timer)
{
timer->cont = 0;
fluid_timer_join(timer);
FLUID_FREE(timer);
return FLUID_OK;
}
int
fluid_timer_join(fluid_timer_t* timer)
{
ULONG wait_result;
if (timer->thread_id == -1) {
return FLUID_OK;
}
wait_result = DosWaitThread(&timer->thread_id, DCWW_WAIT);
return (wait_result == 0)? FLUID_OK : FLUID_FAILED;
}
/***************************************************************
*
* Time
*/
double rdtsc(void);
double fluid_estimate_cpu_frequency(void);
static double fluid_cpu_frequency = -1.0;
void fluid_time_config(void)
{
if (fluid_cpu_frequency < 0.0) {
fluid_cpu_frequency = fluid_estimate_cpu_frequency() / 1000000.0;
}
}
unsigned int fluid_curtime(void)
{
ULONG ulMS;
DosQuerySysInfo( QSV_MS_COUNT, QSV_MS_COUNT, &ulMS, sizeof( ULONG ));
return ulMS;
}
double fluid_utime(void)
{
return (rdtsc() / fluid_cpu_frequency);
}
#define Q2ULL( q ) (*(unsigned long long *)&q)
double rdtsc(void)
{
QWORD t;
DosTmrQueryTime(&t);
return (double)Q2ULL(t);
}
double fluid_estimate_cpu_frequency(void)
{
unsigned int before, after;
QWORD start, stop;
before = fluid_curtime();
DosTmrQueryTime(&start);
DosSleep(1000);
after = fluid_curtime();
DosTmrQueryTime(&stop);
return (double) 1000 * (Q2ULL(stop) - Q2ULL(start)) / (after - before);
}
#elif defined(__BEOS__) || defined(__HAIKU__)
struct _fluid_timer_t
@ -1153,6 +1332,75 @@ int fluid_thread_join(fluid_thread_t* thread)
return (wait_result == WAIT_OBJECT_0)? FLUID_OK : FLUID_FAILED;
}
#elif defined(__OS2__)
struct _fluid_thread_t {
int thread_id;
fluid_thread_func_t func;
void* data;
int detached;
};
static void fluid_thread_start(void *data)
{
fluid_thread_t* thread = (fluid_thread_t*) data;
thread->func(thread->data);
if (thread->detached) {
FLUID_FREE(thread);
}
return 0;
}
fluid_thread_t* new_fluid_thread(fluid_thread_func_t func, void* data, int detach)
{
fluid_thread_t* thread;
if (func == NULL) {
FLUID_LOG(FLUID_ERR, "Invalid thread function");
return NULL;
}
thread = FLUID_NEW(fluid_thread_t);
if (thread == NULL) {
FLUID_LOG(FLUID_ERR, "Out of memory");
return NULL;
}
thread->data = data;
thread->func = func;
thread->detached = detach;
thread->thread_id = _beginthread(fluid_thread_start, NULL, 256 * 1024, (void *) thread);
if (thread->thread_id == -1) {
FLUID_LOG(FLUID_ERR, "Couldn't create the thread");
FLUID_FREE(thread);
return NULL;
}
return thread;
}
int delete_fluid_thread(fluid_thread_t* thread)
{
FLUID_FREE(thread);
return FLUID_OK;
}
int fluid_thread_join(fluid_thread_t* thread)
{
ULONG wait_result;
if (thread->thread_id == -1) {
return FLUID_OK;
}
wait_result = DosWaitThread(&thread->thread_id, DCWW_WAIT);
return (wait_result == 0)? FLUID_OK : FLUID_FAILED;
}
#elif defined(__BEOS__) || defined(__HAIKU__)
/* Not implemented */
fluid_thread_t* new_fluid_thread(fluid_thread_func_t func, void* data, int detach) { return NULL; }

View File

@ -90,6 +90,15 @@ double fluid_utime(void);
unsigned int fluid_curtime();
#define fluid_utime() 0.0
#elif defined(__OS2__)
#define INCL_DOS
#include <os2.h>
typedef int socklen_t;
unsigned int fluid_curtime(void);
double fluid_utime(void);
#elif (defined(__BEOS__) || defined(__HAIKU__))
#include <OS.h>
@ -143,13 +152,12 @@ typedef HANDLE fluid_mutex_t;
#define fluid_mutex_lock(_m) WaitForSingleObject(_m, INFINITE)
#define fluid_mutex_unlock(_m) ReleaseMutex(_m)
#else
#ifndef HAIKU_TARGET_PLATFORM_HAIKU
typedef sem_id fluid_mutex_t;
#define fluid_mutex_init(_m) { (_m) = create_sem(1, "fs_sem"); }
#define fluid_mutex_destroy(_m) delete_sem(_m);
#define fluid_mutex_lock(_m) acquire_sem(_m);
#define fluid_mutex_unlock(_m) release_sem(_m);
#elif defined(__OS2__)
typedef HMTX fluid_mutex_t;
#define fluid_mutex_init(_m) { (_m) = 0; DosCreateMutexSem( NULL, &(_m), 0, FALSE ); }
#define fluid_mutex_destroy(_m) if (_m) { DosCloseMutexSem(_m); }
#define fluid_mutex_lock(_m) DosRequestMutexSem(_m, -1L)
#define fluid_mutex_unlock(_m) DosReleaseMutexSem(_m)
#else
typedef pthread_mutex_t fluid_mutex_t;
@ -158,7 +166,6 @@ typedef pthread_mutex_t fluid_mutex_t;
#define fluid_mutex_lock(_m) pthread_mutex_lock(&(_m))
#define fluid_mutex_unlock(_m) pthread_mutex_unlock(&(_m))
#endif
#endif
/**
@ -283,7 +290,7 @@ extern fluid_profile_data_t fluid_profile_data[];
sample data.
*/
#if HAVE_SYS_MMAN_H
#if defined(HAVE_SYS_MMAN_H) && !defined(__OS2__)
#define fluid_mlock(_p,_n) mlock(_p, _n)
#define fluid_munlock(_p,_n) munlock(_p,_n)
#else

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

@ -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 MIDI port name (alsa_seq, coremidi drivers)\n");
printf(" -o\n"
" Define a setting, -o name=value (\"-o help\" to dump current values)\n");
printf(" -R, --reverb\n"