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:
parent
1a7d0f796b
commit
dd0edf1f7c
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
@ -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));
|
||||
|
||||
|
@ -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
|
||||
|
@ -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; }
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user