updated fluidsynth to 1.0.8

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24454 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Jérôme Duval
2008-03-18 22:17:50 +00:00
parent a529aaf3c6
commit 5c102180bd
71 changed files with 4114 additions and 4125 deletions
+31 -34
View File
@@ -44,40 +44,37 @@ extern "C" {
#endif #endif
/** /**
* @file fluidsynth.h
\file fluidsynth.h * @brief FluidSynth is a real-time synthesizer designed for SoundFont(R) files.
*
\brief fluidsynth is a real-time SoundFont(R) synthesizer. This is * This is the header of the fluidsynth library and contains the
the header of the fluidsynth library and contains the * synthesizer's public API.
synthesizer's public API. *
* Depending on how you want to use or extend the synthesizer you
Depending on how you want to use or extend the synthesizer you * will need different API functions. You probably do not need all
will need different API functions. You probably do not need all * of them. Here is what you might want to do:
of them. Here is what you might want to do: *
* o Embedded synthesizer: create a new synthesizer and send MIDI
o Embedded synthesizer: create a new synthesizer and send MIDI * events to it. The sound goes directly to the audio output of
events to it. The sound goes directly to the audio output of * your system.
your system. *
* o Plugin synthesizer: create a synthesizer and send MIDI events
o Plugin synthesizer: create a synthesizer and send MIDI events * but pull the audio back into your application.
but pull the audio back into your application. *
* o SoundFont plugin: create a new type of "SoundFont" and allow
o SoundFont plugin: create a new type of "SoundFont" and allow * the synthesizer to load your type of SoundFonts.
the synthesizer to load your type of SoundFonts. *
* o MIDI input: Create a MIDI handler to read the MIDI input on your
o MIDI input: Create a MIDI handler to read the MIDI input on your * machine and send the MIDI events directly to the synthesizer.
machine and send the MIDI events directly to the synthesizer. *
* o MIDI files: Open MIDI files and send the MIDI events to the
o MIDI files: Open MIDI files and send the MIDI events to the * synthesizer.
synthesizer. *
* o Command lines: You can send textual commands to the synthesizer.
o Command lines: You can send textual commands to the synthesizer. *
* SoundFont(R) is a registered trademark of E-mu Systems, Inc.
*/
SoundFont(R) is a registered trademark of E-mu Systems, Inc.
*/
#include "fluidsynth/types.h" #include "fluidsynth/types.h"
#include "fluidsynth/settings.h" #include "fluidsynth/settings.h"
+22 -8
View File
@@ -25,15 +25,29 @@
extern "C" { extern "C" {
#endif #endif
/**
* @file audio.h
* @brief Functions for audio driver output.
*
* Defines functions for creating audio driver output. Use
* new_fluid_audio_driver() to create a new audio driver for a given synth
* and configuration settings. The function new_fluid_audio_driver2() can be
* used if custom audio processing is desired before the audio is sent to the
* audio driver (although it is not as efficient).
*/
/**
/** Audio driver * Callback function type used with new_fluid_audio_driver2() to allow for
* * custom user audio processing before the audio is sent to the driver. This
* * function is responsible for rendering the audio to the buffers.
*/ * @param data The user data parameter as passed to new_fluid_audio_driver2().
* @param len Length of the audio in frames.
* @param nin Count of buffers in 'in'
/** The function should return non-zero if an error occured. */ * @param in FIXME - Not used currently?
* @param nout Count of arrays in 'out' (i.e., channel count)
* @param out Output buffers, one for each channel
* @return Should return 0 on success, non-zero if an error occured.
*/
typedef int (*fluid_audio_func_t)(void* data, int len, typedef int (*fluid_audio_func_t)(void* data, int len,
int nin, float** in, int nin, float** in,
int nout, float** out); int nout, float** out);
+29 -20
View File
@@ -25,28 +25,37 @@
extern "C" { extern "C" {
#endif #endif
/**
* @file event.h
* @brief Sequencer event functions and defines.
*
* Functions and constants for creating/processing sequencer events.
*/
/**
* Sequencer event type enumeration.
*/
enum fluid_seq_event_type { enum fluid_seq_event_type {
FLUID_SEQ_NOTE = 0, FLUID_SEQ_NOTE = 0, /**< Note event (DOCME) */
FLUID_SEQ_NOTEON, FLUID_SEQ_NOTEON, /**< Note on event */
FLUID_SEQ_NOTEOFF, FLUID_SEQ_NOTEOFF, /**< Note off event */
FLUID_SEQ_ALLSOUNDSOFF, FLUID_SEQ_ALLSOUNDSOFF, /**< All sounds off event */
FLUID_SEQ_ALLNOTESOFF, FLUID_SEQ_ALLNOTESOFF, /**< All notes off event */
FLUID_SEQ_BANKSELECT, FLUID_SEQ_BANKSELECT, /**< Bank select message */
FLUID_SEQ_PROGRAMCHANGE, FLUID_SEQ_PROGRAMCHANGE, /**< Program change message */
FLUID_SEQ_PROGRAMSELECT, FLUID_SEQ_PROGRAMSELECT, /**< Program select message (DOCME) */
FLUID_SEQ_PITCHBEND, FLUID_SEQ_PITCHBEND, /**< Pitch bend message */
FLUID_SEQ_PITCHWHHELSENS, FLUID_SEQ_PITCHWHHELSENS, /**< Pitch wheel sensitivity set message */
FLUID_SEQ_MODULATION, FLUID_SEQ_MODULATION, /**< Modulation controller event */
FLUID_SEQ_SUSTAIN, FLUID_SEQ_SUSTAIN, /**< Sustain controller event */
FLUID_SEQ_CONTROLCHANGE, FLUID_SEQ_CONTROLCHANGE, /**< MIDI control change event */
FLUID_SEQ_PAN, FLUID_SEQ_PAN, /**< Stereo pan set event */
FLUID_SEQ_VOLUME, FLUID_SEQ_VOLUME, /**< Volume set event */
FLUID_SEQ_REVERBSEND, FLUID_SEQ_REVERBSEND, /**< Reverb send set event */
FLUID_SEQ_CHORUSSEND, FLUID_SEQ_CHORUSSEND, /**< Chorus send set event */
FLUID_SEQ_TIMER, FLUID_SEQ_TIMER, /**< Timer event (DOCME) */
FLUID_SEQ_ANYCONTROLCHANGE, // used for remove_events only FLUID_SEQ_ANYCONTROLCHANGE, /**< DOCME (used for remove_events only) */
FLUID_SEQ_LASTEVENT FLUID_SEQ_LASTEVENT /**< Defines the count of event enums */
}; };
/* Event alloc/free */ /* Event alloc/free */
+81 -75
View File
@@ -25,99 +25,105 @@
extern "C" { extern "C" {
#endif #endif
/**
* @file gen.h
* @brief Functions and defines for SoundFont generator effects.
*/
/** List of generator numbers /**
Soundfont 2.01 specifications section 8.1.3 */ * Generator (effect) numbers (Soundfont 2.01 specifications section 8.1.3)
*/
enum fluid_gen_type { enum fluid_gen_type {
GEN_STARTADDROFS, GEN_STARTADDROFS, /**< Sample start address offset (0-32767) */
GEN_ENDADDROFS, GEN_ENDADDROFS, /**< Sample end address offset (-32767-0) */
GEN_STARTLOOPADDROFS, GEN_STARTLOOPADDROFS, /**< Sample loop start address offset (-32767-32767) */
GEN_ENDLOOPADDROFS, GEN_ENDLOOPADDROFS, /**< Sample loop end address offset (-32767-32767) */
GEN_STARTADDRCOARSEOFS, GEN_STARTADDRCOARSEOFS, /**< Sample start address coarse offset (X 32768) */
GEN_MODLFOTOPITCH, GEN_MODLFOTOPITCH, /**< Modulation LFO to pitch */
GEN_VIBLFOTOPITCH, GEN_VIBLFOTOPITCH, /**< Vibrato LFO to pitch */
GEN_MODENVTOPITCH, GEN_MODENVTOPITCH, /**< Modulation envelope to pitch */
GEN_FILTERFC, GEN_FILTERFC, /**< Filter cutoff */
GEN_FILTERQ, GEN_FILTERQ, /**< Filter Q */
GEN_MODLFOTOFILTERFC, GEN_MODLFOTOFILTERFC, /**< Modulation LFO to filter cutoff */
GEN_MODENVTOFILTERFC, GEN_MODENVTOFILTERFC, /**< Modulation envelope to filter cutoff */
GEN_ENDADDRCOARSEOFS, GEN_ENDADDRCOARSEOFS, /**< Sample end address coarse offset (X 32768) */
GEN_MODLFOTOVOL, GEN_MODLFOTOVOL, /**< Modulation LFO to volume */
GEN_UNUSED1, GEN_UNUSED1, /**< Unused */
GEN_CHORUSSEND, GEN_CHORUSSEND, /**< Chorus send amount */
GEN_REVERBSEND, GEN_REVERBSEND, /**< Reverb send amount */
GEN_PAN, GEN_PAN, /**< Stereo panning */
GEN_UNUSED2, GEN_UNUSED2, /**< Unused */
GEN_UNUSED3, GEN_UNUSED3, /**< Unused */
GEN_UNUSED4, GEN_UNUSED4, /**< Unused */
GEN_MODLFODELAY, GEN_MODLFODELAY, /**< Modulation LFO delay */
GEN_MODLFOFREQ, GEN_MODLFOFREQ, /**< Modulation LFO frequency */
GEN_VIBLFODELAY, GEN_VIBLFODELAY, /**< Vibrato LFO delay */
GEN_VIBLFOFREQ, GEN_VIBLFOFREQ, /**< Vibrato LFO frequency */
GEN_MODENVDELAY, GEN_MODENVDELAY, /**< Modulation envelope delay */
GEN_MODENVATTACK, GEN_MODENVATTACK, /**< Modulation envelope attack */
GEN_MODENVHOLD, GEN_MODENVHOLD, /**< Modulation envelope hold */
GEN_MODENVDECAY, GEN_MODENVDECAY, /**< Modulation envelope decay */
GEN_MODENVSUSTAIN, GEN_MODENVSUSTAIN, /**< Modulation envelope sustain */
GEN_MODENVRELEASE, GEN_MODENVRELEASE, /**< Modulation envelope release */
GEN_KEYTOMODENVHOLD, GEN_KEYTOMODENVHOLD, /**< Key to modulation envelope hold */
GEN_KEYTOMODENVDECAY, GEN_KEYTOMODENVDECAY, /**< Key to modulation envelope decay */
GEN_VOLENVDELAY, GEN_VOLENVDELAY, /**< Volume envelope delay */
GEN_VOLENVATTACK, GEN_VOLENVATTACK, /**< Volume envelope attack */
GEN_VOLENVHOLD, GEN_VOLENVHOLD, /**< Volume envelope hold */
GEN_VOLENVDECAY, GEN_VOLENVDECAY, /**< Volume envelope decay */
GEN_VOLENVSUSTAIN, GEN_VOLENVSUSTAIN, /**< Volume envelope sustain */
GEN_VOLENVRELEASE, GEN_VOLENVRELEASE, /**< Volume envelope release */
GEN_KEYTOVOLENVHOLD, GEN_KEYTOVOLENVHOLD, /**< Key to volume envelope hold */
GEN_KEYTOVOLENVDECAY, GEN_KEYTOVOLENVDECAY, /**< Key to volume envelope decay */
GEN_INSTRUMENT, GEN_INSTRUMENT, /**< Instrument ID (shouldn't be set by user) */
GEN_RESERVED1, GEN_RESERVED1, /**< Reserved */
GEN_KEYRANGE, GEN_KEYRANGE, /**< MIDI note range */
GEN_VELRANGE, GEN_VELRANGE, /**< MIDI velocity range */
GEN_STARTLOOPADDRCOARSEOFS, GEN_STARTLOOPADDRCOARSEOFS, /**< Sample start loop address coarse offset (X 32768) */
GEN_KEYNUM, GEN_KEYNUM, /**< Fixed MIDI note number */
GEN_VELOCITY, GEN_VELOCITY, /**< Fixed MIDI velocity value */
GEN_ATTENUATION, GEN_ATTENUATION, /**< Initial volume attenuation */
GEN_RESERVED2, GEN_RESERVED2, /**< Reserved */
GEN_ENDLOOPADDRCOARSEOFS, GEN_ENDLOOPADDRCOARSEOFS, /**< Sample end loop address coarse offset (X 32768) */
GEN_COARSETUNE, GEN_COARSETUNE, /**< Coarse tuning */
GEN_FINETUNE, GEN_FINETUNE, /**< Fine tuning */
GEN_SAMPLEID, GEN_SAMPLEID, /**< Sample ID (shouldn't be set by user) */
GEN_SAMPLEMODE, GEN_SAMPLEMODE, /**< Sample mode flags */
GEN_RESERVED3, GEN_RESERVED3, /**< Reserved */
GEN_SCALETUNE, GEN_SCALETUNE, /**< Scale tuning */
GEN_EXCLUSIVECLASS, GEN_EXCLUSIVECLASS, /**< Exclusive class number */
GEN_OVERRIDEROOTKEY, GEN_OVERRIDEROOTKEY, /**< Sample root note override */
/* the initial pitch is not a "standard" generator. It is not /* the initial pitch is not a "standard" generator. It is not
* mentioned in the list of generator in the SF2 specifications. It * mentioned in the list of generator in the SF2 specifications. It
* is used, however, as the destination for the default pitch wheel * is used, however, as the destination for the default pitch wheel
* modulator. */ * modulator. */
GEN_PITCH, GEN_PITCH, /**< Pitch (NOTE: Not a real SoundFont generator) */
GEN_LAST GEN_LAST /**< Value defines the count of generators (#fluid_gen_type) */
}; };
/* /**
* fluid_gen_t * SoundFont generator structure.
* Sound font generator */
*/
typedef struct _fluid_gen_t typedef struct _fluid_gen_t
{ {
unsigned char flags; /* is it used or not */ unsigned char flags; /**< Is the generator set or not (#fluid_gen_flags) */
double val; /* The nominal value */ double val; /**< The nominal value */
double mod; /* Change by modulators */ double mod; /**< Change by modulators */
double nrpn; /* Change by NRPN messages */ double nrpn; /**< Change by NRPN messages */
} fluid_gen_t; } fluid_gen_t;
/**
* Enum value for 'flags' field of #_fluid_gen_t (not really flags).
*/
enum fluid_gen_flags enum fluid_gen_flags
{ {
GEN_UNUSED, GEN_UNUSED, /**< Generator value is not set */
GEN_SET, GEN_SET, /**< Generator value is set */
GEN_ABS_NRPN GEN_ABS_NRPN /**< DOCME */
}; };
/** Reset an array of generators to the SF2.01 default values */
FLUIDSYNTH_API int fluid_gen_set_default_values(fluid_gen_t* gen); FLUIDSYNTH_API int fluid_gen_set_default_values(fluid_gen_t* gen);
+34 -36
View File
@@ -27,57 +27,55 @@ extern "C" {
#endif #endif
/** /**
* * @file log.h
* Logging interface * @brief Logging interface
* *
* The default logging function of the fluidsynth prints its messages * The default logging function of the fluidsynth prints its messages
* to the stderr. The synthesizer uses four level of messages: FLUID_PANIC, * to the stderr. The synthesizer uses five level of messages: #FLUID_PANIC,
* ERR, WARN, and FLUID_DBG. They are commented in the definition below. * #FLUID_ERR, #FLUID_WARN, #FLUID_INFO, and #FLUID_DBG.
* *
* A client application can install a new log function to handle the * A client application can install a new log function to handle the
* messages differently. In the following example, the application * messages differently. In the following example, the application
* sets a callback function to display "FLUID_PANIC" messages in a dialog, * sets a callback function to display #FLUID_PANIC messages in a dialog,
* and ignores all other messages by setting the log function to * and ignores all other messages by setting the log function to
* NULL: * NULL:
* *
* ... * DOCME (formatting)
* fluid_set_log_function(FLUID_PANIC, show_dialog, (void*) root_window); * fluid_set_log_function(FLUID_PANIC, show_dialog, (void*) root_window);
* fluid_set_log_function(ERR, NULL, NULL); * fluid_set_log_function(FLUID_ERR, NULL, NULL);
* fluid_set_log_function(WARN, NULL, NULL); * fluid_set_log_function(FLUID_WARN, NULL, NULL);
* fluid_set_log_function(FLUID_DBG, NULL, NULL); * fluid_set_log_function(FLUID_DBG, NULL, NULL);
* ... */
*
*/
/**
* FluidSynth log levels.
*/
enum fluid_log_level { enum fluid_log_level {
FLUID_PANIC, /* the synth can't function correctly any more */ FLUID_PANIC, /**< The synth can't function correctly any more */
FLUID_ERR, /* the synth can function, but with serious limitation */ FLUID_ERR, /**< Serious error occurred */
FLUID_WARN, /* the synth might not function as expected */ FLUID_WARN, /**< Warning */
FLUID_INFO, /* verbose messages */ FLUID_INFO, /**< Verbose informational messages */
FLUID_DBG, /* debugging messages */ FLUID_DBG, /**< Debugging messages */
LAST_LOG_LEVEL LAST_LOG_LEVEL
}; };
/**
* Log function handler callback type used by fluid_set_log_function().
* @param level Log level (#fluid_log_level)
* @param message Log message text
* @param data User data pointer supplied to fluid_set_log_function().
*/
typedef void (*fluid_log_function_t)(int level, char* message, void* data); typedef void (*fluid_log_function_t)(int level, char* message, void* data);
/** fluid_set_log_function installs a new log function for the
* specified level. It returns the previously installed function.
*/
FLUIDSYNTH_API FLUIDSYNTH_API
fluid_log_function_t fluid_set_log_function(int level, fluid_log_function_t fun, void* data); fluid_log_function_t fluid_set_log_function(int level, fluid_log_function_t fun, void* data);
/** fluid_default_log_function is the fluid's default log function. It
* prints to the stderr. */
FLUIDSYNTH_API void fluid_default_log_function(int level, char* message, void* data); FLUIDSYNTH_API void fluid_default_log_function(int level, char* message, void* data);
/** print a message to the log */
FLUIDSYNTH_API int fluid_log(int level, char * fmt, ...); FLUIDSYNTH_API int fluid_log(int level, char * fmt, ...);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
+21 -37
View File
@@ -25,7 +25,10 @@
extern "C" { extern "C" {
#endif #endif
/**
* @file midi.h
* @brief Functions for MIDI events, drivers and MIDI file playback.
*/
FLUIDSYNTH_API fluid_midi_event_t* new_fluid_midi_event(void); FLUIDSYNTH_API fluid_midi_event_t* new_fluid_midi_event(void);
FLUIDSYNTH_API int delete_fluid_midi_event(fluid_midi_event_t* event); FLUIDSYNTH_API int delete_fluid_midi_event(fluid_midi_event_t* event);
@@ -48,58 +51,41 @@ FLUIDSYNTH_API int fluid_midi_event_get_pitch(fluid_midi_event_t* evt);
FLUIDSYNTH_API int fluid_midi_event_set_pitch(fluid_midi_event_t* evt, int val); FLUIDSYNTH_API int fluid_midi_event_set_pitch(fluid_midi_event_t* evt, int val);
/* Generic callback function for MIDI events. /**
* Will be used between * Generic callback function for MIDI events.
* - MIDI driver and MIDI router * @param data User defined data pointer
* - MIDI router and synth * @param event The MIDI event
* to communicate events. * @return DOCME
* In the not-so-far future... *
*/ * Will be used between
* - MIDI driver and MIDI router
* - MIDI router and synth
* to communicate events.
* In the not-so-far future...
*/
typedef int (*handle_midi_event_func_t)(void* data, fluid_midi_event_t* event); typedef int (*handle_midi_event_func_t)(void* data, fluid_midi_event_t* event);
/* /*
* * MIDI router
* MIDI router *
* * The MIDI handler forwards incoming MIDI events to the synthesizer
* The MIDI handler forwards incoming MIDI events to the synthesizer */
*
*/
/** Create a new midi router. A midi handler connects to a midi input
* device and forwards incoming midi events to the synthesizer.
*/
FLUIDSYNTH_API fluid_midi_router_t* new_fluid_midi_router(fluid_settings_t* settings, FLUIDSYNTH_API fluid_midi_router_t* new_fluid_midi_router(fluid_settings_t* settings,
handle_midi_event_func_t handler, handle_midi_event_func_t handler,
void* event_handler_data); void* event_handler_data);
/** Delete the midi router.
*
* \param handler a pointer to the midi handler
* \return 0 if no error occured, -1 otherwise
*/
FLUIDSYNTH_API int delete_fluid_midi_router(fluid_midi_router_t* handler); FLUIDSYNTH_API int delete_fluid_midi_router(fluid_midi_router_t* handler);
/** The standard handler function. Every MIDI event goes through
this. */
FLUIDSYNTH_API int fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event); FLUIDSYNTH_API int fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event);
/** An optional link in the MIDI chain to dump MIDI data between MIDI
driver and router */
FLUIDSYNTH_API int fluid_midi_dump_prerouter(void* data, fluid_midi_event_t* event); FLUIDSYNTH_API int fluid_midi_dump_prerouter(void* data, fluid_midi_event_t* event);
/** An optional link in the MIDI chain to dump MIDI data between MIDI
router and the synthesizer */
FLUIDSYNTH_API int fluid_midi_dump_postrouter(void* data, fluid_midi_event_t* event); FLUIDSYNTH_API int fluid_midi_dump_postrouter(void* data, fluid_midi_event_t* event);
/* /*
*
* MIDI driver * MIDI driver
* *
* The MIDI handler forwards incoming MIDI events to the synthesizer * The MIDI handler forwards incoming MIDI events to the synthesizer
*
*/ */
FLUIDSYNTH_API FLUIDSYNTH_API
fluid_midi_driver_t* new_fluid_midi_driver(fluid_settings_t* settings, fluid_midi_driver_t* new_fluid_midi_driver(fluid_settings_t* settings,
handle_midi_event_func_t handler, handle_midi_event_func_t handler,
@@ -110,11 +96,9 @@ FLUIDSYNTH_API void delete_fluid_midi_driver(fluid_midi_driver_t* driver);
/* /*
*
* MIDI file player * MIDI file player
* *
* The MIDI player allows you to play MIDI files with the FLUID Synth * The MIDI player allows you to play MIDI files with the FLUID Synth
*
*/ */
FLUIDSYNTH_API fluid_player_t* new_fluid_player(fluid_synth_t* synth); FLUIDSYNTH_API fluid_player_t* new_fluid_player(fluid_synth_t* synth);
+2 -2
View File
@@ -144,9 +144,9 @@ struct _fluid_sample_t
{ {
char name[21]; char name[21];
unsigned int start; unsigned int start;
unsigned int end; unsigned int end; /* Note: Index of last valid sample point (contrary to SF spec) */
unsigned int loopstart; unsigned int loopstart;
unsigned int loopend; unsigned int loopend; /* Note: first point following the loop (superimposed on loopstart) */
unsigned int samplerate; unsigned int samplerate;
int origpitch; int origpitch;
int pitchadj; int pitchadj;
+2 -2
View File
@@ -26,10 +26,10 @@
extern "C" { extern "C" {
#endif #endif
#define FLUIDSYNTH_VERSION "1.0.7" #define FLUIDSYNTH_VERSION "1.0.8"
#define FLUIDSYNTH_VERSION_MAJOR 1 #define FLUIDSYNTH_VERSION_MAJOR 1
#define FLUIDSYNTH_VERSION_MINOR 0 #define FLUIDSYNTH_VERSION_MINOR 0
#define FLUIDSYNTH_VERSION_MICRO 7 #define FLUIDSYNTH_VERSION_MICRO 8
FLUIDSYNTH_API void fluid_version(int *major, int *minor, int *micro); FLUIDSYNTH_API void fluid_version(int *major, int *minor, int *micro);
+11 -8
View File
@@ -6,10 +6,10 @@
[:Development:] [:Development:]
Many people contributed to FluidSynth, send suggestions or bug Many people contributed to FluidSynth, sent suggestions or bug
fixes. The project was started by Peter Hanappe who is the main fixes. The project was started by Peter Hanappe who is the main
author. Josh Green is the current maintainer. Below you'll find a author. Josh Green is the current maintainer. Below you'll find a
summery of contributions. summary of contributions.
* Peter Hanappe. Initiated the project. files: sticked his nose in all * Peter Hanappe. Initiated the project. files: sticked his nose in all
@@ -24,10 +24,6 @@ summery of contributions.
(the blue waves with FluidSynth letters partially submerged). (the blue waves with FluidSynth letters partially submerged).
files: iiwu_defsfont.{c,h}, iiwu_alsa{c,h} and others. files: iiwu_defsfont.{c,h}, iiwu_alsa{c,h} and others.
* Stephane Letz from Grame wrote most of the MidiShare driver, all of
the PortAudio driver, ported iiwusynth to MacOS X, and sent in many
fixes. files: iiwu_midishare.c, iiwu_portaudio.c
* Markus Nentwig (re-)designed the resonant filter, the chorus, the * Markus Nentwig (re-)designed the resonant filter, the chorus, the
LADSPA subsystem, the MIDI router, optimized for SSE, made many LADSPA subsystem, the MIDI router, optimized for SSE, made many
changes and bug fixes and got the synthesizer to actually work. Most changes and bug fixes and got the synthesizer to actually work. Most
@@ -36,6 +32,10 @@ summery of contributions.
iiwu_sse.h, iiwu_dsp_core.h, iiwu_rev.{c,h}, and basically all the iiwu_sse.h, iiwu_dsp_core.h, iiwu_rev.{c,h}, and basically all the
other files. other files.
* Stephane Letz from Grame wrote most of the MidiShare driver, all of
the PortAudio driver, ported iiwusynth to MacOS X, and sent in many
fixes. files: iiwu_midishare.c, iiwu_portaudio.c
* Antoine Schmitt added the sequencer support, support for sample * Antoine Schmitt added the sequencer support, support for sample
loading (RAM Sfont), developed the loading (RAM Sfont), developed the
MacroMedia Director Xtra, and send in many many bug reports. Thanks MacroMedia Director Xtra, and send in many many bug reports. Thanks
@@ -67,8 +67,7 @@ summery of contributions.
portability. portability.
* The midi device uses code from jMax's alsarawmidi.c file and from * The midi device uses code from jMax's alsarawmidi.c file and from
Smurf's midi_alsaraw.c by Josh Green. Josh also added support for Smurf's midi_alsaraw.c by Josh Green. file: iiwu_alsa.c
the alsa sequencer interface. file: iiwu_alsa.c
* The reverb algorithm was written by Jezar * The reverb algorithm was written by Jezar
(http://www.dreampoint.co.uk). His code is public domain. The code (http://www.dreampoint.co.uk). His code is public domain. The code
@@ -115,3 +114,7 @@ Gerald Pye
Rui Nuno Capela Rui Nuno Capela
Frieder Bürzele Frieder Bürzele
Henri Manson Henri Manson
Mihail Zenkov
Paul Millar
Nick Daly
David Hilvert
+1 -1
View File
@@ -14,6 +14,7 @@ SharedLibrary libfluidsynth.so :
fluid_cmd.c fluid_cmd.c
fluid_conv.c fluid_conv.c
fluid_defsfont.c fluid_defsfont.c
fluid_dsp_float.c
fluid_event.c fluid_event.c
fluid_gen.c fluid_gen.c
fluid_hash.c fluid_hash.c
@@ -28,7 +29,6 @@ SharedLibrary libfluidsynth.so :
fluid_seq.c fluid_seq.c
fluid_seqbind.c fluid_seqbind.c
fluid_settings.c fluid_settings.c
fluid_strtok.c
fluid_synth.c fluid_synth.c
fluid_sys.c fluid_sys.c
fluid_tuning.c fluid_tuning.c
+73 -44
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -25,12 +25,12 @@
* fluid_adriver_definition_t * fluid_adriver_definition_t
*/ */
typedef struct _fluid_audriver_definition_t typedef struct _fluid_audriver_definition_t
{ {
char* name; char* name;
fluid_audio_driver_t* (*new)(fluid_settings_t* settings, fluid_synth_t* synth); fluid_audio_driver_t* (*new)(fluid_settings_t* settings, fluid_synth_t* synth);
fluid_audio_driver_t* (*new2)(fluid_settings_t* settings, fluid_audio_driver_t* (*new2)(fluid_settings_t* settings,
fluid_audio_func_t func, fluid_audio_func_t func,
void* data); void* data);
int (*free)(fluid_audio_driver_t* driver); int (*free)(fluid_audio_driver_t* driver);
void (*settings)(fluid_settings_t* settings); void (*settings)(fluid_settings_t* settings);
@@ -48,57 +48,57 @@ void fluid_alsa_audio_driver_settings(fluid_settings_t* settings);
#endif #endif
#if OSS_SUPPORT #if OSS_SUPPORT
fluid_audio_driver_t* new_fluid_oss_audio_driver(fluid_settings_t* settings, fluid_audio_driver_t* new_fluid_oss_audio_driver(fluid_settings_t* settings,
fluid_synth_t* synth); fluid_synth_t* synth);
fluid_audio_driver_t* new_fluid_oss_audio_driver2(fluid_settings_t* settings, fluid_audio_driver_t* new_fluid_oss_audio_driver2(fluid_settings_t* settings,
fluid_audio_func_t func, void* data); fluid_audio_func_t func, void* data);
int delete_fluid_oss_audio_driver(fluid_audio_driver_t* p); int delete_fluid_oss_audio_driver(fluid_audio_driver_t* p);
void fluid_oss_audio_driver_settings(fluid_settings_t* settings); void fluid_oss_audio_driver_settings(fluid_settings_t* settings);
#endif #endif
#if COREAUDIO_SUPPORT #if COREAUDIO_SUPPORT
fluid_audio_driver_t* new_fluid_core_audio_driver(fluid_settings_t* settings, fluid_audio_driver_t* new_fluid_core_audio_driver(fluid_settings_t* settings,
fluid_synth_t* synth); fluid_synth_t* synth);
fluid_audio_driver_t* new_fluid_core_audio_driver2(fluid_settings_t* settings, fluid_audio_driver_t* new_fluid_core_audio_driver2(fluid_settings_t* settings,
fluid_audio_func_t func, fluid_audio_func_t func,
void* data); void* data);
int delete_fluid_core_audio_driver(fluid_audio_driver_t* p); int delete_fluid_core_audio_driver(fluid_audio_driver_t* p);
void fluid_core_audio_driver_settings(fluid_settings_t* settings); void fluid_core_audio_driver_settings(fluid_settings_t* settings);
#endif #endif
#if DSOUND_SUPPORT #if DSOUND_SUPPORT
fluid_audio_driver_t* new_fluid_dsound_audio_driver(fluid_settings_t* settings, fluid_audio_driver_t* new_fluid_dsound_audio_driver(fluid_settings_t* settings,
fluid_synth_t* synth); fluid_synth_t* synth);
int delete_fluid_dsound_audio_driver(fluid_audio_driver_t* p); int delete_fluid_dsound_audio_driver(fluid_audio_driver_t* p);
void fluid_dsound_audio_driver_settings(fluid_settings_t* settings); void fluid_dsound_audio_driver_settings(fluid_settings_t* settings);
#endif #endif
#if PORTAUDIO_SUPPORT #if PORTAUDIO_SUPPORT
fluid_audio_driver_t* new_fluid_portaudio_driver(fluid_settings_t* settings, fluid_audio_driver_t* new_fluid_portaudio_driver(fluid_settings_t* settings,
fluid_synth_t* synth); fluid_synth_t* synth);
int delete_fluid_portaudio_driver(fluid_audio_driver_t* p); int delete_fluid_portaudio_driver(fluid_audio_driver_t* p);
#endif #endif
#if JACK_SUPPORT #if JACK_SUPPORT
fluid_audio_driver_t* new_fluid_jack_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth); fluid_audio_driver_t* new_fluid_jack_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth);
fluid_audio_driver_t* new_fluid_jack_audio_driver2(fluid_settings_t* settings, fluid_audio_driver_t* new_fluid_jack_audio_driver2(fluid_settings_t* settings,
fluid_audio_func_t func, void* data); fluid_audio_func_t func, void* data);
int delete_fluid_jack_audio_driver(fluid_audio_driver_t* p); int delete_fluid_jack_audio_driver(fluid_audio_driver_t* p);
void fluid_jack_audio_driver_settings(fluid_settings_t* settings); void fluid_jack_audio_driver_settings(fluid_settings_t* settings);
#endif #endif
#if SNDMAN_SUPPORT #if SNDMAN_SUPPORT
fluid_audio_driver_t* new_fluid_sndmgr_audio_driver(fluid_settings_t* settings, fluid_audio_driver_t* new_fluid_sndmgr_audio_driver(fluid_settings_t* settings,
fluid_synth_t* synth); fluid_synth_t* synth);
fluid_audio_driver_t* new_fluid_sndmgr_audio_driver2(fluid_settings_t* settings, fluid_audio_driver_t* new_fluid_sndmgr_audio_driver2(fluid_settings_t* settings,
fluid_audio_func_t func, fluid_audio_func_t func,
void* data); void* data);
int delete_fluid_sndmgr_audio_driver(fluid_audio_driver_t* p); int delete_fluid_sndmgr_audio_driver(fluid_audio_driver_t* p);
#endif #endif
#define AUFILE_SUPPORT 1 #define AUFILE_SUPPORT 1
#if AUFILE_SUPPORT #if AUFILE_SUPPORT
fluid_audio_driver_t* new_fluid_file_audio_driver(fluid_settings_t* settings, fluid_audio_driver_t* new_fluid_file_audio_driver(fluid_settings_t* settings,
fluid_synth_t* synth); fluid_synth_t* synth);
int delete_fluid_file_audio_driver(fluid_audio_driver_t* p); int delete_fluid_file_audio_driver(fluid_audio_driver_t* p);
void fluid_file_audio_driver_settings(fluid_settings_t* settings); void fluid_file_audio_driver_settings(fluid_settings_t* settings);
@@ -106,10 +106,10 @@ void fluid_file_audio_driver_settings(fluid_settings_t* settings);
fluid_audriver_definition_t fluid_audio_drivers[] = { fluid_audriver_definition_t fluid_audio_drivers[] = {
#if OSS_SUPPORT #if OSS_SUPPORT
{ "oss", { "oss",
new_fluid_oss_audio_driver, new_fluid_oss_audio_driver,
new_fluid_oss_audio_driver2, new_fluid_oss_audio_driver2,
delete_fluid_oss_audio_driver, delete_fluid_oss_audio_driver,
fluid_oss_audio_driver_settings }, fluid_oss_audio_driver_settings },
#endif #endif
#if ALSA_SUPPORT #if ALSA_SUPPORT
@@ -120,45 +120,45 @@ fluid_audriver_definition_t fluid_audio_drivers[] = {
fluid_alsa_audio_driver_settings }, fluid_alsa_audio_driver_settings },
#endif #endif
#if COREAUDIO_SUPPORT #if COREAUDIO_SUPPORT
{ "coreaudio", { "coreaudio",
new_fluid_core_audio_driver, new_fluid_core_audio_driver,
new_fluid_core_audio_driver2, new_fluid_core_audio_driver2,
delete_fluid_core_audio_driver, delete_fluid_core_audio_driver,
fluid_core_audio_driver_settings }, fluid_core_audio_driver_settings },
#endif #endif
#if DSOUND_SUPPORT #if DSOUND_SUPPORT
{ "dsound", { "dsound",
new_fluid_dsound_audio_driver, new_fluid_dsound_audio_driver,
NULL, NULL,
delete_fluid_dsound_audio_driver, delete_fluid_dsound_audio_driver,
fluid_dsound_audio_driver_settings }, fluid_dsound_audio_driver_settings },
#endif #endif
#if PORTAUDIO_SUPPORT #if PORTAUDIO_SUPPORT
{ "portaudio", { "portaudio",
new_fluid_portaudio_driver, new_fluid_portaudio_driver,
NULL, NULL,
delete_fluid_portaudio_driver, delete_fluid_portaudio_driver,
NULL }, NULL },
#endif #endif
#if SNDMAN_SUPPORT #if SNDMAN_SUPPORT
{ "sndman", { "sndman",
new_fluid_sndmgr_audio_driver, new_fluid_sndmgr_audio_driver,
new_fluid_sndmgr_audio_driver2, new_fluid_sndmgr_audio_driver2,
delete_fluid_sndmgr_audio_driver, delete_fluid_sndmgr_audio_driver,
NULL }, NULL },
#endif #endif
#if JACK_SUPPORT #if JACK_SUPPORT
{ "jack", { "jack",
new_fluid_jack_audio_driver, new_fluid_jack_audio_driver,
new_fluid_jack_audio_driver2, new_fluid_jack_audio_driver2,
delete_fluid_jack_audio_driver, delete_fluid_jack_audio_driver,
fluid_jack_audio_driver_settings }, fluid_jack_audio_driver_settings },
#endif #endif
#if AUFILE_SUPPORT #if AUFILE_SUPPORT
{ "file", { "file",
new_fluid_file_audio_driver, new_fluid_file_audio_driver,
NULL, NULL,
delete_fluid_file_audio_driver, delete_fluid_file_audio_driver,
fluid_file_audio_driver_settings }, fluid_file_audio_driver_settings },
#endif #endif
{ NULL, NULL, NULL, NULL, NULL } { NULL, NULL, NULL, NULL, NULL }
@@ -241,11 +241,21 @@ void fluid_audio_driver_settings(fluid_settings_t* settings)
if (fluid_audio_drivers[i].settings != NULL) { if (fluid_audio_drivers[i].settings != NULL) {
fluid_audio_drivers[i].settings(settings); fluid_audio_drivers[i].settings(settings);
} }
} }
} }
fluid_audio_driver_t* /**
* Create a new audio driver.
* @param settings Configuration settings used to select and create the audio
* driver.
* @param synth Synthesizer instance for which the audio driver is created for.
* @return The new audio driver instance.
*
* Creates a new audio driver for a given 'synth' instance with a defined set
* of configuration 'settings'.
*/
fluid_audio_driver_t*
new_fluid_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth) new_fluid_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth)
{ {
int i; int i;
@@ -260,7 +270,7 @@ new_fluid_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth)
driver = (*fluid_audio_drivers[i].new)(settings, synth); driver = (*fluid_audio_drivers[i].new)(settings, synth);
if (driver) { if (driver) {
driver->name = fluid_audio_drivers[i].name; driver->name = fluid_audio_drivers[i].name;
} }
return driver; return driver;
} }
} }
@@ -269,7 +279,20 @@ new_fluid_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth)
return NULL; return NULL;
} }
fluid_audio_driver_t* /**
* Create a new audio driver.
* @param settings Configuration settings used to select and create the audio
* driver.
* @param func Function called to fill audio buffers for audio playback
* @param data User defined data pointer to pass to 'func'
* @return The new audio driver instance.
*
* Like new_fluid_audio_driver() but allows for custom audio processing before
* audio is sent to audio driver. It is the responsibility of the callback
* 'func' to render the audio into the buffers.
* NOTE: Not as efficient as new_fluid_audio_driver().
*/
fluid_audio_driver_t*
new_fluid_audio_driver2(fluid_settings_t* settings, fluid_audio_func_t func, void* data) new_fluid_audio_driver2(fluid_settings_t* settings, fluid_audio_func_t func, void* data)
{ {
int i; int i;
@@ -285,7 +308,7 @@ new_fluid_audio_driver2(fluid_settings_t* settings, fluid_audio_func_t func, voi
driver = (*fluid_audio_drivers[i].new2)(settings, func, data); driver = (*fluid_audio_drivers[i].new2)(settings, func, data);
if (driver) { if (driver) {
driver->name = fluid_audio_drivers[i].name; driver->name = fluid_audio_drivers[i].name;
} }
return driver; return driver;
} }
} }
@@ -294,7 +317,13 @@ new_fluid_audio_driver2(fluid_settings_t* settings, fluid_audio_func_t func, voi
return NULL; return NULL;
} }
void /**
* Deletes an audio driver instance.
* @param driver Audio driver instance to delete
*
* Shuts down an audio driver and deletes its instance.
*/
void
delete_fluid_audio_driver(fluid_audio_driver_t* driver) delete_fluid_audio_driver(fluid_audio_driver_t* driver)
{ {
int i; int i;
+2 -2
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -30,7 +30,7 @@ void fluid_audio_driver_settings(fluid_settings_t* settings);
* fluid_audio_driver_t * fluid_audio_driver_t
*/ */
struct _fluid_audio_driver_t struct _fluid_audio_driver_t
{ {
char* name; char* name;
}; };
+16 -37
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -20,7 +20,7 @@
/* fluid_aufile.c /* fluid_aufile.c
* *
* Audio driver, outputs the audio to a file (non real-time) * Audio driver, outputs the audio to a file (non real-time)
* *
*/ */
@@ -31,9 +31,9 @@
/** fluid_file_audio_driver_t /** fluid_file_audio_driver_t
* *
* This structure should not be accessed directly. Use audio port * This structure should not be accessed directly. Use audio port
* functions instead. * functions instead.
*/ */
typedef struct { typedef struct {
fluid_audio_driver_t driver; fluid_audio_driver_t driver;
@@ -70,7 +70,7 @@ void fluid_file_audio_driver_settings(fluid_settings_t* settings)
} }
fluid_audio_driver_t* fluid_audio_driver_t*
new_fluid_file_audio_driver(fluid_settings_t* settings, new_fluid_file_audio_driver(fluid_settings_t* settings,
fluid_synth_t* synth) fluid_synth_t* synth)
{ {
@@ -82,7 +82,7 @@ new_fluid_file_audio_driver(fluid_settings_t* settings,
dev = FLUID_NEW(fluid_file_audio_driver_t); dev = FLUID_NEW(fluid_file_audio_driver_t);
if (dev == NULL) { if (dev == NULL) {
FLUID_LOG(FLUID_ERR, "Out of memory"); FLUID_LOG(FLUID_ERR, "Out of memory");
return NULL; return NULL;
} }
FLUID_MEMSET(dev, 0, sizeof(fluid_file_audio_driver_t)); FLUID_MEMSET(dev, 0, sizeof(fluid_file_audio_driver_t));
@@ -125,7 +125,7 @@ new_fluid_file_audio_driver(fluid_settings_t* settings,
int delete_fluid_file_audio_driver(fluid_audio_driver_t* p) int delete_fluid_file_audio_driver(fluid_audio_driver_t* p)
{ {
fluid_file_audio_driver_t* dev = (fluid_file_audio_driver_t*) p; fluid_file_audio_driver_t* dev = (fluid_file_audio_driver_t*) p;
if (dev == NULL) { if (dev == NULL) {
return FLUID_OK; return FLUID_OK;
} }
@@ -157,48 +157,27 @@ int delete_fluid_file_audio_driver(fluid_audio_driver_t* p)
static int fluid_file_audio_run_s16(void* d, unsigned int clock_time) static int fluid_file_audio_run_s16(void* d, unsigned int clock_time)
{ {
fluid_file_audio_driver_t* dev = (fluid_file_audio_driver_t*) d; fluid_file_audio_driver_t* dev = (fluid_file_audio_driver_t*) d;
float* handle[2]; int n, offset;
int i, k, n, offset;
float s;
unsigned int sample_time; unsigned int sample_time;
handle[0] = dev->left;
handle[1] = dev->right;
sample_time = (unsigned int) (dev->samples / dev->sample_rate * 1000.0); sample_time = (unsigned int) (dev->samples / dev->sample_rate * 1000.0);
if (sample_time > clock_time) { if (sample_time > clock_time) {
return 1; return 1;
} }
(*dev->callback)(dev->data, dev->period_size, 0, NULL, 2, handle); fluid_synth_write_s16(dev->data, dev->period_size, dev->buf, 0, 2, dev->buf, 1, 2);
for (i = 0, k = 0; i < dev->period_size; i++, k += 2) {
s = 32768.0f * dev->left[i];
fluid_clip(s, -32768.0f, 32767.0f);
dev->buf[k] = (short) s;
}
for (i = 0, k = 1; i < dev->period_size; i++, k += 2) {
s = 32768.0f * dev->right[i];
fluid_clip(s, -32768.0f, 32767.0f);
dev->buf[k] = (short) s;
}
for (offset = 0; offset < dev->buf_size; offset += n) { for (offset = 0; offset < dev->buf_size; offset += n) {
n = fwrite((char*) dev->buf + offset, 1, dev->buf_size - offset, dev->file); n = fwrite((char*) dev->buf + offset, 1, dev->buf_size - offset, dev->file);
if (n < 0) { if (n < 0) {
FLUID_LOG(FLUID_ERR, "Audio file error"); FLUID_LOG(FLUID_ERR, "Audio output file write error: %s",
return 0; strerror (errno));
} return 0;
}
} }
dev->samples += dev->period_size; dev->samples += dev->period_size;
return 1; return 1;
error_recovery:
return 0;
} }
+43 -37
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -28,7 +28,7 @@
/* /*
* new_fluid_channel * new_fluid_channel
*/ */
fluid_channel_t* fluid_channel_t*
new_fluid_channel(fluid_synth_t* synth, int num) new_fluid_channel(fluid_synth_t* synth, int num)
{ {
fluid_channel_t* chan; fluid_channel_t* chan;
@@ -41,6 +41,7 @@ new_fluid_channel(fluid_synth_t* synth, int num)
chan->synth = synth; chan->synth = synth;
chan->channum = num; chan->channum = num;
chan->preset = NULL;
fluid_channel_init(chan); fluid_channel_init(chan);
fluid_channel_init_ctrl(chan); fluid_channel_init_ctrl(chan);
@@ -48,19 +49,22 @@ new_fluid_channel(fluid_synth_t* synth, int num)
return chan; return chan;
} }
void void
fluid_channel_init(fluid_channel_t* chan) fluid_channel_init(fluid_channel_t* chan)
{ {
chan->prognum = (chan->channum == 9)? 0 : chan->channum; chan->prognum = (chan->channum == 9)? 0 : chan->channum;
chan->banknum = (chan->channum == 9)? 128 : 0; chan->banknum = (chan->channum == 9)? 128 : 0;
chan->sfontnum = 0; chan->sfontnum = 0;
if (chan->preset) delete_fluid_preset (chan->preset);
chan->preset = fluid_synth_find_preset(chan->synth, chan->banknum, chan->prognum); chan->preset = fluid_synth_find_preset(chan->synth, chan->banknum, chan->prognum);
chan->interp_method = FLUID_INTERP_DEFAULT; chan->interp_method = FLUID_INTERP_DEFAULT;
chan->tuning = NULL; chan->tuning = NULL;
chan->nrpn_select = 0; chan->nrpn_select = 0;
} }
void void
fluid_channel_init_ctrl(fluid_channel_t* chan) fluid_channel_init_ctrl(fluid_channel_t* chan)
{ {
int i; int i;
@@ -79,21 +83,21 @@ fluid_channel_init_ctrl(fluid_channel_t* chan)
for (i = 0; i < 128; i++) { for (i = 0; i < 128; i++) {
SETCC(chan, i, 0); SETCC(chan, i, 0);
} }
/* Volume / initial attenuation (MSB & LSB) */ /* Volume / initial attenuation (MSB & LSB) */
SETCC(chan, 7, 127); SETCC(chan, 7, 127);
SETCC(chan, 39, 0); SETCC(chan, 39, 0);
/* Pan (MSB & LSB) */ /* Pan (MSB & LSB) */
SETCC(chan, 10, 64); SETCC(chan, 10, 64);
SETCC(chan, 10, 64); SETCC(chan, 10, 64);
/* Expression (MSB & LSB) */ /* Expression (MSB & LSB) */
SETCC(chan, 11, 127); SETCC(chan, 11, 127);
SETCC(chan, 43, 127); SETCC(chan, 43, 127);
} }
void void
fluid_channel_reset(fluid_channel_t* chan) fluid_channel_reset(fluid_channel_t* chan)
{ {
fluid_channel_init(chan); fluid_channel_init(chan);
@@ -103,9 +107,10 @@ fluid_channel_reset(fluid_channel_t* chan)
/* /*
* delete_fluid_channel * delete_fluid_channel
*/ */
int int
delete_fluid_channel(fluid_channel_t* chan) delete_fluid_channel(fluid_channel_t* chan)
{ {
if (chan->preset) delete_fluid_preset (chan->preset);
FLUID_FREE(chan); FLUID_FREE(chan);
return FLUID_OK; return FLUID_OK;
} }
@@ -113,12 +118,13 @@ delete_fluid_channel(fluid_channel_t* chan)
/* /*
* fluid_channel_set_preset * fluid_channel_set_preset
*/ */
int int
fluid_channel_set_preset(fluid_channel_t* chan, fluid_preset_t* preset) fluid_channel_set_preset(fluid_channel_t* chan, fluid_preset_t* preset)
{ {
fluid_preset_notify(chan->preset, FLUID_PRESET_UNSELECTED, chan->channum); fluid_preset_notify(chan->preset, FLUID_PRESET_UNSELECTED, chan->channum);
fluid_preset_notify(preset, FLUID_PRESET_SELECTED, chan->channum); fluid_preset_notify(preset, FLUID_PRESET_SELECTED, chan->channum);
if (chan->preset) delete_fluid_preset (chan->preset);
chan->preset = preset; chan->preset = preset;
return FLUID_OK; return FLUID_OK;
} }
@@ -126,7 +132,7 @@ fluid_channel_set_preset(fluid_channel_t* chan, fluid_preset_t* preset)
/* /*
* fluid_channel_get_preset * fluid_channel_get_preset
*/ */
fluid_preset_t* fluid_preset_t*
fluid_channel_get_preset(fluid_channel_t* chan) fluid_channel_get_preset(fluid_channel_t* chan)
{ {
return chan->preset; return chan->preset;
@@ -135,7 +141,7 @@ fluid_channel_get_preset(fluid_channel_t* chan)
/* /*
* fluid_channel_get_banknum * fluid_channel_get_banknum
*/ */
unsigned int unsigned int
fluid_channel_get_banknum(fluid_channel_t* chan) fluid_channel_get_banknum(fluid_channel_t* chan)
{ {
return chan->banknum; return chan->banknum;
@@ -144,7 +150,7 @@ fluid_channel_get_banknum(fluid_channel_t* chan)
/* /*
* fluid_channel_set_prognum * fluid_channel_set_prognum
*/ */
int int
fluid_channel_set_prognum(fluid_channel_t* chan, int prognum) fluid_channel_set_prognum(fluid_channel_t* chan, int prognum)
{ {
chan->prognum = prognum; chan->prognum = prognum;
@@ -154,7 +160,7 @@ fluid_channel_set_prognum(fluid_channel_t* chan, int prognum)
/* /*
* fluid_channel_get_prognum * fluid_channel_get_prognum
*/ */
int int
fluid_channel_get_prognum(fluid_channel_t* chan) fluid_channel_get_prognum(fluid_channel_t* chan)
{ {
return chan->prognum; return chan->prognum;
@@ -163,7 +169,7 @@ fluid_channel_get_prognum(fluid_channel_t* chan)
/* /*
* fluid_channel_set_banknum * fluid_channel_set_banknum
*/ */
int int
fluid_channel_set_banknum(fluid_channel_t* chan, unsigned int banknum) fluid_channel_set_banknum(fluid_channel_t* chan, unsigned int banknum)
{ {
chan->banknum = banknum; chan->banknum = banknum;
@@ -173,14 +179,14 @@ fluid_channel_set_banknum(fluid_channel_t* chan, unsigned int banknum)
/* /*
* fluid_channel_cc * fluid_channel_cc
*/ */
int int
fluid_channel_cc(fluid_channel_t* chan, int num, int value) fluid_channel_cc(fluid_channel_t* chan, int num, int value)
{ {
chan->cc[num] = value; chan->cc[num] = value;
switch (num) { switch (num) {
case SUSTAIN_SWITCH: case SUSTAIN_SWITCH:
{ {
if (value < 64) { if (value < 64) {
/* printf("** sustain off\n"); */ /* printf("** sustain off\n"); */
@@ -190,7 +196,7 @@ fluid_channel_cc(fluid_channel_t* chan, int num, int value)
} }
} }
break; break;
case BANK_SELECT_MSB: case BANK_SELECT_MSB:
{ {
chan->bank_msb = (unsigned char) (value & 0x7f); chan->bank_msb = (unsigned char) (value & 0x7f);
@@ -207,17 +213,17 @@ fluid_channel_cc(fluid_channel_t* chan, int num, int value)
fluid_channel_set_banknum(chan, (unsigned int)(value & 0x7f)); /* KLE */ fluid_channel_set_banknum(chan, (unsigned int)(value & 0x7f)); /* KLE */
} }
break; break;
case BANK_SELECT_LSB: case BANK_SELECT_LSB:
{ {
/* FIXME: according to the Downloadable Sounds II specification, /* FIXME: according to the Downloadable Sounds II specification,
bit 31 should be set when we receive the message on channel bit 31 should be set when we receive the message on channel
10 (drum channel) */ 10 (drum channel) */
fluid_channel_set_banknum(chan, (((unsigned int) value & 0x7f) fluid_channel_set_banknum(chan, (((unsigned int) value & 0x7f)
+ ((unsigned int) chan->bank_msb << 7))); + ((unsigned int) chan->bank_msb << 7)));
} }
break; break;
case ALL_NOTES_OFF: case ALL_NOTES_OFF:
fluid_synth_all_notes_off(chan->synth, chan->channum); fluid_synth_all_notes_off(chan->synth, chan->channum);
break; break;
@@ -231,7 +237,7 @@ fluid_channel_cc(fluid_channel_t* chan, int num, int value)
fluid_synth_modulate_voices_all(chan->synth, chan->channum); fluid_synth_modulate_voices_all(chan->synth, chan->channum);
break; break;
case DATA_ENTRY_MSB: case DATA_ENTRY_MSB:
{ {
int data = (value << 7) + chan->cc[DATA_ENTRY_LSB]; int data = (value << 7) + chan->cc[DATA_ENTRY_LSB];
@@ -239,7 +245,7 @@ fluid_channel_cc(fluid_channel_t* chan, int num, int value)
if ((chan->cc[NRPN_MSB] == 120) && (chan->cc[NRPN_LSB] < 100)) { if ((chan->cc[NRPN_MSB] == 120) && (chan->cc[NRPN_LSB] < 100)) {
float val = fluid_gen_scale_nrpn(chan->nrpn_select, data); 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_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); fluid_synth_set_gen(chan->synth, chan->channum, chan->nrpn_select, val);
} }
break; break;
} }
@@ -262,7 +268,7 @@ fluid_channel_cc(fluid_channel_t* chan, int num, int value)
chan->nrpn_select += value; chan->nrpn_select += value;
FLUID_LOG(FLUID_WARN, "%s: %d: NRPN Select = %d", __FILE__, __LINE__, chan->nrpn_select); FLUID_LOG(FLUID_WARN, "%s: %d: NRPN Select = %d", __FILE__, __LINE__, chan->nrpn_select);
} }
} }
break; break;
case RPN_MSB: case RPN_MSB:
@@ -278,14 +284,14 @@ fluid_channel_cc(fluid_channel_t* chan, int num, int value)
default: default:
fluid_synth_modulate_voices(chan->synth, chan->channum, 1, num); fluid_synth_modulate_voices(chan->synth, chan->channum, 1, num);
} }
return FLUID_OK; return FLUID_OK;
} }
/* /*
* fluid_channel_get_cc * fluid_channel_get_cc
*/ */
int int
fluid_channel_get_cc(fluid_channel_t* chan, int num) fluid_channel_get_cc(fluid_channel_t* chan, int num)
{ {
return ((num >= 0) && (num < 128))? chan->cc[num] : 0; return ((num >= 0) && (num < 128))? chan->cc[num] : 0;
@@ -294,7 +300,7 @@ fluid_channel_get_cc(fluid_channel_t* chan, int num)
/* /*
* fluid_channel_pitch_bend * fluid_channel_pitch_bend
*/ */
int int
fluid_channel_pitch_bend(fluid_channel_t* chan, int val) fluid_channel_pitch_bend(fluid_channel_t* chan, int val)
{ {
chan->pitch_bend = val; chan->pitch_bend = val;
@@ -305,7 +311,7 @@ fluid_channel_pitch_bend(fluid_channel_t* chan, int val)
/* /*
* fluid_channel_pitch_wheel_sens * fluid_channel_pitch_wheel_sens
*/ */
int int
fluid_channel_pitch_wheel_sens(fluid_channel_t* chan, int val) fluid_channel_pitch_wheel_sens(fluid_channel_t* chan, int val)
{ {
chan->pitch_wheel_sensitivity = val; chan->pitch_wheel_sensitivity = val;
@@ -316,7 +322,7 @@ fluid_channel_pitch_wheel_sens(fluid_channel_t* chan, int val)
/* /*
* fluid_channel_get_num * fluid_channel_get_num
*/ */
int int
fluid_channel_get_num(fluid_channel_t* chan) fluid_channel_get_num(fluid_channel_t* chan)
{ {
return chan->channum; return chan->channum;
@@ -324,7 +330,7 @@ fluid_channel_get_num(fluid_channel_t* chan)
/* Purpose: /* Purpose:
* Sets the index of the interpolation method used on this channel, * Sets the index of the interpolation method used on this channel,
* as in fluid_interp in fluidsynth.h * as in fluid_interp in fluidsynth.h
*/ */
void fluid_channel_set_interp_method(fluid_channel_t* chan, int new_method) void fluid_channel_set_interp_method(fluid_channel_t* chan, int new_method)
{ {
@@ -333,7 +339,7 @@ void fluid_channel_set_interp_method(fluid_channel_t* chan, int new_method)
/* Purpose: /* Purpose:
* Returns the index of the interpolation method used on this channel, * Returns the index of the interpolation method used on this channel,
* as in fluid_interp in fluidsynth.h * as in fluid_interp in fluidsynth.h
*/ */
int fluid_channel_get_interp_method(fluid_channel_t* chan) int fluid_channel_get_interp_method(fluid_channel_t* chan)
{ {
+2 -2
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -64,7 +64,7 @@ struct _fluid_channel_t
* generators set in the SoundFont. For example, if the NRPN * generators set in the SoundFont. For example, if the NRPN
* specifies an attack of 100 msec then 100 msec will be added to the * specifies an attack of 100 msec then 100 msec will be added to the
* combined attack time of the sound font and the modulators. * combined attack time of the sound font and the modulators.
* *
* However, it is useful to be able to specify the generator value * However, it is useful to be able to specify the generator value
* absolutely, completely ignoring the generators of the sound font * absolutely, completely ignoring the generators of the sound font
* and the values of modulators. The gen_abs field, is a boolean * and the values of modulators. The gen_abs field, is a boolean
+61 -60
View File
@@ -2,8 +2,8 @@
* August 24, 1998 * August 24, 1998
* Copyright (C) 1998 Juergen Mueller And Sundry Contributors * Copyright (C) 1998 Juergen Mueller And Sundry Contributors
* This source code is freely redistributable and may be used for * This source code is freely redistributable and may be used for
* any purpose. This copyright notice must be maintained. * any purpose. This copyright notice must be maintained.
* Juergen Mueller And Sundry Contributors are not responsible for * Juergen Mueller And Sundry Contributors are not responsible for
* the consequences of using this software. * the consequences of using this software.
*/ */
@@ -12,7 +12,7 @@
CHANGES CHANGES
- Adapted for fluidsynth, Peter Hanappe, March 2002 - Adapted for fluidsynth, Peter Hanappe, March 2002
- Variable delay line implementation using bandlimited - Variable delay line implementation using bandlimited
interpolation, code reorganization: Markus Nentwig May 2002 interpolation, code reorganization: Markus Nentwig May 2002
@@ -21,7 +21,7 @@
/* /*
* Chorus effect. * Chorus effect.
* *
* Flow diagram scheme for n delays ( 1 <= n <= MAX_CHORUS ): * Flow diagram scheme for n delays ( 1 <= n <= MAX_CHORUS ):
* *
* * gain-in ___ * * gain-in ___
@@ -40,7 +40,7 @@
* +---->| delay n |----------------------------->| | * +---->| delay n |----------------------------->| |
* |_________| | | * |_________| | |
* /|\ |___| * /|\ |___|
* | | * | |
* +-----------------+ +--------------+ | * gain-out * +-----------------+ +--------------+ | * gain-out
* | Delay control n |<--| mod. speed n | | * | Delay control n |<--| mod. speed n | |
* +-----------------+ +--------------+ +----->obuff * +-----------------+ +--------------+ +----->obuff
@@ -74,10 +74,10 @@
#define MIN_SPEED_HZ 0.29 #define MIN_SPEED_HZ 0.29
#define MAX_SPEED_HZ 5 #define MAX_SPEED_HZ 5
/* Length of one delay line in samples: /* Length of one delay line in samples:
* Set through MAX_SAMPLES_LN2. * Set through MAX_SAMPLES_LN2.
* For example: * For example:
* MAX_SAMPLES_LN2=12 * MAX_SAMPLES_LN2=12
* => MAX_SAMPLES=pow(2,12)=4096 * => MAX_SAMPLES=pow(2,12)=4096
* => MAX_SAMPLES_ANDMASK=4095 * => MAX_SAMPLES_ANDMASK=4095
*/ */
@@ -89,7 +89,7 @@
/* Interpolate how many steps between samples? Must be power of two /* Interpolate how many steps between samples? Must be power of two
For example: 8 => use a resolution of 256 steps between any two For example: 8 => use a resolution of 256 steps between any two
samples samples
*/ */
#define INTERPOLATION_SUBSAMPLES_LN2 8 #define INTERPOLATION_SUBSAMPLES_LN2 8
#define INTERPOLATION_SUBSAMPLES (1 << (INTERPOLATION_SUBSAMPLES_LN2-1)) #define INTERPOLATION_SUBSAMPLES (1 << (INTERPOLATION_SUBSAMPLES_LN2-1))
@@ -98,13 +98,13 @@
/* Use how many samples for interpolation? Must be odd. '7' sounds /* Use how many samples for interpolation? Must be odd. '7' sounds
relatively clean, when listening to the modulated delay signal relatively clean, when listening to the modulated delay signal
alone. For a demo on aliasing try '1' With '3', the aliasing is alone. For a demo on aliasing try '1' With '3', the aliasing is
still quite pronounced for some input frequencies still quite pronounced for some input frequencies
*/ */
#define INTERPOLATION_SAMPLES 5 #define INTERPOLATION_SAMPLES 5
/* Private data for SKEL file */ /* Private data for SKEL file */
struct _fluid_chorus_t { struct _fluid_chorus_t {
/* Store the values between fluid_chorus_set_xxx and fluid_chorus_update /* Store the values between fluid_chorus_set_xxx and fluid_chorus_update
* Logic behind this: * Logic behind this:
* - both 'parameter' and 'new_parameter' hold the same value. * - both 'parameter' and 'new_parameter' hold the same value.
* - To change the chorus settings, 'new_parameter' is modified and * - To change the chorus settings, 'new_parameter' is modified and
@@ -124,7 +124,7 @@ struct _fluid_chorus_t {
int new_number_blocks; /* next value, if parameter check is OK */ int new_number_blocks; /* next value, if parameter check is OK */
fluid_real_t *chorusbuf; fluid_real_t *chorusbuf;
int counter; int counter;
long phase[MAX_CHORUS]; long phase[MAX_CHORUS];
long modulation_period_samples; long modulation_period_samples;
int *lookup_tab; int *lookup_tab;
@@ -137,12 +137,12 @@ struct _fluid_chorus_t {
void fluid_chorus_triangle(int *buf, int len, int depth); void fluid_chorus_triangle(int *buf, int len, int depth);
void fluid_chorus_sine(int *buf, int len, int depth); void fluid_chorus_sine(int *buf, int len, int depth);
fluid_chorus_t* fluid_chorus_t*
new_fluid_chorus(fluid_real_t sample_rate) new_fluid_chorus(fluid_real_t sample_rate)
{ {
int i; int ii; int i; int ii;
fluid_chorus_t* chorus; fluid_chorus_t* chorus;
chorus = FLUID_NEW(fluid_chorus_t); chorus = FLUID_NEW(fluid_chorus_t);
if (chorus == NULL) { if (chorus == NULL) {
fluid_log(FLUID_PANIC, "chorus: Out of memory"); fluid_log(FLUID_PANIC, "chorus: Out of memory");
@@ -157,7 +157,7 @@ new_fluid_chorus(fluid_real_t sample_rate)
/* i: Offset in terms of whole samples */ /* i: Offset in terms of whole samples */
for (i = 0; i < INTERPOLATION_SAMPLES; i++){ for (i = 0; i < INTERPOLATION_SAMPLES; i++){
/* ii: Offset in terms of fractional samples ('subsamples') */ /* ii: Offset in terms of fractional samples ('subsamples') */
for (ii = 0; ii < INTERPOLATION_SUBSAMPLES; ii++){ for (ii = 0; ii < INTERPOLATION_SUBSAMPLES; ii++){
/* Move the origin into the center of the table */ /* Move the origin into the center of the table */
@@ -182,7 +182,7 @@ new_fluid_chorus(fluid_real_t sample_rate)
fluid_log(FLUID_PANIC, "chorus: Out of memory"); fluid_log(FLUID_PANIC, "chorus: Out of memory");
goto error_recovery; goto error_recovery;
} }
/* allocate sample buffer */ /* allocate sample buffer */
chorus->chorusbuf = FLUID_ARRAY(fluid_real_t, MAX_SAMPLES); chorus->chorusbuf = FLUID_ARRAY(fluid_real_t, MAX_SAMPLES);
@@ -194,7 +194,7 @@ new_fluid_chorus(fluid_real_t sample_rate)
if (fluid_chorus_init(chorus) != FLUID_OK){ if (fluid_chorus_init(chorus) != FLUID_OK){
goto error_recovery; goto error_recovery;
}; };
return chorus; return chorus;
error_recovery: error_recovery:
@@ -203,7 +203,7 @@ new_fluid_chorus(fluid_real_t sample_rate)
} }
int int
fluid_chorus_init(fluid_chorus_t* chorus) fluid_chorus_init(fluid_chorus_t* chorus)
{ {
int i; int i;
@@ -306,7 +306,7 @@ int fluid_chorus_get_type(fluid_chorus_t* chorus)
return chorus->type; return chorus->type;
}; };
void void
delete_fluid_chorus(fluid_chorus_t* chorus) delete_fluid_chorus(fluid_chorus_t* chorus)
{ {
if (chorus == NULL) { if (chorus == NULL) {
@@ -320,7 +320,7 @@ delete_fluid_chorus(fluid_chorus_t* chorus)
if (chorus->lookup_tab != NULL) { if (chorus->lookup_tab != NULL) {
FLUID_FREE(chorus->lookup_tab); FLUID_FREE(chorus->lookup_tab);
} }
FLUID_FREE(chorus); FLUID_FREE(chorus);
} }
@@ -328,12 +328,12 @@ delete_fluid_chorus(fluid_chorus_t* chorus)
/* Purpose: /* Purpose:
* Calculates the internal chorus parameters using the settings from * Calculates the internal chorus parameters using the settings from
* fluid_chorus_set_xxx. */ * fluid_chorus_set_xxx. */
int int
fluid_chorus_update(fluid_chorus_t* chorus) fluid_chorus_update(fluid_chorus_t* chorus)
{ {
int i; int i;
int modulation_depth_samples; int modulation_depth_samples;
if (chorus->new_number_blocks < 0) { if (chorus->new_number_blocks < 0) {
fluid_log(FLUID_WARN, "chorus: number blocks must be >=0! Setting value to 0."); fluid_log(FLUID_WARN, "chorus: number blocks must be >=0! Setting value to 0.");
chorus->new_number_blocks = 0; chorus->new_number_blocks = 0;
@@ -342,13 +342,13 @@ fluid_chorus_update(fluid_chorus_t* chorus)
MAX_CHORUS); MAX_CHORUS);
chorus->new_number_blocks = MAX_CHORUS; chorus->new_number_blocks = MAX_CHORUS;
}; };
if (chorus->new_speed_Hz < MIN_SPEED_HZ) { if (chorus->new_speed_Hz < MIN_SPEED_HZ) {
fluid_log(FLUID_WARN, "chorus: speed is too low (min %f)! Setting value to min.", fluid_log(FLUID_WARN, "chorus: speed is too low (min %f)! Setting value to min.",
(double) MIN_SPEED_HZ); (double) MIN_SPEED_HZ);
chorus->new_speed_Hz = MIN_SPEED_HZ; chorus->new_speed_Hz = MIN_SPEED_HZ;
} else if (chorus->new_speed_Hz > MAX_SPEED_HZ) { } else if (chorus->new_speed_Hz > MAX_SPEED_HZ) {
fluid_log(FLUID_WARN, "chorus: speed must be below %f Hz! Setting value to max.", fluid_log(FLUID_WARN, "chorus: speed must be below %f Hz! Setting value to max.",
(double) MAX_SPEED_HZ); (double) MAX_SPEED_HZ);
chorus->new_speed_Hz = MAX_SPEED_HZ; chorus->new_speed_Hz = MAX_SPEED_HZ;
} }
@@ -357,7 +357,7 @@ fluid_chorus_update(fluid_chorus_t* chorus)
chorus->new_depth_ms = 0.0; chorus->new_depth_ms = 0.0;
} }
/* Depth: Check for too high value through modulation_depth_samples. */ /* Depth: Check for too high value through modulation_depth_samples. */
if (chorus->new_level < 0.0) { if (chorus->new_level < 0.0) {
fluid_log(FLUID_WARN, "chorus: level must be positive! Setting value to 0."); fluid_log(FLUID_WARN, "chorus: level must be positive! Setting value to 0.");
chorus->new_level = 0.0; chorus->new_level = 0.0;
@@ -366,40 +366,40 @@ fluid_chorus_update(fluid_chorus_t* chorus)
"Setting it to 0.1."); "Setting it to 0.1.");
chorus->new_level = 0.1; chorus->new_level = 0.1;
} }
/* The modulating LFO goes through a full period every x samples: */ /* The modulating LFO goes through a full period every x samples: */
chorus->modulation_period_samples = chorus->sample_rate / chorus->new_speed_Hz; chorus->modulation_period_samples = chorus->sample_rate / chorus->new_speed_Hz;
/* The variation in delay time is x: */ /* The variation in delay time is x: */
modulation_depth_samples = (int) modulation_depth_samples = (int)
(chorus->new_depth_ms / 1000.0 /* convert modulation depth in ms to s*/ (chorus->new_depth_ms / 1000.0 /* convert modulation depth in ms to s*/
* chorus->sample_rate); * chorus->sample_rate);
if (modulation_depth_samples > MAX_SAMPLES) { if (modulation_depth_samples > MAX_SAMPLES) {
fluid_log(FLUID_WARN, "chorus: Too high depth. Setting it to max (%d).", MAX_SAMPLES); fluid_log(FLUID_WARN, "chorus: Too high depth. Setting it to max (%d).", MAX_SAMPLES);
modulation_depth_samples = MAX_SAMPLES; modulation_depth_samples = MAX_SAMPLES;
} }
/* initialize LFO table */ /* initialize LFO table */
if (chorus->type == FLUID_CHORUS_MOD_SINE) { if (chorus->type == FLUID_CHORUS_MOD_SINE) {
fluid_chorus_sine(chorus->lookup_tab, chorus->modulation_period_samples, fluid_chorus_sine(chorus->lookup_tab, chorus->modulation_period_samples,
modulation_depth_samples); modulation_depth_samples);
} else if (chorus->type == FLUID_CHORUS_MOD_TRIANGLE) { } else if (chorus->type == FLUID_CHORUS_MOD_TRIANGLE) {
fluid_chorus_triangle(chorus->lookup_tab, chorus->modulation_period_samples, fluid_chorus_triangle(chorus->lookup_tab, chorus->modulation_period_samples,
modulation_depth_samples); modulation_depth_samples);
} else { } else {
fluid_log(FLUID_WARN, "chorus: Unknown modulation type. Using sinewave."); fluid_log(FLUID_WARN, "chorus: Unknown modulation type. Using sinewave.");
chorus->type = FLUID_CHORUS_MOD_SINE; chorus->type = FLUID_CHORUS_MOD_SINE;
fluid_chorus_sine(chorus->lookup_tab, chorus->modulation_period_samples, fluid_chorus_sine(chorus->lookup_tab, chorus->modulation_period_samples,
modulation_depth_samples); modulation_depth_samples);
}; };
for (i = 0; i < chorus->number_blocks; i++) { for (i = 0; i < chorus->number_blocks; i++) {
/* Set the phase of the chorus blocks equally spaced */ /* Set the phase of the chorus blocks equally spaced */
chorus->phase[i] = (int) ((double) chorus->modulation_period_samples chorus->phase[i] = (int) ((double) chorus->modulation_period_samples
* (double) i / (double) chorus->number_blocks); * (double) i / (double) chorus->number_blocks);
} }
/* Start of the circular buffer */ /* Start of the circular buffer */
chorus->counter = 0; chorus->counter = 0;
@@ -409,7 +409,7 @@ fluid_chorus_update(fluid_chorus_t* chorus)
chorus->speed_Hz = chorus->new_speed_Hz; chorus->speed_Hz = chorus->new_speed_Hz;
chorus->number_blocks = chorus->new_number_blocks; chorus->number_blocks = chorus->new_number_blocks;
return FLUID_OK; return FLUID_OK;
/* failure: */ /* failure: */
/* Note: This lives on the assumption, that the last chorus values were correct. /* Note: This lives on the assumption, that the last chorus values were correct.
* If not, this will loop forever and a day. */ * If not, this will loop forever and a day. */
@@ -423,7 +423,7 @@ fluid_chorus_update(fluid_chorus_t* chorus)
} }
void fluid_chorus_processmix(fluid_chorus_t* chorus, fluid_real_t *in, void fluid_chorus_processmix(fluid_chorus_t* chorus, fluid_real_t *in,
fluid_real_t *left_out, fluid_real_t *right_out) fluid_real_t *left_out, fluid_real_t *right_out)
{ {
int sample_index; int sample_index;
@@ -447,19 +447,19 @@ void fluid_chorus_processmix(fluid_chorus_t* chorus, fluid_real_t *in,
for (i = 0; i < chorus->number_blocks; i++) { for (i = 0; i < chorus->number_blocks; i++) {
int ii; int ii;
/* Calculate the delay in subsamples for the delay line of chorus block nr. */ /* Calculate the delay in subsamples for the delay line of chorus block nr. */
/* The value in the lookup table is so, that this expression /* The value in the lookup table is so, that this expression
* will always be positive. It will always include a number of * will always be positive. It will always include a number of
* full periods of MAX_SAMPLES*INTERPOLATION_SUBSAMPLES to * full periods of MAX_SAMPLES*INTERPOLATION_SUBSAMPLES to
* remain positive at all times. */ * remain positive at all times. */
int pos_subsamples = (INTERPOLATION_SUBSAMPLES * chorus->counter int pos_subsamples = (INTERPOLATION_SUBSAMPLES * chorus->counter
- chorus->lookup_tab[chorus->phase[i]]); - chorus->lookup_tab[chorus->phase[i]]);
int pos_samples = pos_subsamples/INTERPOLATION_SUBSAMPLES; int pos_samples = pos_subsamples/INTERPOLATION_SUBSAMPLES;
/* modulo divide by INTERPOLATION_SUBSAMPLES */ /* modulo divide by INTERPOLATION_SUBSAMPLES */
pos_subsamples &= INTERPOLATION_SUBSAMPLES_ANDMASK; pos_subsamples &= INTERPOLATION_SUBSAMPLES_ANDMASK;
for (ii = 0; ii < INTERPOLATION_SAMPLES; ii++){ for (ii = 0; ii < INTERPOLATION_SAMPLES; ii++){
/* Add the delayed signal to the chorus sum d_out Note: The /* Add the delayed signal to the chorus sum d_out Note: The
* delay in the delay line moves backwards for increasing * delay in the delay line moves backwards for increasing
@@ -467,8 +467,8 @@ void fluid_chorus_processmix(fluid_chorus_t* chorus, fluid_real_t *in,
/* The & in chorusbuf[...] is equivalent to a division modulo /* The & in chorusbuf[...] is equivalent to a division modulo
MAX_SAMPLES, only faster. */ MAX_SAMPLES, only faster. */
d_out += (chorus->chorusbuf[pos_samples & MAX_SAMPLES_ANDMASK] d_out += chorus->chorusbuf[pos_samples & MAX_SAMPLES_ANDMASK]
* chorus->sinc_table[ii][pos_subsamples]); * chorus->sinc_table[ii][pos_subsamples];
pos_samples--; pos_samples--;
}; };
@@ -478,11 +478,11 @@ void fluid_chorus_processmix(fluid_chorus_t* chorus, fluid_real_t *in,
} /* foreach chorus block */ } /* foreach chorus block */
d_out *= chorus->level; d_out *= chorus->level;
/* Add the chorus sum d_out to output */ /* Add the chorus sum d_out to output */
left_out[sample_index] += d_out; left_out[sample_index] += d_out;
right_out[sample_index] += d_out; right_out[sample_index] += d_out;
/* Move forward in circular buffer */ /* Move forward in circular buffer */
chorus->counter++; chorus->counter++;
chorus->counter %= MAX_SAMPLES; chorus->counter %= MAX_SAMPLES;
@@ -490,8 +490,8 @@ void fluid_chorus_processmix(fluid_chorus_t* chorus, fluid_real_t *in,
} /* foreach sample */ } /* foreach sample */
} }
/* Duplication of code ... */ /* Duplication of code ... (replaces sample data instead of mixing) */
void fluid_chorus_processreplace(fluid_chorus_t* chorus, fluid_real_t *in, void fluid_chorus_processreplace(fluid_chorus_t* chorus, fluid_real_t *in,
fluid_real_t *left_out, fluid_real_t *right_out) fluid_real_t *left_out, fluid_real_t *right_out)
{ {
int sample_index; int sample_index;
@@ -515,19 +515,19 @@ void fluid_chorus_processreplace(fluid_chorus_t* chorus, fluid_real_t *in,
for (i = 0; i < chorus->number_blocks; i++) { for (i = 0; i < chorus->number_blocks; i++) {
int ii; int ii;
/* Calculate the delay in subsamples for the delay line of chorus block nr. */ /* Calculate the delay in subsamples for the delay line of chorus block nr. */
/* The value in the lookup table is so, that this expression /* The value in the lookup table is so, that this expression
* will always be positive. It will always include a number of * will always be positive. It will always include a number of
* full periods of MAX_SAMPLES*INTERPOLATION_SUBSAMPLES to * full periods of MAX_SAMPLES*INTERPOLATION_SUBSAMPLES to
* remain positive at all times. */ * remain positive at all times. */
int pos_subsamples = (INTERPOLATION_SUBSAMPLES * chorus->counter int pos_subsamples = (INTERPOLATION_SUBSAMPLES * chorus->counter
- chorus->lookup_tab[chorus->phase[i]]); - chorus->lookup_tab[chorus->phase[i]]);
int pos_samples = pos_subsamples / INTERPOLATION_SUBSAMPLES; int pos_samples = pos_subsamples / INTERPOLATION_SUBSAMPLES;
/* modulo divide by INTERPOLATION_SUBSAMPLES */ /* modulo divide by INTERPOLATION_SUBSAMPLES */
pos_subsamples &= INTERPOLATION_SUBSAMPLES_ANDMASK; pos_subsamples &= INTERPOLATION_SUBSAMPLES_ANDMASK;
for (ii = 0; ii < INTERPOLATION_SAMPLES; ii++){ for (ii = 0; ii < INTERPOLATION_SAMPLES; ii++){
/* Add the delayed signal to the chorus sum d_out Note: The /* Add the delayed signal to the chorus sum d_out Note: The
* delay in the delay line moves backwards for increasing * delay in the delay line moves backwards for increasing
@@ -535,7 +535,8 @@ void fluid_chorus_processreplace(fluid_chorus_t* chorus, fluid_real_t *in,
/* The & in chorusbuf[...] is equivalent to a division modulo /* The & in chorusbuf[...] is equivalent to a division modulo
MAX_SAMPLES, only faster. */ MAX_SAMPLES, only faster. */
d_out += chorus->chorusbuf[pos_samples & MAX_SAMPLES_ANDMASK] * chorus->sinc_table[ii][pos_subsamples]; d_out += chorus->chorusbuf[pos_samples & MAX_SAMPLES_ANDMASK]
* chorus->sinc_table[ii][pos_subsamples];
pos_samples--; pos_samples--;
}; };
@@ -545,11 +546,11 @@ void fluid_chorus_processreplace(fluid_chorus_t* chorus, fluid_real_t *in,
} /* foreach chorus block */ } /* foreach chorus block */
d_out *= chorus->level; d_out *= chorus->level;
/* Add the chorus sum d_out to output */ /* Store the chorus sum d_out to output */
left_out[sample_index] = d_out; left_out[sample_index] = d_out;
right_out[sample_index] = d_out; right_out[sample_index] = d_out;
/* Move forward in circular buffer */ /* Move forward in circular buffer */
chorus->counter++; chorus->counter++;
chorus->counter %= MAX_SAMPLES; chorus->counter %= MAX_SAMPLES;
@@ -598,7 +599,7 @@ void fluid_chorus_triangle(int *buf, int len, int depth)
} }
} }
void void
fluid_chorus_reset(fluid_chorus_t* chorus) fluid_chorus_reset(fluid_chorus_t* chorus)
{ {
fluid_chorus_init(chorus); fluid_chorus_init(chorus);
+3 -3
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -32,9 +32,9 @@ typedef struct _fluid_chorus_t fluid_chorus_t;
*/ */
fluid_chorus_t* new_fluid_chorus(fluid_real_t sample_rate); fluid_chorus_t* new_fluid_chorus(fluid_real_t sample_rate);
void delete_fluid_chorus(fluid_chorus_t* chorus); void delete_fluid_chorus(fluid_chorus_t* chorus);
void fluid_chorus_processmix(fluid_chorus_t* chorus, fluid_real_t *in, void fluid_chorus_processmix(fluid_chorus_t* chorus, fluid_real_t *in,
fluid_real_t *left_out, fluid_real_t *right_out); fluid_real_t *left_out, fluid_real_t *right_out);
void fluid_chorus_processreplace(fluid_chorus_t* chorus, fluid_real_t *in, void fluid_chorus_processreplace(fluid_chorus_t* chorus, fluid_real_t *in,
fluid_real_t *left_out, fluid_real_t *right_out); fluid_real_t *left_out, fluid_real_t *right_out);
int fluid_chorus_init(fluid_chorus_t* chorus); int fluid_chorus_init(fluid_chorus_t* chorus);
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -80,8 +80,8 @@ int fluid_handle_settings(fluid_synth_t* synth, int ac, char** av, fluid_ostream
fluid_cmd_t* fluid_cmd_copy(fluid_cmd_t* cmd); fluid_cmd_t* fluid_cmd_copy(fluid_cmd_t* cmd);
void delete_fluid_cmd(fluid_cmd_t* cmd); void delete_fluid_cmd(fluid_cmd_t* cmd);
int fluid_cmd_handler_handle(fluid_cmd_handler_t* handler, int fluid_cmd_handler_handle(fluid_cmd_handler_t* handler,
int ac, char** av, int ac, char** av,
fluid_ostream_t out); fluid_ostream_t out);
@@ -90,9 +90,9 @@ void fluid_server_remove_client(fluid_server_t* server, fluid_client_t* client);
void fluid_server_add_client(fluid_server_t* server, fluid_client_t* client); void fluid_server_add_client(fluid_server_t* server, fluid_client_t* client);
fluid_client_t* new_fluid_client(fluid_server_t* server, fluid_client_t* new_fluid_client(fluid_server_t* server,
fluid_settings_t* settings, fluid_settings_t* settings,
fluid_cmd_handler_t* handler, fluid_cmd_handler_t* handler,
fluid_socket_t sock); fluid_socket_t sock);
void delete_fluid_client(fluid_client_t* client); void delete_fluid_client(fluid_client_t* client);
+23 -23
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -35,7 +35,7 @@ fluid_real_t fluid_pan_tab[FLUID_PAN_SIZE];
* *
* Does all the initialization for this module. * Does all the initialization for this module.
*/ */
void void
fluid_conversion_config(void) fluid_conversion_config(void)
{ {
int i; int i;
@@ -44,7 +44,7 @@ fluid_conversion_config(void)
for (i = 0; i < FLUID_CENTS_HZ_SIZE; i++) { for (i = 0; i < FLUID_CENTS_HZ_SIZE; i++) {
fluid_ct2hz_tab[i] = (fluid_real_t) pow(2.0, (double) i / 1200.0); fluid_ct2hz_tab[i] = (fluid_real_t) pow(2.0, (double) i / 1200.0);
} }
/* centibels to amplitude conversion /* centibels to amplitude conversion
* Note: SF2.01 section 8.1.3: Initial attenuation range is * Note: SF2.01 section 8.1.3: Initial attenuation range is
* between 0 and 144 dB. Therefore a negative attenuation is * between 0 and 144 dB. Therefore a negative attenuation is
@@ -75,7 +75,7 @@ fluid_conversion_config(void)
fluid_convex_tab[0] = 0; fluid_convex_tab[0] = 0;
fluid_convex_tab[127] = 1.0; fluid_convex_tab[127] = 1.0;
x = log10(128.0 / 127.0); x = log10(128.0 / 127.0);
/* There seems to be an error in the specs. The equations are /* There seems to be an error in the specs. The equations are
implemented according to the pictures on SF2.01 page 73. */ implemented according to the pictures on SF2.01 page 73. */
@@ -95,11 +95,11 @@ fluid_conversion_config(void)
/* /*
* fluid_ct2hz * fluid_ct2hz
*/ */
fluid_real_t fluid_real_t
fluid_ct2hz_real(fluid_real_t cents) fluid_ct2hz_real(fluid_real_t cents)
{ {
if (cents < 0) if (cents < 0)
return (fluid_real_t) 1.0; return (fluid_real_t) 1.0;
else if (cents < 900) { else if (cents < 900) {
return (fluid_real_t) 6.875 * fluid_ct2hz_tab[(int) (cents + 300)]; return (fluid_real_t) 6.875 * fluid_ct2hz_tab[(int) (cents + 300)];
} else if (cents < 2100) { } else if (cents < 2100) {
@@ -132,8 +132,8 @@ fluid_ct2hz_real(fluid_real_t cents)
/* /*
* fluid_ct2hz * fluid_ct2hz
*/ */
fluid_real_t fluid_real_t
fluid_ct2hz(fluid_real_t cents) fluid_ct2hz(fluid_real_t cents)
{ {
/* Filter fc limit: SF2.01 page 48 # 8 */ /* Filter fc limit: SF2.01 page 48 # 8 */
if (cents >= 13500){ if (cents >= 13500){
@@ -150,15 +150,15 @@ fluid_ct2hz(fluid_real_t cents)
* in: a value between 0 and 960, 0 is no attenuation * in: a value between 0 and 960, 0 is no attenuation
* out: a value between 1 and 0 * out: a value between 1 and 0
*/ */
fluid_real_t fluid_real_t
fluid_cb2amp(fluid_real_t cb) fluid_cb2amp(fluid_real_t cb)
{ {
/* /*
* cb: an attenuation in 'centibels' (1/10 dB) * cb: an attenuation in 'centibels' (1/10 dB)
* SF2.01 page 49 # 48 limits it to 144 dB. * SF2.01 page 49 # 48 limits it to 144 dB.
* 96 dB is reasonable for 16 bit systems, 144 would make sense for 24 bit. * 96 dB is reasonable for 16 bit systems, 144 would make sense for 24 bit.
*/ */
/* minimum attenuation: 0 dB */ /* minimum attenuation: 0 dB */
if (cb < 0) { if (cb < 0) {
return 1.0; return 1.0;
@@ -166,7 +166,7 @@ fluid_cb2amp(fluid_real_t cb)
if (cb >= FLUID_CB_AMP_SIZE) { if (cb >= FLUID_CB_AMP_SIZE) {
return 0.0; return 0.0;
} }
return fluid_cb2amp_tab[(int) cb]; return fluid_cb2amp_tab[(int) cb];
} }
/* /*
@@ -178,7 +178,7 @@ fluid_cb2amp(fluid_real_t cb)
* Note: Volume attenuation is supposed to be centibels but EMU8k/10k don't * Note: Volume attenuation is supposed to be centibels but EMU8k/10k don't
* follow this. Thats the reason for separate fluid_cb2amp and fluid_atten2amp. * follow this. Thats the reason for separate fluid_cb2amp and fluid_atten2amp.
*/ */
fluid_real_t fluid_real_t
fluid_atten2amp(fluid_real_t atten) fluid_atten2amp(fluid_real_t atten)
{ {
if (atten < 0) return 1.0; if (atten < 0) return 1.0;
@@ -189,7 +189,7 @@ fluid_atten2amp(fluid_real_t atten)
/* /*
* fluid_tc2sec_delay * fluid_tc2sec_delay
*/ */
fluid_real_t fluid_real_t
fluid_tc2sec_delay(fluid_real_t tc) fluid_tc2sec_delay(fluid_real_t tc)
{ {
/* SF2.01 section 8.1.2 items 21, 23, 25, 33 /* SF2.01 section 8.1.2 items 21, 23, 25, 33
@@ -212,7 +212,7 @@ fluid_tc2sec_delay(fluid_real_t tc)
/* /*
* fluid_tc2sec_attack * fluid_tc2sec_attack
*/ */
fluid_real_t fluid_real_t
fluid_tc2sec_attack(fluid_real_t tc) fluid_tc2sec_attack(fluid_real_t tc)
{ {
/* SF2.01 section 8.1.2 items 26, 34 /* SF2.01 section 8.1.2 items 26, 34
@@ -228,7 +228,7 @@ fluid_tc2sec_attack(fluid_real_t tc)
/* /*
* fluid_tc2sec * fluid_tc2sec
*/ */
fluid_real_t fluid_real_t
fluid_tc2sec(fluid_real_t tc) fluid_tc2sec(fluid_real_t tc)
{ {
/* No range checking here! */ /* No range checking here! */
@@ -238,7 +238,7 @@ fluid_tc2sec(fluid_real_t tc)
/* /*
* fluid_tc2sec_release * fluid_tc2sec_release
*/ */
fluid_real_t fluid_real_t
fluid_tc2sec_release(fluid_real_t tc) fluid_tc2sec_release(fluid_real_t tc)
{ {
/* SF2.01 section 8.1.2 items 30, 38 /* SF2.01 section 8.1.2 items 30, 38
@@ -256,7 +256,7 @@ fluid_tc2sec_release(fluid_real_t tc)
* *
* Convert from absolute cents to Hertz * Convert from absolute cents to Hertz
*/ */
fluid_real_t fluid_real_t
fluid_act2hz(fluid_real_t c) fluid_act2hz(fluid_real_t c)
{ {
return (fluid_real_t) (8.176 * pow(2.0, (double) c / 1200.0)); return (fluid_real_t) (8.176 * pow(2.0, (double) c / 1200.0));
@@ -267,7 +267,7 @@ fluid_act2hz(fluid_real_t c)
* *
* Convert from Hertz to cents * Convert from Hertz to cents
*/ */
fluid_real_t fluid_real_t
fluid_hz2ct(fluid_real_t f) fluid_hz2ct(fluid_real_t f)
{ {
return (fluid_real_t) (6900 + 1200 * log(f / 440.0) / log(2.0)); return (fluid_real_t) (6900 + 1200 * log(f / 440.0) / log(2.0));
@@ -276,7 +276,7 @@ fluid_hz2ct(fluid_real_t f)
/* /*
* fluid_pan * fluid_pan
*/ */
fluid_real_t fluid_real_t
fluid_pan(fluid_real_t c, int left) fluid_pan(fluid_real_t c, int left)
{ {
if (left) { if (left) {
@@ -294,7 +294,7 @@ fluid_pan(fluid_real_t c, int left)
/* /*
* fluid_concave * fluid_concave
*/ */
fluid_real_t fluid_real_t
fluid_concave(fluid_real_t val) fluid_concave(fluid_real_t val)
{ {
if (val < 0) { if (val < 0) {
@@ -308,7 +308,7 @@ fluid_concave(fluid_real_t val)
/* /*
* fluid_convex * fluid_convex
*/ */
fluid_real_t fluid_real_t
fluid_convex(fluid_real_t val) fluid_convex(fluid_real_t val)
{ {
if (val < 0) { if (val < 0) {
+1 -1
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
File diff suppressed because it is too large Load Diff
+4 -6
View File
@@ -13,7 +13,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -218,7 +218,6 @@ extern unsigned short badpgen[]; /* list of bad preset generators */
void sfont_init_chunks (void); void sfont_init_chunks (void);
void sfont_close (SFData * sf); void sfont_close (SFData * sf);
void sfont_free_data (SFData * sf);
void sfont_free_zone (SFZone * zone); void sfont_free_zone (SFZone * zone);
int sfont_preset_compare_func (void* a, void* b); int sfont_preset_compare_func (void* a, void* b);
@@ -230,8 +229,8 @@ int gen_validp (int gen);
/*-----------------------------------sffile.h----------------------------*/ /*-----------------------------------sffile.h----------------------------*/
/* /*
File structures and routines (used to be in sffile.h) File structures and routines (used to be in sffile.h)
*/ */
#define CHNKIDSTR(id) &idlist[(id - 1) * 4] #define CHNKIDSTR(id) &idlist[(id - 1) * 4]
@@ -427,7 +426,6 @@ enum
#define ErrnoEnd ErrWrite #define ErrnoEnd ErrWrite
int gerr (int ev, char * fmt, ...); int gerr (int ev, char * fmt, ...);
void *safe_malloc (size_t size);
int safe_fread (void *buf, int count, FILE * fd); int safe_fread (void *buf, int count, FILE * fd);
int safe_fwrite (void *buf, int count, FILE * fd); int safe_fwrite (void *buf, int count, FILE * fd);
int safe_fseek (FILE * fd, long ofs, int whence); int safe_fseek (FILE * fd, long ofs, int whence);
@@ -443,7 +441,7 @@ int safe_fseek (FILE * fd, long ofs, int whence);
/*************************************************************** /***************************************************************
* *
* FORWARD DECLARATIONS * FORWARD DECLARATIONS
*/ */
typedef struct _fluid_defsfont_t fluid_defsfont_t; typedef struct _fluid_defsfont_t fluid_defsfont_t;
typedef struct _fluid_defpreset_t fluid_defpreset_t; typedef struct _fluid_defpreset_t fluid_defpreset_t;
-26
View File
@@ -1,26 +0,0 @@
/* FluidSynth - A Software Synthesizer
*
* Copyright (C) 2003 Peter Hanappe and others.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License
* as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307, USA
*/
#ifdef ENABLE_SSE
#include "fluid_dsp_sse.c"
#else
/* #include "fluid_dsp_simple.c" */
#include "fluid_dsp_float.c"
#endif
+633 -227
View File
@@ -11,271 +11,677 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307, USA * 02111-1307, USA
*/ */
#include "fluidsynth_priv.h"
#include "fluid_phase.h"
/* Purpose: /* Purpose:
* Low-level voice processing:
* *
* - interpolates (obtains values between the samples of the original waveform data) * Interpolates audio data (obtains values between the samples of the original
* - filters (applies a lowpass filter with variable cutoff frequency and quality factor) * waveform data).
* - mixes the processed sample to left and right output using the pan setting
* - sends the processed sample to chorus and reverb
* *
* * Variables loaded from the voice structure (assigned in fluid_voice_write()):
* This file does -not- generate an object file.
* Instead, it is #included in several places in fluid_voice.c.
* The motivation for this is
* - Calling it as a subroutine may be time consuming, especially with optimization off
* - The previous implementation as a macro was clumsy to handle
*
*
* Fluid_voice.c sets a couple of variables before #including this:
* - dsp_data: Pointer to the original waveform data * - dsp_data: Pointer to the original waveform data
* - dsp_left_buf: The generated signal goes here, left channel
* - dsp_right_buf: right channel
* - dsp_reverb_buf: Send to reverb unit
* - dsp_chorus_buf: Send to chorus unit
* - dsp_start: Start processing at this output buffer index
* - dsp_end: End processing just before this output buffer index
* - dsp_a1: Coefficient for the filter
* - dsp_a2: same
* - dsp_b0: same
* - dsp_b1: same
* - dsp_b2: same
* - dsp_filter_flag: Set, the filter is needed (many sound fonts don't use
* the filter at all. If it is left at its default setting
* of roughly 20 kHz, there is no need to apply filterling.)
* - dsp_interp_method: Which interpolation method to use.
* - voice holds the voice structure
*
* Some variables are set and modified:
* - dsp_phase: The position in the original waveform data. * - dsp_phase: The position in the original waveform data.
* This has an integer and a fractional part (between samples). * This has an integer and a fractional part (between samples).
* - dsp_phase_incr: For each output sample, the position in the original * - dsp_phase_incr: For each output sample, the position in the original
* waveform advances by dsp_phase_incr. This also has an integer * waveform advances by dsp_phase_incr. This also has an integer
* part and a fractional part. * part and a fractional part.
* If a sample is played at root pitch (no pitch change), * If a sample is played at root pitch (no pitch change),
* dsp_phase_incr is integer=1 and fractional=0. * dsp_phase_incr is integer=1 and fractional=0.
* - dsp_amp: The current amplitude envelope value. * - dsp_amp: The current amplitude envelope value.
* - dsp_amp_incr: The changing rate of the amplitude envelope. * - dsp_amp_incr: The changing rate of the amplitude envelope.
* *
* A couple of variables are used internally, their results are discarded: * A couple of variables are used internally, their results are discarded:
* - dsp_i: Index through the output buffer * - dsp_i: Index through the output buffer
* - dsp_phase_fractional: The fractional part of dsp_phase * - dsp_buf: Output buffer of floating point values (FLUID_BUFSIZE in length)
* - dsp_coeff: A table of four coefficients, depending on the fractional phase.
* Used to interpolate between samples.
* - dsp_process_buffer: Holds the processed signal between stages
* - dsp_centernode: delay line for the IIR filter
* - dsp_hist1: same
* - dsp_hist2: same
*
*/ */
/* Purpose: #include "fluidsynth_priv.h"
* zap_almost_zero will return a number, as long as its #include "fluid_synth.h"
* absolute value is over a certain threshold. Otherwise 0. See #include "fluid_voice.h"
* fluid_rev.c for documentation (denormal numbers)
*/
# if defined(WITH_FLOAT)
# define zap_almost_zero(_sample) \
((((*(unsigned int*)&(_sample))&0x7f800000) < 0x08000000)? 0.0f : (_sample))
# else
/* 1e-20 was chosen as an arbitrary (small) threshold. */
#define zap_almost_zero(_sample) ((abs(_sample) < 1e-20)? 0.0f : (_sample))
#endif
/* Interpolation (find a value between two samples of the original waveform) */ /* Interpolation (find a value between two samples of the original waveform) */
if ((fluid_phase_fract(dsp_phase) == 0) /* Linear interpolation table (2 coefficients centered on 1st) */
&& (fluid_phase_fract(dsp_phase_incr) == 0) static fluid_real_t interp_coeff_linear[FLUID_INTERP_MAX][2];
&& (fluid_phase_index(dsp_phase_incr) == 1)) {
/* Check for a special case: The current phase falls directly on an /* 4th order (cubic) interpolation table (4 coefficients centered on 2nd) */
* original sample. Also, the stepsize per output sample is exactly static fluid_real_t interp_coeff[FLUID_INTERP_MAX][4];
* one sample, no fractional part. In other words: The sample is
* played back at normal phase and root pitch. => No interpolation
* needed.
*/
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) {
/* Mix to the buffer and advance the phase by one sample */
dsp_buf[dsp_i] = dsp_amp * dsp_data[fluid_phase_index_plusplus(dsp_phase)];
dsp_amp += dsp_amp_incr;
}
} else { /* 7th order interpolation (7 coefficients centered on 3rd) */
static fluid_real_t sinc_table7[FLUID_INTERP_MAX][7];
/* wave table interpolation: Choose the interpolation method */
switch(dsp_interp_method){
case FLUID_INTERP_NONE:
/* No interpolation. Just take the sample, which is closest to
* the playback pointer. Questionable quality, but very
* efficient. */
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) {
dsp_phase_index = fluid_phase_index(dsp_phase);
dsp_buf[dsp_i] = dsp_amp * dsp_data[dsp_phase_index];
/* increment phase and amplitude */
fluid_phase_incr(dsp_phase, dsp_phase_incr);
dsp_amp += dsp_amp_incr;
};
break;
case FLUID_INTERP_LINEAR:
/* Straight line interpolation. */
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) {
dsp_coeff = &interp_coeff_linear[fluid_phase_fract_to_tablerow(dsp_phase)];
dsp_phase_index = fluid_phase_index(dsp_phase);
dsp_buf[dsp_i] = (dsp_amp *
(dsp_coeff->a0 * dsp_data[dsp_phase_index]
+ dsp_coeff->a1 * dsp_data[dsp_phase_index+1]));
/* increment phase and amplitude */
fluid_phase_incr(dsp_phase, dsp_phase_incr);
dsp_amp += dsp_amp_incr;
};
break;
case FLUID_INTERP_4THORDER:
default:
/* Default interpolation loop using floats */
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) {
dsp_coeff = &interp_coeff[fluid_phase_fract_to_tablerow(dsp_phase)];
dsp_phase_index = fluid_phase_index(dsp_phase);
dsp_buf[dsp_i] = (dsp_amp *
(dsp_coeff->a0 * dsp_data[dsp_phase_index]
+ dsp_coeff->a1 * dsp_data[dsp_phase_index+1]
+ dsp_coeff->a2 * dsp_data[dsp_phase_index+2]
+ dsp_coeff->a3 * dsp_data[dsp_phase_index+3]));
/* increment phase and amplitude */
fluid_phase_incr(dsp_phase, dsp_phase_incr);
dsp_amp += dsp_amp_incr;
}
break;
case FLUID_INTERP_7THORDER: #define SINC_INTERP_ORDER 7 /* 7th order constant */
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) {
int fract = fluid_phase_fract_to_tablerow(dsp_phase);
dsp_phase_index = fluid_phase_index(dsp_phase);
dsp_buf[dsp_i] = (dsp_amp *
(sinc_table7[0][fract] * (fluid_real_t) dsp_data[dsp_phase_index]
+ sinc_table7[1][fract] * (fluid_real_t) dsp_data[dsp_phase_index+1]
+ sinc_table7[2][fract] * (fluid_real_t) dsp_data[dsp_phase_index+2]
+ sinc_table7[3][fract] * (fluid_real_t) dsp_data[dsp_phase_index+3]
+ sinc_table7[4][fract] * (fluid_real_t) dsp_data[dsp_phase_index+4]
+ sinc_table7[5][fract] * (fluid_real_t) dsp_data[dsp_phase_index+5]
+ sinc_table7[6][fract] * (fluid_real_t) dsp_data[dsp_phase_index+6]));
/* increment phase and amplitude */
fluid_phase_incr(dsp_phase, dsp_phase_incr);
dsp_amp += dsp_amp_incr;
}
break;
} /* switch interpolation method */
} /* If interpolation is needed */
/* filter (implement the voice filter according to Soundfont standard) */
if (dsp_use_filter_flag) {
/* Check for denormal number (too close to zero) once in a
* while. This is not a big concern here - why would someone play a
* sample with an empty tail? */
dsp_hist1 = zap_almost_zero(dsp_hist1);
/* Two versions of the filter loop. One, while the filter is
* changing towards its new setting. The other, if the filter
* doesn't change.
*/
if (dsp_filter_coeff_incr_count > 0) {
/* The increment is added to each filter coefficient
filter_coeff_incr_count times. */
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) {
/* The filter is implemented in Direct-II form. */
dsp_centernode = dsp_buf[dsp_i] - dsp_a1 * dsp_hist1 - dsp_a2 * dsp_hist2;
dsp_buf[dsp_i] = dsp_b02 * (dsp_centernode + dsp_hist2) + dsp_b1 * dsp_hist1;
dsp_hist2 = dsp_hist1;
dsp_hist1 = dsp_centernode;
if (dsp_filter_coeff_incr_count-- > 0){
dsp_a1 += dsp_a1_incr;
dsp_a2 += dsp_a2_incr;
dsp_b02 += dsp_b02_incr;
dsp_b1 += dsp_b1_incr;
}
} /* for dsp_i */
} else {
/* The filter parameters are constant. This is duplicated to save
* time. */
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) {
/* The filter is implemented in Direct-II form. */
dsp_centernode = dsp_buf[dsp_i] - dsp_a1 * dsp_hist1 - dsp_a2 * dsp_hist2;
dsp_buf[dsp_i] = dsp_b02 * (dsp_centernode + dsp_hist2) + dsp_b1 * dsp_hist1;
dsp_hist2 = dsp_hist1;
dsp_hist1 = dsp_centernode;
}
} /* if filter is fixed */
} /* if filter is enabled */
/* Initializes interpolation tables */
void fluid_dsp_float_config (void)
{
int i, i2;
double x, v;
double i_shifted;
/* pan (Copy the signal to the left and right output buffer) The voice /* Initialize the coefficients for the interpolation. The math comes
* panning generator has a range of -500 .. 500. If it is centered, * from a mail, posted by Olli Niemitalo to the music-dsp mailing
* it's close to 0. voice->amp_left and voice->amp_right are then the * list (I found it in the music-dsp archives
* same, and we can save one multiplication per voice and sample. * http://www.smartelectronix.com/musicdsp/). */
*/
if ((-0.5 < voice->pan) && (voice->pan < 0.5)) {
/* The voice is centered. Use voice->amp_left twice. */
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) {
float v = voice->amp_left * dsp_buf[dsp_i];
dsp_left_buf[dsp_i] += v;
dsp_right_buf[dsp_i] += v;
}
} else { for (i = 0; i < FLUID_INTERP_MAX; i++)
{
x = (double) i / (double) FLUID_INTERP_MAX;
/* The voice is not centered. For stereo samples, one of the interp_coeff[i][0] = (fluid_real_t)(x * (-0.5 + x * (1 - 0.5 * x)));
* amplitudes will be zero. */ interp_coeff[i][1] = (fluid_real_t)(1.0 + x * x * (1.5 * x - 2.5));
if (voice->amp_left != 0.0){ interp_coeff[i][2] = (fluid_real_t)(x * (0.5 + x * (2.0 - 1.5 * x)));
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) { interp_coeff[i][3] = (fluid_real_t)(0.5 * x * x * (x - 1.0));
dsp_left_buf[dsp_i] += voice->amp_left * dsp_buf[dsp_i];
} interp_coeff_linear[i][0] = (fluid_real_t)(1.0 - x);
} interp_coeff_linear[i][1] = (fluid_real_t)x;
if (voice->amp_right != 0.0){ }
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) {
dsp_right_buf[dsp_i] += voice->amp_right * dsp_buf[dsp_i]; /* i: Offset in terms of whole samples */
} for (i = 0; i < SINC_INTERP_ORDER; i++)
} { /* i2: Offset in terms of fractional samples ('subsamples') */
for (i2 = 0; i2 < FLUID_INTERP_MAX; i2++)
{
/* center on middle of table */
i_shifted = (double)i - ((double)SINC_INTERP_ORDER / 2.0)
+ (double)i2 / (double)FLUID_INTERP_MAX;
/* sinc(0) cannot be calculated straightforward (limit needed for 0/0) */
if (fabs (i_shifted) > 0.000001)
{
v = (fluid_real_t)sin (i_shifted * M_PI) / (M_PI * i_shifted);
/* Hamming window */
v *= (fluid_real_t)0.5 * (1.0 + cos (2.0 * M_PI * i_shifted / (fluid_real_t)SINC_INTERP_ORDER));
}
else v = 1.0;
sinc_table7[FLUID_INTERP_MAX - i2 - 1][i] = v;
}
}
#if 0
for (i = 0; i < FLUID_INTERP_MAX; i++)
{
printf ("%d %0.3f %0.3f %0.3f %0.3f %0.3f %0.3f %0.3f\n",
i, sinc_table7[0][i], sinc_table7[1][i], sinc_table7[2][i],
sinc_table7[3][i], sinc_table7[4][i], sinc_table7[5][i], sinc_table7[6][i]);
}
#endif
fluid_check_fpe("interpolation table calculation");
} }
/* reverb send. Buffer may be NULL. */
if ((dsp_reverb_buf != NULL) && (voice->amp_reverb != 0.0)) { /* No interpolation. Just take the sample, which is closest to
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) { * the playback pointer. Questionable quality, but very
dsp_reverb_buf[dsp_i] += voice->amp_reverb * dsp_buf[dsp_i]; * efficient. */
} int
fluid_dsp_float_interpolate_none (fluid_voice_t *voice)
{
fluid_phase_t dsp_phase = voice->phase;
fluid_phase_t dsp_phase_incr, end_phase;
short int *dsp_data = voice->sample->data;
fluid_real_t *dsp_buf = voice->dsp_buf;
fluid_real_t dsp_amp = voice->amp;
fluid_real_t dsp_amp_incr = voice->amp_incr;
unsigned int dsp_i = 0;
unsigned int dsp_phase_index;
unsigned int end_index;
int looping;
/* Convert playback "speed" floating point value to phase index/fract */
fluid_phase_set_float (dsp_phase_incr, voice->phase_incr);
/* voice is currently looping? */
looping = _SAMPLEMODE (voice) == FLUID_LOOP_DURING_RELEASE
|| (_SAMPLEMODE (voice) == FLUID_LOOP_UNTIL_RELEASE
&& voice->volenv_section < FLUID_VOICE_ENVRELEASE);
end_index = looping ? voice->loopend - 1 : voice->end;
while (1)
{
dsp_phase_index = fluid_phase_index_round (dsp_phase); /* round to nearest point */
/* interpolate sequence of sample points */
for ( ; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++)
{
dsp_buf[dsp_i] = dsp_amp * dsp_data[dsp_phase_index];
/* increment phase and amplitude */
fluid_phase_incr (dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index_round (dsp_phase); /* round to nearest point */
dsp_amp += dsp_amp_incr;
}
/* break out if not looping (buffer may not be full) */
if (!looping) break;
/* go back to loop start */
if (dsp_phase_index > end_index)
{
fluid_phase_sub_int (dsp_phase, voice->loopend - voice->loopstart);
voice->has_looped = 1;
}
/* break out if filled buffer */
if (dsp_i >= FLUID_BUFSIZE) break;
}
voice->phase = dsp_phase;
voice->amp = dsp_amp;
return (dsp_i);
} }
/* chorus send. Buffer may be NULL. */ /* Straight line interpolation.
if ((dsp_chorus_buf != NULL) && (voice->amp_chorus != 0)) { * Returns number of samples processed (usually FLUID_BUFSIZE but could be
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) { * smaller if end of sample occurs).
dsp_chorus_buf[dsp_i] += voice->amp_chorus * dsp_buf[dsp_i]; */
} int
fluid_dsp_float_interpolate_linear (fluid_voice_t *voice)
{
fluid_phase_t dsp_phase = voice->phase;
fluid_phase_t dsp_phase_incr, end_phase;
short int *dsp_data = voice->sample->data;
fluid_real_t *dsp_buf = voice->dsp_buf;
fluid_real_t dsp_amp = voice->amp;
fluid_real_t dsp_amp_incr = voice->amp_incr;
unsigned int dsp_i = 0;
unsigned int dsp_phase_index;
unsigned int end_index;
short int point;
fluid_real_t *coeffs;
int looping;
/* Convert playback "speed" floating point value to phase index/fract */
fluid_phase_set_float (dsp_phase_incr, voice->phase_incr);
/* voice is currently looping? */
looping = _SAMPLEMODE (voice) == FLUID_LOOP_DURING_RELEASE
|| (_SAMPLEMODE (voice) == FLUID_LOOP_UNTIL_RELEASE
&& voice->volenv_section < FLUID_VOICE_ENVRELEASE);
/* last index before 2nd interpolation point must be specially handled */
end_index = (looping ? voice->loopend - 1 : voice->end) - 1;
/* 2nd interpolation point to use at end of loop or sample */
if (looping) point = dsp_data[voice->loopstart]; /* loop start */
else point = dsp_data[voice->end]; /* duplicate end for samples no longer looping */
while (1)
{
dsp_phase_index = fluid_phase_index (dsp_phase);
/* interpolate the sequence of sample points */
for ( ; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++)
{
coeffs = interp_coeff_linear[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * dsp_data[dsp_phase_index]
+ coeffs[1] * dsp_data[dsp_phase_index+1]);
/* increment phase and amplitude */
fluid_phase_incr (dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index (dsp_phase);
dsp_amp += dsp_amp_incr;
}
/* break out if buffer filled */
if (dsp_i >= FLUID_BUFSIZE) break;
end_index++; /* we're now interpolating the last point */
/* interpolate within last point */
for (; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
{
coeffs = interp_coeff_linear[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * dsp_data[dsp_phase_index]
+ coeffs[1] * point);
/* increment phase and amplitude */
fluid_phase_incr (dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index (dsp_phase);
dsp_amp += dsp_amp_incr; /* increment amplitude */
}
if (!looping) break; /* break out if not looping (end of sample) */
/* go back to loop start (if past */
if (dsp_phase_index > end_index)
{
fluid_phase_sub_int (dsp_phase, voice->loopend - voice->loopstart);
voice->has_looped = 1;
}
/* break out if filled buffer */
if (dsp_i >= FLUID_BUFSIZE) break;
end_index--; /* set end back to second to last sample point */
}
voice->phase = dsp_phase;
voice->amp = dsp_amp;
return (dsp_i);
}
/* 4th order (cubic) interpolation.
* Returns number of samples processed (usually FLUID_BUFSIZE but could be
* smaller if end of sample occurs).
*/
int
fluid_dsp_float_interpolate_4th_order (fluid_voice_t *voice)
{
fluid_phase_t dsp_phase = voice->phase;
fluid_phase_t dsp_phase_incr, end_phase;
short int *dsp_data = voice->sample->data;
fluid_real_t *dsp_buf = voice->dsp_buf;
fluid_real_t dsp_amp = voice->amp;
fluid_real_t dsp_amp_incr = voice->amp_incr;
unsigned int dsp_i = 0;
unsigned int dsp_phase_index;
unsigned int start_index, end_index;
short int start_point, end_point1, end_point2;
fluid_real_t *coeffs;
int looping;
/* Convert playback "speed" floating point value to phase index/fract */
fluid_phase_set_float (dsp_phase_incr, voice->phase_incr);
/* voice is currently looping? */
looping = _SAMPLEMODE (voice) == FLUID_LOOP_DURING_RELEASE
|| (_SAMPLEMODE (voice) == FLUID_LOOP_UNTIL_RELEASE
&& voice->volenv_section < FLUID_VOICE_ENVRELEASE);
/* last index before 4th interpolation point must be specially handled */
end_index = (looping ? voice->loopend - 1 : voice->end) - 2;
if (voice->has_looped) /* set start_index and start point if looped or not */
{
start_index = voice->loopstart;
start_point = dsp_data[voice->loopend - 1]; /* last point in loop (wrap around) */
}
else
{
start_index = voice->start;
start_point = dsp_data[voice->start]; /* just duplicate the point */
}
/* get points off the end (loop start if looping, duplicate point if end) */
if (looping)
{
end_point1 = dsp_data[voice->loopstart];
end_point2 = dsp_data[voice->loopstart + 1];
}
else
{
end_point1 = dsp_data[voice->end];
end_point2 = end_point1;
}
while (1)
{
dsp_phase_index = fluid_phase_index (dsp_phase);
/* interpolate first sample point (start or loop start) if needed */
for ( ; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
{
coeffs = interp_coeff[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * start_point
+ coeffs[1] * dsp_data[dsp_phase_index]
+ coeffs[2] * dsp_data[dsp_phase_index+1]
+ coeffs[3] * dsp_data[dsp_phase_index+2]);
/* increment phase and amplitude */
fluid_phase_incr (dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index (dsp_phase);
dsp_amp += dsp_amp_incr;
}
/* interpolate the sequence of sample points */
for ( ; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++)
{
coeffs = interp_coeff[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * dsp_data[dsp_phase_index-1]
+ coeffs[1] * dsp_data[dsp_phase_index]
+ coeffs[2] * dsp_data[dsp_phase_index+1]
+ coeffs[3] * dsp_data[dsp_phase_index+2]);
/* increment phase and amplitude */
fluid_phase_incr (dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index (dsp_phase);
dsp_amp += dsp_amp_incr;
}
/* break out if buffer filled */
if (dsp_i >= FLUID_BUFSIZE) break;
end_index++; /* we're now interpolating the 2nd to last point */
/* interpolate within 2nd to last point */
for (; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
{
coeffs = interp_coeff[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * dsp_data[dsp_phase_index-1]
+ coeffs[1] * dsp_data[dsp_phase_index]
+ coeffs[2] * dsp_data[dsp_phase_index+1]
+ coeffs[3] * end_point1);
/* increment phase and amplitude */
fluid_phase_incr (dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index (dsp_phase);
dsp_amp += dsp_amp_incr;
}
end_index++; /* we're now interpolating the last point */
/* interpolate within the last point */
for (; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
{
coeffs = interp_coeff[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * dsp_data[dsp_phase_index-1]
+ coeffs[1] * dsp_data[dsp_phase_index]
+ coeffs[2] * end_point1
+ coeffs[3] * end_point2);
/* increment phase and amplitude */
fluid_phase_incr (dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index (dsp_phase);
dsp_amp += dsp_amp_incr;
}
if (!looping) break; /* break out if not looping (end of sample) */
/* go back to loop start */
if (dsp_phase_index > end_index)
{
fluid_phase_sub_int (dsp_phase, voice->loopend - voice->loopstart);
if (!voice->has_looped)
{
voice->has_looped = 1;
start_index = voice->loopstart;
start_point = dsp_data[voice->loopend - 1];
}
}
/* break out if filled buffer */
if (dsp_i >= FLUID_BUFSIZE) break;
end_index -= 2; /* set end back to third to last sample point */
}
voice->phase = dsp_phase;
voice->amp = dsp_amp;
return (dsp_i);
}
/* 7th order interpolation.
* Returns number of samples processed (usually FLUID_BUFSIZE but could be
* smaller if end of sample occurs).
*/
int
fluid_dsp_float_interpolate_7th_order (fluid_voice_t *voice)
{
fluid_phase_t dsp_phase = voice->phase;
fluid_phase_t dsp_phase_incr, end_phase;
short int *dsp_data = voice->sample->data;
fluid_real_t *dsp_buf = voice->dsp_buf;
fluid_real_t dsp_amp = voice->amp;
fluid_real_t dsp_amp_incr = voice->amp_incr;
unsigned int dsp_i = 0;
unsigned int dsp_phase_index;
unsigned int start_index, end_index;
short int start_points[3];
short int end_points[3];
fluid_real_t *coeffs;
int looping;
/* Convert playback "speed" floating point value to phase index/fract */
fluid_phase_set_float (dsp_phase_incr, voice->phase_incr);
/* add 1/2 sample to dsp_phase since 7th order interpolation is centered on
* the 4th sample point */
fluid_phase_incr (dsp_phase, (fluid_phase_t)0x80000000);
/* voice is currently looping? */
looping = _SAMPLEMODE (voice) == FLUID_LOOP_DURING_RELEASE
|| (_SAMPLEMODE (voice) == FLUID_LOOP_UNTIL_RELEASE
&& voice->volenv_section < FLUID_VOICE_ENVRELEASE);
/* last index before 7th interpolation point must be specially handled */
end_index = (looping ? voice->loopend - 1 : voice->end) - 3;
if (voice->has_looped) /* set start_index and start point if looped or not */
{
start_index = voice->loopstart;
start_points[0] = dsp_data[voice->loopend - 1];
start_points[1] = dsp_data[voice->loopend - 2];
start_points[2] = dsp_data[voice->loopend - 3];
}
else
{
start_index = voice->start;
start_points[0] = dsp_data[voice->start]; /* just duplicate the start point */
start_points[1] = start_points[0];
start_points[2] = start_points[0];
}
/* get the 3 points off the end (loop start if looping, duplicate point if end) */
if (looping)
{
end_points[0] = dsp_data[voice->loopstart];
end_points[1] = dsp_data[voice->loopstart + 1];
end_points[2] = dsp_data[voice->loopstart + 2];
}
else
{
end_points[0] = dsp_data[voice->end];
end_points[1] = end_points[0];
end_points[2] = end_points[0];
}
while (1)
{
dsp_phase_index = fluid_phase_index (dsp_phase);
/* interpolate first sample point (start or loop start) if needed */
for ( ; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
{
coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp
* (coeffs[0] * (fluid_real_t)start_points[2]
+ coeffs[1] * (fluid_real_t)start_points[1]
+ coeffs[2] * (fluid_real_t)start_points[0]
+ coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
+ coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1]
+ coeffs[5] * (fluid_real_t)dsp_data[dsp_phase_index+2]
+ coeffs[6] * (fluid_real_t)dsp_data[dsp_phase_index+3]);
/* increment phase and amplitude */
fluid_phase_incr (dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index (dsp_phase);
dsp_amp += dsp_amp_incr;
}
start_index++;
/* interpolate 2nd to first sample point (start or loop start) if needed */
for ( ; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
{
coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp
* (coeffs[0] * (fluid_real_t)start_points[1]
+ coeffs[1] * (fluid_real_t)start_points[0]
+ coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1]
+ coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
+ coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1]
+ coeffs[5] * (fluid_real_t)dsp_data[dsp_phase_index+2]
+ coeffs[6] * (fluid_real_t)dsp_data[dsp_phase_index+3]);
/* increment phase and amplitude */
fluid_phase_incr (dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index (dsp_phase);
dsp_amp += dsp_amp_incr;
}
start_index++;
/* interpolate 3rd to first sample point (start or loop start) if needed */
for ( ; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
{
coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp
* (coeffs[0] * (fluid_real_t)start_points[0]
+ coeffs[1] * (fluid_real_t)dsp_data[dsp_phase_index-2]
+ coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1]
+ coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
+ coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1]
+ coeffs[5] * (fluid_real_t)dsp_data[dsp_phase_index+2]
+ coeffs[6] * (fluid_real_t)dsp_data[dsp_phase_index+3]);
/* increment phase and amplitude */
fluid_phase_incr (dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index (dsp_phase);
dsp_amp += dsp_amp_incr;
}
start_index -= 2; /* set back to original start index */
/* interpolate the sequence of sample points */
for ( ; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++)
{
coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp
* (coeffs[0] * (fluid_real_t)dsp_data[dsp_phase_index-3]
+ coeffs[1] * (fluid_real_t)dsp_data[dsp_phase_index-2]
+ coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1]
+ coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
+ coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1]
+ coeffs[5] * (fluid_real_t)dsp_data[dsp_phase_index+2]
+ coeffs[6] * (fluid_real_t)dsp_data[dsp_phase_index+3]);
/* increment phase and amplitude */
fluid_phase_incr (dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index (dsp_phase);
dsp_amp += dsp_amp_incr;
}
/* break out if buffer filled */
if (dsp_i >= FLUID_BUFSIZE) break;
end_index++; /* we're now interpolating the 3rd to last point */
/* interpolate within 3rd to last point */
for (; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
{
coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp
* (coeffs[0] * (fluid_real_t)dsp_data[dsp_phase_index-3]
+ coeffs[1] * (fluid_real_t)dsp_data[dsp_phase_index-2]
+ coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1]
+ coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
+ coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1]
+ coeffs[5] * (fluid_real_t)dsp_data[dsp_phase_index+2]
+ coeffs[6] * (fluid_real_t)end_points[0]);
/* increment phase and amplitude */
fluid_phase_incr (dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index (dsp_phase);
dsp_amp += dsp_amp_incr;
}
end_index++; /* we're now interpolating the 2nd to last point */
/* interpolate within 2nd to last point */
for (; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
{
coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp
* (coeffs[0] * (fluid_real_t)dsp_data[dsp_phase_index-3]
+ coeffs[1] * (fluid_real_t)dsp_data[dsp_phase_index-2]
+ coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1]
+ coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
+ coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1]
+ coeffs[5] * (fluid_real_t)end_points[0]
+ coeffs[6] * (fluid_real_t)end_points[1]);
/* increment phase and amplitude */
fluid_phase_incr (dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index (dsp_phase);
dsp_amp += dsp_amp_incr;
}
end_index++; /* we're now interpolating the last point */
/* interpolate within last point */
for (; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
{
coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)];
dsp_buf[dsp_i] = dsp_amp
* (coeffs[0] * (fluid_real_t)dsp_data[dsp_phase_index-3]
+ coeffs[1] * (fluid_real_t)dsp_data[dsp_phase_index-2]
+ coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1]
+ coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
+ coeffs[4] * (fluid_real_t)end_points[0]
+ coeffs[5] * (fluid_real_t)end_points[1]
+ coeffs[6] * (fluid_real_t)end_points[2]);
/* increment phase and amplitude */
fluid_phase_incr (dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index (dsp_phase);
dsp_amp += dsp_amp_incr;
}
if (!looping) break; /* break out if not looping (end of sample) */
/* go back to loop start */
if (dsp_phase_index > end_index)
{
fluid_phase_sub_int (dsp_phase, voice->loopend - voice->loopstart);
if (!voice->has_looped)
{
voice->has_looped = 1;
start_index = voice->loopstart;
start_points[0] = dsp_data[voice->loopend - 1];
start_points[1] = dsp_data[voice->loopend - 2];
start_points[2] = dsp_data[voice->loopend - 3];
}
}
/* break out if filled buffer */
if (dsp_i >= FLUID_BUFSIZE) break;
end_index -= 3; /* set end back to 4th to last sample point */
}
/* sub 1/2 sample from dsp_phase since 7th order interpolation is centered on
* the 4th sample point (correct back to real value) */
fluid_phase_decr (dsp_phase, (fluid_phase_t)0x80000000);
voice->phase = dsp_phase;
voice->amp = dsp_amp;
return (dsp_i);
} }
+20 -20
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -19,7 +19,7 @@
*/ */
/* Purpose: /* Purpose:
* Low-level voice processing: * Low-level voice processing:
* *
* - interpolates (obtains values between the samples of the original waveform data) * - interpolates (obtains values between the samples of the original waveform data)
@@ -60,7 +60,7 @@
* - dsp_phase_incr: For each output sample, the position in the original * - dsp_phase_incr: For each output sample, the position in the original
* waveform advances by dsp_phase_incr. This also has an integer * waveform advances by dsp_phase_incr. This also has an integer
* part and a fractional part. * part and a fractional part.
* If a sample is played at root pitch (no pitch change), * If a sample is played at root pitch (no pitch change),
* dsp_phase_incr is integer=1 and fractional=0. * dsp_phase_incr is integer=1 and fractional=0.
* - dsp_amp: The current amplitude envelope value. * - dsp_amp: The current amplitude envelope value.
* - dsp_amp_incr: The changing rate of the amplitude envelope. * - dsp_amp_incr: The changing rate of the amplitude envelope.
@@ -74,37 +74,37 @@
* - dsp_centernode: delay line for the IIR filter * - dsp_centernode: delay line for the IIR filter
* - dsp_hist1: same * - dsp_hist1: same
* - dsp_hist2: same * - dsp_hist2: same
* *
*/ */
/* Nonoptimized DSP loop */ /* Nonoptimized DSP loop */
#warning "This code is meant for experiments only."; #warning "This code is meant for experiments only.";
/* wave table interpolation */ /* wave table interpolation */
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) { for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) {
dsp_coeff = &interp_coeff[fluid_phase_fract_to_tablerow(dsp_phase)]; dsp_coeff = &interp_coeff[fluid_phase_fract_to_tablerow(dsp_phase)];
dsp_phase_index = fluid_phase_index(dsp_phase); dsp_phase_index = fluid_phase_index(dsp_phase);
dsp_sample = (dsp_amp * dsp_sample = (dsp_amp *
(dsp_coeff->a0 * dsp_data[dsp_phase_index] (dsp_coeff->a0 * dsp_data[dsp_phase_index]
+ dsp_coeff->a1 * dsp_data[dsp_phase_index+1] + dsp_coeff->a1 * dsp_data[dsp_phase_index+1]
+ dsp_coeff->a2 * dsp_data[dsp_phase_index+2] + dsp_coeff->a2 * dsp_data[dsp_phase_index+2]
+ dsp_coeff->a3 * dsp_data[dsp_phase_index+3])); + dsp_coeff->a3 * dsp_data[dsp_phase_index+3]));
/* increment phase and amplitude */ /* increment phase and amplitude */
fluid_phase_incr(dsp_phase, dsp_phase_incr); fluid_phase_incr(dsp_phase, dsp_phase_incr);
dsp_amp += dsp_amp_incr; dsp_amp += dsp_amp_incr;
/* filter */ /* filter */
/* The filter is implemented in Direct-II form. */ /* The filter is implemented in Direct-II form. */
dsp_centernode = dsp_sample - dsp_a1 * dsp_hist1 - dsp_a2 * dsp_hist2; dsp_centernode = dsp_sample - dsp_a1 * dsp_hist1 - dsp_a2 * dsp_hist2;
dsp_sample = dsp_b0 * dsp_centernode + dsp_b1 * dsp_hist1 + dsp_b2 * dsp_hist2; dsp_sample = dsp_b0 * dsp_centernode + dsp_b1 * dsp_hist1 + dsp_b2 * dsp_hist2;
dsp_hist2 = dsp_hist1; dsp_hist2 = dsp_hist1;
dsp_hist1 = dsp_centernode; dsp_hist1 = dsp_centernode;
/* pan */ /* pan */
dsp_left_buf[dsp_i] += voice->amp_left * dsp_sample; dsp_left_buf[dsp_i] += voice->amp_left * dsp_sample;
dsp_right_buf[dsp_i] += voice->amp_right * dsp_sample; dsp_right_buf[dsp_i] += voice->amp_right * dsp_sample;
/* reverb */ /* reverb */
-387
View File
@@ -1,387 +0,0 @@
/* FluidSynth - A Software Synthesizer
*
* Copyright (C) 2003 Peter Hanappe and others.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License
* as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307, USA
*/
/* Purpose:
* Low-level voice processing:
*
* - interpolates (obtains values between the samples of the original waveform data)
* - filters (applies a lowpass filter with variable cutoff frequency and quality factor)
* - mixes the processed sample to left and right output using the pan setting
* - sends the processed sample to chorus and reverb
*
*
* This file does -not- generate an object file.
* Instead, it is #included in several places in fluid_voice.c.
* The motivation for this is
* - Calling it as a subroutine may be time consuming, especially with optimization off
* - The previous implementation as a macro was clumsy to handle
*
*
* Fluid_voice.c sets a couple of variables before #including this:
* - dsp_data: Pointer to the original waveform data
* - dsp_left_buf: The generated signal goes here, left channel
* - dsp_right_buf: right channel
* - dsp_reverb_buf: Send to reverb unit
* - dsp_chorus_buf: Send to chorus unit
* - dsp_start: Start processing at this output buffer index
* - dsp_end: End processing just before this output buffer index
* - dsp_a1: Coefficient for the filter
* - dsp_a2: same
* - dsp_b0: same
* - dsp_b1: same
* - dsp_b2: same
* - dsp_filter_flag: Set, the filter is needed (many sound fonts don't use
* the filter at all. If it is left at its default setting
* of roughly 20 kHz, there is no need to apply filterling.)
* - dsp_interp_method: Which interpolation method to use.
* - voice holds the voice structure
*
* Some variables are set and modified:
* - dsp_phase: The position in the original waveform data.
* This has an integer and a fractional part (between samples).
* - dsp_phase_incr: For each output sample, the position in the original
* waveform advances by dsp_phase_incr. This also has an integer
* part and a fractional part.
* If a sample is played at root pitch (no pitch change),
* dsp_phase_incr is integer=1 and fractional=0.
* - dsp_amp: The current amplitude envelope value.
* - dsp_amp_incr: The changing rate of the amplitude envelope.
*
* A couple of variables are used internally, their results are discarded:
* - dsp_i: Index through the output buffer
* - dsp_phase_fractional: The fractional part of dsp_phase
* - dsp_coeff: A table of four coefficients, depending on the fractional phase.
* Used to interpolate between samples.
* - dsp_process_buffer: Holds the processed signal between stages
* - dsp_centernode: delay line for the IIR filter
* - dsp_hist1: same
* - dsp_hist2: same
*
*/
/* Purpose:
* zap_almost_zero will return a number, as long as its
* absolute value is over a certain threshold. Otherwise 0. See
* fluid_rev.c for documentation (denormal numbers)
*/
# if defined(WITH_FLOAT)
# define zap_almost_zero(_sample) \
((((*(unsigned int*)&(_sample))&0x7f800000) < 0x08000000)? 0.0f : (_sample))
# else
/* 1e-20 was chosen as an arbitrary (small) threshold. */
#define zap_almost_zero(_sample) ((abs(_sample) < 1e-20)? 0.0f : (_sample))
#endif
/* Interpolation (find a value between two samples of the original waveform) */
if ((fluid_phase_fract(dsp_phase) == 0)
&& (fluid_phase_fract(dsp_phase_incr) == 0)
&& (fluid_phase_index(dsp_phase_incr) == 1)) {
/* Check for a special case: The current phase falls directly on an
* original sample. Also, the stepsize per output sample is exactly
* one sample, no fractional part. In other words: The sample is
* played back at normal phase and root pitch. => No interpolation
* needed.
*/
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) {
/* Mix to the buffer and advance the phase by one sample */
dsp_buf[dsp_i] = dsp_amp * dsp_data[fluid_phase_index_plusplus(dsp_phase)];
dsp_amp += dsp_amp_incr;
}
} else {
/* wave table interpolation: Choose the interpolation method */
/* !!! SSE interpolation is less efficient that normal interpolation. */
/* Initialize amplitude increase */
sse_b->sf[0] = sse_b->sf[1] = sse_b->sf[2] = sse_b->sf[3] = 4.*dsp_amp_incr;
/* Initialize amplitude => xmm7
* The amplitude is kept in xmm7 throughout the whole process
*/
sse_a->sf[0]=sse_a->sf[1]=sse_a->sf[2]=sse_a->sf[3]=dsp_amp;
sse_a->sf[1] += dsp_amp_incr;
sse_a->sf[2] += 2.* dsp_amp_incr;
sse_a->sf[3] += 3.* dsp_amp_incr;
movaps_m2r(*sse_a,xmm7);
/* Where to store the result */
sse_dest=(sse_t*)&dsp_buf[0];
for (dsp_i = 0; dsp_i < FLUID_BUFSIZE; dsp_i += 4) {
/* Note / fixme: The coefficients are first copied to
* sse_c, then to the xmm register. Can't get it through
* the compiler differently... */
/* Load the four source samples for the 1st output sample */
dsp_phase_index = fluid_phase_index(dsp_phase);
sse_a->sf[0]=(fluid_real_t)dsp_data[dsp_phase_index];
sse_a->sf[1]=(fluid_real_t)dsp_data[dsp_phase_index+1];
sse_a->sf[2]=(fluid_real_t)dsp_data[dsp_phase_index+2];
sse_a->sf[3]=(fluid_real_t)dsp_data[dsp_phase_index+3];
movaps_m2r(*sse_a,xmm0);
*sse_c=interp_coeff_sse[fluid_phase_fract_to_tablerow(dsp_phase)];
mulps_m2r(*sse_c,xmm0);
fluid_phase_incr(dsp_phase, dsp_phase_incr);
/* Load the four source samples for the 2nd output sample */
dsp_phase_index = fluid_phase_index(dsp_phase);
sse_a->sf[0]=(fluid_real_t)dsp_data[dsp_phase_index];
sse_a->sf[1]=(fluid_real_t)dsp_data[dsp_phase_index+1];
sse_a->sf[2]=(fluid_real_t)dsp_data[dsp_phase_index+2];
sse_a->sf[3]=(fluid_real_t)dsp_data[dsp_phase_index+3];
movaps_m2r(*sse_a,xmm1);
*sse_c=interp_coeff_sse[fluid_phase_fract_to_tablerow(dsp_phase)];
mulps_m2r(*sse_c,xmm1);
fluid_phase_incr(dsp_phase, dsp_phase_incr);
/* Load the four source samples for the 3rd output sample */
dsp_phase_index = fluid_phase_index(dsp_phase);
sse_a->sf[0]=(fluid_real_t)dsp_data[dsp_phase_index];
sse_a->sf[1]=(fluid_real_t)dsp_data[dsp_phase_index+1];
sse_a->sf[2]=(fluid_real_t)dsp_data[dsp_phase_index+2];
sse_a->sf[3]=(fluid_real_t)dsp_data[dsp_phase_index+3];
movaps_m2r(*sse_a,xmm2);
*sse_c=interp_coeff_sse[fluid_phase_fract_to_tablerow(dsp_phase)];
mulps_m2r(*sse_c,xmm2);
fluid_phase_incr(dsp_phase, dsp_phase_incr);
/* Load the four source samples for the 4th output sample */
dsp_phase_index = fluid_phase_index(dsp_phase);
sse_a->sf[0]=(fluid_real_t)dsp_data[dsp_phase_index];
sse_a->sf[1]=(fluid_real_t)dsp_data[dsp_phase_index+1];
sse_a->sf[2]=(fluid_real_t)dsp_data[dsp_phase_index+2];
sse_a->sf[3]=(fluid_real_t)dsp_data[dsp_phase_index+3];
movaps_m2r(*sse_a,xmm3);
*sse_c=interp_coeff_sse[fluid_phase_fract_to_tablerow(dsp_phase)];
mulps_m2r(*sse_c,xmm3);
fluid_phase_incr(dsp_phase, dsp_phase_incr);
#if 0
/*Testcase for horizontal add */
sse_a->sf[0]=0.1;sse_a->sf[1]=0.01;sse_a->sf[2]=0.001;sse_a->sf[3]=0.0001;
movaps_m2r(*sse_a,xmm0);
sse_a->sf[0]=0.2;sse_a->sf[1]=0.02;sse_a->sf[2]=0.002;sse_a->sf[3]=0.0002;
movaps_m2r(*sse_a,xmm1);
sse_a->sf[0]=0.3;sse_a->sf[1]=0.03;sse_a->sf[2]=0.003;sse_a->sf[3]=0.0003;
movaps_m2r(*sse_a,xmm2);
sse_a->sf[0]=0.4;sse_a->sf[1]=0.04;sse_a->sf[2]=0.004;sse_a->sf[3]=0.0004;
movaps_m2r(*sse_a,xmm3);
#endif /* #if 0 */
#if 1
/* Horizontal add
* xmm4[0]:=xmm0[0]+xmm1[0]+xmm2[0]+xmm3[0]
* xmm4[1]:=xmm0[1]+xmm1[1]+xmm2[1]+xmm3[1]
* etc.
* The only register, which is unused, is xmm7.
*/
movaps_r2r(xmm0,xmm5);
movaps_r2r(xmm2,xmm6);
movlhps_r2r(xmm1,xmm5);
movlhps_r2r(xmm3,xmm6);
movhlps_r2r(xmm0,xmm1);
movhlps_r2r(xmm2,xmm3);
addps_r2r(xmm1,xmm5);
addps_r2r(xmm3,xmm6);
movaps_r2r(xmm5,xmm4);
shufps_r2r(xmm6,xmm5,0xDD);
shufps_r2r(xmm6,xmm4,0x88);
addps_r2r(xmm5,xmm4);
/* movaps_r2m(xmm4,*sse_a); */
/* printf("xmm4 (Result): %f %f %f %f\n", */
/* sse_a->sf[0], sse_a->sf[1], */
/* sse_a->sf[2], sse_a->sf[3]); */
#else
/* Add using normal FPU */
movaps_r2m(xmm0,*sse_a);
sse_c->sf[0]=sse_a->sf[0]+sse_a->sf[1]+sse_a->sf[2]+sse_a->sf[3];
movaps_r2m(xmm1,*sse_a);
sse_c->sf[1]=sse_a->sf[0]+sse_a->sf[1]+sse_a->sf[2]+sse_a->sf[3];
movaps_r2m(xmm2,*sse_a);
sse_c->sf[2]=sse_a->sf[0]+sse_a->sf[1]+sse_a->sf[2]+sse_a->sf[3];
movaps_r2m(xmm3,*sse_a);
sse_c->sf[3]=sse_a->sf[0]+sse_a->sf[1]+sse_a->sf[2]+sse_a->sf[3];
movaps_m2r(*sse_c,xmm4);
#endif /* #if 1 */
/* end horizontal add. Result in xmm6. */
/* Multiply xmm4 with amplitude */
mulps_r2r(xmm7,xmm4);
/* Store the result */
movaps_r2m(xmm4,*sse_dest); // ++
/* Advance the position in the output buffer */
sse_dest++;
/* Change the amplitude */
addps_m2r(*sse_b,xmm7);
} /* for dsp_i in steps of four */
movaps_r2m(xmm7,*sse_a);
/* Retrieve the last amplitude value. */
dsp_amp=sse_a->sf[3];
} /* If interpolation is needed */
/* filter (implement the voice filter according to Soundfont standard) */
if (dsp_use_filter_flag) {
/* Check for denormal number (too close to zero) once in a
* while. This is not a big concern here - why would someone play a
* sample with an empty tail? */
dsp_hist1 = zap_almost_zero(dsp_hist1);
/* Two versions of the filter loop. One, while the filter is
* changing towards its new setting. The other, if the filter
* doesn't change.
*/
if (dsp_filter_coeff_incr_count > 0) {
/* The increment is added to each filter coefficient
filter_coeff_incr_count times. */
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) {
/* The filter is implemented in Direct-II form. */
dsp_centernode = dsp_buf[dsp_i] - dsp_a1 * dsp_hist1 - dsp_a2 * dsp_hist2;
dsp_buf[dsp_i] = dsp_b02 * (dsp_centernode + dsp_hist2) + dsp_b1 * dsp_hist1;
dsp_hist2 = dsp_hist1;
dsp_hist1 = dsp_centernode;
if (dsp_filter_coeff_incr_count-- > 0){
dsp_a1 += dsp_a1_incr;
dsp_a2 += dsp_a2_incr;
dsp_b02 += dsp_b02_incr;
dsp_b1 += dsp_b1_incr;
}
} /* for dsp_i */
} else {
/* The filter parameters are constant. This is duplicated to save
* time. */
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) {
/* The filter is implemented in Direct-II form. */
dsp_centernode = dsp_buf[dsp_i] - dsp_a1 * dsp_hist1 - dsp_a2 * dsp_hist2;
dsp_buf[dsp_i] = dsp_b02 * (dsp_centernode + dsp_hist2) + dsp_b1 * dsp_hist1;
dsp_hist2 = dsp_hist1;
dsp_hist1 = dsp_centernode;
}
} /* if filter is fixed */
} /* if filter is enabled */
/* The following optimization will process a whole buffer using the
* SSE extension of the Pentium processor.
*/
if (voice->amp_left != 0.0) {
sse_a->sf[0]=voice->amp_left;
sse_a->sf[1]=voice->amp_left;
sse_a->sf[2]=voice->amp_left;
sse_a->sf[3]=voice->amp_left;
movaps_m2r(*sse_a,xmm0);
sse_src=(sse_t*)dsp_buf;
sse_dest=(sse_t*)&dsp_left_buf[0];
for (dsp_i = 0; dsp_i < FLUID_BUFSIZE; dsp_i+=4) {
movaps_m2r(*sse_src,xmm4); /* Load original sample */
mulps_r2r(xmm0,xmm4); /* Gain */
sse_src++;
addps_m2r(*sse_dest,xmm4); /* Mix with buf */
movaps_r2m(xmm4,*sse_dest); /* Store in buf */
sse_dest++;
}
}
if (voice->amp_right != 0.0){
sse_a->sf[0]=voice->amp_right;
sse_a->sf[1]=voice->amp_right;
sse_a->sf[2]=voice->amp_right;
sse_a->sf[3]=voice->amp_right;
movaps_m2r(*sse_a,xmm0);
sse_src=(sse_t*)dsp_buf;
sse_dest=(sse_t*)&dsp_right_buf[0];
for (dsp_i = 0; dsp_i < FLUID_BUFSIZE; dsp_i+=4) {
movaps_m2r(*sse_src,xmm4); /* Load original sample */
sse_src++;
mulps_r2r(xmm0,xmm4); /* Gain */
addps_m2r(*sse_dest,xmm4); /* Mix with buf */
movaps_r2m(xmm4,*sse_dest); /* Store in buf */
sse_dest++;
}
}
/* reverb send. Buffer may be NULL. */
if (dsp_reverb_buf && voice->amp_reverb != 0.0){
sse_a->sf[0]=voice->amp_reverb;
sse_a->sf[1]=voice->amp_reverb;
sse_a->sf[2]=voice->amp_reverb;
sse_a->sf[3]=voice->amp_reverb;
movaps_m2r(*sse_a,xmm0);
sse_src=(sse_t*)dsp_buf;
sse_dest=(sse_t*)&dsp_reverb_buf[0];
for (dsp_i = 0; dsp_i < FLUID_BUFSIZE; dsp_i+=4) {
movaps_m2r(*sse_src,xmm4); /* Load original sample */
sse_src++;
mulps_r2r(xmm0,xmm4); /* Gain */
addps_m2r(*sse_dest,xmm4); /* Mix with buf */
movaps_r2m(xmm4,*sse_dest); /* Store in buf */
sse_dest++;
}
}
/* chorus send. Buffer may be NULL. */
if (dsp_chorus_buf && voice->amp_chorus != 0){
sse_a->sf[0]=voice->amp_chorus;
sse_a->sf[1]=voice->amp_chorus;
sse_a->sf[2]=voice->amp_chorus;
sse_a->sf[3]=voice->amp_chorus;
movaps_m2r(*sse_a,xmm0);
sse_src=(sse_t*)dsp_buf;
sse_dest=(sse_t*)&dsp_chorus_buf[0];
for (dsp_i = 0; dsp_i < FLUID_BUFSIZE; dsp_i+=4) {
movaps_m2r(*sse_src,xmm4); /* Load original sample */
sse_src++;
mulps_r2r(xmm0,xmm4); /* Gain */
addps_m2r(*sse_dest,xmm4); /* Mix with buf */
movaps_r2m(xmm4,*sse_dest); /* Store in buf */
sse_dest++;
}
}
+266 -26
View File
@@ -11,14 +11,14 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307, USA * 02111-1307, USA
*/ */
/* /*
2002 : API design by Peter Hanappe and Antoine Schmitt 2002 : API design by Peter Hanappe and Antoine Schmitt
August 2002 : Implementation by Antoine Schmitt as@gratin.org August 2002 : Implementation by Antoine Schmitt as@gratin.org
@@ -27,7 +27,7 @@
Oct4.2002 : AS : corrected bug in heap allocation, that caused a crash during sequencer free. Oct4.2002 : AS : corrected bug in heap allocation, that caused a crash during sequencer free.
*/ */
#include "fluid_event_priv.h" #include "fluid_event_priv.h"
#include "fluidsynth_priv.h" #include "fluidsynth_priv.h"
@@ -38,11 +38,15 @@
/* Event alloc/free */ /* Event alloc/free */
fluid_event_t* /**
* Create a new sequencer event structure.
* @return New sequencer event structure or NULL if out of memory
*/
fluid_event_t*
new_fluid_event() new_fluid_event()
{ {
fluid_event_t* evt; fluid_event_t* evt;
evt = FLUID_NEW(fluid_event_t); evt = FLUID_NEW(fluid_event_t);
if (evt == NULL) { if (evt == NULL) {
fluid_log(FLUID_PANIC, "event: Out of memory\n"); fluid_log(FLUID_PANIC, "event: Out of memory\n");
@@ -50,46 +54,69 @@ new_fluid_event()
} }
FLUID_MEMSET(evt, 0, sizeof(fluid_event_t)); FLUID_MEMSET(evt, 0, sizeof(fluid_event_t));
// by default, no type // by default, no type
evt->dest = -1; evt->dest = -1;
evt->src = -1; evt->src = -1;
evt->type = -1; evt->type = -1;
return(evt); return(evt);
} }
void /**
* Delete a sequencer event structure.
* @param evt Sequencer event structure created by new_fluid_event().
*/
void
delete_fluid_event(fluid_event_t* evt) delete_fluid_event(fluid_event_t* evt)
{ {
if (evt == NULL) { if (evt == NULL) {
return; return;
} }
FLUID_FREE(evt); FLUID_FREE(evt);
} }
/* Initializing events */ /**
* Set the time field of a sequencer event.
* @internal
* @param evt Sequencer event structure
* @param time Time value to assign
*/
void void
fluid_event_set_time(fluid_event_t* evt, unsigned int time) fluid_event_set_time(fluid_event_t* evt, unsigned int time)
{ {
evt->time = time; evt->time = time;
} }
/**
* Set source of a sequencer event (DOCME).
* @param evt Sequencer event structure
* @param src DOCME
*/
void void
fluid_event_set_source(fluid_event_t* evt, short src) fluid_event_set_source(fluid_event_t* evt, short src)
{ {
evt->src = src; evt->src = src;
} }
/**
* Set destination of a sequencer event (DOCME).
* @param evt Sequencer event structure
* @param dest DOCME
*/
void void
fluid_event_set_dest(fluid_event_t* evt, short dest) fluid_event_set_dest(fluid_event_t* evt, short dest)
{ {
evt->dest = dest; evt->dest = dest;
} }
/* Timer events */ /**
* Set a sequencer event to be a timer event.
* @param evt Sequencer event structure
* @param data DOCME
*/
void void
fluid_event_timer(fluid_event_t* evt, void* data) fluid_event_timer(fluid_event_t* evt, void* data)
{ {
@@ -97,8 +124,13 @@ fluid_event_timer(fluid_event_t* evt, void* data)
evt->data = data; evt->data = data;
} }
/**
/* Note events */ * Set a sequencer event to be a note on event.
* @param evt Sequencer event structure
* @param channel MIDI channel number
* @param key MIDI note number (0-127)
* @param vel MIDI velocity value (0-127)
*/
void void
fluid_event_noteon(fluid_event_t* evt, int channel, short key, short vel) fluid_event_noteon(fluid_event_t* evt, int channel, short key, short vel)
{ {
@@ -108,6 +140,12 @@ fluid_event_noteon(fluid_event_t* evt, int channel, short key, short vel)
evt->vel = vel; evt->vel = vel;
} }
/**
* Set a sequencer event to be a note off event.
* @param evt Sequencer event structure
* @param channel MIDI channel number
* @param key MIDI note number (0-127)
*/
void void
fluid_event_noteoff(fluid_event_t* evt, int channel, short key) fluid_event_noteoff(fluid_event_t* evt, int channel, short key)
{ {
@@ -116,6 +154,14 @@ fluid_event_noteoff(fluid_event_t* evt, int channel, short key)
evt->key = key; evt->key = key;
} }
/**
* Set a sequencer event to be a note duration event.
* @param evt Sequencer event structure
* @param channel MIDI channel number
* @param key MIDI note number (0-127)
* @param vel MIDI velocity value (0-127)
* @param duration Duration of note (DOCME units?)
*/
void void
fluid_event_note(fluid_event_t* evt, int channel, short key, short vel, unsigned int duration) fluid_event_note(fluid_event_t* evt, int channel, short key, short vel, unsigned int duration)
{ {
@@ -126,6 +172,11 @@ fluid_event_note(fluid_event_t* evt, int channel, short key, short vel, unsigned
evt->duration = duration; evt->duration = duration;
} }
/**
* Set a sequencer event to be an all sounds off event.
* @param evt Sequencer event structure
* @param channel MIDI channel number
*/
void void
fluid_event_all_sounds_off(fluid_event_t* evt, int channel) fluid_event_all_sounds_off(fluid_event_t* evt, int channel)
{ {
@@ -133,6 +184,11 @@ fluid_event_all_sounds_off(fluid_event_t* evt, int channel)
evt->channel = channel; evt->channel = channel;
} }
/**
* Set a sequencer event to be a all notes off event.
* @param evt Sequencer event structure
* @param channel MIDI channel number
*/
void void
fluid_event_all_notes_off(fluid_event_t* evt, int channel) fluid_event_all_notes_off(fluid_event_t* evt, int channel)
{ {
@@ -140,6 +196,12 @@ fluid_event_all_notes_off(fluid_event_t* evt, int channel)
evt->channel = channel; evt->channel = channel;
} }
/**
* Set a sequencer event to be a bank select event.
* @param evt Sequencer event structure
* @param channel MIDI channel number
* @param bank_num MIDI bank number (0-16383)
*/
void void
fluid_event_bank_select(fluid_event_t* evt, int channel, short bank_num) fluid_event_bank_select(fluid_event_t* evt, int channel, short bank_num)
{ {
@@ -148,6 +210,12 @@ fluid_event_bank_select(fluid_event_t* evt, int channel, short bank_num)
evt->control = bank_num; evt->control = bank_num;
} }
/**
* Set a sequencer event to be a program change event.
* @param evt Sequencer event structure
* @param channel MIDI channel number
* @param val MIDI program number (0-127)
*/
void void
fluid_event_program_change(fluid_event_t* evt, int channel, short val) fluid_event_program_change(fluid_event_t* evt, int channel, short val)
{ {
@@ -156,6 +224,14 @@ fluid_event_program_change(fluid_event_t* evt, int channel, short val)
evt->value = val; evt->value = val;
} }
/**
* Set a sequencer event to be a program select event.
* @param evt Sequencer event structure
* @param channel MIDI channel number
* @param sfont_id SoundFont ID number
* @param bank_num MIDI bank number (0-16383)
* @param preset_num MIDI preset number (0-127)
*/
void void
fluid_event_program_select(fluid_event_t* evt, int channel, fluid_event_program_select(fluid_event_t* evt, int channel,
unsigned int sfont_id, short bank_num, short preset_num) unsigned int sfont_id, short bank_num, short preset_num)
@@ -167,6 +243,12 @@ fluid_event_program_select(fluid_event_t* evt, int channel,
evt->control = bank_num; evt->control = bank_num;
} }
/**
* Set a sequencer event to be an any control change event.
* @param evt Sequencer event structure
* @param channel MIDI channel number
* DOCME
*/
void void
fluid_event_any_control_change(fluid_event_t* evt, int channel) fluid_event_any_control_change(fluid_event_t* evt, int channel)
{ {
@@ -174,6 +256,12 @@ fluid_event_any_control_change(fluid_event_t* evt, int channel)
evt->channel = channel; evt->channel = channel;
} }
/**
* Set a sequencer event to be a pitch bend event.
* @param evt Sequencer event structure
* @param channel MIDI channel number
* @param pitch MIDI pitch bend value (0-16383, 8192 = no bend)
*/
void void
fluid_event_pitch_bend(fluid_event_t* evt, int channel, int pitch) fluid_event_pitch_bend(fluid_event_t* evt, int channel, int pitch)
{ {
@@ -184,6 +272,12 @@ fluid_event_pitch_bend(fluid_event_t* evt, int channel, int pitch)
evt->pitch = pitch; evt->pitch = pitch;
} }
/**
* Set a sequencer event to be a pitch wheel sensitivity event.
* @param evt Sequencer event structure
* @param channel MIDI channel number
* @param value MIDI pitch wheel sensitivity value (DOCME units?)
*/
void void
fluid_event_pitch_wheelsens(fluid_event_t* evt, int channel, short value) fluid_event_pitch_wheelsens(fluid_event_t* evt, int channel, short value)
{ {
@@ -192,6 +286,12 @@ fluid_event_pitch_wheelsens(fluid_event_t* evt, int channel, short value)
evt->value = value; evt->value = value;
} }
/**
* Set a sequencer event to be a modulation event.
* @param evt Sequencer event structure
* @param channel MIDI channel number
* @param val MIDI modulation value (0-127)
*/
void void
fluid_event_modulation(fluid_event_t* evt, int channel, short val) fluid_event_modulation(fluid_event_t* evt, int channel, short val)
{ {
@@ -202,6 +302,12 @@ fluid_event_modulation(fluid_event_t* evt, int channel, short val)
evt->value = val; evt->value = val;
} }
/**
* Set a sequencer event to be a MIDI sustain event.
* @param evt Sequencer event structure
* @param channel MIDI channel number
* @param val MIDI sustain value (0-127)
*/
void void
fluid_event_sustain(fluid_event_t* evt, int channel, short val) fluid_event_sustain(fluid_event_t* evt, int channel, short val)
{ {
@@ -212,6 +318,13 @@ fluid_event_sustain(fluid_event_t* evt, int channel, short val)
evt->value = val; evt->value = val;
} }
/**
* Set a sequencer event to be a MIDI control change event.
* @param evt Sequencer event structure
* @param channel MIDI channel number
* @param control MIDI control number (0-127)
* @param val MIDI control value (0-16383 DOCME is that true?)
*/
void void
fluid_event_control_change(fluid_event_t* evt, int channel, short control, short val) fluid_event_control_change(fluid_event_t* evt, int channel, short control, short val)
{ {
@@ -221,6 +334,12 @@ fluid_event_control_change(fluid_event_t* evt, int channel, short control, short
evt->value = val; evt->value = val;
} }
/**
* Set a sequencer event to be a stereo pan event.
* @param evt Sequencer event structure
* @param channel MIDI channel number
* @param val MIDI panning value (0-127, 0=left, 64 = middle, 127 = right)
*/
void void
fluid_event_pan(fluid_event_t* evt, int channel, short val) fluid_event_pan(fluid_event_t* evt, int channel, short val)
{ {
@@ -231,6 +350,12 @@ fluid_event_pan(fluid_event_t* evt, int channel, short val)
evt->value = val; evt->value = val;
} }
/**
* Set a sequencer event to be a volume event.
* @param evt Sequencer event structure
* @param channel MIDI channel number
* @param val Volume value (0-127)
*/
void void
fluid_event_volume(fluid_event_t* evt, int channel, short val) fluid_event_volume(fluid_event_t* evt, int channel, short val)
{ {
@@ -241,6 +366,12 @@ fluid_event_volume(fluid_event_t* evt, int channel, short val)
evt->value = val; evt->value = val;
} }
/**
* Set a sequencer event to be a reverb send event.
* @param evt Sequencer event structure
* @param channel MIDI channel number
* @param val Reverb amount (0-127)
*/
void void
fluid_event_reverb_send(fluid_event_t* evt, int channel, short val) fluid_event_reverb_send(fluid_event_t* evt, int channel, short val)
{ {
@@ -251,6 +382,12 @@ fluid_event_reverb_send(fluid_event_t* evt, int channel, short val)
evt->value = val; evt->value = val;
} }
/**
* Set a sequencer event to be a chorus send event.
* @param evt Sequencer event structure
* @param channel MIDI channel number
* @param val Chorus amount (0-127)
*/
void void
fluid_event_chorus_send(fluid_event_t* evt, int channel, short val) fluid_event_chorus_send(fluid_event_t* evt, int channel, short val)
{ {
@@ -261,76 +398,179 @@ fluid_event_chorus_send(fluid_event_t* evt, int channel, short val)
evt->value = val; evt->value = val;
} }
/* Accessing event data */
/*
* Accessing event data
*/
/**
* Get the event type (#fluid_seq_event_type) field from a sequencer event structure.
* @param evt Sequencer event structure
* @return Event type (#fluid_seq_event_type).
*/
int fluid_event_get_type(fluid_event_t* evt) int fluid_event_get_type(fluid_event_t* evt)
{ {
return evt->type; return evt->type;
} }
/**
* Get the time field from a sequencer event structure.
* @param evt Sequencer event structure
* @return Time value (DOCME units?)
*/
unsigned int fluid_event_get_time(fluid_event_t* evt) unsigned int fluid_event_get_time(fluid_event_t* evt)
{ {
return evt->time; return evt->time;
} }
/**
* Get the source field from a sequencer event structure.
* @param evt Sequencer event structure
* @return DOCME
*/
short fluid_event_get_source(fluid_event_t* evt) short fluid_event_get_source(fluid_event_t* evt)
{ {
return evt->src; return evt->src;
} }
/**
* Get the dest field from a sequencer event structure.
* @param evt Sequencer event structure
* @return DOCME
*/
short fluid_event_get_dest(fluid_event_t* evt) short fluid_event_get_dest(fluid_event_t* evt)
{ {
return evt->dest; return evt->dest;
} }
/**
* Get the MIDI channel field from a sequencer event structure.
* @param evt Sequencer event structure
* @return MIDI channel number (DOCME 0-15 or more?)
*/
int fluid_event_get_channel(fluid_event_t* evt) int fluid_event_get_channel(fluid_event_t* evt)
{ {
return evt->channel; return evt->channel;
} }
/**
* Get the MIDI note field from a sequencer event structure.
* @param evt Sequencer event structure
* @return MIDI note number (0-127)
*/
short fluid_event_get_key(fluid_event_t* evt) short fluid_event_get_key(fluid_event_t* evt)
{ {
return evt->key; return evt->key;
} }
/**
* Get the MIDI velocity field from a sequencer event structure.
* @param evt Sequencer event structure
* @return MIDI velocity value (0-127)
*/
short fluid_event_get_velocity(fluid_event_t* evt) short fluid_event_get_velocity(fluid_event_t* evt)
{ {
return evt->vel; return evt->vel;
} }
/**
* Get the MIDI control number field from a sequencer event structure.
* @param evt Sequencer event structure
* @return MIDI control number (0-127)
*/
short fluid_event_get_control(fluid_event_t* evt) short fluid_event_get_control(fluid_event_t* evt)
{ {
return evt->control; return evt->control;
} }
/**
* Get the value field from a sequencer event structure.
* @param evt Sequencer event structure
* @return Value field of event.
*
* The Value field is used by the following event types:
* #FLUID_SEQ_PROGRAMCHANGE, #FLUID_SEQ_PROGRAMSELECT (preset_num),
* #FLUID_SEQ_PITCHWHHELSENS, #FLUID_SEQ_MODULATION, #FLUID_SEQ_SUSTAIN,
* #FLUID_SEQ_CONTROLCHANGE, #FLUID_SEQ_PAN, #FLUID_SEQ_VOLUME,
* #FLUID_SEQ_REVERBSEND, #FLUID_SEQ_CHORUSSEND.
*/
short fluid_event_get_value(fluid_event_t* evt) short fluid_event_get_value(fluid_event_t* evt)
{ {
return evt->value; return evt->value;
} }
/**
* Get the data field from a sequencer event structure.
* @param evt Sequencer event structure
* @return Data field of event.
*
* Used by the #FLUID_SEQ_TIMER event type.
*/
void* fluid_event_get_data(fluid_event_t* evt) void* fluid_event_get_data(fluid_event_t* evt)
{ {
return evt->data; return evt->data;
} }
/**
* Get the duration field from a sequencer event structure.
* @param evt Sequencer event structure
* @return Note duration value (DOCME units?)
*
* Used by the #FLUID_SEQ_NOTE event type.
*/
unsigned int fluid_event_get_duration(fluid_event_t* evt) unsigned int fluid_event_get_duration(fluid_event_t* evt)
{ {
return evt->duration; return evt->duration;
} }
/**
* Get the MIDI bank field from a sequencer event structure.
* @param evt Sequencer event structure
* @return MIDI bank number (0-16383)
*
* Used by the #FLUID_SEQ_BANKSELECT and #FLUID_SEQ_PROGRAMSELECT
* event types.
*/
short fluid_event_get_bank(fluid_event_t* evt) short fluid_event_get_bank(fluid_event_t* evt)
{ {
return evt->control; return evt->control;
} }
/**
* Get the pitch field from a sequencer event structure.
* @param evt Sequencer event structure
* @return MIDI pitch bend pitch value (0-16383, 8192 = no bend)
*
* Used by the #FLUID_SEQ_PITCHBEND event type.
*/
int fluid_event_get_pitch(fluid_event_t* evt) int fluid_event_get_pitch(fluid_event_t* evt)
{ {
return evt->pitch; return evt->pitch;
} }
short
/**
* Get the MIDI program field from a sequencer event structure.
* @param evt Sequencer event structure
* @return MIDI program number (0-127)
*
* Used by the #FLUID_SEQ_PROGRAMCHANGE and #FLUID_SEQ_PROGRAMSELECT
* event types.
*/
short
fluid_event_get_program(fluid_event_t* evt) fluid_event_get_program(fluid_event_t* evt)
{ {
return evt->value; return evt->value;
} }
unsigned int
/**
* Get the SoundFont ID field from a sequencer event structure.
* @param evt Sequencer event structure
* @return SoundFont identifier value.
*
* Used by the #FLUID_SEQ_PROGRAMSELECT event type.
*/
unsigned int
fluid_event_get_sfont_id(fluid_event_t* evt) fluid_event_get_sfont_id(fluid_event_t* evt)
{ {
return evt->duration; return evt->duration;
@@ -378,21 +618,21 @@ _fluid_evt_heap_init(int nbEvents)
int i; int i;
fluid_evt_heap_t* heap; fluid_evt_heap_t* heap;
int siz = 2*sizeof(fluid_evt_entry *) + sizeof(fluid_evt_entry)*nbEvents; int siz = 2*sizeof(fluid_evt_entry *) + sizeof(fluid_evt_entry)*nbEvents;
heap = (fluid_evt_heap_t *)FLUID_MALLOC(siz); heap = (fluid_evt_heap_t *)FLUID_MALLOC(siz);
if (heap == NULL) { if (heap == NULL) {
fluid_log(FLUID_PANIC, "sequencer: Out of memory\n"); fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
return NULL; return NULL;
} }
FLUID_MEMSET(heap, 0, siz); FLUID_MEMSET(heap, 0, siz);
/* link all heap events */ /* link all heap events */
{ {
fluid_evt_entry *tmp = &(heap->pool); fluid_evt_entry *tmp = &(heap->pool);
for (i = 0 ; i < nbEvents - 1 ; i++) for (i = 0 ; i < nbEvents - 1 ; i++)
tmp[i].next = &(tmp[i+1]); tmp[i].next = &(tmp[i+1]);
tmp[nbEvents-1].next = NULL; tmp[nbEvents-1].next = NULL;
/* set head & tail */ /* set head & tail */
heap->tail = &(tmp[nbEvents-1]); heap->tail = &(tmp[nbEvents-1]);
heap->head = &(heap->pool); heap->head = &(heap->pool);
@@ -422,7 +662,7 @@ _fluid_evt_heap_free(fluid_evt_heap_t* heap)
fluid_mutex_destroy(heap->mutex); fluid_mutex_destroy(heap->mutex);
FLUID_FREE(heap); FLUID_FREE(heap);
#else #else
FLUID_FREE(heap); FLUID_FREE(heap);
#endif #endif
@@ -461,12 +701,12 @@ _fluid_seq_heap_get_free(fluid_evt_heap_t* heap)
#else #else
fluid_evt_entry* evt; fluid_evt_entry* evt;
if (heap->head == NULL) return NULL; if (heap->head == NULL) return NULL;
/* take from head of the heap */ /* take from head of the heap */
/* critical - should threadlock ? */ /* critical - should threadlock ? */
evt = heap->head; evt = heap->head;
heap->head = heap->head->next; heap->head = heap->head->next;
return evt; return evt;
#endif #endif
} }
+2 -2
View File
@@ -11,14 +11,14 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307, USA * 02111-1307, USA
*/ */
#ifndef _FLUID_EVENT_PRIV_H #ifndef _FLUID_EVENT_PRIV_H
#define _FLUID_EVENT_PRIV_H #define _FLUID_EVENT_PRIV_H
+10 -9
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -89,11 +89,12 @@ fluid_gen_info_t fluid_gen_info[] = {
}; };
/* fluid_gen_set_default_values /**
* * Set an array of generators to their default values.
* Set an array of generators to their initial value * @param gen Array of generators (should be #GEN_LAST in size).
* @return Always returns 0
*/ */
int int
fluid_gen_set_default_values(fluid_gen_t* gen) fluid_gen_set_default_values(fluid_gen_t* gen)
{ {
int i; int i;
@@ -111,9 +112,9 @@ fluid_gen_set_default_values(fluid_gen_t* gen)
/* fluid_gen_init /* fluid_gen_init
* *
* Set an array of generators to their initial value * Set an array of generators to their initial value
*/ */
int int
fluid_gen_init(fluid_gen_t* gen, fluid_channel_t* channel) fluid_gen_init(fluid_gen_t* gen, fluid_channel_t* channel)
{ {
int i; int i;
@@ -135,8 +136,8 @@ fluid_gen_init(fluid_gen_t* gen, fluid_channel_t* channel)
} }
fluid_real_t fluid_gen_scale(int gen, float value) fluid_real_t fluid_gen_scale(int gen, float value)
{ {
return (fluid_gen_info[gen].min return (fluid_gen_info[gen].min
+ value * (fluid_gen_info[gen].max - fluid_gen_info[gen].min)); + value * (fluid_gen_info[gen].max - fluid_gen_info[gen].min));
} }
+1 -1
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+46 -46
View File
@@ -21,10 +21,10 @@
* Modified by the GLib Team and others 1997-2000. See the AUTHORS * Modified by the GLib Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GLib Team. See the ChangeLog * file for a list of people on the GLib Team. See the ChangeLog
* files for a list of changes. These files are distributed with * files for a list of changes. These files are distributed with
* GLib at ftp://ftp.gtk.org/pub/gtk/. * GLib at ftp://ftp.gtk.org/pub/gtk/.
*/ */
/* /*
* MT safe * MT safe
*/ */
@@ -60,7 +60,7 @@ struct _fluid_hashtable_t {
if ((3 * hash_table->size <= hash_table->nnodes) \ if ((3 * hash_table->size <= hash_table->nnodes) \
&& (hash_table->size < HASH_TABLE_MAX_SIZE)) { \ && (hash_table->size < HASH_TABLE_MAX_SIZE)) { \
fluid_hashtable_resize(hash_table); \ fluid_hashtable_resize(hash_table); \
} }
static void fluid_hashtable_resize(fluid_hashtable_t *hash_table); static void fluid_hashtable_resize(fluid_hashtable_t *hash_table);
static fluid_hashnode_t** fluid_hashtable_lookup_node(fluid_hashtable_t *hash_table, char* key); static fluid_hashnode_t** fluid_hashtable_lookup_node(fluid_hashtable_t *hash_table, char* key);
@@ -69,7 +69,7 @@ static fluid_hashnode_t** fluid_hashtable_lookup_node(fluid_hashtable_t *hash_ta
* new_fluid_hashtable: * new_fluid_hashtable:
* *
* Creates a new #fluid_hashtable_t. * Creates a new #fluid_hashtable_t.
* *
* Return value: a new #fluid_hashtable_t. * Return value: a new #fluid_hashtable_t.
**/ **/
fluid_hashtable_t* fluid_hashtable_t*
@@ -94,22 +94,22 @@ new_fluid_hashtable(fluid_hash_delete_t del)
/** /**
* delete_fluid_hashtable: * delete_fluid_hashtable:
* @hash_table: a #fluid_hashtable_t. * @hash_table: a #fluid_hashtable_t.
* *
* Destroys the #fluid_hashtable_t. If keys and/or values are dynamically * Destroys the #fluid_hashtable_t. If keys and/or values are dynamically
* allocated, you should either free them first or create the #fluid_hashtable_t * allocated, you should either free them first or create the #fluid_hashtable_t
* using fluid_hashtable_new_full(). In the latter case the destroy functions * using fluid_hashtable_new_full(). In the latter case the destroy functions
* you supplied will be called on all keys and values before destroying * you supplied will be called on all keys and values before destroying
* the #fluid_hashtable_t. * the #fluid_hashtable_t.
**/ **/
void void
delete_fluid_hashtable(fluid_hashtable_t *hash_table) delete_fluid_hashtable(fluid_hashtable_t *hash_table)
{ {
unsigned int i; unsigned int i;
if (hash_table == NULL) { if (hash_table == NULL) {
return; return;
} }
for (i = 0; i < hash_table->size; i++) { for (i = 0; i < hash_table->size; i++) {
delete_fluid_hashnodes(hash_table->nodes[i], hash_table->del); delete_fluid_hashnodes(hash_table->nodes[i], hash_table->del);
} }
@@ -123,13 +123,13 @@ static /*inline*/ fluid_hashnode_t**
fluid_hashtable_lookup_node (fluid_hashtable_t* hash_table, char* key) fluid_hashtable_lookup_node (fluid_hashtable_t* hash_table, char* key)
{ {
fluid_hashnode_t **node; fluid_hashnode_t **node;
node = &hash_table->nodes[fluid_str_hash(key) % hash_table->size]; node = &hash_table->nodes[fluid_str_hash(key) % hash_table->size];
while (*node && (FLUID_STRCMP((*node)->key, key) != 0)) { while (*node && (FLUID_STRCMP((*node)->key, key) != 0)) {
node = &(*node)->next; node = &(*node)->next;
} }
return node; return node;
} }
@@ -137,16 +137,16 @@ fluid_hashtable_lookup_node (fluid_hashtable_t* hash_table, char* key)
* fluid_hashtable_lookup: * fluid_hashtable_lookup:
* @hash_table: a #fluid_hashtable_t. * @hash_table: a #fluid_hashtable_t.
* @key: the key to look up. * @key: the key to look up.
* *
* Looks up a key in a #fluid_hashtable_t. * Looks up a key in a #fluid_hashtable_t.
* *
* Return value: the associated value, or %NULL if the key is not found. * Return value: the associated value, or %NULL if the key is not found.
**/ **/
int int
fluid_hashtable_lookup(fluid_hashtable_t *hash_table, char* key, void** value, int* type) fluid_hashtable_lookup(fluid_hashtable_t *hash_table, char* key, void** value, int* type)
{ {
fluid_hashnode_t *node; fluid_hashnode_t *node;
node = *fluid_hashtable_lookup_node(hash_table, key); node = *fluid_hashtable_lookup_node(hash_table, key);
if (node) { if (node) {
@@ -167,22 +167,22 @@ fluid_hashtable_lookup(fluid_hashtable_t *hash_table, char* key, void** value, i
* @hash_table: a #fluid_hashtable_t. * @hash_table: a #fluid_hashtable_t.
* @key: a key to insert. * @key: a key to insert.
* @value: the value to associate with the key. * @value: the value to associate with the key.
* *
* Inserts a new key and value into a #fluid_hashtable_t. * Inserts a new key and value into a #fluid_hashtable_t.
* *
* If the key already exists in the #fluid_hashtable_t its current value is replaced * If the key already exists in the #fluid_hashtable_t its current value is replaced
* with the new value. If you supplied a @value_destroy_func when creating the * with the new value. If you supplied a @value_destroy_func when creating the
* #fluid_hashtable_t, the old value is freed using that function. If you supplied * #fluid_hashtable_t, the old value is freed using that function. If you supplied
* a @key_destroy_func when creating the #fluid_hashtable_t, the passed key is freed * a @key_destroy_func when creating the #fluid_hashtable_t, the passed key is freed
* using that function. * using that function.
**/ **/
void void
fluid_hashtable_insert(fluid_hashtable_t *hash_table, char* key, void* value, int type) fluid_hashtable_insert(fluid_hashtable_t *hash_table, char* key, void* value, int type)
{ {
fluid_hashnode_t **node; fluid_hashnode_t **node;
node = fluid_hashtable_lookup_node(hash_table, key); node = fluid_hashtable_lookup_node(hash_table, key);
if (*node) { if (*node) {
(*node)->value = value; (*node)->value = value;
(*node)->type = type; (*node)->type = type;
@@ -199,21 +199,21 @@ fluid_hashtable_insert(fluid_hashtable_t *hash_table, char* key, void* value, in
* @hash_table: a #GHashTable. * @hash_table: a #GHashTable.
* @key: a key to insert. * @key: a key to insert.
* @value: the value to associate with the key. * @value: the value to associate with the key.
* *
* Inserts a new key and value into a #GHashTable similar to * Inserts a new key and value into a #GHashTable similar to
* fluid_hashtable_insert(). The difference is that if the key already exists * fluid_hashtable_insert(). The difference is that if the key already exists
* in the #GHashTable, it gets replaced by the new key. If you supplied a * in the #GHashTable, it gets replaced by the new key. If you supplied a
* @value_destroy_func when creating the #GHashTable, the old value is freed * @value_destroy_func when creating the #GHashTable, the old value is freed
* using that function. If you supplied a @key_destroy_func when creating the * using that function. If you supplied a @key_destroy_func when creating the
* #GHashTable, the old key is freed using that function. * #GHashTable, the old key is freed using that function.
**/ **/
void void
fluid_hashtable_replace(fluid_hashtable_t *hash_table, char* key, void* value, int type) fluid_hashtable_replace(fluid_hashtable_t *hash_table, char* key, void* value, int type)
{ {
fluid_hashnode_t **node; fluid_hashnode_t **node;
node = fluid_hashtable_lookup_node(hash_table, key); node = fluid_hashtable_lookup_node(hash_table, key);
if (*node) { if (*node) {
if (hash_table->del) { if (hash_table->del) {
hash_table->del((*node)->value, (*node)->type); hash_table->del((*node)->value, (*node)->type);
@@ -231,30 +231,30 @@ fluid_hashtable_replace(fluid_hashtable_t *hash_table, char* key, void* value, i
* fluid_hashtable_remove: * fluid_hashtable_remove:
* @hash_table: a #fluid_hashtable_t. * @hash_table: a #fluid_hashtable_t.
* @key: the key to remove. * @key: the key to remove.
* *
* Removes a key and its associated value from a #fluid_hashtable_t. * Removes a key and its associated value from a #fluid_hashtable_t.
* *
* If the #fluid_hashtable_t was created using fluid_hashtable_new_full(), the * If the #fluid_hashtable_t was created using fluid_hashtable_new_full(), the
* key and value are freed using the supplied destroy functions, otherwise * key and value are freed using the supplied destroy functions, otherwise
* you have to make sure that any dynamically allocated values are freed * you have to make sure that any dynamically allocated values are freed
* yourself. * yourself.
* *
* Return value: %TRUE if the key was found and removed from the #fluid_hashtable_t. * Return value: %TRUE if the key was found and removed from the #fluid_hashtable_t.
**/ **/
int int
fluid_hashtable_remove (fluid_hashtable_t *hash_table, char* key) fluid_hashtable_remove (fluid_hashtable_t *hash_table, char* key)
{ {
fluid_hashnode_t **node, *dest; fluid_hashnode_t **node, *dest;
node = fluid_hashtable_lookup_node(hash_table, key); node = fluid_hashtable_lookup_node(hash_table, key);
if (*node) { if (*node) {
dest = *node; dest = *node;
(*node) = dest->next; (*node) = dest->next;
delete_fluid_hashnode(dest, hash_table->del); delete_fluid_hashnode(dest, hash_table->del);
hash_table->nnodes--; hash_table->nnodes--;
FLUID_HASHTABLE_RESIZE (hash_table); FLUID_HASHTABLE_RESIZE (hash_table);
return 1; return 1;
} }
@@ -266,7 +266,7 @@ fluid_hashtable_remove (fluid_hashtable_t *hash_table, char* key)
* @hash_table: a #fluid_hashtable_t. * @hash_table: a #fluid_hashtable_t.
* @func: the function to call for each key/value pair. * @func: the function to call for each key/value pair.
* @user_data: user data to pass to the function. * @user_data: user data to pass to the function.
* *
* Calls the given function for each of the key/value pairs in the * Calls the given function for each of the key/value pairs in the
* #fluid_hashtable_t. The function is passed the key and value of each * #fluid_hashtable_t. The function is passed the key and value of each
* pair, and the given @user_data parameter. The hash table may not * pair, and the given @user_data parameter. The hash table may not
@@ -290,9 +290,9 @@ fluid_hashtable_foreach(fluid_hashtable_t *hash_table, fluid_hash_iter_t func, v
/** /**
* fluid_hashtable_size: * fluid_hashtable_size:
* @hash_table: a #fluid_hashtable_t. * @hash_table: a #fluid_hashtable_t.
* *
* Returns the number of elements contained in the #fluid_hashtable_t. * Returns the number of elements contained in the #fluid_hashtable_t.
* *
* Return value: the number of key/value pairs in the #fluid_hashtable_t. * Return value: the number of key/value pairs in the #fluid_hashtable_t.
**/ **/
unsigned int unsigned int
@@ -315,14 +315,14 @@ fluid_hashtable_resize(fluid_hashtable_t *hash_table)
new_size = (new_size > HASH_TABLE_MAX_SIZE)? HASH_TABLE_MAX_SIZE : new_size; new_size = (new_size > HASH_TABLE_MAX_SIZE)? HASH_TABLE_MAX_SIZE : new_size;
/* printf("%s: %d: resizing, new size = %d\n", __FILE__, __LINE__, new_size); */ /* printf("%s: %d: resizing, new size = %d\n", __FILE__, __LINE__, new_size); */
new_nodes = FLUID_ARRAY(fluid_hashnode_t*, new_size); new_nodes = FLUID_ARRAY(fluid_hashnode_t*, new_size);
FLUID_MEMSET(new_nodes, 0, new_size * sizeof(fluid_hashnode_t*)); FLUID_MEMSET(new_nodes, 0, new_size * sizeof(fluid_hashnode_t*));
for (i = 0; i < hash_table->size; i++) { for (i = 0; i < hash_table->size; i++) {
for (node = hash_table->nodes[i]; node; node = next) { for (node = hash_table->nodes[i]; node; node = next) {
next = node->next; next = node->next;
hash_val = fluid_str_hash(node->key) % new_size; hash_val = fluid_str_hash(node->key) % new_size;
node->next = new_nodes[hash_val]; node->next = new_nodes[hash_val];
new_nodes[hash_val] = node; new_nodes[hash_val] = node;
} }
@@ -337,14 +337,14 @@ static fluid_hashnode_t*
new_fluid_hashnode(char* key, void* value, int type) new_fluid_hashnode(char* key, void* value, int type)
{ {
fluid_hashnode_t *hash_node; fluid_hashnode_t *hash_node;
hash_node = FLUID_NEW(fluid_hashnode_t); hash_node = FLUID_NEW(fluid_hashnode_t);
hash_node->key = FLUID_STRDUP(key); hash_node->key = FLUID_STRDUP(key);
hash_node->value = value; hash_node->value = value;
hash_node->type = type; hash_node->type = type;
hash_node->next = NULL; hash_node->next = NULL;
return hash_node; return hash_node;
} }
@@ -367,7 +367,7 @@ delete_fluid_hashnodes(fluid_hashnode_t *hash_node, fluid_hash_delete_t del)
fluid_hashnode_t *next = hash_node->next; fluid_hashnode_t *next = hash_node->next;
delete_fluid_hashnode(hash_node, del); delete_fluid_hashnode(hash_node, del);
hash_node = next; hash_node = next;
} }
} }
+1 -1
View File
@@ -21,7 +21,7 @@
* Modified by the GLib Team and others 1997-2000. See the AUTHORS * Modified by the GLib Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GLib Team. See the ChangeLog * file for a list of people on the GLib Team. See the ChangeLog
* files for a list of changes. These files are distributed with * files for a list of changes. These files are distributed with
* GLib at ftp://ftp.gtk.org/pub/gtk/. * GLib at ftp://ftp.gtk.org/pub/gtk/.
*/ */
/* /*
+11 -11
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -52,15 +52,15 @@ int fluid_istream_readline(fluid_istream_t in, char* prompt, char* buf, int len)
#if WITH_READLINE #if WITH_READLINE
if (in == fluid_get_stdin()) { if (in == fluid_get_stdin()) {
char* line; char* line;
line = readline(prompt); line = readline(prompt);
if (line == NULL) { if (line == NULL) {
return -1; return -1;
} }
snprintf(buf, len, "%s", line); snprintf(buf, len, "%s", line);
buf[len - 1] = 0; buf[len - 1] = 0;
free(line); free(line);
return 1; return 1;
} else { } else {
@@ -78,19 +78,19 @@ int fluid_istream_gets(fluid_istream_t in, char* buf, int len)
int n; int n;
buf[len - 1] = 0; buf[len - 1] = 0;
while (--len > 0) { while (--len > 0) {
n = read(in, &c, 1); n = read(in, &c, 1);
if (n == 0) { if (n == 0) {
*buf++ = 0; *buf++ = 0;
return 0; return 0;
} }
if (n < 0) { if (n < 0) {
return n; return n;
} }
if ((c == '\n') || (c == '\r')) { if ((c == '\n') || (c == '\r')) {
*buf++ = 0; *buf++ = 0;
return 1; return 1;
} }
*buf++ = c; *buf++ = c;
} }
@@ -102,12 +102,12 @@ int fluid_istream_gets(fluid_istream_t in, char* buf, int len)
int fluid_ostream_printf(fluid_ostream_t out, char* format, ...) int fluid_ostream_printf(fluid_ostream_t out, char* format, ...)
{ {
char buf[4096]; char buf[4096];
va_list args; va_list args;
int len; int len;
va_start(args, format); va_start(args, format);
len = vsnprintf(buf, 4095, format, args); len = vsnprintf(buf, 4095, format, args);
va_end(args); va_end(args);
if (len <= 0) { if (len <= 0) {
printf("fluid_ostream_printf: buffer overflow"); printf("fluid_ostream_printf: buffer overflow");
+6 -6
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -23,15 +23,15 @@
#define _FLUID_IO_H #define _FLUID_IO_H
/** Read a line from the input stream. /** Read a line from the input stream.
\returns 0 if end-of-stream, -1 if error, non zero otherwise \returns 0 if end-of-stream, -1 if error, non zero otherwise
*/ */
int fluid_istream_readline(fluid_istream_t in, char* prompt, char* buf, int len); int fluid_istream_readline(fluid_istream_t in, char* prompt, char* buf, int len);
/** Read a line from the input stream. /** Read a line from the input stream.
\returns The number of bytes written. If an error occured, -1 is \returns The number of bytes written. If an error occured, -1 is
returned. returned.
*/ */
+110 -110
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -57,17 +57,17 @@ fluid_LADSPA_FxUnit_t* new_fluid_LADSPA_FxUnit(fluid_synth_t* synth){
return FxUnit; return FxUnit;
}; };
/* Purpose: /* Purpose:
* Creates the system nodes to get data into and out of the Fx unit. * Creates the system nodes to get data into and out of the Fx unit.
*/ */
void fluid_LADSPA_CreateSystemNodes(fluid_LADSPA_FxUnit_t* FxUnit){ void fluid_LADSPA_CreateSystemNodes(fluid_LADSPA_FxUnit_t* FxUnit){
char str[99]; char str[99];
int nr_input_nodes; int nr_input_nodes;
int nr_fx_input_nodes; int nr_fx_input_nodes;
int nr_output_nodes; int nr_output_nodes;
int temp; int temp;
int i; int i;
/* Retrieve the number of synth / audio out / Fx send nodes */ /* Retrieve the number of synth / audio out / Fx send nodes */
assert(fluid_settings_getint(FxUnit->synth->settings, "synth.audio-groups", &temp)); assert(fluid_settings_getint(FxUnit->synth->settings, "synth.audio-groups", &temp));
nr_input_nodes=(int) temp; nr_input_nodes=(int) temp;
@@ -78,7 +78,7 @@ void fluid_LADSPA_CreateSystemNodes(fluid_LADSPA_FxUnit_t* FxUnit){
assert(fluid_settings_getint(FxUnit->synth->settings, "synth.effects-channels", &temp)); assert(fluid_settings_getint(FxUnit->synth->settings, "synth.effects-channels", &temp));
nr_fx_input_nodes=temp; nr_fx_input_nodes=temp;
/* Create regular input nodes (associated with audio groups) */ /* Create regular input nodes (associated with audio groups) */
for (i=0; i < nr_input_nodes; i++){ for (i=0; i < nr_input_nodes; i++){
sprintf(str, "in%i_L",(i+1)); sprintf(str, "in%i_L",(i+1));
@@ -104,13 +104,13 @@ void fluid_LADSPA_CreateSystemNodes(fluid_LADSPA_FxUnit_t* FxUnit){
}; };
}; };
/* Purpose: /* Purpose:
* Creates predeclared nodes for control of the Fx unit during operation. * Creates predeclared nodes for control of the Fx unit during operation.
*/ */
void fluid_LADSPA_CreateUserControlNodes(fluid_LADSPA_FxUnit_t* FxUnit){ void fluid_LADSPA_CreateUserControlNodes(fluid_LADSPA_FxUnit_t* FxUnit){
int i; int i;
fluid_LADSPA_Node_t* CurrentNode; fluid_LADSPA_Node_t* CurrentNode;
for (i=0; i<FxUnit->NumberUserControlNodes; i++){ for (i=0; i<FxUnit->NumberUserControlNodes; i++){
CurrentNode=fluid_LADSPA_CreateNode(FxUnit,FxUnit->UserControlNodeNames[i],fluid_LADSPA_node_is_control); CurrentNode=fluid_LADSPA_CreateNode(FxUnit,FxUnit->UserControlNodeNames[i],fluid_LADSPA_node_is_control);
assert(CurrentNode); assert(CurrentNode);
@@ -120,10 +120,10 @@ void fluid_LADSPA_CreateUserControlNodes(fluid_LADSPA_FxUnit_t* FxUnit){
}; };
}; };
/* Purpose: /* Purpose:
* Returns the pointer to the shared library loaded using 'LibraryFilename' (if it has been loaded). * Returns the pointer to the shared library loaded using 'LibraryFilename' (if it has been loaded).
* Return NULL otherwise. * Return NULL otherwise.
* If not: Clear Fx and abort. * If not: Clear Fx and abort.
*/ */
void * fluid_LADSPA_RetrieveSharedLibrary(fluid_LADSPA_FxUnit_t* FxUnit, char * LibraryFilename){ void * fluid_LADSPA_RetrieveSharedLibrary(fluid_LADSPA_FxUnit_t* FxUnit, char * LibraryFilename){
void * CurrentLib=NULL; void * CurrentLib=NULL;
@@ -137,15 +137,15 @@ void * fluid_LADSPA_RetrieveSharedLibrary(fluid_LADSPA_FxUnit_t* FxUnit, char *
return CurrentLib; return CurrentLib;
}; };
/* Purpose: /* Purpose:
* Loads a shared LADSPA library. * Loads a shared LADSPA library.
* Return NULL, if failed. * Return NULL, if failed.
* TODO: use LADSPA_PATH * TODO: use LADSPA_PATH
*/ */
void * fluid_LADSPA_LoadSharedLibrary(fluid_LADSPA_FxUnit_t* FxUnit, char * LibraryFilename){ void * fluid_LADSPA_LoadSharedLibrary(fluid_LADSPA_FxUnit_t* FxUnit, char * LibraryFilename){
void * LoadedLib; void * LoadedLib;
assert(LibraryFilename); assert(LibraryFilename);
LoadedLib=dlopen(LibraryFilename,RTLD_NOW); LoadedLib=dlopen(LibraryFilename,RTLD_NOW);
if (!LoadedLib){ if (!LoadedLib){
return NULL; return NULL;
}; };
@@ -155,7 +155,7 @@ void * fluid_LADSPA_LoadSharedLibrary(fluid_LADSPA_FxUnit_t* FxUnit, char * Libr
return LoadedLib; return LoadedLib;
}; };
/* Purpose: /* Purpose:
* Retrieves a descriptor to the plugin labeled 'PluginLabel' from the shared library. * Retrieves a descriptor to the plugin labeled 'PluginLabel' from the shared library.
*/ */
const LADSPA_Descriptor * fluid_LADSPA_Retrieve_Plugin_Descriptor(void * CurrentLib, char * PluginLabel){ const LADSPA_Descriptor * fluid_LADSPA_Retrieve_Plugin_Descriptor(void * CurrentLib, char * PluginLabel){
@@ -164,16 +164,16 @@ const LADSPA_Descriptor * fluid_LADSPA_Retrieve_Plugin_Descriptor(void * Current
const LADSPA_Descriptor * psDescriptor; const LADSPA_Descriptor * psDescriptor;
pfDescriptorFunction = (LADSPA_Descriptor_Function)dlsym(CurrentLib,"ladspa_descriptor"); pfDescriptorFunction = (LADSPA_Descriptor_Function)dlsym(CurrentLib,"ladspa_descriptor");
while (pfDescriptorFunction(lPluginIndex)){ while (pfDescriptorFunction(lPluginIndex)){
psDescriptor = pfDescriptorFunction(lPluginIndex); psDescriptor = pfDescriptorFunction(lPluginIndex);
if (FLUID_STRCMP(psDescriptor->Label, PluginLabel) == 0){ if (FLUID_STRCMP(psDescriptor->Label, PluginLabel) == 0){
return psDescriptor; return psDescriptor;
}; };
lPluginIndex++; lPluginIndex++;
}; };
return NULL; return NULL;
}; };
/* Purpose: /* Purpose:
* Finds out, if 'PortName' starts with 'PluginPort'. * Finds out, if 'PortName' starts with 'PluginPort'.
* Spaces and underscore mean the same. * Spaces and underscore mean the same.
* The comparison is not case sensitive. * The comparison is not case sensitive.
@@ -203,7 +203,7 @@ fluid_LADSPA_Stringmatch_t fluid_LADSPA_Check_SubString_Match(const char * Plugi
}; };
/* Purpose: /* Purpose:
* Load the plugins added with 'ladspa_add' and then start the Fx unit. * Load the plugins added with 'ladspa_add' and then start the Fx unit.
*/ */
int int
@@ -214,7 +214,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
char * PluginLabel; char * PluginLabel;
char ** TokenSequence; char ** TokenSequence;
void * CurrentLib; void * CurrentLib;
int NodeCount; //x int NodeCount; //x
int IngoingSignalCount; // Count signals going into LADSPA Fx section int IngoingSignalCount; // Count signals going into LADSPA Fx section
int OutgoingSignalCount; // Count signals going out of LADSPA Fx section int OutgoingSignalCount; // Count signals going out of LADSPA Fx section
int ReturnVal=FLUID_OK; /* If warnings occur, this is set to -1. */ int ReturnVal=FLUID_OK; /* If warnings occur, this is set to -1. */
@@ -223,7 +223,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
L(fluid_ostream_printf(out,"ladspa_start: starting...")); L(fluid_ostream_printf(out,"ladspa_start: starting..."));
assert(synth); assert(synth);
FxUnit=synth->LADSPA_FxUnit; assert(FxUnit); FxUnit=synth->LADSPA_FxUnit; assert(FxUnit);
/* When calling fluid_ladspastart, the Fx unit must be 'cleared' (no plugins, no libs, no nodes). Verify this here. */ /* When calling fluid_ladspastart, the Fx unit must be 'cleared' (no plugins, no libs, no nodes). Verify this here. */
if (FxUnit->NumberPlugins || FxUnit->NumberLibs){ if (FxUnit->NumberPlugins || FxUnit->NumberLibs){
fluid_ostream_printf(out, "***Error006***\n" fluid_ostream_printf(out, "***Error006***\n"
@@ -238,12 +238,12 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
"Use ladspa_add first!\n"); "Use ladspa_add first!\n");
fluid_LADSPA_clear(FxUnit); fluid_LADSPA_clear(FxUnit);
return(PrintErrorMessage); return(PrintErrorMessage);
}; };
/* Create predefined nodes */ /* Create predefined nodes */
L(fluid_ostream_printf(out,"ladspa_start: creating predefined nodes...")); L(fluid_ostream_printf(out,"ladspa_start: creating predefined nodes..."));
fluid_LADSPA_CreateSystemNodes(FxUnit); fluid_LADSPA_CreateSystemNodes(FxUnit);
/* Create predeclared nodes, that will allow to control the Fx unit during operation */ /* Create predeclared nodes, that will allow to control the Fx unit during operation */
L(fluid_ostream_printf(out,"ladspa_start: creating user control nodes...")); L(fluid_ostream_printf(out,"ladspa_start: creating user control nodes..."));
fluid_LADSPA_CreateUserControlNodes(FxUnit); fluid_LADSPA_CreateUserControlNodes(FxUnit);
@@ -251,14 +251,14 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
L(fluid_ostream_printf(out,"ladspa_start: Processing command lines...")); L(fluid_ostream_printf(out,"ladspa_start: Processing command lines..."));
for (CommandLineCount=0; CommandLineCount<FxUnit->NumberCommands; CommandLineCount++){ for (CommandLineCount=0; CommandLineCount<FxUnit->NumberCommands; CommandLineCount++){
int CurrentPlugin_PortConnected[FLUID_LADSPA_MaxTokens/3]; /* For example: 100 tokens corresponds to roughly 30 ports. */ int CurrentPlugin_PortConnected[FLUID_LADSPA_MaxTokens/3]; /* For example: 100 tokens corresponds to roughly 30 ports. */
char LibFullPath[FLUID_LADSPA_MaxPathLength]; char LibFullPath[FLUID_LADSPA_MaxPathLength];
const LADSPA_Descriptor * CurrentPluginDescriptor; const LADSPA_Descriptor * CurrentPluginDescriptor;
LADSPA_Handle CurrentPlugin; LADSPA_Handle CurrentPlugin;
unsigned long PortCount; unsigned long PortCount;
int TokenCount=0; int TokenCount=0;
char * Search; char * Search;
int HasASlash=0; int HasASlash=0;
if (FxUnit->NumberPlugins>=FLUID_LADSPA_MaxPlugins){ if (FxUnit->NumberPlugins>=FLUID_LADSPA_MaxPlugins){
fluid_ostream_printf(out, "***Error003***\n" fluid_ostream_printf(out, "***Error003***\n"
"Too many plugins at the same time (%i).\n" "Too many plugins at the same time (%i).\n"
@@ -269,13 +269,13 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
}; };
L(fluid_ostream_printf(out,"Processing plugin nr. %i",FxUnit->NumberPlugins)); L(fluid_ostream_printf(out,"Processing plugin nr. %i",FxUnit->NumberPlugins));
TokenSequence=FxUnit->LADSPA_Command_Sequence[CommandLineCount]; TokenSequence=FxUnit->LADSPA_Command_Sequence[CommandLineCount];
assert(TokenSequence); assert(TokenSequence);
/* Check, if the library is already loaded. If not, load. */ /* Check, if the library is already loaded. If not, load. */
LibraryFilename=TokenSequence[TokenCount++]; assert(LibraryFilename); LibraryFilename=TokenSequence[TokenCount++]; assert(LibraryFilename);
L(fluid_ostream_printf(out,"Library name from ladspa_add: %s",LibraryFilename)); L(fluid_ostream_printf(out,"Library name from ladspa_add: %s",LibraryFilename));
/* A slash-free filename refers to the LADSPA_PATH directory. Add that path, if needed. */ /* A slash-free filename refers to the LADSPA_PATH directory. Add that path, if needed. */
@@ -286,7 +286,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
* If that fails, signal error. * If that fails, signal error.
* Otherwise leave the filename as it is. * Otherwise leave the filename as it is.
*/; */;
/* Determine, if the library name is just the filename, or a path (including a slash) */ /* Determine, if the library name is just the filename, or a path (including a slash) */
Search=LibraryFilename; Search=LibraryFilename;
while (*Search != '\0') { while (*Search != '\0') {
@@ -295,9 +295,9 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
}; };
Search++; Search++;
}; };
if (!HasASlash){ if (!HasASlash){
if (!LADSPA_Path){ if (!LADSPA_Path){
fluid_ostream_printf(out, "***Error018***\n" fluid_ostream_printf(out, "***Error018***\n"
"The library file name %s does not include a path.\n" "The library file name %s does not include a path.\n"
"The environment variable LADSPA_PATH is not set.\n" "The environment variable LADSPA_PATH is not set.\n"
@@ -319,7 +319,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
CurrentLib=fluid_LADSPA_RetrieveSharedLibrary(FxUnit, LibFullPath); CurrentLib=fluid_LADSPA_RetrieveSharedLibrary(FxUnit, LibFullPath);
if (!CurrentLib){ if (!CurrentLib){
LADSPA_Descriptor_Function pfDescriptorFunction; LADSPA_Descriptor_Function pfDescriptorFunction;
L(fluid_ostream_printf(out,"Library %s not yet loaded. Loading.",LibFullPath)); L(fluid_ostream_printf(out,"Library %s not yet loaded. Loading.",LibFullPath));
@@ -330,7 +330,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
fluid_LADSPA_clear(FxUnit); fluid_LADSPA_clear(FxUnit);
return(PrintErrorMessage); return(PrintErrorMessage);
}; };
/* Load a LADSPA plugin library and store it for future use.*/ /* Load a LADSPA plugin library and store it for future use.*/
CurrentLib=fluid_LADSPA_LoadSharedLibrary(FxUnit, LibFullPath); CurrentLib=fluid_LADSPA_LoadSharedLibrary(FxUnit, LibFullPath);
@@ -350,23 +350,23 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
if (!pcError) {pcError="Huh?! No error from lib!";}; if (!pcError) {pcError="Huh?! No error from lib!";};
fluid_ostream_printf(out, "***Error015***\n" fluid_ostream_printf(out, "***Error015***\n"
"Unable to find ladspa_descriptor() function in plugin library file \"%s\": %s.\n" "Unable to find ladspa_descriptor() function in plugin library file \"%s\": %s.\n"
"Are you sure this is a LADSPA plugin file?\n", "Are you sure this is a LADSPA plugin file?\n",
LibraryFilename, LibraryFilename,
pcError); pcError);
fluid_LADSPA_clear(FxUnit); fluid_LADSPA_clear(FxUnit);
return(PrintErrorMessage); return(PrintErrorMessage);
}; };
L(fluid_ostream_printf(out,"Library loaded.")); L(fluid_ostream_printf(out,"Library loaded."));
}; };
PluginLabel=TokenSequence[TokenCount++]; assert(PluginLabel); PluginLabel=TokenSequence[TokenCount++]; assert(PluginLabel);
L(fluid_ostream_printf(out,"Plugin Label from ladspa_add: %s",PluginLabel)); L(fluid_ostream_printf(out,"Plugin Label from ladspa_add: %s",PluginLabel));
/* Retrieve a 'plugin descriptor' from the library. */ /* Retrieve a 'plugin descriptor' from the library. */
L(fluid_ostream_printf(out,"Looking for the plugin labeled %s",PluginLabel)); L(fluid_ostream_printf(out,"Looking for the plugin labeled %s",PluginLabel));
CurrentPluginDescriptor=fluid_LADSPA_Retrieve_Plugin_Descriptor(CurrentLib, PluginLabel); CurrentPluginDescriptor=fluid_LADSPA_Retrieve_Plugin_Descriptor(CurrentLib, PluginLabel);
/* Check, that the plugin was actually found.*/ /* Check, that the plugin was actually found.*/
if (CurrentPluginDescriptor==NULL){ if (CurrentPluginDescriptor==NULL){
@@ -379,30 +379,30 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
fluid_LADSPA_clear(FxUnit); fluid_LADSPA_clear(FxUnit);
return(PrintErrorMessage); return(PrintErrorMessage);
}; };
/* Create an instance of the plugin type from the descriptor */ /* Create an instance of the plugin type from the descriptor */
L(fluid_ostream_printf(out,"instantiating plugin %s",PluginLabel)); L(fluid_ostream_printf(out,"instantiating plugin %s",PluginLabel));
CurrentPlugin=CurrentPluginDescriptor CurrentPlugin=CurrentPluginDescriptor
->instantiate(CurrentPluginDescriptor,44100); /* Sample rate hardcoded */ ->instantiate(CurrentPluginDescriptor,44100); /* Sample rate hardcoded */
assert(CurrentPlugin); assert(CurrentPlugin);
/* The descriptor ("type of plugin") and the instance are stored for each plugin instantiation. /* The descriptor ("type of plugin") and the instance are stored for each plugin instantiation.
If one plugin type is instantiated several times, they will have the same descriptor, only If one plugin type is instantiated several times, they will have the same descriptor, only
different instances.*/ different instances.*/
FxUnit->PluginDescriptorTable[FxUnit->NumberPlugins]=CurrentPluginDescriptor; FxUnit->PluginDescriptorTable[FxUnit->NumberPlugins]=CurrentPluginDescriptor;
FxUnit->PluginInstanceTable[FxUnit->NumberPlugins]=CurrentPlugin; FxUnit->PluginInstanceTable[FxUnit->NumberPlugins]=CurrentPlugin;
/* /*
* *
* Wire up the inputs and outputs * Wire up the inputs and outputs
* *
*/ */
/* List for checking, that each plugin port is exactly connected once */ /* List for checking, that each plugin port is exactly connected once */
for (PortCount=0; PortCount<CurrentPluginDescriptor->PortCount; PortCount++){ for (PortCount=0; PortCount<CurrentPluginDescriptor->PortCount; PortCount++){
CurrentPlugin_PortConnected[PortCount]=0; CurrentPlugin_PortConnected[PortCount]=0;
}; };
/* Note: There are three NULL tokens at the end. The last condition may be evaluated even if the first one already detects the end. */ /* Note: There are three NULL tokens at the end. The last condition may be evaluated even if the first one already detects the end. */
while (TokenSequence[TokenCount] && TokenSequence[TokenCount+1] && TokenSequence[TokenCount+2]){ while (TokenSequence[TokenCount] && TokenSequence[TokenCount+1] && TokenSequence[TokenCount+2]){
int CurrentPort_StringMatchCount; int CurrentPort_StringMatchCount;
@@ -418,11 +418,11 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
CurrentPort_StringMatchCount=0; CurrentPort_StringMatchCount=0;
L(fluid_ostream_printf(out,"Wiring %s %s %s",Plugin_Port, Direction, FLUID_Node)); L(fluid_ostream_printf(out,"Wiring %s %s %s",Plugin_Port, Direction, FLUID_Node));
/* Find the port number on the plugin, that belongs to "Plugin_Port". /* Find the port number on the plugin, that belongs to "Plugin_Port".
* Match the identifier specified by the user against the first characters * Match the identifier specified by the user against the first characters
* of the port name. * of the port name.
* *
* If the given identifier matches several port names only partly, then the input is ambiguous, an error * If the given identifier matches several port names only partly, then the input is ambiguous, an error
* message results. * message results.
* *
@@ -430,19 +430,19 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
* - Output Envelope Attack (s) * - Output Envelope Attack (s)
* - Output Envelope Decay (s) * - Output Envelope Decay (s)
* - Output * - Output
* *
* The user input 'Output' matches the first two labels partly, the third fully. This will be accepted. * The user input 'Output' matches the first two labels partly, the third fully. This will be accepted.
* The user input 'Out' matches all three only partly, this results in an error message. * The user input 'Out' matches all three only partly, this results in an error message.
*/ */
for (PortCount=0; PortCount<CurrentPluginDescriptor->PortCount; PortCount++){ for (PortCount=0; PortCount<CurrentPluginDescriptor->PortCount; PortCount++){
PortName=CurrentPluginDescriptor->PortNames[PortCount]; PortName=CurrentPluginDescriptor->PortNames[PortCount];
StringMatchType=fluid_LADSPA_Check_SubString_Match(Plugin_Port, PortName); StringMatchType=fluid_LADSPA_Check_SubString_Match(Plugin_Port, PortName);
/* If a full-string match has been found earlier, reject all partial matches. */ /* If a full-string match has been found earlier, reject all partial matches. */
if (StringMatchType==fluid_LADSPA_FullMatch || if (StringMatchType==fluid_LADSPA_FullMatch ||
(StringMatchType==fluid_LADSPA_PartialMatch && CurrentPort_StringMatchType != fluid_LADSPA_FullMatch)){ (StringMatchType==fluid_LADSPA_PartialMatch && CurrentPort_StringMatchType != fluid_LADSPA_FullMatch)){
if(StringMatchType==fluid_LADSPA_FullMatch && CurrentPort_StringMatchType==fluid_LADSPA_FullMatch){ if(StringMatchType==fluid_LADSPA_FullMatch && CurrentPort_StringMatchType==fluid_LADSPA_FullMatch){
fluid_ostream_printf(out, "***Error027***\n" fluid_ostream_printf(out, "***Error027***\n"
"While processing plugin %s: The port label %s appears more than once!\n" "While processing plugin %s: The port label %s appears more than once!\n"
@@ -450,14 +450,14 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
fluid_LADSPA_clear(FxUnit); fluid_LADSPA_clear(FxUnit);
return(PrintErrorMessage); return(PrintErrorMessage);
}; };
CurrentPort_Index=PortCount; CurrentPort_Index=PortCount;
CurrentPort_StringMatchType=StringMatchType; CurrentPort_StringMatchType=StringMatchType;
CurrentPort_StringMatchCount++; CurrentPort_StringMatchCount++;
}; /* if suitable match */ }; /* if suitable match */
}; /* For port count */ }; /* For port count */
/* Several partial matches? Then the identifier is not unique. */ /* Several partial matches? Then the identifier is not unique. */
if (CurrentPort_StringMatchCount > 1 && CurrentPort_StringMatchType == fluid_LADSPA_PartialMatch){ if (CurrentPort_StringMatchCount > 1 && CurrentPort_StringMatchType == fluid_LADSPA_PartialMatch){
fluid_ostream_printf(out, "***Error019***\n" fluid_ostream_printf(out, "***Error019***\n"
@@ -467,7 +467,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
fluid_LADSPA_clear(FxUnit); fluid_LADSPA_clear(FxUnit);
return(PrintErrorMessage); return(PrintErrorMessage);
}; };
if (CurrentPort_Index<0){ if (CurrentPort_Index<0){
fluid_ostream_printf(out, "***Error017***\n" fluid_ostream_printf(out, "***Error017***\n"
"Unable to find port '%s' on plugin %s\n" "Unable to find port '%s' on plugin %s\n"
@@ -479,13 +479,13 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
fluid_LADSPA_clear(FxUnit); fluid_LADSPA_clear(FxUnit);
return(PrintErrorMessage); return(PrintErrorMessage);
}; };
CurrentPort_Descriptor=CurrentPluginDescriptor->PortDescriptors[CurrentPort_Index]; CurrentPort_Descriptor=CurrentPluginDescriptor->PortDescriptors[CurrentPort_Index];
assert(CurrentPort_Descriptor); assert(CurrentPort_Descriptor);
/* Retrieve the node with the right name. */ /* Retrieve the node with the right name. */
Current_Node=fluid_LADSPA_RetrieveNode(FxUnit,FLUID_Node); Current_Node=fluid_LADSPA_RetrieveNode(FxUnit,FLUID_Node);
#define PortIsAudio LADSPA_IS_PORT_AUDIO(CurrentPort_Descriptor) && !(LADSPA_IS_PORT_CONTROL(CurrentPort_Descriptor)) #define PortIsAudio LADSPA_IS_PORT_AUDIO(CurrentPort_Descriptor) && !(LADSPA_IS_PORT_CONTROL(CurrentPort_Descriptor))
#define PortIsControl LADSPA_IS_PORT_CONTROL(CurrentPort_Descriptor) && !(LADSPA_IS_PORT_AUDIO(CurrentPort_Descriptor)) #define PortIsControl LADSPA_IS_PORT_CONTROL(CurrentPort_Descriptor) && !(LADSPA_IS_PORT_AUDIO(CurrentPort_Descriptor))
if (!Current_Node){ if (!Current_Node){
/* Doesn't exist? Then create it. */ /* Doesn't exist? Then create it. */
if (FxUnit->NumberNodes>=FLUID_LADSPA_MaxNodes){ if (FxUnit->NumberNodes>=FLUID_LADSPA_MaxNodes){
@@ -504,21 +504,21 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
"Plugin port number %i is neither input nor output!\n" "Plugin port number %i is neither input nor output!\n"
"This is an error in the plugin.\n" "This is an error in the plugin.\n"
"Please check plugin sourcecode.\n", "Please check plugin sourcecode.\n",
CurrentPort_Index); CurrentPort_Index);
fluid_LADSPA_clear(FxUnit); fluid_LADSPA_clear(FxUnit);
return(PrintErrorMessage); return(PrintErrorMessage);
}; };
}; };
assert(Current_Node); assert(Current_Node);
/* /*
* *
* Check flowgraph for some possible errors. * Check flowgraph for some possible errors.
* *
*/ */
if (FLUID_STRCMP(Direction,"->")==0){ if (FLUID_STRCMP(Direction,"->")==0){
/* Data from plugin to FLUID, into node /* Data from plugin to FLUID, into node
* *
* *** Rule: **** * *** Rule: ****
* A node may not have more than one data source.*/ * A node may not have more than one data source.*/
@@ -530,11 +530,11 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
}; };
Current_Node->InCount++; Current_Node->InCount++;
} else if (FLUID_STRCMP(Direction,"<-")==0){ } else if (FLUID_STRCMP(Direction,"<-")==0){
/* Data from FLUID to plugin, out of node /* Data from FLUID to plugin, out of node
* *
* This check verifies the integrity of the flow graph: * This check verifies the integrity of the flow graph:
* *** Rule *** * *** Rule ***
* The execution order of the plugins is the order, in which they are programmed. * The execution order of the plugins is the order, in which they are programmed.
* The plugins must be ordered so, that the input of a plugin is already computed at the time of its execution. * The plugins must be ordered so, that the input of a plugin is already computed at the time of its execution.
* If the user tries to read data out of a node that has not yet an input, then something is wrong.*/ * If the user tries to read data out of a node that has not yet an input, then something is wrong.*/
assert(Current_Node->InCount<=1); assert(Current_Node->InCount<=1);
@@ -542,7 +542,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
fluid_ostream_printf(out, "***Error010***\n" fluid_ostream_printf(out, "***Error010***\n"
"Plugin %s tries to read data through input %s from node %s.\n" "Plugin %s tries to read data through input %s from node %s.\n"
"But at this point there is no valid data at that node.\n" "But at this point there is no valid data at that node.\n"
"Please check the flowgraph and especially the execution order!\n",PluginLabel,Plugin_Port,FLUID_Node); "Please check the flowgraph and especially the execution order!\n",PluginLabel,Plugin_Port,FLUID_Node);
fluid_LADSPA_clear(FxUnit); fluid_LADSPA_clear(FxUnit);
return(PrintErrorMessage); return(PrintErrorMessage);
}; };
@@ -550,7 +550,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
} else { } else {
fluid_ostream_printf(out, "***Error024***\n" fluid_ostream_printf(out, "***Error024***\n"
"Syntax error: Illegal `arrow' `%s', expecting -> or <-\n", "Syntax error: Illegal `arrow' `%s', expecting -> or <-\n",
Direction); Direction);
fluid_LADSPA_clear(FxUnit); fluid_LADSPA_clear(FxUnit);
return(PrintErrorMessage); return(PrintErrorMessage);
}; };
@@ -558,7 +558,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
/* In any case, there must be a valid data source for the port at this time. */ /* In any case, there must be a valid data source for the port at this time. */
assert(Current_Node->InCount==1); assert(Current_Node->InCount==1);
/* Keep track on the number of connections to each port. /* Keep track on the number of connections to each port.
* This error occurs only, if an attempt is made to connect one port twice (i.e. ladspa_add libname pluginname port <- nodex port <- nodey) */ * This error occurs only, if an attempt is made to connect one port twice (i.e. ladspa_add libname pluginname port <- nodex port <- nodey) */
if (CurrentPlugin_PortConnected[CurrentPort_Index]){ if (CurrentPlugin_PortConnected[CurrentPort_Index]){
fluid_ostream_printf(out, "***Error011***\n" fluid_ostream_printf(out, "***Error011***\n"
@@ -570,9 +570,9 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
/* /*
* *
* Connect the port * Connect the port
* *
*/ */
L(fluid_ostream_printf(out,"Connecting %i",CurrentPort_Index)); L(fluid_ostream_printf(out,"Connecting %i",CurrentPort_Index));
CurrentPluginDescriptor->connect_port CurrentPluginDescriptor->connect_port
(CurrentPlugin, (CurrentPlugin,
@@ -580,7 +580,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
Current_Node->buf Current_Node->buf
); );
CurrentPlugin_PortConnected[CurrentPort_Index]++; CurrentPlugin_PortConnected[CurrentPort_Index]++;
}; /* While Tokensequence (more connections) */ }; /* While Tokensequence (more connections) */
/* /*
@@ -588,7 +588,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
* Check for left-over tokens * Check for left-over tokens
* *
*/ */
if (TokenSequence[TokenCount]){ if (TokenSequence[TokenCount]){
char * T1="";char * T2="";char * T3=""; char * T1="";char * T2="";char * T3="";
if (TokenSequence[TokenCount]){T1=TokenSequence[TokenCount];}; if (TokenSequence[TokenCount]){T1=TokenSequence[TokenCount];};
@@ -599,7 +599,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
fluid_LADSPA_clear(FxUnit); fluid_LADSPA_clear(FxUnit);
return(PrintErrorMessage); return(PrintErrorMessage);
}; };
/* /*
* *
* Check, that all plugin ports are connected * Check, that all plugin ports are connected
@@ -615,7 +615,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
return(PrintErrorMessage); return(PrintErrorMessage);
}; };
}; };
/* /*
* *
*Run activate function on plugin, where possible *Run activate function on plugin, where possible
@@ -625,21 +625,21 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
if (CurrentPluginDescriptor->activate !=NULL){ if (CurrentPluginDescriptor->activate !=NULL){
CurrentPluginDescriptor->activate(CurrentPlugin); CurrentPluginDescriptor->activate(CurrentPlugin);
}; };
FxUnit->NumberPlugins++; FxUnit->NumberPlugins++;
}; /* For CommandLineCount: once for each new command (i.e. plugin instantiation request from user */ }; /* For CommandLineCount: once for each new command (i.e. plugin instantiation request from user */
/* /*
* *
* Further flow graph checks * Further flow graph checks
* *
*/ */
L(fluid_ostream_printf(out,"Checking flow graph")); L(fluid_ostream_printf(out,"Checking flow graph"));
IngoingSignalCount=0; IngoingSignalCount=0;
OutgoingSignalCount=0; OutgoingSignalCount=0;
for (NodeCount=0; NodeCount<FxUnit->NumberNodes; NodeCount++){ for (NodeCount=0; NodeCount<FxUnit->NumberNodes; NodeCount++){
fluid_LADSPA_Node_t* Current_Node; fluid_LADSPA_Node_t* Current_Node;
Current_Node=FxUnit->Nodelist[NodeCount]; Current_Node=FxUnit->Nodelist[NodeCount];
@@ -649,8 +649,8 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
} else if (Current_Node->flags & fluid_LADSPA_node_is_sink){ } else if (Current_Node->flags & fluid_LADSPA_node_is_sink){
OutgoingSignalCount+=Current_Node->InCount; OutgoingSignalCount+=Current_Node->InCount;
} else { } else {
/* A node without any input doesn't make sense. /* A node without any input doesn't make sense.
* The flow graph check aborts with an error. This case cannot happen. * The flow graph check aborts with an error. This case cannot happen.
*/ */
if (Current_Node->InCount==0 && !Current_Node->flags & fluid_LADSPA_node_is_dummy){ /* There can only be one warning at a time. */ if (Current_Node->InCount==0 && !Current_Node->flags & fluid_LADSPA_node_is_dummy){ /* There can only be one warning at a time. */
@@ -658,12 +658,12 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
"No input into node %s.\n" "No input into node %s.\n"
"Use '_' as first char in nodename to suppress this warning.\n" "Use '_' as first char in nodename to suppress this warning.\n"
"Hint: Check for typos in the node name.\n",Current_Node->Name); "Hint: Check for typos in the node name.\n",Current_Node->Name);
/* A warning can also be printed as an error message (check fluid_cmd.c). The only difference between /* A warning can also be printed as an error message (check fluid_cmd.c). The only difference between
the return values -1 and 0 is, that -1 prints the result. */ the return values -1 and 0 is, that -1 prints the result. */
}; };
ReturnVal=PrintErrorMessage; ReturnVal=PrintErrorMessage;
}; };
/* A node without any output doesn't make sense. */ /* A node without any output doesn't make sense. */
if (Current_Node->OutCount==0 && !Current_Node->flags & fluid_LADSPA_node_is_dummy){ if (Current_Node->OutCount==0 && !Current_Node->flags & fluid_LADSPA_node_is_dummy){
fluid_ostream_printf(out, "***Warning021***\n" fluid_ostream_printf(out, "***Warning021***\n"
@@ -675,27 +675,27 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
/* A free-flying node simply cannot happen. */ /* A free-flying node simply cannot happen. */
assert(Current_Node->OutCount+Current_Node->InCount); assert(Current_Node->OutCount+Current_Node->InCount);
}; /* Foreach node */ }; /* Foreach node */
/* Issue a warning, if no signal goes into the Fx section. */ /* Issue a warning, if no signal goes into the Fx section. */
if (IngoingSignalCount==0){ if (IngoingSignalCount==0){
fluid_ostream_printf(out, "***Warning022***\n" fluid_ostream_printf(out, "***Warning022***\n"
"You have not connected anything to the synthesizer section (in1_L, in1_R).\n"); "You have not connected anything to the synthesizer section (in1_L, in1_R).\n");
ReturnVal=PrintErrorMessage; ReturnVal=PrintErrorMessage;
}; };
/* Issue a warning, if no signal leaves the Fx section. */ /* Issue a warning, if no signal leaves the Fx section. */
if (OutgoingSignalCount==0){ if (OutgoingSignalCount==0){
fluid_ostream_printf(out, "***Warning023***\n" fluid_ostream_printf(out, "***Warning023***\n"
"You have not connected anything to the output (out1_L, out1_R).\n"); "You have not connected anything to the output (out1_L, out1_R).\n");
}; };
/* Finally turn on the Fx unit. */ /* Finally turn on the Fx unit. */
FxUnit->Bypass=fluid_LADSPA_Active; FxUnit->Bypass=fluid_LADSPA_Active;
L(fluid_ostream_printf(out,"LADSPA Init OK")); L(fluid_ostream_printf(out,"LADSPA Init OK"));
return(ReturnVal); return(ReturnVal);
}; };
void void
fluid_LADSPA_run(fluid_LADSPA_FxUnit_t* FxUnit, fluid_real_t* left_buf[], fluid_real_t* right_buf[], fluid_real_t* fx_left_buf[], fluid_real_t* fx_right_buf[]){ fluid_LADSPA_run(fluid_LADSPA_FxUnit_t* FxUnit, fluid_real_t* left_buf[], fluid_real_t* right_buf[], fluid_real_t* fx_left_buf[], fluid_real_t* fx_right_buf[]){
int i; int i;
int ii; int ii;
@@ -719,10 +719,10 @@ fluid_LADSPA_run(fluid_LADSPA_FxUnit_t* FxUnit, fluid_real_t* left_buf[], fluid_
assert(fluid_settings_getint(FxUnit->synth->settings, "synth.effects-channels", &temp)); assert(fluid_settings_getint(FxUnit->synth->settings, "synth.effects-channels", &temp));
nr_fx_sends=temp; nr_fx_sends=temp;
/* Fixme: Retrieving nodes via names is inefficient /* Fixme: Retrieving nodes via names is inefficient
* (but not that bad, because the interesting nodes are always at the start of the list). * (but not that bad, because the interesting nodes are always at the start of the list).
*/ */
/* Input and output are processed via the same buffers. Therefore the effect is bypassed by just skipping everything else. */ /* Input and output are processed via the same buffers. Therefore the effect is bypassed by just skipping everything else. */
if (FxUnit->Bypass==fluid_LADSPA_Bypassed){ if (FxUnit->Bypass==fluid_LADSPA_Bypassed){
return; return;
@@ -736,7 +736,7 @@ fluid_LADSPA_run(fluid_LADSPA_FxUnit_t* FxUnit, fluid_real_t* left_buf[], fluid_
L(printf("LADSPA_Run: Command line asked for bypass of Fx unit. Acknowledged.")); L(printf("LADSPA_Run: Command line asked for bypass of Fx unit. Acknowledged."));
return; return;
}; };
assert(FxUnit); assert(FxUnit);
/* Clear the output buffers, if they are not connected anywhere */ /* Clear the output buffers, if they are not connected anywhere */
@@ -756,16 +756,16 @@ fluid_LADSPA_run(fluid_LADSPA_FxUnit_t* FxUnit, fluid_real_t* left_buf[], fluid_
FLUID_MEMSET(n->buf, 0, byte_size); FLUID_MEMSET(n->buf, 0, byte_size);
}; };
}; };
/* Prepare the incoming data: /* Prepare the incoming data:
* Convert fluid_real_t data type to LADSPA_Data type */ * Convert fluid_real_t data type to LADSPA_Data type */
for (ii=0; ii < nr_groups; ii++){ for (ii=0; ii < nr_groups; ii++){
fluid_real_t* src_buf=left_buf[ii]; fluid_real_t* src_buf=left_buf[ii];
sprintf(str, "in%i_L",(ii+1)); sprintf(str, "in%i_L",(ii+1));
n=fluid_LADSPA_RetrieveNode(FxUnit, str); assert(n); n=fluid_LADSPA_RetrieveNode(FxUnit, str); assert(n);
assert(FLUID_BUFSIZE % 2 == 0); assert(FLUID_BUFSIZE % 2 == 0);
/* Add a very small high frequency signal. This avoids denormal number problems. */ /* Add a very small high frequency signal. This avoids denormal number problems. */
for (i=0; i<FLUID_BUFSIZE;){ for (i=0; i<FLUID_BUFSIZE;){
n->buf[i]=(LADSPA_Data)(src_buf[i]+1.e-15); n->buf[i]=(LADSPA_Data)(src_buf[i]+1.e-15);
@@ -816,7 +816,7 @@ fluid_LADSPA_run(fluid_LADSPA_FxUnit_t* FxUnit, fluid_real_t* left_buf[], fluid_
for (i=0; i<FLUID_BUFSIZE; i++){ for (i=0; i<FLUID_BUFSIZE; i++){
dest_buf[i]=(fluid_real_t)n->buf[i]; dest_buf[i]=(fluid_real_t)n->buf[i];
}; };
dest_buf=right_buf[ii]; dest_buf=right_buf[ii];
sprintf(str, "out%i_R",(ii+1)); sprintf(str, "out%i_R",(ii+1));
n=fluid_LADSPA_RetrieveNode(FxUnit, str); assert(n); n=fluid_LADSPA_RetrieveNode(FxUnit, str); assert(n);
@@ -826,7 +826,7 @@ fluid_LADSPA_run(fluid_LADSPA_FxUnit_t* FxUnit, fluid_real_t* left_buf[], fluid_
}; };
}; };
fluid_LADSPA_Node_t* fluid_LADSPA_Node_t*
fluid_LADSPA_RetrieveNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name){ fluid_LADSPA_RetrieveNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name){
int i=0; int i=0;
assert(FxUnit);assert(Name); assert(FxUnit);assert(Name);
@@ -840,12 +840,12 @@ fluid_LADSPA_RetrieveNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name){
}; };
/* Purpose: /* Purpose:
* Creates a new node from the node name given by the user. * Creates a new node from the node name given by the user.
*/ */
fluid_LADSPA_Node_t* fluid_LADSPA_Node_t*
fluid_LADSPA_CreateNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name, int flags){ fluid_LADSPA_CreateNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name, int flags){
int Dummy=0; int Dummy=0;
fluid_LADSPA_Node_t* NewNode; fluid_LADSPA_Node_t* NewNode;
assert(FxUnit); assert(FxUnit);
assert(Name); assert(Name);
@@ -858,7 +858,7 @@ fluid_LADSPA_CreateNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name, int flags){
fluid_LADSPA_clear(FxUnit); fluid_LADSPA_clear(FxUnit);
return NULL; return NULL;
}; };
/* Don't allow node names, which start with -, 0..9 */ /* Don't allow node names, which start with -, 0..9 */
if (Name[0] == '-' || (Name[0]>='0' && Name[0]<='9')){ if (Name[0] == '-' || (Name[0]>='0' && Name[0]<='9')){
printf( "***Error026***\n" printf( "***Error026***\n"
@@ -870,7 +870,7 @@ fluid_LADSPA_CreateNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name, int flags){
fluid_LADSPA_clear(FxUnit); fluid_LADSPA_clear(FxUnit);
return NULL; return NULL;
}; };
/* A nodename starting with "_" is a possible dummy node, which may (but need not) act as a data sink or source (dummy node). */ /* A nodename starting with "_" is a possible dummy node, which may (but need not) act as a data sink or source (dummy node). */
if (Name[0] == ' '){ /* ??? Should be '_' ??? */ if (Name[0] == ' '){ /* ??? Should be '_' ??? */
Dummy=1; Dummy=1;
@@ -880,7 +880,7 @@ fluid_LADSPA_CreateNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name, int flags){
/* Audio node contains buffer. */ /* Audio node contains buffer. */
NewNode->buf=FLUID_ARRAY(LADSPA_Data, (FLUID_BUFSIZE));assert(NewNode->buf); NewNode->buf=FLUID_ARRAY(LADSPA_Data, (FLUID_BUFSIZE));assert(NewNode->buf);
/* It is permitted to use a dummy node without input. Therefore clear all node buffers at startup. */ /* It is permitted to use a dummy node without input. Therefore clear all node buffers at startup. */
FLUID_MEMSET(NewNode->buf, 0, (FLUID_BUFSIZE*sizeof(LADSPA_Data))); FLUID_MEMSET(NewNode->buf, 0, (FLUID_BUFSIZE*sizeof(LADSPA_Data)));
} else if (flags & fluid_LADSPA_node_is_control){ } else if (flags & fluid_LADSPA_node_is_control){
/* Control node contains single value. */ /* Control node contains single value. */
NewNode->buf=FLUID_ARRAY(LADSPA_Data, 1);assert(NewNode->buf); NewNode->buf=FLUID_ARRAY(LADSPA_Data, 1);assert(NewNode->buf);
@@ -939,7 +939,7 @@ void fluid_LADSPA_clear(fluid_LADSPA_FxUnit_t* FxUnit){
FLUID_FREE(FxUnit->UserControlNodeNames[i]); FLUID_FREE(FxUnit->UserControlNodeNames[i]);
}; };
FxUnit->NumberUserControlNodes=0; FxUnit->NumberUserControlNodes=0;
L(printf("Clear all plugin instances")); L(printf("Clear all plugin instances"));
for (i=0; i<FxUnit->NumberPlugins; i++){ for (i=0; i<FxUnit->NumberPlugins; i++){
assert(FxUnit->PluginDescriptorTable[i]); assert(FxUnit->PluginDescriptorTable[i]);
@@ -952,14 +952,14 @@ void fluid_LADSPA_clear(fluid_LADSPA_FxUnit_t* FxUnit){
FxUnit->PluginDescriptorTable[i]->cleanup(FxUnit->PluginInstanceTable[i]); FxUnit->PluginDescriptorTable[i]->cleanup(FxUnit->PluginInstanceTable[i]);
}; };
FxUnit->NumberPlugins=0; FxUnit->NumberPlugins=0;
L(printf("Clear all nodes")); /* Only after removing plugins! */ L(printf("Clear all nodes")); /* Only after removing plugins! */
for (i=0; i<FxUnit->NumberNodes; i++){ for (i=0; i<FxUnit->NumberNodes; i++){
FLUID_FREE(FxUnit->Nodelist[i]->buf); FLUID_FREE(FxUnit->Nodelist[i]->buf);
FLUID_FREE(FxUnit->Nodelist[i]); FLUID_FREE(FxUnit->Nodelist[i]);
}; };
FxUnit->NumberNodes=0; FxUnit->NumberNodes=0;
L(printf("Clear all plugin libraries")); L(printf("Clear all plugin libraries"));
for (i=0; i<FxUnit->NumberLibs; i++){ for (i=0; i<FxUnit->NumberLibs; i++){
@@ -1012,7 +1012,7 @@ int fluid_LADSPA_handle_add(fluid_synth_t* synth, int ac, char** av, fluid_ostre
fluid_LADSPA_clear(FxUnit); fluid_LADSPA_clear(FxUnit);
return(PrintErrorMessage); return(PrintErrorMessage);
}; };
/* CommandLine (token sequence) is terminated with NULL. /* CommandLine (token sequence) is terminated with NULL.
* Add two more NULLs, so that a chunk of three tokens can be checked later without risk.*/ * Add two more NULLs, so that a chunk of three tokens can be checked later without risk.*/
@@ -1052,7 +1052,7 @@ int fluid_LADSPA_handle_declnode(fluid_synth_t* synth, int ac, char** av, fluid_
fluid_LADSPA_clear(FxUnit); fluid_LADSPA_clear(FxUnit);
return(PrintErrorMessage); return(PrintErrorMessage);
}; };
NodeName=FLUID_STRDUP(av[0]); assert(NodeName); NodeName=FLUID_STRDUP(av[0]); assert(NodeName);
NodeValue=atof(av[1]); NodeValue=atof(av[1]);
FxUnit->UserControlNodeNames[FxUnit->NumberUserControlNodes]=NodeName; FxUnit->UserControlNodeNames[FxUnit->NumberUserControlNodes]=NodeName;
+18 -18
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -79,7 +79,7 @@ typedef enum {
fluid_LADSPA_node_is_user_ctrl=32 fluid_LADSPA_node_is_user_ctrl=32
} fluid_LADSPA_nodeflags; } fluid_LADSPA_nodeflags;
/* fluid_LADSPA_Node_t /* fluid_LADSPA_Node_t
* An internal node of the Fx unit. * An internal node of the Fx unit.
* A 'node' is the 'glue' that connects several LADSPA plugins. * A 'node' is the 'glue' that connects several LADSPA plugins.
* Basically it's a real-valued variable (control node) or a real-valued buffer (audio node). * Basically it's a real-valued variable (control node) or a real-valued buffer (audio node).
@@ -107,11 +107,11 @@ typedef struct {
int NumberLibs; int NumberLibs;
void * ppvPluginLibs[FLUID_LADSPA_MaxLibs]; void * ppvPluginLibs[FLUID_LADSPA_MaxLibs];
char * ppvPluginLibNames[FLUID_LADSPA_MaxLibs]; char * ppvPluginLibNames[FLUID_LADSPA_MaxLibs];
/*List of plugins (descriptor and instance) /*List of plugins (descriptor and instance)
* A LADSPA plugin descriptor points to the code, which is executed, when a plugin is run. * A LADSPA plugin descriptor points to the code, which is executed, when a plugin is run.
* The plugin instance is given as a parameter, when calling. * The plugin instance is given as a parameter, when calling.
*/ */
int NumberPlugins; int NumberPlugins;
const LADSPA_Descriptor * PluginDescriptorTable[FLUID_LADSPA_MaxPlugins]; const LADSPA_Descriptor * PluginDescriptorTable[FLUID_LADSPA_MaxPlugins];
LADSPA_Handle * PluginInstanceTable[FLUID_LADSPA_MaxPlugins]; LADSPA_Handle * PluginInstanceTable[FLUID_LADSPA_MaxPlugins];
@@ -119,12 +119,12 @@ typedef struct {
/* List of nodes */ /* List of nodes */
int NumberNodes; int NumberNodes;
fluid_LADSPA_Node_t * Nodelist[FLUID_LADSPA_MaxNodes]; fluid_LADSPA_Node_t * Nodelist[FLUID_LADSPA_MaxNodes];
/* List of Command lines /* List of Command lines
* During the setup phase, each ladspa_add command creates one command sequence. For example: * During the setup phase, each ladspa_add command creates one command sequence. For example:
* ./aw.so alienwah_stereo Input <- Master_L_Synth Output -> Master_R_Synth Parameter <- #42.0 * ./aw.so alienwah_stereo Input <- Master_L_Synth Output -> Master_R_Synth Parameter <- #42.0
* Those lists are stored in LADSPA_Command_Sequence. * Those lists are stored in LADSPA_Command_Sequence.
* One command line results in one plugin => size MaxPlugins. * One command line results in one plugin => size MaxPlugins.
*/ */
int NumberCommands; int NumberCommands;
char ** LADSPA_Command_Sequence[FLUID_LADSPA_MaxPlugins]; char ** LADSPA_Command_Sequence[FLUID_LADSPA_MaxPlugins];
@@ -138,11 +138,11 @@ typedef struct {
/* Bypass switch /* Bypass switch
* If set, the LADSPA Fx unit does not touch the signal.*/ * If set, the LADSPA Fx unit does not touch the signal.*/
fluid_LADSPA_BypassState Bypass; fluid_LADSPA_BypassState Bypass;
/* Communication between the 'command line' process and the synthesis process. /* Communication between the 'command line' process and the synthesis process.
* A possible conflict situation arises, when fluid_clear is called, and starts to destroy * A possible conflict situation arises, when fluid_clear is called, and starts to destroy
* the plugins. But the synthesis thread still processes plugins at the same time. The consequences are ugly. * the plugins. But the synthesis thread still processes plugins at the same time. The consequences are ugly.
* Therefore ladspa_clear waits for acknowledgement from the synthesis thread, that the Fx unit is bypassed. * Therefore ladspa_clear waits for acknowledgement from the synthesis thread, that the Fx unit is bypassed.
* 'cond' is used for the communication, the mutex is required for changing the condition. * 'cond' is used for the communication, the mutex is required for changing the condition.
*/ */
@@ -168,13 +168,13 @@ fluid_LADSPA_FxUnit_t* new_fluid_LADSPA_FxUnit(fluid_synth_t* synth);
*/ */
void fluid_LADSPA_run(fluid_LADSPA_FxUnit_t* Fx_unit, fluid_real_t* left_buf[], fluid_real_t* right_buf[], fluid_real_t* fx_left_buf[], fluid_real_t* fx_right_buf[]); void fluid_LADSPA_run(fluid_LADSPA_FxUnit_t* Fx_unit, fluid_real_t* left_buf[], fluid_real_t* right_buf[], fluid_real_t* fx_left_buf[], fluid_real_t* fx_right_buf[]);
/* Purpose: /* Purpose:
* Returns the node belonging to Name or NULL, if not found * Returns the node belonging to Name or NULL, if not found
*/ */
fluid_LADSPA_Node_t* fluid_LADSPA_RetrieveNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name); fluid_LADSPA_Node_t* fluid_LADSPA_RetrieveNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name);
/* Purpose: /* Purpose:
* Creates a new node with the given characteristics. * Creates a new node with the given characteristics.
*/ */
fluid_LADSPA_Node_t* fluid_LADSPA_CreateNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name, int flags); fluid_LADSPA_Node_t* fluid_LADSPA_CreateNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name, int flags);
@@ -196,8 +196,8 @@ void fluid_LADSPA_shutdown(fluid_LADSPA_FxUnit_t* FxUnit);
/* /*
* fluid_handle_LADSPA_XXX * fluid_handle_LADSPA_XXX
* Those functions are called from fluid_cmd, when a command is entered on the command line. * Those functions are called from fluid_cmd, when a command is entered on the command line.
*/ */
/* Purpose: /* Purpose:
@@ -226,12 +226,12 @@ int fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ost
int fluid_LADSPA_handle_add(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out); int fluid_LADSPA_handle_add(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out);
/* Purpose: /* Purpose:
* Declares a user control node and a value; for further processing in ladspa_start. * Declares a user control node and a value; for further processing in ladspa_start.
*/ */
int fluid_LADSPA_handle_declnode(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out); int fluid_LADSPA_handle_declnode(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out);
/* Purpose: /* Purpose:
* Assigns a value to the a user control node * Assigns a value to the a user control node
*/ */
int fluid_LADSPA_handle_setnode(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out); int fluid_LADSPA_handle_setnode(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out);
+20 -20
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -73,7 +73,7 @@ fluid_lash_save (fluid_synth_t * synth)
fluid_sfont_t * sfont; fluid_sfont_t * sfont;
lash_config_t * config; lash_config_t * config;
char num[32]; char num[32];
sfcount = fluid_synth_sfcount (synth); sfcount = fluid_synth_sfcount (synth);
config = lash_config_new (); config = lash_config_new ();
@@ -85,12 +85,12 @@ fluid_lash_save (fluid_synth_t * synth)
{ {
sfont = fluid_synth_get_sfont (synth, i); sfont = fluid_synth_get_sfont (synth, i);
config = lash_config_new (); config = lash_config_new ();
sprintf (num, "%d", i); sprintf (num, "%d", i);
lash_config_set_key (config, num); lash_config_set_key (config, num);
lash_config_set_value_string (config, sfont->get_name (sfont)); lash_config_set_value_string (config, sfont->get_name (sfont));
lash_send_config (fluid_lash_client, config); lash_send_config (fluid_lash_client, config);
} }
} }
@@ -110,11 +110,11 @@ fluid_lash_run (void * data)
int done = 0; int done = 0;
int err; int err;
int pending_restores = 0; int pending_restores = 0;
synth = (fluid_synth_t *) data; synth = (fluid_synth_t *) data;
while (!done) while (!done)
{ {
while ( (event = lash_get_event (fluid_lash_client)) ) while ( (event = lash_get_event (fluid_lash_client)) )
{ {
switch (lash_event_get_type (event)) switch (lash_event_get_type (event))
@@ -144,7 +144,7 @@ fluid_lash_run (void * data)
break; break;
} }
} }
while ( (config = lash_get_config (fluid_lash_client)) ) while ( (config = lash_get_config (fluid_lash_client)) )
{ {
if (strcmp (lash_config_get_key (config), "soundfont count") == 0) if (strcmp (lash_config_get_key (config), "soundfont count") == 0)
@@ -162,10 +162,10 @@ fluid_lash_run (void * data)
lash_send_event (fluid_lash_client, event); lash_send_event (fluid_lash_client, event);
} }
} }
usleep (10000); usleep (10000);
} }
return NULL; return NULL;
} }
@@ -200,7 +200,7 @@ fluid_lash_save (fluid_synth_t * synth)
fluid_sfont_t * sfont; fluid_sfont_t * sfont;
cca_config_t * config; cca_config_t * config;
char num[32]; char num[32];
sfcount = fluid_synth_sfcount (synth); sfcount = fluid_synth_sfcount (synth);
config = cca_config_new (); config = cca_config_new ();
@@ -212,12 +212,12 @@ fluid_lash_save (fluid_synth_t * synth)
{ {
sfont = fluid_synth_get_sfont (synth, i); sfont = fluid_synth_get_sfont (synth, i);
config = cca_config_new (); config = cca_config_new ();
sprintf (num, "%d", i); sprintf (num, "%d", i);
cca_config_set_key (config, num); cca_config_set_key (config, num);
cca_config_set_value_string (config, sfont->get_name (sfont)); cca_config_set_value_string (config, sfont->get_name (sfont));
cca_send_config (fluid_lash_client, config); cca_send_config (fluid_lash_client, config);
} }
} }
@@ -238,9 +238,9 @@ fluid_lash_run (void * data)
int done = 0; int done = 0;
int err; int err;
int pending_restores = 0; int pending_restores = 0;
synth = (fluid_synth_t *) data; synth = (fluid_synth_t *) data;
while (!done) while (!done)
{ {
while ( (event = cca_get_event (fluid_lash_client)) ) while ( (event = cca_get_event (fluid_lash_client)) )
@@ -272,7 +272,7 @@ fluid_lash_run (void * data)
break; break;
} }
} }
while ( (config = cca_get_config (fluid_lash_client)) ) while ( (config = cca_get_config (fluid_lash_client)) )
{ {
if (strcmp (cca_config_get_key (config), "soundfont count") == 0) if (strcmp (cca_config_get_key (config), "soundfont count") == 0)
@@ -290,10 +290,10 @@ fluid_lash_run (void * data)
cca_send_event (fluid_lash_client, event); cca_send_event (fluid_lash_client, event);
} }
} }
usleep (10000); usleep (10000);
} }
return NULL; return NULL;
} }
+3 -1
View File
@@ -11,13 +11,15 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307, USA * 02111-1307, USA
*/ */
#if HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif
#if defined(HAVE_LASH) || defined(HAVE_LADCCA) #if defined(HAVE_LASH) || defined(HAVE_LADCCA)
+13 -13
View File
@@ -21,7 +21,7 @@
* Modified by the GLib Team and others 1997-1999. See the AUTHORS * Modified by the GLib Team and others 1997-1999. See the AUTHORS
* file for a list of people on the GLib Team. See the ChangeLog * file for a list of people on the GLib Team. See the ChangeLog
* files for a list of changes. These files are distributed with * files for a list of changes. These files are distributed with
* GLib at ftp://ftp.gtk.org/pub/gtk/. * GLib at ftp://ftp.gtk.org/pub/gtk/.
*/ */
@@ -120,10 +120,10 @@ fluid_list_remove(fluid_list_t *list, void* data)
} }
tmp->next = NULL; tmp->next = NULL;
delete_fluid_list(tmp); delete_fluid_list(tmp);
break; break;
} }
prev = tmp; prev = tmp;
tmp = tmp->next; tmp = tmp->next;
} }
@@ -151,15 +151,15 @@ fluid_list_remove_link(fluid_list_t *list, fluid_list_t *link)
tmp->next = NULL; tmp->next = NULL;
break; break;
} }
prev = tmp; prev = tmp;
tmp = tmp->next; tmp = tmp->next;
} }
return list; return list;
} }
static fluid_list_t* static fluid_list_t*
fluid_list_sort_merge(fluid_list_t *l1, fluid_list_t *l2, fluid_compare_func_t compare_func) fluid_list_sort_merge(fluid_list_t *l1, fluid_list_t *l2, fluid_compare_func_t compare_func)
{ {
fluid_list_t list, *l; fluid_list_t list, *l;
@@ -176,11 +176,11 @@ fluid_list_sort_merge(fluid_list_t *l1, fluid_list_t *l2, fluid_compare_func_t c
} }
} }
l->next= l1 ? l1 : l2; l->next= l1 ? l1 : l2;
return list.next; return list.next;
} }
fluid_list_t* fluid_list_t*
fluid_list_sort(fluid_list_t *list, fluid_compare_func_t compare_func) fluid_list_sort(fluid_list_t *list, fluid_compare_func_t compare_func)
{ {
fluid_list_t *l1, *l2; fluid_list_t *l1, *l2;
@@ -192,15 +192,15 @@ fluid_list_sort(fluid_list_t *list, fluid_compare_func_t compare_func)
return list; return list;
} }
l1 = list; l1 = list;
l2 = list->next; l2 = list->next;
while ((l2 = l2->next) != NULL) { while ((l2 = l2->next) != NULL) {
if ((l2 = l2->next) == NULL) if ((l2 = l2->next) == NULL)
break; break;
l1=l1->next; l1=l1->next;
} }
l2 = l1->next; l2 = l1->next;
l1->next = NULL; l1->next = NULL;
return fluid_list_sort_merge(fluid_list_sort(list, compare_func), return fluid_list_sort_merge(fluid_list_sort(list, compare_func),
@@ -220,7 +220,7 @@ fluid_list_last(fluid_list_t *list)
return list; return list;
} }
int int
fluid_list_size(fluid_list_t *list) fluid_list_size(fluid_list_t *list)
{ {
int n = 0; int n = 0;
@@ -249,7 +249,7 @@ fluid_list_t* fluid_list_insert_at(fluid_list_t *list, int n, void* data)
new_list->next = cur; new_list->next = cur;
if (prev) { if (prev) {
prev->next = new_list; prev->next = new_list;
return list; return list;
} else { } else {
return new_list; return new_list;
+38 -27
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -25,13 +25,13 @@
/* ALSA */ /* ALSA */
#if ALSA_SUPPORT #if ALSA_SUPPORT
fluid_midi_driver_t* new_fluid_alsa_rawmidi_driver(fluid_settings_t* settings, fluid_midi_driver_t* new_fluid_alsa_rawmidi_driver(fluid_settings_t* settings,
handle_midi_event_func_t handler, handle_midi_event_func_t handler,
void* event_handler_data); void* event_handler_data);
int delete_fluid_alsa_rawmidi_driver(fluid_midi_driver_t* p); int delete_fluid_alsa_rawmidi_driver(fluid_midi_driver_t* p);
void fluid_alsa_rawmidi_driver_settings(fluid_settings_t* settings); void fluid_alsa_rawmidi_driver_settings(fluid_settings_t* settings);
fluid_midi_driver_t* new_fluid_alsa_seq_driver(fluid_settings_t* settings, fluid_midi_driver_t* new_fluid_alsa_seq_driver(fluid_settings_t* settings,
handle_midi_event_func_t handler, handle_midi_event_func_t handler,
void* event_handler_data); void* event_handler_data);
int delete_fluid_alsa_seq_driver(fluid_midi_driver_t* p); int delete_fluid_alsa_seq_driver(fluid_midi_driver_t* p);
void fluid_alsa_seq_driver_settings(fluid_settings_t* settings); void fluid_alsa_seq_driver_settings(fluid_settings_t* settings);
@@ -40,7 +40,7 @@ void fluid_alsa_seq_driver_settings(fluid_settings_t* settings);
/* OSS */ /* OSS */
#if OSS_SUPPORT #if OSS_SUPPORT
fluid_midi_driver_t* new_fluid_oss_midi_driver(fluid_settings_t* settings, fluid_midi_driver_t* new_fluid_oss_midi_driver(fluid_settings_t* settings,
handle_midi_event_func_t handler, handle_midi_event_func_t handler,
void* event_handler_data); void* event_handler_data);
int delete_fluid_oss_midi_driver(fluid_midi_driver_t* p); int delete_fluid_oss_midi_driver(fluid_midi_driver_t* p);
void fluid_oss_midi_driver_settings(fluid_settings_t* settings); void fluid_oss_midi_driver_settings(fluid_settings_t* settings);
@@ -49,7 +49,7 @@ void fluid_oss_midi_driver_settings(fluid_settings_t* settings);
/* Windows MIDI service */ /* Windows MIDI service */
#if WINMIDI_SUPPORT #if WINMIDI_SUPPORT
fluid_midi_driver_t* new_fluid_winmidi_driver(fluid_settings_t* settings, fluid_midi_driver_t* new_fluid_winmidi_driver(fluid_settings_t* settings,
handle_midi_event_func_t handler, handle_midi_event_func_t handler,
void* event_handler_data); void* event_handler_data);
int delete_fluid_winmidi_driver(fluid_midi_driver_t* p); int delete_fluid_winmidi_driver(fluid_midi_driver_t* p);
#endif #endif
@@ -57,7 +57,7 @@ int delete_fluid_winmidi_driver(fluid_midi_driver_t* p);
/* definitions for the MidiShare driver */ /* definitions for the MidiShare driver */
#if MIDISHARE_SUPPORT #if MIDISHARE_SUPPORT
fluid_midi_driver_t* new_fluid_midishare_midi_driver(fluid_settings_t* settings, fluid_midi_driver_t* new_fluid_midishare_midi_driver(fluid_settings_t* settings,
void* event_handler_data, void* event_handler_data,
handle_midi_event_func_t handler); handle_midi_event_func_t handler);
int delete_fluid_midishare_midi_driver(fluid_midi_driver_t* p); int delete_fluid_midishare_midi_driver(fluid_midi_driver_t* p);
#endif #endif
@@ -69,8 +69,8 @@ int delete_fluid_midishare_midi_driver(fluid_midi_driver_t* p);
*/ */
struct fluid_mdriver_definition_t { struct fluid_mdriver_definition_t {
char* name; char* name;
fluid_midi_driver_t* (*new)(fluid_settings_t* settings, fluid_midi_driver_t* (*new)(fluid_settings_t* settings,
handle_midi_event_func_t event_handler, handle_midi_event_func_t event_handler,
void* event_handler_data); void* event_handler_data);
int (*free)(fluid_midi_driver_t* p); int (*free)(fluid_midi_driver_t* p);
void (*settings)(fluid_settings_t* settings); void (*settings)(fluid_settings_t* settings);
@@ -79,31 +79,31 @@ struct fluid_mdriver_definition_t {
struct fluid_mdriver_definition_t fluid_midi_drivers[] = { struct fluid_mdriver_definition_t fluid_midi_drivers[] = {
#if OSS_SUPPORT #if OSS_SUPPORT
{ "oss", { "oss",
new_fluid_oss_midi_driver, new_fluid_oss_midi_driver,
delete_fluid_oss_midi_driver, delete_fluid_oss_midi_driver,
fluid_oss_midi_driver_settings }, fluid_oss_midi_driver_settings },
#endif #endif
#if ALSA_SUPPORT #if ALSA_SUPPORT
{ "alsa_raw", { "alsa_raw",
new_fluid_alsa_rawmidi_driver, new_fluid_alsa_rawmidi_driver,
delete_fluid_alsa_rawmidi_driver, delete_fluid_alsa_rawmidi_driver,
fluid_alsa_rawmidi_driver_settings }, fluid_alsa_rawmidi_driver_settings },
{ "alsa_seq", { "alsa_seq",
new_fluid_alsa_seq_driver, new_fluid_alsa_seq_driver,
delete_fluid_alsa_seq_driver, delete_fluid_alsa_seq_driver,
fluid_alsa_seq_driver_settings }, fluid_alsa_seq_driver_settings },
#endif #endif
#if WINMIDI_SUPPORT #if WINMIDI_SUPPORT
{ "winmidi", { "winmidi",
new_fluid_winmidi_driver, new_fluid_winmidi_driver,
delete_fluid_winmidi_driver, delete_fluid_winmidi_driver,
NULL }, NULL },
#endif #endif
#if MIDISHARE_SUPPORT #if MIDISHARE_SUPPORT
{ "midishare", { "midishare",
new_fluid_midishare_midi_driver, new_fluid_midishare_midi_driver,
delete_fluid_midishare_midi_driver, delete_fluid_midishare_midi_driver,
NULL }, NULL },
#endif #endif
{ NULL, NULL, NULL, NULL } { NULL, NULL, NULL, NULL }
@@ -112,7 +112,7 @@ struct fluid_mdriver_definition_t fluid_midi_drivers[] = {
void fluid_midi_driver_settings(fluid_settings_t* settings) void fluid_midi_driver_settings(fluid_settings_t* settings)
{ {
int i; int i;
/* Set the default driver */ /* Set the default driver */
@@ -147,11 +147,18 @@ void fluid_midi_driver_settings(fluid_settings_t* settings)
if (fluid_midi_drivers[i].settings != NULL) { if (fluid_midi_drivers[i].settings != NULL) {
fluid_midi_drivers[i].settings(settings); fluid_midi_drivers[i].settings(settings);
} }
} }
} }
/**
* Create a new MIDI driver instance.
* @param settings Settings used to configure new MIDI driver.
* @param handler MIDI handler callback (for example: fluid_midi_router_handle_midi_event()
* for MIDI router)
* @param event_handler_data Caller defined data to pass to 'handler'
* @return New MIDI driver instance or NULL on error
*/
fluid_midi_driver_t* new_fluid_midi_driver(fluid_settings_t* settings, handle_midi_event_func_t handler, void* event_handler_data) fluid_midi_driver_t* new_fluid_midi_driver(fluid_settings_t* settings, handle_midi_event_func_t handler, void* event_handler_data)
{ {
int i; int i;
@@ -171,6 +178,10 @@ fluid_midi_driver_t* new_fluid_midi_driver(fluid_settings_t* settings, handle_mi
return NULL; return NULL;
} }
/**
* Delete a MIDI driver instance.
* @param driver MIDI driver to delete
*/
void delete_fluid_midi_driver(fluid_midi_driver_t* driver) void delete_fluid_midi_driver(fluid_midi_driver_t* driver)
{ {
int i; int i;
@@ -180,5 +191,5 @@ void delete_fluid_midi_driver(fluid_midi_driver_t* driver)
fluid_midi_drivers[i].free(driver); fluid_midi_drivers[i].free(driver);
return; return;
} }
} }
} }
+2 -2
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -30,7 +30,7 @@ void fluid_midi_driver_settings(fluid_settings_t* settings);
* fluid_midi_driver_t * fluid_midi_driver_t
*/ */
struct _fluid_midi_driver_t struct _fluid_midi_driver_t
{ {
char* name; char* name;
handle_midi_event_func_t handler; handle_midi_event_func_t handler;
+178 -93
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -55,8 +55,12 @@ static int remains_80e0[] = {
* *
* MIDIFILE * MIDIFILE
*/ */
/*
* new_fluid_midi_file /**
* Open a MIDI file and return a new MIDI file handle.
* @internal
* @param filename Path of file to open.
* @return New MIDI file handle or NULL on error.
*/ */
fluid_midi_file* new_fluid_midi_file(char* filename) fluid_midi_file* new_fluid_midi_file(char* filename)
{ {
@@ -76,7 +80,7 @@ fluid_midi_file* new_fluid_midi_file(char* filename)
if (mf->fp == NULL) { if (mf->fp == NULL) {
FLUID_LOG(FLUID_ERR, "Couldn't open the MIDI file"); FLUID_LOG(FLUID_ERR, "Couldn't open the MIDI file");
FLUID_FREE(mf); FLUID_FREE(mf);
return NULL; return NULL;
} }
if (fluid_midi_file_read_mthd(mf) != FLUID_OK) { if (fluid_midi_file_read_mthd(mf) != FLUID_OK) {
@@ -86,8 +90,10 @@ fluid_midi_file* new_fluid_midi_file(char* filename)
return mf; return mf;
} }
/* /**
* delete_fluid_midi_file * Delete a MIDI file handle.
* @internal
* @param mf MIDI file handle to close and free.
*/ */
void delete_fluid_midi_file(fluid_midi_file* mf) void delete_fluid_midi_file(fluid_midi_file* mf)
{ {
@@ -102,7 +108,7 @@ void delete_fluid_midi_file(fluid_midi_file* mf)
} }
/* /*
* fluid_midi_file_getc * Get the next byte in a MIDI file.
*/ */
int fluid_midi_file_getc(fluid_midi_file* mf) int fluid_midi_file_getc(fluid_midi_file* mf)
{ {
@@ -150,7 +156,7 @@ int fluid_midi_file_skip(fluid_midi_file* mf, int skip)
int err = FLUID_FSEEK(mf->fp, skip, SEEK_CUR); int err = FLUID_FSEEK(mf->fp, skip, SEEK_CUR);
if (err) { if (err) {
FLUID_LOG(FLUID_ERR, "Failed to seek position in file"); FLUID_LOG(FLUID_ERR, "Failed to seek position in file");
return FLUID_FAILED; return FLUID_FAILED;
} }
return FLUID_OK; return FLUID_OK;
} }
@@ -289,7 +295,7 @@ int fluid_midi_file_read_track(fluid_midi_file* mf, fluid_player_t* player, int
while (!fluid_midi_file_eot(mf)) { while (!fluid_midi_file_eot(mf)) {
if (fluid_midi_file_read_event(mf, track) != FLUID_OK) { if (fluid_midi_file_read_event(mf, track) != FLUID_OK) {
return FLUID_FAILED; return FLUID_FAILED;
} }
} }
@@ -318,7 +324,7 @@ int fluid_midi_file_read_track(fluid_midi_file* mf, fluid_player_t* player, int
* fluid_midi_file_read_varlen * fluid_midi_file_read_varlen
*/ */
int fluid_midi_file_read_varlen(fluid_midi_file* mf) int fluid_midi_file_read_varlen(fluid_midi_file* mf)
{ {
int i; int i;
int c; int c;
mf->varlen = 0; mf->varlen = 0;
@@ -338,7 +344,7 @@ int fluid_midi_file_read_varlen(fluid_midi_file* mf)
} else { } else {
mf->varlen += c; mf->varlen += c;
break; break;
} }
} }
return FLUID_OK; return FLUID_OK;
} }
@@ -382,7 +388,7 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track)
} }
fluid_midi_file_push(mf, status); fluid_midi_file_push(mf, status);
status = mf->running_status; status = mf->running_status;
} }
/* check what message we have */ /* check what message we have */
if (status & 0x80) { if (status & 0x80) {
@@ -426,7 +432,7 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track)
} }
return FLUID_OK; return FLUID_OK;
} else if (status == MIDI_META_EVENT) { /* meta events */ } else if (status == MIDI_META_EVENT) { /* meta events */
int result = FLUID_OK; int result = FLUID_OK;
@@ -498,7 +504,7 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track)
break; break;
} }
mf->eot = 1; mf->eot = 1;
break; break;
case MIDI_SET_TEMPO: case MIDI_SET_TEMPO:
if (mf->varlen != 3) { if (mf->varlen != 3) {
@@ -519,7 +525,7 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track)
evt->param1 = tempo; evt->param1 = tempo;
evt->param2 = 0; evt->param2 = 0;
fluid_track_add_event(track, evt); fluid_track_add_event(track, evt);
break; break;
case MIDI_SMPTE_OFFSET: case MIDI_SMPTE_OFFSET:
if (mf->varlen != 5) { if (mf->varlen != 5) {
@@ -527,7 +533,7 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track)
result = FLUID_FAILED; result = FLUID_FAILED;
break; break;
} }
break; /* we don't use smtp */ break; /* we don't use smtp */
case MIDI_TIME_SIGNATURE: case MIDI_TIME_SIGNATURE:
if (mf->varlen != 4) { if (mf->varlen != 4) {
@@ -540,7 +546,7 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track)
clocks = metadata[2]; clocks = metadata[2];
notes = metadata[3]; notes = metadata[3];
FLUID_LOG(FLUID_DBG, "signature=%d/%d, metronome=%d, 32nd-notes=%d", FLUID_LOG(FLUID_DBG, "signature=%d/%d, metronome=%d, 32nd-notes=%d",
nominator, denominator, clocks, notes); nominator, denominator, clocks, notes);
break; break;
@@ -568,7 +574,7 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track)
} }
return result; return result;
} else { /* channel messages */ } else { /* channel messages */
type = status & 0xf0; type = status & 0xf0;
@@ -589,7 +595,7 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track)
} }
break; break;
case NOTE_OFF: case NOTE_OFF:
if ((param2 = fluid_midi_file_getc(mf)) < 0) { if ((param2 = fluid_midi_file_getc(mf)) < 0) {
FLUID_LOG(FLUID_ERR, "Unexpected end of file"); FLUID_LOG(FLUID_ERR, "Unexpected end of file");
return FLUID_FAILED; return FLUID_FAILED;
@@ -629,7 +635,7 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track)
default: default:
/* Can't possibly happen !? */ /* Can't possibly happen !? */
FLUID_LOG(FLUID_ERR, "Unrecognized MIDI event"); FLUID_LOG(FLUID_ERR, "Unrecognized MIDI event");
return FLUID_FAILED; return FLUID_FAILED;
} }
evt = new_fluid_midi_event(); evt = new_fluid_midi_event();
if (evt == NULL) { if (evt == NULL) {
@@ -660,8 +666,9 @@ int fluid_midi_file_get_division(fluid_midi_file* midifile)
* fluid_track_t * fluid_track_t
*/ */
/* /**
* new_fluid_midi_event * Create a MIDI event structure.
* @return New MIDI event structure or NULL when out of memory.
*/ */
fluid_midi_event_t* new_fluid_midi_event() fluid_midi_event_t* new_fluid_midi_event()
{ {
@@ -680,8 +687,10 @@ fluid_midi_event_t* new_fluid_midi_event()
return evt; return evt;
} }
/* /**
* delete_fluid_midi_event * Delete MIDI event structure.
* @param evt MIDI event structure
* @return Always returns 0
*/ */
int delete_fluid_midi_event(fluid_midi_event_t* evt) int delete_fluid_midi_event(fluid_midi_event_t* evt)
{ {
@@ -696,16 +705,23 @@ int delete_fluid_midi_event(fluid_midi_event_t* evt)
return FLUID_OK; return FLUID_OK;
} }
/* /**
* fluid_midi_event_get_type * Get the event type field of a MIDI event structure.
* DOCME - Event type enum appears to be internal (fluid_midi.h)
* @param evt MIDI event structure
* @return Event type field
*/ */
int fluid_midi_event_get_type(fluid_midi_event_t* evt) int fluid_midi_event_get_type(fluid_midi_event_t* evt)
{ {
return evt->type; return evt->type;
} }
/* /**
* fluid_midi_event_set_type * Set the event type field of a MIDI event structure.
* DOCME - Event type enum appears to be internal (fluid_midi.h)
* @param evt MIDI event structure
* @param type Event type field
* @return Always returns 0
*/ */
int fluid_midi_event_set_type(fluid_midi_event_t* evt, int type) int fluid_midi_event_set_type(fluid_midi_event_t* evt, int type)
{ {
@@ -713,16 +729,21 @@ int fluid_midi_event_set_type(fluid_midi_event_t* evt, int type)
return FLUID_OK; return FLUID_OK;
} }
/* /**
* fluid_midi_event_get_channel * Get the channel field of a MIDI event structure.
* @param evt MIDI event structure
* @return Channel field
*/ */
int fluid_midi_event_get_channel(fluid_midi_event_t* evt) int fluid_midi_event_get_channel(fluid_midi_event_t* evt)
{ {
return evt->channel; return evt->channel;
} }
/* /**
* fluid_midi_event_set_channel * Set the channel field of a MIDI event structure.
* @param evt MIDI event structure
* @param chan MIDI channel field
* @return Always returns 0
*/ */
int fluid_midi_event_set_channel(fluid_midi_event_t* evt, int chan) int fluid_midi_event_set_channel(fluid_midi_event_t* evt, int chan)
{ {
@@ -730,16 +751,21 @@ int fluid_midi_event_set_channel(fluid_midi_event_t* evt, int chan)
return FLUID_OK; return FLUID_OK;
} }
/* /**
* fluid_midi_event_get_key * Get the key field of a MIDI event structure.
* @param evt MIDI event structure
* @return MIDI note number (0-127)
*/ */
int fluid_midi_event_get_key(fluid_midi_event_t* evt) int fluid_midi_event_get_key(fluid_midi_event_t* evt)
{ {
return evt->param1; return evt->param1;
} }
/* /**
* fluid_midi_event_set_key * Set the key field of a MIDI event structure.
* @param evt MIDI event structure
* @param v MIDI note number (0-127)
* @return Always returns 0
*/ */
int fluid_midi_event_set_key(fluid_midi_event_t* evt, int v) int fluid_midi_event_set_key(fluid_midi_event_t* evt, int v)
{ {
@@ -747,16 +773,21 @@ int fluid_midi_event_set_key(fluid_midi_event_t* evt, int v)
return FLUID_OK; return FLUID_OK;
} }
/* /**
* fluid_midi_event_get_velocity * Get the velocity field of a MIDI event structure.
* @param evt MIDI event structure
* @return MIDI velocity number (0-127)
*/ */
int fluid_midi_event_get_velocity(fluid_midi_event_t* evt) int fluid_midi_event_get_velocity(fluid_midi_event_t* evt)
{ {
return evt->param2; return evt->param2;
} }
/* /**
* fluid_midi_event_set_velocity * Set the velocity field of a MIDI event structure.
* @param evt MIDI event structure
* @param v MIDI velocity value
* @return Always returns 0
*/ */
int fluid_midi_event_set_velocity(fluid_midi_event_t* evt, int v) int fluid_midi_event_set_velocity(fluid_midi_event_t* evt, int v)
{ {
@@ -764,16 +795,21 @@ int fluid_midi_event_set_velocity(fluid_midi_event_t* evt, int v)
return FLUID_OK; return FLUID_OK;
} }
/* /**
* fluid_midi_event_get_control * Get the control number of a MIDI event structure.
* @param evt MIDI event structure
* @return MIDI control number
*/ */
int fluid_midi_event_get_control(fluid_midi_event_t* evt) int fluid_midi_event_get_control(fluid_midi_event_t* evt)
{ {
return evt->param1; return evt->param1;
} }
/* /**
* fluid_midi_event_set_control * Set the control field of a MIDI event structure.
* @param evt MIDI event structure
* @param v MIDI control number
* @return Always returns 0
*/ */
int fluid_midi_event_set_control(fluid_midi_event_t* evt, int v) int fluid_midi_event_set_control(fluid_midi_event_t* evt, int v)
{ {
@@ -781,16 +817,21 @@ int fluid_midi_event_set_control(fluid_midi_event_t* evt, int v)
return FLUID_OK; return FLUID_OK;
} }
/* /**
* fluid_midi_event_get_value * Get the value field from a MIDI event structure.
* @param evt MIDI event structure
* @return Value field
*/ */
int fluid_midi_event_get_value(fluid_midi_event_t* evt) int fluid_midi_event_get_value(fluid_midi_event_t* evt)
{ {
return evt->param2; return evt->param2;
} }
/* /**
* fluid_midi_event_set_value * Set the value field of a MIDI event structure.
* @param evt MIDI event structure
* @param v Value to assign
* @return Always returns 0
*/ */
int fluid_midi_event_set_value(fluid_midi_event_t* evt, int v) int fluid_midi_event_set_value(fluid_midi_event_t* evt, int v)
{ {
@@ -798,22 +839,44 @@ int fluid_midi_event_set_value(fluid_midi_event_t* evt, int v)
return FLUID_OK; return FLUID_OK;
} }
/**
* Get the program field of a MIDI event structure.
* @param evt MIDI event structure
* @return MIDI program number (0-127)
*/
int fluid_midi_event_get_program(fluid_midi_event_t* evt) int fluid_midi_event_get_program(fluid_midi_event_t* evt)
{ {
return evt->param1; return evt->param1;
} }
/**
* Set the program field of a MIDI event structure.
* @param evt MIDI event structure
* @param val MIDI program number (0-127)
* @return Always returns 0
*/
int fluid_midi_event_set_program(fluid_midi_event_t* evt, int val) int fluid_midi_event_set_program(fluid_midi_event_t* evt, int val)
{ {
evt->param1 = val; evt->param1 = val;
return FLUID_OK; return FLUID_OK;
} }
/**
* Get the pitch field of a MIDI event structure.
* @param evt MIDI event structure
* @return Pitch value (DOCME units?)
*/
int fluid_midi_event_get_pitch(fluid_midi_event_t* evt) int fluid_midi_event_get_pitch(fluid_midi_event_t* evt)
{ {
return evt->param1; return evt->param1;
} }
/**
* Set the pitch field of a MIDI event structure.
* @param evt MIDI event structure
* @param val Pitch value (DOCME units?)
* @return Always returns 0
*/
int fluid_midi_event_set_pitch(fluid_midi_event_t* evt, int val) int fluid_midi_event_set_pitch(fluid_midi_event_t* evt, int val)
{ {
evt->param1 = val; evt->param1 = val;
@@ -904,7 +967,7 @@ int fluid_track_set_name(fluid_track_t* track, char* name)
} }
if (name == NULL) { if (name == NULL) {
track->name = NULL; track->name = NULL;
return FLUID_OK; return FLUID_OK;
} }
len = FLUID_STRLEN(name); len = FLUID_STRLEN(name);
track->name = FLUID_MALLOC(len + 1); track->name = FLUID_MALLOC(len + 1);
@@ -913,7 +976,7 @@ int fluid_track_set_name(fluid_track_t* track, char* name)
return FLUID_FAILED; return FLUID_FAILED;
} }
FLUID_STRCPY(track->name, name); FLUID_STRCPY(track->name, name);
return FLUID_OK; return FLUID_OK;
} }
/* /*
@@ -995,7 +1058,7 @@ fluid_midi_event_t* fluid_track_next_event(fluid_track_t* track)
/* /*
* fluid_track_reset * fluid_track_reset
*/ */
int int
fluid_track_reset(fluid_track_t* track) fluid_track_reset(fluid_track_t* track)
{ {
track->ticks = 0; track->ticks = 0;
@@ -1006,8 +1069,8 @@ fluid_track_reset(fluid_track_t* track)
/* /*
* fluid_track_send_events * fluid_track_send_events
*/ */
int int
fluid_track_send_events(fluid_track_t* track, fluid_track_send_events(fluid_track_t* track,
fluid_synth_t* synth, fluid_synth_t* synth,
fluid_player_t* player, fluid_player_t* player,
unsigned int ticks) unsigned int ticks)
@@ -1046,8 +1109,11 @@ fluid_track_send_events(fluid_track_t* track,
* *
* fluid_player * fluid_player
*/ */
/*
* new_fluid_player /**
* Create a new MIDI player.
* @param synth Fluid synthesizer instance to create player for
* @return New MIDI player instance or NULL on error (out of memory)
*/ */
fluid_player_t* new_fluid_player(fluid_synth_t* synth) fluid_player_t* new_fluid_player(fluid_synth_t* synth)
{ {
@@ -1075,8 +1141,10 @@ fluid_player_t* new_fluid_player(fluid_synth_t* synth)
return player; return player;
} }
/* /**
* delete_fluid_player * Delete a MIDI player instance.
* @param player MIDI player instance
* @return Always returns 0
*/ */
int delete_fluid_player(fluid_player_t* player) int delete_fluid_player(fluid_player_t* player)
{ {
@@ -1157,7 +1225,7 @@ int fluid_player_load(fluid_player_t* player, char *filename)
{ {
fluid_midi_file* midifile; fluid_midi_file* midifile;
midifile = new_fluid_midi_file(filename); midifile = new_fluid_midi_file(filename);
if (midifile == NULL) { if (midifile == NULL) {
return FLUID_FAILED; return FLUID_FAILED;
} }
@@ -1169,7 +1237,7 @@ int fluid_player_load(fluid_player_t* player, char *filename)
return FLUID_FAILED; return FLUID_FAILED;
} }
delete_fluid_midi_file(midifile); delete_fluid_midi_file(midifile);
return FLUID_OK; return FLUID_OK;
} }
/* /*
@@ -1217,9 +1285,9 @@ int fluid_player_callback(void* data, unsigned int msec)
} }
player->cur_msec = msec; player->cur_msec = msec;
player->cur_ticks = (player->start_ticks + player->cur_ticks = (player->start_ticks +
(int) ((double) (player->cur_msec - player->start_msec) / player->deltatime)); (int) ((double) (player->cur_msec - player->start_msec) / player->deltatime));
for (i = 0; i < player->ntracks; i++) { for (i = 0; i < player->ntracks; i++) {
if (!fluid_track_eot(player->track[i])) { if (!fluid_track_eot(player->track[i])) {
status = FLUID_PLAYER_PLAYING; status = FLUID_PLAYER_PLAYING;
@@ -1232,30 +1300,32 @@ int fluid_player_callback(void* data, unsigned int msec)
player->status = status; player->status = status;
if (player->status == FLUID_PLAYER_DONE) { if (player->status == FLUID_PLAYER_DONE) {
FLUID_LOG(FLUID_DBG, "%s: %d: Duration=%.3f sec", FLUID_LOG(FLUID_DBG, "%s: %d: Duration=%.3f sec",
__FILE__, __LINE__, (msec - player->begin_msec) / 1000.0); __FILE__, __LINE__, (msec - player->begin_msec) / 1000.0);
player->current_file = NULL; player->current_file = NULL;
} }
return 1; return 1;
} }
/* /**
* fluid_player_play * Activates play mode for a MIDI player if not already playing.
* @param player MIDI player instance
* @return 0 on success, -1 on failure
*/ */
int fluid_player_play(fluid_player_t* player) int fluid_player_play(fluid_player_t* player)
{ {
if (player->status == FLUID_PLAYER_PLAYING) { if (player->status == FLUID_PLAYER_PLAYING) {
return FLUID_OK; return FLUID_OK;
} }
if (player->playlist == NULL) { if (player->playlist == NULL) {
return FLUID_OK; return FLUID_OK;
} }
player->status = FLUID_PLAYER_PLAYING; player->status = FLUID_PLAYER_PLAYING;
player->timer = new_fluid_timer((int) player->deltatime, fluid_player_callback, player->timer = new_fluid_timer((int) player->deltatime, fluid_player_callback,
(void*) player, 1, 0); (void*) player, 1, 0);
if (player->timer == NULL) { if (player->timer == NULL) {
return FLUID_FAILED; return FLUID_FAILED;
@@ -1263,8 +1333,10 @@ int fluid_player_play(fluid_player_t* player)
return FLUID_OK; return FLUID_OK;
} }
/* /**
* fluid_player_stop * Stops a MIDI player.
* @param player MIDI player instance
* @return Always returns 0
*/ */
int fluid_player_stop(fluid_player_t* player) int fluid_player_stop(fluid_player_t* player)
{ {
@@ -1276,8 +1348,13 @@ int fluid_player_stop(fluid_player_t* player)
return FLUID_OK; return FLUID_OK;
} }
/* /* FIXME - Looping seems to not actually be implemented? */
* fluid_player_set_loop
/**
* Enable looping of a MIDI player (DOCME - Does this actually work?)
* @param player MIDI player instance
* @param loop Value for looping (DOCME - What would this value be, boolean/time index?)
* @return Always returns 0
*/ */
int fluid_player_set_loop(fluid_player_t* player, int loop) int fluid_player_set_loop(fluid_player_t* player, int loop)
{ {
@@ -1285,8 +1362,12 @@ int fluid_player_set_loop(fluid_player_t* player, int loop)
return FLUID_OK; return FLUID_OK;
} }
/* /**
* fluid_player_set_midi_tempo * Set the tempo of a MIDI player.
* @param player MIDI player instance
* @param tempo Tempo to set playback speed to (DOCME - Units?)
* @return Always returns 0
*
*/ */
int fluid_player_set_midi_tempo(fluid_player_t* player, int tempo) int fluid_player_set_midi_tempo(fluid_player_t* player, int tempo)
{ {
@@ -1294,23 +1375,29 @@ int fluid_player_set_midi_tempo(fluid_player_t* player, int tempo)
player->deltatime = (double) tempo / player->division / 1000.0; /* in milliseconds */ player->deltatime = (double) tempo / player->division / 1000.0; /* in milliseconds */
player->start_msec = player->cur_msec; player->start_msec = player->cur_msec;
player->start_ticks = player->cur_ticks; player->start_ticks = player->cur_ticks;
FLUID_LOG(FLUID_DBG,"tempo=%d, tick time=%f msec, cur time=%d msec, cur tick=%d", FLUID_LOG(FLUID_DBG,"tempo=%d, tick time=%f msec, cur time=%d msec, cur tick=%d",
tempo, player->deltatime, player->cur_msec, player->cur_ticks); tempo, player->deltatime, player->cur_msec, player->cur_ticks);
return FLUID_OK; return FLUID_OK;
} }
/* /**
* fluid_player_set_bpm * Set the tempo of a MIDI player in beats per minute.
* @param player MIDI player instance
* @param bpm Tempo in beats per minute
* @return Always returns 0
*/ */
int fluid_player_set_bpm(fluid_player_t* player, int bpm) int fluid_player_set_bpm(fluid_player_t* player, int bpm)
{ {
return fluid_player_set_midi_tempo(player, (int)((double) 60 * 1e6 / bpm)); return fluid_player_set_midi_tempo(player, (int)((double) 60 * 1e6 / bpm));
} }
/* /**
* fluid_player_join * Wait for a MIDI player to terminate (when done playing).
* @param player MIDI player instance
* @return 0 on success, -1 otherwise
*
*/ */
int fluid_player_join(fluid_player_t* player) int fluid_player_join(fluid_player_t* player)
{ {
@@ -1360,10 +1447,10 @@ fluid_midi_event_t* fluid_midi_parser_parse(fluid_midi_parser_t* parser, unsigne
/* 'Process' system real-time messages */ /* 'Process' system real-time messages */
/*********************************************************************/ /*********************************************************************/
/* There are not too many real-time messages that are of interest here. /* There are not too many real-time messages that are of interest here.
* They can occur anywhere, even in the middle of a noteon message! * They can occur anywhere, even in the middle of a noteon message!
* Real-time range: 0xF8 .. 0xFF * Real-time range: 0xF8 .. 0xFF
* Note: Real-time does not affect (running) status. * Note: Real-time does not affect (running) status.
*/ */
if (c >= 0xF8){ if (c >= 0xF8){
if (c == MIDI_SYSTEM_RESET){ if (c == MIDI_SYSTEM_RESET){
parser->event.type = c; parser->event.type = c;
@@ -1372,23 +1459,23 @@ fluid_midi_event_t* fluid_midi_parser_parse(fluid_midi_parser_t* parser, unsigne
}; };
return NULL; return NULL;
}; };
/*********************************************************************/ /*********************************************************************/
/* 'Process' system common messages (again, just skip them) */ /* 'Process' system common messages (again, just skip them) */
/*********************************************************************/ /*********************************************************************/
/* There are no system common messages that are of interest here. /* There are no system common messages that are of interest here.
* System common range: 0xF0 .. 0xF7 * System common range: 0xF0 .. 0xF7
*/ */
if (c > 0xF0){ if (c > 0xF0){
/* MIDI specs say: To ignore a non-real-time message, just discard all data up to /* MIDI specs say: To ignore a non-real-time message, just discard all data up to
* the next status byte. * the next status byte.
* And our parser will ignore data that is received without a valid status. * And our parser will ignore data that is received without a valid status.
* Note: system common cancels running status. */ * Note: system common cancels running status. */
parser->status = 0; parser->status = 0;
return NULL; return NULL;
}; };
/*********************************************************************/ /*********************************************************************/
/* Process voice category messages: */ /* Process voice category messages: */
/*********************************************************************/ /*********************************************************************/
@@ -1399,7 +1486,7 @@ fluid_midi_event_t* fluid_midi_parser_parse(fluid_midi_parser_t* parser, unsigne
* as soon as a byte >= 0x80 comes in, we are dealing with a status byte * as soon as a byte >= 0x80 comes in, we are dealing with a status byte
* and start a new event. * and start a new event.
*/ */
if (c & 0x80){ if (c & 0x80){
parser->channel = c & 0x0F; parser->channel = c & 0x0F;
parser->status = c & 0xF0; parser->status = c & 0xF0;
@@ -1431,12 +1518,12 @@ fluid_midi_event_t* fluid_midi_parser_parse(fluid_midi_parser_t* parser, unsigne
if (parser->nr_bytes < parser->nr_bytes_total){ if (parser->nr_bytes < parser->nr_bytes_total){
return NULL; return NULL;
}; };
/*********************************************************************/ /*********************************************************************/
/* Send the event */ /* Send the event */
/*********************************************************************/ /*********************************************************************/
/* The event is ready-to-go. /* The event is ready-to-go.
* About 'running status': * About 'running status':
* The MIDI protocol has a built-in compression mechanism. If several similar events are sent * The MIDI protocol has a built-in compression mechanism. If several similar events are sent
* in-a-row, for example note-ons, then the event type is only sent once. For this case, * in-a-row, for example note-ons, then the event type is only sent once. For this case,
* the last event type (status) is remembered. * the last event type (status) is remembered.
@@ -1459,14 +1546,14 @@ fluid_midi_event_t* fluid_midi_parser_parse(fluid_midi_parser_t* parser, unsigne
/* Pitch-bend is transmitted with 14-bit precision. */ /* Pitch-bend is transmitted with 14-bit precision. */
parser->event.param1 = ((parser->p[1] << 7) | parser->p[0]); /* Note: '|' does here the same as '+' (no common bits), but might be faster */ parser->event.param1 = ((parser->p[1] << 7) | parser->p[0]); /* Note: '|' does here the same as '+' (no common bits), but might be faster */
break; break;
default: default:
/* Unlikely */ /* Unlikely */
return NULL; return NULL;
}; };
return &parser->event; return &parser->event;
}; };
/* Purpose: /* Purpose:
* Returns the length of the MIDI message starting with c. * Returns the length of the MIDI message starting with c.
* Taken from Nagano Daisuke's USB-MIDI driver */ * Taken from Nagano Daisuke's USB-MIDI driver */
int fluid_midi_event_length(unsigned char event){ int fluid_midi_event_length(unsigned char event){
@@ -1525,5 +1612,3 @@ int fluid_midi_send_event(fluid_synth_t* synth, fluid_player_t* player, fluid_mi
} }
return FLUID_OK; return FLUID_OK;
} }
+6 -6
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -161,14 +161,14 @@ enum midi_meta_event {
MIDI_SEQUENCER_EVENT = 0x7f MIDI_SEQUENCER_EVENT = 0x7f
}; };
enum fluid_player_status enum fluid_player_status
{ {
FLUID_PLAYER_READY, FLUID_PLAYER_READY,
FLUID_PLAYER_PLAYING, FLUID_PLAYER_PLAYING,
FLUID_PLAYER_DONE FLUID_PLAYER_DONE
}; };
enum fluid_driver_status enum fluid_driver_status
{ {
FLUID_MIDI_READY, FLUID_MIDI_READY,
FLUID_MIDI_LISTENING, FLUID_MIDI_LISTENING,
@@ -181,7 +181,7 @@ enum fluid_driver_status
*/ */
/* From ctype.h */ /* From ctype.h */
#define fluid_isascii(c) (((c) & ~0x7f) == 0) #define fluid_isascii(c) (((c) & ~0x7f) == 0)
@@ -222,7 +222,7 @@ fluid_midi_event_t* fluid_track_next_event(fluid_track_t* track);
int fluid_track_get_duration(fluid_track_t* track); int fluid_track_get_duration(fluid_track_t* track);
int fluid_track_reset(fluid_track_t* track); int fluid_track_reset(fluid_track_t* track);
int fluid_track_send_events(fluid_track_t* track, int fluid_track_send_events(fluid_track_t* track,
fluid_synth_t* synth, fluid_synth_t* synth,
fluid_player_t* player, fluid_player_t* player,
unsigned int ticks); unsigned int ticks);
@@ -273,7 +273,7 @@ typedef struct {
int uses_smpte; int uses_smpte;
unsigned int smpte_fps; unsigned int smpte_fps;
unsigned int smpte_res; unsigned int smpte_res;
unsigned int division; /* If uses_SMPTE == 0 then division is unsigned int division; /* If uses_SMPTE == 0 then division is
ticks per beat (quarter-note) */ ticks per beat (quarter-note) */
double tempo; /* Beats per second (SI rules =) */ double tempo; /* Beats per second (SI rules =) */
int tracklen; int tracklen;
+99 -89
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -26,21 +26,29 @@
#include "fluid_synth.h" #include "fluid_synth.h"
#include "fluid_io.h" #include "fluid_io.h"
/* /**
* new_fluid_midi_router * Create a new midi router.
* @param settings Settings used to configure MIDI router
* @param handler MIDI event callback
* @param event_handler_data Caller defined data pointer which gets passed to 'handler'
* @return New MIDI router instance or NULL on error
*
* A midi handler connects to a midi input
* device and forwards incoming midi events to the synthesizer.
*/ */
fluid_midi_router_t* fluid_midi_router_t*
new_fluid_midi_router(fluid_settings_t* settings, handle_midi_event_func_t handler, void* event_handler_data) new_fluid_midi_router(fluid_settings_t* settings, handle_midi_event_func_t handler, void* event_handler_data)
{ {
fluid_midi_router_t* router=NULL; fluid_midi_router_t* router=NULL;
fluid_midi_router_rule_t* rule=NULL;; fluid_midi_router_rule_t* rule=NULL;
/* create the router */ /* create the router */
router = FLUID_NEW(fluid_midi_router_t); if (router == NULL){ router = FLUID_NEW(fluid_midi_router_t); if (router == NULL){
FLUID_LOG(FLUID_ERR, "Out of memory"); FLUID_LOG(FLUID_ERR, "Out of memory");
return NULL; return NULL;
}; };
/* Clear the router, so that error_recovery can safely free all the rules. /* Clear the router, so that error_recovery can safely free all the rules.
* Dump functions are also NULLed. * Dump functions are also NULLed.
*/ */
FLUID_MEMSET(router, 0, sizeof(fluid_midi_router_t)); FLUID_MEMSET(router, 0, sizeof(fluid_midi_router_t));
@@ -53,12 +61,12 @@ new_fluid_midi_router(fluid_settings_t* settings, handle_midi_event_func_t handl
router->event_handler=handler; router->event_handler=handler;
router->event_handler_data=event_handler_data; router->event_handler_data=event_handler_data;
/* Create the default routing rules /* Create the default routing rules
* They accept events on any channel for any range of parameters, * They accept events on any channel for any range of parameters,
* and route them unchanged ("result=par*1.0+0") */ * and route them unchanged ("result=par*1.0+0") */
if (fluid_midi_router_create_default_rules(router) != FLUID_OK) goto error_recovery; if (fluid_midi_router_create_default_rules(router) != FLUID_OK) goto error_recovery;
return router; return router;
error_recovery: error_recovery:
@@ -68,10 +76,12 @@ new_fluid_midi_router(fluid_settings_t* settings, handle_midi_event_func_t handl
return NULL; return NULL;
} }
/* /**
* delete_fluid_midi_router * Delete a MIDI router instance.
* @param router MIDI router to delete
* @return Always returns 0
*/ */
int int
delete_fluid_midi_router(fluid_midi_router_t* router) delete_fluid_midi_router(fluid_midi_router_t* router)
{ {
if (router == NULL) { if (router == NULL) {
@@ -84,7 +94,7 @@ delete_fluid_midi_router(fluid_midi_router_t* router)
/* /*
* fluid_midi_router_destroy_all_rules(fluid_midi_router_t* router) * fluid_midi_router_destroy_all_rules(fluid_midi_router_t* router)
* Purpose: * Purpose:
* Frees the used memory. This is used only for shutdown! * Frees the used memory. This is used only for shutdown!
*/ */
void fluid_midi_router_destroy_all_rules(fluid_midi_router_t* router){ void fluid_midi_router_destroy_all_rules(fluid_midi_router_t* router){
@@ -127,7 +137,7 @@ fluid_midi_router_rule_t* new_fluid_midi_router_rule(void)
/* /*
* delete_fluid_midi_router_rule * delete_fluid_midi_router_rule
*/ */
int int
delete_fluid_midi_router_rule(fluid_midi_router_rule_t* rule) delete_fluid_midi_router_rule(fluid_midi_router_rule_t* rule)
{ {
FLUID_FREE(rule); FLUID_FREE(rule);
@@ -139,7 +149,7 @@ int fluid_midi_router_create_default_rules(fluid_midi_router_t* router)
{ {
fluid_midi_router_rule_t** rules[6]; fluid_midi_router_rule_t** rules[6];
int i; int i;
rules[0]=&router->note_rules; rules[0]=&router->note_rules;
rules[1]=&router->cc_rules; rules[1]=&router->cc_rules;
rules[2]=&router->progchange_rules; rules[2]=&router->progchange_rules;
@@ -238,18 +248,22 @@ int fluid_midi_router_end(fluid_midi_router_t* router){
delete_fluid_midi_router_rule(rule); delete_fluid_midi_router_rule(rule);
return FLUID_FAILED; return FLUID_FAILED;
}; };
/* /**
* fluid_midi_router_send_event * Handle a MIDI event through a MIDI router instance.
* @param data MIDI router instance #fluid_midi_router_t (DOCME why is it a void *?)
* @param event MIDI event to handle
* @return 0 on success, -1 otherwise
*
* Purpose: The midi router is called for each event, that is received * Purpose: The midi router is called for each event, that is received
* via the 'physical' midi input. Each event can trigger an arbitrary number * via the 'physical' midi input. Each event can trigger an arbitrary number
* of generated events. * of generated events.
* *
* In default mode, a noteon event is just forwarded to the synth's 'noteon' function, * In default mode, a noteon event is just forwarded to the synth's 'noteon' function,
* a 'CC' event to the synth's 'CC' function and so on. * a 'CC' event to the synth's 'CC' function and so on.
* *
* The router can be used to * The router can be used to
* - filter messages (for example: Pass sustain pedal CCs only to selected channels), * - filter messages (for example: Pass sustain pedal CCs only to selected channels),
* - split the keyboard (noteon with notenr < x: to ch 1, >x to ch 2), * - split the keyboard (noteon with notenr < x: to ch 1, >x to ch 2),
* - layer sounds (for each noteon received on ch 1, create a noteon on ch1, ch2, ch3,...) * - layer sounds (for each noteon received on ch 1, create a noteon on ch1, ch2, ch3,...)
* - velocity scaling (for each noteon event, scale the velocity by 1.27 to give DX7 users * - velocity scaling (for each noteon event, scale the velocity by 1.27 to give DX7 users
@@ -258,7 +272,7 @@ int fluid_midi_router_end(fluid_midi_router_t* router){
* - get rid of aftertouch * - get rid of aftertouch
* - ... * - ...
*/ */
int int
fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event) fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event)
{ {
fluid_midi_router_t* router=(fluid_midi_router_t*)data; fluid_midi_router_t* router=(fluid_midi_router_t*)data;
@@ -276,12 +290,12 @@ fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event)
if (event->type == NOTE_ON && event->param2 == 0) { if (event->type == NOTE_ON && event->param2 == 0) {
/* Channel: Remains the same /* Channel: Remains the same
* Param 1: Note number, remains the same * Param 1: Note number, remains the same
* Param 2: release velocity), set to max * Param 2: release velocity), set to max
*/ */
event->type = NOTE_OFF; event->type = NOTE_OFF;
event->param2=127; event->param2=127;
}; };
/* Lock the rules table, so that for example the shell thread doesn't /* Lock the rules table, so that for example the shell thread doesn't
* clear the rules we are just working with */ * clear the rules we are just working with */
fluid_mutex_lock(router->ruletables_mutex); fluid_mutex_lock(router->ruletables_mutex);
@@ -324,26 +338,26 @@ fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event)
default: default:
break; break;
} }
/* At this point 'rule' contains the first rule in a linked list. /* At this point 'rule' contains the first rule in a linked list.
* Check for all rules, whether channel and parameter ranges match. * Check for all rules, whether channel and parameter ranges match.
*/ */
while (rule){ while (rule){
int chan; /* Channel of the generated event */ int chan; /* Channel of the generated event */
int par1; /* par1 of the generated event */ int par1; /* par1 of the generated event */
int par2=0; int par2=0;
int event_par1=(int)event->param1; int event_par1=(int)event->param1;
int event_par2=(int)event->param2; int event_par2=(int)event->param2;
fluid_midi_event_t new_event; fluid_midi_event_t new_event;
/* Store the pointer to the next rule right now. If the rule is later flagged for destruction, /* Store the pointer to the next rule right now. If the rule is later flagged for destruction,
* it may not be accessed anymore. * it may not be accessed anymore.
*/ */
next_rule=rule->next; next_rule=rule->next;
/* Check, whether the rule is still active. Expired rules cannot be removed immediately, /* Check, whether the rule is still active. Expired rules cannot be removed immediately,
* because freeing memory in a realtime thread is no good idea. And the MIDI thread, * because freeing memory in a realtime thread is no good idea. And the MIDI thread,
* which calls us here, has raised priority.*/ * which calls us here, has raised priority.*/
if (rule->state == MIDIRULE_DONE){ if (rule->state == MIDIRULE_DONE){
goto do_next_rule; goto do_next_rule;
@@ -374,11 +388,11 @@ fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event)
goto do_next_rule; goto do_next_rule;
} }
}; };
/* Par 2 window (only applies to event types, which have 2 pars) /* Par 2 window (only applies to event types, which have 2 pars)
* For noteoff events, velocity switching doesn't make any sense. * For noteoff events, velocity switching doesn't make any sense.
* Velocity scaling might be useful, though. * Velocity scaling might be useful, though.
*/ */
if (event_has_par2 && event->type != NOTE_OFF){ if (event_has_par2 && event->type != NOTE_OFF){
if (rule->par2_min > rule->par2_max){ if (rule->par2_min > rule->par2_max){
/* Inverted rule: Exclude everything between max and min (but not min/max) */ /* Inverted rule: Exclude everything between max and min (but not min/max) */
@@ -392,9 +406,9 @@ fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event)
}; };
}; };
}; };
/* Channel scaling / offset /* Channel scaling / offset
* Note: rule->chan_mul will probably be 0 or 1. If it's 0, input from all * Note: rule->chan_mul will probably be 0 or 1. If it's 0, input from all
* input channels is mapped to the same synth channel. * input channels is mapped to the same synth channel.
*/ */
chan=(int)((fluid_real_t)event->channel * (fluid_real_t)rule->chan_mul + (fluid_real_t)rule->chan_add + 0.5); chan=(int)((fluid_real_t)event->channel * (fluid_real_t)rule->chan_mul + (fluid_real_t)rule->chan_add + 0.5);
@@ -406,7 +420,7 @@ fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event)
if (event_has_par2){ if (event_has_par2){
par2=(int)((fluid_real_t)event_par2 * (fluid_real_t)rule->par2_mul + (fluid_real_t)rule->par2_add + 0.5); par2=(int)((fluid_real_t)event_par2 * (fluid_real_t)rule->par2_mul + (fluid_real_t)rule->par2_add + 0.5);
}; };
/* Channel range limiting */ /* Channel range limiting */
if (chan < 0){ if (chan < 0){
chan=0; chan=0;
@@ -437,7 +451,7 @@ fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event)
*/ */
if ( if (
event->type == NOTE_ON event->type == NOTE_ON
|| (event->type == CONTROL_CHANGE && par1 == SUSTAIN_SWITCH && par2 >= 64) || (event->type == CONTROL_CHANGE && par1 == SUSTAIN_SWITCH && par2 >= 64)
){ ){
/* Noteon or sustain pedal down event generated */ /* Noteon or sustain pedal down event generated */
@@ -446,7 +460,7 @@ fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event)
rule->pending_events++; rule->pending_events++;
}; };
} else if ( } else if (
event->type == NOTE_OFF event->type == NOTE_OFF
|| (event->type == CONTROL_CHANGE && par1 == SUSTAIN_SWITCH && par2 < 64) || (event->type == CONTROL_CHANGE && par1 == SUSTAIN_SWITCH && par2 < 64)
){ ){
/* Noteoff or sustain pedal up event generated */ /* Noteoff or sustain pedal up event generated */
@@ -463,7 +477,7 @@ fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event)
/* There are no more pending events in the rule - all keys are up. /* There are no more pending events in the rule - all keys are up.
* Change its state to 'unused', it will be cleared up at the next * Change its state to 'unused', it will be cleared up at the next
* opportunity to run 'free' safely. * opportunity to run 'free' safely.
* Note: After this, the rule may disappear at any time * Note: After this, the rule may disappear at any time
*/ */
rule->state=MIDIRULE_DONE; rule->state=MIDIRULE_DONE;
}; };
@@ -477,9 +491,9 @@ fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event)
goto do_next_rule; goto do_next_rule;
}; };
}; };
/* At this point it is decided, what is sent to the synth. /* At this point it is decided, what is sent to the synth.
* Create a new event and make the appropriate call * Create a new event and make the appropriate call
*/ */
fluid_midi_event_set_type(&new_event, event->type); fluid_midi_event_set_type(&new_event, event->type);
@@ -516,8 +530,8 @@ int fluid_midi_router_handle_clear(fluid_synth_t* synth, int ac, char** av, flui
if (ac != 0) { if (ac != 0) {
fluid_ostream_printf(out, "router_clear needs no arguments.\n"); fluid_ostream_printf(out, "router_clear needs no arguments.\n");
goto error_recovery; goto error_recovery;
} }
/* Disable rules and mark for destruction */ /* Disable rules and mark for destruction */
fluid_midi_router_disable_all_rules(router); fluid_midi_router_disable_all_rules(router);
@@ -536,8 +550,8 @@ int fluid_midi_router_handle_default(fluid_synth_t* synth, int ac, char** av, fl
if (ac != 0) { if (ac != 0) {
fluid_ostream_printf(out, "router_default needs no arguments.\n"); fluid_ostream_printf(out, "router_default needs no arguments.\n");
return -1; return -1;
} }
/* Disable rules and mark for destruction */ /* Disable rules and mark for destruction */
fluid_midi_router_disable_all_rules(router); fluid_midi_router_disable_all_rules(router);
@@ -564,7 +578,7 @@ int fluid_midi_router_handle_begin(fluid_synth_t* synth, int ac, char** av, flui
fluid_ostream_printf(out, "router_begin needs no arguments.\n"); fluid_ostream_printf(out, "router_begin needs no arguments.\n");
goto error_recovery; goto error_recovery;
} }
if (FLUID_STRCMP(av[0],"note") == 0){ if (FLUID_STRCMP(av[0],"note") == 0){
dest=& router->note_rules; dest=& router->note_rules;
} else if (FLUID_STRCMP(av[0],"cc") == 0){ } else if (FLUID_STRCMP(av[0],"cc") == 0){
@@ -578,12 +592,12 @@ int fluid_midi_router_handle_begin(fluid_synth_t* synth, int ac, char** av, flui
} else if (FLUID_STRCMP(av[0],"kpress") == 0){ } else if (FLUID_STRCMP(av[0],"kpress") == 0){
dest=& router->key_pressure_rules; dest=& router->key_pressure_rules;
}; };
if (dest == NULL){ if (dest == NULL){
fluid_ostream_printf(out, "router_begin args: note, cc, prog, pbend, cpress, kpress\n"); fluid_ostream_printf(out, "router_begin args: note, cc, prog, pbend, cpress, kpress\n");
goto error_recovery; goto error_recovery;
}; };
if (fluid_midi_router_begin(router, dest) != FLUID_OK){ if (fluid_midi_router_begin(router, dest) != FLUID_OK){
goto error_recovery; goto error_recovery;
}; };
@@ -609,8 +623,8 @@ int fluid_midi_router_handle_end(fluid_synth_t* synth, int ac, char** av, fluid_
if (fluid_midi_router_end(router) != FLUID_OK){ if (fluid_midi_router_end(router) != FLUID_OK){
FLUID_LOG(FLUID_ERR, "midi_router_end failed"); FLUID_LOG(FLUID_ERR, "midi_router_end failed");
goto error_recovery; goto error_recovery;
}; };
/* Free unused rules (give it a try) */ /* Free unused rules (give it a try) */
fluid_midi_router_free_unused_rules(router); fluid_midi_router_free_unused_rules(router);
@@ -658,7 +672,7 @@ int fluid_midi_router_handle_par1(fluid_synth_t* synth, int ac, char** av, fluid
router->new_rule_par1_add=atoi(av[3]); router->new_rule_par1_add=atoi(av[3]);
/* Free unused rules (give it a try) */ /* Free unused rules (give it a try) */
fluid_midi_router_free_unused_rules(router); fluid_midi_router_free_unused_rules(router);
return 0; return 0;
@@ -760,23 +774,23 @@ void fluid_midi_router_free_unused_rules(fluid_midi_router_t* router)
default: default:
break; break;
}; };
while (*p){ while (*p){
fluid_midi_router_rule_t* current_rule=*p; fluid_midi_router_rule_t* current_rule=*p;
fluid_midi_router_rule_t* next_rule=current_rule->next; fluid_midi_router_rule_t* next_rule=current_rule->next;
if (current_rule->state == MIDIRULE_DONE){ if (current_rule->state == MIDIRULE_DONE){
/* p points to current_rule. /* p points to current_rule.
* current_rule->next points to next_rule. * current_rule->next points to next_rule.
* Unlink current_rule from the chain by setting the content * Unlink current_rule from the chain by setting the content
* of p to next_rule. * of p to next_rule.
*/ */
*p=next_rule; *p=next_rule;
/* Now the rule is not in the chain anymore. Destroy it. */ /* Now the rule is not in the chain anymore. Destroy it. */
delete_fluid_midi_router_rule(current_rule); delete_fluid_midi_router_rule(current_rule);
} else { } else {
/* We have to keep the rule, there is still unfinished business. */ /* We have to keep the rule, there is still unfinished business. */
p = &current_rule->next; p = &current_rule->next;
@@ -785,48 +799,44 @@ void fluid_midi_router_free_unused_rules(fluid_midi_router_t* router)
fluid_mutex_unlock(router->ruletables_mutex); fluid_mutex_unlock(router->ruletables_mutex);
}; };
}; };
/* Purpose: /**
* This function demonstrates, how to access incoming MIDI messages. * MIDI event callback function to display event information to stdout
* It prints a message to stdout (which can be used to hook up an external user interface), * @param data MIDI router instance
* and hands the event on to the MIDI router. * @param event MIDI event data
* It is not a part of the MIDI router, but an added link in the MIDI chain. * @return 0 on success, -1 otherwise
*
* An implementation of the #handle_midi_event_func_t function type, used for
* displaying MIDI event information between the MIDI driver and router to
* stdout. Useful for adding into a MIDI router chain for debugging MIDI events.
*/ */
int fluid_midi_dump_prerouter(void* data, fluid_midi_event_t* event) int fluid_midi_dump_prerouter(void* data, fluid_midi_event_t* event)
{ {
switch (event->type) { switch (event->type) {
case NOTE_ON: case NOTE_ON:
fprintf(stdout, "event_pre_noteon %i %i %i\n", fprintf(stdout, "event_pre_noteon %i %i %i\n",
event->channel, event->param1, event->param2); event->channel, event->param1, event->param2);
fflush(stdout);
break; break;
case NOTE_OFF: case NOTE_OFF:
fprintf(stdout, "event_pre_noteoff %i %i %i\n", fprintf(stdout, "event_pre_noteoff %i %i %i\n",
event->channel, event->param1, event->param2); event->channel, event->param1, event->param2);
fflush(stdout);
break;
break; break;
case CONTROL_CHANGE: case CONTROL_CHANGE:
fprintf(stdout, "event_pre_cc %i %i %i\n", fprintf(stdout, "event_pre_cc %i %i %i\n",
event->channel, event->param1, event->param2); event->channel, event->param1, event->param2);
fflush(stdout);
break; break;
case PROGRAM_CHANGE: case PROGRAM_CHANGE:
fprintf(stdout, "event_pre_prog %i %i\n", event->channel, event->param1); fprintf(stdout, "event_pre_prog %i %i\n", event->channel, event->param1);
fflush(stdout);
break; break;
case PITCH_BEND: case PITCH_BEND:
fprintf(stdout, "event_pre_pitch %i %i\n", event->channel, event->param1); fprintf(stdout, "event_pre_pitch %i %i\n", event->channel, event->param1);
fflush(stdout);
break; break;
case CHANNEL_PRESSURE: case CHANNEL_PRESSURE:
fprintf(stdout, "event_pre_cpress %i %i\n", event->channel, event->param1); fprintf(stdout, "event_pre_cpress %i %i\n", event->channel, event->param1);
fflush(stdout);
break; break;
case KEY_PRESSURE: case KEY_PRESSURE:
fprintf(stdout, "event_pre_kpress %i %i %i\n", fprintf(stdout, "event_pre_kpress %i %i %i\n",
event->channel, event->param1, event->param2); event->channel, event->param1, event->param2);
fflush(stdout);
break; break;
default: default:
break; break;
@@ -834,30 +844,30 @@ int fluid_midi_dump_prerouter(void* data, fluid_midi_event_t* event)
return fluid_midi_router_handle_midi_event((fluid_midi_router_t*) data, event); return fluid_midi_router_handle_midi_event((fluid_midi_router_t*) data, event);
}; };
/* Purpose: /**
* This function demonstrates, how to access MIDI messages going from the MIDI * MIDI event callback function to display event information to stdout
* router to the synth. * @param data MIDI router instance
* Again, it prints a message to stdout and hands the event on to the synth. * @param event MIDI event data
* It is not a part of the MIDI router, but an added link in the MIDI chain. * @return 0 on success, -1 otherwise
*
* An implementation of the #handle_midi_event_func_t function type, used for
* displaying MIDI event information between the MIDI driver and router to
* stdout. Useful for adding into a MIDI router chain for debugging MIDI events.
*/ */
int fluid_midi_dump_postrouter(void* data, fluid_midi_event_t* event) int fluid_midi_dump_postrouter(void* data, fluid_midi_event_t* event)
{ {
switch (event->type) { switch (event->type) {
case NOTE_ON: case NOTE_ON:
fprintf(stdout, "event_post_noteon %i %i %i\n", fprintf(stdout, "event_post_noteon %i %i %i\n",
event->channel, event->param1, event->param2); event->channel, event->param1, event->param2);
fflush(stdout);
break; break;
case NOTE_OFF: case NOTE_OFF:
fprintf(stdout, "event_post_noteoff %i %i %i\n", fprintf(stdout, "event_post_noteoff %i %i %i\n",
event->channel, event->param1, event->param2); event->channel, event->param1, event->param2);
fflush(stdout);
break;
break; break;
case CONTROL_CHANGE: case CONTROL_CHANGE:
fprintf(stdout, "event_post_cc %i %i %i\n", fprintf(stdout, "event_post_cc %i %i %i\n",
event->channel, event->param1, event->param2); event->channel, event->param1, event->param2);
fflush(stdout);
break; break;
case PROGRAM_CHANGE: case PROGRAM_CHANGE:
fprintf(stdout, "event_post_prog %i %i\n", event->channel, event->param1); fprintf(stdout, "event_post_prog %i %i\n", event->channel, event->param1);
@@ -869,7 +879,7 @@ int fluid_midi_dump_postrouter(void* data, fluid_midi_event_t* event)
fprintf(stdout, "event_post_cpress %i %i\n", event->channel, event->param1); fprintf(stdout, "event_post_cpress %i %i\n", event->channel, event->param1);
break; break;
case KEY_PRESSURE: case KEY_PRESSURE:
fprintf(stdout, "event_post_kpress %i %i %i\n", fprintf(stdout, "event_post_kpress %i %i %i\n",
event->channel, event->param1, event->param2); event->channel, event->param1, event->param2);
break; break;
default: default:
+2 -2
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -79,7 +79,7 @@ struct _fluid_midi_router_t {
void* event_handler_data; /* One arg for the callback */ void* event_handler_data; /* One arg for the callback */
int nr_midi_channels; /* For clipping the midi channel */ int nr_midi_channels; /* For clipping the midi channel */
fluid_mutex_t ruletables_mutex; fluid_mutex_t ruletables_mutex;
}; };
struct _fluid_midi_router_rule_t { struct _fluid_midi_router_rule_t {
+52 -52
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -25,56 +25,56 @@
/* /*
* fluid_mod_clone * fluid_mod_clone
*/ */
void void
fluid_mod_clone(fluid_mod_t* mod, fluid_mod_t* src) fluid_mod_clone(fluid_mod_t* mod, fluid_mod_t* src)
{ {
mod->dest = src->dest; mod->dest = src->dest;
mod->src1 = src->src1; mod->src1 = src->src1;
mod->flags1 = src->flags1; mod->flags1 = src->flags1;
mod->src2 = src->src2; mod->src2 = src->src2;
mod->flags2 = src->flags2; mod->flags2 = src->flags2;
mod->amount = src->amount; mod->amount = src->amount;
} }
/* /*
* fluid_mod_set_source1 * fluid_mod_set_source1
*/ */
void void
fluid_mod_set_source1(fluid_mod_t* mod, int src, int flags) fluid_mod_set_source1(fluid_mod_t* mod, int src, int flags)
{ {
mod->src1 = src; mod->src1 = src;
mod->flags1 = flags; mod->flags1 = flags;
} }
/* /*
* fluid_mod_set_source2 * fluid_mod_set_source2
*/ */
void void
fluid_mod_set_source2(fluid_mod_t* mod, int src, int flags) fluid_mod_set_source2(fluid_mod_t* mod, int src, int flags)
{ {
mod->src2 = src; mod->src2 = src;
mod->flags2 = flags; mod->flags2 = flags;
} }
/* /*
* fluid_mod_set_dest * fluid_mod_set_dest
*/ */
void void
fluid_mod_set_dest(fluid_mod_t* mod, int dest) fluid_mod_set_dest(fluid_mod_t* mod, int dest)
{ {
mod->dest = dest; mod->dest = dest;
} }
/* /*
* fluid_mod_set_amount * fluid_mod_set_amount
*/ */
void void
fluid_mod_set_amount(fluid_mod_t* mod, double amount) fluid_mod_set_amount(fluid_mod_t* mod, double amount)
{ {
mod->amount = (double) amount; mod->amount = (double) amount;
} }
int fluid_mod_get_source1(fluid_mod_t* mod) int fluid_mod_get_source1(fluid_mod_t* mod)
{ {
return mod->src1; return mod->src1;
} }
@@ -108,7 +108,7 @@ double fluid_mod_get_amount(fluid_mod_t* mod)
/* /*
* fluid_mod_get_value * fluid_mod_get_value
*/ */
fluid_real_t fluid_real_t
fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voice) fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voice)
{ {
fluid_real_t v1 = 0.0, v2 = 1.0; fluid_real_t v1 = 0.0, v2 = 1.0;
@@ -117,9 +117,9 @@ fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voic
if (chan == NULL) { if (chan == NULL) {
return 0.0f; return 0.0f;
} }
/* 'special treatment' for default controller /* 'special treatment' for default controller
* *
* Reference: SF2.01 section 8.4.2 * Reference: SF2.01 section 8.4.2
* *
* The GM default controller 'vel-to-filter cut off' is not clearly * The GM default controller 'vel-to-filter cut off' is not clearly
@@ -140,10 +140,10 @@ fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voic
* several SF2.1 sound fonts (where it is used only to turn it off). * several SF2.1 sound fonts (where it is used only to turn it off).
* */ * */
if ((mod->src2 == FLUID_MOD_VELOCITY) && if ((mod->src2 == FLUID_MOD_VELOCITY) &&
(mod->src1 == FLUID_MOD_VELOCITY) && (mod->src1 == FLUID_MOD_VELOCITY) &&
(mod->flags1 == (FLUID_MOD_GC | FLUID_MOD_UNIPOLAR (mod->flags1 == (FLUID_MOD_GC | FLUID_MOD_UNIPOLAR
| FLUID_MOD_NEGATIVE | FLUID_MOD_LINEAR)) && | FLUID_MOD_NEGATIVE | FLUID_MOD_LINEAR)) &&
(mod->flags2 == (FLUID_MOD_GC | FLUID_MOD_UNIPOLAR (mod->flags2 == (FLUID_MOD_GC | FLUID_MOD_UNIPOLAR
| FLUID_MOD_POSITIVE | FLUID_MOD_SWITCH)) && | FLUID_MOD_POSITIVE | FLUID_MOD_SWITCH)) &&
(mod->dest == GEN_FILTERFC)) { (mod->dest == GEN_FILTERFC)) {
if (voice->vel < 64){ if (voice->vel < 64){
@@ -152,37 +152,37 @@ fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voic
return (fluid_real_t) mod->amount * (127 - voice->vel) / 127; return (fluid_real_t) mod->amount * (127 - voice->vel) / 127;
} }
} }
/* get the initial value of the first source */ /* get the initial value of the first source */
if (mod->src1 > 0) { if (mod->src1 > 0) {
if (mod->flags1 & FLUID_MOD_CC) { if (mod->flags1 & FLUID_MOD_CC) {
v1 = fluid_channel_get_cc(chan, mod->src1); v1 = fluid_channel_get_cc(chan, mod->src1);
} else { /* source 1 is one of the direct controllers */ } else { /* source 1 is one of the direct controllers */
switch (mod->src1) { switch (mod->src1) {
case FLUID_MOD_NONE: /* SF 2.01 8.2.1 item 0: src enum=0 => value is 1 */ case FLUID_MOD_NONE: /* SF 2.01 8.2.1 item 0: src enum=0 => value is 1 */
v1 = range1; v1 = range1;
break; break;
case FLUID_MOD_VELOCITY: case FLUID_MOD_VELOCITY:
v1 = voice->vel; v1 = voice->vel;
break; break;
case FLUID_MOD_KEY: case FLUID_MOD_KEY:
v1 = voice->key; v1 = voice->key;
break; break;
case FLUID_MOD_KEYPRESSURE: case FLUID_MOD_KEYPRESSURE:
v1 = chan->key_pressure; v1 = chan->key_pressure;
break; break;
case FLUID_MOD_CHANNELPRESSURE: case FLUID_MOD_CHANNELPRESSURE:
v1 = chan->channel_pressure; v1 = chan->channel_pressure;
break; break;
case FLUID_MOD_PITCHWHEEL: case FLUID_MOD_PITCHWHEEL:
v1 = chan->pitch_bend; v1 = chan->pitch_bend;
range1 = 0x4000; range1 = 0x4000;
break; break;
case FLUID_MOD_PITCHWHEELSENS: case FLUID_MOD_PITCHWHEELSENS:
v1 = chan->pitch_wheel_sensitivity; v1 = chan->pitch_wheel_sensitivity;
break; break;
default: default:
v1 = 0.0; v1 = 0.0;
} }
} }
@@ -192,7 +192,7 @@ fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voic
v1 /= range1; v1 /= range1;
break; break;
case 1: /* linear, unipolar, negative */ case 1: /* linear, unipolar, negative */
v1 = 1.0f - v1 / range1; v1 = 1.0f - v1 / range1;
break; break;
case 2: /* linear, bipolar, positive */ case 2: /* linear, bipolar, positive */
v1 = -1.0f + 2.0f * v1 / range1; v1 = -1.0f + 2.0f * v1 / range1;
@@ -252,29 +252,29 @@ fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voic
v2 = fluid_channel_get_cc(chan, mod->src2); v2 = fluid_channel_get_cc(chan, mod->src2);
} else { } else {
switch (mod->src2) { switch (mod->src2) {
case FLUID_MOD_NONE: /* SF 2.01 8.2.1 item 0: src enum=0 => value is 1 */ case FLUID_MOD_NONE: /* SF 2.01 8.2.1 item 0: src enum=0 => value is 1 */
v2 = range2; v2 = range2;
break; break;
case FLUID_MOD_VELOCITY: case FLUID_MOD_VELOCITY:
v2 = voice->vel; v2 = voice->vel;
break; break;
case FLUID_MOD_KEY: case FLUID_MOD_KEY:
v2 = voice->key; v2 = voice->key;
break; break;
case FLUID_MOD_KEYPRESSURE: case FLUID_MOD_KEYPRESSURE:
v2 = chan->key_pressure; v2 = chan->key_pressure;
break; break;
case FLUID_MOD_CHANNELPRESSURE: case FLUID_MOD_CHANNELPRESSURE:
v2 = chan->channel_pressure; v2 = chan->channel_pressure;
break; break;
case FLUID_MOD_PITCHWHEEL: case FLUID_MOD_PITCHWHEEL:
v2 = chan->pitch_bend; v2 = chan->pitch_bend;
break; break;
case FLUID_MOD_PITCHWHEELSENS: case FLUID_MOD_PITCHWHEELSENS:
v2 = chan->pitch_wheel_sensitivity; v2 = chan->pitch_wheel_sensitivity;
break; break;
default: default:
v1 = 0.0f; v1 = 0.0f;
} }
} }
@@ -284,7 +284,7 @@ fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voic
v2 /= range2; v2 /= range2;
break; break;
case 1: /* linear, unipolar, negative */ case 1: /* linear, unipolar, negative */
v2 = 1.0f - v2 / range2; v2 = 1.0f - v2 / range2;
break; break;
case 2: /* linear, bipolar, positive */ case 2: /* linear, bipolar, positive */
v2 = -1.0f + 2.0f * v2 / range2; v2 = -1.0f + 2.0f * v2 / range2;
@@ -340,12 +340,12 @@ fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voic
/* /*
* fluid_mod_new * fluid_mod_new
*/ */
fluid_mod_t* fluid_mod_t*
fluid_mod_new() fluid_mod_new()
{ {
fluid_mod_t* mod = FLUID_NEW(fluid_mod_t); fluid_mod_t* mod = FLUID_NEW(fluid_mod_t);
if (mod == NULL) { if (mod == NULL) {
FLUID_LOG(FLUID_ERR, "Out of memory"); FLUID_LOG(FLUID_ERR, "Out of memory");
return NULL; return NULL;
} }
return mod; return mod;
@@ -362,7 +362,7 @@ fluid_mod_delete(fluid_mod_t * mod)
/* /*
* fluid_mod_test_identity * fluid_mod_test_identity
*/ */
/* Purpose: /* Purpose:
* Checks, if two modulators are identical. * Checks, if two modulators are identical.
* SF2.01 section 9.5.1 page 69, 'bullet' 3 defines 'identical'. * SF2.01 section 9.5.1 page 69, 'bullet' 3 defines 'identical'.
@@ -384,7 +384,7 @@ void fluid_dump_modulator(fluid_mod_t * mod){
int flags1=mod->flags1; int flags1=mod->flags1;
int flags2=mod->flags2; int flags2=mod->flags2;
fluid_real_t amount=(fluid_real_t)mod->amount; fluid_real_t amount=(fluid_real_t)mod->amount;
printf("Src: "); printf("Src: ");
if (flags1 & FLUID_MOD_CC){ if (flags1 & FLUID_MOD_CC){
printf("MIDI CC=%i",src1); printf("MIDI CC=%i",src1);
@@ -408,8 +408,8 @@ void fluid_dump_modulator(fluid_mod_t * mod){
printf("(unknown: %i)", src1); printf("(unknown: %i)", src1);
}; /* switch src1 */ }; /* switch src1 */
}; /* if not CC */ }; /* if not CC */
if (flags1 & FLUID_MOD_NEGATIVE){printf("- ");} else {printf("+ ");}; if (flags1 & FLUID_MOD_NEGATIVE){printf("- ");} else {printf("+ ");};
if (flags1 & FLUID_MOD_BIPOLAR){printf("bip ");} else {printf("unip ");}; if (flags1 & FLUID_MOD_BIPOLAR){printf("bip ");} else {printf("unip ");};
printf("-> "); printf("-> ");
switch(dest){ switch(dest){
case GEN_FILTERQ: printf("Q"); break; case GEN_FILTERQ: printf("Q"); break;
+2 -2
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -25,7 +25,7 @@
#include "fluid_conv.h" #include "fluid_conv.h"
void fluid_mod_clone(fluid_mod_t* mod, fluid_mod_t* src); void fluid_mod_clone(fluid_mod_t* mod, fluid_mod_t* src);
fluid_real_t fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voice); fluid_real_t fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voice);
void fluid_dump_modulator(fluid_mod_t * mod); void fluid_dump_modulator(fluid_mod_t * mod);
#define fluid_mod_has_source(mod,cc,ctrl) \ #define fluid_mod_has_source(mod,cc,ctrl) \
+28 -88
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -37,141 +37,81 @@
#define FLUID_FRACT_MAX ((double)4294967296.0) #define FLUID_FRACT_MAX ((double)4294967296.0)
/* fluid_phase_t /* fluid_phase_t
* Purpose: * Purpose:
* Playing pointer for voice playback * Playing pointer for voice playback
* *
* When a sample is played back at a different pitch, the playing pointer in the * When a sample is played back at a different pitch, the playing pointer in the
* source sample will not advance exactly one sample per output sample. * source sample will not advance exactly one sample per output sample.
* This playing pointer is implemented using fluid_phase_t. * This playing pointer is implemented using fluid_phase_t.
* It is a 64 bit number. The higher 32 bits contain the 'index' (number of * It is a 64 bit number. The higher 32 bits contain the 'index' (number of
* the current sample), the lower 32 bits the fractional part. * the current sample), the lower 32 bits the fractional part.
* Access is possible in two ways:
* -through the 64 bit part 'b64', if the architecture supports 64 bit integers
* -through 'index' and 'fract'
* Note: b64 and index / fract share the same memory location!
*/ */
typedef union { typedef unsigned long long fluid_phase_t;
struct{
/* Note, that the two 32-bit ints form a 64-bit int! */
#ifdef WORDS_BIGENDIAN
sint32 index;
uint32 fract;
#else
uint32 fract;
sint32 index;
#endif
} b32;
#ifdef USE_LONGLONG
long long b64;
#endif
} fluid_phase_t;
/* Purpose: /* Purpose:
* Set a to b. * Set a to b.
* a: fluid_phase_t * a: fluid_phase_t
* b: fluid_phase_t * b: fluid_phase_t
*/ */
#ifdef USE_LONGLONG
#define fluid_phase_set(a,b) a=b; #define fluid_phase_set(a,b) a=b;
#else
#define fluid_phase_set(a, b) { \
(a).b32.fract = (b).b32.fract; \
(a).b32.index = (b).b32.index; \
}
#endif
#define fluid_phase_set_int(a, b) { \ #define fluid_phase_set_int(a, b) ((a) = ((unsigned long long)(b)) << 32)
(a).b32.index = (sint32) (b); \
(a).b32.fract = 0; \
}
/* Purpose: /* Purpose:
* Sets the phase a to a phase increment given in b. * Sets the phase a to a phase increment given in b.
* For example, assume b is 0.9. After setting a to it, adding a to * For example, assume b is 0.9. After setting a to it, adding a to
* the playing pointer will advance it by 0.9 samples. */ * the playing pointer will advance it by 0.9 samples. */
#define fluid_phase_set_float(a, b) { \ #define fluid_phase_set_float(a, b) \
(a).b32.index = (sint32) (b); \ (a) = (((unsigned long long)(b)) << 32) \
(a).b32.fract = (uint32) (((double)(b) - (double)((a).b32.index)) * (double)FLUID_FRACT_MAX); \ | (uint32) (((double)(b) - (int)(b)) * (double)FLUID_FRACT_MAX)
}
/* create a fluid_phase_t from an index and a fraction value */
#define fluid_phase_from_index_fract(index, fract) \
((((unsigned long long)(index)) << 32) + (fract))
/* Purpose: /* Purpose:
* Return the index and the fractional part, respectively. */ * Return the index and the fractional part, respectively. */
#define fluid_phase_index(_x) \ #define fluid_phase_index(_x) \
((int)(_x).b32.index) ((unsigned int)((_x) >> 32))
#define fluid_phase_fract(_x) \ #define fluid_phase_fract(_x) \
((_x).b32.fract) ((uint32)((_x) & 0xFFFFFFFF))
/* Get the phase index with fractional rounding */
#define fluid_phase_index_round(_x) \
((unsigned int)(((_x) + 0x80000000) >> 32))
/* Purpose: /* Purpose:
* Takes the fractional part of the argument phase and * Takes the fractional part of the argument phase and
* calculates the corresponding position in the interpolation table. * calculates the corresponding position in the interpolation table.
* The fractional position of the playing pointer is calculated with a quite high * The fractional position of the playing pointer is calculated with a quite high
* resolution (32 bits). It would be unpractical to keep a set of interpolation * resolution (32 bits). It would be unpractical to keep a set of interpolation
* coefficients for each possible fractional part... * coefficients for each possible fractional part...
*/ */
#define fluid_phase_fract_to_tablerow(_x) \ #define fluid_phase_fract_to_tablerow(_x) \
((int)(((_x).b32.fract & FLUID_INTERP_BITS_MASK) >> FLUID_INTERP_BITS_SHIFT)) ((unsigned int)(fluid_phase_fract(_x) & FLUID_INTERP_BITS_MASK) >> FLUID_INTERP_BITS_SHIFT)
#define fluid_phase_double(_x) \ #define fluid_phase_double(_x) \
((double)((_x).b32.index) + ((double)((_x).b32.fract) / FLUID_FRACT_MAX)) ((double)(fluid_phase_index(_x)) + ((double)fluid_phase_fract(_x) / FLUID_FRACT_MAX))
/* Purpose: /* Purpose:
* Advance a by a step of b (both are fluid_phase_t). * Advance a by a step of b (both are fluid_phase_t).
*/ */
#ifdef USE_LONGLONG #define fluid_phase_incr(a, b) a += b
#define fluid_phase_incr(a, b) (a).b64 += (b).b64;
#else
/* The idea to use (a).index += (b).index + ((a).fract < (b).fract) to
handle wrap-arounds comes from Mozilla's macros to handle 64-bit
integer on 32-bit platforms. Header prlong.h in the NSPR
library. www.mozilla.org. */
#define fluid_phase_incr(a, b) { \
(a).b32.fract += (b).b32.fract; \
(a).b32.index += (b).b32.index + ((a).b32.fract < (b).b32.fract); \
}
#endif
/* Purpose: /* Purpose:
* Subtract b from a (both are fluid_phase_t). * Subtract b from a (both are fluid_phase_t).
*/ */
#ifdef USE_LONGLONG #define fluid_phase_decr(a, b) a -= b
#define fluid_phase_decr(a, b) a-=b;
#else
#define fluid_phase_decr(a, b) { \
(a).b32.index -= b.b32.index - ((a).b32.fract < (b).b32.fract); \
(a).b32.fract -= b.b32.fract; \
}
#endif
/* Purpose: /* Purpose:
* Subtract b samples from a. * Subtract b samples from a.
*/ */
#define fluid_phase_sub_int(a, b) { (a).b32.index -= b; } #define fluid_phase_sub_int(a, b) ((a) -= (unsigned long long)(b) << 32)
#if 0
#define fluid_phase_fract(_x) \
((fluid_real_t)((double)((_x).fract) / FLUID_FRACT_MAX))
#define fluid_phase_lt(a, b) \
(((a).index < (b).index) || (((a).index == (b).index) && ((a).fract < (b).fract)))
#define fluid_phase_gt(a, b) \
(((a).index > (b).index) || (((a).index == (b).index) && ((a).fract > (b).fract)))
#define fluid_phase_eq(a, b) \
(((a).index == (b).index) && ((a).fract == (b).fract))
#endif
/* Purpose: /* Purpose:
* The playing pointer is _phase. How many output samples are produced, until the point _p1 in the sample is reached, * Creates the expression a.index++. */
* if _phase advances in steps of _incr? #define fluid_phase_index_plusplus(a) (((a) += 0x100000000LL)
*/
#define fluid_phase_steps(_phase,_index,_incr) \
(int)(((double)(_index) - fluid_phase_double(_phase)) / (double)_incr)
/* Purpose:
* Creates the expression a.index++.
* It is slightly different, when USE_LONGLONG is turned on. */
#define fluid_phase_index_plusplus(a) (((a).b32.index)++)
#endif /* _FLUID_PHASE_H */ #endif /* _FLUID_PHASE_H */
+112 -110
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -21,7 +21,7 @@
#include "fluid_ramsfont.h" #include "fluid_ramsfont.h"
#include "fluid_sys.h" #include "fluid_sys.h"
#include "fluid_synth.h" #include "fluid_synth.h"
/* thenumber of samples before the start and after the end */ /* thenumber of samples before the start and after the end */
#define SAMPLE_LOOP_MARGIN 8 #define SAMPLE_LOOP_MARGIN 8
@@ -40,12 +40,12 @@ fluid_ramsfont_create_sfont()
{ {
fluid_sfont_t* sfont; fluid_sfont_t* sfont;
fluid_ramsfont_t* ramsfont; fluid_ramsfont_t* ramsfont;
ramsfont = new_fluid_ramsfont(); ramsfont = new_fluid_ramsfont();
if (ramsfont == NULL) { if (ramsfont == NULL) {
return NULL; return NULL;
} }
sfont = FLUID_NEW(fluid_sfont_t); sfont = FLUID_NEW(fluid_sfont_t);
if (sfont == NULL) { if (sfont == NULL) {
FLUID_LOG(FLUID_ERR, "Out of memory"); FLUID_LOG(FLUID_ERR, "Out of memory");
@@ -130,33 +130,35 @@ int fluid_ramsfont_sfont_iteration_next(fluid_sfont_t* sfont, fluid_preset_t* pr
int fluid_rampreset_preset_delete(fluid_preset_t* preset) int fluid_rampreset_preset_delete(fluid_preset_t* preset)
{ {
FLUID_FREE(preset); FLUID_FREE(preset);
printf("TODO: free modulators\n");
/* TODO: free modulators */
return 0; return 0;
} }
char* fluid_rampreset_preset_get_name(fluid_preset_t* preset) char* fluid_rampreset_preset_get_name(fluid_preset_t* preset)
{ {
return fluid_rampreset_get_name((fluid_rampreset_t*) preset->data); return fluid_rampreset_get_name((fluid_rampreset_t*) preset->data);
} }
int fluid_rampreset_preset_get_banknum(fluid_preset_t* preset) int fluid_rampreset_preset_get_banknum(fluid_preset_t* preset)
{ {
return fluid_rampreset_get_banknum((fluid_rampreset_t*) preset->data); return fluid_rampreset_get_banknum((fluid_rampreset_t*) preset->data);
} }
int fluid_rampreset_preset_get_num(fluid_preset_t* preset) int fluid_rampreset_preset_get_num(fluid_preset_t* preset)
{ {
return fluid_rampreset_get_num((fluid_rampreset_t*) preset->data); return fluid_rampreset_get_num((fluid_rampreset_t*) preset->data);
} }
int fluid_rampreset_preset_noteon(fluid_preset_t* preset, fluid_synth_t* synth, int chan, int key, int vel) int fluid_rampreset_preset_noteon(fluid_preset_t* preset, fluid_synth_t* synth, int chan, int key, int vel)
{ {
return fluid_rampreset_noteon((fluid_rampreset_t*) preset->data, synth, chan, key, vel); return fluid_rampreset_noteon((fluid_rampreset_t*) preset->data, synth, chan, key, vel);
} }
/*************************************************************** /***************************************************************
* *
* SFONT * SFONT
@@ -214,7 +216,7 @@ int delete_fluid_ramsfont(fluid_ramsfont_t* sfont)
delete_fluid_rampreset(preset); delete_fluid_rampreset(preset);
preset = sfont->preset; preset = sfont->preset;
} }
FLUID_FREE(sfont); FLUID_FREE(sfont);
return FLUID_OK; return FLUID_OK;
} }
@@ -242,7 +244,7 @@ fluid_ramsfont_set_name(fluid_ramsfont_t* sfont, char * name)
* *
* Add a preset to the SoundFont * Add a preset to the SoundFont
*/ */
int fluid_ramsfont_add_preset(fluid_ramsfont_t* sfont, fluid_rampreset_t* preset) int fluid_ramsfont_add_preset(fluid_ramsfont_t* sfont, fluid_rampreset_t* preset)
{ {
fluid_rampreset_t *cur, *prev; fluid_rampreset_t *cur, *prev;
if (sfont->preset == NULL) { if (sfont->preset == NULL) {
@@ -253,7 +255,7 @@ int fluid_ramsfont_add_preset(fluid_ramsfont_t* sfont, fluid_rampreset_t* preset
cur = sfont->preset; cur = sfont->preset;
prev = NULL; prev = NULL;
while (cur != NULL) { while (cur != NULL) {
if ((preset->bank < cur->bank) if ((preset->bank < cur->bank)
|| ((preset->bank == cur->bank) && (preset->num < cur->num))) { || ((preset->bank == cur->bank) && (preset->num < cur->num))) {
if (prev == NULL) { if (prev == NULL) {
preset->next = cur; preset->next = cur;
@@ -285,7 +287,7 @@ int fluid_ramsfont_add_izone(fluid_ramsfont_t* sfont,
- add the sample to the list of samples - add the sample to the list of samples
*/ */
int err; int err;
fluid_rampreset_t* preset = fluid_ramsfont_get_preset(sfont, bank, num); fluid_rampreset_t* preset = fluid_ramsfont_get_preset(sfont, bank, num);
if (preset == NULL) { if (preset == NULL) {
// Create it // Create it
@@ -293,27 +295,27 @@ int fluid_ramsfont_add_izone(fluid_ramsfont_t* sfont,
if (preset == NULL) { if (preset == NULL) {
return FLUID_FAILED; return FLUID_FAILED;
} }
preset->bank = bank; preset->bank = bank;
preset->num = num; preset->num = num;
err = fluid_rampreset_add_sample(preset, sample, lokey, hikey); err = fluid_rampreset_add_sample(preset, sample, lokey, hikey);
if (err != FLUID_OK) { if (err != FLUID_OK) {
return FLUID_FAILED; return FLUID_FAILED;
} }
// sort the preset // sort the preset
fluid_ramsfont_add_preset(sfont, preset); fluid_ramsfont_add_preset(sfont, preset);
} else { } else {
// just add it // just add it
err = fluid_rampreset_add_sample(preset, sample, lokey, hikey); err = fluid_rampreset_add_sample(preset, sample, lokey, hikey);
if (err != FLUID_OK) { if (err != FLUID_OK) {
return FLUID_FAILED; return FLUID_FAILED;
} }
} }
sfont->sample = fluid_list_append(sfont->sample, sample); sfont->sample = fluid_list_append(sfont->sample, sample);
return FLUID_OK; return FLUID_OK;
} }
@@ -343,12 +345,12 @@ int fluid_ramsfont_remove_izone(fluid_ramsfont_t* sfont,
int fluid_ramsfont_izone_set_gen(fluid_ramsfont_t* sfont, int fluid_ramsfont_izone_set_gen(fluid_ramsfont_t* sfont,
unsigned int bank, unsigned int num, fluid_sample_t* sample, unsigned int bank, unsigned int num, fluid_sample_t* sample,
int gen_type, float value) { int gen_type, float value) {
fluid_rampreset_t* preset = fluid_ramsfont_get_preset(sfont, bank, num); fluid_rampreset_t* preset = fluid_ramsfont_get_preset(sfont, bank, num);
if (preset == NULL) { if (preset == NULL) {
return FLUID_FAILED; return FLUID_FAILED;
} }
return fluid_rampreset_izone_set_gen(preset, sample, gen_type, value); return fluid_rampreset_izone_set_gen(preset, sample, gen_type, value);
} }
@@ -360,14 +362,14 @@ int fluid_ramsfont_izone_set_loop(fluid_ramsfont_t* sfont,
if (preset == NULL) { if (preset == NULL) {
return FLUID_FAILED; return FLUID_FAILED;
} }
return fluid_rampreset_izone_set_loop(preset, sample, on, loopstart, loopend); return fluid_rampreset_izone_set_loop(preset, sample, on, loopstart, loopend);
} }
/* /*
* fluid_ramsfont_get_preset * fluid_ramsfont_get_preset
*/ */
fluid_rampreset_t* fluid_ramsfont_get_preset(fluid_ramsfont_t* sfont, unsigned int bank, unsigned int num) fluid_rampreset_t* fluid_ramsfont_get_preset(fluid_ramsfont_t* sfont, unsigned int bank, unsigned int num)
{ {
fluid_rampreset_t* preset = sfont->preset; fluid_rampreset_t* preset = sfont->preset;
while (preset != NULL) { while (preset != NULL) {
@@ -415,12 +417,12 @@ struct _fluid_rampreset_voice_t {
/* /*
* new_fluid_rampreset * new_fluid_rampreset
*/ */
fluid_rampreset_t* fluid_rampreset_t*
new_fluid_rampreset(fluid_ramsfont_t* sfont) new_fluid_rampreset(fluid_ramsfont_t* sfont)
{ {
fluid_rampreset_t* preset = FLUID_NEW(fluid_rampreset_t); fluid_rampreset_t* preset = FLUID_NEW(fluid_rampreset_t);
if (preset == NULL) { if (preset == NULL) {
FLUID_LOG(FLUID_ERR, "Out of memory"); FLUID_LOG(FLUID_ERR, "Out of memory");
return NULL; return NULL;
} }
preset->next = NULL; preset->next = NULL;
@@ -437,13 +439,13 @@ new_fluid_rampreset(fluid_ramsfont_t* sfont)
/* /*
* delete_fluid_rampreset * delete_fluid_rampreset
*/ */
int int
delete_fluid_rampreset(fluid_rampreset_t* preset) delete_fluid_rampreset(fluid_rampreset_t* preset)
{ {
int err = FLUID_OK; int err = FLUID_OK;
fluid_preset_zone_t* zone; fluid_preset_zone_t* zone;
fluid_rampreset_voice_t *data; fluid_rampreset_voice_t *data;
if (preset->global_zone != NULL) { if (preset->global_zone != NULL) {
if (delete_fluid_preset_zone(preset->global_zone) != FLUID_OK) { if (delete_fluid_preset_zone(preset->global_zone) != FLUID_OK) {
err = FLUID_FAILED; err = FLUID_FAILED;
@@ -458,37 +460,37 @@ delete_fluid_rampreset(fluid_rampreset_t* preset)
} }
zone = preset->zone; zone = preset->zone;
} }
if (preset->presetvoices != NULL) { if (preset->presetvoices != NULL) {
fluid_list_t *tmp = preset->presetvoices, *next; fluid_list_t *tmp = preset->presetvoices, *next;
while (tmp) { while (tmp) {
data = (fluid_rampreset_voice_t *)(tmp->data); data = (fluid_rampreset_voice_t *)(tmp->data);
FLUID_FREE(data); FLUID_FREE(data);
next = tmp->next; next = tmp->next;
FLUID_FREE(tmp); FLUID_FREE(tmp);
tmp = next; tmp = next;
} }
} }
preset->presetvoices = NULL; preset->presetvoices = NULL;
FLUID_FREE(preset); FLUID_FREE(preset);
return err; return err;
} }
int int
fluid_rampreset_get_banknum(fluid_rampreset_t* preset) fluid_rampreset_get_banknum(fluid_rampreset_t* preset)
{ {
return preset->bank; return preset->bank;
} }
int int
fluid_rampreset_get_num(fluid_rampreset_t* preset) fluid_rampreset_get_num(fluid_rampreset_t* preset)
{ {
return preset->num; return preset->num;
} }
char* char*
fluid_rampreset_get_name(fluid_rampreset_t* preset) fluid_rampreset_get_name(fluid_rampreset_t* preset)
{ {
return preset->name; return preset->name;
@@ -497,7 +499,7 @@ fluid_rampreset_get_name(fluid_rampreset_t* preset)
/* /*
* fluid_rampreset_next * fluid_rampreset_next
*/ */
fluid_rampreset_t* fluid_rampreset_t*
fluid_rampreset_next(fluid_rampreset_t* preset) fluid_rampreset_next(fluid_rampreset_t* preset)
{ {
return preset->next; return preset->next;
@@ -507,7 +509,7 @@ fluid_rampreset_next(fluid_rampreset_t* preset)
/* /*
* fluid_rampreset_add_zone * fluid_rampreset_add_zone
*/ */
int int
fluid_rampreset_add_zone(fluid_rampreset_t* preset, fluid_preset_zone_t* zone) fluid_rampreset_add_zone(fluid_rampreset_t* preset, fluid_preset_zone_t* zone)
{ {
if (preset->zone == NULL) { if (preset->zone == NULL) {
@@ -527,7 +529,7 @@ fluid_rampreset_add_zone(fluid_rampreset_t* preset, fluid_preset_zone_t* zone)
int fluid_rampreset_add_sample(fluid_rampreset_t* preset, fluid_sample_t* sample, int lokey, int hikey) int fluid_rampreset_add_sample(fluid_rampreset_t* preset, fluid_sample_t* sample, int lokey, int hikey)
{ {
/* create a new instrument zone, with the given sample */ /* create a new instrument zone, with the given sample */
/* one preset zone */ /* one preset zone */
if (preset->zone == NULL) { if (preset->zone == NULL) {
fluid_preset_zone_t* zone; fluid_preset_zone_t* zone;
@@ -535,17 +537,17 @@ int fluid_rampreset_add_sample(fluid_rampreset_t* preset, fluid_sample_t* sample
if (zone == NULL) { if (zone == NULL) {
return FLUID_FAILED; return FLUID_FAILED;
} }
/* its instrument */ /* its instrument */
zone->inst = (fluid_inst_t*) new_fluid_inst(); zone->inst = (fluid_inst_t*) new_fluid_inst();
if (zone->inst == NULL) { if (zone->inst == NULL) {
delete_fluid_preset_zone(zone); delete_fluid_preset_zone(zone);
return FLUID_FAILED; return FLUID_FAILED;
} }
fluid_rampreset_add_zone(preset, zone); fluid_rampreset_add_zone(preset, zone);
} }
/* add an instrument zone for each sample */ /* add an instrument zone for each sample */
{ {
fluid_inst_t* inst = fluid_preset_zone_get_inst(preset->zone); fluid_inst_t* inst = fluid_preset_zone_get_inst(preset->zone);
@@ -553,20 +555,20 @@ int fluid_rampreset_add_sample(fluid_rampreset_t* preset, fluid_sample_t* sample
if (izone == NULL) { if (izone == NULL) {
return FLUID_FAILED; return FLUID_FAILED;
} }
if (fluid_inst_add_zone(inst, izone) != FLUID_OK) { if (fluid_inst_add_zone(inst, izone) != FLUID_OK) {
delete_fluid_inst_zone(izone); delete_fluid_inst_zone(izone);
return FLUID_FAILED; return FLUID_FAILED;
} }
izone->sample = sample; izone->sample = sample;
izone->keylo = lokey; izone->keylo = lokey;
izone->keyhi = hikey; izone->keyhi = hikey;
// give the preset the name of the sample // give the preset the name of the sample
FLUID_MEMCPY(preset->name, sample->name, 20); FLUID_MEMCPY(preset->name, sample->name, 20);
} }
return FLUID_OK; return FLUID_OK;
} }
@@ -574,9 +576,9 @@ fluid_inst_zone_t* fluid_rampreset_izoneforsample(fluid_rampreset_t* preset, flu
{ {
fluid_inst_t* inst; fluid_inst_t* inst;
fluid_inst_zone_t* izone; fluid_inst_zone_t* izone;
if (preset->zone == NULL) return NULL; if (preset->zone == NULL) return NULL;
inst = fluid_preset_zone_get_inst(preset->zone); inst = fluid_preset_zone_get_inst(preset->zone);
izone = inst->zone; izone = inst->zone;
while (izone) { while (izone) {
@@ -591,17 +593,17 @@ int fluid_rampreset_izone_set_loop(fluid_rampreset_t* preset, fluid_sample_t* sa
int on, float loopstart, float loopend) { int on, float loopstart, float loopend) {
fluid_inst_zone_t* izone = fluid_rampreset_izoneforsample(preset, sample); fluid_inst_zone_t* izone = fluid_rampreset_izoneforsample(preset, sample);
short coarse, fine; short coarse, fine;
if (izone == NULL) if (izone == NULL)
return FLUID_FAILED; return FLUID_FAILED;
if (!on) { if (!on) {
izone->gen[GEN_SAMPLEMODE].flags = GEN_SET; izone->gen[GEN_SAMPLEMODE].flags = GEN_SET;
izone->gen[GEN_SAMPLEMODE].val = FLUID_UNLOOPED; izone->gen[GEN_SAMPLEMODE].val = FLUID_UNLOOPED;
fluid_rampreset_updatevoices(preset, GEN_SAMPLEMODE, FLUID_UNLOOPED); fluid_rampreset_updatevoices(preset, GEN_SAMPLEMODE, FLUID_UNLOOPED);
return FLUID_OK; return FLUID_OK;
} }
/* NOTE : We should check that (sample->startloop + loopStart <= sample->endloop - loopend - 32) */ /* NOTE : We should check that (sample->startloop + loopStart <= sample->endloop - loopend - 32) */
/* loopstart */ /* loopstart */
@@ -645,12 +647,12 @@ int fluid_rampreset_izone_set_loop(fluid_rampreset_t* preset, fluid_sample_t* sa
izone->gen[GEN_SAMPLEMODE].flags = GEN_SET; izone->gen[GEN_SAMPLEMODE].flags = GEN_SET;
izone->gen[GEN_SAMPLEMODE].val = FLUID_LOOP_DURING_RELEASE; izone->gen[GEN_SAMPLEMODE].val = FLUID_LOOP_DURING_RELEASE;
fluid_rampreset_updatevoices(preset, GEN_SAMPLEMODE, FLUID_LOOP_DURING_RELEASE); fluid_rampreset_updatevoices(preset, GEN_SAMPLEMODE, FLUID_LOOP_DURING_RELEASE);
/* If the loop points are the whole samples, we are supposed to /* If the loop points are the whole samples, we are supposed to
copy the frames around in the margins (the start to the end margin and copy the frames around in the margins (the start to the end margin and
the end to the start margin), but it works fine without this. Maybe some time the end to the start margin), but it works fine without this. Maybe some time
it will be needed (see SAMPLE_LOOP_MARGIN) -- Antoie Schmitt May 2003 */ it will be needed (see SAMPLE_LOOP_MARGIN) -- Antoie Schmitt May 2003 */
return FLUID_OK; return FLUID_OK;
} }
@@ -659,12 +661,12 @@ int fluid_rampreset_izone_set_gen(fluid_rampreset_t* preset, fluid_sample_t* sam
fluid_inst_zone_t* izone = fluid_rampreset_izoneforsample(preset, sample); fluid_inst_zone_t* izone = fluid_rampreset_izoneforsample(preset, sample);
if (izone == NULL) if (izone == NULL)
return FLUID_FAILED; return FLUID_FAILED;
izone->gen[gen_type].flags = GEN_SET; izone->gen[gen_type].flags = GEN_SET;
izone->gen[gen_type].val = value; izone->gen[gen_type].val = value;
fluid_rampreset_updatevoices(preset, gen_type, value); fluid_rampreset_updatevoices(preset, gen_type, value);
return FLUID_OK; return FLUID_OK;
} }
@@ -672,7 +674,7 @@ int fluid_rampreset_remove_izone(fluid_rampreset_t* preset, fluid_sample_t* samp
fluid_inst_t* inst; fluid_inst_t* inst;
fluid_inst_zone_t* izone, * prev; fluid_inst_zone_t* izone, * prev;
int found = 0; int found = 0;
if (preset->zone == NULL) return FLUID_FAILED; if (preset->zone == NULL) return FLUID_FAILED;
inst = fluid_preset_zone_get_inst(preset->zone); inst = fluid_preset_zone_get_inst(preset->zone);
izone = inst->zone; izone = inst->zone;
@@ -694,7 +696,7 @@ int fluid_rampreset_remove_izone(fluid_rampreset_t* preset, fluid_sample_t* samp
} }
if (!found) if (!found)
return FLUID_FAILED; return FLUID_FAILED;
// stop all the voices that use this sample, so that // stop all the voices that use this sample, so that
// the sample can be cleared up // the sample can be cleared up
{ {
@@ -719,23 +721,23 @@ int fluid_rampreset_remove_izone(fluid_rampreset_t* preset, fluid_sample_t* samp
/* /*
* fluid_rampreset_remembervoice * fluid_rampreset_remembervoice
*/ */
int int
fluid_rampreset_remembervoice(fluid_rampreset_t* preset, fluid_voice_t* voice) { fluid_rampreset_remembervoice(fluid_rampreset_t* preset, fluid_voice_t* voice) {
/* stores the voice and the its ID in the preset for later update on gen_set */ /* stores the voice and the its ID in the preset for later update on gen_set */
fluid_rampreset_voice_t *presetvoice = FLUID_NEW(fluid_rampreset_voice_t); fluid_rampreset_voice_t *presetvoice = FLUID_NEW(fluid_rampreset_voice_t);
if (presetvoice == NULL) { if (presetvoice == NULL) {
FLUID_LOG(FLUID_ERR, "Out of memory"); FLUID_LOG(FLUID_ERR, "Out of memory");
return FLUID_FAILED; return FLUID_FAILED;
} }
presetvoice->voice = voice; presetvoice->voice = voice;
presetvoice->voiceID = fluid_voice_get_id(voice); presetvoice->voiceID = fluid_voice_get_id(voice);
preset->presetvoices = fluid_list_append(preset->presetvoices, (void *)presetvoice); preset->presetvoices = fluid_list_append(preset->presetvoices, (void *)presetvoice);
if (preset->presetvoices == NULL) { if (preset->presetvoices == NULL) {
FLUID_FREE(presetvoice); FLUID_FREE(presetvoice);
FLUID_LOG(FLUID_ERR, "Out of memory"); FLUID_LOG(FLUID_ERR, "Out of memory");
return FLUID_FAILED; return FLUID_FAILED;
} }
return FLUID_OK; return FLUID_OK;
} }
@@ -743,10 +745,10 @@ fluid_rampreset_remembervoice(fluid_rampreset_t* preset, fluid_voice_t* voice) {
/* /*
* fluid_rampreset_updatevoice * fluid_rampreset_updatevoice
*/ */
void void
fluid_rampreset_updatevoices(fluid_rampreset_t* preset, int gen_type, float val) { fluid_rampreset_updatevoices(fluid_rampreset_t* preset, int gen_type, float val) {
fluid_list_t *tmp = preset->presetvoices, *prev = NULL, *next; fluid_list_t *tmp = preset->presetvoices, *prev = NULL, *next;
/* walk the presetvoice to update them if they are still active and ours. /* walk the presetvoice to update them if they are still active and ours.
If their ID has changed or their state is not playing, they are not ours, so we forget them If their ID has changed or their state is not playing, they are not ours, so we forget them
*/ */
@@ -756,7 +758,7 @@ fluid_rampreset_updatevoices(fluid_rampreset_t* preset, int gen_type, float val)
if (!fluid_voice_is_playing(voice) || (fluid_voice_get_id(voice) != presetvoice->voiceID)) { if (!fluid_voice_is_playing(voice) || (fluid_voice_get_id(voice) != presetvoice->voiceID)) {
/* forget it */ /* forget it */
FLUID_FREE(presetvoice); FLUID_FREE(presetvoice);
/* unlink it */ /* unlink it */
next = tmp->next; next = tmp->next;
FLUID_FREE(tmp); FLUID_FREE(tmp);
@@ -764,15 +766,15 @@ fluid_rampreset_updatevoices(fluid_rampreset_t* preset, int gen_type, float val)
prev->next = next; prev->next = next;
} else { } else {
preset->presetvoices = next; preset->presetvoices = next;
} }
tmp = next; tmp = next;
} else { } else {
/* update */ /* update */
fluid_voice_gen_set(voice, gen_type, val); fluid_voice_gen_set(voice, gen_type, val);
fluid_voice_update_param(voice, gen_type); fluid_voice_update_param(voice, gen_type);
/* next */ /* next */
prev = tmp; prev = tmp;
tmp = tmp->next; tmp = tmp->next;
@@ -784,8 +786,8 @@ fluid_rampreset_updatevoices(fluid_rampreset_t* preset, int gen_type, float val)
/* /*
* fluid_rampreset_noteon * fluid_rampreset_noteon
*/ */
int int
fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan, int key, int vel) fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan, int key, int vel)
{ {
fluid_preset_zone_t *preset_zone; fluid_preset_zone_t *preset_zone;
fluid_inst_t* inst; fluid_inst_t* inst;
@@ -796,7 +798,7 @@ fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan
fluid_mod_t * mod_list[FLUID_NUM_MOD]; /* list for 'sorting' preset modulators */ fluid_mod_t * mod_list[FLUID_NUM_MOD]; /* list for 'sorting' preset modulators */
int mod_list_count; int mod_list_count;
int i; int i;
/* run thru all the zones of this preset */ /* run thru all the zones of this preset */
preset_zone = preset->zone; preset_zone = preset->zone;
while (preset_zone != NULL) { while (preset_zone != NULL) {
@@ -804,45 +806,45 @@ fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan
/* check if the note falls into the key and velocity range of this /* check if the note falls into the key and velocity range of this
preset */ preset */
if (fluid_preset_zone_inside_range(preset_zone, key, vel)) { if (fluid_preset_zone_inside_range(preset_zone, key, vel)) {
inst = fluid_preset_zone_get_inst(preset_zone); inst = fluid_preset_zone_get_inst(preset_zone);
global_inst_zone = fluid_inst_get_global_zone(inst); global_inst_zone = fluid_inst_get_global_zone(inst);
/* run thru all the zones of this instrument */ /* run thru all the zones of this instrument */
inst_zone = fluid_inst_get_zone(inst); inst_zone = fluid_inst_get_zone(inst);
while (inst_zone != NULL) { while (inst_zone != NULL) {
/* make sure this instrument zone has a valid sample */ /* make sure this instrument zone has a valid sample */
sample = fluid_inst_zone_get_sample(inst_zone); sample = fluid_inst_zone_get_sample(inst_zone);
if (fluid_sample_in_rom(sample) || (sample == NULL)) { if (fluid_sample_in_rom(sample) || (sample == NULL)) {
inst_zone = fluid_inst_zone_next(inst_zone); inst_zone = fluid_inst_zone_next(inst_zone);
continue; continue;
} }
/* check if the note falls into the key and velocity range of this /* check if the note falls into the key and velocity range of this
instrument */ instrument */
if (fluid_inst_zone_inside_range(inst_zone, key, vel) && (sample != NULL)) { if (fluid_inst_zone_inside_range(inst_zone, key, vel) && (sample != NULL)) {
/* this is a good zone. allocate a new synthesis process and /* this is a good zone. allocate a new synthesis process and
initialize it */ initialize it */
voice = fluid_synth_alloc_voice(synth, sample, chan, key, vel); voice = fluid_synth_alloc_voice(synth, sample, chan, key, vel);
if (voice == NULL) { if (voice == NULL) {
return FLUID_FAILED; return FLUID_FAILED;
} }
if (fluid_rampreset_remembervoice(preset, voice) != FLUID_OK) { if (fluid_rampreset_remembervoice(preset, voice) != FLUID_OK) {
return FLUID_FAILED; return FLUID_FAILED;
} }
z = inst_zone; z = inst_zone;
/* Instrument level, generators */ /* Instrument level, generators */
for (i = 0; i < GEN_LAST; i++) { for (i = 0; i < GEN_LAST; i++) {
/* SF 2.01 section 9.4 'bullet' 4: /* SF 2.01 section 9.4 'bullet' 4:
* *
* A generator in a local instrument zone supersedes a * A generator in a local instrument zone supersedes a
* global instrument zone generator. Both cases supersede * global instrument zone generator. Both cases supersede
@@ -852,7 +854,7 @@ fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan
fluid_voice_gen_set(voice, i, inst_zone->gen[i].val); fluid_voice_gen_set(voice, i, inst_zone->gen[i].val);
} else if (global_inst_zone != NULL && global_inst_zone->gen[i].flags){ } else if (global_inst_zone != NULL && global_inst_zone->gen[i].flags){
fluid_voice_gen_set(voice, i, global_inst_zone->gen[i].val); fluid_voice_gen_set(voice, i, global_inst_zone->gen[i].val);
} else { } else {
/* The generator has not been defined in this instrument. /* The generator has not been defined in this instrument.
@@ -861,7 +863,7 @@ fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan
}; };
}; /* for all generators */ }; /* for all generators */
/* global instrument zone, modulators: Put them all into a /* global instrument zone, modulators: Put them all into a
* list. */ * list. */
@@ -874,7 +876,7 @@ fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan
mod = mod->next; mod = mod->next;
}; };
}; };
/* local instrument zone, modulators. /* local instrument zone, modulators.
* Replace modulators with the same definition in the list: * Replace modulators with the same definition in the list:
* SF 2.01 page 69, 'bullet' 8 * SF 2.01 page 69, 'bullet' 8
@@ -893,7 +895,7 @@ fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan
mod_list[i] = NULL; mod_list[i] = NULL;
}; };
}; };
/* Finally add the new modulator to to the list. */ /* Finally add the new modulator to to the list. */
mod_list[mod_list_count++] = mod; mod_list[mod_list_count++] = mod;
mod = mod->next; mod = mod->next;
@@ -918,12 +920,12 @@ fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan
/* SF 2.01 section 8.5 page 58: If some generators are /* SF 2.01 section 8.5 page 58: If some generators are
* encountered at preset level, they should be ignored */ * encountered at preset level, they should be ignored */
if ((i != GEN_STARTADDROFS) if ((i != GEN_STARTADDROFS)
&& (i != GEN_ENDADDROFS) && (i != GEN_ENDADDROFS)
&& (i != GEN_STARTLOOPADDROFS) && (i != GEN_STARTLOOPADDROFS)
&& (i != GEN_ENDLOOPADDROFS) && (i != GEN_ENDLOOPADDROFS)
&& (i != GEN_STARTADDRCOARSEOFS) && (i != GEN_STARTADDRCOARSEOFS)
&& (i != GEN_ENDADDRCOARSEOFS) && (i != GEN_ENDADDRCOARSEOFS)
&& (i != GEN_STARTLOOPADDRCOARSEOFS) && (i != GEN_STARTLOOPADDRCOARSEOFS)
&& (i != GEN_KEYNUM) && (i != GEN_KEYNUM)
&& (i != GEN_VELOCITY) && (i != GEN_VELOCITY)
@@ -946,8 +948,8 @@ fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan
}; };
}; /* if available at preset level */ }; /* if available at preset level */
}; /* for all generators */ }; /* for all generators */
/* Global preset zone, modulators: put them all into a /* Global preset zone, modulators: put them all into a
* list. */ * list. */
mod_list_count = 0; mod_list_count = 0;
@@ -963,12 +965,12 @@ fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan
mod_list[i] = NULL; mod_list[i] = NULL;
}; };
}; };
/* Finally add the new modulator to the list. */ /* Finally add the new modulator to the list. */
mod_list[mod_list_count++] = mod; mod_list[mod_list_count++] = mod;
mod = mod->next; mod = mod->next;
}; };
/* Add preset modulators (global / local) to the voice. */ /* Add preset modulators (global / local) to the voice. */
for (i = 0; i < mod_list_count; i++){ for (i = 0; i < mod_list_count; i++){
mod = mod_list[i]; mod = mod_list[i];
@@ -979,7 +981,7 @@ fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan
* page */ * page */
fluid_voice_add_mod(voice, mod, FLUID_VOICE_ADD); fluid_voice_add_mod(voice, mod, FLUID_VOICE_ADD);
}; };
}; };
/* add the synthesis process to the synthesis loop. */ /* add the synthesis process to the synthesis loop. */
fluid_synth_start_voice(synth, voice); fluid_synth_start_voice(synth, voice);
@@ -1029,18 +1031,18 @@ fluid_sample_set_sound_data(fluid_sample_t* sample, short *data, unsigned int nb
/* 16 bit mono 44.1KHz data in */ /* 16 bit mono 44.1KHz data in */
/* in all cases, the sample has ownership of the data : it will release it in the end */ /* in all cases, the sample has ownership of the data : it will release it in the end */
unsigned int storedNbFrames; unsigned int storedNbFrames;
/* in case we already have some data */ /* in case we already have some data */
if (sample->data != NULL) { if (sample->data != NULL) {
FLUID_FREE(sample->data); FLUID_FREE(sample->data);
} }
if (copy_data) { if (copy_data) {
/* nbframes should be >= 48 (SoundFont specs) */ /* nbframes should be >= 48 (SoundFont specs) */
storedNbFrames = nbframes; storedNbFrames = nbframes;
if (storedNbFrames < 48) storedNbFrames = 48; if (storedNbFrames < 48) storedNbFrames = 48;
sample->data = FLUID_MALLOC(storedNbFrames*2 + 4*SAMPLE_LOOP_MARGIN); sample->data = FLUID_MALLOC(storedNbFrames*2 + 4*SAMPLE_LOOP_MARGIN);
if (sample->data == NULL) { if (sample->data == NULL) {
FLUID_LOG(FLUID_ERR, "Out of memory"); FLUID_LOG(FLUID_ERR, "Out of memory");
@@ -1054,7 +1056,7 @@ fluid_sample_set_sound_data(fluid_sample_t* sample, short *data, unsigned int nb
FLUID_MEMCPY((char*)(sample->data) + 2*SAMPLE_LOOP_MARGIN + storedNbFrames*2, (char*)data, 2*SAMPLE_LOOP_MARGIN); FLUID_MEMCPY((char*)(sample->data) + 2*SAMPLE_LOOP_MARGIN + storedNbFrames*2, (char*)data, 2*SAMPLE_LOOP_MARGIN);
FLUID_MEMCPY((char*)(sample->data), (char*)data + nbframes*2 - 2*SAMPLE_LOOP_MARGIN, 2*SAMPLE_LOOP_MARGIN); FLUID_MEMCPY((char*)(sample->data), (char*)data + nbframes*2 - 2*SAMPLE_LOOP_MARGIN, 2*SAMPLE_LOOP_MARGIN);
#endif #endif
/* pointers */ /* pointers */
/* all from the start of data */ /* all from the start of data */
sample->start = SAMPLE_LOOP_MARGIN; sample->start = SAMPLE_LOOP_MARGIN;
@@ -1065,11 +1067,11 @@ fluid_sample_set_sound_data(fluid_sample_t* sample, short *data, unsigned int nb
sample->start = 0; sample->start = 0;
sample->end = nbframes; sample->end = nbframes;
} }
/* only used as markers for the LOOP generators : set them on the first real frame */ /* only used as markers for the LOOP generators : set them on the first real frame */
sample->loopstart = sample->start; sample->loopstart = sample->start;
sample->loopend = sample->end; sample->loopend = sample->end;
sample->samplerate = 44100; sample->samplerate = 44100;
sample->origpitch = rootkey; sample->origpitch = rootkey;
sample->pitchadj = 0; sample->pitchadj = 0;
@@ -1082,7 +1084,7 @@ fluid_sample_set_sound_data(fluid_sample_t* sample, short *data, unsigned int nb
/* /*
* new_fluid_ramsample * new_fluid_ramsample
*/ */
fluid_sample_t* fluid_sample_t*
new_fluid_ramsample() new_fluid_ramsample()
{ {
/* same as new_fluid_sample. Only here so that it is exported */ /* same as new_fluid_sample. Only here so that it is exported */
@@ -1090,7 +1092,7 @@ new_fluid_ramsample()
sample = FLUID_NEW(fluid_sample_t); sample = FLUID_NEW(fluid_sample_t);
if (sample == NULL) { if (sample == NULL) {
FLUID_LOG(FLUID_ERR, "Out of memory"); FLUID_LOG(FLUID_ERR, "Out of memory");
return NULL; return NULL;
} }
+1 -1
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+46 -45
View File
@@ -16,7 +16,7 @@
* REVERB * REVERB
*/ */
/* Denormalising: /* Denormalising:
* *
* According to music-dsp thread 'Denormalise', Pentium processors * According to music-dsp thread 'Denormalise', Pentium processors
* have a hardware 'feature', that is of interest here, related to * have a hardware 'feature', that is of interest here, related to
@@ -76,15 +76,15 @@ void fluid_allpass_init(fluid_allpass* allpass);
void fluid_allpass_setfeedback(fluid_allpass* allpass, fluid_real_t val); void fluid_allpass_setfeedback(fluid_allpass* allpass, fluid_real_t val);
fluid_real_t fluid_allpass_getfeedback(fluid_allpass* allpass); fluid_real_t fluid_allpass_getfeedback(fluid_allpass* allpass);
void void
fluid_allpass_setbuffer(fluid_allpass* allpass, fluid_real_t *buf, int size) fluid_allpass_setbuffer(fluid_allpass* allpass, fluid_real_t *buf, int size)
{ {
allpass->bufidx = 0; allpass->bufidx = 0;
allpass->buffer = buf; allpass->buffer = buf;
allpass->bufsize = size; allpass->bufsize = size;
} }
void void
fluid_allpass_init(fluid_allpass* allpass) fluid_allpass_init(fluid_allpass* allpass)
{ {
int i; int i;
@@ -95,13 +95,13 @@ fluid_allpass_init(fluid_allpass* allpass)
} }
} }
void void
fluid_allpass_setfeedback(fluid_allpass* allpass, fluid_real_t val) fluid_allpass_setfeedback(fluid_allpass* allpass, fluid_real_t val)
{ {
allpass->feedback = val; allpass->feedback = val;
} }
fluid_real_t fluid_real_t
fluid_allpass_getfeedback(fluid_allpass* allpass) fluid_allpass_getfeedback(fluid_allpass* allpass)
{ {
return allpass->feedback; return allpass->feedback;
@@ -151,16 +151,16 @@ fluid_real_t fluid_comb_getdamp(fluid_comb* comb);
void fluid_comb_setfeedback(fluid_comb* comb, fluid_real_t val); void fluid_comb_setfeedback(fluid_comb* comb, fluid_real_t val);
fluid_real_t fluid_comb_getfeedback(fluid_comb* comb); fluid_real_t fluid_comb_getfeedback(fluid_comb* comb);
void void
fluid_comb_setbuffer(fluid_comb* comb, fluid_real_t *buf, int size) fluid_comb_setbuffer(fluid_comb* comb, fluid_real_t *buf, int size)
{ {
comb->filterstore = 0; comb->filterstore = 0;
comb->bufidx = 0; comb->bufidx = 0;
comb->buffer = buf; comb->buffer = buf;
comb->bufsize = size; comb->bufsize = size;
} }
void void
fluid_comb_init(fluid_comb* comb) fluid_comb_init(fluid_comb* comb)
{ {
int i; int i;
@@ -171,27 +171,27 @@ fluid_comb_init(fluid_comb* comb)
} }
} }
void void
fluid_comb_setdamp(fluid_comb* comb, fluid_real_t val) fluid_comb_setdamp(fluid_comb* comb, fluid_real_t val)
{ {
comb->damp1 = val; comb->damp1 = val;
comb->damp2 = 1 - val; comb->damp2 = 1 - val;
} }
fluid_real_t fluid_real_t
fluid_comb_getdamp(fluid_comb* comb) fluid_comb_getdamp(fluid_comb* comb)
{ {
return comb->damp1; return comb->damp1;
} }
void void
fluid_comb_setfeedback(fluid_comb* comb, fluid_real_t val) fluid_comb_setfeedback(fluid_comb* comb, fluid_real_t val)
{ {
comb->feedback = val; comb->feedback = val;
} }
fluid_real_t fluid_real_t
fluid_comb_getfeedback(fluid_comb* comb) fluid_comb_getfeedback(fluid_comb* comb)
{ {
return comb->feedback; return comb->feedback;
} }
@@ -227,11 +227,11 @@ fluid_comb_getfeedback(fluid_comb* comb)
#define numallpasses 4 #define numallpasses 4
#define fixedgain 0.015f #define fixedgain 0.015f
#define scalewet 3.0f #define scalewet 3.0f
#define scaledamp 0.4f #define scaledamp 1.0f
#define scaleroom 0.28f #define scaleroom 0.28f
#define offsetroom 0.7f #define offsetroom 0.7f
#define initialroom 0.5f #define initialroom 0.5f
#define initialdamp 0.5f #define initialdamp 0.2f
#define initialwet 1 #define initialwet 1
#define initialdry 0 #define initialdry 0
#define initialwidth 1 #define initialwidth 1
@@ -275,7 +275,7 @@ struct _fluid_revmodel_t {
fluid_real_t width; fluid_real_t width;
fluid_real_t gain; fluid_real_t gain;
/* /*
The following are all declared inline The following are all declared inline
to remove the need for dynamic allocation to remove the need for dynamic allocation
with its subsequent error-checking messiness with its subsequent error-checking messiness
*/ */
@@ -316,7 +316,7 @@ struct _fluid_revmodel_t {
void fluid_revmodel_update(fluid_revmodel_t* rev); void fluid_revmodel_update(fluid_revmodel_t* rev);
void fluid_revmodel_init(fluid_revmodel_t* rev); void fluid_revmodel_init(fluid_revmodel_t* rev);
fluid_revmodel_t* fluid_revmodel_t*
new_fluid_revmodel() new_fluid_revmodel()
{ {
fluid_revmodel_t* rev; fluid_revmodel_t* rev;
@@ -376,13 +376,13 @@ new_fluid_revmodel()
return rev; return rev;
} }
void void
delete_fluid_revmodel(fluid_revmodel_t* rev) delete_fluid_revmodel(fluid_revmodel_t* rev)
{ {
FLUID_FREE(rev); FLUID_FREE(rev);
} }
void void
fluid_revmodel_init(fluid_revmodel_t* rev) fluid_revmodel_init(fluid_revmodel_t* rev)
{ {
int i; int i;
@@ -396,14 +396,14 @@ fluid_revmodel_init(fluid_revmodel_t* rev)
} }
} }
void void
fluid_revmodel_reset(fluid_revmodel_t* rev) fluid_revmodel_reset(fluid_revmodel_t* rev)
{ {
fluid_revmodel_init(rev); fluid_revmodel_init(rev);
} }
void void
fluid_revmodel_processreplace(fluid_revmodel_t* rev, fluid_real_t *in, fluid_revmodel_processreplace(fluid_revmodel_t* rev, fluid_real_t *in,
fluid_real_t *left_out, fluid_real_t *right_out) fluid_real_t *left_out, fluid_real_t *right_out)
{ {
int i, k = 0; int i, k = 0;
@@ -412,7 +412,7 @@ fluid_revmodel_processreplace(fluid_revmodel_t* rev, fluid_real_t *in,
for (k = 0; k < FLUID_BUFSIZE; k++) { for (k = 0; k < FLUID_BUFSIZE; k++) {
outL = outR = 0; outL = outR = 0;
/* The original Freeverb code expects a stereo signal and 'input' /* The original Freeverb code expects a stereo signal and 'input'
* is set to the sum of the left and right input sample. Since * is set to the sum of the left and right input sample. Since
* this code works on a mono signal, 'input' is set to twice the * this code works on a mono signal, 'input' is set to twice the
@@ -438,10 +438,10 @@ fluid_revmodel_processreplace(fluid_revmodel_t* rev, fluid_real_t *in,
left_out[k] = outL * rev->wet1 + outR * rev->wet2; left_out[k] = outL * rev->wet1 + outR * rev->wet2;
right_out[k] = outR * rev->wet1 + outL * rev->wet2; right_out[k] = outR * rev->wet1 + outL * rev->wet2;
} }
} }
void void
fluid_revmodel_processmix(fluid_revmodel_t* rev, fluid_real_t *in, fluid_revmodel_processmix(fluid_revmodel_t* rev, fluid_real_t *in,
fluid_real_t *left_out, fluid_real_t *right_out) fluid_real_t *left_out, fluid_real_t *right_out)
{ {
int i, k = 0; int i, k = 0;
@@ -450,7 +450,7 @@ fluid_revmodel_processmix(fluid_revmodel_t* rev, fluid_real_t *in,
for (k = 0; k < FLUID_BUFSIZE; k++) { for (k = 0; k < FLUID_BUFSIZE; k++) {
outL = outR = 0; outL = outR = 0;
/* The original Freeverb code expects a stereo signal and 'input' /* The original Freeverb code expects a stereo signal and 'input'
* is set to the sum of the left and right input sample. Since * is set to the sum of the left and right input sample. Since
* this code works on a mono signal, 'input' is set to twice the * this code works on a mono signal, 'input' is set to twice the
@@ -478,7 +478,7 @@ fluid_revmodel_processmix(fluid_revmodel_t* rev, fluid_real_t *in,
} }
} }
void void
fluid_revmodel_update(fluid_revmodel_t* rev) fluid_revmodel_update(fluid_revmodel_t* rev)
{ {
/* Recalculate internal values after parameter change */ /* Recalculate internal values after parameter change */
@@ -491,6 +491,7 @@ fluid_revmodel_update(fluid_revmodel_t* rev)
fluid_comb_setfeedback(&rev->combL[i], rev->roomsize); fluid_comb_setfeedback(&rev->combL[i], rev->roomsize);
fluid_comb_setfeedback(&rev->combR[i], rev->roomsize); fluid_comb_setfeedback(&rev->combR[i], rev->roomsize);
} }
for (i = 0; i < numcombs; i++) { for (i = 0; i < numcombs; i++) {
fluid_comb_setdamp(&rev->combL[i], rev->damp); fluid_comb_setdamp(&rev->combL[i], rev->damp);
fluid_comb_setdamp(&rev->combR[i], rev->damp); fluid_comb_setdamp(&rev->combR[i], rev->damp);
@@ -503,7 +504,7 @@ fluid_revmodel_update(fluid_revmodel_t* rev)
because as you develop the reverb model, you may because as you develop the reverb model, you may
wish to take dynamic action when they are called. wish to take dynamic action when they are called.
*/ */
void void
fluid_revmodel_setroomsize(fluid_revmodel_t* rev, fluid_real_t value) fluid_revmodel_setroomsize(fluid_revmodel_t* rev, fluid_real_t value)
{ {
/* fluid_clip(value, 0.0f, 1.0f); */ /* fluid_clip(value, 0.0f, 1.0f); */
@@ -511,13 +512,13 @@ fluid_revmodel_setroomsize(fluid_revmodel_t* rev, fluid_real_t value)
fluid_revmodel_update(rev); fluid_revmodel_update(rev);
} }
fluid_real_t fluid_real_t
fluid_revmodel_getroomsize(fluid_revmodel_t* rev) fluid_revmodel_getroomsize(fluid_revmodel_t* rev)
{ {
return (rev->roomsize - offsetroom) / scaleroom; return (rev->roomsize - offsetroom) / scaleroom;
} }
void void
fluid_revmodel_setdamp(fluid_revmodel_t* rev, fluid_real_t value) fluid_revmodel_setdamp(fluid_revmodel_t* rev, fluid_real_t value)
{ {
/* fluid_clip(value, 0.0f, 1.0f); */ /* fluid_clip(value, 0.0f, 1.0f); */
@@ -525,27 +526,27 @@ fluid_revmodel_setdamp(fluid_revmodel_t* rev, fluid_real_t value)
fluid_revmodel_update(rev); fluid_revmodel_update(rev);
} }
fluid_real_t fluid_real_t
fluid_revmodel_getdamp(fluid_revmodel_t* rev) fluid_revmodel_getdamp(fluid_revmodel_t* rev)
{ {
return rev->damp / scaledamp; return rev->damp / scaledamp;
} }
void void
fluid_revmodel_setlevel(fluid_revmodel_t* rev, fluid_real_t value) fluid_revmodel_setlevel(fluid_revmodel_t* rev, fluid_real_t value)
{ {
/* fluid_clip(value, 0.0f, 1.0f); */ fluid_clip(value, 0.0f, 1.0f);
/* rev->wet = value * scalewet; */ rev->wet = value * scalewet;
/* fluid_revmodel_update(rev); */ fluid_revmodel_update(rev);
} }
fluid_real_t fluid_real_t
fluid_revmodel_getlevel(fluid_revmodel_t* rev) fluid_revmodel_getlevel(fluid_revmodel_t* rev)
{ {
return rev->wet / scalewet; return rev->wet / scalewet;
} }
void void
fluid_revmodel_setwidth(fluid_revmodel_t* rev, fluid_real_t value) fluid_revmodel_setwidth(fluid_revmodel_t* rev, fluid_real_t value)
{ {
/* fluid_clip(value, 0.0f, 1.0f); */ /* fluid_clip(value, 0.0f, 1.0f); */
@@ -553,7 +554,7 @@ fluid_revmodel_setwidth(fluid_revmodel_t* rev, fluid_real_t value)
fluid_revmodel_update(rev); fluid_revmodel_update(rev);
} }
fluid_real_t fluid_real_t
fluid_revmodel_getwidth(fluid_revmodel_t* rev) fluid_revmodel_getwidth(fluid_revmodel_t* rev)
{ {
return rev->width; return rev->width;
+3 -3
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -33,10 +33,10 @@ typedef struct _fluid_revmodel_t fluid_revmodel_t;
fluid_revmodel_t* new_fluid_revmodel(void); fluid_revmodel_t* new_fluid_revmodel(void);
void delete_fluid_revmodel(fluid_revmodel_t* rev); void delete_fluid_revmodel(fluid_revmodel_t* rev);
void fluid_revmodel_processmix(fluid_revmodel_t* rev, fluid_real_t *in, void fluid_revmodel_processmix(fluid_revmodel_t* rev, fluid_real_t *in,
fluid_real_t *left_out, fluid_real_t *right_out); fluid_real_t *left_out, fluid_real_t *right_out);
void fluid_revmodel_processreplace(fluid_revmodel_t* rev, fluid_real_t *in, void fluid_revmodel_processreplace(fluid_revmodel_t* rev, fluid_real_t *in,
fluid_real_t *left_out, fluid_real_t *right_out); fluid_real_t *left_out, fluid_real_t *right_out);
void fluid_revmodel_reset(fluid_revmodel_t* rev); void fluid_revmodel_reset(fluid_revmodel_t* rev);
+103 -103
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -19,14 +19,14 @@
*/ */
/* /*
2002 : API design by Peter Hanappe and Antoine Schmitt 2002 : API design by Peter Hanappe and Antoine Schmitt
August 2002 : Implementation by Antoine Schmitt as@gratin.org August 2002 : Implementation by Antoine Schmitt as@gratin.org
as part of the infiniteCD author project as part of the infiniteCD author project
http://www.infiniteCD.org/ http://www.infiniteCD.org/
*/ */
#include "fluid_event_priv.h" #include "fluid_event_priv.h"
#include "fluidsynth_priv.h" // FLUID_NEW, etc #include "fluidsynth_priv.h" // FLUID_NEW, etc
#include "fluid_sys.h" // timer, threads, etc... #include "fluid_sys.h" // timer, threads, etc...
@@ -82,11 +82,11 @@ int _fluid_seq_queue_process(void* data, unsigned int msec); // callback from ti
/* API implementation */ /* API implementation */
fluid_sequencer_t* fluid_sequencer_t*
new_fluid_sequencer() new_fluid_sequencer()
{ {
fluid_sequencer_t* seq; fluid_sequencer_t* seq;
seq = FLUID_NEW(fluid_sequencer_t); seq = FLUID_NEW(fluid_sequencer_t);
if (seq == NULL) { if (seq == NULL) {
fluid_log(FLUID_PANIC, "sequencer: Out of memory\n"); fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
@@ -99,7 +99,7 @@ new_fluid_sequencer()
seq->startMs = fluid_curtime(); seq->startMs = fluid_curtime();
seq->clients = NULL; seq->clients = NULL;
seq->clientsID = 0; seq->clientsID = 0;
if (-1 == _fluid_seq_queue_init(seq, FLUID_SEQUENCER_EVENTS_MAX)) { if (-1 == _fluid_seq_queue_init(seq, FLUID_SEQUENCER_EVENTS_MAX)) {
FLUID_FREE(seq); FLUID_FREE(seq);
fluid_log(FLUID_PANIC, "sequencer: Out of memory\n"); fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
@@ -113,7 +113,7 @@ new_fluid_sequencer()
_fluid_seq_queue_end(seq); _fluid_seq_queue_end(seq);
FLUID_FREE(seq); FLUID_FREE(seq);
fluid_log(FLUID_PANIC, "sequencer: Out of memory\n"); fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
return NULL; return NULL;
} }
seq->traceptr = seq->tracebuf; seq->traceptr = seq->tracebuf;
#endif #endif
@@ -121,16 +121,16 @@ new_fluid_sequencer()
return(seq); return(seq);
} }
void void
delete_fluid_sequencer(fluid_sequencer_t* seq) delete_fluid_sequencer(fluid_sequencer_t* seq)
{ {
if (seq == NULL) { if (seq == NULL) {
return; return;
} }
_fluid_seq_queue_end(seq); _fluid_seq_queue_end(seq);
/* cleanup clients */ /* cleanup clients */
if (seq->clients) { if (seq->clients) {
fluid_list_t *tmp = seq->clients; fluid_list_t *tmp = seq->clients;
@@ -142,9 +142,9 @@ delete_fluid_sequencer(fluid_sequencer_t* seq)
delete_fluid_list(seq->clients); delete_fluid_list(seq->clients);
seq->clients = NULL; seq->clients = NULL;
} }
#if FLUID_SEQ_WITH_TRACE #if FLUID_SEQ_WITH_TRACE
if (seq->tracebuf != NULL) if (seq->tracebuf != NULL)
FLUID_FREE(seq->tracebuf); FLUID_FREE(seq->tracebuf);
seq->tracebuf = NULL; seq->tracebuf = NULL;
#endif #endif
@@ -161,7 +161,7 @@ fluid_seq_dotrace(fluid_sequencer_t* seq, char *fmt, ...)
va_list args; va_list args;
int len, remain = seq->tracelen - (seq->traceptr - seq->tracebuf); int len, remain = seq->tracelen - (seq->traceptr - seq->tracebuf);
if (remain <= 0) return; if (remain <= 0) return;
va_start (args, fmt); va_start (args, fmt);
len = vsnprintf(seq->traceptr, remain, fmt, args); len = vsnprintf(seq->traceptr, remain, fmt, args);
va_end (args); va_end (args);
@@ -175,7 +175,7 @@ fluid_seq_dotrace(fluid_sequencer_t* seq, char *fmt, ...)
seq->traceptr = seq->tracebuf + seq->tracelen; seq->traceptr = seq->tracebuf + seq->tracelen;
} }
} }
return; return;
} }
@@ -198,12 +198,12 @@ void fluid_seq_dotrace(fluid_sequencer_t* seq, char *fmt, ...) {}
/* clients */ /* clients */
short fluid_sequencer_register_client(fluid_sequencer_t* seq, char* name, short fluid_sequencer_register_client(fluid_sequencer_t* seq, char* name,
fluid_event_callback_t callback, void* data) { fluid_event_callback_t callback, void* data) {
fluid_sequencer_client_t * client; fluid_sequencer_client_t * client;
char * nameCopy; char * nameCopy;
client = FLUID_NEW(fluid_sequencer_client_t); client = FLUID_NEW(fluid_sequencer_client_t);
if (client == NULL) { if (client == NULL) {
fluid_log(FLUID_PANIC, "sequencer: Out of memory\n"); fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
@@ -215,16 +215,16 @@ short fluid_sequencer_register_client(fluid_sequencer_t* seq, char* name,
fluid_log(FLUID_PANIC, "sequencer: Out of memory\n"); fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
return -1; return -1;
} }
seq->clientsID++; seq->clientsID++;
client->name = nameCopy; client->name = nameCopy;
client->id = seq->clientsID; client->id = seq->clientsID;
client->callback = callback; client->callback = callback;
client->data = data; client->data = data;
seq->clients = fluid_list_append(seq->clients, (void *)client); seq->clients = fluid_list_append(seq->clients, (void *)client);
return (client->id); return (client->id);
} }
@@ -232,15 +232,15 @@ short fluid_sequencer_register_client(fluid_sequencer_t* seq, char* name,
void fluid_sequencer_unregister_client(fluid_sequencer_t* seq, short id) void fluid_sequencer_unregister_client(fluid_sequencer_t* seq, short id)
{ {
fluid_list_t *tmp; fluid_list_t *tmp;
if (seq->clients == NULL) return; if (seq->clients == NULL) return;
tmp = seq->clients; tmp = seq->clients;
while (tmp) { while (tmp) {
fluid_sequencer_client_t *client = (fluid_sequencer_client_t*)tmp->data; fluid_sequencer_client_t *client = (fluid_sequencer_client_t*)tmp->data;
if (client->id == id) { if (client->id == id) {
if (client->name) if (client->name)
FLUID_FREE(client->name); FLUID_FREE(client->name);
seq->clients = fluid_list_remove_link(seq->clients, tmp); seq->clients = fluid_list_remove_link(seq->clients, tmp);
delete1_fluid_list(tmp); delete1_fluid_list(tmp);
@@ -253,7 +253,7 @@ void fluid_sequencer_unregister_client(fluid_sequencer_t* seq, short id)
int fluid_sequencer_count_clients(fluid_sequencer_t* seq) int fluid_sequencer_count_clients(fluid_sequencer_t* seq)
{ {
if (seq->clients == NULL) if (seq->clients == NULL)
return 0; return 0;
return fluid_list_size(seq->clients); return fluid_list_size(seq->clients);
} }
@@ -274,17 +274,17 @@ short fluid_sequencer_get_client_id(fluid_sequencer_t* seq, int index)
char* fluid_sequencer_get_client_name(fluid_sequencer_t* seq, int id) char* fluid_sequencer_get_client_name(fluid_sequencer_t* seq, int id)
{ {
fluid_list_t *tmp; fluid_list_t *tmp;
if (seq->clients == NULL) if (seq->clients == NULL)
return NULL; return NULL;
tmp = seq->clients; tmp = seq->clients;
while (tmp) { while (tmp) {
fluid_sequencer_client_t *client = (fluid_sequencer_client_t*)tmp->data; fluid_sequencer_client_t *client = (fluid_sequencer_client_t*)tmp->data;
if (client->id == id) if (client->id == id)
return client->name; return client->name;
tmp = tmp->next; tmp = tmp->next;
} }
return NULL; return NULL;
@@ -293,16 +293,16 @@ char* fluid_sequencer_get_client_name(fluid_sequencer_t* seq, int id)
int fluid_sequencer_client_is_dest(fluid_sequencer_t* seq, int id) int fluid_sequencer_client_is_dest(fluid_sequencer_t* seq, int id)
{ {
fluid_list_t *tmp; fluid_list_t *tmp;
if (seq->clients == NULL) return 0; if (seq->clients == NULL) return 0;
tmp = seq->clients; tmp = seq->clients;
while (tmp) { while (tmp) {
fluid_sequencer_client_t *client = (fluid_sequencer_client_t*)tmp->data; fluid_sequencer_client_t *client = (fluid_sequencer_client_t*)tmp->data;
if (client->id == id) if (client->id == id)
return (client->callback != NULL); return (client->callback != NULL);
tmp = tmp->next; tmp = tmp->next;
} }
return 0; return 0;
@@ -312,15 +312,15 @@ int fluid_sequencer_client_is_dest(fluid_sequencer_t* seq, int id)
void fluid_sequencer_send_now(fluid_sequencer_t* seq, fluid_event_t* evt) void fluid_sequencer_send_now(fluid_sequencer_t* seq, fluid_event_t* evt)
{ {
short destID = fluid_event_get_dest(evt); short destID = fluid_event_get_dest(evt);
/* find callback */ /* find callback */
fluid_list_t *tmp = seq->clients; fluid_list_t *tmp = seq->clients;
while (tmp) { while (tmp) {
fluid_sequencer_client_t *dest = (fluid_sequencer_client_t*)tmp->data; fluid_sequencer_client_t *dest = (fluid_sequencer_client_t*)tmp->data;
if (dest->id == destID) { if (dest->id == destID) {
if (dest->callback) if (dest->callback)
(dest->callback)(fluid_sequencer_get_tick(seq), (dest->callback)(fluid_sequencer_get_tick(seq),
evt, seq, dest->data); evt, seq, dest->data);
return; return;
} }
@@ -336,24 +336,24 @@ fluid_sequencer_send_at(fluid_sequencer_t* seq, fluid_event_t* evt, unsigned int
/* set absolute */ /* set absolute */
if (!absolute) if (!absolute)
time = now + time; time = now + time;
/* time stamp event */ /* time stamp event */
fluid_event_set_time(evt, time); fluid_event_set_time(evt, time);
/* process late */ /* process late */
if (time < now) { if (time < now) {
fluid_sequencer_send_now(seq, evt); fluid_sequencer_send_now(seq, evt);
return 0; return 0;
} }
/* process now */ /* process now */
if (time == now) { if (time == now) {
fluid_sequencer_send_now(seq, evt); fluid_sequencer_send_now(seq, evt);
return 0; return 0;
} }
/* queue for processing later */ /* queue for processing later */
return _fluid_seq_queue_pre_insert(seq, evt); return _fluid_seq_queue_pre_insert(seq, evt);
} }
void void
@@ -382,14 +382,14 @@ void fluid_sequencer_set_time_scale(fluid_sequencer_t* seq, double scale)
fluid_log(FLUID_WARN, "sequencer: scale <= 0 : %f\n", scale); fluid_log(FLUID_WARN, "sequencer: scale <= 0 : %f\n", scale);
return; return;
} }
if (scale > 1000.0) if (scale > 1000.0)
// Otherwise : problems with the timer = 0ms... // Otherwise : problems with the timer = 0ms...
scale = 1000.0; scale = 1000.0;
if (seq->scale != scale) { if (seq->scale != scale) {
double oldScale = seq->scale; double oldScale = seq->scale;
// stop timer // stop timer
if (seq->timer) { if (seq->timer) {
delete_fluid_timer(seq->timer); delete_fluid_timer(seq->timer);
@@ -405,10 +405,10 @@ void fluid_sequencer_set_time_scale(fluid_sequencer_t* seq, double scale)
{ {
fluid_evt_entry* tmp; fluid_evt_entry* tmp;
tmp = seq->preQueue; tmp = seq->preQueue;
while (tmp) { while (tmp) {
if (tmp->entryType == FLUID_EVT_ENTRY_INSERT) if (tmp->entryType == FLUID_EVT_ENTRY_INSERT)
tmp->evt.time = tmp->evt.time*seq->scale/oldScale; tmp->evt.time = tmp->evt.time*seq->scale/oldScale;
tmp = tmp->next; tmp = tmp->next;
} }
} }
@@ -434,7 +434,7 @@ double fluid_sequencer_get_time_scale(fluid_sequencer_t* seq)
/* /*
The queue stores all future events to be processed. The queue stores all future events to be processed.
Data structures Data structures
There is a heap, allocated at init time, for managing a pool There is a heap, allocated at init time, for managing a pool
@@ -455,33 +455,33 @@ double fluid_sequencer_get_time_scale(fluid_sequencer_t* seq)
events is fast (below 65535 ticks, that is about 1 minute if 1 events is fast (below 65535 ticks, that is about 1 minute if 1
tick=1ms). Inserting later events is more slow, but this is a tick=1ms). Inserting later events is more slow, but this is a
realtime engine, isn't it ? realtime engine, isn't it ?
The queue0 starts at queue0StartTime. When 256 ticks have The queue0 starts at queue0StartTime. When 256 ticks have
elapsed, the queue0 array is emptied, and the first cell of elapsed, the queue0 array is emptied, and the first cell of
the queue1 array is expanded in the queue0 array, according to the queue1 array is expanded in the queue0 array, according to
the time of each event. The queue1 array is shifted to the the time of each event. The queue1 array is shifted to the
left, and the first events of the queueLater list are inserte left, and the first events of the queueLater list are inserte
in the last cell of the queue1 array. in the last cell of the queue1 array.
We remember the previously managed cell in queue0 in the We remember the previously managed cell in queue0 in the
prevCellNb variable. When processing the current cell, we prevCellNb variable. When processing the current cell, we
process the events in between (late events). process the events in between (late events).
Functions Functions
The main thread functions first get an event entry from the The main thread functions first get an event entry from the
heap, and copy the given event into it, then merely enqueue it heap, and copy the given event into it, then merely enqueue it
in a preQueue. This is in order to protect the data structure: in a preQueue. This is in order to protect the data structure:
everything is managed in the callback (thread or interrupt, everything is managed in the callback (thread or interrupt,
depending on the architecture). depending on the architecture).
All queue data structure management is done in a timer All queue data structure management is done in a timer
callback: '_fluid_seq_queue_process'. The callback: '_fluid_seq_queue_process'. The
_fluid_seq_queue_process function first process the preQueue, _fluid_seq_queue_process function first process the preQueue,
inserting or removing event entrys from the queue, then inserting or removing event entrys from the queue, then
processes the queue, by sending events ready to be sent at the processes the queue, by sending events ready to be sent at the
current time. current time.
Critical sections between the main thread (or app) and the Critical sections between the main thread (or app) and the
sequencer thread (or interrupt) are: sequencer thread (or interrupt) are:
@@ -530,11 +530,11 @@ _fluid_seq_queue_init(fluid_sequencer_t* seq, int maxEvents)
seq->queueLater = NULL; seq->queueLater = NULL;
seq->queue0StartTime = fluid_sequencer_get_tick(seq); seq->queue0StartTime = fluid_sequencer_get_tick(seq);
seq->prevCellNb = -1; seq->prevCellNb = -1;
fluid_mutex_init(seq->mutex); fluid_mutex_init(seq->mutex);
/* start timer */ /* start timer */
seq->timer = new_fluid_timer((int)(1000/seq->scale), _fluid_seq_queue_process, seq->timer = new_fluid_timer((int)(1000/seq->scale), _fluid_seq_queue_process,
(void *)seq, 1, 0); (void *)seq, 1, 0);
return (0); return (0);
} }
@@ -546,7 +546,7 @@ _fluid_seq_queue_end(fluid_sequencer_t* seq)
delete_fluid_timer(seq->timer); delete_fluid_timer(seq->timer);
seq->timer = NULL; seq->timer = NULL;
} }
if (seq->heap) { if (seq->heap) {
_fluid_evt_heap_free(seq->heap); _fluid_evt_heap_free(seq->heap);
seq->heap = NULL; seq->heap = NULL;
@@ -572,11 +572,11 @@ _fluid_seq_queue_pre_insert(fluid_sequencer_t* seq, fluid_event_t * evt)
fluid_log(FLUID_PANIC, "sequencer: no more free events\n"); fluid_log(FLUID_PANIC, "sequencer: no more free events\n");
return -1; return -1;
} }
evtentry->next = NULL; evtentry->next = NULL;
evtentry->entryType = FLUID_EVT_ENTRY_INSERT; evtentry->entryType = FLUID_EVT_ENTRY_INSERT;
FLUID_MEMCPY(&(evtentry->evt), evt, sizeof(fluid_event_t)); FLUID_MEMCPY(&(evtentry->evt), evt, sizeof(fluid_event_t));
fluid_mutex_lock(seq->mutex); fluid_mutex_lock(seq->mutex);
/* append to preQueue */ /* append to preQueue */
@@ -588,7 +588,7 @@ _fluid_seq_queue_pre_insert(fluid_sequencer_t* seq, fluid_event_t * evt)
seq->preQueueLast = evtentry; seq->preQueueLast = evtentry;
fluid_mutex_unlock(seq->mutex); fluid_mutex_unlock(seq->mutex);
return (0); return (0);
} }
@@ -604,7 +604,7 @@ _fluid_seq_queue_pre_remove(fluid_sequencer_t* seq, short src, short dest, int t
fluid_log(FLUID_PANIC, "sequencer: no more free events\n"); fluid_log(FLUID_PANIC, "sequencer: no more free events\n");
return; return;
} }
evtentry->next = NULL; evtentry->next = NULL;
evtentry->entryType = FLUID_EVT_ENTRY_REMOVE; evtentry->entryType = FLUID_EVT_ENTRY_REMOVE;
{ {
@@ -614,7 +614,7 @@ _fluid_seq_queue_pre_remove(fluid_sequencer_t* seq, short src, short dest, int t
fluid_event_set_dest(evt, dest); fluid_event_set_dest(evt, dest);
evt->type = type; evt->type = type;
} }
fluid_mutex_lock(seq->mutex); fluid_mutex_lock(seq->mutex);
/* append to preQueue */ /* append to preQueue */
@@ -624,7 +624,7 @@ _fluid_seq_queue_pre_remove(fluid_sequencer_t* seq, short src, short dest, int t
seq->preQueue = evtentry; seq->preQueue = evtentry;
} }
seq->preQueueLast = evtentry; seq->preQueueLast = evtentry;
fluid_mutex_unlock(seq->mutex); fluid_mutex_unlock(seq->mutex);
return; return;
} }
@@ -632,7 +632,7 @@ _fluid_seq_queue_pre_remove(fluid_sequencer_t* seq, short src, short dest, int t
/*********************** /***********************
* callback from timer * callback from timer
* (may be in a different thread, or in an interrupt) * (may be in a different thread, or in an interrupt)
* *
***********************/ ***********************/
int int
_fluid_seq_queue_process(void* data, unsigned int msec) _fluid_seq_queue_process(void* data, unsigned int msec)
@@ -651,23 +651,23 @@ _fluid_seq_queue_process(void* data, unsigned int msec)
seq->preQueueLast = NULL; seq->preQueueLast = NULL;
fluid_mutex_unlock(seq->mutex); fluid_mutex_unlock(seq->mutex);
/* walk all the preQueue and process them in order : inserts and removes */ /* walk all the preQueue and process them in order : inserts and removes */
while (tmp) { while (tmp) {
next = tmp->next; next = tmp->next;
if (tmp->entryType == FLUID_EVT_ENTRY_REMOVE) { if (tmp->entryType == FLUID_EVT_ENTRY_REMOVE) {
_fluid_seq_queue_remove_entries_matching(seq, tmp); _fluid_seq_queue_remove_entries_matching(seq, tmp);
} else { } else {
_fluid_seq_queue_insert_entry(seq, tmp); _fluid_seq_queue_insert_entry(seq, tmp);
} }
tmp = next; tmp = next;
} }
/* send queued events */ /* send queued events */
_fluid_seq_queue_send_queued_events(seq); _fluid_seq_queue_send_queued_events(seq);
/* continue timer */ /* continue timer */
return 1; return 1;
} }
@@ -680,7 +680,7 @@ _fluid_seq_queue_print_later(fluid_sequencer_t* seq)
fluid_evt_entry* tmp = seq->queueLater; fluid_evt_entry* tmp = seq->queueLater;
printf("queueLater:\n"); printf("queueLater:\n");
while (tmp) { while (tmp) {
unsigned int delay = tmp->evt.time - seq->queue0StartTime; unsigned int delay = tmp->evt.time - seq->queue0StartTime;
printf("queueLater: Delay = %i\n", delay); printf("queueLater: Delay = %i\n", delay);
@@ -720,19 +720,19 @@ _fluid_seq_queue_insert_queue_later(fluid_sequencer_t* seq, fluid_evt_entry* evt
{ {
fluid_evt_entry* prev; fluid_evt_entry* prev;
fluid_evt_entry* tmp; fluid_evt_entry* tmp;
unsigned int time = evtentry->evt.time; unsigned int time = evtentry->evt.time;
/* insert in 'queueLater', after the ones that have the same /* insert in 'queueLater', after the ones that have the same
* time */ * time */
/* first? */ /* first? */
if ((seq->queueLater == NULL) if ((seq->queueLater == NULL)
|| (seq->queueLater->evt.time > time)) { || (seq->queueLater->evt.time > time)) {
evtentry->next = seq->queueLater; evtentry->next = seq->queueLater;
seq->queueLater = evtentry; seq->queueLater = evtentry;
return; return;
} }
/* walk queueLater */ /* walk queueLater */
/* this is the only slow thing : if the event is more /* this is the only slow thing : if the event is more
than 65535 ticks after the current time */ than 65535 ticks after the current time */
@@ -752,7 +752,7 @@ _fluid_seq_queue_insert_queue_later(fluid_sequencer_t* seq, fluid_evt_entry* evt
/* last */ /* last */
evtentry->next = NULL; evtentry->next = NULL;
prev->next = evtentry; prev->next = evtentry;
} }
void void
@@ -760,43 +760,43 @@ _fluid_seq_queue_insert_entry(fluid_sequencer_t* seq, fluid_evt_entry * evtentry
{ {
/* time is relative to seq origin, in ticks */ /* time is relative to seq origin, in ticks */
fluid_event_t * evt = &(evtentry->evt); fluid_event_t * evt = &(evtentry->evt);
unsigned int time = evt->time; unsigned int time = evt->time;
unsigned int delay; unsigned int delay;
if (seq->queue0StartTime > 0) { if (seq->queue0StartTime > 0) {
/* queue0StartTime could be < 0 if the scale changed a /* queue0StartTime could be < 0 if the scale changed a
lot early, breaking the following comparison lot early, breaking the following comparison
*/ */
if (time < (unsigned int)seq->queue0StartTime) { if (time < (unsigned int)seq->queue0StartTime) {
/* we are late, send now */ /* we are late, send now */
fluid_sequencer_send_now(seq, evt); fluid_sequencer_send_now(seq, evt);
_fluid_seq_heap_set_free(seq->heap, evtentry); _fluid_seq_heap_set_free(seq->heap, evtentry);
return; return;
} }
} }
if (seq->prevCellNb >= 0) { if (seq->prevCellNb >= 0) {
/* prevCellNb could be -1 is seq was just started - unlikely */ /* prevCellNb could be -1 is seq was just started - unlikely */
/* prevCellNb can also be -1 if cellNb was reset to 0 in /* prevCellNb can also be -1 if cellNb was reset to 0 in
_fluid_seq_queue_send_queued_events() */ _fluid_seq_queue_send_queued_events() */
if (time <= (unsigned int)(seq->queue0StartTime + seq->prevCellNb)) { if (time <= (unsigned int)(seq->queue0StartTime + seq->prevCellNb)) {
/* we are late, send now */ /* we are late, send now */
fluid_sequencer_send_now(seq, evt); fluid_sequencer_send_now(seq, evt);
_fluid_seq_heap_set_free(seq->heap, evtentry); _fluid_seq_heap_set_free(seq->heap, evtentry);
return; return;
} }
} }
delay = time - seq->queue0StartTime; delay = time - seq->queue0StartTime;
if (delay > 65535) { if (delay > 65535) {
_fluid_seq_queue_insert_queue_later(seq, evtentry); _fluid_seq_queue_insert_queue_later(seq, evtentry);
} else if (delay > 255) { } else if (delay > 255) {
_fluid_seq_queue_insert_queue1(seq, evtentry, delay/256 - 1); _fluid_seq_queue_insert_queue1(seq, evtentry, delay/256 - 1);
} else { } else {
_fluid_seq_queue_insert_queue0(seq, evtentry, delay); _fluid_seq_queue_insert_queue0(seq, evtentry, delay);
} }
@@ -806,21 +806,21 @@ int
_fluid_seq_queue_matchevent(fluid_event_t* evt, int templType, short templSrc, short templDest) _fluid_seq_queue_matchevent(fluid_event_t* evt, int templType, short templSrc, short templDest)
{ {
int eventType; int eventType;
if (templSrc != -1 && templSrc != fluid_event_get_source(evt)) if (templSrc != -1 && templSrc != fluid_event_get_source(evt))
return 0; return 0;
if (templDest != -1 && templDest != fluid_event_get_dest(evt)) if (templDest != -1 && templDest != fluid_event_get_dest(evt))
return 0; return 0;
if (templType == -1) if (templType == -1)
return 1; return 1;
eventType = fluid_event_get_type(evt); eventType = fluid_event_get_type(evt);
if (templType == eventType) if (templType == eventType)
return 1; return 1;
if (templType == FLUID_SEQ_ANYCONTROLCHANGE) if (templType == FLUID_SEQ_ANYCONTROLCHANGE)
if (eventType == FLUID_SEQ_PITCHBEND || if (eventType == FLUID_SEQ_PITCHBEND ||
eventType == FLUID_SEQ_MODULATION || eventType == FLUID_SEQ_MODULATION ||
@@ -841,14 +841,14 @@ _fluid_seq_queue_remove_entries_matching(fluid_sequencer_t* seq, fluid_evt_entry
/* we walk everything : this is slow, but that is life */ /* we walk everything : this is slow, but that is life */
int i, type; int i, type;
short src, dest; short src, dest;
src = templ->evt.src; src = templ->evt.src;
dest = templ->evt.dest; dest = templ->evt.dest;
type = templ->evt.type; type = templ->evt.type;
/* we can set it free now */ /* we can set it free now */
_fluid_seq_heap_set_free(seq->heap, templ); _fluid_seq_heap_set_free(seq->heap, templ);
/* queue0 */ /* queue0 */
for (i = 0 ; i < 256 ; i++) { for (i = 0 ; i < 256 ; i++) {
fluid_evt_entry* tmp = seq->queue0[i][0]; fluid_evt_entry* tmp = seq->queue0[i][0];
@@ -876,10 +876,10 @@ _fluid_seq_queue_remove_entries_matching(fluid_sequencer_t* seq, fluid_evt_entry
} else { } else {
prev = tmp; prev = tmp;
tmp = prev->next; tmp = prev->next;
} }
} }
} }
/* queue1 */ /* queue1 */
for (i = 0 ; i < 255 ; i++) { for (i = 0 ; i < 255 ; i++) {
fluid_evt_entry* tmp = seq->queue1[i][0]; fluid_evt_entry* tmp = seq->queue1[i][0];
@@ -906,7 +906,7 @@ _fluid_seq_queue_remove_entries_matching(fluid_sequencer_t* seq, fluid_evt_entry
} else { } else {
prev = tmp; prev = tmp;
tmp = prev->next; tmp = prev->next;
} }
} }
} }
@@ -950,9 +950,9 @@ _fluid_seq_queue_send_cell_events(fluid_sequencer_t* seq, int cellNb)
_fluid_seq_heap_set_free(seq->heap, tmp); _fluid_seq_heap_set_free(seq->heap, tmp);
tmp = next; tmp = next;
} }
seq->queue0[cellNb][0] = NULL; seq->queue0[cellNb][0] = NULL;
seq->queue0[cellNb][1] = NULL; seq->queue0[cellNb][1] = NULL;
} }
void void
@@ -989,7 +989,7 @@ _fluid_seq_queue_slide(fluid_sequencer_t* seq)
} }
seq->queue1[254][0] = NULL; seq->queue1[254][0] = NULL;
seq->queue1[254][1] = NULL; seq->queue1[254][1] = NULL;
/* append queueLater to queue1[254] */ /* append queueLater to queue1[254] */
count = 0; count = 0;
@@ -1003,9 +1003,9 @@ _fluid_seq_queue_slide(fluid_sequencer_t* seq)
next = tmp->next; next = tmp->next;
/* append it */ /* append it */
_fluid_seq_queue_insert_queue1(seq, tmp, 254); _fluid_seq_queue_insert_queue1(seq, tmp, 254);
tmp = next; tmp = next;
count++; count++;
} }
@@ -1024,14 +1024,14 @@ _fluid_seq_queue_send_queued_events(fluid_sequencer_t* seq)
cellNb = 0; cellNb = 0;
_fluid_seq_queue_slide(seq); _fluid_seq_queue_slide(seq);
} /* slide */ } /* slide */
/* process queue0[cellNb] */ /* process queue0[cellNb] */
_fluid_seq_queue_send_cell_events(seq, cellNb); _fluid_seq_queue_send_cell_events(seq, cellNb);
/* next cell */ /* next cell */
cellNb++; cellNb++;
} }
seq->prevCellNb = cellNb - 1; seq->prevCellNb = cellNb - 1;
} }
+19 -19
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -28,7 +28,7 @@
*/ */
#include "fluidsynth_priv.h" #include "fluidsynth_priv.h"
/*************************************************************** /***************************************************************
* *
* SEQUENCER BINDING * SEQUENCER BINDING
@@ -47,17 +47,17 @@ short fluid_sequencer_register_fluidsynth(fluid_sequencer_t* seq, fluid_synth_t*
void fluid_seq_fluidsynth_callback(unsigned int time, fluid_event_t* evt, fluid_sequencer_t* seq, void* data) void fluid_seq_fluidsynth_callback(unsigned int time, fluid_event_t* evt, fluid_sequencer_t* seq, void* data)
{ {
fluid_synth_t* synth = (fluid_synth_t *)data; fluid_synth_t* synth = (fluid_synth_t *)data;
switch (fluid_event_get_type(evt)) { switch (fluid_event_get_type(evt)) {
case FLUID_SEQ_NOTEON: case FLUID_SEQ_NOTEON:
fluid_synth_noteon(synth, fluid_event_get_channel(evt), fluid_event_get_key(evt), fluid_event_get_velocity(evt)); fluid_synth_noteon(synth, fluid_event_get_channel(evt), fluid_event_get_key(evt), fluid_event_get_velocity(evt));
break; break;
case FLUID_SEQ_NOTEOFF: case FLUID_SEQ_NOTEOFF:
fluid_synth_noteoff(synth, fluid_event_get_channel(evt), fluid_event_get_key(evt)); fluid_synth_noteoff(synth, fluid_event_get_channel(evt), fluid_event_get_key(evt));
break; break;
case FLUID_SEQ_NOTE: case FLUID_SEQ_NOTE:
{ {
unsigned int dur; unsigned int dur;
@@ -75,28 +75,28 @@ void fluid_seq_fluidsynth_callback(unsigned int time, fluid_event_t* evt, fluid_
case FLUID_SEQ_ALLNOTESOFF: case FLUID_SEQ_ALLNOTESOFF:
fluid_synth_cc(synth, fluid_event_get_channel(evt), 0x7B, 0); fluid_synth_cc(synth, fluid_event_get_channel(evt), 0x7B, 0);
break; break;
case FLUID_SEQ_BANKSELECT: case FLUID_SEQ_BANKSELECT:
fluid_synth_bank_select(synth, fluid_event_get_channel(evt), fluid_event_get_bank(evt)); fluid_synth_bank_select(synth, fluid_event_get_channel(evt), fluid_event_get_bank(evt));
break; break;
case FLUID_SEQ_PROGRAMCHANGE: case FLUID_SEQ_PROGRAMCHANGE:
fluid_synth_program_change(synth, fluid_event_get_channel(evt), fluid_event_get_program(evt)); fluid_synth_program_change(synth, fluid_event_get_channel(evt), fluid_event_get_program(evt));
break; break;
case FLUID_SEQ_PROGRAMSELECT: case FLUID_SEQ_PROGRAMSELECT:
fluid_synth_program_select(synth, fluid_event_get_channel(evt), fluid_event_get_sfont_id(evt), fluid_synth_program_select(synth, fluid_event_get_channel(evt), fluid_event_get_sfont_id(evt),
fluid_event_get_bank(evt), fluid_event_get_program(evt)); fluid_event_get_bank(evt), fluid_event_get_program(evt));
break; break;
case FLUID_SEQ_ANYCONTROLCHANGE: case FLUID_SEQ_ANYCONTROLCHANGE:
/* nothing = only used by remove_events */ /* nothing = only used by remove_events */
break; break;
case FLUID_SEQ_PITCHBEND: case FLUID_SEQ_PITCHBEND:
fluid_synth_pitch_bend(synth, fluid_event_get_channel(evt), fluid_event_get_pitch(evt)); fluid_synth_pitch_bend(synth, fluid_event_get_channel(evt), fluid_event_get_pitch(evt));
break; break;
case FLUID_SEQ_PITCHWHHELSENS: case FLUID_SEQ_PITCHWHHELSENS:
fluid_synth_pitch_wheel_sens(synth, fluid_event_get_channel(evt), fluid_event_get_value(evt)); fluid_synth_pitch_wheel_sens(synth, fluid_event_get_channel(evt), fluid_event_get_value(evt));
break; break;
@@ -104,53 +104,53 @@ void fluid_seq_fluidsynth_callback(unsigned int time, fluid_event_t* evt, fluid_
case FLUID_SEQ_CONTROLCHANGE: case FLUID_SEQ_CONTROLCHANGE:
fluid_synth_cc(synth, fluid_event_get_channel(evt), fluid_event_get_control(evt), fluid_event_get_value(evt)); fluid_synth_cc(synth, fluid_event_get_channel(evt), fluid_event_get_control(evt), fluid_event_get_value(evt));
break; break;
case FLUID_SEQ_MODULATION: case FLUID_SEQ_MODULATION:
{ {
short ctrl = 0x01; // MODULATION_MSB short ctrl = 0x01; // MODULATION_MSB
fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt)); fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
} }
break; break;
case FLUID_SEQ_SUSTAIN: case FLUID_SEQ_SUSTAIN:
{ {
short ctrl = 0x40; // SUSTAIN_SWITCH short ctrl = 0x40; // SUSTAIN_SWITCH
fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt)); fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
} }
break; break;
case FLUID_SEQ_PAN: case FLUID_SEQ_PAN:
{ {
short ctrl = 0x0A; // PAN_MSB short ctrl = 0x0A; // PAN_MSB
fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt)); fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
} }
break; break;
case FLUID_SEQ_VOLUME: case FLUID_SEQ_VOLUME:
{ {
short ctrl = 0x07; // VOLUME_MSB short ctrl = 0x07; // VOLUME_MSB
fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt)); fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
} }
break; break;
case FLUID_SEQ_REVERBSEND: case FLUID_SEQ_REVERBSEND:
{ {
short ctrl = 0x5B; // EFFECTS_DEPTH1 short ctrl = 0x5B; // EFFECTS_DEPTH1
fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt)); fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
} }
break; break;
case FLUID_SEQ_CHORUSSEND: case FLUID_SEQ_CHORUSSEND:
{ {
short ctrl = 0x5D; // EFFECTS_DEPTH3 short ctrl = 0x5D; // EFFECTS_DEPTH3
fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt)); fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
} }
break; break;
case FLUID_SEQ_TIMER: case FLUID_SEQ_TIMER:
/* nothing in fluidsynth */ /* nothing in fluidsynth */
break; break;
default: default:
break; break;
} }
+128 -115
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -19,18 +19,21 @@
*/ */
#include "fluidsynth_priv.h" #include "fluidsynth_priv.h"
#include "fluid_settings.h" #include "fluid_sys.h"
#include "fluid_hash.h" #include "fluid_hash.h"
#include "fluid_strtok.h"
#include "fluid_synth.h" #include "fluid_synth.h"
#include "fluid_cmd.h" #include "fluid_cmd.h"
#include "fluid_adriver.h" #include "fluid_adriver.h"
#include "fluid_mdriver.h" #include "fluid_mdriver.h"
#include "fluid_settings.h"
/* maximum allowed components of a settings variable (separated by '.') */
#define MAX_SETTINGS_TOKENS 8 /* currently only a max of 3 are used */
#define MAX_SETTINGS_LABEL 256 /* max length of a settings variable label */
static void fluid_settings_init(fluid_settings_t* settings); static void fluid_settings_init(fluid_settings_t* settings);
static void fluid_settings_hash_delete(void* value, int type); static void fluid_settings_hash_delete(void* value, int type);
static int fluid_settings_tokenize(char* s, char* buf, char** ptr); static int fluid_settings_tokenize(char* s, char *buf, char** ptr);
typedef struct { typedef struct {
@@ -42,7 +45,7 @@ typedef struct {
void* data; void* data;
} fluid_str_setting_t; } fluid_str_setting_t;
static fluid_str_setting_t* static fluid_str_setting_t*
new_fluid_str_setting(char* value, char* def, int hints, fluid_str_update_t fun, void* data) new_fluid_str_setting(char* value, char* def, int hints, fluid_str_update_t fun, void* data)
{ {
fluid_str_setting_t* str; fluid_str_setting_t* str;
@@ -60,13 +63,20 @@ static void delete_fluid_str_setting(fluid_str_setting_t* str)
{ {
if (str) { if (str) {
if (str->value) { if (str->value) {
FLUID_FREE(str->value); FLUID_FREE(str->value);
} }
if (str->def) { if (str->def) {
FLUID_FREE(str->def); FLUID_FREE(str->def);
} }
if (str->options) { if (str->options) {
delete_fluid_list(str->options); fluid_list_t* list = str->options;
while (list) {
FLUID_FREE (list->data);
list = fluid_list_next(list);
}
delete_fluid_list(str->options);
} }
FLUID_FREE(str); FLUID_FREE(str);
} }
@@ -86,7 +96,7 @@ typedef struct {
} fluid_num_setting_t; } fluid_num_setting_t;
static fluid_num_setting_t* static fluid_num_setting_t*
new_fluid_num_setting(double min, double max, double def, new_fluid_num_setting(double min, double max, double def,
int hints, fluid_num_update_t fun, void* data) int hints, fluid_num_update_t fun, void* data)
{ {
@@ -123,7 +133,7 @@ typedef struct {
} fluid_int_setting_t; } fluid_int_setting_t;
static fluid_int_setting_t* static fluid_int_setting_t*
new_fluid_int_setting(int min, int max, int def, new_fluid_int_setting(int min, int max, int def,
int hints, fluid_int_update_t fun, void* data) int hints, fluid_int_update_t fun, void* data)
{ {
@@ -189,37 +199,46 @@ void fluid_settings_init(fluid_settings_t* settings)
fluid_midi_driver_settings(settings); fluid_midi_driver_settings(settings);
} }
static fluid_strtok_t* fluid_settings_strtok = NULL; static int fluid_settings_tokenize(char* s, char *buf, char** ptr)
int fluid_settings_tokenize(char* s, char* buf, char** ptr)
{ {
char *tokstr, *tok;
int n = 0; int n = 0;
FLUID_STRCPY(buf, s); if (strlen (s) > MAX_SETTINGS_LABEL)
{
if (fluid_settings_strtok == NULL) { FLUID_LOG(FLUID_ERR, "Setting variable name exceeded max length of %d chars",
fluid_settings_strtok = new_fluid_strtok(buf, "."); MAX_SETTINGS_LABEL);
} else { return 0;
fluid_strtok_set(fluid_settings_strtok, buf, ".");
} }
while (fluid_strtok_has_more(fluid_settings_strtok)) { FLUID_STRCPY(buf, s); /* copy string to buffer, since it gets modified */
ptr[n++] = fluid_strtok_next_token(fluid_settings_strtok); tokstr = buf;
while ((tok = fluid_strtok (&tokstr, ".")))
{
if (n > MAX_SETTINGS_TOKENS)
{
FLUID_LOG(FLUID_ERR, "Setting variable name exceeded max token count of %d",
MAX_SETTINGS_TOKENS);
return 0;
}
ptr[n++] = tok;
} }
return n; return n;
} }
/** returns 1 if the value exists, 0 otherwise */ /** returns 1 if the value exists, 0 otherwise */
static int fluid_settings_get(fluid_settings_t* settings, static int fluid_settings_get(fluid_settings_t* settings,
char** name, int len, char** name, int len,
void** value, int* type) void** value, int* type)
{ {
fluid_hashtable_t* table = settings; fluid_hashtable_t* table = settings;
int t; int t;
void* v; void* v;
int n; int n;
for (n = 0; n < len; n++) { for (n = 0; n < len; n++) {
if (table == NULL) { if (table == NULL) {
@@ -244,10 +263,9 @@ static int fluid_settings_get(fluid_settings_t* settings,
return 1; return 1;
} }
/** returns 1 if the value has been set, zero otherwise */ /** returns 1 if the value has been set, zero otherwise */
static int fluid_settings_set(fluid_settings_t* settings, static int fluid_settings_set(fluid_settings_t* settings,
char** name, int len, char** name, int len,
void* value, int type) void* value, int type)
{ {
fluid_hashtable_t* table = settings; fluid_hashtable_t* table = settings;
@@ -276,29 +294,29 @@ static int fluid_settings_set(fluid_settings_t* settings,
} }
} }
fluid_hashtable_replace(table, name[num], value, type); fluid_hashtable_replace(table, name[num], value, type);
return 1; return 1;
} }
/** returns 1 if the value has been resgister correctly, 0 /** returns 1 if the value has been registered correctly, 0
otherwise */ otherwise */
int fluid_settings_register_str(fluid_settings_t* settings, char* name, char* def, int hints, int fluid_settings_register_str(fluid_settings_t* settings, char* name, char* def, int hints,
fluid_str_update_t fun, void* data) fluid_str_update_t fun, void* data)
{ {
int type; int type;
void* value; void* value;
char buf[1024]; char* tokens[MAX_SETTINGS_TOKENS];
char* tokens[16]; char buf[MAX_SETTINGS_LABEL+1];
int ntokens; int ntokens;
fluid_str_setting_t* setting; fluid_str_setting_t* setting;
ntokens = fluid_settings_tokenize(name, buf, tokens); ntokens = fluid_settings_tokenize(name, buf, tokens);
if (!fluid_settings_get(settings, tokens, ntokens, &value, &type)) { if (!fluid_settings_get(settings, tokens, ntokens, &value, &type)) {
setting = new_fluid_str_setting(def, def, hints, fun, data); setting = new_fluid_str_setting(def, def, hints, fun, data);
return fluid_settings_set(settings, tokens, ntokens, setting, FLUID_STR_TYPE); return fluid_settings_set(settings, tokens, ntokens, setting, FLUID_STR_TYPE);
} else { } else {
/* if variable already exists, don't change its value. */ /* if variable already exists, don't change its value. */
if (type == FLUID_STR_TYPE) { if (type == FLUID_STR_TYPE) {
@@ -317,14 +335,14 @@ int fluid_settings_register_str(fluid_settings_t* settings, char* name, char* de
/** returns 1 if the value has been register correctly, zero /** returns 1 if the value has been register correctly, zero
otherwise */ otherwise */
int fluid_settings_register_num(fluid_settings_t* settings, char* name, double def, int fluid_settings_register_num(fluid_settings_t* settings, char* name, double def,
double min, double max, int hints, double min, double max, int hints,
fluid_num_update_t fun, void* data) fluid_num_update_t fun, void* data)
{ {
int type; int type;
void* value; void* value;
char buf[1024]; char* tokens[MAX_SETTINGS_TOKENS];
char* tokens[16]; char buf[MAX_SETTINGS_LABEL+1];
int ntokens; int ntokens;
ntokens = fluid_settings_tokenize(name, buf, tokens); ntokens = fluid_settings_tokenize(name, buf, tokens);
@@ -357,14 +375,14 @@ int fluid_settings_register_num(fluid_settings_t* settings, char* name, double d
/** returns 1 if the value has been register correctly, zero /** returns 1 if the value has been register correctly, zero
otherwise */ otherwise */
int fluid_settings_register_int(fluid_settings_t* settings, char* name, int def, int fluid_settings_register_int(fluid_settings_t* settings, char* name, int def,
int min, int max, int hints, int min, int max, int hints,
fluid_int_update_t fun, void* data) fluid_int_update_t fun, void* data)
{ {
int type; int type;
void* value; void* value;
char buf[1024]; char* tokens[MAX_SETTINGS_TOKENS];
char* tokens[16]; char buf[MAX_SETTINGS_LABEL+1];
int ntokens; int ntokens;
ntokens = fluid_settings_tokenize(name, buf, tokens); ntokens = fluid_settings_tokenize(name, buf, tokens);
@@ -395,13 +413,12 @@ int fluid_settings_register_int(fluid_settings_t* settings, char* name, int def,
} }
} }
int fluid_settings_get_type(fluid_settings_t* settings, char* name) int fluid_settings_get_type(fluid_settings_t* settings, char* name)
{ {
int type; int type;
void* value; void* value;
char buf[1024]; char* tokens[MAX_SETTINGS_TOKENS];
char* tokens[16]; char buf[MAX_SETTINGS_LABEL+1];
int ntokens; int ntokens;
ntokens = fluid_settings_tokenize(name, buf, tokens); ntokens = fluid_settings_tokenize(name, buf, tokens);
@@ -409,13 +426,12 @@ int fluid_settings_get_type(fluid_settings_t* settings, char* name)
return (fluid_settings_get(settings, tokens, ntokens, &value, &type))? type : FLUID_NO_TYPE; return (fluid_settings_get(settings, tokens, ntokens, &value, &type))? type : FLUID_NO_TYPE;
} }
int fluid_settings_get_hints(fluid_settings_t* settings, char* name) int fluid_settings_get_hints(fluid_settings_t* settings, char* name)
{ {
int type; int type;
void* value; void* value;
char buf[1024]; char* tokens[MAX_SETTINGS_TOKENS];
char* tokens[16]; char buf[MAX_SETTINGS_LABEL+1];
int ntokens; int ntokens;
ntokens = fluid_settings_tokenize(name, buf, tokens); ntokens = fluid_settings_tokenize(name, buf, tokens);
@@ -439,8 +455,8 @@ int fluid_settings_is_realtime(fluid_settings_t* settings, char* name)
{ {
int type; int type;
void* value; void* value;
char buf[1024]; char* tokens[MAX_SETTINGS_TOKENS];
char* tokens[16]; char buf[MAX_SETTINGS_LABEL+1];
int ntokens; int ntokens;
ntokens = fluid_settings_tokenize(name, buf, tokens); ntokens = fluid_settings_tokenize(name, buf, tokens);
@@ -461,11 +477,10 @@ int fluid_settings_is_realtime(fluid_settings_t* settings, char* name)
} }
} }
int fluid_settings_setstr(fluid_settings_t* settings, char* name, char* str) int fluid_settings_setstr(fluid_settings_t* settings, char* name, char* str)
{ {
char buf[1024]; char* tokens[MAX_SETTINGS_TOKENS];
char* tokens[16]; char buf[MAX_SETTINGS_LABEL+1];
int ntokens; int ntokens;
int type; int type;
void* value; void* value;
@@ -474,7 +489,7 @@ int fluid_settings_setstr(fluid_settings_t* settings, char* name, char* str)
ntokens = fluid_settings_tokenize(name, buf, tokens); ntokens = fluid_settings_tokenize(name, buf, tokens);
if (fluid_settings_get(settings, tokens, ntokens, &value, &type)) { if (fluid_settings_get(settings, tokens, ntokens, &value, &type)) {
if (type != FLUID_STR_TYPE) { if (type != FLUID_STR_TYPE) {
return 0; return 0;
} }
@@ -485,14 +500,14 @@ int fluid_settings_setstr(fluid_settings_t* settings, char* name, char* str)
FLUID_FREE(setting->value); FLUID_FREE(setting->value);
} }
setting->value = str? FLUID_STRDUP(str) : NULL; setting->value = str? FLUID_STRDUP(str) : NULL;
if (setting->update) { if (setting->update) {
(*setting->update)(setting->data, name, setting->value); (*setting->update)(setting->data, name, setting->value);
} }
return 1; return 1;
} else { } else {
/* insert a new setting */ /* insert a new setting */
fluid_str_setting_t* setting; fluid_str_setting_t* setting;
setting = new_fluid_str_setting(str, NULL, 0, NULL, NULL); setting = new_fluid_str_setting(str, NULL, 0, NULL, NULL);
@@ -504,13 +519,13 @@ int fluid_settings_getstr(fluid_settings_t* settings, char* name, char** str)
{ {
int type; int type;
void* value; void* value;
char buf[1024]; char* tokens[MAX_SETTINGS_TOKENS];
char* tokens[16]; char buf[MAX_SETTINGS_LABEL+1];
int ntokens; int ntokens;
ntokens = fluid_settings_tokenize(name, buf, tokens); ntokens = fluid_settings_tokenize(name, buf, tokens);
if (fluid_settings_get(settings, tokens, ntokens, &value, &type) if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
&& (type == FLUID_STR_TYPE)) { && (type == FLUID_STR_TYPE)) {
fluid_str_setting_t* setting = (fluid_str_setting_t*) value; fluid_str_setting_t* setting = (fluid_str_setting_t*) value;
*str = setting->value; *str = setting->value;
@@ -520,18 +535,17 @@ int fluid_settings_getstr(fluid_settings_t* settings, char* name, char** str)
return 0; return 0;
} }
int fluid_settings_str_equal(fluid_settings_t* settings, char* name, char* s) int fluid_settings_str_equal(fluid_settings_t* settings, char* name, char* s)
{ {
int type; int type;
void* value; void* value;
char buf[1024]; char* tokens[MAX_SETTINGS_TOKENS];
char* tokens[16]; char buf[MAX_SETTINGS_LABEL+1];
int ntokens; int ntokens;
ntokens = fluid_settings_tokenize(name, buf, tokens); ntokens = fluid_settings_tokenize(name, buf, tokens);
if (fluid_settings_get(settings, tokens, ntokens, &value, &type) if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
&& (type == FLUID_STR_TYPE)) { && (type == FLUID_STR_TYPE)) {
fluid_str_setting_t* setting = (fluid_str_setting_t*) value; fluid_str_setting_t* setting = (fluid_str_setting_t*) value;
return FLUID_STRCMP(setting->value, s) == 0; return FLUID_STRCMP(setting->value, s) == 0;
@@ -539,19 +553,18 @@ int fluid_settings_str_equal(fluid_settings_t* settings, char* name, char* s)
return 0; return 0;
} }
char*
char*
fluid_settings_getstr_default(fluid_settings_t* settings, char* name) fluid_settings_getstr_default(fluid_settings_t* settings, char* name)
{ {
int type; int type;
void* value; void* value;
char buf[1024]; char* tokens[MAX_SETTINGS_TOKENS];
char* tokens[16]; char buf[MAX_SETTINGS_LABEL+1];
int ntokens; int ntokens;
ntokens = fluid_settings_tokenize(name, buf, tokens); ntokens = fluid_settings_tokenize(name, buf, tokens);
if (fluid_settings_get(settings, tokens, ntokens, &value, &type) if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
&& (type == FLUID_STR_TYPE)) { && (type == FLUID_STR_TYPE)) {
fluid_str_setting_t* setting = (fluid_str_setting_t*) value; fluid_str_setting_t* setting = (fluid_str_setting_t*) value;
return setting->def; return setting->def;
@@ -564,13 +577,13 @@ int fluid_settings_add_option(fluid_settings_t* settings, char* name, char* s)
{ {
int type; int type;
void* value; void* value;
char buf[1024]; char* tokens[MAX_SETTINGS_TOKENS];
char* tokens[16]; char buf[MAX_SETTINGS_LABEL+1];
int ntokens; int ntokens;
ntokens = fluid_settings_tokenize(name, buf, tokens); ntokens = fluid_settings_tokenize(name, buf, tokens);
if (fluid_settings_get(settings, tokens, ntokens, &value, &type) if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
&& (type == FLUID_STR_TYPE)) { && (type == FLUID_STR_TYPE)) {
fluid_str_setting_t* setting = (fluid_str_setting_t*) value; fluid_str_setting_t* setting = (fluid_str_setting_t*) value;
char* copy = FLUID_STRDUP(s); char* copy = FLUID_STRDUP(s);
@@ -578,20 +591,20 @@ int fluid_settings_add_option(fluid_settings_t* settings, char* name, char* s)
return 1; return 1;
} else { } else {
return 0; return 0;
} }
} }
int fluid_settings_remove_option(fluid_settings_t* settings, char* name, char* s) int fluid_settings_remove_option(fluid_settings_t* settings, char* name, char* s)
{ {
int type; int type;
void* value; void* value;
char buf[1024]; char* tokens[MAX_SETTINGS_TOKENS];
char* tokens[16]; char buf[MAX_SETTINGS_LABEL+1];
int ntokens; int ntokens;
ntokens = fluid_settings_tokenize(name, buf, tokens); ntokens = fluid_settings_tokenize(name, buf, tokens);
if (fluid_settings_get(settings, tokens, ntokens, &value, &type) if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
&& (type == FLUID_STR_TYPE)) { && (type == FLUID_STR_TYPE)) {
fluid_str_setting_t* setting = (fluid_str_setting_t*) value; fluid_str_setting_t* setting = (fluid_str_setting_t*) value;
@@ -600,6 +613,7 @@ int fluid_settings_remove_option(fluid_settings_t* settings, char* name, char* s
while (list) { while (list) {
char* option = (char*) fluid_list_get(list); char* option = (char*) fluid_list_get(list);
if (FLUID_STRCMP(s, option) == 0) { if (FLUID_STRCMP(s, option) == 0) {
FLUID_FREE (option);
setting->options = fluid_list_remove_link(setting->options, list); setting->options = fluid_list_remove_link(setting->options, list);
return 1; return 1;
} }
@@ -609,17 +623,16 @@ int fluid_settings_remove_option(fluid_settings_t* settings, char* name, char* s
return 0; return 0;
} else { } else {
return 0; return 0;
} }
} }
int fluid_settings_setnum(fluid_settings_t* settings, char* name, double val) int fluid_settings_setnum(fluid_settings_t* settings, char* name, double val)
{ {
int type; int type;
void* value; void* value;
fluid_num_setting_t* setting; fluid_num_setting_t* setting;
char buf[1024]; char* tokens[MAX_SETTINGS_TOKENS];
char* tokens[16]; char buf[MAX_SETTINGS_LABEL+1];
int ntokens; int ntokens;
ntokens = fluid_settings_tokenize(name, buf, tokens); ntokens = fluid_settings_tokenize(name, buf, tokens);
@@ -631,22 +644,22 @@ int fluid_settings_setnum(fluid_settings_t* settings, char* name, double val)
} }
setting = (fluid_num_setting_t*) value; setting = (fluid_num_setting_t*) value;
if (val < setting->min) { if (val < setting->min) {
val = setting->min; val = setting->min;
} else if (val > setting->max) { } else if (val > setting->max) {
val = setting->max; val = setting->max;
} }
setting->value = val; setting->value = val;
if (setting->update) { if (setting->update) {
(*setting->update)(setting->data, name, val); (*setting->update)(setting->data, name, val);
} }
return 1; return 1;
} else { } else {
/* insert a new setting */ /* insert a new setting */
fluid_num_setting_t* setting; fluid_num_setting_t* setting;
setting = new_fluid_num_setting(-1e10, 1e10, 0.0f, 0, NULL, NULL); setting = new_fluid_num_setting(-1e10, 1e10, 0.0f, 0, NULL, NULL);
@@ -659,13 +672,13 @@ int fluid_settings_getnum(fluid_settings_t* settings, char* name, double* val)
{ {
int type; int type;
void* value; void* value;
char buf[1024]; char* tokens[MAX_SETTINGS_TOKENS];
char* tokens[16]; char buf[MAX_SETTINGS_LABEL+1];
int ntokens; int ntokens;
ntokens = fluid_settings_tokenize(name, buf, tokens); ntokens = fluid_settings_tokenize(name, buf, tokens);
if (fluid_settings_get(settings, tokens, ntokens, &value, &type) if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
&& (type == FLUID_NUM_TYPE)) { && (type == FLUID_NUM_TYPE)) {
fluid_num_setting_t* setting = (fluid_num_setting_t*) value; fluid_num_setting_t* setting = (fluid_num_setting_t*) value;
*val = setting->value; *val = setting->value;
@@ -679,13 +692,13 @@ void fluid_settings_getnum_range(fluid_settings_t* settings, char* name, double*
{ {
int type; int type;
void* value; void* value;
char buf[1024]; char* tokens[MAX_SETTINGS_TOKENS];
char* tokens[16]; char buf[MAX_SETTINGS_LABEL+1];
int ntokens; int ntokens;
ntokens = fluid_settings_tokenize(name, buf, tokens); ntokens = fluid_settings_tokenize(name, buf, tokens);
if (fluid_settings_get(settings, tokens, ntokens, &value, &type) if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
&& (type == FLUID_NUM_TYPE)) { && (type == FLUID_NUM_TYPE)) {
fluid_num_setting_t* setting = (fluid_num_setting_t*) value; fluid_num_setting_t* setting = (fluid_num_setting_t*) value;
*min = setting->min; *min = setting->min;
@@ -693,18 +706,18 @@ void fluid_settings_getnum_range(fluid_settings_t* settings, char* name, double*
} }
} }
double double
fluid_settings_getnum_default(fluid_settings_t* settings, char* name) fluid_settings_getnum_default(fluid_settings_t* settings, char* name)
{ {
int type; int type;
void* value; void* value;
char buf[1024]; char* tokens[MAX_SETTINGS_TOKENS];
char* tokens[16]; char buf[MAX_SETTINGS_LABEL+1];
int ntokens; int ntokens;
ntokens = fluid_settings_tokenize(name, buf, tokens); ntokens = fluid_settings_tokenize(name, buf, tokens);
if (fluid_settings_get(settings, tokens, ntokens, &value, &type) if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
&& (type == FLUID_NUM_TYPE)) { && (type == FLUID_NUM_TYPE)) {
fluid_num_setting_t* setting = (fluid_num_setting_t*) value; fluid_num_setting_t* setting = (fluid_num_setting_t*) value;
return setting->def; return setting->def;
@@ -719,8 +732,8 @@ int fluid_settings_setint(fluid_settings_t* settings, char* name, int val)
int type; int type;
void* value; void* value;
fluid_int_setting_t* setting; fluid_int_setting_t* setting;
char buf[1024]; char* tokens[MAX_SETTINGS_TOKENS];
char* tokens[16]; char buf[MAX_SETTINGS_LABEL+1];
int ntokens; int ntokens;
ntokens = fluid_settings_tokenize(name, buf, tokens); ntokens = fluid_settings_tokenize(name, buf, tokens);
@@ -732,22 +745,22 @@ int fluid_settings_setint(fluid_settings_t* settings, char* name, int val)
} }
setting = (fluid_int_setting_t*) value; setting = (fluid_int_setting_t*) value;
if (val < setting->min) { if (val < setting->min) {
val = setting->min; val = setting->min;
} else if (val > setting->max) { } else if (val > setting->max) {
val = setting->max; val = setting->max;
} }
setting->value = val; setting->value = val;
if (setting->update) { if (setting->update) {
(*setting->update)(setting->data, name, val); (*setting->update)(setting->data, name, val);
} }
return 1; return 1;
} else { } else {
/* insert a new setting */ /* insert a new setting */
fluid_int_setting_t* setting; fluid_int_setting_t* setting;
setting = new_fluid_int_setting(INT_MIN, INT_MAX, 0, 0, NULL, NULL); setting = new_fluid_int_setting(INT_MIN, INT_MAX, 0, 0, NULL, NULL);
@@ -760,13 +773,13 @@ int fluid_settings_getint(fluid_settings_t* settings, char* name, int* val)
{ {
int type; int type;
void* value; void* value;
char buf[1024]; char* tokens[MAX_SETTINGS_TOKENS];
char* tokens[16]; char buf[MAX_SETTINGS_LABEL+1];
int ntokens; int ntokens;
ntokens = fluid_settings_tokenize(name, buf, tokens); ntokens = fluid_settings_tokenize(name, buf, tokens);
if (fluid_settings_get(settings, tokens, ntokens, &value, &type) if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
&& (type == FLUID_INT_TYPE)) { && (type == FLUID_INT_TYPE)) {
fluid_int_setting_t* setting = (fluid_int_setting_t*) value; fluid_int_setting_t* setting = (fluid_int_setting_t*) value;
*val = setting->value; *val = setting->value;
@@ -780,13 +793,13 @@ void fluid_settings_getint_range(fluid_settings_t* settings, char* name, int* mi
{ {
int type; int type;
void* value; void* value;
char buf[1024]; char* tokens[MAX_SETTINGS_TOKENS];
char* tokens[16]; char buf[MAX_SETTINGS_LABEL+1];
int ntokens; int ntokens;
ntokens = fluid_settings_tokenize(name, buf, tokens); ntokens = fluid_settings_tokenize(name, buf, tokens);
if (fluid_settings_get(settings, tokens, ntokens, &value, &type) if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
&& (type == FLUID_INT_TYPE)) { && (type == FLUID_INT_TYPE)) {
fluid_int_setting_t* setting = (fluid_int_setting_t*) value; fluid_int_setting_t* setting = (fluid_int_setting_t*) value;
*min = setting->min; *min = setting->min;
@@ -799,13 +812,13 @@ fluid_settings_getint_default(fluid_settings_t* settings, char* name)
{ {
int type; int type;
void* value; void* value;
char buf[1024]; char* tokens[MAX_SETTINGS_TOKENS];
char* tokens[16]; char buf[MAX_SETTINGS_LABEL+1];
int ntokens; int ntokens;
ntokens = fluid_settings_tokenize(name, buf, tokens); ntokens = fluid_settings_tokenize(name, buf, tokens);
if (fluid_settings_get(settings, tokens, ntokens, &value, &type) if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
&& (type == FLUID_INT_TYPE)) { && (type == FLUID_INT_TYPE)) {
fluid_int_setting_t* setting = (fluid_int_setting_t*) value; fluid_int_setting_t* setting = (fluid_int_setting_t*) value;
return setting->def; return setting->def;
@@ -817,13 +830,13 @@ fluid_settings_getint_default(fluid_settings_t* settings, char* name)
void fluid_settings_foreach_option(fluid_settings_t* settings, char* name, void* data, void fluid_settings_foreach_option(fluid_settings_t* settings, char* name, void* data,
fluid_settings_foreach_option_t func) fluid_settings_foreach_option_t func)
{ {
int type; int type;
void* value; void* value;
char buf[1024]; char* tokens[MAX_SETTINGS_TOKENS];
char* tokens[16]; char buf[MAX_SETTINGS_LABEL+1];
int ntokens; int ntokens;
if (!func) { if (!func) {
@@ -832,7 +845,7 @@ void fluid_settings_foreach_option(fluid_settings_t* settings, char* name, void*
ntokens = fluid_settings_tokenize(name, buf, tokens); ntokens = fluid_settings_tokenize(name, buf, tokens);
if (fluid_settings_get(settings, tokens, ntokens, &value, &type) if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
&& (type == FLUID_STR_TYPE)) { && (type == FLUID_STR_TYPE)) {
fluid_str_setting_t* setting = (fluid_str_setting_t*) value; fluid_str_setting_t* setting = (fluid_str_setting_t*) value;
@@ -843,7 +856,7 @@ void fluid_settings_foreach_option(fluid_settings_t* settings, char* name, void*
(*func)(data, name, option); (*func)(data, name, option);
list = fluid_list_next(list); list = fluid_list_next(list);
} }
} }
} }
+3 -3
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -42,13 +42,13 @@ int fluid_settings_register_str(fluid_settings_t* settings, char* name, char* de
/** returns 0 if the value has been resgister correctly, non-zero /** returns 0 if the value has been resgister correctly, non-zero
otherwise */ otherwise */
int fluid_settings_register_num(fluid_settings_t* settings, char* name, double min, double max, int fluid_settings_register_num(fluid_settings_t* settings, char* name, double min, double max,
double def, int hints, fluid_num_update_t fun, void* data); double def, int hints, fluid_num_update_t fun, void* data);
/** returns 0 if the value has been resgister correctly, non-zero /** returns 0 if the value has been resgister correctly, non-zero
otherwise */ otherwise */
int fluid_settings_register_int(fluid_settings_t* settings, char* name, int min, int max, int fluid_settings_register_int(fluid_settings_t* settings, char* name, int min, int max,
int def, int hints, fluid_int_update_t fun, void* data); int def, int hints, fluid_int_update_t fun, void* data);
+2 -2
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -61,7 +61,7 @@
#define fluid_sample_decr_ref(_sample) \ #define fluid_sample_decr_ref(_sample) \
(_sample)->refcount--; \ (_sample)->refcount--; \
if (((_sample)->refcount == 0) && ((_sample)->notify)) \ if (((_sample)->refcount == 0) && ((_sample)->notify)) \
(*(_sample)->notify)(_sample, FLUID_SAMPLE_DONE); (*(_sample)->notify)(_sample, FLUID_SAMPLE_DONE);
-263
View File
@@ -1,263 +0,0 @@
/*
* sse.h
* Copyright (C) 1999 R. Fisher
*
* This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
*
* mpeg2dec is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* mpeg2dec is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* Purpose:
* This file defines assembler macros for the SSE instructions of Pentium III and higher.
* They are used to execute several floating point multiplications in parallel.
*/
#ifndef FLUID_SSE_H
#define FLUID_SSE_H
typedef union {
float sf[4]; /* Single-precision (32-bit) value */
} __attribute__ ((aligned(16))) sse_t; /* On a 16 byte (128-bit) boundary */
#define sse_i2r(op, imm, reg) \
__asm__ __volatile__ (#op " %0, %%" #reg \
: /* nothing */ \
: "X" (imm) )
#define sse_m2r(op, mem, reg) \
__asm__ __volatile__ (#op " %0, %%" #reg \
: /* nothing */ \
: "X" (mem))
#define sse_r2m(op, reg, mem) \
__asm__ __volatile__ (#op " %%" #reg ", %0" \
: "=X" (mem) \
: /* nothing */ )
#define sse_r2r(op, regs, regd) \
__asm__ __volatile__ (#op " %" #regs ", %" #regd)
#define sse_r2ri(op, regs, regd, imm) \
__asm__ __volatile__ (#op " %0, %%" #regs ", %%" #regd \
: /* nothing */ \
: "X" (imm) )
#define sse_m2ri(op, mem, reg, subop) \
__asm__ __volatile__ (#op " %0, %%" #reg ", " #subop \
: /* nothing */ \
: "X" (mem))
#define movaps_m2r(var, reg) sse_m2r(movaps, var, reg)
#define movaps_r2m(reg, var) sse_r2m(movaps, reg, var)
#define movaps_r2r(regs, regd) sse_r2r(movaps, regs, regd)
#define movntps_r2m(xmmreg, var) sse_r2m(movntps, xmmreg, var)
#define movups_m2r(var, reg) sse_m2r(movups, var, reg)
#define movups_r2m(reg, var) sse_r2m(movups, reg, var)
#define movups_r2r(regs, regd) sse_r2r(movups, regs, regd)
#define movhlps_r2r(regs, regd) sse_r2r(movhlps, regs, regd)
#define movlhps_r2r(regs, regd) sse_r2r(movlhps, regs, regd)
#define movhps_m2r(var, reg) sse_m2r(movhps, var, reg)
#define movhps_r2m(reg, var) sse_r2m(movhps, reg, var)
#define movlps_m2r(var, reg) sse_m2r(movlps, var, reg)
#define movlps_r2m(reg, var) sse_r2m(movlps, reg, var)
#define movss_m2r(var, reg) sse_m2r(movss, var, reg)
#define movss_r2m(reg, var) sse_r2m(movss, reg, var)
#define movss_r2r(regs, regd) sse_r2r(movss, regs, regd)
#define shufps_m2r(var, reg, index) sse_m2ri(shufps, var, reg, index)
#define shufps_r2r(regs, regd, index) sse_r2ri(shufps, regs, regd, index)
#define cvtpi2ps_m2r(var, xmmreg) sse_m2r(cvtpi2ps, var, xmmreg)
#define cvtpi2ps_r2r(mmreg, xmmreg) sse_r2r(cvtpi2ps, mmreg, xmmreg)
#define cvtps2pi_m2r(var, mmreg) sse_m2r(cvtps2pi, var, mmreg)
#define cvtps2pi_r2r(xmmreg, mmreg) sse_r2r(cvtps2pi, mmreg, xmmreg)
#define cvttps2pi_m2r(var, mmreg) sse_m2r(cvttps2pi, var, mmreg)
#define cvttps2pi_r2r(xmmreg, mmreg) sse_r2r(cvttps2pi, mmreg, xmmreg)
#define cvtsi2ss_m2r(var, xmmreg) sse_m2r(cvtsi2ss, var, xmmreg)
#define cvtsi2ss_r2r(reg, xmmreg) sse_r2r(cvtsi2ss, reg, xmmreg)
#define cvtss2si_m2r(var, reg) sse_m2r(cvtss2si, var, reg)
#define cvtss2si_r2r(xmmreg, reg) sse_r2r(cvtss2si, xmmreg, reg)
#define cvttss2si_m2r(var, reg) sse_m2r(cvtss2si, var, reg)
#define cvttss2si_r2r(xmmreg, reg) sse_r2r(cvtss2si, xmmreg, reg)
#define movmskps(xmmreg, reg) \
__asm__ __volatile__ ("movmskps %" #xmmreg ", %" #reg)
#define addps_m2r(var, reg) sse_m2r(addps, var, reg)
#define addps_r2r(regs, regd) sse_r2r(addps, regs, regd)
#define addss_m2r(var, reg) sse_m2r(addss, var, reg)
#define addss_r2r(regs, regd) sse_r2r(addss, regs, regd)
#define subps_m2r(var, reg) sse_m2r(subps, var, reg)
#define subps_r2r(regs, regd) sse_r2r(subps, regs, regd)
#define subss_m2r(var, reg) sse_m2r(subss, var, reg)
#define subss_r2r(regs, regd) sse_r2r(subss, regs, regd)
#define mulps_m2r(var, reg) sse_m2r(mulps, var, reg)
#define mulps_r2r(regs, regd) sse_r2r(mulps, regs, regd)
#define mulss_m2r(var, reg) sse_m2r(mulss, var, reg)
#define mulss_r2r(regs, regd) sse_r2r(mulss, regs, regd)
#define divps_m2r(var, reg) sse_m2r(divps, var, reg)
#define divps_r2r(regs, regd) sse_r2r(divps, regs, regd)
#define divss_m2r(var, reg) sse_m2r(divss, var, reg)
#define divss_r2r(regs, regd) sse_r2r(divss, regs, regd)
#define rcpps_m2r(var, reg) sse_m2r(rcpps, var, reg)
#define rcpps_r2r(regs, regd) sse_r2r(rcpps, regs, regd)
#define rcpss_m2r(var, reg) sse_m2r(rcpss, var, reg)
#define rcpss_r2r(regs, regd) sse_r2r(rcpss, regs, regd)
#define rsqrtps_m2r(var, reg) sse_m2r(rsqrtps, var, reg)
#define rsqrtps_r2r(regs, regd) sse_r2r(rsqrtps, regs, regd)
#define rsqrtss_m2r(var, reg) sse_m2r(rsqrtss, var, reg)
#define rsqrtss_r2r(regs, regd) sse_r2r(rsqrtss, regs, regd)
#define sqrtps_m2r(var, reg) sse_m2r(sqrtps, var, reg)
#define sqrtps_r2r(regs, regd) sse_r2r(sqrtps, regs, regd)
#define sqrtss_m2r(var, reg) sse_m2r(sqrtss, var, reg)
#define sqrtss_r2r(regs, regd) sse_r2r(sqrtss, regs, regd)
#define andps_m2r(var, reg) sse_m2r(andps, var, reg)
#define andps_r2r(regs, regd) sse_r2r(andps, regs, regd)
#define andnps_m2r(var, reg) sse_m2r(andnps, var, reg)
#define andnps_r2r(regs, regd) sse_r2r(andnps, regs, regd)
#define orps_m2r(var, reg) sse_m2r(orps, var, reg)
#define orps_r2r(regs, regd) sse_r2r(orps, regs, regd)
#define xorps_m2r(var, reg) sse_m2r(xorps, var, reg)
#define xorps_r2r(regs, regd) sse_r2r(xorps, regs, regd)
#define maxps_m2r(var, reg) sse_m2r(maxps, var, reg)
#define maxps_r2r(regs, regd) sse_r2r(maxps, regs, regd)
#define maxss_m2r(var, reg) sse_m2r(maxss, var, reg)
#define maxss_r2r(regs, regd) sse_r2r(maxss, regs, regd)
#define minps_m2r(var, reg) sse_m2r(minps, var, reg)
#define minps_r2r(regs, regd) sse_r2r(minps, regs, regd)
#define minss_m2r(var, reg) sse_m2r(minss, var, reg)
#define minss_r2r(regs, regd) sse_r2r(minss, regs, regd)
#define cmpps_m2r(var, reg, op) sse_m2ri(cmpps, var, reg, op)
#define cmpps_r2r(regs, regd, op) sse_r2ri(cmpps, regs, regd, op)
#define cmpeqps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 0)
#define cmpeqps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 0)
#define cmpltps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 1)
#define cmpltps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 1)
#define cmpleps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 2)
#define cmpleps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 2)
#define cmpunordps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 3)
#define cmpunordps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 3)
#define cmpneqps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 4)
#define cmpneqps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 4)
#define cmpnltps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 5)
#define cmpnltps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 5)
#define cmpnleps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 6)
#define cmpnleps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 6)
#define cmpordps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 7)
#define cmpordps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 7)
#define cmpss_m2r(var, reg, op) sse_m2ri(cmpss, var, reg, op)
#define cmpss_r2r(regs, regd, op) sse_r2ri(cmpss, regs, regd, op)
#define cmpeqss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 0)
#define cmpeqss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 0)
#define cmpltss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 1)
#define cmpltss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 1)
#define cmpless_m2r(var, reg) sse_m2ri(cmpss, var, reg, 2)
#define cmpless_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 2)
#define cmpunordss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 3)
#define cmpunordss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 3)
#define cmpneqss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 4)
#define cmpneqss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 4)
#define cmpnltss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 5)
#define cmpnltss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 5)
#define cmpnless_m2r(var, reg) sse_m2ri(cmpss, var, reg, 6)
#define cmpnless_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 6)
#define cmpordss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 7)
#define cmpordss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 7)
#define comiss_m2r(var, reg) sse_m2r(comiss, var, reg)
#define comiss_r2r(regs, regd) sse_r2r(comiss, regs, regd)
#define ucomiss_m2r(var, reg) sse_m2r(ucomiss, var, reg)
#define ucomiss_r2r(regs, regd) sse_r2r(ucomiss, regs, regd)
#define unpcklps_m2r(var, reg) sse_m2r(unpcklps, var, reg)
#define unpcklps_r2r(regs, regd) sse_r2r(unpcklps, regs, regd)
#define unpckhps_m2r(var, reg) sse_m2r(unpckhps, var, reg)
#define unpckhps_r2r(regs, regd) sse_r2r(unpckhps, regs, regd)
#define fxrstor(mem) \
__asm__ __volatile__ ("fxrstor %0" \
: /* nothing */ \
: "X" (mem))
#define fxsave(mem) \
__asm__ __volatile__ ("fxsave %0" \
: /* nothing */ \
: "X" (mem))
#define stmxcsr(mem) \
__asm__ __volatile__ ("stmxcsr %0" \
: /* nothing */ \
: "X" (mem))
#define ldmxcsr(mem) \
__asm__ __volatile__ ("ldmxcsr %0" \
: /* nothing */ \
: "X" (mem))
#endif
-123
View File
@@ -1,123 +0,0 @@
/* FluidSynth - A Software Synthesizer
*
* Copyright (C) 2003 Peter Hanappe and others.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License
* as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307, USA
*/
#include "fluid_strtok.h"
#include "fluidsynth_priv.h"
/*
* new_fluid_strtok
*/
fluid_strtok_t* new_fluid_strtok(char* s, char* d)
{
fluid_strtok_t* st;
st = FLUID_NEW(fluid_strtok_t);
if (st == NULL) {
FLUID_LOG(FLUID_ERR, "Out of memory");
return NULL;
}
/* Careful! the strings are not copied for speed */
st->string = s;
st->delimiters = d;
st->offset = 0;
st->len = (s == NULL)? 0 : strlen(s);
return st;
}
int delete_fluid_strtok(fluid_strtok_t* st)
{
if (st == NULL) {
FLUID_LOG(FLUID_ERR, "Null pointer");
return 0;
}
free(st);
return 0;
}
int fluid_strtok_set(fluid_strtok_t* st, char* s, char* d)
{
/* Careful! the strings are not copied for speed */
st->string = s;
st->delimiters = d;
st->offset = 0;
st->len = (s == NULL)? 0 : strlen(s);
return 0;
}
char* fluid_strtok_next_token(fluid_strtok_t* st)
{
int start = st->offset;
int end;
if ((st == NULL) || (st->string == NULL) || (st->delimiters == NULL)) {
FLUID_LOG(FLUID_ERR, "Null pointer");
return NULL;
}
if (start >= st->len) {
return NULL;
}
while (fluid_strtok_char_index(st->string[start], st->delimiters) >= 0) {
if (start == st->len) {
return NULL;
}
start++;
}
end = start + 1;
while (fluid_strtok_char_index(st->string[end], st->delimiters) < 0) {
if (end == st->len) {
break;
}
end++;
}
st->string[end] = 0;
st->offset = end + 1;
return &st->string[start];
}
int fluid_strtok_has_more(fluid_strtok_t* st)
{
int cur = st->offset;
if ((st == NULL) || (st->string == NULL) || (st->delimiters == NULL)) {
FLUID_LOG(FLUID_ERR, "Null pointer");
return -1;
}
while (cur < st->len) {
if (fluid_strtok_char_index(st->string[cur], st->delimiters) < 0) {
return -1;
}
cur++;
}
return 0;
}
int fluid_strtok_char_index(char c, char* s)
{
int i;
if (s == NULL) {
FLUID_LOG(FLUID_ERR, "Null pointer");
return -1;
}
for (i = 0; s[i] != 0; i++) {
if (s[i] == c) {
return i;
}
}
return -1;
}
-44
View File
@@ -1,44 +0,0 @@
/* FluidSynth - A Software Synthesizer
*
* Copyright (C) 2003 Peter Hanappe and others.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License
* as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307, USA
*/
#ifndef _FLUID_STRTOK_H
#define _FLUID_STRTOK_H
#include "fluidsynth_priv.h"
/** string tokenizer */
typedef struct {
char* string;
char* delimiters;
int offset;
int len;
} fluid_strtok_t;
fluid_strtok_t* new_fluid_strtok(char* s, char* d);
int delete_fluid_strtok(fluid_strtok_t* st);
int fluid_strtok_set(fluid_strtok_t* st, char* s, char* d);
char* fluid_strtok_next_token(fluid_strtok_t* st);
int fluid_strtok_has_more(fluid_strtok_t* st);
int fluid_strtok_char_index(char c, char* s);
#endif /* _FLUID_STRTOK_H */
File diff suppressed because it is too large Load Diff
+15 -19
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -98,7 +98,7 @@ struct _fluid_synth_t
double sample_rate; /** The sample rate */ double sample_rate; /** The sample rate */
int midi_channels; /** the number of MIDI channels (>= 16) */ int midi_channels; /** the number of MIDI channels (>= 16) */
int audio_channels; /** the number of audio channels (1 channel=left+right) */ int audio_channels; /** the number of audio channels (1 channel=left+right) */
int audio_groups; /** the number of (stereo) 'sub'groups from the synth. int audio_groups; /** the number of (stereo) 'sub'groups from the synth.
Typically equal to audio_channels. */ Typically equal to audio_channels. */
int effects_channels; /** the number of effects channels (= 2) */ int effects_channels; /** the number of effects channels (= 2) */
unsigned int state; /** the synthesizer state */ unsigned int state; /** the synthesizer state */
@@ -120,7 +120,7 @@ struct _fluid_synth_t
int nvoice; /** the length of the synthesis process array */ int nvoice; /** the length of the synthesis process array */
fluid_voice_t** voice; /** the synthesis processes */ fluid_voice_t** voice; /** the synthesis processes */
unsigned int noteid; /** the id is incremented for every new note. it's used for noteoff's */ unsigned int noteid; /** the id is incremented for every new note. it's used for noteoff's */
unsigned int storeid; unsigned int storeid;
int nbuf; /** How many audio buffers are used? (depends on nr of audio channels / groups)*/ int nbuf; /** How many audio buffers are used? (depends on nr of audio channels / groups)*/
fluid_real_t** left_buf; fluid_real_t** left_buf;
@@ -128,23 +128,19 @@ struct _fluid_synth_t
fluid_real_t** fx_left_buf; fluid_real_t** fx_left_buf;
fluid_real_t** fx_right_buf; fluid_real_t** fx_right_buf;
fluid_real_t** left_ubuf; /* Stores the unaligned buffers (see new_fluid_synth) */
fluid_real_t** right_ubuf; /* Stores the unaligned buffers (see new_fluid_synth) */
fluid_real_t** fx_left_ubuf; /* Stores the unaligned buffers (see new_fluid_synth) */
fluid_real_t** fx_right_ubuf; /* Stores the unaligned buffers (see new_fluid_synth) */
fluid_revmodel_t* reverb; fluid_revmodel_t* reverb;
fluid_chorus_t* chorus; fluid_chorus_t* chorus;
int cur; /** the current sample in the audio buffers to be output */ int cur; /** the current sample in the audio buffers to be output */
int dither_index; /* current index in random dither value buffer: fluid_synth_(write_s16|dither_s16) */
char outbuf[256]; /** buffer for message output */ char outbuf[256]; /** buffer for message output */
double cpu_load; double cpu_load;
fluid_tuning_t*** tuning; /** 128 banks of 128 programs for the tunings */ fluid_tuning_t*** tuning; /** 128 banks of 128 programs for the tunings */
fluid_tuning_t* cur_tuning; /** current tuning in the iteration */ fluid_tuning_t* cur_tuning; /** current tuning in the iteration */
fluid_midi_router_t* midi_router; /* The midi router. Could be done nicer. */ fluid_midi_router_t* midi_router; /* The midi router. Could be done nicer. */
fluid_mutex_t busy; /* Indicates, whether the audio thread is currently running. fluid_mutex_t busy; /* Indicates, whether the audio thread is currently running.
* Note: This simple scheme does -not- provide 100 % protection against * Note: This simple scheme does -not- provide 100 % protection against
* thread problems, for example from MIDI thread and shell thread * thread problems, for example from MIDI thread and shell thread
*/ */
@@ -153,7 +149,6 @@ struct _fluid_synth_t
#endif #endif
}; };
/** returns 1 if the value has been set, 0 otherwise */ /** returns 1 if the value has been set, 0 otherwise */
int fluid_synth_setstr(fluid_synth_t* synth, char* name, char* str); int fluid_synth_setstr(fluid_synth_t* synth, char* name, char* str);
@@ -177,13 +172,13 @@ int fluid_synth_set_reverb_preset(fluid_synth_t* synth, int num);
int fluid_synth_one_block(fluid_synth_t* synth, int do_not_mix_fx_to_out); int fluid_synth_one_block(fluid_synth_t* synth, int do_not_mix_fx_to_out);
fluid_preset_t* fluid_synth_get_preset(fluid_synth_t* synth, fluid_preset_t* fluid_synth_get_preset(fluid_synth_t* synth,
unsigned int sfontnum, unsigned int sfontnum,
unsigned int banknum, unsigned int banknum,
unsigned int prognum); unsigned int prognum);
fluid_preset_t* fluid_synth_find_preset(fluid_synth_t* synth, fluid_preset_t* fluid_synth_find_preset(fluid_synth_t* synth,
unsigned int banknum, unsigned int banknum,
unsigned int prognum); unsigned int prognum);
int fluid_synth_all_notes_off(fluid_synth_t* synth, int chan); int fluid_synth_all_notes_off(fluid_synth_t* synth, int chan);
@@ -210,8 +205,9 @@ int fluid_synth_update_polyphony(fluid_synth_t* synth, char* name, int value);
fluid_bank_offset_t* fluid_synth_get_bank_offset0(fluid_synth_t* synth, int sfont_id); fluid_bank_offset_t* fluid_synth_get_bank_offset0(fluid_synth_t* synth, int sfont_id);
void fluid_synth_remove_bank_offset(fluid_synth_t* synth, int sfont_id); void fluid_synth_remove_bank_offset(fluid_synth_t* synth, int sfont_id);
void fluid_synth_dither_s16(int *dither_index, int len, float* lin, float* rin,
void* lout, int loff, int lincr,
void* rout, int roff, int rincr);
/* /*
* misc * misc
*/ */
+201 -112
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -20,7 +20,6 @@
#include "fluid_sys.h" #include "fluid_sys.h"
//#include <fpu_control.h>
static char fluid_errbuf[512]; /* buffer for error message */ static char fluid_errbuf[512]; /* buffer for error message */
@@ -34,7 +33,7 @@ static char* fluid_libname = "fluidsynth";
void fluid_sys_config() void fluid_sys_config()
{ {
fluid_log_config(); fluid_log_config();
fluid_time_config(); fluid_time_config();
} }
@@ -48,25 +47,29 @@ int fluid_debug(int level, char * fmt, ...)
{ {
if (fluid_debug_flags & level) { if (fluid_debug_flags & level) {
fluid_log_function_t fun; fluid_log_function_t fun;
va_list args; va_list args;
va_start (args, fmt); va_start (args, fmt);
vsnprintf(fluid_errbuf, sizeof (fluid_errbuf), fmt, args); vsnprintf(fluid_errbuf, sizeof (fluid_errbuf), fmt, args);
va_end (args); va_end (args);
fun = fluid_log_function[FLUID_DBG]; fun = fluid_log_function[FLUID_DBG];
if (fun != NULL) { if (fun != NULL) {
(*fun)(level, fluid_errbuf, fluid_log_user_data[FLUID_DBG]); (*fun)(level, fluid_errbuf, fluid_log_user_data[FLUID_DBG]);
} }
} }
return 0; return 0;
} }
#endif #endif
/* /**
* fluid_set_log_function * Installs a new log function for a specified log level.
* @param level Log level to install handler for.
* @param fun Callback function handler to call for logged messages
* @param data User supplied data pointer to pass to log function
* @return The previously installed function.
*/ */
fluid_log_function_t fluid_log_function_t
fluid_set_log_function(int level, fluid_log_function_t fun, void* data) fluid_set_log_function(int level, fluid_log_function_t fun, void* data)
{ {
fluid_log_function_t old = NULL; fluid_log_function_t old = NULL;
@@ -79,10 +82,13 @@ fluid_set_log_function(int level, fluid_log_function_t fun, void* data)
return old; return old;
} }
/* /**
* fluid_default_log_function * Default log function which prints to the stderr.
* @param level Log level
* @param message Log message
* @param data User supplied data (not used)
*/ */
void void
fluid_default_log_function(int level, char* message, void* data) fluid_default_log_function(int level, char* message, void* data)
{ {
FILE* out; FILE* out;
@@ -92,25 +98,25 @@ fluid_default_log_function(int level, char* message, void* data)
#else #else
out = stderr; out = stderr;
#endif #endif
if (fluid_log_initialized == 0) { if (fluid_log_initialized == 0) {
fluid_log_config(); fluid_log_config();
} }
switch (level) { switch (level) {
case FLUID_PANIC: case FLUID_PANIC:
FLUID_FPRINTF(out, "%s: panic: %s\n", fluid_libname, message); FLUID_FPRINTF(out, "%s: panic: %s\n", fluid_libname, message);
break; break;
case FLUID_ERR: case FLUID_ERR:
FLUID_FPRINTF(out, "%s: error: %s\n", fluid_libname, message); FLUID_FPRINTF(out, "%s: error: %s\n", fluid_libname, message);
break; break;
case FLUID_WARN: case FLUID_WARN:
FLUID_FPRINTF(out, "%s: warning: %s\n", fluid_libname, message); FLUID_FPRINTF(out, "%s: warning: %s\n", fluid_libname, message);
break; break;
case FLUID_INFO: case FLUID_INFO:
FLUID_FPRINTF(out, "%s: %s\n", fluid_libname, message); FLUID_FPRINTF(out, "%s: %s\n", fluid_libname, message);
break; break;
case FLUID_DBG: case FLUID_DBG:
#if DEBUG #if DEBUG
FLUID_FPRINTF(out, "%s: debug: %s\n", fluid_libname, message); FLUID_FPRINTF(out, "%s: debug: %s\n", fluid_libname, message);
#endif #endif
@@ -125,7 +131,7 @@ fluid_default_log_function(int level, char* message, void* data)
/* /*
* fluid_init_log * fluid_init_log
*/ */
void void
fluid_log_config(void) fluid_log_config(void)
{ {
if (fluid_log_initialized == 0) { if (fluid_log_initialized == 0) {
@@ -135,37 +141,41 @@ fluid_log_config(void)
if (fluid_log_function[FLUID_PANIC] == NULL) { if (fluid_log_function[FLUID_PANIC] == NULL) {
fluid_set_log_function(FLUID_PANIC, fluid_default_log_function, NULL); fluid_set_log_function(FLUID_PANIC, fluid_default_log_function, NULL);
} }
if (fluid_log_function[FLUID_ERR] == NULL) { if (fluid_log_function[FLUID_ERR] == NULL) {
fluid_set_log_function(FLUID_ERR, fluid_default_log_function, NULL); fluid_set_log_function(FLUID_ERR, fluid_default_log_function, NULL);
} }
if (fluid_log_function[FLUID_WARN] == NULL) { if (fluid_log_function[FLUID_WARN] == NULL) {
fluid_set_log_function(FLUID_WARN, fluid_default_log_function, NULL); fluid_set_log_function(FLUID_WARN, fluid_default_log_function, NULL);
} }
if (fluid_log_function[FLUID_INFO] == NULL) { if (fluid_log_function[FLUID_INFO] == NULL) {
fluid_set_log_function(FLUID_INFO, fluid_default_log_function, NULL); fluid_set_log_function(FLUID_INFO, fluid_default_log_function, NULL);
} }
if (fluid_log_function[FLUID_DBG] == NULL) { if (fluid_log_function[FLUID_DBG] == NULL) {
fluid_set_log_function(FLUID_DBG, fluid_default_log_function, NULL); fluid_set_log_function(FLUID_DBG, fluid_default_log_function, NULL);
} }
} }
} }
/* /**
* fluid_log * Print a message to the log.
* @param level Log level (#fluid_log_level).
* @param fmt Printf style format string for log message
* @param ... Arguments for printf 'fmt' message string
* @return Always returns -1
*/ */
int int
fluid_log(int level, char* fmt, ...) fluid_log(int level, char* fmt, ...)
{ {
fluid_log_function_t fun = NULL; fluid_log_function_t fun = NULL;
va_list args; va_list args;
va_start (args, fmt); va_start (args, fmt);
vsnprintf(fluid_errbuf, sizeof (fluid_errbuf), fmt, args); vsnprintf(fluid_errbuf, sizeof (fluid_errbuf), fmt, args);
va_end (args); va_end (args);
if ((level >= 0) && (level < LAST_LOG_LEVEL)) { if ((level >= 0) && (level < LAST_LOG_LEVEL)) {
fun = fluid_log_function[level]; fun = fluid_log_function[level];
@@ -173,14 +183,83 @@ fluid_log(int level, char* fmt, ...)
(*fun)(level, fluid_errbuf, fluid_log_user_data[level]); (*fun)(level, fluid_errbuf, fluid_log_user_data[level]);
} }
} }
return FLUID_FAILED; return FLUID_FAILED;
} }
/**
* An improved strtok, still trashes the input string, but is portable and
* thread safe. Also skips token chars at beginning of token string and never
* returns an empty token (will return NULL if source ends in token chars though).
* NOTE: NOT part of public API
* @internal
* @param str Pointer to a string pointer of source to tokenize. Pointer gets
* updated on each invocation to point to beginning of next token. Note that
* token char get's overwritten with a 0 byte. String pointer is set to NULL
* when final token is returned.
* @param delim String of delimiter chars.
* @return Pointer to the next token or NULL if no more tokens.
*/
char *fluid_strtok (char **str, char *delim)
{
char *s, *d, *token;
char c;
if (str == NULL || delim == NULL || !*delim)
{
FLUID_LOG(FLUID_ERR, "Null pointer");
return NULL;
}
s = *str;
if (!s) return NULL; /* str points to a NULL pointer? (tokenize already ended) */
/* skip delimiter chars at beginning of token */
do
{
c = *s;
if (!c) /* end of source string? */
{
*str = NULL;
return NULL;
}
for (d = delim; *d; d++) /* is source char a token char? */
{
if (c == *d) /* token char match? */
{
s++; /* advance to next source char */
break;
}
}
} while (*d); /* while token char match */
token = s; /* start of token found */
/* search for next token char or end of source string */
for (s = s+1; *s; s++)
{
c = *s;
for (d = delim; *d; d++) /* is source char a token char? */
{
if (c == *d) /* token char match? */
{
*s = '\0'; /* overwrite token char with zero byte to terminate token */
*str = s+1; /* update str to point to beginning of next token */
return token;
}
}
}
/* we get here only if source string ended */
*str = NULL;
return token;
}
/* /*
* fluid_error * fluid_error
*/ */
char* char*
fluid_error() fluid_error()
{ {
return fluid_errbuf; return fluid_errbuf;
@@ -188,9 +267,9 @@ fluid_error()
/* /*
* *
* fluid_is_midifile * fluid_is_midifile
*/ */
int int
fluid_is_midifile(char* filename) fluid_is_midifile(char* filename)
{ {
@@ -205,14 +284,14 @@ fluid_is_midifile(char* filename)
return 0; return 0;
} }
fclose(fp); fclose(fp);
return strncmp(id, "MThd", 4) == 0; return strncmp(id, "MThd", 4) == 0;
} }
/* /*
* fluid_is_soundfont * fluid_is_soundfont
* *
*/ */
int int
fluid_is_soundfont(char* filename) fluid_is_soundfont(char* filename)
{ {
@@ -227,7 +306,7 @@ fluid_is_soundfont(char* filename)
return 0; return 0;
} }
fclose(fp); fclose(fp);
return strncmp(id, "RIFF", 4) == 0; return strncmp(id, "RIFF", 4) == 0;
} }
@@ -245,7 +324,7 @@ fluid_is_soundfont(char* filename)
* *
*/ */
struct _fluid_timer_t struct _fluid_timer_t
{ {
long msec; long msec;
fluid_timer_callback_t callback; fluid_timer_callback_t callback;
@@ -259,13 +338,13 @@ struct _fluid_timer_t
static int fluid_timer_count = 0; static int fluid_timer_count = 0;
DWORD WINAPI fluid_timer_run(LPVOID data); DWORD WINAPI fluid_timer_run(LPVOID data);
fluid_timer_t* fluid_timer_t*
new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data, new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data,
int new_thread, int auto_destroy) int new_thread, int auto_destroy)
{ {
fluid_timer_t* timer = FLUID_NEW(fluid_timer_t); fluid_timer_t* timer = FLUID_NEW(fluid_timer_t);
if (timer == NULL) { if (timer == NULL) {
FLUID_LOG(FLUID_ERR, "Out of memory"); FLUID_LOG(FLUID_ERR, "Out of memory");
return NULL; return NULL;
} }
@@ -279,18 +358,18 @@ new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data,
if (new_thread) { if (new_thread) {
timer->thread = CreateThread(NULL, 0, fluid_timer_run, (LPVOID) timer, 0, &timer->thread_id); timer->thread = CreateThread(NULL, 0, fluid_timer_run, (LPVOID) timer, 0, &timer->thread_id);
if (timer->thread == NULL) { if (timer->thread == NULL) {
FLUID_LOG(FLUID_ERR, "Couldn't create timer thread"); FLUID_LOG(FLUID_ERR, "Couldn't create timer thread");
FLUID_FREE(timer); FLUID_FREE(timer);
return NULL; return NULL;
} }
SetThreadPriority(timer->thread, THREAD_PRIORITY_TIME_CRITICAL); SetThreadPriority(timer->thread, THREAD_PRIORITY_TIME_CRITICAL);
} else { } else {
fluid_timer_run((LPVOID) timer); fluid_timer_run((LPVOID) timer);
} }
return timer; return timer;
} }
DWORD WINAPI DWORD WINAPI
fluid_timer_run(LPVOID data) fluid_timer_run(LPVOID data)
{ {
int count = 0; int count = 0;
@@ -337,16 +416,16 @@ fluid_timer_run(LPVOID data)
return 0; return 0;
} }
int int
delete_fluid_timer(fluid_timer_t* timer) delete_fluid_timer(fluid_timer_t* timer)
{ {
timer->cont = 0; timer->cont = 0;
fluid_timer_join(timer); fluid_timer_join(timer);
FLUID_FREE(timer); FLUID_FREE(timer);
return FLUID_OK; return FLUID_OK;
} }
int int
fluid_timer_join(fluid_timer_t* timer) fluid_timer_join(fluid_timer_t* timer)
{ {
DWORD wait_result; DWORD wait_result;
@@ -371,7 +450,7 @@ static double fluid_cpu_frequency = -1.0;
void fluid_time_config(void) void fluid_time_config(void)
{ {
if (fluid_cpu_frequency < 0.0) { if (fluid_cpu_frequency < 0.0) {
fluid_cpu_frequency = fluid_estimate_cpu_frequency() / 1000000.0; fluid_cpu_frequency = fluid_estimate_cpu_frequency() / 1000000.0;
} }
} }
@@ -422,7 +501,7 @@ double fluid_estimate_cpu_frequency(void)
QueryPerformanceCounter(&start); QueryPerformanceCounter(&start);
Sleep(1000); Sleep(1000);
after = fluid_curtime(); after = fluid_curtime();
QueryPerformanceCounter(&stop); QueryPerformanceCounter(&stop);
@@ -445,7 +524,7 @@ double fluid_estimate_cpu_frequency(void)
* Timer * Timer
*/ */
struct _fluid_timer_t struct _fluid_timer_t
{ {
TMTask myTmTask; TMTask myTmTask;
long msec; long msec;
@@ -472,13 +551,13 @@ _timerCallback(fluid_timer_t *timer)
timer->count++; timer->count++;
} }
fluid_timer_t* fluid_timer_t*
new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data, new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data,
int new_thread, int auto_destroy) int new_thread, int auto_destroy)
{ {
fluid_timer_t* timer = FLUID_NEW(fluid_timer_t); fluid_timer_t* timer = FLUID_NEW(fluid_timer_t);
if (timer == NULL) { if (timer == NULL) {
FLUID_LOG(FLUID_ERR, "Out of memory"); FLUID_LOG(FLUID_ERR, "Out of memory");
return NULL; return NULL;
} }
@@ -501,14 +580,14 @@ new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data,
timer->isInstalled = 1; timer->isInstalled = 1;
timer->count = 0; timer->count = 0;
timer->auto_destroy = auto_destroy; timer->auto_destroy = auto_destroy;
InsXTime((QElemPtr)timer); InsXTime((QElemPtr)timer);
PrimeTime((QElemPtr)timer, msec); PrimeTime((QElemPtr)timer, msec);
return timer; return timer;
} }
int int
delete_fluid_timer(fluid_timer_t* timer) delete_fluid_timer(fluid_timer_t* timer)
{ {
if (timer->isInstalled) { if (timer->isInstalled) {
@@ -518,7 +597,7 @@ delete_fluid_timer(fluid_timer_t* timer)
return FLUID_OK; return FLUID_OK;
} }
int int
fluid_timer_join(fluid_timer_t* timer) fluid_timer_join(fluid_timer_t* timer)
{ {
if (timer->isInstalled) { if (timer->isInstalled) {
@@ -545,16 +624,17 @@ unsigned int fluid_curtime()
UnsignedWide uS; UnsignedWide uS;
double mSf; double mSf;
unsigned int ms; unsigned int ms;
Microseconds(&uS); Microseconds(&uS);
mSf = ((((double) uS.hi) * kTwoPower32) + uS.lo)/1000.0f; mSf = ((((double) uS.hi) * kTwoPower32) + uS.lo)/1000.0f;
ms = mSf; ms = mSf;
return (ms); return (ms);
} }
#elif __BEOS__ #elif __BEOS__
struct _fluid_timer_t struct _fluid_timer_t
@@ -660,8 +740,8 @@ double fluid_utime(void)
* *
* Timer * Timer
*/ */
struct _fluid_timer_t struct _fluid_timer_t
{ {
long msec; long msec;
fluid_timer_callback_t callback; fluid_timer_callback_t callback;
@@ -671,7 +751,7 @@ struct _fluid_timer_t
int auto_destroy; int auto_destroy;
}; };
void* void*
fluid_timer_start(void *data) fluid_timer_start(void *data)
{ {
int count = 0; int count = 0;
@@ -714,8 +794,8 @@ fluid_timer_start(void *data)
return NULL; return NULL;
} }
fluid_timer_t* fluid_timer_t*
new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data, new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data,
int new_thread, int auto_destroy) int new_thread, int auto_destroy)
{ {
pthread_attr_t *attr = NULL; pthread_attr_t *attr = NULL;
@@ -726,7 +806,7 @@ new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data,
fluid_timer_t* timer = FLUID_NEW(fluid_timer_t); fluid_timer_t* timer = FLUID_NEW(fluid_timer_t);
if (timer == NULL) { if (timer == NULL) {
FLUID_LOG(FLUID_ERR, "Out of memory"); FLUID_LOG(FLUID_ERR, "Out of memory");
return NULL; return NULL;
} }
timer->msec = msec; timer->msec = msec;
@@ -736,7 +816,7 @@ new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data,
timer->thread = 0; timer->thread = 0;
timer->auto_destroy = auto_destroy; timer->auto_destroy = auto_destroy;
err = pthread_attr_init(&rt_attr); err = pthread_attr_init(&rt_attr);
if (err == 0) { if (err == 0) {
err = pthread_attr_setschedpolicy(&rt_attr, SCHED_FIFO); err = pthread_attr_setschedpolicy(&rt_attr, SCHED_FIFO);
if (err == 0) { if (err == 0) {
@@ -744,14 +824,14 @@ new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data,
err = pthread_attr_setschedparam(&rt_attr, &priority); err = pthread_attr_setschedparam(&rt_attr, &priority);
if (err == 0) { if (err == 0) {
attr = &rt_attr; attr = &rt_attr;
} }
} }
} }
if (new_thread) { if (new_thread) {
err = pthread_create(&timer->thread, attr, fluid_timer_start, (void*) timer); err = pthread_create(&timer->thread, attr, fluid_timer_start, (void*) timer);
if (err == 0) { if (err == 0) {
FLUID_LOG(FLUID_DBG, "The timer thread was created with real-time priority"); FLUID_LOG(FLUID_DBG, "The timer thread was created with real-time priority");
} else { } else {
/* Create the thread with default attributes */ /* Create the thread with default attributes */
err = pthread_create(&timer->thread, NULL, fluid_timer_start, (void*) timer); err = pthread_create(&timer->thread, NULL, fluid_timer_start, (void*) timer);
@@ -769,7 +849,7 @@ new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data,
return timer; return timer;
} }
int int
delete_fluid_timer(fluid_timer_t* timer) delete_fluid_timer(fluid_timer_t* timer)
{ {
timer->cont = 0; timer->cont = 0;
@@ -779,7 +859,7 @@ delete_fluid_timer(fluid_timer_t* timer)
return FLUID_OK; return FLUID_OK;
} }
int int
fluid_timer_join(fluid_timer_t* timer) fluid_timer_join(fluid_timer_t* timer)
{ {
int err = 0; int err = 0;
@@ -805,7 +885,8 @@ double fluid_estimate_cpu_frequency(void);
void fluid_time_config(void) void fluid_time_config(void)
{ {
if (fluid_cpu_frequency < 0.0) { if (fluid_cpu_frequency < 0.0) {
fluid_cpu_frequency = fluid_estimate_cpu_frequency() / 1000000.0; fluid_cpu_frequency = fluid_estimate_cpu_frequency() / 1000000.0;
if (fluid_cpu_frequency == 0.0) fluid_cpu_frequency = 1.0;
} }
} }
@@ -849,11 +930,11 @@ double fluid_estimate_cpu_frequency(void)
unsigned int a0, b0, a1, b1; unsigned int a0, b0, a1, b1;
unsigned int before, after; unsigned int before, after;
before = fluid_curtime(); before = fluid_curtime();
__asm__ ("rdtsc" : "=a" (a0), "=d" (b0)); __asm__ ("rdtsc" : "=a" (a0), "=d" (b0));
sleep(1); sleep(1);
after = fluid_curtime(); after = fluid_curtime();
__asm__ ("rdtsc" : "=a" (a1), "=d" (b1)); __asm__ ("rdtsc" : "=a" (a1), "=d" (b1));
@@ -866,7 +947,7 @@ double fluid_estimate_cpu_frequency(void)
#endif #endif
#if 0 #ifdef FPE_CHECK
/*************************************************************** /***************************************************************
* *
@@ -875,7 +956,7 @@ double fluid_estimate_cpu_frequency(void)
* The floating point exception functions were taken from Ircam's * The floating point exception functions were taken from Ircam's
* jMax source code. http://www.ircam.fr/jmax * jMax source code. http://www.ircam.fr/jmax
* *
* FIXME: check in config for i386 machine * FIXME: check in config for i386 machine
* *
* Currently not used. I leave the code here in case we want to pick * Currently not used. I leave the code here in case we want to pick
* this up again some time later. * this up again some time later.
@@ -900,7 +981,8 @@ double fluid_estimate_cpu_frequency(void)
#define _FPU_CLR_SW() __asm__ ("fnclex" : : ) #define _FPU_CLR_SW() __asm__ ("fnclex" : : )
/* Purpose: /* Purpose:
* Checks, if the floating point unit has produced an exception in the meantime. * Checks, if the floating point unit has produced an exception, print a message
* if so and clear the exception.
*/ */
unsigned int fluid_check_fpe_i386(char* explanation) unsigned int fluid_check_fpe_i386(char* explanation)
{ {
@@ -909,11 +991,10 @@ unsigned int fluid_check_fpe_i386(char* explanation)
_FPU_GET_SW(s); _FPU_GET_SW(s);
_FPU_CLR_SW(); _FPU_CLR_SW();
if ((s & _FPU_STATUS_IE) s &= _FPU_STATUS_IE | _FPU_STATUS_DE | _FPU_STATUS_ZE | _FPU_STATUS_OE | _FPU_STATUS_UE;
|| (s & _FPU_STATUS_DE)
|| (s & _FPU_STATUS_ZE) if (s)
|| (s & _FPU_STATUS_OE) {
|| (s & _FPU_STATUS_UE)) {
FLUID_LOG(FLUID_WARN, "FPE exception (before or in %s): %s%s%s%s%s", explanation, FLUID_LOG(FLUID_WARN, "FPE exception (before or in %s): %s%s%s%s%s", explanation,
(s & _FPU_STATUS_IE) ? "Invalid operation " : "", (s & _FPU_STATUS_IE) ? "Invalid operation " : "",
(s & _FPU_STATUS_DE) ? "Denormal number " : "", (s & _FPU_STATUS_DE) ? "Denormal number " : "",
@@ -921,14 +1002,22 @@ unsigned int fluid_check_fpe_i386(char* explanation)
(s & _FPU_STATUS_OE) ? "Overflow " : "", (s & _FPU_STATUS_OE) ? "Overflow " : "",
(s & _FPU_STATUS_UE) ? "Underflow " : ""); (s & _FPU_STATUS_UE) ? "Underflow " : "");
} }
return s; return s;
} }
#endif /* Purpose:
* Clear floating point exception.
*/
void fluid_clear_fpe_i386 (void)
{
_FPU_CLR_SW();
}
#endif // ifdef FPE_CHECK
#endif #endif // #else (its POSIX)
/*************************************************************** /***************************************************************
@@ -939,7 +1028,7 @@ unsigned int fluid_check_fpe_i386(char* explanation)
#if WITH_PROFILING #if WITH_PROFILING
fluid_profile_data_t fluid_profile_data[] = fluid_profile_data_t fluid_profile_data[] =
{ {
{ FLUID_PROF_WRITE_S16, "fluid_synth_write_s16 ", 1e10, 0.0, 0.0, 0}, { FLUID_PROF_WRITE_S16, "fluid_synth_write_s16 ", 1e10, 0.0, 0.0, 0},
{ FLUID_PROF_ONE_BLOCK, "fluid_synth_one_block ", 1e10, 0.0, 0.0, 0}, { FLUID_PROF_ONE_BLOCK, "fluid_synth_one_block ", 1e10, 0.0, 0.0, 0},
@@ -950,7 +1039,7 @@ fluid_profile_data_t fluid_profile_data[] =
{ FLUID_PROF_ONE_BLOCK_CHORUS, "fluid_synth_one_block:chorus ", 1e10, 0.0, 0.0, 0}, { FLUID_PROF_ONE_BLOCK_CHORUS, "fluid_synth_one_block:chorus ", 1e10, 0.0, 0.0, 0},
{ FLUID_PROF_VOICE_NOTE, "fluid_voice:note ", 1e10, 0.0, 0.0, 0}, { FLUID_PROF_VOICE_NOTE, "fluid_voice:note ", 1e10, 0.0, 0.0, 0},
{ FLUID_PROF_VOICE_RELEASE, "fluid_voice:release ", 1e10, 0.0, 0.0, 0}, { FLUID_PROF_VOICE_RELEASE, "fluid_voice:release ", 1e10, 0.0, 0.0, 0},
{ FLUID_PROF_LAST, "last", 1e100, 0.0, 0.0, 0} { FLUID_PROF_LAST, "last", 1e100, 0.0, 0.0, 0}
}; };
@@ -959,16 +1048,16 @@ void fluid_profiling_print(void)
int i; int i;
printf("fluid_profiling_print\n"); printf("fluid_profiling_print\n");
FLUID_LOG(FLUID_INFO, "Estimated CPU frequency: %.0f MHz", fluid_cpu_frequency); FLUID_LOG(FLUID_INFO, "Estimated CPU frequency: %.0f MHz", fluid_cpu_frequency);
FLUID_LOG(FLUID_INFO, "Estimated times: min/avg/max (micro seconds)"); FLUID_LOG(FLUID_INFO, "Estimated times: min/avg/max (micro seconds)");
for (i = 0; i < FLUID_PROF_LAST; i++) { for (i = 0; i < FLUID_PROF_LAST; i++) {
if (fluid_profile_data[i].count > 0) { if (fluid_profile_data[i].count > 0) {
FLUID_LOG(FLUID_INFO, "%s: %.3f/%.3f/%.3f", FLUID_LOG(FLUID_INFO, "%s: %.3f/%.3f/%.3f",
fluid_profile_data[i].description, fluid_profile_data[i].description,
fluid_profile_data[i].min, fluid_profile_data[i].min,
fluid_profile_data[i].total / fluid_profile_data[i].count, fluid_profile_data[i].total / fluid_profile_data[i].count,
fluid_profile_data[i].max); fluid_profile_data[i].max);
} else { } else {
FLUID_LOG(FLUID_DBG, "%s: no profiling available", fluid_profile_data[i].description); FLUID_LOG(FLUID_DBG, "%s: no profiling available", fluid_profile_data[i].description);
@@ -1010,7 +1099,7 @@ static DWORD WINAPI fluid_thread_start(LPVOID data)
thread->func(thread->data); thread->func(thread->data);
if (thread->detached) { if (thread->detached) {
FLUID_FREE(thread); FLUID_FREE(thread);
} }
return 0; return 0;
@@ -1022,13 +1111,13 @@ fluid_thread_t* new_fluid_thread(fluid_thread_func_t func, void* data, int detac
fluid_thread_t* thread; fluid_thread_t* thread;
if (func == NULL) { if (func == NULL) {
FLUID_LOG(FLUID_ERR, "Invalid thread function"); FLUID_LOG(FLUID_ERR, "Invalid thread function");
return NULL; return NULL;
} }
thread = FLUID_NEW(fluid_thread_t); thread = FLUID_NEW(fluid_thread_t);
if (thread == NULL) { if (thread == NULL) {
FLUID_LOG(FLUID_ERR, "Out of memory"); FLUID_LOG(FLUID_ERR, "Out of memory");
return NULL; return NULL;
} }
@@ -1036,21 +1125,21 @@ fluid_thread_t* new_fluid_thread(fluid_thread_func_t func, void* data, int detac
thread->func = func; thread->func = func;
thread->detached = detach; thread->detached = detach;
thread->thread = CreateThread(NULL, 0, fluid_thread_start, (LPVOID) thread, thread->thread = CreateThread(NULL, 0, fluid_thread_start, (LPVOID) thread,
0, &thread->thread_id); 0, &thread->thread_id);
if (thread->thread == NULL) { if (thread->thread == NULL) {
FLUID_LOG(FLUID_ERR, "Couldn't create the thread"); FLUID_LOG(FLUID_ERR, "Couldn't create the thread");
FLUID_FREE(thread); FLUID_FREE(thread);
return NULL; return NULL;
} }
return thread; return thread;
} }
int delete_fluid_thread(fluid_thread_t* thread) int delete_fluid_thread(fluid_thread_t* thread)
{ {
FLUID_FREE(thread); FLUID_FREE(thread);
return FLUID_OK; return FLUID_OK;
} }
@@ -1087,7 +1176,7 @@ static void* fluid_thread_start(void *data)
thread->func(thread->data); thread->func(thread->data);
if (thread->detached) { if (thread->detached) {
FLUID_FREE(thread); FLUID_FREE(thread);
} }
return NULL; return NULL;
@@ -1099,13 +1188,13 @@ fluid_thread_t* new_fluid_thread(fluid_thread_func_t func, void* data, int detac
pthread_attr_t attr; pthread_attr_t attr;
if (func == NULL) { if (func == NULL) {
FLUID_LOG(FLUID_ERR, "Invalid thread function"); FLUID_LOG(FLUID_ERR, "Invalid thread function");
return NULL; return NULL;
} }
thread = FLUID_NEW(fluid_thread_t); thread = FLUID_NEW(fluid_thread_t);
if (thread == NULL) { if (thread == NULL) {
FLUID_LOG(FLUID_ERR, "Out of memory"); FLUID_LOG(FLUID_ERR, "Out of memory");
return NULL; return NULL;
} }
@@ -1124,14 +1213,14 @@ fluid_thread_t* new_fluid_thread(fluid_thread_func_t func, void* data, int detac
FLUID_FREE(thread); FLUID_FREE(thread);
return NULL; return NULL;
} }
return thread; return thread;
} }
int delete_fluid_thread(fluid_thread_t* thread) int delete_fluid_thread(fluid_thread_t* thread)
{ {
FLUID_FREE(thread); FLUID_FREE(thread);
return FLUID_OK; return FLUID_OK;
} }
int fluid_thread_join(fluid_thread_t* thread) int fluid_thread_join(fluid_thread_t* thread)
@@ -1235,7 +1324,7 @@ static void fluid_server_socket_run(void* data)
while (server_socket->cont) { while (server_socket->cont) {
client_socket = accept(server_socket->socket, (struct sockaddr*) &addr, &addrlen); client_socket = accept(server_socket->socket, (struct sockaddr*) &addr, &addrlen);
FLUID_LOG(FLUID_DBG, "New client connection"); FLUID_LOG(FLUID_DBG, "New client connection");
if (client_socket == INVALID_SOCKET) { if (client_socket == INVALID_SOCKET) {
@@ -1250,13 +1339,13 @@ static void fluid_server_socket_run(void* data)
if (r != 0) { if (r != 0) {
fluid_socket_close(client_socket); fluid_socket_close(client_socket);
} }
} }
} }
FLUID_LOG(FLUID_DBG, "Server closing"); FLUID_LOG(FLUID_DBG, "Server closing");
} }
fluid_server_socket_t* fluid_server_socket_t*
new_fluid_server_socket(int port, fluid_server_func_t func, void* data) new_fluid_server_socket(int port, fluid_server_func_t func, void* data)
{ {
fluid_server_socket_t* server_socket; fluid_server_socket_t* server_socket;
@@ -1293,7 +1382,7 @@ new_fluid_server_socket(int port, fluid_server_func_t func, void* data)
server_socket = FLUID_NEW(fluid_server_socket_t); server_socket = FLUID_NEW(fluid_server_socket_t);
if (server_socket == NULL) { if (server_socket == NULL) {
FLUID_LOG(FLUID_ERR, "Out of memory"); FLUID_LOG(FLUID_ERR, "Out of memory");
fluid_socket_close(sock); fluid_socket_close(sock);
return NULL; return NULL;
} }
+31 -23
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -43,8 +43,15 @@ void fluid_sys_config(void);
void fluid_log_config(void); void fluid_log_config(void);
void fluid_time_config(void); void fluid_time_config(void);
/*
* Utility functions
*/
char *fluid_strtok (char **str, char *delim);
/** /**
Additional debugging system, separate from the log system. This Additional debugging system, separate from the log system. This
allows to print selected debug messages of a specific subsystem. allows to print selected debug messages of a specific subsystem.
@@ -61,7 +68,7 @@ enum fluid_debug_level {
int fluid_debug(int level, char * fmt, ...); int fluid_debug(int level, char * fmt, ...);
#else #else
#define fluid_debug #define fluid_debug
#endif #endif
@@ -98,7 +105,7 @@ double fluid_utime(void);
/** /**
Timers Timers
*/ */
@@ -109,25 +116,25 @@ typedef int (*fluid_timer_callback_t)(void* data, unsigned int msec);
typedef struct _fluid_timer_t fluid_timer_t; typedef struct _fluid_timer_t fluid_timer_t;
fluid_timer_t* new_fluid_timer(int msec, fluid_timer_callback_t callback, fluid_timer_t* new_fluid_timer(int msec, fluid_timer_callback_t callback,
void* data, int new_thread, int auto_destroy); void* data, int new_thread, int auto_destroy);
int delete_fluid_timer(fluid_timer_t* timer); int delete_fluid_timer(fluid_timer_t* timer);
int fluid_timer_join(fluid_timer_t* timer); int fluid_timer_join(fluid_timer_t* timer);
int fluid_timer_stop(fluid_timer_t* timer); int fluid_timer_stop(fluid_timer_t* timer);
/** /**
Muteces Muteces
*/ */
#if defined(MACOS9) #if defined(MACOS9)
typedef int fluid_mutex_t; typedef int fluid_mutex_t;
#define fluid_mutex_init(_m) { (_m) = 0; } #define fluid_mutex_init(_m) { (_m) = 0; }
#define fluid_mutex_destroy(_m) #define fluid_mutex_destroy(_m)
#define fluid_mutex_lock(_m) #define fluid_mutex_lock(_m)
#define fluid_mutex_unlock(_m) #define fluid_mutex_unlock(_m)
#elif defined(WIN32) #elif defined(WIN32)
typedef HANDLE fluid_mutex_t; typedef HANDLE fluid_mutex_t;
@@ -140,7 +147,7 @@ typedef HANDLE fluid_mutex_t;
#ifndef HAIKU_TARGET_PLATFORM_HAIKU #ifndef HAIKU_TARGET_PLATFORM_HAIKU
typedef sem_id fluid_mutex_t; typedef sem_id fluid_mutex_t;
#define fluid_mutex_init(_m) { (_m) = create_sem(1, "fs_sem"); } #define fluid_mutex_init(_m) { (_m) = create_sem(1, "fs_sem"); }
#define fluid_mutex_destroy(_m) delete_sem(_m); #define fluid_mutex_destroy(_m) delete_sem(_m);
#define fluid_mutex_lock(_m) acquire_sem(_m); #define fluid_mutex_lock(_m) acquire_sem(_m);
#define fluid_mutex_unlock(_m) release_sem(_m); #define fluid_mutex_unlock(_m) release_sem(_m);
@@ -153,6 +160,7 @@ typedef pthread_mutex_t fluid_mutex_t;
#endif #endif
#endif #endif
/** /**
Threads Threads
@@ -199,13 +207,13 @@ fluid_ostream_t fluid_socket_get_ostream(fluid_socket_t sock);
/** /**
Profiling Profiling
*/ */
/** /**
Profile numbers. List all the pieces of code you want to profile Profile numbers. List all the pieces of code you want to profile
here. Be sure to add an entry in the fluid_profile_data table in here. Be sure to add an entry in the fluid_profile_data table in
fluid_sys.c fluid_sys.c
@@ -267,9 +275,9 @@ extern fluid_profile_data_t fluid_profile_data[];
/** /**
Memory locking Memory locking
Memory locking is used to avoid swapping of the large block of Memory locking is used to avoid swapping of the large block of
sample data. sample data.
@@ -280,26 +288,26 @@ extern fluid_profile_data_t fluid_profile_data[];
#define fluid_munlock(_p,_n) munlock(_p,_n) #define fluid_munlock(_p,_n) munlock(_p,_n)
#else #else
#define fluid_mlock(_p,_n) 0 #define fluid_mlock(_p,_n) 0
#define fluid_munlock(_p,_n) #define fluid_munlock(_p,_n)
#endif #endif
/** /**
Floating point exceptions Floating point exceptions
fluid_check_fpe() checks for "unnormalized numbers" and other fluid_check_fpe() checks for "unnormalized numbers" and other
exceptions of the floating point processsor. exceptions of the floating point processsor.
*/ */
#if 0 #ifdef FPE_CHECK
/* Enable FPE exception check */
#define fluid_check_fpe(expl) fluid_check_fpe_i386(expl) #define fluid_check_fpe(expl) fluid_check_fpe_i386(expl)
#define fluid_clear_fpe() fluid_clear_fpe_i386()
#else #else
/* Disable FPE exception check */
#define fluid_check_fpe(expl) #define fluid_check_fpe(expl)
#define fluid_clear_fpe()
#endif #endif
unsigned int fluid_check_fpe_i386(char * explanation_in_case_of_fpe); unsigned int fluid_check_fpe_i386(char * explanation_in_case_of_fpe);
void fluid_clear_fpe_i386(void);
#endif /* _FLUID_SYS_H */ #endif /* _FLUID_SYS_H */
+3 -3
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -38,7 +38,7 @@ fluid_tuning_t* new_fluid_tuning(char* name, int bank, int prog)
if (name != NULL) { if (name != NULL) {
tuning->name = FLUID_STRDUP(name); tuning->name = FLUID_STRDUP(name);
} }
tuning->bank = bank; tuning->bank = bank;
tuning->prog = prog; tuning->prog = prog;
@@ -69,7 +69,7 @@ void fluid_tuning_set_name(fluid_tuning_t* tuning, char* name)
} }
if (name != NULL) { if (name != NULL) {
tuning->name = FLUID_STRDUP(name); tuning->name = FLUID_STRDUP(name);
} }
} }
char* fluid_tuning_get_name(fluid_tuning_t* tuning) char* fluid_tuning_get_name(fluid_tuning_t* tuning)
+1 -1
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
File diff suppressed because it is too large Load Diff
+37 -34
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -43,9 +43,9 @@ enum fluid_voice_status
struct _fluid_env_data_t { struct _fluid_env_data_t {
unsigned int count; unsigned int count;
fluid_real_t coeff; fluid_real_t coeff;
fluid_real_t incr; fluid_real_t incr;
fluid_real_t min; fluid_real_t min;
fluid_real_t max; fluid_real_t max;
}; };
/* Indices for envelope tables */ /* Indices for envelope tables */
@@ -60,20 +60,12 @@ enum fluid_voice_envelope_index_t{
FLUID_VOICE_ENVLAST FLUID_VOICE_ENVLAST
}; };
/*
* interpolation data
*/
typedef struct {
fluid_real_t a0, a1, a2, a3;
/* signed int c0, c1, c2, c3; */
} fluid_interp_coeff_t;
/* /*
* fluid_voice_t * fluid_voice_t
*/ */
struct _fluid_voice_t struct _fluid_voice_t
{ {
unsigned int id; /* the id is incremented for every new noteon. unsigned int id; /* the id is incremented for every new noteon.
it's used for noteoff's */ it's used for noteoff's */
unsigned char status; unsigned char status;
unsigned char chan; /* the channel number, quick access for channel messages */ unsigned char chan; /* the channel number, quick access for channel messages */
@@ -85,7 +77,7 @@ struct _fluid_voice_t
int mod_count; int mod_count;
int has_looped; /* Flag that is set as soon as the first loop is completed. */ int has_looped; /* Flag that is set as soon as the first loop is completed. */
fluid_sample_t* sample; fluid_sample_t* sample;
int check_sample_sanity_flag; /* Flag that initiates, that sample-related parameters int check_sample_sanity_flag; /* Flag that initiates, that sample-related parameters
have to be checked. */ have to be checked. */
#if 0 #if 0
/* Instead of keeping a pointer to a fluid_sample_t structure, /* Instead of keeping a pointer to a fluid_sample_t structure,
@@ -116,12 +108,16 @@ struct _fluid_voice_t
unsigned int start_time; unsigned int start_time;
unsigned int ticks; unsigned int ticks;
fluid_real_t amp; /* the linear amplitude */ fluid_real_t amp; /* current linear amplitude */
fluid_phase_t phase; /* the phase of the sample wave */ fluid_phase_t phase; /* the phase of the sample wave */
#if 0 /* Temporary variables used in fluid_voice_write() */
fluid_real_t incr; /* the phase increment for the next 64 samples [NEW, PH] */
#endif fluid_real_t phase_incr; /* the phase increment for the next 64 samples */
fluid_real_t amp_incr; /* amplitude increment value */
fluid_real_t *dsp_buf; /* buffer to store interpolated sample data to */
/* End temporary variables */
/* basic parameters */ /* basic parameters */
fluid_real_t pitch; /* the pitch in midicents */ fluid_real_t pitch; /* the pitch in midicents */
@@ -134,7 +130,7 @@ struct _fluid_voice_t
int start; int start;
int end; int end;
int loopstart; int loopstart;
int loopend; int loopend; /* Note: first point following the loop (superimposed on loopstart) */
/* master gain */ /* master gain */
fluid_real_t synth_gain; fluid_real_t synth_gain;
@@ -152,22 +148,22 @@ struct _fluid_voice_t
unsigned int modenv_count; unsigned int modenv_count;
int modenv_section; int modenv_section;
fluid_real_t modenv_val; /* the value of the modulation envelope */ fluid_real_t modenv_val; /* the value of the modulation envelope */
fluid_real_t modenv_to_fc; fluid_real_t modenv_to_fc;
fluid_real_t modenv_to_pitch; fluid_real_t modenv_to_pitch;
/* mod lfo */ /* mod lfo */
fluid_real_t modlfo_val; /* the value of the modulation LFO */ fluid_real_t modlfo_val; /* the value of the modulation LFO */
unsigned int modlfo_delay; /* the delay of the lfo in samples */ unsigned int modlfo_delay; /* the delay of the lfo in samples */
fluid_real_t modlfo_incr; /* the lfo frequency is converted to a per-buffer increment */ fluid_real_t modlfo_incr; /* the lfo frequency is converted to a per-buffer increment */
fluid_real_t modlfo_to_fc; fluid_real_t modlfo_to_fc;
fluid_real_t modlfo_to_pitch; fluid_real_t modlfo_to_pitch;
fluid_real_t modlfo_to_vol; fluid_real_t modlfo_to_vol;
/* vib lfo */ /* vib lfo */
fluid_real_t viblfo_val; /* the value of the vibrato LFO */ fluid_real_t viblfo_val; /* the value of the vibrato LFO */
unsigned int viblfo_delay; /* the delay of the lfo in samples */ unsigned int viblfo_delay; /* the delay of the lfo in samples */
fluid_real_t viblfo_incr; /* the lfo frequency is converted to a per-buffer increment */ fluid_real_t viblfo_incr; /* the lfo frequency is converted to a per-buffer increment */
fluid_real_t viblfo_to_pitch; fluid_real_t viblfo_to_pitch;
/* resonant filter */ /* resonant filter */
fluid_real_t fres; /* the resonance frequency, in cents (not absolute cents) */ fluid_real_t fres; /* the resonance frequency, in cents (not absolute cents) */
@@ -177,7 +173,7 @@ struct _fluid_voice_t
fluid_real_t q_lin; /* the q-factor on a linear scale */ fluid_real_t q_lin; /* the q-factor on a linear scale */
fluid_real_t filter_gain; /* Gain correction factor, depends on q */ fluid_real_t filter_gain; /* Gain correction factor, depends on q */
fluid_real_t hist1, hist2; /* Sample history for the IIR filter */ fluid_real_t hist1, hist2; /* Sample history for the IIR filter */
int filter_startup; /* Flag: If set, the filter will be set directly. int filter_startup; /* Flag: If set, the filter will be set directly.
Else it changes smoothly. */ Else it changes smoothly. */
/* filter coefficients */ /* filter coefficients */
@@ -219,14 +215,14 @@ struct _fluid_voice_t
fluid_voice_t* new_fluid_voice(fluid_real_t output_rate); fluid_voice_t* new_fluid_voice(fluid_real_t output_rate);
int delete_fluid_voice(fluid_voice_t* voice); int delete_fluid_voice(fluid_voice_t* voice);
void fluid_voice_start(fluid_voice_t* voice); void fluid_voice_start(fluid_voice_t* voice);
int fluid_voice_write(fluid_voice_t* voice, int fluid_voice_write(fluid_voice_t* voice,
fluid_real_t* left, fluid_real_t* right, fluid_real_t* left, fluid_real_t* right,
fluid_real_t* reverb_buf, fluid_real_t* chorus_buf); fluid_real_t* reverb_buf, fluid_real_t* chorus_buf);
int fluid_voice_init(fluid_voice_t* voice, fluid_sample_t* sample, int fluid_voice_init(fluid_voice_t* voice, fluid_sample_t* sample,
fluid_channel_t* channel, int key, int vel, fluid_channel_t* channel, int key, int vel,
unsigned int id, unsigned int time, fluid_real_t gain); unsigned int id, unsigned int time, fluid_real_t gain);
int fluid_voice_modulate(fluid_voice_t* voice, int cc, int ctrl); int fluid_voice_modulate(fluid_voice_t* voice, int cc, int ctrl);
@@ -250,7 +246,7 @@ int fluid_voice_noteoff(fluid_voice_t* voice);
int fluid_voice_off(fluid_voice_t* voice); int fluid_voice_off(fluid_voice_t* voice);
int fluid_voice_calculate_runtime_synthesis_parameters(fluid_voice_t* voice); int fluid_voice_calculate_runtime_synthesis_parameters(fluid_voice_t* voice);
fluid_channel_t* fluid_voice_get_channel(fluid_voice_t* voice); fluid_channel_t* fluid_voice_get_channel(fluid_voice_t* voice);
int calculate_hold_decay_buffers(fluid_voice_t* voice, int gen_base, int calculate_hold_decay_buffers(fluid_voice_t* voice, int gen_base,
int gen_key2base, int is_decay); int gen_key2base, int is_decay);
int fluid_voice_kill_excl(fluid_voice_t* voice); int fluid_voice_kill_excl(fluid_voice_t* voice);
fluid_real_t fluid_voice_get_lower_boundary_for_attenuation(fluid_voice_t* voice); fluid_real_t fluid_voice_get_lower_boundary_for_attenuation(fluid_voice_t* voice);
@@ -282,7 +278,14 @@ fluid_real_t fluid_voice_gen_value(fluid_voice_t* voice, int num);
#define FLUID_SAMPLESANITY_CHECK (1 << 0) #define FLUID_SAMPLESANITY_CHECK (1 << 0)
#define FLUID_SAMPLESANITY_STARTUP (1 << 1) #define FLUID_SAMPLESANITY_STARTUP (1 << 1)
void fluid_voice_config(void);
/* defined in fluid_dsp_float.c */
void fluid_dsp_float_config (void);
int fluid_dsp_float_interpolate_none (fluid_voice_t *voice);
int fluid_dsp_float_interpolate_linear (fluid_voice_t *voice);
int fluid_dsp_float_interpolate_4th_order (fluid_voice_t *voice);
int fluid_dsp_float_interpolate_7th_order (fluid_voice_t *voice);
#endif /* _FLUID_VOICE_H */ #endif /* _FLUID_VOICE_H */
+31 -30
View File
@@ -11,14 +11,16 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307, USA * 02111-1307, USA
*/ */
#if HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
@@ -37,10 +39,6 @@
#include "fluidsynth.h" #include "fluidsynth.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#if defined(WIN32) && !defined(MINGW32) #if defined(WIN32) && !defined(MINGW32)
#include "config_win32.h" #include "config_win32.h"
#endif #endif
@@ -88,7 +86,7 @@ extern int optind, opterr, optopt;
/* process_o_cmd_line_option /* process_o_cmd_line_option
* *
* Purpose: * Purpose:
* Process a command line option -o setting=value, * Process a command line option -o setting=value,
* for example: -o synth.polyhony=16 * for example: -o synth.polyhony=16
*/ */
void process_o_cmd_line_option(fluid_settings_t* settings, char* optarg){ void process_o_cmd_line_option(fluid_settings_t* settings, char* optarg){
@@ -127,7 +125,7 @@ void process_o_cmd_line_option(fluid_settings_t* settings, char* optarg){
default: default:
fprintf (stderr, "Settings argument on command line: Failed to set \"%s\" to \"%s\".\n" fprintf (stderr, "Settings argument on command line: Failed to set \"%s\" to \"%s\".\n"
"Most likely the parameter \"%s\" does not exist.\n", optarg, val, optarg); "Most likely the parameter \"%s\" does not exist.\n", optarg, val, optarg);
} }
} }
static void static void
@@ -180,7 +178,7 @@ settings_foreach_func (void *data, char *name, int type)
#ifdef HAVE_SIGNAL_H #ifdef HAVE_SIGNAL_H
/* /*
* handle_signal * handle_signal
*/ */
void handle_signal(int sig_num) void handle_signal(int sig_num)
@@ -192,7 +190,7 @@ void handle_signal(int sig_num)
/* /*
* main * main
*/ */
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
fluid_settings_t* settings; fluid_settings_t* settings;
int arg1 = 1; int arg1 = 1;
@@ -200,7 +198,7 @@ int main(int argc, char** argv)
int c, i, fragcount = DEFAULT_FRAG_COUNT; int c, i, fragcount = DEFAULT_FRAG_COUNT;
int interactive = 1; int interactive = 1;
int midi_in = 1; int midi_in = 1;
fluid_player_t* player = NULL; fluid_player_t* player = NULL;
fluid_midi_router_t* router = NULL; fluid_midi_router_t* router = NULL;
fluid_midi_driver_t* mdriver = NULL; fluid_midi_driver_t* mdriver = NULL;
fluid_audio_driver_t* adriver = NULL; fluid_audio_driver_t* adriver = NULL;
@@ -354,7 +352,7 @@ int main(int argc, char** argv)
case 'n': case 'n':
midi_in = 0; midi_in = 0;
break; break;
case 'o': case 'o':
process_o_cmd_line_option(settings, optarg); process_o_cmd_line_option(settings, optarg);
break; break;
case 'R': case 'R':
@@ -433,16 +431,16 @@ int main(int argc, char** argv)
*/ */
if ((audio_groups == 0) && (audio_channels != 0)) { if ((audio_groups == 0) && (audio_channels != 0)) {
audio_groups = audio_channels; audio_groups = audio_channels;
} }
fluid_settings_setint(settings, "synth.audio-groups", audio_groups); fluid_settings_setint(settings, "synth.audio-groups", audio_groups);
/* create the synthesizer */ /* create the synthesizer */
synth = new_fluid_synth(settings); synth = new_fluid_synth(settings);
if (synth == NULL) { if (synth == NULL) {
fprintf(stderr, "Failed to create the synthesizer\n"); fprintf(stderr, "Failed to create the synthesizer\n");
exit(-1); exit(-1);
} }
cmd_handler = new_fluid_cmd_handler(synth); cmd_handler = new_fluid_cmd_handler(synth);
if (cmd_handler == NULL) { if (cmd_handler == NULL) {
fprintf(stderr, "Failed to create the command handler\n"); fprintf(stderr, "Failed to create the command handler\n");
@@ -458,13 +456,16 @@ int main(int argc, char** argv)
fluid_source(cmd_handler, buf); fluid_source(cmd_handler, buf);
} }
/* load the soundfonts */ /* load the soundfonts (check that all non options are SoundFont or MIDI files) */
for (i = arg1; i < argc; i++) { for (i = arg1; i < argc; i++) {
if ((argv[i][0] != '-') && fluid_is_soundfont(argv[i])) { if (fluid_is_soundfont(argv[i]))
if (fluid_synth_sfload(synth, argv[i], 1) == -1) { {
if (fluid_synth_sfload(synth, argv[i], 1) == -1)
fprintf(stderr, "Failed to load the SoundFont %s\n", argv[i]); fprintf(stderr, "Failed to load the SoundFont %s\n", argv[i]);
}
} }
else if (!fluid_is_midifile(argv[i]))
fprintf (stderr, "Parameter '%s' not a SoundFont or MIDI file or error occurred identifying it.\n",
argv[i]);
} }
#ifdef HAVE_SIGNAL_H #ifdef HAVE_SIGNAL_H
@@ -487,10 +488,10 @@ int main(int argc, char** argv)
*/ */
router = new_fluid_midi_router( router = new_fluid_midi_router(
settings, settings,
dump ? fluid_midi_dump_postrouter : fluid_synth_handle_midi_event, dump ? fluid_midi_dump_postrouter : fluid_synth_handle_midi_event,
(void*)synth); (void*)synth);
if (router == NULL) { if (router == NULL) {
fprintf(stderr, "Failed to create the MIDI input router; no MIDI input\n" fprintf(stderr, "Failed to create the MIDI input router; no MIDI input\n"
"will be available. You can access the synthesizer \n" "will be available. You can access the synthesizer \n"
@@ -498,7 +499,7 @@ int main(int argc, char** argv)
} else { } else {
fluid_synth_set_midi_router(synth, router); /* Fixme, needed for command handler */ fluid_synth_set_midi_router(synth, router); /* Fixme, needed for command handler */
mdriver = new_fluid_midi_driver( mdriver = new_fluid_midi_driver(
settings, settings,
dump ? fluid_midi_dump_prerouter : fluid_midi_router_handle_midi_event, dump ? fluid_midi_dump_prerouter : fluid_midi_router_handle_midi_event,
(void*) router); (void*) router);
if (mdriver == NULL) { if (mdriver == NULL) {
@@ -561,7 +562,7 @@ int main(int argc, char** argv)
* 0. * 0.
*/ */
fluid_settings_setstr(settings, "shell.prompt", dump ? "" : "> "); fluid_settings_setstr(settings, "shell.prompt", dump ? "" : "> ");
fluid_usershell(settings, cmd_handler); fluid_usershell(settings, cmd_handler);
} }
cleanup: cleanup:
@@ -584,7 +585,7 @@ int main(int argc, char** argv)
/* if the user typed 'quit' in the shell, stop the player */ /* if the user typed 'quit' in the shell, stop the player */
if (interactive) { if (interactive) {
fluid_player_stop(player); fluid_player_stop(player);
} }
fluid_player_join(player); fluid_player_join(player);
delete_fluid_player(player); delete_fluid_player(player);
} }
@@ -623,8 +624,8 @@ static fluid_cmd_handler_t* newclient(void* data, char* addr)
/* /*
* print_usage * print_usage
*/ */
void void
print_usage() print_usage()
{ {
print_welcome (); print_welcome ();
fprintf(stderr, "Usage: fluidsynth [options] [soundfonts]\n"); fprintf(stderr, "Usage: fluidsynth [options] [soundfonts]\n");
@@ -635,8 +636,8 @@ print_usage()
/* /*
* print_welcome * print_welcome
*/ */
void void
print_welcome() print_welcome()
{ {
printf("FluidSynth version %s\n" printf("FluidSynth version %s\n"
"Copyright (C) 2000-2006 Peter Hanappe and others.\n" "Copyright (C) 2000-2006 Peter Hanappe and others.\n"
@@ -648,8 +649,8 @@ print_welcome()
/* /*
* print_help * print_help
*/ */
void void
print_help() print_help()
{ {
print_welcome (); print_welcome ();
printf("Usage: \n"); printf("Usage: \n");
+9 -24
View File
@@ -11,7 +11,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details. * Library General Public License for more details.
* *
* You should have received a copy of the GNU Library General Public * You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
@@ -26,9 +26,9 @@
#include "config.h" #include "config.h"
#endif #endif
//#if defined(__POWERPC__) && !(defined(__APPLE__) && defined(__MACH__)) #if defined(__POWERPC__) && !(defined(__APPLE__) && defined(__MACH__))
//#include "config_maxmsp43.h" #include "config_maxmsp43.h"
//#endif #endif
#if defined(WIN32) && !defined(MINGW32) #if defined(WIN32) && !defined(MINGW32)
#include "config_win32.h" #include "config_win32.h"
@@ -229,7 +229,7 @@ typedef u_int64_t uint64;
/*************************************************************** /***************************************************************
* *
* FORWARD DECLARATIONS * FORWARD DECLARATIONS
*/ */
typedef struct _fluid_env_data_t fluid_env_data_t; typedef struct _fluid_env_data_t fluid_env_data_t;
typedef struct _fluid_adriver_definition_t fluid_adriver_definition_t; typedef struct _fluid_adriver_definition_t fluid_adriver_definition_t;
@@ -241,7 +241,7 @@ typedef struct _fluid_server_socket_t fluid_server_socket_t;
/*************************************************************** /***************************************************************
* *
* CONSTANTS * CONSTANTS
*/ */
#define FLUID_BUFSIZE 64 #define FLUID_BUFSIZE 64
@@ -267,7 +267,7 @@ typedef FILE* fluid_file;
#define FLUID_FSEEK(_f,_n,_set) fseek(_f,_n,_set) #define FLUID_FSEEK(_f,_n,_set) fseek(_f,_n,_set)
#define FLUID_MEMCPY(_dst,_src,_n) memcpy(_dst,_src,_n) #define FLUID_MEMCPY(_dst,_src,_n) memcpy(_dst,_src,_n)
#define FLUID_MEMSET(_s,_c,_n) memset(_s,_c,_n) #define FLUID_MEMSET(_s,_c,_n) memset(_s,_c,_n)
#define FLUID_STRLEN(_s) strlen(_s) #define FLUID_STRLEN(_s) strlen(_s)
#define FLUID_STRCMP(_s,_t) strcmp(_s,_t) #define FLUID_STRCMP(_s,_t) strcmp(_s,_t)
#define FLUID_STRNCMP(_s,_t,_n) strncmp(_s,_t,_n) #define FLUID_STRNCMP(_s,_t,_n) strncmp(_s,_t,_n)
#define FLUID_STRCPY(_dst,_src) strcpy(_dst,_src) #define FLUID_STRCPY(_dst,_src) strcpy(_dst,_src)
@@ -276,31 +276,16 @@ typedef FILE* fluid_file;
#define FLUID_STRDUP(s) strdup(s) #define FLUID_STRDUP(s) strdup(s)
#else #else
#define FLUID_STRDUP(s) FLUID_STRCPY(FLUID_MALLOC(FLUID_STRLEN(s) + 1), s) #define FLUID_STRDUP(s) FLUID_STRCPY(FLUID_MALLOC(FLUID_STRLEN(s) + 1), s)
#endif #endif
#define FLUID_SPRINTF sprintf #define FLUID_SPRINTF sprintf
#define FLUID_FPRINTF fprintf #define FLUID_FPRINTF fprintf
#define fluid_clip(_val, _min, _max) \ #define fluid_clip(_val, _min, _max) \
{ (_val) = ((_val) < (_min))? (_min) : (((_val) > (_max))? (_max) : (_val)); } { (_val) = ((_val) < (_min))? (_min) : (((_val) > (_max))? (_max) : (_val)); }
/* Purpose:
* Some commands (SSE extensions on Pentium) need aligned data(
* The address must be ...xxx0.
* Take a pointer, and round it up to the next suitable address.
* Obviously, one has to allocate 15 bytes of additional memory.
* As soon as proper alignment is supported by the compiler, this
* can be removed.
*/
#ifdef ENABLE_SSE
/* FIXME - This is broken on AMD 64 - only used if SSE enabled */
#define FLUID_ALIGN16BYTE(ptr)(((int)(ptr)+15) & (~0xFL))
#else
#define FLUID_ALIGN16BYTE(ptr) ptr
#endif
#if WITH_FTS #if WITH_FTS
#define FLUID_PRINTF post #define FLUID_PRINTF post
#define FLUID_FLUSH() #define FLUID_FLUSH()
#else #else
#define FLUID_PRINTF printf #define FLUID_PRINTF printf
#define FLUID_FLUSH() fflush(stdout) #define FLUID_FLUSH() fflush(stdout)