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:
@@ -44,40 +44,37 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
|
||||
\file fluidsynth.h
|
||||
|
||||
\brief fluidsynth is a real-time SoundFont(R) synthesizer. This is
|
||||
the header of the fluidsynth library and contains the
|
||||
synthesizer's public API.
|
||||
|
||||
Depending on how you want to use or extend the synthesizer you
|
||||
will need different API functions. You probably do not need all
|
||||
of them. Here is what you might want to do:
|
||||
|
||||
o Embedded synthesizer: create a new synthesizer and send MIDI
|
||||
events to it. The sound goes directly to the audio output of
|
||||
your system.
|
||||
|
||||
o Plugin synthesizer: create a synthesizer and send MIDI events
|
||||
but pull the audio back into your application.
|
||||
|
||||
o SoundFont plugin: create a new type of "SoundFont" and allow
|
||||
the synthesizer to load your type of SoundFonts.
|
||||
|
||||
o MIDI input: Create a MIDI handler to read the MIDI input on your
|
||||
machine and send the MIDI events directly to the synthesizer.
|
||||
|
||||
o MIDI files: Open MIDI files and send the MIDI events 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.
|
||||
|
||||
*/
|
||||
/**
|
||||
* @file fluidsynth.h
|
||||
* @brief FluidSynth is a real-time synthesizer designed for SoundFont(R) files.
|
||||
*
|
||||
* This is the header of the fluidsynth library and contains the
|
||||
* synthesizer's public API.
|
||||
*
|
||||
* Depending on how you want to use or extend the synthesizer you
|
||||
* will need different API functions. You probably do not need all
|
||||
* of them. Here is what you might want to do:
|
||||
*
|
||||
* o Embedded synthesizer: create a new synthesizer and send MIDI
|
||||
* events to it. The sound goes directly to the audio output of
|
||||
* your system.
|
||||
*
|
||||
* o Plugin synthesizer: create a synthesizer and send MIDI events
|
||||
* but pull the audio back into your application.
|
||||
*
|
||||
* o SoundFont plugin: create a new type of "SoundFont" and allow
|
||||
* the synthesizer to load your type of SoundFonts.
|
||||
*
|
||||
* o MIDI input: Create a MIDI handler to read the MIDI input on your
|
||||
* machine and send the MIDI events directly to the synthesizer.
|
||||
*
|
||||
* o MIDI files: Open MIDI files and send the MIDI events 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.
|
||||
*/
|
||||
|
||||
#include "fluidsynth/types.h"
|
||||
#include "fluidsynth/settings.h"
|
||||
|
||||
@@ -25,15 +25,29 @@
|
||||
extern "C" {
|
||||
#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
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/** The function should return non-zero if an error occured. */
|
||||
/**
|
||||
* 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'
|
||||
* @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,
|
||||
int nin, float** in,
|
||||
int nout, float** out);
|
||||
|
||||
@@ -25,28 +25,37 @@
|
||||
extern "C" {
|
||||
#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 {
|
||||
FLUID_SEQ_NOTE = 0,
|
||||
FLUID_SEQ_NOTEON,
|
||||
FLUID_SEQ_NOTEOFF,
|
||||
FLUID_SEQ_ALLSOUNDSOFF,
|
||||
FLUID_SEQ_ALLNOTESOFF,
|
||||
FLUID_SEQ_BANKSELECT,
|
||||
FLUID_SEQ_PROGRAMCHANGE,
|
||||
FLUID_SEQ_PROGRAMSELECT,
|
||||
FLUID_SEQ_PITCHBEND,
|
||||
FLUID_SEQ_PITCHWHHELSENS,
|
||||
FLUID_SEQ_MODULATION,
|
||||
FLUID_SEQ_SUSTAIN,
|
||||
FLUID_SEQ_CONTROLCHANGE,
|
||||
FLUID_SEQ_PAN,
|
||||
FLUID_SEQ_VOLUME,
|
||||
FLUID_SEQ_REVERBSEND,
|
||||
FLUID_SEQ_CHORUSSEND,
|
||||
FLUID_SEQ_TIMER,
|
||||
FLUID_SEQ_ANYCONTROLCHANGE, // used for remove_events only
|
||||
FLUID_SEQ_LASTEVENT
|
||||
FLUID_SEQ_NOTE = 0, /**< Note event (DOCME) */
|
||||
FLUID_SEQ_NOTEON, /**< Note on event */
|
||||
FLUID_SEQ_NOTEOFF, /**< Note off event */
|
||||
FLUID_SEQ_ALLSOUNDSOFF, /**< All sounds off event */
|
||||
FLUID_SEQ_ALLNOTESOFF, /**< All notes off event */
|
||||
FLUID_SEQ_BANKSELECT, /**< Bank select message */
|
||||
FLUID_SEQ_PROGRAMCHANGE, /**< Program change message */
|
||||
FLUID_SEQ_PROGRAMSELECT, /**< Program select message (DOCME) */
|
||||
FLUID_SEQ_PITCHBEND, /**< Pitch bend message */
|
||||
FLUID_SEQ_PITCHWHHELSENS, /**< Pitch wheel sensitivity set message */
|
||||
FLUID_SEQ_MODULATION, /**< Modulation controller event */
|
||||
FLUID_SEQ_SUSTAIN, /**< Sustain controller event */
|
||||
FLUID_SEQ_CONTROLCHANGE, /**< MIDI control change event */
|
||||
FLUID_SEQ_PAN, /**< Stereo pan set event */
|
||||
FLUID_SEQ_VOLUME, /**< Volume set event */
|
||||
FLUID_SEQ_REVERBSEND, /**< Reverb send set event */
|
||||
FLUID_SEQ_CHORUSSEND, /**< Chorus send set event */
|
||||
FLUID_SEQ_TIMER, /**< Timer event (DOCME) */
|
||||
FLUID_SEQ_ANYCONTROLCHANGE, /**< DOCME (used for remove_events only) */
|
||||
FLUID_SEQ_LASTEVENT /**< Defines the count of event enums */
|
||||
};
|
||||
|
||||
/* Event alloc/free */
|
||||
|
||||
@@ -25,99 +25,105 @@
|
||||
extern "C" {
|
||||
#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 {
|
||||
GEN_STARTADDROFS,
|
||||
GEN_ENDADDROFS,
|
||||
GEN_STARTLOOPADDROFS,
|
||||
GEN_ENDLOOPADDROFS,
|
||||
GEN_STARTADDRCOARSEOFS,
|
||||
GEN_MODLFOTOPITCH,
|
||||
GEN_VIBLFOTOPITCH,
|
||||
GEN_MODENVTOPITCH,
|
||||
GEN_FILTERFC,
|
||||
GEN_FILTERQ,
|
||||
GEN_MODLFOTOFILTERFC,
|
||||
GEN_MODENVTOFILTERFC,
|
||||
GEN_ENDADDRCOARSEOFS,
|
||||
GEN_MODLFOTOVOL,
|
||||
GEN_UNUSED1,
|
||||
GEN_CHORUSSEND,
|
||||
GEN_REVERBSEND,
|
||||
GEN_PAN,
|
||||
GEN_UNUSED2,
|
||||
GEN_UNUSED3,
|
||||
GEN_UNUSED4,
|
||||
GEN_MODLFODELAY,
|
||||
GEN_MODLFOFREQ,
|
||||
GEN_VIBLFODELAY,
|
||||
GEN_VIBLFOFREQ,
|
||||
GEN_MODENVDELAY,
|
||||
GEN_MODENVATTACK,
|
||||
GEN_MODENVHOLD,
|
||||
GEN_MODENVDECAY,
|
||||
GEN_MODENVSUSTAIN,
|
||||
GEN_MODENVRELEASE,
|
||||
GEN_KEYTOMODENVHOLD,
|
||||
GEN_KEYTOMODENVDECAY,
|
||||
GEN_VOLENVDELAY,
|
||||
GEN_VOLENVATTACK,
|
||||
GEN_VOLENVHOLD,
|
||||
GEN_VOLENVDECAY,
|
||||
GEN_VOLENVSUSTAIN,
|
||||
GEN_VOLENVRELEASE,
|
||||
GEN_KEYTOVOLENVHOLD,
|
||||
GEN_KEYTOVOLENVDECAY,
|
||||
GEN_INSTRUMENT,
|
||||
GEN_RESERVED1,
|
||||
GEN_KEYRANGE,
|
||||
GEN_VELRANGE,
|
||||
GEN_STARTLOOPADDRCOARSEOFS,
|
||||
GEN_KEYNUM,
|
||||
GEN_VELOCITY,
|
||||
GEN_ATTENUATION,
|
||||
GEN_RESERVED2,
|
||||
GEN_ENDLOOPADDRCOARSEOFS,
|
||||
GEN_COARSETUNE,
|
||||
GEN_FINETUNE,
|
||||
GEN_SAMPLEID,
|
||||
GEN_SAMPLEMODE,
|
||||
GEN_RESERVED3,
|
||||
GEN_SCALETUNE,
|
||||
GEN_EXCLUSIVECLASS,
|
||||
GEN_OVERRIDEROOTKEY,
|
||||
GEN_STARTADDROFS, /**< Sample start address offset (0-32767) */
|
||||
GEN_ENDADDROFS, /**< Sample end address offset (-32767-0) */
|
||||
GEN_STARTLOOPADDROFS, /**< Sample loop start address offset (-32767-32767) */
|
||||
GEN_ENDLOOPADDROFS, /**< Sample loop end address offset (-32767-32767) */
|
||||
GEN_STARTADDRCOARSEOFS, /**< Sample start address coarse offset (X 32768) */
|
||||
GEN_MODLFOTOPITCH, /**< Modulation LFO to pitch */
|
||||
GEN_VIBLFOTOPITCH, /**< Vibrato LFO to pitch */
|
||||
GEN_MODENVTOPITCH, /**< Modulation envelope to pitch */
|
||||
GEN_FILTERFC, /**< Filter cutoff */
|
||||
GEN_FILTERQ, /**< Filter Q */
|
||||
GEN_MODLFOTOFILTERFC, /**< Modulation LFO to filter cutoff */
|
||||
GEN_MODENVTOFILTERFC, /**< Modulation envelope to filter cutoff */
|
||||
GEN_ENDADDRCOARSEOFS, /**< Sample end address coarse offset (X 32768) */
|
||||
GEN_MODLFOTOVOL, /**< Modulation LFO to volume */
|
||||
GEN_UNUSED1, /**< Unused */
|
||||
GEN_CHORUSSEND, /**< Chorus send amount */
|
||||
GEN_REVERBSEND, /**< Reverb send amount */
|
||||
GEN_PAN, /**< Stereo panning */
|
||||
GEN_UNUSED2, /**< Unused */
|
||||
GEN_UNUSED3, /**< Unused */
|
||||
GEN_UNUSED4, /**< Unused */
|
||||
GEN_MODLFODELAY, /**< Modulation LFO delay */
|
||||
GEN_MODLFOFREQ, /**< Modulation LFO frequency */
|
||||
GEN_VIBLFODELAY, /**< Vibrato LFO delay */
|
||||
GEN_VIBLFOFREQ, /**< Vibrato LFO frequency */
|
||||
GEN_MODENVDELAY, /**< Modulation envelope delay */
|
||||
GEN_MODENVATTACK, /**< Modulation envelope attack */
|
||||
GEN_MODENVHOLD, /**< Modulation envelope hold */
|
||||
GEN_MODENVDECAY, /**< Modulation envelope decay */
|
||||
GEN_MODENVSUSTAIN, /**< Modulation envelope sustain */
|
||||
GEN_MODENVRELEASE, /**< Modulation envelope release */
|
||||
GEN_KEYTOMODENVHOLD, /**< Key to modulation envelope hold */
|
||||
GEN_KEYTOMODENVDECAY, /**< Key to modulation envelope decay */
|
||||
GEN_VOLENVDELAY, /**< Volume envelope delay */
|
||||
GEN_VOLENVATTACK, /**< Volume envelope attack */
|
||||
GEN_VOLENVHOLD, /**< Volume envelope hold */
|
||||
GEN_VOLENVDECAY, /**< Volume envelope decay */
|
||||
GEN_VOLENVSUSTAIN, /**< Volume envelope sustain */
|
||||
GEN_VOLENVRELEASE, /**< Volume envelope release */
|
||||
GEN_KEYTOVOLENVHOLD, /**< Key to volume envelope hold */
|
||||
GEN_KEYTOVOLENVDECAY, /**< Key to volume envelope decay */
|
||||
GEN_INSTRUMENT, /**< Instrument ID (shouldn't be set by user) */
|
||||
GEN_RESERVED1, /**< Reserved */
|
||||
GEN_KEYRANGE, /**< MIDI note range */
|
||||
GEN_VELRANGE, /**< MIDI velocity range */
|
||||
GEN_STARTLOOPADDRCOARSEOFS, /**< Sample start loop address coarse offset (X 32768) */
|
||||
GEN_KEYNUM, /**< Fixed MIDI note number */
|
||||
GEN_VELOCITY, /**< Fixed MIDI velocity value */
|
||||
GEN_ATTENUATION, /**< Initial volume attenuation */
|
||||
GEN_RESERVED2, /**< Reserved */
|
||||
GEN_ENDLOOPADDRCOARSEOFS, /**< Sample end loop address coarse offset (X 32768) */
|
||||
GEN_COARSETUNE, /**< Coarse tuning */
|
||||
GEN_FINETUNE, /**< Fine tuning */
|
||||
GEN_SAMPLEID, /**< Sample ID (shouldn't be set by user) */
|
||||
GEN_SAMPLEMODE, /**< Sample mode flags */
|
||||
GEN_RESERVED3, /**< Reserved */
|
||||
GEN_SCALETUNE, /**< Scale tuning */
|
||||
GEN_EXCLUSIVECLASS, /**< Exclusive class number */
|
||||
GEN_OVERRIDEROOTKEY, /**< Sample root note override */
|
||||
|
||||
/* the initial pitch is not a "standard" generator. It is not
|
||||
* mentioned in the list of generator in the SF2 specifications. It
|
||||
* is used, however, as the destination for the default pitch wheel
|
||||
* modulator. */
|
||||
GEN_PITCH,
|
||||
GEN_LAST
|
||||
GEN_PITCH, /**< Pitch (NOTE: Not a real SoundFont generator) */
|
||||
GEN_LAST /**< Value defines the count of generators (#fluid_gen_type) */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* fluid_gen_t
|
||||
* Sound font generator
|
||||
*/
|
||||
/**
|
||||
* SoundFont generator structure.
|
||||
*/
|
||||
typedef struct _fluid_gen_t
|
||||
{
|
||||
unsigned char flags; /* is it used or not */
|
||||
double val; /* The nominal value */
|
||||
double mod; /* Change by modulators */
|
||||
double nrpn; /* Change by NRPN messages */
|
||||
unsigned char flags; /**< Is the generator set or not (#fluid_gen_flags) */
|
||||
double val; /**< The nominal value */
|
||||
double mod; /**< Change by modulators */
|
||||
double nrpn; /**< Change by NRPN messages */
|
||||
} fluid_gen_t;
|
||||
|
||||
/**
|
||||
* Enum value for 'flags' field of #_fluid_gen_t (not really flags).
|
||||
*/
|
||||
enum fluid_gen_flags
|
||||
{
|
||||
GEN_UNUSED,
|
||||
GEN_SET,
|
||||
GEN_ABS_NRPN
|
||||
GEN_UNUSED, /**< Generator value is not set */
|
||||
GEN_SET, /**< Generator value is set */
|
||||
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);
|
||||
|
||||
|
||||
|
||||
@@ -27,57 +27,55 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Logging interface
|
||||
*
|
||||
* The default logging function of the fluidsynth prints its messages
|
||||
* to the stderr. The synthesizer uses four level of messages: FLUID_PANIC,
|
||||
* ERR, WARN, and FLUID_DBG. They are commented in the definition below.
|
||||
*
|
||||
* A client application can install a new log function to handle the
|
||||
* messages differently. In the following example, the application
|
||||
* sets a callback function to display "FLUID_PANIC" messages in a dialog,
|
||||
* and ignores all other messages by setting the log function to
|
||||
* NULL:
|
||||
*
|
||||
* ...
|
||||
* fluid_set_log_function(FLUID_PANIC, show_dialog, (void*) root_window);
|
||||
* fluid_set_log_function(ERR, NULL, NULL);
|
||||
* fluid_set_log_function(WARN, NULL, NULL);
|
||||
* fluid_set_log_function(FLUID_DBG, NULL, NULL);
|
||||
* ...
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* @file log.h
|
||||
* @brief Logging interface
|
||||
*
|
||||
* The default logging function of the fluidsynth prints its messages
|
||||
* to the stderr. The synthesizer uses five level of messages: #FLUID_PANIC,
|
||||
* #FLUID_ERR, #FLUID_WARN, #FLUID_INFO, and #FLUID_DBG.
|
||||
*
|
||||
* A client application can install a new log function to handle the
|
||||
* messages differently. In the following example, the application
|
||||
* sets a callback function to display #FLUID_PANIC messages in a dialog,
|
||||
* and ignores all other messages by setting the log function to
|
||||
* NULL:
|
||||
*
|
||||
* DOCME (formatting)
|
||||
* fluid_set_log_function(FLUID_PANIC, show_dialog, (void*) root_window);
|
||||
* fluid_set_log_function(FLUID_ERR, NULL, NULL);
|
||||
* fluid_set_log_function(FLUID_WARN, NULL, NULL);
|
||||
* fluid_set_log_function(FLUID_DBG, NULL, NULL);
|
||||
*/
|
||||
|
||||
/**
|
||||
* FluidSynth log levels.
|
||||
*/
|
||||
enum fluid_log_level {
|
||||
FLUID_PANIC, /* the synth can't function correctly any more */
|
||||
FLUID_ERR, /* the synth can function, but with serious limitation */
|
||||
FLUID_WARN, /* the synth might not function as expected */
|
||||
FLUID_INFO, /* verbose messages */
|
||||
FLUID_DBG, /* debugging messages */
|
||||
FLUID_PANIC, /**< The synth can't function correctly any more */
|
||||
FLUID_ERR, /**< Serious error occurred */
|
||||
FLUID_WARN, /**< Warning */
|
||||
FLUID_INFO, /**< Verbose informational messages */
|
||||
FLUID_DBG, /**< Debugging messages */
|
||||
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);
|
||||
|
||||
/** fluid_set_log_function installs a new log function for the
|
||||
* specified level. It returns the previously installed function.
|
||||
*/
|
||||
FLUIDSYNTH_API
|
||||
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);
|
||||
|
||||
/** print a message to the log */
|
||||
FLUIDSYNTH_API int fluid_log(int level, char * fmt, ...);
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -25,7 +25,10 @@
|
||||
extern "C" {
|
||||
#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 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);
|
||||
|
||||
|
||||
/* Generic callback function for MIDI events.
|
||||
* Will be used between
|
||||
* - MIDI driver and MIDI router
|
||||
* - MIDI router and synth
|
||||
* to communicate events.
|
||||
* In the not-so-far future...
|
||||
*/
|
||||
/**
|
||||
* Generic callback function for MIDI events.
|
||||
* @param data User defined data pointer
|
||||
* @param event The MIDI event
|
||||
* @return DOCME
|
||||
*
|
||||
* 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);
|
||||
|
||||
/*
|
||||
*
|
||||
* MIDI router
|
||||
*
|
||||
* The MIDI handler forwards incoming MIDI events to the synthesizer
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* MIDI router
|
||||
*
|
||||
* 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,
|
||||
handle_midi_event_func_t handler,
|
||||
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);
|
||||
|
||||
/** 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);
|
||||
|
||||
/** 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);
|
||||
|
||||
/** 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);
|
||||
|
||||
/*
|
||||
*
|
||||
* MIDI driver
|
||||
*
|
||||
* The MIDI handler forwards incoming MIDI events to the synthesizer
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
FLUIDSYNTH_API
|
||||
fluid_midi_driver_t* new_fluid_midi_driver(fluid_settings_t* settings,
|
||||
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
|
||||
*
|
||||
* 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);
|
||||
|
||||
@@ -144,9 +144,9 @@ struct _fluid_sample_t
|
||||
{
|
||||
char name[21];
|
||||
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 loopend;
|
||||
unsigned int loopend; /* Note: first point following the loop (superimposed on loopstart) */
|
||||
unsigned int samplerate;
|
||||
int origpitch;
|
||||
int pitchadj;
|
||||
|
||||
@@ -26,10 +26,10 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define FLUIDSYNTH_VERSION "1.0.7"
|
||||
#define FLUIDSYNTH_VERSION "1.0.8"
|
||||
#define FLUIDSYNTH_VERSION_MAJOR 1
|
||||
#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);
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
|
||||
[: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
|
||||
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
|
||||
@@ -24,10 +24,6 @@ summery of contributions.
|
||||
(the blue waves with FluidSynth letters partially submerged).
|
||||
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
|
||||
LADSPA subsystem, the MIDI router, optimized for SSE, made many
|
||||
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
|
||||
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
|
||||
loading (RAM Sfont), developed the
|
||||
MacroMedia Director Xtra, and send in many many bug reports. Thanks
|
||||
@@ -67,8 +67,7 @@ summery of contributions.
|
||||
portability.
|
||||
|
||||
* 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
|
||||
the alsa sequencer interface. file: iiwu_alsa.c
|
||||
Smurf's midi_alsaraw.c by Josh Green. file: iiwu_alsa.c
|
||||
|
||||
* The reverb algorithm was written by Jezar
|
||||
(http://www.dreampoint.co.uk). His code is public domain. The code
|
||||
@@ -115,3 +114,7 @@ Gerald Pye
|
||||
Rui Nuno Capela
|
||||
Frieder Bürzele
|
||||
Henri Manson
|
||||
Mihail Zenkov
|
||||
Paul Millar
|
||||
Nick Daly
|
||||
David Hilvert
|
||||
|
||||
@@ -14,6 +14,7 @@ SharedLibrary libfluidsynth.so :
|
||||
fluid_cmd.c
|
||||
fluid_conv.c
|
||||
fluid_defsfont.c
|
||||
fluid_dsp_float.c
|
||||
fluid_event.c
|
||||
fluid_gen.c
|
||||
fluid_hash.c
|
||||
@@ -28,7 +29,6 @@ SharedLibrary libfluidsynth.so :
|
||||
fluid_seq.c
|
||||
fluid_seqbind.c
|
||||
fluid_settings.c
|
||||
fluid_strtok.c
|
||||
fluid_synth.c
|
||||
fluid_sys.c
|
||||
fluid_tuning.c
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -25,12 +25,12 @@
|
||||
* fluid_adriver_definition_t
|
||||
*/
|
||||
|
||||
typedef struct _fluid_audriver_definition_t
|
||||
typedef struct _fluid_audriver_definition_t
|
||||
{
|
||||
char* name;
|
||||
fluid_audio_driver_t* (*new)(fluid_settings_t* settings, fluid_synth_t* synth);
|
||||
fluid_audio_driver_t* (*new2)(fluid_settings_t* settings,
|
||||
fluid_audio_func_t func,
|
||||
fluid_audio_driver_t* (*new2)(fluid_settings_t* settings,
|
||||
fluid_audio_func_t func,
|
||||
void* data);
|
||||
int (*free)(fluid_audio_driver_t* driver);
|
||||
void (*settings)(fluid_settings_t* settings);
|
||||
@@ -48,57 +48,57 @@ void fluid_alsa_audio_driver_settings(fluid_settings_t* settings);
|
||||
#endif
|
||||
|
||||
#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_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);
|
||||
int delete_fluid_oss_audio_driver(fluid_audio_driver_t* p);
|
||||
void fluid_oss_audio_driver_settings(fluid_settings_t* settings);
|
||||
#endif
|
||||
|
||||
#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_audio_driver_t* new_fluid_core_audio_driver2(fluid_settings_t* settings,
|
||||
fluid_audio_func_t func,
|
||||
fluid_audio_driver_t* new_fluid_core_audio_driver2(fluid_settings_t* settings,
|
||||
fluid_audio_func_t func,
|
||||
void* data);
|
||||
int delete_fluid_core_audio_driver(fluid_audio_driver_t* p);
|
||||
void fluid_core_audio_driver_settings(fluid_settings_t* settings);
|
||||
#endif
|
||||
|
||||
#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);
|
||||
int delete_fluid_dsound_audio_driver(fluid_audio_driver_t* p);
|
||||
void fluid_dsound_audio_driver_settings(fluid_settings_t* settings);
|
||||
#endif
|
||||
|
||||
#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);
|
||||
int delete_fluid_portaudio_driver(fluid_audio_driver_t* p);
|
||||
#endif
|
||||
|
||||
#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_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);
|
||||
int delete_fluid_jack_audio_driver(fluid_audio_driver_t* p);
|
||||
void fluid_jack_audio_driver_settings(fluid_settings_t* settings);
|
||||
#endif
|
||||
|
||||
#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_audio_driver_t* new_fluid_sndmgr_audio_driver2(fluid_settings_t* settings,
|
||||
fluid_audio_func_t func,
|
||||
fluid_audio_driver_t* new_fluid_sndmgr_audio_driver2(fluid_settings_t* settings,
|
||||
fluid_audio_func_t func,
|
||||
void* data);
|
||||
int delete_fluid_sndmgr_audio_driver(fluid_audio_driver_t* p);
|
||||
#endif
|
||||
|
||||
#define AUFILE_SUPPORT 1
|
||||
#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);
|
||||
int delete_fluid_file_audio_driver(fluid_audio_driver_t* p);
|
||||
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[] = {
|
||||
#if OSS_SUPPORT
|
||||
{ "oss",
|
||||
new_fluid_oss_audio_driver,
|
||||
{ "oss",
|
||||
new_fluid_oss_audio_driver,
|
||||
new_fluid_oss_audio_driver2,
|
||||
delete_fluid_oss_audio_driver,
|
||||
delete_fluid_oss_audio_driver,
|
||||
fluid_oss_audio_driver_settings },
|
||||
#endif
|
||||
#if ALSA_SUPPORT
|
||||
@@ -120,45 +120,45 @@ fluid_audriver_definition_t fluid_audio_drivers[] = {
|
||||
fluid_alsa_audio_driver_settings },
|
||||
#endif
|
||||
#if COREAUDIO_SUPPORT
|
||||
{ "coreaudio",
|
||||
new_fluid_core_audio_driver,
|
||||
{ "coreaudio",
|
||||
new_fluid_core_audio_driver,
|
||||
new_fluid_core_audio_driver2,
|
||||
delete_fluid_core_audio_driver,
|
||||
delete_fluid_core_audio_driver,
|
||||
fluid_core_audio_driver_settings },
|
||||
#endif
|
||||
#if DSOUND_SUPPORT
|
||||
{ "dsound",
|
||||
new_fluid_dsound_audio_driver,
|
||||
{ "dsound",
|
||||
new_fluid_dsound_audio_driver,
|
||||
NULL,
|
||||
delete_fluid_dsound_audio_driver,
|
||||
delete_fluid_dsound_audio_driver,
|
||||
fluid_dsound_audio_driver_settings },
|
||||
#endif
|
||||
#if PORTAUDIO_SUPPORT
|
||||
{ "portaudio",
|
||||
new_fluid_portaudio_driver,
|
||||
{ "portaudio",
|
||||
new_fluid_portaudio_driver,
|
||||
NULL,
|
||||
delete_fluid_portaudio_driver,
|
||||
NULL },
|
||||
delete_fluid_portaudio_driver,
|
||||
NULL },
|
||||
#endif
|
||||
#if SNDMAN_SUPPORT
|
||||
{ "sndman",
|
||||
new_fluid_sndmgr_audio_driver,
|
||||
{ "sndman",
|
||||
new_fluid_sndmgr_audio_driver,
|
||||
new_fluid_sndmgr_audio_driver2,
|
||||
delete_fluid_sndmgr_audio_driver,
|
||||
delete_fluid_sndmgr_audio_driver,
|
||||
NULL },
|
||||
#endif
|
||||
#if JACK_SUPPORT
|
||||
{ "jack",
|
||||
new_fluid_jack_audio_driver,
|
||||
{ "jack",
|
||||
new_fluid_jack_audio_driver,
|
||||
new_fluid_jack_audio_driver2,
|
||||
delete_fluid_jack_audio_driver,
|
||||
delete_fluid_jack_audio_driver,
|
||||
fluid_jack_audio_driver_settings },
|
||||
#endif
|
||||
#if AUFILE_SUPPORT
|
||||
{ "file",
|
||||
new_fluid_file_audio_driver,
|
||||
{ "file",
|
||||
new_fluid_file_audio_driver,
|
||||
NULL,
|
||||
delete_fluid_file_audio_driver,
|
||||
delete_fluid_file_audio_driver,
|
||||
fluid_file_audio_driver_settings },
|
||||
#endif
|
||||
{ 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) {
|
||||
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)
|
||||
{
|
||||
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);
|
||||
if (driver) {
|
||||
driver->name = fluid_audio_drivers[i].name;
|
||||
}
|
||||
}
|
||||
return driver;
|
||||
}
|
||||
}
|
||||
@@ -269,7 +279,20 @@ new_fluid_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth)
|
||||
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)
|
||||
{
|
||||
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);
|
||||
if (driver) {
|
||||
driver->name = fluid_audio_drivers[i].name;
|
||||
}
|
||||
}
|
||||
return driver;
|
||||
}
|
||||
}
|
||||
@@ -294,7 +317,13 @@ new_fluid_audio_driver2(fluid_settings_t* settings, fluid_audio_func_t func, voi
|
||||
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)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -30,7 +30,7 @@ void fluid_audio_driver_settings(fluid_settings_t* settings);
|
||||
* fluid_audio_driver_t
|
||||
*/
|
||||
|
||||
struct _fluid_audio_driver_t
|
||||
struct _fluid_audio_driver_t
|
||||
{
|
||||
char* name;
|
||||
};
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
/* 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
|
||||
*
|
||||
*
|
||||
* This structure should not be accessed directly. Use audio port
|
||||
* functions instead.
|
||||
* functions instead.
|
||||
*/
|
||||
typedef struct {
|
||||
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,
|
||||
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);
|
||||
if (dev == NULL) {
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
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)
|
||||
{
|
||||
fluid_file_audio_driver_t* dev = (fluid_file_audio_driver_t*) p;
|
||||
|
||||
|
||||
if (dev == NULL) {
|
||||
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)
|
||||
{
|
||||
fluid_file_audio_driver_t* dev = (fluid_file_audio_driver_t*) d;
|
||||
float* handle[2];
|
||||
int i, k, n, offset;
|
||||
float s;
|
||||
int n, offset;
|
||||
unsigned int sample_time;
|
||||
|
||||
handle[0] = dev->left;
|
||||
handle[1] = dev->right;
|
||||
|
||||
|
||||
sample_time = (unsigned int) (dev->samples / dev->sample_rate * 1000.0);
|
||||
if (sample_time > clock_time) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
(*dev->callback)(dev->data, dev->period_size, 0, NULL, 2, handle);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
fluid_synth_write_s16(dev->data, dev->period_size, dev->buf, 0, 2, dev->buf, 1, 2);
|
||||
|
||||
for (offset = 0; offset < dev->buf_size; offset += n) {
|
||||
|
||||
|
||||
n = fwrite((char*) dev->buf + offset, 1, dev->buf_size - offset, dev->file);
|
||||
if (n < 0) {
|
||||
FLUID_LOG(FLUID_ERR, "Audio file error");
|
||||
return 0;
|
||||
}
|
||||
FLUID_LOG(FLUID_ERR, "Audio output file write error: %s",
|
||||
strerror (errno));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dev->samples += dev->period_size;
|
||||
|
||||
return 1;
|
||||
|
||||
error_recovery:
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -28,7 +28,7 @@
|
||||
/*
|
||||
* new_fluid_channel
|
||||
*/
|
||||
fluid_channel_t*
|
||||
fluid_channel_t*
|
||||
new_fluid_channel(fluid_synth_t* synth, int num)
|
||||
{
|
||||
fluid_channel_t* chan;
|
||||
@@ -41,6 +41,7 @@ new_fluid_channel(fluid_synth_t* synth, int num)
|
||||
|
||||
chan->synth = synth;
|
||||
chan->channum = num;
|
||||
chan->preset = NULL;
|
||||
|
||||
fluid_channel_init(chan);
|
||||
fluid_channel_init_ctrl(chan);
|
||||
@@ -48,19 +49,22 @@ new_fluid_channel(fluid_synth_t* synth, int num)
|
||||
return chan;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
fluid_channel_init(fluid_channel_t* chan)
|
||||
{
|
||||
chan->prognum = (chan->channum == 9)? 0 : chan->channum;
|
||||
chan->banknum = (chan->channum == 9)? 128 : 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->interp_method = FLUID_INTERP_DEFAULT;
|
||||
chan->tuning = NULL;
|
||||
chan->nrpn_select = 0;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
fluid_channel_init_ctrl(fluid_channel_t* chan)
|
||||
{
|
||||
int i;
|
||||
@@ -79,21 +83,21 @@ fluid_channel_init_ctrl(fluid_channel_t* chan)
|
||||
for (i = 0; i < 128; i++) {
|
||||
SETCC(chan, i, 0);
|
||||
}
|
||||
|
||||
|
||||
/* Volume / initial attenuation (MSB & LSB) */
|
||||
SETCC(chan, 7, 127);
|
||||
SETCC(chan, 39, 0);
|
||||
SETCC(chan, 7, 127);
|
||||
SETCC(chan, 39, 0);
|
||||
|
||||
/* Pan (MSB & LSB) */
|
||||
SETCC(chan, 10, 64);
|
||||
SETCC(chan, 10, 64);
|
||||
SETCC(chan, 10, 64);
|
||||
SETCC(chan, 10, 64);
|
||||
|
||||
/* Expression (MSB & LSB) */
|
||||
SETCC(chan, 11, 127);
|
||||
SETCC(chan, 43, 127);
|
||||
SETCC(chan, 11, 127);
|
||||
SETCC(chan, 43, 127);
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
fluid_channel_reset(fluid_channel_t* chan)
|
||||
{
|
||||
fluid_channel_init(chan);
|
||||
@@ -103,9 +107,10 @@ fluid_channel_reset(fluid_channel_t* chan)
|
||||
/*
|
||||
* delete_fluid_channel
|
||||
*/
|
||||
int
|
||||
int
|
||||
delete_fluid_channel(fluid_channel_t* chan)
|
||||
{
|
||||
if (chan->preset) delete_fluid_preset (chan->preset);
|
||||
FLUID_FREE(chan);
|
||||
return FLUID_OK;
|
||||
}
|
||||
@@ -113,12 +118,13 @@ delete_fluid_channel(fluid_channel_t* chan)
|
||||
/*
|
||||
* fluid_channel_set_preset
|
||||
*/
|
||||
int
|
||||
int
|
||||
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(preset, FLUID_PRESET_SELECTED, chan->channum);
|
||||
|
||||
if (chan->preset) delete_fluid_preset (chan->preset);
|
||||
chan->preset = preset;
|
||||
return FLUID_OK;
|
||||
}
|
||||
@@ -126,7 +132,7 @@ fluid_channel_set_preset(fluid_channel_t* chan, fluid_preset_t* preset)
|
||||
/*
|
||||
* fluid_channel_get_preset
|
||||
*/
|
||||
fluid_preset_t*
|
||||
fluid_preset_t*
|
||||
fluid_channel_get_preset(fluid_channel_t* chan)
|
||||
{
|
||||
return chan->preset;
|
||||
@@ -135,7 +141,7 @@ fluid_channel_get_preset(fluid_channel_t* chan)
|
||||
/*
|
||||
* fluid_channel_get_banknum
|
||||
*/
|
||||
unsigned int
|
||||
unsigned int
|
||||
fluid_channel_get_banknum(fluid_channel_t* chan)
|
||||
{
|
||||
return chan->banknum;
|
||||
@@ -144,7 +150,7 @@ fluid_channel_get_banknum(fluid_channel_t* chan)
|
||||
/*
|
||||
* fluid_channel_set_prognum
|
||||
*/
|
||||
int
|
||||
int
|
||||
fluid_channel_set_prognum(fluid_channel_t* chan, int prognum)
|
||||
{
|
||||
chan->prognum = prognum;
|
||||
@@ -154,7 +160,7 @@ fluid_channel_set_prognum(fluid_channel_t* chan, int prognum)
|
||||
/*
|
||||
* fluid_channel_get_prognum
|
||||
*/
|
||||
int
|
||||
int
|
||||
fluid_channel_get_prognum(fluid_channel_t* chan)
|
||||
{
|
||||
return chan->prognum;
|
||||
@@ -163,7 +169,7 @@ fluid_channel_get_prognum(fluid_channel_t* chan)
|
||||
/*
|
||||
* fluid_channel_set_banknum
|
||||
*/
|
||||
int
|
||||
int
|
||||
fluid_channel_set_banknum(fluid_channel_t* chan, unsigned int banknum)
|
||||
{
|
||||
chan->banknum = banknum;
|
||||
@@ -173,14 +179,14 @@ fluid_channel_set_banknum(fluid_channel_t* chan, unsigned int banknum)
|
||||
/*
|
||||
* fluid_channel_cc
|
||||
*/
|
||||
int
|
||||
int
|
||||
fluid_channel_cc(fluid_channel_t* chan, int num, int value)
|
||||
{
|
||||
chan->cc[num] = value;
|
||||
|
||||
|
||||
switch (num) {
|
||||
|
||||
case SUSTAIN_SWITCH:
|
||||
|
||||
case SUSTAIN_SWITCH:
|
||||
{
|
||||
if (value < 64) {
|
||||
/* printf("** sustain off\n"); */
|
||||
@@ -190,7 +196,7 @@ fluid_channel_cc(fluid_channel_t* chan, int num, int value)
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case BANK_SELECT_MSB:
|
||||
{
|
||||
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 */
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case BANK_SELECT_LSB:
|
||||
{
|
||||
/* FIXME: according to the Downloadable Sounds II specification,
|
||||
bit 31 should be set when we receive the message on 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)));
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case ALL_NOTES_OFF:
|
||||
fluid_synth_all_notes_off(chan->synth, chan->channum);
|
||||
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);
|
||||
break;
|
||||
|
||||
case DATA_ENTRY_MSB:
|
||||
case DATA_ENTRY_MSB:
|
||||
{
|
||||
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)) {
|
||||
float val = fluid_gen_scale_nrpn(chan->nrpn_select, data);
|
||||
FLUID_LOG(FLUID_WARN, "%s: %d: Data = %d, value = %f", __FILE__, __LINE__, data, val);
|
||||
fluid_synth_set_gen(chan->synth, chan->channum, chan->nrpn_select, val);
|
||||
fluid_synth_set_gen(chan->synth, chan->channum, chan->nrpn_select, val);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -262,7 +268,7 @@ fluid_channel_cc(fluid_channel_t* chan, int num, int value)
|
||||
chan->nrpn_select += value;
|
||||
FLUID_LOG(FLUID_WARN, "%s: %d: NRPN Select = %d", __FILE__, __LINE__, chan->nrpn_select);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case RPN_MSB:
|
||||
@@ -278,14 +284,14 @@ fluid_channel_cc(fluid_channel_t* chan, int num, int value)
|
||||
default:
|
||||
fluid_synth_modulate_voices(chan->synth, chan->channum, 1, num);
|
||||
}
|
||||
|
||||
|
||||
return FLUID_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* fluid_channel_get_cc
|
||||
*/
|
||||
int
|
||||
int
|
||||
fluid_channel_get_cc(fluid_channel_t* chan, int num)
|
||||
{
|
||||
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
|
||||
*/
|
||||
int
|
||||
int
|
||||
fluid_channel_pitch_bend(fluid_channel_t* chan, int val)
|
||||
{
|
||||
chan->pitch_bend = val;
|
||||
@@ -305,7 +311,7 @@ fluid_channel_pitch_bend(fluid_channel_t* chan, int val)
|
||||
/*
|
||||
* fluid_channel_pitch_wheel_sens
|
||||
*/
|
||||
int
|
||||
int
|
||||
fluid_channel_pitch_wheel_sens(fluid_channel_t* chan, int 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
|
||||
*/
|
||||
int
|
||||
int
|
||||
fluid_channel_get_num(fluid_channel_t* chan)
|
||||
{
|
||||
return chan->channum;
|
||||
@@ -324,7 +330,7 @@ fluid_channel_get_num(fluid_channel_t* chan)
|
||||
|
||||
/* Purpose:
|
||||
* 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)
|
||||
{
|
||||
@@ -333,7 +339,7 @@ void fluid_channel_set_interp_method(fluid_channel_t* chan, int new_method)
|
||||
|
||||
/* Purpose:
|
||||
* 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)
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -64,7 +64,7 @@ struct _fluid_channel_t
|
||||
* generators set in the SoundFont. For example, if the NRPN
|
||||
* specifies an attack of 100 msec then 100 msec will be added to the
|
||||
* combined attack time of the sound font and the modulators.
|
||||
*
|
||||
*
|
||||
* However, it is useful to be able to specify the generator value
|
||||
* absolutely, completely ignoring the generators of the sound font
|
||||
* and the values of modulators. The gen_abs field, is a boolean
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
* August 24, 1998
|
||||
* Copyright (C) 1998 Juergen Mueller And Sundry Contributors
|
||||
* This source code is freely redistributable and may be used for
|
||||
* any purpose. This copyright notice must be maintained.
|
||||
* Juergen Mueller And Sundry Contributors are not responsible for
|
||||
* any purpose. This copyright notice must be maintained.
|
||||
* Juergen Mueller And Sundry Contributors are not responsible for
|
||||
* the consequences of using this software.
|
||||
*/
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
CHANGES
|
||||
|
||||
- Adapted for fluidsynth, Peter Hanappe, March 2002
|
||||
|
||||
|
||||
- Variable delay line implementation using bandlimited
|
||||
interpolation, code reorganization: Markus Nentwig May 2002
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
/*
|
||||
* Chorus effect.
|
||||
*
|
||||
*
|
||||
* Flow diagram scheme for n delays ( 1 <= n <= MAX_CHORUS ):
|
||||
*
|
||||
* * gain-in ___
|
||||
@@ -40,7 +40,7 @@
|
||||
* +---->| delay n |----------------------------->| |
|
||||
* |_________| | |
|
||||
* /|\ |___|
|
||||
* | |
|
||||
* | |
|
||||
* +-----------------+ +--------------+ | * gain-out
|
||||
* | Delay control n |<--| mod. speed n | |
|
||||
* +-----------------+ +--------------+ +----->obuff
|
||||
@@ -74,10 +74,10 @@
|
||||
#define MIN_SPEED_HZ 0.29
|
||||
#define MAX_SPEED_HZ 5
|
||||
|
||||
/* Length of one delay line in samples:
|
||||
* Set through MAX_SAMPLES_LN2.
|
||||
* For example:
|
||||
* MAX_SAMPLES_LN2=12
|
||||
/* Length of one delay line in samples:
|
||||
* Set through MAX_SAMPLES_LN2.
|
||||
* For example:
|
||||
* MAX_SAMPLES_LN2=12
|
||||
* => MAX_SAMPLES=pow(2,12)=4096
|
||||
* => MAX_SAMPLES_ANDMASK=4095
|
||||
*/
|
||||
@@ -89,7 +89,7 @@
|
||||
|
||||
/* Interpolate how many steps between samples? Must be power of two
|
||||
For example: 8 => use a resolution of 256 steps between any two
|
||||
samples
|
||||
samples
|
||||
*/
|
||||
#define INTERPOLATION_SUBSAMPLES_LN2 8
|
||||
#define INTERPOLATION_SUBSAMPLES (1 << (INTERPOLATION_SUBSAMPLES_LN2-1))
|
||||
@@ -98,13 +98,13 @@
|
||||
/* Use how many samples for interpolation? Must be odd. '7' sounds
|
||||
relatively clean, when listening to the modulated delay signal
|
||||
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
|
||||
|
||||
/* Private data for SKEL file */
|
||||
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:
|
||||
* - both 'parameter' and 'new_parameter' hold the same value.
|
||||
* - 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 */
|
||||
|
||||
fluid_real_t *chorusbuf;
|
||||
int counter;
|
||||
int counter;
|
||||
long phase[MAX_CHORUS];
|
||||
long modulation_period_samples;
|
||||
int *lookup_tab;
|
||||
@@ -137,12 +137,12 @@ struct _fluid_chorus_t {
|
||||
void fluid_chorus_triangle(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)
|
||||
{
|
||||
int i; int ii;
|
||||
fluid_chorus_t* chorus;
|
||||
|
||||
|
||||
chorus = FLUID_NEW(fluid_chorus_t);
|
||||
if (chorus == NULL) {
|
||||
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 */
|
||||
for (i = 0; i < INTERPOLATION_SAMPLES; i++){
|
||||
|
||||
|
||||
/* ii: Offset in terms of fractional samples ('subsamples') */
|
||||
for (ii = 0; ii < INTERPOLATION_SUBSAMPLES; ii++){
|
||||
/* 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");
|
||||
goto error_recovery;
|
||||
}
|
||||
|
||||
|
||||
/* allocate sample buffer */
|
||||
|
||||
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){
|
||||
goto error_recovery;
|
||||
};
|
||||
|
||||
|
||||
return chorus;
|
||||
|
||||
error_recovery:
|
||||
@@ -203,7 +203,7 @@ new_fluid_chorus(fluid_real_t sample_rate)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
int
|
||||
fluid_chorus_init(fluid_chorus_t* chorus)
|
||||
{
|
||||
int i;
|
||||
@@ -306,7 +306,7 @@ int fluid_chorus_get_type(fluid_chorus_t* chorus)
|
||||
return chorus->type;
|
||||
};
|
||||
|
||||
void
|
||||
void
|
||||
delete_fluid_chorus(fluid_chorus_t* chorus)
|
||||
{
|
||||
if (chorus == NULL) {
|
||||
@@ -320,7 +320,7 @@ delete_fluid_chorus(fluid_chorus_t* chorus)
|
||||
if (chorus->lookup_tab != NULL) {
|
||||
FLUID_FREE(chorus->lookup_tab);
|
||||
}
|
||||
|
||||
|
||||
FLUID_FREE(chorus);
|
||||
}
|
||||
|
||||
@@ -328,12 +328,12 @@ delete_fluid_chorus(fluid_chorus_t* chorus)
|
||||
/* Purpose:
|
||||
* Calculates the internal chorus parameters using the settings from
|
||||
* fluid_chorus_set_xxx. */
|
||||
int
|
||||
int
|
||||
fluid_chorus_update(fluid_chorus_t* chorus)
|
||||
{
|
||||
int i;
|
||||
int modulation_depth_samples;
|
||||
|
||||
|
||||
if (chorus->new_number_blocks < 0) {
|
||||
fluid_log(FLUID_WARN, "chorus: number blocks must be >=0! Setting value to 0.");
|
||||
chorus->new_number_blocks = 0;
|
||||
@@ -342,13 +342,13 @@ fluid_chorus_update(fluid_chorus_t* chorus)
|
||||
MAX_CHORUS);
|
||||
chorus->new_number_blocks = MAX_CHORUS;
|
||||
};
|
||||
|
||||
|
||||
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);
|
||||
chorus->new_speed_Hz = MIN_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);
|
||||
chorus->new_speed_Hz = MAX_SPEED_HZ;
|
||||
}
|
||||
@@ -357,7 +357,7 @@ fluid_chorus_update(fluid_chorus_t* chorus)
|
||||
chorus->new_depth_ms = 0.0;
|
||||
}
|
||||
/* Depth: Check for too high value through modulation_depth_samples. */
|
||||
|
||||
|
||||
if (chorus->new_level < 0.0) {
|
||||
fluid_log(FLUID_WARN, "chorus: level must be positive! Setting value to 0.");
|
||||
chorus->new_level = 0.0;
|
||||
@@ -366,40 +366,40 @@ fluid_chorus_update(fluid_chorus_t* chorus)
|
||||
"Setting it to 0.1.");
|
||||
chorus->new_level = 0.1;
|
||||
}
|
||||
|
||||
|
||||
/* The modulating LFO goes through a full period every x samples: */
|
||||
chorus->modulation_period_samples = chorus->sample_rate / chorus->new_speed_Hz;
|
||||
|
||||
|
||||
/* 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->sample_rate);
|
||||
|
||||
|
||||
if (modulation_depth_samples > MAX_SAMPLES) {
|
||||
fluid_log(FLUID_WARN, "chorus: Too high depth. Setting it to max (%d).", MAX_SAMPLES);
|
||||
modulation_depth_samples = MAX_SAMPLES;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* initialize LFO table */
|
||||
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);
|
||||
} 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);
|
||||
} else {
|
||||
fluid_log(FLUID_WARN, "chorus: Unknown modulation type. Using sinewave.");
|
||||
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);
|
||||
};
|
||||
|
||||
|
||||
for (i = 0; i < chorus->number_blocks; i++) {
|
||||
/* 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);
|
||||
}
|
||||
|
||||
|
||||
/* Start of the circular buffer */
|
||||
chorus->counter = 0;
|
||||
|
||||
@@ -409,7 +409,7 @@ fluid_chorus_update(fluid_chorus_t* chorus)
|
||||
chorus->speed_Hz = chorus->new_speed_Hz;
|
||||
chorus->number_blocks = chorus->new_number_blocks;
|
||||
return FLUID_OK;
|
||||
|
||||
|
||||
/* failure: */
|
||||
/* Note: This lives on the assumption, that the last chorus values were correct.
|
||||
* 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)
|
||||
{
|
||||
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++) {
|
||||
int ii;
|
||||
/* Calculate the delay in subsamples for the delay line of chorus block nr. */
|
||||
|
||||
|
||||
/* The value in the lookup table is so, that this expression
|
||||
* will always be positive. It will always include a number of
|
||||
* full periods of MAX_SAMPLES*INTERPOLATION_SUBSAMPLES to
|
||||
* 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]]);
|
||||
|
||||
|
||||
int pos_samples = pos_subsamples/INTERPOLATION_SUBSAMPLES;
|
||||
|
||||
/* modulo divide by INTERPOLATION_SUBSAMPLES */
|
||||
pos_subsamples &= INTERPOLATION_SUBSAMPLES_ANDMASK;
|
||||
|
||||
|
||||
for (ii = 0; ii < INTERPOLATION_SAMPLES; ii++){
|
||||
/* Add the delayed signal to the chorus sum d_out Note: The
|
||||
* 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
|
||||
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--;
|
||||
};
|
||||
@@ -478,11 +478,11 @@ void fluid_chorus_processmix(fluid_chorus_t* chorus, fluid_real_t *in,
|
||||
} /* foreach chorus block */
|
||||
|
||||
d_out *= chorus->level;
|
||||
|
||||
|
||||
/* Add the chorus sum d_out to output */
|
||||
left_out[sample_index] += d_out;
|
||||
right_out[sample_index] += d_out;
|
||||
|
||||
|
||||
/* Move forward in circular buffer */
|
||||
chorus->counter++;
|
||||
chorus->counter %= MAX_SAMPLES;
|
||||
@@ -490,8 +490,8 @@ void fluid_chorus_processmix(fluid_chorus_t* chorus, fluid_real_t *in,
|
||||
} /* foreach sample */
|
||||
}
|
||||
|
||||
/* Duplication of code ... */
|
||||
void fluid_chorus_processreplace(fluid_chorus_t* chorus, fluid_real_t *in,
|
||||
/* Duplication of code ... (replaces sample data instead of mixing) */
|
||||
void fluid_chorus_processreplace(fluid_chorus_t* chorus, fluid_real_t *in,
|
||||
fluid_real_t *left_out, fluid_real_t *right_out)
|
||||
{
|
||||
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++) {
|
||||
int ii;
|
||||
/* Calculate the delay in subsamples for the delay line of chorus block nr. */
|
||||
|
||||
|
||||
/* The value in the lookup table is so, that this expression
|
||||
* will always be positive. It will always include a number of
|
||||
* full periods of MAX_SAMPLES*INTERPOLATION_SUBSAMPLES to
|
||||
* 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]]);
|
||||
|
||||
|
||||
int pos_samples = pos_subsamples / INTERPOLATION_SUBSAMPLES;
|
||||
|
||||
/* modulo divide by INTERPOLATION_SUBSAMPLES */
|
||||
pos_subsamples &= INTERPOLATION_SUBSAMPLES_ANDMASK;
|
||||
|
||||
|
||||
for (ii = 0; ii < INTERPOLATION_SAMPLES; ii++){
|
||||
/* Add the delayed signal to the chorus sum d_out Note: The
|
||||
* 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
|
||||
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--;
|
||||
};
|
||||
@@ -545,11 +546,11 @@ void fluid_chorus_processreplace(fluid_chorus_t* chorus, fluid_real_t *in,
|
||||
} /* foreach chorus block */
|
||||
|
||||
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;
|
||||
right_out[sample_index] = d_out;
|
||||
|
||||
|
||||
/* Move forward in circular buffer */
|
||||
chorus->counter++;
|
||||
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_init(chorus);
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -32,9 +32,9 @@ typedef struct _fluid_chorus_t fluid_chorus_t;
|
||||
*/
|
||||
fluid_chorus_t* new_fluid_chorus(fluid_real_t sample_rate);
|
||||
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);
|
||||
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);
|
||||
|
||||
int fluid_chorus_init(fluid_chorus_t* chorus);
|
||||
|
||||
+170
-172
File diff suppressed because it is too large
Load Diff
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -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);
|
||||
void delete_fluid_cmd(fluid_cmd_t* cmd);
|
||||
|
||||
int fluid_cmd_handler_handle(fluid_cmd_handler_t* handler,
|
||||
int ac, char** av,
|
||||
int fluid_cmd_handler_handle(fluid_cmd_handler_t* handler,
|
||||
int ac, char** av,
|
||||
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);
|
||||
|
||||
|
||||
fluid_client_t* new_fluid_client(fluid_server_t* server,
|
||||
fluid_settings_t* settings,
|
||||
fluid_cmd_handler_t* handler,
|
||||
fluid_client_t* new_fluid_client(fluid_server_t* server,
|
||||
fluid_settings_t* settings,
|
||||
fluid_cmd_handler_t* handler,
|
||||
fluid_socket_t sock);
|
||||
|
||||
void delete_fluid_client(fluid_client_t* client);
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -35,7 +35,7 @@ fluid_real_t fluid_pan_tab[FLUID_PAN_SIZE];
|
||||
*
|
||||
* Does all the initialization for this module.
|
||||
*/
|
||||
void
|
||||
void
|
||||
fluid_conversion_config(void)
|
||||
{
|
||||
int i;
|
||||
@@ -44,7 +44,7 @@ fluid_conversion_config(void)
|
||||
for (i = 0; i < FLUID_CENTS_HZ_SIZE; i++) {
|
||||
fluid_ct2hz_tab[i] = (fluid_real_t) pow(2.0, (double) i / 1200.0);
|
||||
}
|
||||
|
||||
|
||||
/* centibels to amplitude conversion
|
||||
* Note: SF2.01 section 8.1.3: Initial attenuation range 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[127] = 1.0;
|
||||
x = log10(128.0 / 127.0);
|
||||
|
||||
|
||||
/* There seems to be an error in the specs. The equations are
|
||||
implemented according to the pictures on SF2.01 page 73. */
|
||||
|
||||
@@ -95,11 +95,11 @@ fluid_conversion_config(void)
|
||||
/*
|
||||
* fluid_ct2hz
|
||||
*/
|
||||
fluid_real_t
|
||||
fluid_ct2hz_real(fluid_real_t cents)
|
||||
fluid_real_t
|
||||
fluid_ct2hz_real(fluid_real_t cents)
|
||||
{
|
||||
if (cents < 0)
|
||||
return (fluid_real_t) 1.0;
|
||||
return (fluid_real_t) 1.0;
|
||||
else if (cents < 900) {
|
||||
return (fluid_real_t) 6.875 * fluid_ct2hz_tab[(int) (cents + 300)];
|
||||
} else if (cents < 2100) {
|
||||
@@ -132,8 +132,8 @@ fluid_ct2hz_real(fluid_real_t cents)
|
||||
/*
|
||||
* fluid_ct2hz
|
||||
*/
|
||||
fluid_real_t
|
||||
fluid_ct2hz(fluid_real_t cents)
|
||||
fluid_real_t
|
||||
fluid_ct2hz(fluid_real_t cents)
|
||||
{
|
||||
/* Filter fc limit: SF2.01 page 48 # 8 */
|
||||
if (cents >= 13500){
|
||||
@@ -150,15 +150,15 @@ fluid_ct2hz(fluid_real_t cents)
|
||||
* in: a value between 0 and 960, 0 is no attenuation
|
||||
* out: a value between 1 and 0
|
||||
*/
|
||||
fluid_real_t
|
||||
fluid_real_t
|
||||
fluid_cb2amp(fluid_real_t cb)
|
||||
{
|
||||
/*
|
||||
/*
|
||||
* cb: an attenuation in 'centibels' (1/10 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.
|
||||
*/
|
||||
|
||||
|
||||
/* minimum attenuation: 0 dB */
|
||||
if (cb < 0) {
|
||||
return 1.0;
|
||||
@@ -166,7 +166,7 @@ fluid_cb2amp(fluid_real_t cb)
|
||||
if (cb >= FLUID_CB_AMP_SIZE) {
|
||||
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
|
||||
* follow this. Thats the reason for separate fluid_cb2amp and fluid_atten2amp.
|
||||
*/
|
||||
fluid_real_t
|
||||
fluid_real_t
|
||||
fluid_atten2amp(fluid_real_t atten)
|
||||
{
|
||||
if (atten < 0) return 1.0;
|
||||
@@ -189,7 +189,7 @@ fluid_atten2amp(fluid_real_t atten)
|
||||
/*
|
||||
* fluid_tc2sec_delay
|
||||
*/
|
||||
fluid_real_t
|
||||
fluid_real_t
|
||||
fluid_tc2sec_delay(fluid_real_t tc)
|
||||
{
|
||||
/* 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_real_t
|
||||
fluid_real_t
|
||||
fluid_tc2sec_attack(fluid_real_t tc)
|
||||
{
|
||||
/* SF2.01 section 8.1.2 items 26, 34
|
||||
@@ -228,7 +228,7 @@ fluid_tc2sec_attack(fluid_real_t tc)
|
||||
/*
|
||||
* fluid_tc2sec
|
||||
*/
|
||||
fluid_real_t
|
||||
fluid_real_t
|
||||
fluid_tc2sec(fluid_real_t tc)
|
||||
{
|
||||
/* No range checking here! */
|
||||
@@ -238,7 +238,7 @@ fluid_tc2sec(fluid_real_t tc)
|
||||
/*
|
||||
* fluid_tc2sec_release
|
||||
*/
|
||||
fluid_real_t
|
||||
fluid_real_t
|
||||
fluid_tc2sec_release(fluid_real_t tc)
|
||||
{
|
||||
/* 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
|
||||
*/
|
||||
fluid_real_t
|
||||
fluid_real_t
|
||||
fluid_act2hz(fluid_real_t c)
|
||||
{
|
||||
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
|
||||
*/
|
||||
fluid_real_t
|
||||
fluid_real_t
|
||||
fluid_hz2ct(fluid_real_t f)
|
||||
{
|
||||
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_real_t
|
||||
fluid_real_t
|
||||
fluid_pan(fluid_real_t c, int left)
|
||||
{
|
||||
if (left) {
|
||||
@@ -294,7 +294,7 @@ fluid_pan(fluid_real_t c, int left)
|
||||
/*
|
||||
* fluid_concave
|
||||
*/
|
||||
fluid_real_t
|
||||
fluid_real_t
|
||||
fluid_concave(fluid_real_t val)
|
||||
{
|
||||
if (val < 0) {
|
||||
@@ -308,7 +308,7 @@ fluid_concave(fluid_real_t val)
|
||||
/*
|
||||
* fluid_convex
|
||||
*/
|
||||
fluid_real_t
|
||||
fluid_real_t
|
||||
fluid_convex(fluid_real_t val)
|
||||
{
|
||||
if (val < 0) {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -13,7 +13,7 @@
|
||||
* 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
|
||||
@@ -218,7 +218,6 @@ extern unsigned short badpgen[]; /* list of bad preset generators */
|
||||
void sfont_init_chunks (void);
|
||||
|
||||
void sfont_close (SFData * sf);
|
||||
void sfont_free_data (SFData * sf);
|
||||
void sfont_free_zone (SFZone * zone);
|
||||
int sfont_preset_compare_func (void* a, void* b);
|
||||
|
||||
@@ -230,8 +229,8 @@ int gen_validp (int gen);
|
||||
|
||||
|
||||
/*-----------------------------------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]
|
||||
@@ -427,7 +426,6 @@ enum
|
||||
#define ErrnoEnd ErrWrite
|
||||
|
||||
int gerr (int ev, char * fmt, ...);
|
||||
void *safe_malloc (size_t size);
|
||||
int safe_fread (void *buf, int count, FILE * fd);
|
||||
int safe_fwrite (void *buf, int count, FILE * fd);
|
||||
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_defpreset_t fluid_defpreset_t;
|
||||
|
||||
@@ -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
|
||||
@@ -11,271 +11,677 @@
|
||||
* 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 "fluidsynth_priv.h"
|
||||
#include "fluid_phase.h"
|
||||
|
||||
/* Purpose:
|
||||
* Low-level voice processing:
|
||||
/* Purpose:
|
||||
*
|
||||
* - 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
|
||||
* Interpolates audio data (obtains values between the samples of the original
|
||||
* waveform data).
|
||||
*
|
||||
*
|
||||
* 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:
|
||||
* Variables loaded from the voice structure (assigned in fluid_voice_write()):
|
||||
* - 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),
|
||||
* 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
|
||||
*
|
||||
* - dsp_buf: Output buffer of floating point values (FLUID_BUFSIZE in length)
|
||||
*/
|
||||
|
||||
/* 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)
|
||||
*/
|
||||
#include "fluidsynth_priv.h"
|
||||
#include "fluid_synth.h"
|
||||
#include "fluid_voice.h"
|
||||
|
||||
# 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)) {
|
||||
/* Linear interpolation table (2 coefficients centered on 1st) */
|
||||
static fluid_real_t interp_coeff_linear[FLUID_INTERP_MAX][2];
|
||||
|
||||
/* 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;
|
||||
}
|
||||
/* 4th order (cubic) interpolation table (4 coefficients centered on 2nd) */
|
||||
static fluid_real_t interp_coeff[FLUID_INTERP_MAX][4];
|
||||
|
||||
} else {
|
||||
|
||||
/* 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;
|
||||
/* 7th order interpolation (7 coefficients centered on 3rd) */
|
||||
static fluid_real_t sinc_table7[FLUID_INTERP_MAX][7];
|
||||
|
||||
|
||||
case FLUID_INTERP_7THORDER:
|
||||
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 */
|
||||
#define SINC_INTERP_ORDER 7 /* 7th order constant */
|
||||
|
||||
|
||||
/* 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
|
||||
* panning generator has a range of -500 .. 500. If it is centered,
|
||||
* it's close to 0. voice->amp_left and voice->amp_right are then the
|
||||
* same, and we can save one multiplication per voice and sample.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
/* Initialize the coefficients for the interpolation. The math comes
|
||||
* from a mail, posted by Olli Niemitalo to the music-dsp mailing
|
||||
* list (I found it in the music-dsp archives
|
||||
* http://www.smartelectronix.com/musicdsp/). */
|
||||
|
||||
} 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
|
||||
* amplitudes will be zero. */
|
||||
if (voice->amp_left != 0.0){
|
||||
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) {
|
||||
dsp_left_buf[dsp_i] += voice->amp_left * dsp_buf[dsp_i];
|
||||
}
|
||||
}
|
||||
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];
|
||||
}
|
||||
}
|
||||
interp_coeff[i][0] = (fluid_real_t)(x * (-0.5 + x * (1 - 0.5 * x)));
|
||||
interp_coeff[i][1] = (fluid_real_t)(1.0 + x * x * (1.5 * x - 2.5));
|
||||
interp_coeff[i][2] = (fluid_real_t)(x * (0.5 + x * (2.0 - 1.5 * x)));
|
||||
interp_coeff[i][3] = (fluid_real_t)(0.5 * x * x * (x - 1.0));
|
||||
|
||||
interp_coeff_linear[i][0] = (fluid_real_t)(1.0 - x);
|
||||
interp_coeff_linear[i][1] = (fluid_real_t)x;
|
||||
}
|
||||
|
||||
/* 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)) {
|
||||
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) {
|
||||
dsp_reverb_buf[dsp_i] += voice->amp_reverb * dsp_buf[dsp_i];
|
||||
}
|
||||
|
||||
/* No interpolation. Just take the sample, which is closest to
|
||||
* the playback pointer. Questionable quality, but very
|
||||
* 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. */
|
||||
if ((dsp_chorus_buf != NULL) && (voice->amp_chorus != 0)) {
|
||||
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) {
|
||||
dsp_chorus_buf[dsp_i] += voice->amp_chorus * dsp_buf[dsp_i];
|
||||
}
|
||||
/* Straight line interpolation.
|
||||
* Returns number of samples processed (usually FLUID_BUFSIZE but could be
|
||||
* smaller if end of sample occurs).
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -19,7 +19,7 @@
|
||||
*/
|
||||
|
||||
|
||||
/* Purpose:
|
||||
/* Purpose:
|
||||
* Low-level voice processing:
|
||||
*
|
||||
* - 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
|
||||
* 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),
|
||||
* 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.
|
||||
@@ -74,37 +74,37 @@
|
||||
* - dsp_centernode: delay line for the IIR filter
|
||||
* - dsp_hist1: same
|
||||
* - dsp_hist2: same
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* Nonoptimized DSP loop */
|
||||
#warning "This code is meant for experiments only.";
|
||||
|
||||
/* wave table interpolation */
|
||||
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) {
|
||||
/* wave table interpolation */
|
||||
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_sample = (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 = &interp_coeff[fluid_phase_fract_to_tablerow(dsp_phase)];
|
||||
dsp_phase_index = fluid_phase_index(dsp_phase);
|
||||
dsp_sample = (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);
|
||||
|
||||
/* increment phase and amplitude */
|
||||
fluid_phase_incr(dsp_phase, dsp_phase_incr);
|
||||
dsp_amp += dsp_amp_incr;
|
||||
|
||||
/* filter */
|
||||
/* The filter is implemented in Direct-II form. */
|
||||
/* filter */
|
||||
/* The filter is implemented in Direct-II form. */
|
||||
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_hist2 = dsp_hist1;
|
||||
dsp_hist1 = dsp_centernode;
|
||||
dsp_hist2 = dsp_hist1;
|
||||
dsp_hist1 = dsp_centernode;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* reverb */
|
||||
|
||||
@@ -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++;
|
||||
}
|
||||
}
|
||||
@@ -11,14 +11,14 @@
|
||||
* 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
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
2002 : API design by Peter Hanappe and Antoine Schmitt
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "fluid_event_priv.h"
|
||||
#include "fluidsynth_priv.h"
|
||||
|
||||
@@ -38,11 +38,15 @@
|
||||
|
||||
/* 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()
|
||||
{
|
||||
fluid_event_t* evt;
|
||||
|
||||
|
||||
evt = FLUID_NEW(fluid_event_t);
|
||||
if (evt == NULL) {
|
||||
fluid_log(FLUID_PANIC, "event: Out of memory\n");
|
||||
@@ -50,46 +54,69 @@ new_fluid_event()
|
||||
}
|
||||
|
||||
FLUID_MEMSET(evt, 0, sizeof(fluid_event_t));
|
||||
|
||||
|
||||
// by default, no type
|
||||
evt->dest = -1;
|
||||
evt->src = -1;
|
||||
evt->type = -1;
|
||||
|
||||
return(evt);
|
||||
evt->dest = -1;
|
||||
evt->src = -1;
|
||||
evt->type = -1;
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
if (evt == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
fluid_event_set_time(fluid_event_t* evt, unsigned int time)
|
||||
{
|
||||
evt->time = time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set source of a sequencer event (DOCME).
|
||||
* @param evt Sequencer event structure
|
||||
* @param src DOCME
|
||||
*/
|
||||
void
|
||||
fluid_event_set_source(fluid_event_t* evt, short src)
|
||||
{
|
||||
evt->src = src;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set destination of a sequencer event (DOCME).
|
||||
* @param evt Sequencer event structure
|
||||
* @param dest DOCME
|
||||
*/
|
||||
void
|
||||
fluid_event_set_dest(fluid_event_t* evt, short dest)
|
||||
{
|
||||
evt->dest = dest;
|
||||
}
|
||||
|
||||
/* Timer events */
|
||||
/**
|
||||
* Set a sequencer event to be a timer event.
|
||||
* @param evt Sequencer event structure
|
||||
* @param data DOCME
|
||||
*/
|
||||
void
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/* 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
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a sequencer event to be an all sounds off event.
|
||||
* @param evt Sequencer event structure
|
||||
* @param channel MIDI channel number
|
||||
*/
|
||||
void
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a sequencer event to be a all notes off event.
|
||||
* @param evt Sequencer event structure
|
||||
* @param channel MIDI channel number
|
||||
*/
|
||||
void
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
fluid_event_program_select(fluid_event_t* evt, int channel,
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a sequencer event to be an any control change event.
|
||||
* @param evt Sequencer event structure
|
||||
* @param channel MIDI channel number
|
||||
* DOCME
|
||||
*/
|
||||
void
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
return evt->duration;
|
||||
@@ -378,21 +618,21 @@ _fluid_evt_heap_init(int nbEvents)
|
||||
int i;
|
||||
fluid_evt_heap_t* heap;
|
||||
int siz = 2*sizeof(fluid_evt_entry *) + sizeof(fluid_evt_entry)*nbEvents;
|
||||
|
||||
|
||||
heap = (fluid_evt_heap_t *)FLUID_MALLOC(siz);
|
||||
if (heap == NULL) {
|
||||
fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
|
||||
return NULL;
|
||||
}
|
||||
FLUID_MEMSET(heap, 0, siz);
|
||||
|
||||
|
||||
/* link all heap events */
|
||||
{
|
||||
fluid_evt_entry *tmp = &(heap->pool);
|
||||
for (i = 0 ; i < nbEvents - 1 ; i++)
|
||||
tmp[i].next = &(tmp[i+1]);
|
||||
tmp[nbEvents-1].next = NULL;
|
||||
|
||||
|
||||
/* set head & tail */
|
||||
heap->tail = &(tmp[nbEvents-1]);
|
||||
heap->head = &(heap->pool);
|
||||
@@ -422,7 +662,7 @@ _fluid_evt_heap_free(fluid_evt_heap_t* heap)
|
||||
fluid_mutex_destroy(heap->mutex);
|
||||
|
||||
FLUID_FREE(heap);
|
||||
|
||||
|
||||
#else
|
||||
FLUID_FREE(heap);
|
||||
#endif
|
||||
@@ -461,12 +701,12 @@ _fluid_seq_heap_get_free(fluid_evt_heap_t* heap)
|
||||
#else
|
||||
fluid_evt_entry* evt;
|
||||
if (heap->head == NULL) return NULL;
|
||||
|
||||
|
||||
/* take from head of the heap */
|
||||
/* critical - should threadlock ? */
|
||||
evt = heap->head;
|
||||
heap->head = heap->head->next;
|
||||
|
||||
|
||||
return evt;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -11,14 +11,14 @@
|
||||
* 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_EVENT_PRIV_H
|
||||
#define _FLUID_EVENT_PRIV_H
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -89,11 +89,12 @@ fluid_gen_info_t fluid_gen_info[] = {
|
||||
};
|
||||
|
||||
|
||||
/* fluid_gen_set_default_values
|
||||
*
|
||||
* Set an array of generators to their initial value
|
||||
/**
|
||||
* Set an array of generators to their default values.
|
||||
* @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)
|
||||
{
|
||||
int i;
|
||||
@@ -111,9 +112,9 @@ fluid_gen_set_default_values(fluid_gen_t* gen)
|
||||
|
||||
/* 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
return (fluid_gen_info[gen].min
|
||||
{
|
||||
return (fluid_gen_info[gen].min
|
||||
+ value * (fluid_gen_info[gen].max - fluid_gen_info[gen].min));
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
* 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
|
||||
* 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
|
||||
*/
|
||||
|
||||
@@ -60,7 +60,7 @@ struct _fluid_hashtable_t {
|
||||
if ((3 * hash_table->size <= hash_table->nnodes) \
|
||||
&& (hash_table->size < HASH_TABLE_MAX_SIZE)) { \
|
||||
fluid_hashtable_resize(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);
|
||||
@@ -69,7 +69,7 @@ static fluid_hashnode_t** fluid_hashtable_lookup_node(fluid_hashtable_t *hash_ta
|
||||
* new_fluid_hashtable:
|
||||
*
|
||||
* Creates a new #fluid_hashtable_t.
|
||||
*
|
||||
*
|
||||
* Return value: a new #fluid_hashtable_t.
|
||||
**/
|
||||
fluid_hashtable_t*
|
||||
@@ -94,22 +94,22 @@ new_fluid_hashtable(fluid_hash_delete_t del)
|
||||
/**
|
||||
* delete_fluid_hashtable:
|
||||
* @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
|
||||
* using fluid_hashtable_new_full(). In the latter case the destroy functions
|
||||
* you supplied will be called on all keys and values before destroying
|
||||
* using fluid_hashtable_new_full(). In the latter case the destroy functions
|
||||
* you supplied will be called on all keys and values before destroying
|
||||
* the #fluid_hashtable_t.
|
||||
**/
|
||||
void
|
||||
delete_fluid_hashtable(fluid_hashtable_t *hash_table)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
|
||||
if (hash_table == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < hash_table->size; i++) {
|
||||
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_hashnode_t **node;
|
||||
|
||||
|
||||
node = &hash_table->nodes[fluid_str_hash(key) % hash_table->size];
|
||||
|
||||
|
||||
while (*node && (FLUID_STRCMP((*node)->key, key) != 0)) {
|
||||
node = &(*node)->next;
|
||||
}
|
||||
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -137,16 +137,16 @@ fluid_hashtable_lookup_node (fluid_hashtable_t* hash_table, char* key)
|
||||
* fluid_hashtable_lookup:
|
||||
* @hash_table: a #fluid_hashtable_t.
|
||||
* @key: the key to look up.
|
||||
*
|
||||
*
|
||||
* Looks up a key in a #fluid_hashtable_t.
|
||||
*
|
||||
*
|
||||
* Return value: the associated value, or %NULL if the key is not found.
|
||||
**/
|
||||
int
|
||||
fluid_hashtable_lookup(fluid_hashtable_t *hash_table, char* key, void** value, int* type)
|
||||
{
|
||||
fluid_hashnode_t *node;
|
||||
|
||||
|
||||
node = *fluid_hashtable_lookup_node(hash_table, key);
|
||||
|
||||
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.
|
||||
* @key: a key to insert.
|
||||
* @value: the value to associate with the key.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* 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
|
||||
* 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.
|
||||
**/
|
||||
void
|
||||
fluid_hashtable_insert(fluid_hashtable_t *hash_table, char* key, void* value, int type)
|
||||
{
|
||||
fluid_hashnode_t **node;
|
||||
|
||||
|
||||
node = fluid_hashtable_lookup_node(hash_table, key);
|
||||
|
||||
|
||||
if (*node) {
|
||||
(*node)->value = value;
|
||||
(*node)->type = type;
|
||||
@@ -199,21 +199,21 @@ fluid_hashtable_insert(fluid_hashtable_t *hash_table, char* key, void* value, in
|
||||
* @hash_table: a #GHashTable.
|
||||
* @key: a key to insert.
|
||||
* @value: the value to associate with the key.
|
||||
*
|
||||
* Inserts a new key and value into a #GHashTable similar to
|
||||
* 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
|
||||
* @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
|
||||
* #GHashTable, the old key is freed using that function.
|
||||
*
|
||||
* Inserts a new key and value into a #GHashTable similar to
|
||||
* 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
|
||||
* @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
|
||||
* #GHashTable, the old key is freed using that function.
|
||||
**/
|
||||
void
|
||||
fluid_hashtable_replace(fluid_hashtable_t *hash_table, char* key, void* value, int type)
|
||||
{
|
||||
fluid_hashnode_t **node;
|
||||
|
||||
|
||||
node = fluid_hashtable_lookup_node(hash_table, key);
|
||||
|
||||
|
||||
if (*node) {
|
||||
if (hash_table->del) {
|
||||
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:
|
||||
* @hash_table: a #fluid_hashtable_t.
|
||||
* @key: the key to remove.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
*
|
||||
* Return value: %TRUE if the key was found and removed from the #fluid_hashtable_t.
|
||||
**/
|
||||
int
|
||||
fluid_hashtable_remove (fluid_hashtable_t *hash_table, char* key)
|
||||
{
|
||||
fluid_hashnode_t **node, *dest;
|
||||
|
||||
|
||||
node = fluid_hashtable_lookup_node(hash_table, key);
|
||||
if (*node) {
|
||||
dest = *node;
|
||||
(*node) = dest->next;
|
||||
delete_fluid_hashnode(dest, hash_table->del);
|
||||
hash_table->nnodes--;
|
||||
|
||||
|
||||
FLUID_HASHTABLE_RESIZE (hash_table);
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -266,7 +266,7 @@ fluid_hashtable_remove (fluid_hashtable_t *hash_table, char* key)
|
||||
* @hash_table: a #fluid_hashtable_t.
|
||||
* @func: the function to call for each key/value pair.
|
||||
* @user_data: user data to pass to the function.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* 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:
|
||||
* @hash_table: a #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.
|
||||
**/
|
||||
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;
|
||||
|
||||
/* printf("%s: %d: resizing, new size = %d\n", __FILE__, __LINE__, new_size); */
|
||||
|
||||
|
||||
new_nodes = FLUID_ARRAY(fluid_hashnode_t*, new_size);
|
||||
FLUID_MEMSET(new_nodes, 0, new_size * sizeof(fluid_hashnode_t*));
|
||||
|
||||
for (i = 0; i < hash_table->size; i++) {
|
||||
for (node = hash_table->nodes[i]; node; 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];
|
||||
new_nodes[hash_val] = node;
|
||||
}
|
||||
@@ -337,14 +337,14 @@ static fluid_hashnode_t*
|
||||
new_fluid_hashnode(char* key, void* value, int type)
|
||||
{
|
||||
fluid_hashnode_t *hash_node;
|
||||
|
||||
|
||||
hash_node = FLUID_NEW(fluid_hashnode_t);
|
||||
|
||||
|
||||
hash_node->key = FLUID_STRDUP(key);
|
||||
hash_node->value = value;
|
||||
hash_node->type = type;
|
||||
hash_node->next = NULL;
|
||||
|
||||
|
||||
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;
|
||||
delete_fluid_hashnode(hash_node, del);
|
||||
hash_node = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
* 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
|
||||
* 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,7 +11,7 @@
|
||||
* 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
|
||||
@@ -52,15 +52,15 @@ int fluid_istream_readline(fluid_istream_t in, char* prompt, char* buf, int len)
|
||||
#if WITH_READLINE
|
||||
if (in == fluid_get_stdin()) {
|
||||
char* line;
|
||||
|
||||
|
||||
line = readline(prompt);
|
||||
if (line == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
snprintf(buf, len, "%s", line);
|
||||
buf[len - 1] = 0;
|
||||
|
||||
|
||||
free(line);
|
||||
return 1;
|
||||
} else {
|
||||
@@ -78,19 +78,19 @@ int fluid_istream_gets(fluid_istream_t in, char* buf, int len)
|
||||
int n;
|
||||
|
||||
buf[len - 1] = 0;
|
||||
|
||||
|
||||
while (--len > 0) {
|
||||
n = read(in, &c, 1);
|
||||
if (n == 0) {
|
||||
*buf++ = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (n < 0) {
|
||||
return n;
|
||||
}
|
||||
if ((c == '\n') || (c == '\r')) {
|
||||
*buf++ = 0;
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
*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, ...)
|
||||
{
|
||||
char buf[4096];
|
||||
va_list args;
|
||||
va_list args;
|
||||
int len;
|
||||
|
||||
va_start(args, format);
|
||||
len = vsnprintf(buf, 4095, format, args);
|
||||
va_end(args);
|
||||
va_start(args, format);
|
||||
len = vsnprintf(buf, 4095, format, args);
|
||||
va_end(args);
|
||||
|
||||
if (len <= 0) {
|
||||
printf("fluid_ostream_printf: buffer overflow");
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -23,15 +23,15 @@
|
||||
#define _FLUID_IO_H
|
||||
|
||||
|
||||
/** Read a line from the input stream.
|
||||
|
||||
\returns 0 if end-of-stream, -1 if error, non zero otherwise
|
||||
/** Read a line from the input stream.
|
||||
|
||||
\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);
|
||||
|
||||
|
||||
/** 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
|
||||
returned.
|
||||
*/
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -57,17 +57,17 @@ fluid_LADSPA_FxUnit_t* new_fluid_LADSPA_FxUnit(fluid_synth_t* synth){
|
||||
return FxUnit;
|
||||
};
|
||||
|
||||
/* Purpose:
|
||||
/* Purpose:
|
||||
* Creates the system nodes to get data into and out of the Fx unit.
|
||||
*/
|
||||
void fluid_LADSPA_CreateSystemNodes(fluid_LADSPA_FxUnit_t* FxUnit){
|
||||
char str[99];
|
||||
char str[99];
|
||||
int nr_input_nodes;
|
||||
int nr_fx_input_nodes;
|
||||
int nr_output_nodes;
|
||||
int temp;
|
||||
int i;
|
||||
|
||||
|
||||
/* Retrieve the number of synth / audio out / Fx send nodes */
|
||||
assert(fluid_settings_getint(FxUnit->synth->settings, "synth.audio-groups", &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));
|
||||
nr_fx_input_nodes=temp;
|
||||
|
||||
|
||||
/* Create regular input nodes (associated with audio groups) */
|
||||
for (i=0; i < nr_input_nodes; i++){
|
||||
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.
|
||||
*/
|
||||
void fluid_LADSPA_CreateUserControlNodes(fluid_LADSPA_FxUnit_t* FxUnit){
|
||||
void fluid_LADSPA_CreateUserControlNodes(fluid_LADSPA_FxUnit_t* FxUnit){
|
||||
int i;
|
||||
fluid_LADSPA_Node_t* CurrentNode;
|
||||
|
||||
|
||||
for (i=0; i<FxUnit->NumberUserControlNodes; i++){
|
||||
CurrentNode=fluid_LADSPA_CreateNode(FxUnit,FxUnit->UserControlNodeNames[i],fluid_LADSPA_node_is_control);
|
||||
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).
|
||||
* 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 * CurrentLib=NULL;
|
||||
@@ -137,15 +137,15 @@ void * fluid_LADSPA_RetrieveSharedLibrary(fluid_LADSPA_FxUnit_t* FxUnit, char *
|
||||
return CurrentLib;
|
||||
};
|
||||
|
||||
/* Purpose:
|
||||
/* Purpose:
|
||||
* Loads a shared LADSPA library.
|
||||
* Return NULL, if failed.
|
||||
* Return NULL, if failed.
|
||||
* TODO: use LADSPA_PATH
|
||||
*/
|
||||
void * fluid_LADSPA_LoadSharedLibrary(fluid_LADSPA_FxUnit_t* FxUnit, char * LibraryFilename){
|
||||
void * LoadedLib;
|
||||
assert(LibraryFilename);
|
||||
LoadedLib=dlopen(LibraryFilename,RTLD_NOW);
|
||||
LoadedLib=dlopen(LibraryFilename,RTLD_NOW);
|
||||
if (!LoadedLib){
|
||||
return NULL;
|
||||
};
|
||||
@@ -155,7 +155,7 @@ void * fluid_LADSPA_LoadSharedLibrary(fluid_LADSPA_FxUnit_t* FxUnit, char * Libr
|
||||
return LoadedLib;
|
||||
};
|
||||
|
||||
/* Purpose:
|
||||
/* Purpose:
|
||||
* Retrieves a descriptor to the plugin labeled 'PluginLabel' from the shared library.
|
||||
*/
|
||||
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;
|
||||
pfDescriptorFunction = (LADSPA_Descriptor_Function)dlsym(CurrentLib,"ladspa_descriptor");
|
||||
while (pfDescriptorFunction(lPluginIndex)){
|
||||
psDescriptor = pfDescriptorFunction(lPluginIndex);
|
||||
psDescriptor = pfDescriptorFunction(lPluginIndex);
|
||||
if (FLUID_STRCMP(psDescriptor->Label, PluginLabel) == 0){
|
||||
return psDescriptor;
|
||||
return psDescriptor;
|
||||
};
|
||||
lPluginIndex++;
|
||||
};
|
||||
return NULL;
|
||||
};
|
||||
};
|
||||
|
||||
/* Purpose:
|
||||
/* Purpose:
|
||||
* Finds out, if 'PortName' starts with 'PluginPort'.
|
||||
* Spaces and underscore mean the same.
|
||||
* The comparison is not case sensitive.
|
||||
@@ -203,7 +203,7 @@ fluid_LADSPA_Stringmatch_t fluid_LADSPA_Check_SubString_Match(const char * Plugi
|
||||
};
|
||||
|
||||
/* 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
|
||||
@@ -214,7 +214,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
||||
char * PluginLabel;
|
||||
char ** TokenSequence;
|
||||
void * CurrentLib;
|
||||
int NodeCount; //x
|
||||
int NodeCount; //x
|
||||
int IngoingSignalCount; // Count signals going into 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. */
|
||||
@@ -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..."));
|
||||
assert(synth);
|
||||
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. */
|
||||
if (FxUnit->NumberPlugins || FxUnit->NumberLibs){
|
||||
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");
|
||||
fluid_LADSPA_clear(FxUnit);
|
||||
return(PrintErrorMessage);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
/* Create predefined nodes */
|
||||
L(fluid_ostream_printf(out,"ladspa_start: creating predefined nodes..."));
|
||||
fluid_LADSPA_CreateSystemNodes(FxUnit);
|
||||
|
||||
|
||||
/* Create predeclared nodes, that will allow to control the Fx unit during operation */
|
||||
L(fluid_ostream_printf(out,"ladspa_start: creating user control nodes..."));
|
||||
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..."));
|
||||
for (CommandLineCount=0; CommandLineCount<FxUnit->NumberCommands; CommandLineCount++){
|
||||
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;
|
||||
LADSPA_Handle CurrentPlugin;
|
||||
LADSPA_Handle CurrentPlugin;
|
||||
unsigned long PortCount;
|
||||
int TokenCount=0;
|
||||
char * Search;
|
||||
int HasASlash=0;
|
||||
|
||||
int HasASlash=0;
|
||||
|
||||
if (FxUnit->NumberPlugins>=FLUID_LADSPA_MaxPlugins){
|
||||
fluid_ostream_printf(out, "***Error003***\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));
|
||||
|
||||
|
||||
TokenSequence=FxUnit->LADSPA_Command_Sequence[CommandLineCount];
|
||||
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);
|
||||
|
||||
|
||||
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. */
|
||||
|
||||
@@ -286,7 +286,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
||||
* If that fails, signal error.
|
||||
* Otherwise leave the filename as it is.
|
||||
*/;
|
||||
|
||||
|
||||
/* Determine, if the library name is just the filename, or a path (including a slash) */
|
||||
Search=LibraryFilename;
|
||||
while (*Search != '\0') {
|
||||
@@ -295,9 +295,9 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
||||
};
|
||||
Search++;
|
||||
};
|
||||
|
||||
|
||||
if (!HasASlash){
|
||||
if (!LADSPA_Path){
|
||||
if (!LADSPA_Path){
|
||||
fluid_ostream_printf(out, "***Error018***\n"
|
||||
"The library file name %s does not include a path.\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);
|
||||
if (!CurrentLib){
|
||||
LADSPA_Descriptor_Function pfDescriptorFunction;
|
||||
LADSPA_Descriptor_Function pfDescriptorFunction;
|
||||
|
||||
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);
|
||||
return(PrintErrorMessage);
|
||||
};
|
||||
|
||||
|
||||
/* Load a LADSPA plugin library and store it for future use.*/
|
||||
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!";};
|
||||
fluid_ostream_printf(out, "***Error015***\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,
|
||||
pcError);
|
||||
fluid_LADSPA_clear(FxUnit);
|
||||
return(PrintErrorMessage);
|
||||
};
|
||||
|
||||
|
||||
L(fluid_ostream_printf(out,"Library loaded."));
|
||||
};
|
||||
|
||||
|
||||
PluginLabel=TokenSequence[TokenCount++]; assert(PluginLabel);
|
||||
L(fluid_ostream_printf(out,"Plugin Label from ladspa_add: %s",PluginLabel));
|
||||
/* Retrieve a 'plugin descriptor' from the library. */
|
||||
L(fluid_ostream_printf(out,"Looking for the plugin labeled %s",PluginLabel));
|
||||
|
||||
|
||||
CurrentPluginDescriptor=fluid_LADSPA_Retrieve_Plugin_Descriptor(CurrentLib, PluginLabel);
|
||||
|
||||
|
||||
|
||||
/* Check, that the plugin was actually found.*/
|
||||
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);
|
||||
return(PrintErrorMessage);
|
||||
};
|
||||
|
||||
|
||||
/* Create an instance of the plugin type from the descriptor */
|
||||
L(fluid_ostream_printf(out,"instantiating plugin %s",PluginLabel));
|
||||
CurrentPlugin=CurrentPluginDescriptor
|
||||
->instantiate(CurrentPluginDescriptor,44100); /* Sample rate hardcoded */
|
||||
assert(CurrentPlugin);
|
||||
|
||||
|
||||
/* 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
|
||||
different instances.*/
|
||||
FxUnit->PluginDescriptorTable[FxUnit->NumberPlugins]=CurrentPluginDescriptor;
|
||||
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 */
|
||||
for (PortCount=0; PortCount<CurrentPluginDescriptor->PortCount; PortCount++){
|
||||
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. */
|
||||
while (TokenSequence[TokenCount] && TokenSequence[TokenCount+1] && TokenSequence[TokenCount+2]){
|
||||
int CurrentPort_StringMatchCount;
|
||||
@@ -418,11 +418,11 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
||||
CurrentPort_StringMatchCount=0;
|
||||
|
||||
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".
|
||||
* Match the identifier specified by the user against the first characters
|
||||
* of the port name.
|
||||
*
|
||||
*
|
||||
* If the given identifier matches several port names only partly, then the input is ambiguous, an error
|
||||
* 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 Decay (s)
|
||||
* - Output
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
for (PortCount=0; PortCount<CurrentPluginDescriptor->PortCount; PortCount++){
|
||||
PortName=CurrentPluginDescriptor->PortNames[PortCount];
|
||||
|
||||
|
||||
StringMatchType=fluid_LADSPA_Check_SubString_Match(Plugin_Port, PortName);
|
||||
/* If a full-string match has been found earlier, reject all partial matches. */
|
||||
if (StringMatchType==fluid_LADSPA_FullMatch ||
|
||||
(StringMatchType==fluid_LADSPA_PartialMatch && CurrentPort_StringMatchType != fluid_LADSPA_FullMatch)){
|
||||
|
||||
|
||||
if(StringMatchType==fluid_LADSPA_FullMatch && CurrentPort_StringMatchType==fluid_LADSPA_FullMatch){
|
||||
fluid_ostream_printf(out, "***Error027***\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);
|
||||
return(PrintErrorMessage);
|
||||
};
|
||||
|
||||
|
||||
CurrentPort_Index=PortCount;
|
||||
CurrentPort_StringMatchType=StringMatchType;
|
||||
CurrentPort_StringMatchCount++;
|
||||
|
||||
|
||||
}; /* if suitable match */
|
||||
}; /* For port count */
|
||||
|
||||
|
||||
/* Several partial matches? Then the identifier is not unique. */
|
||||
if (CurrentPort_StringMatchCount > 1 && CurrentPort_StringMatchType == fluid_LADSPA_PartialMatch){
|
||||
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);
|
||||
return(PrintErrorMessage);
|
||||
};
|
||||
|
||||
|
||||
if (CurrentPort_Index<0){
|
||||
fluid_ostream_printf(out, "***Error017***\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);
|
||||
return(PrintErrorMessage);
|
||||
};
|
||||
CurrentPort_Descriptor=CurrentPluginDescriptor->PortDescriptors[CurrentPort_Index];
|
||||
CurrentPort_Descriptor=CurrentPluginDescriptor->PortDescriptors[CurrentPort_Index];
|
||||
assert(CurrentPort_Descriptor);
|
||||
|
||||
|
||||
/* Retrieve the node with the right name. */
|
||||
Current_Node=fluid_LADSPA_RetrieveNode(FxUnit,FLUID_Node);
|
||||
#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){
|
||||
/* Doesn't exist? Then create it. */
|
||||
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"
|
||||
"This is an error in the plugin.\n"
|
||||
"Please check plugin sourcecode.\n",
|
||||
CurrentPort_Index);
|
||||
CurrentPort_Index);
|
||||
fluid_LADSPA_clear(FxUnit);
|
||||
return(PrintErrorMessage);
|
||||
};
|
||||
};
|
||||
assert(Current_Node);
|
||||
|
||||
/*
|
||||
|
||||
/*
|
||||
*
|
||||
* Check flowgraph for some possible errors.
|
||||
*
|
||||
*/
|
||||
|
||||
if (FLUID_STRCMP(Direction,"->")==0){
|
||||
/* Data from plugin to FLUID, into node
|
||||
/* Data from plugin to FLUID, into node
|
||||
*
|
||||
* *** Rule: ****
|
||||
* 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++;
|
||||
} 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:
|
||||
* *** 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.
|
||||
* 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);
|
||||
@@ -542,7 +542,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
||||
fluid_ostream_printf(out, "***Error010***\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"
|
||||
"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);
|
||||
return(PrintErrorMessage);
|
||||
};
|
||||
@@ -550,7 +550,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
||||
} else {
|
||||
fluid_ostream_printf(out, "***Error024***\n"
|
||||
"Syntax error: Illegal `arrow' `%s', expecting -> or <-\n",
|
||||
Direction);
|
||||
Direction);
|
||||
fluid_LADSPA_clear(FxUnit);
|
||||
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. */
|
||||
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) */
|
||||
if (CurrentPlugin_PortConnected[CurrentPort_Index]){
|
||||
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
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
L(fluid_ostream_printf(out,"Connecting %i",CurrentPort_Index));
|
||||
CurrentPluginDescriptor->connect_port
|
||||
(CurrentPlugin,
|
||||
@@ -580,7 +580,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
||||
Current_Node->buf
|
||||
);
|
||||
CurrentPlugin_PortConnected[CurrentPort_Index]++;
|
||||
|
||||
|
||||
}; /* 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
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
if (TokenSequence[TokenCount]){
|
||||
char * T1="";char * T2="";char * T3="";
|
||||
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);
|
||||
return(PrintErrorMessage);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* 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);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
*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){
|
||||
CurrentPluginDescriptor->activate(CurrentPlugin);
|
||||
};
|
||||
|
||||
|
||||
FxUnit->NumberPlugins++;
|
||||
}; /* For CommandLineCount: once for each new command (i.e. plugin instantiation request from user */
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Further flow graph checks
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
L(fluid_ostream_printf(out,"Checking flow graph"));
|
||||
|
||||
IngoingSignalCount=0;
|
||||
OutgoingSignalCount=0;
|
||||
|
||||
|
||||
for (NodeCount=0; NodeCount<FxUnit->NumberNodes; NodeCount++){
|
||||
fluid_LADSPA_Node_t* Current_Node;
|
||||
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){
|
||||
OutgoingSignalCount+=Current_Node->InCount;
|
||||
} 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.
|
||||
*/
|
||||
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"
|
||||
"Use '_' as first char in nodename to suppress this warning.\n"
|
||||
"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. */
|
||||
};
|
||||
ReturnVal=PrintErrorMessage;
|
||||
};
|
||||
|
||||
|
||||
/* A node without any output doesn't make sense. */
|
||||
if (Current_Node->OutCount==0 && !Current_Node->flags & fluid_LADSPA_node_is_dummy){
|
||||
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. */
|
||||
assert(Current_Node->OutCount+Current_Node->InCount);
|
||||
}; /* Foreach node */
|
||||
|
||||
|
||||
/* Issue a warning, if no signal goes into the Fx section. */
|
||||
if (IngoingSignalCount==0){
|
||||
if (IngoingSignalCount==0){
|
||||
fluid_ostream_printf(out, "***Warning022***\n"
|
||||
"You have not connected anything to the synthesizer section (in1_L, in1_R).\n");
|
||||
ReturnVal=PrintErrorMessage;
|
||||
};
|
||||
|
||||
|
||||
/* Issue a warning, if no signal leaves the Fx section. */
|
||||
if (OutgoingSignalCount==0){
|
||||
if (OutgoingSignalCount==0){
|
||||
fluid_ostream_printf(out, "***Warning023***\n"
|
||||
"You have not connected anything to the output (out1_L, out1_R).\n");
|
||||
};
|
||||
|
||||
|
||||
/* Finally turn on the Fx unit. */
|
||||
FxUnit->Bypass=fluid_LADSPA_Active;
|
||||
L(fluid_ostream_printf(out,"LADSPA Init OK"));
|
||||
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[]){
|
||||
int i;
|
||||
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));
|
||||
nr_fx_sends=temp;
|
||||
|
||||
/* Fixme: Retrieving nodes via names is inefficient
|
||||
* (but not that bad, because the interesting nodes are always at the start of the list).
|
||||
/* Fixme: Retrieving nodes via names is inefficient
|
||||
* (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. */
|
||||
if (FxUnit->Bypass==fluid_LADSPA_Bypassed){
|
||||
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."));
|
||||
return;
|
||||
};
|
||||
|
||||
|
||||
assert(FxUnit);
|
||||
|
||||
/* 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);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/* Prepare the incoming data:
|
||||
* Convert fluid_real_t data type to LADSPA_Data type */
|
||||
for (ii=0; ii < nr_groups; ii++){
|
||||
fluid_real_t* src_buf=left_buf[ii];
|
||||
sprintf(str, "in%i_L",(ii+1));
|
||||
n=fluid_LADSPA_RetrieveNode(FxUnit, str); assert(n);
|
||||
|
||||
|
||||
assert(FLUID_BUFSIZE % 2 == 0);
|
||||
|
||||
|
||||
/* Add a very small high frequency signal. This avoids denormal number problems. */
|
||||
for (i=0; i<FLUID_BUFSIZE;){
|
||||
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++){
|
||||
dest_buf[i]=(fluid_real_t)n->buf[i];
|
||||
};
|
||||
|
||||
|
||||
dest_buf=right_buf[ii];
|
||||
sprintf(str, "out%i_R",(ii+1));
|
||||
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){
|
||||
int i=0;
|
||||
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.
|
||||
*/
|
||||
fluid_LADSPA_Node_t*
|
||||
fluid_LADSPA_Node_t*
|
||||
fluid_LADSPA_CreateNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name, int flags){
|
||||
int Dummy=0;
|
||||
int Dummy=0;
|
||||
fluid_LADSPA_Node_t* NewNode;
|
||||
assert(FxUnit);
|
||||
assert(Name);
|
||||
@@ -858,7 +858,7 @@ fluid_LADSPA_CreateNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name, int flags){
|
||||
fluid_LADSPA_clear(FxUnit);
|
||||
return NULL;
|
||||
};
|
||||
|
||||
|
||||
/* Don't allow node names, which start with -, 0..9 */
|
||||
if (Name[0] == '-' || (Name[0]>='0' && Name[0]<='9')){
|
||||
printf( "***Error026***\n"
|
||||
@@ -870,7 +870,7 @@ fluid_LADSPA_CreateNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name, int flags){
|
||||
fluid_LADSPA_clear(FxUnit);
|
||||
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). */
|
||||
if (Name[0] == ' '){ /* ??? Should be '_' ??? */
|
||||
Dummy=1;
|
||||
@@ -880,7 +880,7 @@ fluid_LADSPA_CreateNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name, int flags){
|
||||
/* Audio node contains buffer. */
|
||||
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. */
|
||||
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){
|
||||
/* Control node contains single value. */
|
||||
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]);
|
||||
};
|
||||
FxUnit->NumberUserControlNodes=0;
|
||||
|
||||
|
||||
L(printf("Clear all plugin instances"));
|
||||
for (i=0; i<FxUnit->NumberPlugins; 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->NumberPlugins=0;
|
||||
|
||||
|
||||
L(printf("Clear all nodes")); /* Only after removing plugins! */
|
||||
for (i=0; i<FxUnit->NumberNodes; i++){
|
||||
FLUID_FREE(FxUnit->Nodelist[i]->buf);
|
||||
FLUID_FREE(FxUnit->Nodelist[i]);
|
||||
};
|
||||
FxUnit->NumberNodes=0;
|
||||
|
||||
|
||||
|
||||
L(printf("Clear all plugin libraries"));
|
||||
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);
|
||||
return(PrintErrorMessage);
|
||||
};
|
||||
|
||||
|
||||
/* CommandLine (token sequence) is terminated with NULL.
|
||||
* 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);
|
||||
return(PrintErrorMessage);
|
||||
};
|
||||
|
||||
|
||||
NodeName=FLUID_STRDUP(av[0]); assert(NodeName);
|
||||
NodeValue=atof(av[1]);
|
||||
FxUnit->UserControlNodeNames[FxUnit->NumberUserControlNodes]=NodeName;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -79,7 +79,7 @@ typedef enum {
|
||||
fluid_LADSPA_node_is_user_ctrl=32
|
||||
} fluid_LADSPA_nodeflags;
|
||||
|
||||
/* fluid_LADSPA_Node_t
|
||||
/* fluid_LADSPA_Node_t
|
||||
* An internal node of the Fx unit.
|
||||
* 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).
|
||||
@@ -107,11 +107,11 @@ typedef struct {
|
||||
int NumberLibs;
|
||||
void * ppvPluginLibs[FLUID_LADSPA_MaxLibs];
|
||||
char * ppvPluginLibNames[FLUID_LADSPA_MaxLibs];
|
||||
|
||||
|
||||
/*List of plugins (descriptor and instance)
|
||||
* 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.
|
||||
*/
|
||||
*/
|
||||
int NumberPlugins;
|
||||
const LADSPA_Descriptor * PluginDescriptorTable[FLUID_LADSPA_MaxPlugins];
|
||||
LADSPA_Handle * PluginInstanceTable[FLUID_LADSPA_MaxPlugins];
|
||||
@@ -119,12 +119,12 @@ typedef struct {
|
||||
/* List of nodes */
|
||||
int NumberNodes;
|
||||
fluid_LADSPA_Node_t * Nodelist[FLUID_LADSPA_MaxNodes];
|
||||
|
||||
|
||||
/* List of Command lines
|
||||
* 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
|
||||
* Those lists are stored in LADSPA_Command_Sequence.
|
||||
* One command line results in one plugin => size MaxPlugins.
|
||||
* ./aw.so alienwah_stereo Input <- Master_L_Synth Output -> Master_R_Synth Parameter <- #42.0
|
||||
* Those lists are stored in LADSPA_Command_Sequence.
|
||||
* One command line results in one plugin => size MaxPlugins.
|
||||
*/
|
||||
int NumberCommands;
|
||||
char ** LADSPA_Command_Sequence[FLUID_LADSPA_MaxPlugins];
|
||||
@@ -138,11 +138,11 @@ typedef struct {
|
||||
|
||||
/* Bypass switch
|
||||
* 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.
|
||||
* 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.
|
||||
* '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[]);
|
||||
|
||||
/* Purpose:
|
||||
* Returns the node belonging to Name or NULL, if not found
|
||||
/* Purpose:
|
||||
* 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);
|
||||
|
||||
/* Purpose:
|
||||
* Creates a new node with the given characteristics.
|
||||
/* Purpose:
|
||||
* Creates a new node with the given characteristics.
|
||||
*/
|
||||
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
|
||||
* Those functions are called from fluid_cmd, when a command is entered on the command line.
|
||||
* fluid_handle_LADSPA_XXX
|
||||
* Those functions are called from fluid_cmd, when a command is entered on the command line.
|
||||
*/
|
||||
|
||||
/* 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);
|
||||
|
||||
/* 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);
|
||||
|
||||
/* 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);
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -73,7 +73,7 @@ fluid_lash_save (fluid_synth_t * synth)
|
||||
fluid_sfont_t * sfont;
|
||||
lash_config_t * config;
|
||||
char num[32];
|
||||
|
||||
|
||||
sfcount = fluid_synth_sfcount (synth);
|
||||
|
||||
config = lash_config_new ();
|
||||
@@ -85,12 +85,12 @@ fluid_lash_save (fluid_synth_t * synth)
|
||||
{
|
||||
sfont = fluid_synth_get_sfont (synth, i);
|
||||
config = lash_config_new ();
|
||||
|
||||
|
||||
sprintf (num, "%d", i);
|
||||
|
||||
|
||||
lash_config_set_key (config, num);
|
||||
lash_config_set_value_string (config, sfont->get_name (sfont));
|
||||
|
||||
|
||||
lash_send_config (fluid_lash_client, config);
|
||||
}
|
||||
}
|
||||
@@ -110,11 +110,11 @@ fluid_lash_run (void * data)
|
||||
int done = 0;
|
||||
int err;
|
||||
int pending_restores = 0;
|
||||
|
||||
|
||||
synth = (fluid_synth_t *) data;
|
||||
|
||||
|
||||
while (!done)
|
||||
{
|
||||
{
|
||||
while ( (event = lash_get_event (fluid_lash_client)) )
|
||||
{
|
||||
switch (lash_event_get_type (event))
|
||||
@@ -144,7 +144,7 @@ fluid_lash_run (void * data)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
while ( (config = lash_get_config (fluid_lash_client)) )
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
usleep (10000);
|
||||
}
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -200,7 +200,7 @@ fluid_lash_save (fluid_synth_t * synth)
|
||||
fluid_sfont_t * sfont;
|
||||
cca_config_t * config;
|
||||
char num[32];
|
||||
|
||||
|
||||
sfcount = fluid_synth_sfcount (synth);
|
||||
|
||||
config = cca_config_new ();
|
||||
@@ -212,12 +212,12 @@ fluid_lash_save (fluid_synth_t * synth)
|
||||
{
|
||||
sfont = fluid_synth_get_sfont (synth, i);
|
||||
config = cca_config_new ();
|
||||
|
||||
|
||||
sprintf (num, "%d", i);
|
||||
|
||||
|
||||
cca_config_set_key (config, num);
|
||||
cca_config_set_value_string (config, sfont->get_name (sfont));
|
||||
|
||||
|
||||
cca_send_config (fluid_lash_client, config);
|
||||
}
|
||||
}
|
||||
@@ -238,9 +238,9 @@ fluid_lash_run (void * data)
|
||||
int done = 0;
|
||||
int err;
|
||||
int pending_restores = 0;
|
||||
|
||||
|
||||
synth = (fluid_synth_t *) data;
|
||||
|
||||
|
||||
while (!done)
|
||||
{
|
||||
while ( (event = cca_get_event (fluid_lash_client)) )
|
||||
@@ -272,7 +272,7 @@ fluid_lash_run (void * data)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
while ( (config = cca_get_config (fluid_lash_client)) )
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
usleep (10000);
|
||||
}
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,13 +11,15 @@
|
||||
* 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
|
||||
*/
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_LASH) || defined(HAVE_LADCCA)
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
* 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
|
||||
* 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;
|
||||
delete_fluid_list(tmp);
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
prev = tmp;
|
||||
tmp = tmp->next;
|
||||
}
|
||||
@@ -151,15 +151,15 @@ fluid_list_remove_link(fluid_list_t *list, fluid_list_t *link)
|
||||
tmp->next = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
prev = tmp;
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
|
||||
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_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;
|
||||
|
||||
|
||||
return list.next;
|
||||
}
|
||||
|
||||
fluid_list_t*
|
||||
fluid_list_t*
|
||||
fluid_list_sort(fluid_list_t *list, fluid_compare_func_t compare_func)
|
||||
{
|
||||
fluid_list_t *l1, *l2;
|
||||
@@ -192,15 +192,15 @@ fluid_list_sort(fluid_list_t *list, fluid_compare_func_t compare_func)
|
||||
return list;
|
||||
}
|
||||
|
||||
l1 = list;
|
||||
l1 = list;
|
||||
l2 = list->next;
|
||||
|
||||
while ((l2 = l2->next) != NULL) {
|
||||
if ((l2 = l2->next) == NULL)
|
||||
if ((l2 = l2->next) == NULL)
|
||||
break;
|
||||
l1=l1->next;
|
||||
}
|
||||
l2 = l1->next;
|
||||
l2 = l1->next;
|
||||
l1->next = NULL;
|
||||
|
||||
return fluid_list_sort_merge(fluid_list_sort(list, compare_func),
|
||||
@@ -220,7 +220,7 @@ fluid_list_last(fluid_list_t *list)
|
||||
return list;
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
fluid_list_size(fluid_list_t *list)
|
||||
{
|
||||
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;
|
||||
|
||||
if (prev) {
|
||||
prev->next = new_list;
|
||||
prev->next = new_list;
|
||||
return list;
|
||||
} else {
|
||||
return new_list;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -25,13 +25,13 @@
|
||||
/* ALSA */
|
||||
#if ALSA_SUPPORT
|
||||
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);
|
||||
int delete_fluid_alsa_rawmidi_driver(fluid_midi_driver_t* p);
|
||||
void fluid_alsa_rawmidi_driver_settings(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);
|
||||
int delete_fluid_alsa_seq_driver(fluid_midi_driver_t* p);
|
||||
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 */
|
||||
#if OSS_SUPPORT
|
||||
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);
|
||||
int delete_fluid_oss_midi_driver(fluid_midi_driver_t* p);
|
||||
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 */
|
||||
#if WINMIDI_SUPPORT
|
||||
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);
|
||||
int delete_fluid_winmidi_driver(fluid_midi_driver_t* p);
|
||||
#endif
|
||||
@@ -57,7 +57,7 @@ int delete_fluid_winmidi_driver(fluid_midi_driver_t* p);
|
||||
/* definitions for the MidiShare driver */
|
||||
#if MIDISHARE_SUPPORT
|
||||
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);
|
||||
int delete_fluid_midishare_midi_driver(fluid_midi_driver_t* p);
|
||||
#endif
|
||||
@@ -69,8 +69,8 @@ int delete_fluid_midishare_midi_driver(fluid_midi_driver_t* p);
|
||||
*/
|
||||
struct fluid_mdriver_definition_t {
|
||||
char* name;
|
||||
fluid_midi_driver_t* (*new)(fluid_settings_t* settings,
|
||||
handle_midi_event_func_t event_handler,
|
||||
fluid_midi_driver_t* (*new)(fluid_settings_t* settings,
|
||||
handle_midi_event_func_t event_handler,
|
||||
void* event_handler_data);
|
||||
int (*free)(fluid_midi_driver_t* p);
|
||||
void (*settings)(fluid_settings_t* settings);
|
||||
@@ -79,31 +79,31 @@ struct fluid_mdriver_definition_t {
|
||||
|
||||
struct fluid_mdriver_definition_t fluid_midi_drivers[] = {
|
||||
#if OSS_SUPPORT
|
||||
{ "oss",
|
||||
new_fluid_oss_midi_driver,
|
||||
delete_fluid_oss_midi_driver,
|
||||
{ "oss",
|
||||
new_fluid_oss_midi_driver,
|
||||
delete_fluid_oss_midi_driver,
|
||||
fluid_oss_midi_driver_settings },
|
||||
#endif
|
||||
#if ALSA_SUPPORT
|
||||
{ "alsa_raw",
|
||||
new_fluid_alsa_rawmidi_driver,
|
||||
delete_fluid_alsa_rawmidi_driver,
|
||||
{ "alsa_raw",
|
||||
new_fluid_alsa_rawmidi_driver,
|
||||
delete_fluid_alsa_rawmidi_driver,
|
||||
fluid_alsa_rawmidi_driver_settings },
|
||||
{ "alsa_seq",
|
||||
new_fluid_alsa_seq_driver,
|
||||
delete_fluid_alsa_seq_driver,
|
||||
{ "alsa_seq",
|
||||
new_fluid_alsa_seq_driver,
|
||||
delete_fluid_alsa_seq_driver,
|
||||
fluid_alsa_seq_driver_settings },
|
||||
#endif
|
||||
#if WINMIDI_SUPPORT
|
||||
{ "winmidi",
|
||||
new_fluid_winmidi_driver,
|
||||
delete_fluid_winmidi_driver,
|
||||
{ "winmidi",
|
||||
new_fluid_winmidi_driver,
|
||||
delete_fluid_winmidi_driver,
|
||||
NULL },
|
||||
#endif
|
||||
#if MIDISHARE_SUPPORT
|
||||
{ "midishare",
|
||||
new_fluid_midishare_midi_driver,
|
||||
delete_fluid_midishare_midi_driver,
|
||||
{ "midishare",
|
||||
new_fluid_midishare_midi_driver,
|
||||
delete_fluid_midishare_midi_driver,
|
||||
NULL },
|
||||
#endif
|
||||
{ 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)
|
||||
{
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Set the default driver */
|
||||
@@ -147,11 +147,18 @@ void fluid_midi_driver_settings(fluid_settings_t* settings)
|
||||
if (fluid_midi_drivers[i].settings != NULL) {
|
||||
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)
|
||||
{
|
||||
int i;
|
||||
@@ -171,6 +178,10 @@ fluid_midi_driver_t* new_fluid_midi_driver(fluid_settings_t* settings, handle_mi
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a MIDI driver instance.
|
||||
* @param driver MIDI driver to delete
|
||||
*/
|
||||
void delete_fluid_midi_driver(fluid_midi_driver_t* driver)
|
||||
{
|
||||
int i;
|
||||
@@ -180,5 +191,5 @@ void delete_fluid_midi_driver(fluid_midi_driver_t* driver)
|
||||
fluid_midi_drivers[i].free(driver);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -30,7 +30,7 @@ void fluid_midi_driver_settings(fluid_settings_t* settings);
|
||||
* fluid_midi_driver_t
|
||||
*/
|
||||
|
||||
struct _fluid_midi_driver_t
|
||||
struct _fluid_midi_driver_t
|
||||
{
|
||||
char* name;
|
||||
handle_midi_event_func_t handler;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -55,8 +55,12 @@ static int remains_80e0[] = {
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
@@ -76,7 +80,7 @@ fluid_midi_file* new_fluid_midi_file(char* filename)
|
||||
if (mf->fp == NULL) {
|
||||
FLUID_LOG(FLUID_ERR, "Couldn't open the MIDI file");
|
||||
FLUID_FREE(mf);
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fluid_midi_file_read_mthd(mf) != FLUID_OK) {
|
||||
@@ -86,8 +90,10 @@ fluid_midi_file* new_fluid_midi_file(char* filename)
|
||||
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)
|
||||
{
|
||||
@@ -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)
|
||||
{
|
||||
@@ -150,7 +156,7 @@ int fluid_midi_file_skip(fluid_midi_file* mf, int skip)
|
||||
int err = FLUID_FSEEK(mf->fp, skip, SEEK_CUR);
|
||||
if (err) {
|
||||
FLUID_LOG(FLUID_ERR, "Failed to seek position in file");
|
||||
return FLUID_FAILED;
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
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)) {
|
||||
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
|
||||
*/
|
||||
int fluid_midi_file_read_varlen(fluid_midi_file* mf)
|
||||
{
|
||||
{
|
||||
int i;
|
||||
int c;
|
||||
mf->varlen = 0;
|
||||
@@ -338,7 +344,7 @@ int fluid_midi_file_read_varlen(fluid_midi_file* mf)
|
||||
} else {
|
||||
mf->varlen += c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
status = mf->running_status;
|
||||
}
|
||||
}
|
||||
|
||||
/* check what message we have */
|
||||
if (status & 0x80) {
|
||||
@@ -426,7 +432,7 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track)
|
||||
}
|
||||
|
||||
return FLUID_OK;
|
||||
|
||||
|
||||
} else if (status == MIDI_META_EVENT) { /* meta events */
|
||||
|
||||
int result = FLUID_OK;
|
||||
@@ -498,7 +504,7 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track)
|
||||
break;
|
||||
}
|
||||
mf->eot = 1;
|
||||
break;
|
||||
break;
|
||||
|
||||
case MIDI_SET_TEMPO:
|
||||
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->param2 = 0;
|
||||
fluid_track_add_event(track, evt);
|
||||
break;
|
||||
break;
|
||||
|
||||
case MIDI_SMPTE_OFFSET:
|
||||
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;
|
||||
break;
|
||||
}
|
||||
break; /* we don't use smtp */
|
||||
break; /* we don't use smtp */
|
||||
|
||||
case MIDI_TIME_SIGNATURE:
|
||||
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];
|
||||
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);
|
||||
|
||||
break;
|
||||
@@ -568,7 +574,7 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track)
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
|
||||
} else { /* channel messages */
|
||||
|
||||
type = status & 0xf0;
|
||||
@@ -589,7 +595,7 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track)
|
||||
}
|
||||
break;
|
||||
|
||||
case NOTE_OFF:
|
||||
case NOTE_OFF:
|
||||
if ((param2 = fluid_midi_file_getc(mf)) < 0) {
|
||||
FLUID_LOG(FLUID_ERR, "Unexpected end of file");
|
||||
return FLUID_FAILED;
|
||||
@@ -629,7 +635,7 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track)
|
||||
default:
|
||||
/* Can't possibly happen !? */
|
||||
FLUID_LOG(FLUID_ERR, "Unrecognized MIDI event");
|
||||
return FLUID_FAILED;
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
evt = new_fluid_midi_event();
|
||||
if (evt == NULL) {
|
||||
@@ -660,8 +666,9 @@ int fluid_midi_file_get_division(fluid_midi_file* midifile)
|
||||
* 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()
|
||||
{
|
||||
@@ -680,8 +687,10 @@ fluid_midi_event_t* new_fluid_midi_event()
|
||||
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)
|
||||
{
|
||||
@@ -696,16 +705,23 @@ int delete_fluid_midi_event(fluid_midi_event_t* evt)
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
@@ -713,16 +729,21 @@ int fluid_midi_event_set_type(fluid_midi_event_t* evt, int type)
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
@@ -730,16 +751,21 @@ int fluid_midi_event_set_channel(fluid_midi_event_t* evt, int chan)
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
@@ -747,16 +773,21 @@ int fluid_midi_event_set_key(fluid_midi_event_t* evt, int v)
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
@@ -764,16 +795,21 @@ int fluid_midi_event_set_velocity(fluid_midi_event_t* evt, int v)
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
@@ -781,16 +817,21 @@ int fluid_midi_event_set_control(fluid_midi_event_t* evt, int v)
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
@@ -798,22 +839,44 @@ int fluid_midi_event_set_value(fluid_midi_event_t* evt, int v)
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
evt->param1 = val;
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
evt->param1 = val;
|
||||
@@ -904,7 +967,7 @@ int fluid_track_set_name(fluid_track_t* track, char* name)
|
||||
}
|
||||
if (name == NULL) {
|
||||
track->name = NULL;
|
||||
return FLUID_OK;
|
||||
return FLUID_OK;
|
||||
}
|
||||
len = FLUID_STRLEN(name);
|
||||
track->name = FLUID_MALLOC(len + 1);
|
||||
@@ -913,7 +976,7 @@ int fluid_track_set_name(fluid_track_t* track, char* name)
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
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
|
||||
*/
|
||||
int
|
||||
int
|
||||
fluid_track_reset(fluid_track_t* track)
|
||||
{
|
||||
track->ticks = 0;
|
||||
@@ -1006,8 +1069,8 @@ fluid_track_reset(fluid_track_t* track)
|
||||
/*
|
||||
* fluid_track_send_events
|
||||
*/
|
||||
int
|
||||
fluid_track_send_events(fluid_track_t* track,
|
||||
int
|
||||
fluid_track_send_events(fluid_track_t* track,
|
||||
fluid_synth_t* synth,
|
||||
fluid_player_t* player,
|
||||
unsigned int ticks)
|
||||
@@ -1046,8 +1109,11 @@ fluid_track_send_events(fluid_track_t* track,
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
@@ -1075,8 +1141,10 @@ fluid_player_t* new_fluid_player(fluid_synth_t* synth)
|
||||
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)
|
||||
{
|
||||
@@ -1157,7 +1225,7 @@ int fluid_player_load(fluid_player_t* player, char *filename)
|
||||
{
|
||||
fluid_midi_file* midifile;
|
||||
|
||||
midifile = new_fluid_midi_file(filename);
|
||||
midifile = new_fluid_midi_file(filename);
|
||||
if (midifile == NULL) {
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
@@ -1169,7 +1237,7 @@ int fluid_player_load(fluid_player_t* player, char *filename)
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
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_ticks = (player->start_ticks +
|
||||
player->cur_ticks = (player->start_ticks +
|
||||
(int) ((double) (player->cur_msec - player->start_msec) / player->deltatime));
|
||||
|
||||
|
||||
for (i = 0; i < player->ntracks; i++) {
|
||||
if (!fluid_track_eot(player->track[i])) {
|
||||
status = FLUID_PLAYER_PLAYING;
|
||||
@@ -1232,30 +1300,32 @@ int fluid_player_callback(void* data, unsigned int msec)
|
||||
player->status = status;
|
||||
|
||||
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);
|
||||
player->current_file = NULL;
|
||||
player->current_file = NULL;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (player->status == FLUID_PLAYER_PLAYING) {
|
||||
return FLUID_OK;
|
||||
}
|
||||
|
||||
|
||||
if (player->playlist == NULL) {
|
||||
return FLUID_OK;
|
||||
}
|
||||
|
||||
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);
|
||||
if (player->timer == NULL) {
|
||||
return FLUID_FAILED;
|
||||
@@ -1263,8 +1333,10 @@ int fluid_player_play(fluid_player_t* player)
|
||||
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)
|
||||
{
|
||||
@@ -1276,8 +1348,13 @@ int fluid_player_stop(fluid_player_t* player)
|
||||
return FLUID_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* fluid_player_set_loop
|
||||
/* FIXME - Looping seems to not actually be implemented? */
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
@@ -1285,8 +1362,12 @@ int fluid_player_set_loop(fluid_player_t* player, int loop)
|
||||
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)
|
||||
{
|
||||
@@ -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->start_msec = player->cur_msec;
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
@@ -1360,10 +1447,10 @@ fluid_midi_event_t* fluid_midi_parser_parse(fluid_midi_parser_t* parser, unsigne
|
||||
/* 'Process' system real-time messages */
|
||||
/*********************************************************************/
|
||||
/* 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
|
||||
* Note: Real-time does not affect (running) status.
|
||||
*/
|
||||
*/
|
||||
if (c >= 0xF8){
|
||||
if (c == MIDI_SYSTEM_RESET){
|
||||
parser->event.type = c;
|
||||
@@ -1372,23 +1459,23 @@ fluid_midi_event_t* fluid_midi_parser_parse(fluid_midi_parser_t* parser, unsigne
|
||||
};
|
||||
return NULL;
|
||||
};
|
||||
|
||||
|
||||
/*********************************************************************/
|
||||
/* 'Process' system common messages (again, just skip them) */
|
||||
/*********************************************************************/
|
||||
/* There are no system common messages that are of interest here.
|
||||
* System common range: 0xF0 .. 0xF7
|
||||
* System common range: 0xF0 .. 0xF7
|
||||
*/
|
||||
|
||||
if (c > 0xF0){
|
||||
/* MIDI specs say: To ignore a non-real-time message, just discard all data up to
|
||||
* the next status byte.
|
||||
/* MIDI specs say: To ignore a non-real-time message, just discard all data up to
|
||||
* the next status byte.
|
||||
* And our parser will ignore data that is received without a valid status.
|
||||
* Note: system common cancels running status. */
|
||||
parser->status = 0;
|
||||
return NULL;
|
||||
};
|
||||
|
||||
|
||||
/*********************************************************************/
|
||||
/* 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
|
||||
* and start a new event.
|
||||
*/
|
||||
|
||||
|
||||
if (c & 0x80){
|
||||
parser->channel = c & 0x0F;
|
||||
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){
|
||||
return NULL;
|
||||
};
|
||||
|
||||
|
||||
/*********************************************************************/
|
||||
/* Send the event */
|
||||
/*********************************************************************/
|
||||
/* 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
|
||||
* 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.
|
||||
@@ -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. */
|
||||
parser->event.param1 = ((parser->p[1] << 7) | parser->p[0]); /* Note: '|' does here the same as '+' (no common bits), but might be faster */
|
||||
break;
|
||||
default:
|
||||
default:
|
||||
/* Unlikely */
|
||||
return NULL;
|
||||
};
|
||||
return &parser->event;
|
||||
};
|
||||
|
||||
/* Purpose:
|
||||
/* Purpose:
|
||||
* Returns the length of the MIDI message starting with c.
|
||||
* Taken from Nagano Daisuke's USB-MIDI driver */
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -161,14 +161,14 @@ enum midi_meta_event {
|
||||
MIDI_SEQUENCER_EVENT = 0x7f
|
||||
};
|
||||
|
||||
enum fluid_player_status
|
||||
enum fluid_player_status
|
||||
{
|
||||
FLUID_PLAYER_READY,
|
||||
FLUID_PLAYER_PLAYING,
|
||||
FLUID_PLAYER_DONE
|
||||
};
|
||||
|
||||
enum fluid_driver_status
|
||||
enum fluid_driver_status
|
||||
{
|
||||
FLUID_MIDI_READY,
|
||||
FLUID_MIDI_LISTENING,
|
||||
@@ -181,7 +181,7 @@ enum fluid_driver_status
|
||||
*/
|
||||
|
||||
/* 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_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_player_t* player,
|
||||
unsigned int ticks);
|
||||
@@ -273,7 +273,7 @@ typedef struct {
|
||||
int uses_smpte;
|
||||
unsigned int smpte_fps;
|
||||
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) */
|
||||
double tempo; /* Beats per second (SI rules =) */
|
||||
int tracklen;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -26,21 +26,29 @@
|
||||
#include "fluid_synth.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)
|
||||
{
|
||||
fluid_midi_router_t* router=NULL;
|
||||
fluid_midi_router_rule_t* rule=NULL;;
|
||||
fluid_midi_router_rule_t* rule=NULL;
|
||||
|
||||
/* create the router */
|
||||
router = FLUID_NEW(fluid_midi_router_t); if (router == NULL){
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
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.
|
||||
*/
|
||||
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_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,
|
||||
* and route them unchanged ("result=par*1.0+0") */
|
||||
|
||||
if (fluid_midi_router_create_default_rules(router) != FLUID_OK) goto error_recovery;
|
||||
|
||||
|
||||
return router;
|
||||
|
||||
error_recovery:
|
||||
@@ -68,10 +76,12 @@ new_fluid_midi_router(fluid_settings_t* settings, handle_midi_event_func_t handl
|
||||
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)
|
||||
{
|
||||
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)
|
||||
* Purpose:
|
||||
* Purpose:
|
||||
* Frees the used memory. This is used only for shutdown!
|
||||
*/
|
||||
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
|
||||
*/
|
||||
int
|
||||
int
|
||||
delete_fluid_midi_router_rule(fluid_midi_router_rule_t* 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];
|
||||
int i;
|
||||
|
||||
|
||||
rules[0]=&router->note_rules;
|
||||
rules[1]=&router->cc_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);
|
||||
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
|
||||
* via the 'physical' midi input. Each event can trigger an arbitrary number
|
||||
* of generated events.
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*
|
||||
* 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),
|
||||
* - 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
|
||||
@@ -258,7 +272,7 @@ int fluid_midi_router_end(fluid_midi_router_t* router){
|
||||
* - get rid of aftertouch
|
||||
* - ...
|
||||
*/
|
||||
int
|
||||
int
|
||||
fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event)
|
||||
{
|
||||
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) {
|
||||
/* Channel: 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->param2=127;
|
||||
};
|
||||
|
||||
|
||||
/* Lock the rules table, so that for example the shell thread doesn't
|
||||
* clear the rules we are just working with */
|
||||
fluid_mutex_lock(router->ruletables_mutex);
|
||||
@@ -324,26 +338,26 @@ fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* At this point 'rule' contains the first rule in a linked list.
|
||||
* Check for all rules, whether channel and parameter ranges match.
|
||||
*/
|
||||
|
||||
|
||||
while (rule){
|
||||
int chan; /* Channel 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_par2=(int)event->param2;
|
||||
fluid_midi_event_t new_event;
|
||||
|
||||
|
||||
/* Store the pointer to the next rule right now. If the rule is later flagged for destruction,
|
||||
* it may not be accessed anymore.
|
||||
*/
|
||||
next_rule=rule->next;
|
||||
|
||||
/* 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,
|
||||
/* 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,
|
||||
* which calls us here, has raised priority.*/
|
||||
if (rule->state == MIDIRULE_DONE){
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* Par 2 window (only applies to event types, which have 2 pars)
|
||||
* For noteoff events, velocity switching doesn't make any sense.
|
||||
* Velocity scaling might be useful, though.
|
||||
*/
|
||||
*/
|
||||
if (event_has_par2 && event->type != NOTE_OFF){
|
||||
if (rule->par2_min > rule->par2_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
|
||||
* 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.
|
||||
*/
|
||||
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){
|
||||
par2=(int)((fluid_real_t)event_par2 * (fluid_real_t)rule->par2_mul + (fluid_real_t)rule->par2_add + 0.5);
|
||||
};
|
||||
|
||||
|
||||
/* Channel range limiting */
|
||||
if (chan < 0){
|
||||
chan=0;
|
||||
@@ -437,7 +451,7 @@ fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event)
|
||||
*/
|
||||
|
||||
if (
|
||||
event->type == NOTE_ON
|
||||
event->type == NOTE_ON
|
||||
|| (event->type == CONTROL_CHANGE && par1 == SUSTAIN_SWITCH && par2 >= 64)
|
||||
){
|
||||
/* 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++;
|
||||
};
|
||||
} else if (
|
||||
event->type == NOTE_OFF
|
||||
event->type == NOTE_OFF
|
||||
|| (event->type == CONTROL_CHANGE && par1 == SUSTAIN_SWITCH && par2 < 64)
|
||||
){
|
||||
/* 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.
|
||||
* Change its state to 'unused', it will be cleared up at the next
|
||||
* 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;
|
||||
};
|
||||
@@ -477,9 +491,9 @@ fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event)
|
||||
goto do_next_rule;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/* 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);
|
||||
@@ -516,8 +530,8 @@ int fluid_midi_router_handle_clear(fluid_synth_t* synth, int ac, char** av, flui
|
||||
if (ac != 0) {
|
||||
fluid_ostream_printf(out, "router_clear needs no arguments.\n");
|
||||
goto error_recovery;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Disable rules and mark for destruction */
|
||||
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) {
|
||||
fluid_ostream_printf(out, "router_default needs no arguments.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Disable rules and mark for destruction */
|
||||
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");
|
||||
goto error_recovery;
|
||||
}
|
||||
|
||||
|
||||
if (FLUID_STRCMP(av[0],"note") == 0){
|
||||
dest=& router->note_rules;
|
||||
} 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){
|
||||
dest=& router->key_pressure_rules;
|
||||
};
|
||||
|
||||
|
||||
if (dest == NULL){
|
||||
fluid_ostream_printf(out, "router_begin args: note, cc, prog, pbend, cpress, kpress\n");
|
||||
goto error_recovery;
|
||||
};
|
||||
|
||||
|
||||
if (fluid_midi_router_begin(router, dest) != FLUID_OK){
|
||||
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){
|
||||
FLUID_LOG(FLUID_ERR, "midi_router_end failed");
|
||||
goto error_recovery;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
/* Free unused rules (give it a try) */
|
||||
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]);
|
||||
|
||||
/* Free unused rules (give it a try) */
|
||||
fluid_midi_router_free_unused_rules(router);
|
||||
fluid_midi_router_free_unused_rules(router);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -760,23 +774,23 @@ void fluid_midi_router_free_unused_rules(fluid_midi_router_t* router)
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
|
||||
while (*p){
|
||||
fluid_midi_router_rule_t* current_rule=*p;
|
||||
fluid_midi_router_rule_t* next_rule=current_rule->next;
|
||||
|
||||
|
||||
if (current_rule->state == MIDIRULE_DONE){
|
||||
/* p points to current_rule.
|
||||
* current_rule->next points to next_rule.
|
||||
* Unlink current_rule from the chain by setting the content
|
||||
* of p to next_rule.
|
||||
*/
|
||||
|
||||
|
||||
*p=next_rule;
|
||||
|
||||
|
||||
/* Now the rule is not in the chain anymore. Destroy it. */
|
||||
delete_fluid_midi_router_rule(current_rule);
|
||||
|
||||
|
||||
} else {
|
||||
/* We have to keep the rule, there is still unfinished business. */
|
||||
p = ¤t_rule->next;
|
||||
@@ -785,48 +799,44 @@ void fluid_midi_router_free_unused_rules(fluid_midi_router_t* router)
|
||||
fluid_mutex_unlock(router->ruletables_mutex);
|
||||
};
|
||||
};
|
||||
|
||||
/* Purpose:
|
||||
* This function demonstrates, how to access incoming MIDI messages.
|
||||
* It prints a message to stdout (which can be used to hook up an external user interface),
|
||||
* and hands the event on to the MIDI router.
|
||||
* It is not a part of the MIDI router, but an added link in the MIDI chain.
|
||||
|
||||
/**
|
||||
* MIDI event callback function to display event information to stdout
|
||||
* @param data MIDI router instance
|
||||
* @param event MIDI event data
|
||||
* @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)
|
||||
{
|
||||
{
|
||||
switch (event->type) {
|
||||
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);
|
||||
fflush(stdout);
|
||||
break;
|
||||
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);
|
||||
fflush(stdout);
|
||||
break;
|
||||
break;
|
||||
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);
|
||||
fflush(stdout);
|
||||
break;
|
||||
case PROGRAM_CHANGE:
|
||||
fprintf(stdout, "event_pre_prog %i %i\n", event->channel, event->param1);
|
||||
fflush(stdout);
|
||||
fprintf(stdout, "event_pre_prog %i %i\n", event->channel, event->param1);
|
||||
break;
|
||||
case PITCH_BEND:
|
||||
fprintf(stdout, "event_pre_pitch %i %i\n", event->channel, event->param1);
|
||||
fflush(stdout);
|
||||
fprintf(stdout, "event_pre_pitch %i %i\n", event->channel, event->param1);
|
||||
break;
|
||||
case CHANNEL_PRESSURE:
|
||||
fprintf(stdout, "event_pre_cpress %i %i\n", event->channel, event->param1);
|
||||
fflush(stdout);
|
||||
break;
|
||||
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);
|
||||
fflush(stdout);
|
||||
break;
|
||||
default:
|
||||
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);
|
||||
};
|
||||
|
||||
/* Purpose:
|
||||
* This function demonstrates, how to access MIDI messages going from the MIDI
|
||||
* router to the synth.
|
||||
* Again, it prints a message to stdout and hands the event on to the synth.
|
||||
* It is not a part of the MIDI router, but an added link in the MIDI chain.
|
||||
/**
|
||||
* MIDI event callback function to display event information to stdout
|
||||
* @param data MIDI router instance
|
||||
* @param event MIDI event data
|
||||
* @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)
|
||||
{
|
||||
switch (event->type) {
|
||||
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);
|
||||
fflush(stdout);
|
||||
break;
|
||||
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);
|
||||
fflush(stdout);
|
||||
break;
|
||||
break;
|
||||
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);
|
||||
fflush(stdout);
|
||||
break;
|
||||
case PROGRAM_CHANGE:
|
||||
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);
|
||||
break;
|
||||
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);
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -79,7 +79,7 @@ struct _fluid_midi_router_t {
|
||||
void* event_handler_data; /* One arg for the callback */
|
||||
|
||||
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 {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -25,56 +25,56 @@
|
||||
/*
|
||||
* fluid_mod_clone
|
||||
*/
|
||||
void
|
||||
void
|
||||
fluid_mod_clone(fluid_mod_t* mod, fluid_mod_t* src)
|
||||
{
|
||||
mod->dest = src->dest;
|
||||
mod->src1 = src->src1;
|
||||
mod->flags1 = src->flags1;
|
||||
mod->src2 = src->src2;
|
||||
mod->flags2 = src->flags2;
|
||||
mod->amount = src->amount;
|
||||
mod->src1 = src->src1;
|
||||
mod->flags1 = src->flags1;
|
||||
mod->src2 = src->src2;
|
||||
mod->flags2 = src->flags2;
|
||||
mod->amount = src->amount;
|
||||
}
|
||||
|
||||
/*
|
||||
* fluid_mod_set_source1
|
||||
*/
|
||||
void
|
||||
void
|
||||
fluid_mod_set_source1(fluid_mod_t* mod, int src, int flags)
|
||||
{
|
||||
mod->src1 = src;
|
||||
mod->flags1 = flags;
|
||||
mod->src1 = src;
|
||||
mod->flags1 = flags;
|
||||
}
|
||||
|
||||
/*
|
||||
* fluid_mod_set_source2
|
||||
*/
|
||||
void
|
||||
void
|
||||
fluid_mod_set_source2(fluid_mod_t* mod, int src, int flags)
|
||||
{
|
||||
mod->src2 = src;
|
||||
mod->flags2 = flags;
|
||||
mod->src2 = src;
|
||||
mod->flags2 = flags;
|
||||
}
|
||||
|
||||
/*
|
||||
* fluid_mod_set_dest
|
||||
*/
|
||||
void
|
||||
void
|
||||
fluid_mod_set_dest(fluid_mod_t* mod, int dest)
|
||||
{
|
||||
mod->dest = dest;
|
||||
mod->dest = dest;
|
||||
}
|
||||
|
||||
/*
|
||||
* fluid_mod_set_amount
|
||||
*/
|
||||
void
|
||||
void
|
||||
fluid_mod_set_amount(fluid_mod_t* mod, 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;
|
||||
}
|
||||
@@ -108,7 +108,7 @@ double fluid_mod_get_amount(fluid_mod_t* mod)
|
||||
/*
|
||||
* 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_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) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
|
||||
/* 'special treatment' for default controller
|
||||
*
|
||||
*
|
||||
* Reference: SF2.01 section 8.4.2
|
||||
*
|
||||
* 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).
|
||||
* */
|
||||
if ((mod->src2 == FLUID_MOD_VELOCITY) &&
|
||||
(mod->src1 == FLUID_MOD_VELOCITY) &&
|
||||
(mod->flags1 == (FLUID_MOD_GC | FLUID_MOD_UNIPOLAR
|
||||
(mod->src1 == FLUID_MOD_VELOCITY) &&
|
||||
(mod->flags1 == (FLUID_MOD_GC | FLUID_MOD_UNIPOLAR
|
||||
| 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)) &&
|
||||
(mod->dest == GEN_FILTERFC)) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* get the initial value of the first source */
|
||||
if (mod->src1 > 0) {
|
||||
if (mod->flags1 & FLUID_MOD_CC) {
|
||||
v1 = fluid_channel_get_cc(chan, mod->src1);
|
||||
} else { /* source 1 is one of the direct controllers */
|
||||
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;
|
||||
break;
|
||||
case FLUID_MOD_VELOCITY:
|
||||
case FLUID_MOD_VELOCITY:
|
||||
v1 = voice->vel;
|
||||
break;
|
||||
case FLUID_MOD_KEY:
|
||||
case FLUID_MOD_KEY:
|
||||
v1 = voice->key;
|
||||
break;
|
||||
case FLUID_MOD_KEYPRESSURE:
|
||||
case FLUID_MOD_KEYPRESSURE:
|
||||
v1 = chan->key_pressure;
|
||||
break;
|
||||
case FLUID_MOD_CHANNELPRESSURE:
|
||||
v1 = chan->channel_pressure;
|
||||
case FLUID_MOD_CHANNELPRESSURE:
|
||||
v1 = chan->channel_pressure;
|
||||
break;
|
||||
case FLUID_MOD_PITCHWHEEL:
|
||||
case FLUID_MOD_PITCHWHEEL:
|
||||
v1 = chan->pitch_bend;
|
||||
range1 = 0x4000;
|
||||
break;
|
||||
case FLUID_MOD_PITCHWHEELSENS:
|
||||
case FLUID_MOD_PITCHWHEELSENS:
|
||||
v1 = chan->pitch_wheel_sensitivity;
|
||||
break;
|
||||
default:
|
||||
v1 = 0.0;
|
||||
default:
|
||||
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;
|
||||
break;
|
||||
case 1: /* linear, unipolar, negative */
|
||||
v1 = 1.0f - v1 / range1;
|
||||
v1 = 1.0f - v1 / range1;
|
||||
break;
|
||||
case 2: /* linear, bipolar, positive */
|
||||
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);
|
||||
} else {
|
||||
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;
|
||||
break;
|
||||
case FLUID_MOD_VELOCITY:
|
||||
case FLUID_MOD_VELOCITY:
|
||||
v2 = voice->vel;
|
||||
break;
|
||||
case FLUID_MOD_KEY:
|
||||
case FLUID_MOD_KEY:
|
||||
v2 = voice->key;
|
||||
break;
|
||||
case FLUID_MOD_KEYPRESSURE:
|
||||
case FLUID_MOD_KEYPRESSURE:
|
||||
v2 = chan->key_pressure;
|
||||
break;
|
||||
case FLUID_MOD_CHANNELPRESSURE:
|
||||
v2 = chan->channel_pressure;
|
||||
case FLUID_MOD_CHANNELPRESSURE:
|
||||
v2 = chan->channel_pressure;
|
||||
break;
|
||||
case FLUID_MOD_PITCHWHEEL:
|
||||
case FLUID_MOD_PITCHWHEEL:
|
||||
v2 = chan->pitch_bend;
|
||||
break;
|
||||
case FLUID_MOD_PITCHWHEELSENS:
|
||||
case FLUID_MOD_PITCHWHEELSENS:
|
||||
v2 = chan->pitch_wheel_sensitivity;
|
||||
break;
|
||||
default:
|
||||
v1 = 0.0f;
|
||||
default:
|
||||
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;
|
||||
break;
|
||||
case 1: /* linear, unipolar, negative */
|
||||
v2 = 1.0f - v2 / range2;
|
||||
v2 = 1.0f - v2 / range2;
|
||||
break;
|
||||
case 2: /* linear, bipolar, positive */
|
||||
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_t*
|
||||
fluid_mod_t*
|
||||
fluid_mod_new()
|
||||
{
|
||||
fluid_mod_t* mod = FLUID_NEW(fluid_mod_t);
|
||||
if (mod == NULL) {
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
return NULL;
|
||||
}
|
||||
return mod;
|
||||
@@ -362,7 +362,7 @@ fluid_mod_delete(fluid_mod_t * mod)
|
||||
|
||||
/*
|
||||
* fluid_mod_test_identity
|
||||
*/
|
||||
*/
|
||||
/* Purpose:
|
||||
* Checks, if two modulators are 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 flags2=mod->flags2;
|
||||
fluid_real_t amount=(fluid_real_t)mod->amount;
|
||||
|
||||
|
||||
printf("Src: ");
|
||||
if (flags1 & FLUID_MOD_CC){
|
||||
printf("MIDI CC=%i",src1);
|
||||
@@ -408,8 +408,8 @@ void fluid_dump_modulator(fluid_mod_t * mod){
|
||||
printf("(unknown: %i)", src1);
|
||||
}; /* switch src1 */
|
||||
}; /* if not CC */
|
||||
if (flags1 & FLUID_MOD_NEGATIVE){printf("- ");} else {printf("+ ");};
|
||||
if (flags1 & FLUID_MOD_BIPOLAR){printf("bip ");} else {printf("unip ");};
|
||||
if (flags1 & FLUID_MOD_NEGATIVE){printf("- ");} else {printf("+ ");};
|
||||
if (flags1 & FLUID_MOD_BIPOLAR){printf("bip ");} else {printf("unip ");};
|
||||
printf("-> ");
|
||||
switch(dest){
|
||||
case GEN_FILTERQ: printf("Q"); break;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -25,7 +25,7 @@
|
||||
#include "fluid_conv.h"
|
||||
|
||||
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);
|
||||
|
||||
#define fluid_mod_has_source(mod,cc,ctrl) \
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -37,141 +37,81 @@
|
||||
|
||||
#define FLUID_FRACT_MAX ((double)4294967296.0)
|
||||
|
||||
/* fluid_phase_t
|
||||
/* fluid_phase_t
|
||||
* Purpose:
|
||||
* Playing pointer for voice playback
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
* 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.
|
||||
* 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 {
|
||||
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;
|
||||
typedef unsigned long long fluid_phase_t;
|
||||
|
||||
/* Purpose:
|
||||
* Set a to b.
|
||||
* a: fluid_phase_t
|
||||
* b: fluid_phase_t
|
||||
*/
|
||||
#ifdef USE_LONGLONG
|
||||
#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) { \
|
||||
(a).b32.index = (sint32) (b); \
|
||||
(a).b32.fract = 0; \
|
||||
}
|
||||
#define fluid_phase_set_int(a, b) ((a) = ((unsigned long long)(b)) << 32)
|
||||
|
||||
/* Purpose:
|
||||
* 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
|
||||
* the playing pointer will advance it by 0.9 samples. */
|
||||
#define fluid_phase_set_float(a, b) { \
|
||||
(a).b32.index = (sint32) (b); \
|
||||
(a).b32.fract = (uint32) (((double)(b) - (double)((a).b32.index)) * (double)FLUID_FRACT_MAX); \
|
||||
}
|
||||
#define fluid_phase_set_float(a, b) \
|
||||
(a) = (((unsigned long long)(b)) << 32) \
|
||||
| (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:
|
||||
* Return the index and the fractional part, respectively. */
|
||||
#define fluid_phase_index(_x) \
|
||||
((int)(_x).b32.index)
|
||||
((unsigned int)((_x) >> 32))
|
||||
#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:
|
||||
* Takes the fractional part of the argument phase and
|
||||
* calculates the corresponding position in the interpolation table.
|
||||
* 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...
|
||||
*/
|
||||
#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) \
|
||||
((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:
|
||||
* Advance a by a step of b (both are fluid_phase_t).
|
||||
*/
|
||||
#ifdef USE_LONGLONG
|
||||
#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
|
||||
#define fluid_phase_incr(a, b) a += b
|
||||
|
||||
/* Purpose:
|
||||
* Subtract b from a (both are fluid_phase_t).
|
||||
*/
|
||||
#ifdef USE_LONGLONG
|
||||
#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
|
||||
#define fluid_phase_decr(a, b) a -= b
|
||||
|
||||
/* Purpose:
|
||||
* Subtract b samples from a.
|
||||
*/
|
||||
#define fluid_phase_sub_int(a, b) { (a).b32.index -= b; }
|
||||
|
||||
#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
|
||||
#define fluid_phase_sub_int(a, b) ((a) -= (unsigned long long)(b) << 32)
|
||||
|
||||
/* Purpose:
|
||||
* The playing pointer is _phase. How many output samples are produced, until the point _p1 in the sample is reached,
|
||||
* if _phase advances in steps of _incr?
|
||||
*/
|
||||
#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)++)
|
||||
* Creates the expression a.index++. */
|
||||
#define fluid_phase_index_plusplus(a) (((a) += 0x100000000LL)
|
||||
|
||||
#endif /* _FLUID_PHASE_H */
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "fluid_ramsfont.h"
|
||||
#include "fluid_sys.h"
|
||||
#include "fluid_synth.h"
|
||||
|
||||
|
||||
/* thenumber of samples before the start and after the end */
|
||||
#define SAMPLE_LOOP_MARGIN 8
|
||||
|
||||
@@ -40,12 +40,12 @@ fluid_ramsfont_create_sfont()
|
||||
{
|
||||
fluid_sfont_t* sfont;
|
||||
fluid_ramsfont_t* ramsfont;
|
||||
|
||||
|
||||
ramsfont = new_fluid_ramsfont();
|
||||
if (ramsfont == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
sfont = FLUID_NEW(fluid_sfont_t);
|
||||
if (sfont == NULL) {
|
||||
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)
|
||||
{
|
||||
FLUID_FREE(preset);
|
||||
printf("TODO: free modulators\n");
|
||||
|
||||
/* TODO: free modulators */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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
|
||||
@@ -214,7 +216,7 @@ int delete_fluid_ramsfont(fluid_ramsfont_t* sfont)
|
||||
delete_fluid_rampreset(preset);
|
||||
preset = sfont->preset;
|
||||
}
|
||||
|
||||
|
||||
FLUID_FREE(sfont);
|
||||
return FLUID_OK;
|
||||
}
|
||||
@@ -242,7 +244,7 @@ fluid_ramsfont_set_name(fluid_ramsfont_t* sfont, char * name)
|
||||
*
|
||||
* 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;
|
||||
if (sfont->preset == NULL) {
|
||||
@@ -253,7 +255,7 @@ int fluid_ramsfont_add_preset(fluid_ramsfont_t* sfont, fluid_rampreset_t* preset
|
||||
cur = sfont->preset;
|
||||
prev = NULL;
|
||||
while (cur != NULL) {
|
||||
if ((preset->bank < cur->bank)
|
||||
if ((preset->bank < cur->bank)
|
||||
|| ((preset->bank == cur->bank) && (preset->num < cur->num))) {
|
||||
if (prev == NULL) {
|
||||
preset->next = cur;
|
||||
@@ -285,7 +287,7 @@ int fluid_ramsfont_add_izone(fluid_ramsfont_t* sfont,
|
||||
- add the sample to the list of samples
|
||||
*/
|
||||
int err;
|
||||
|
||||
|
||||
fluid_rampreset_t* preset = fluid_ramsfont_get_preset(sfont, bank, num);
|
||||
if (preset == NULL) {
|
||||
// Create it
|
||||
@@ -293,27 +295,27 @@ int fluid_ramsfont_add_izone(fluid_ramsfont_t* sfont,
|
||||
if (preset == NULL) {
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
|
||||
|
||||
preset->bank = bank;
|
||||
preset->num = num;
|
||||
|
||||
|
||||
err = fluid_rampreset_add_sample(preset, sample, lokey, hikey);
|
||||
if (err != FLUID_OK) {
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
|
||||
|
||||
// sort the preset
|
||||
fluid_ramsfont_add_preset(sfont, preset);
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
|
||||
// just add it
|
||||
err = fluid_rampreset_add_sample(preset, sample, lokey, hikey);
|
||||
if (err != FLUID_OK) {
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sfont->sample = fluid_list_append(sfont->sample, sample);
|
||||
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,
|
||||
unsigned int bank, unsigned int num, fluid_sample_t* sample,
|
||||
int gen_type, float value) {
|
||||
|
||||
|
||||
fluid_rampreset_t* preset = fluid_ramsfont_get_preset(sfont, bank, num);
|
||||
if (preset == NULL) {
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
|
||||
|
||||
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) {
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
|
||||
|
||||
return fluid_rampreset_izone_set_loop(preset, sample, on, loopstart, loopend);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
while (preset != NULL) {
|
||||
@@ -415,12 +417,12 @@ struct _fluid_rampreset_voice_t {
|
||||
/*
|
||||
* new_fluid_rampreset
|
||||
*/
|
||||
fluid_rampreset_t*
|
||||
fluid_rampreset_t*
|
||||
new_fluid_rampreset(fluid_ramsfont_t* sfont)
|
||||
{
|
||||
fluid_rampreset_t* preset = FLUID_NEW(fluid_rampreset_t);
|
||||
if (preset == NULL) {
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
return NULL;
|
||||
}
|
||||
preset->next = NULL;
|
||||
@@ -437,13 +439,13 @@ new_fluid_rampreset(fluid_ramsfont_t* sfont)
|
||||
/*
|
||||
* delete_fluid_rampreset
|
||||
*/
|
||||
int
|
||||
int
|
||||
delete_fluid_rampreset(fluid_rampreset_t* preset)
|
||||
{
|
||||
int err = FLUID_OK;
|
||||
fluid_preset_zone_t* zone;
|
||||
fluid_rampreset_voice_t *data;
|
||||
|
||||
|
||||
if (preset->global_zone != NULL) {
|
||||
if (delete_fluid_preset_zone(preset->global_zone) != FLUID_OK) {
|
||||
err = FLUID_FAILED;
|
||||
@@ -458,37 +460,37 @@ delete_fluid_rampreset(fluid_rampreset_t* preset)
|
||||
}
|
||||
zone = preset->zone;
|
||||
}
|
||||
|
||||
|
||||
if (preset->presetvoices != NULL) {
|
||||
fluid_list_t *tmp = preset->presetvoices, *next;
|
||||
while (tmp) {
|
||||
data = (fluid_rampreset_voice_t *)(tmp->data);
|
||||
FLUID_FREE(data);
|
||||
|
||||
|
||||
next = tmp->next;
|
||||
FLUID_FREE(tmp);
|
||||
tmp = next;
|
||||
}
|
||||
}
|
||||
preset->presetvoices = NULL;
|
||||
|
||||
|
||||
FLUID_FREE(preset);
|
||||
return err;
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
fluid_rampreset_get_banknum(fluid_rampreset_t* preset)
|
||||
{
|
||||
return preset->bank;
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
fluid_rampreset_get_num(fluid_rampreset_t* preset)
|
||||
{
|
||||
return preset->num;
|
||||
}
|
||||
|
||||
char*
|
||||
char*
|
||||
fluid_rampreset_get_name(fluid_rampreset_t* preset)
|
||||
{
|
||||
return preset->name;
|
||||
@@ -497,7 +499,7 @@ fluid_rampreset_get_name(fluid_rampreset_t* preset)
|
||||
/*
|
||||
* fluid_rampreset_next
|
||||
*/
|
||||
fluid_rampreset_t*
|
||||
fluid_rampreset_t*
|
||||
fluid_rampreset_next(fluid_rampreset_t* preset)
|
||||
{
|
||||
return preset->next;
|
||||
@@ -507,7 +509,7 @@ fluid_rampreset_next(fluid_rampreset_t* preset)
|
||||
/*
|
||||
* fluid_rampreset_add_zone
|
||||
*/
|
||||
int
|
||||
int
|
||||
fluid_rampreset_add_zone(fluid_rampreset_t* preset, fluid_preset_zone_t* zone)
|
||||
{
|
||||
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)
|
||||
{
|
||||
/* create a new instrument zone, with the given sample */
|
||||
|
||||
|
||||
/* one preset zone */
|
||||
if (preset->zone == NULL) {
|
||||
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) {
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
|
||||
|
||||
/* its instrument */
|
||||
zone->inst = (fluid_inst_t*) new_fluid_inst();
|
||||
if (zone->inst == NULL) {
|
||||
delete_fluid_preset_zone(zone);
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
|
||||
|
||||
fluid_rampreset_add_zone(preset, zone);
|
||||
}
|
||||
|
||||
|
||||
/* add an instrument zone for each sample */
|
||||
{
|
||||
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) {
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
|
||||
|
||||
if (fluid_inst_add_zone(inst, izone) != FLUID_OK) {
|
||||
delete_fluid_inst_zone(izone);
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
|
||||
|
||||
izone->sample = sample;
|
||||
izone->keylo = lokey;
|
||||
izone->keyhi = hikey;
|
||||
|
||||
|
||||
// give the preset the name of the sample
|
||||
FLUID_MEMCPY(preset->name, sample->name, 20);
|
||||
}
|
||||
|
||||
|
||||
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_zone_t* izone;
|
||||
|
||||
|
||||
if (preset->zone == NULL) return NULL;
|
||||
|
||||
|
||||
inst = fluid_preset_zone_get_inst(preset->zone);
|
||||
izone = inst->zone;
|
||||
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) {
|
||||
fluid_inst_zone_t* izone = fluid_rampreset_izoneforsample(preset, sample);
|
||||
short coarse, fine;
|
||||
|
||||
|
||||
if (izone == NULL)
|
||||
return FLUID_FAILED;
|
||||
|
||||
|
||||
if (!on) {
|
||||
izone->gen[GEN_SAMPLEMODE].flags = GEN_SET;
|
||||
izone->gen[GEN_SAMPLEMODE].val = FLUID_UNLOOPED;
|
||||
fluid_rampreset_updatevoices(preset, GEN_SAMPLEMODE, FLUID_UNLOOPED);
|
||||
return FLUID_OK;
|
||||
}
|
||||
|
||||
|
||||
/* NOTE : We should check that (sample->startloop + loopStart <= sample->endloop - loopend - 32) */
|
||||
|
||||
/* 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].val = 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
|
||||
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
|
||||
it will be needed (see SAMPLE_LOOP_MARGIN) -- Antoie Schmitt May 2003 */
|
||||
|
||||
|
||||
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);
|
||||
if (izone == NULL)
|
||||
return FLUID_FAILED;
|
||||
|
||||
|
||||
izone->gen[gen_type].flags = GEN_SET;
|
||||
izone->gen[gen_type].val = value;
|
||||
|
||||
|
||||
fluid_rampreset_updatevoices(preset, gen_type, value);
|
||||
|
||||
|
||||
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_zone_t* izone, * prev;
|
||||
int found = 0;
|
||||
|
||||
|
||||
if (preset->zone == NULL) return FLUID_FAILED;
|
||||
inst = fluid_preset_zone_get_inst(preset->zone);
|
||||
izone = inst->zone;
|
||||
@@ -694,7 +696,7 @@ int fluid_rampreset_remove_izone(fluid_rampreset_t* preset, fluid_sample_t* samp
|
||||
}
|
||||
if (!found)
|
||||
return FLUID_FAILED;
|
||||
|
||||
|
||||
// stop all the voices that use this sample, so that
|
||||
// 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
|
||||
*/
|
||||
int
|
||||
int
|
||||
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 */
|
||||
fluid_rampreset_voice_t *presetvoice = FLUID_NEW(fluid_rampreset_voice_t);
|
||||
if (presetvoice == NULL) {
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
|
||||
|
||||
presetvoice->voice = voice;
|
||||
presetvoice->voiceID = fluid_voice_get_id(voice);
|
||||
|
||||
|
||||
preset->presetvoices = fluid_list_append(preset->presetvoices, (void *)presetvoice);
|
||||
if (preset->presetvoices == NULL) {
|
||||
FLUID_FREE(presetvoice);
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
return FLUID_FAILED;
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
return FLUID_OK;
|
||||
}
|
||||
@@ -743,10 +745,10 @@ fluid_rampreset_remembervoice(fluid_rampreset_t* preset, fluid_voice_t* voice) {
|
||||
/*
|
||||
* fluid_rampreset_updatevoice
|
||||
*/
|
||||
void
|
||||
void
|
||||
fluid_rampreset_updatevoices(fluid_rampreset_t* preset, int gen_type, float val) {
|
||||
fluid_list_t *tmp = preset->presetvoices, *prev = NULL, *next;
|
||||
|
||||
|
||||
/* 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
|
||||
*/
|
||||
@@ -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)) {
|
||||
/* forget it */
|
||||
FLUID_FREE(presetvoice);
|
||||
|
||||
|
||||
/* unlink it */
|
||||
next = tmp->next;
|
||||
FLUID_FREE(tmp);
|
||||
@@ -764,15 +766,15 @@ fluid_rampreset_updatevoices(fluid_rampreset_t* preset, int gen_type, float val)
|
||||
prev->next = next;
|
||||
} else {
|
||||
preset->presetvoices = next;
|
||||
}
|
||||
}
|
||||
tmp = next;
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
|
||||
/* update */
|
||||
fluid_voice_gen_set(voice, gen_type, val);
|
||||
fluid_voice_update_param(voice, gen_type);
|
||||
|
||||
fluid_voice_update_param(voice, gen_type);
|
||||
|
||||
/* next */
|
||||
prev = tmp;
|
||||
tmp = tmp->next;
|
||||
@@ -784,8 +786,8 @@ fluid_rampreset_updatevoices(fluid_rampreset_t* preset, int gen_type, float val)
|
||||
/*
|
||||
* fluid_rampreset_noteon
|
||||
*/
|
||||
int
|
||||
fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan, int key, int vel)
|
||||
int
|
||||
fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan, int key, int vel)
|
||||
{
|
||||
fluid_preset_zone_t *preset_zone;
|
||||
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 */
|
||||
int mod_list_count;
|
||||
int i;
|
||||
|
||||
|
||||
/* run thru all the zones of this preset */
|
||||
preset_zone = preset->zone;
|
||||
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
|
||||
preset */
|
||||
if (fluid_preset_zone_inside_range(preset_zone, key, vel)) {
|
||||
|
||||
|
||||
inst = fluid_preset_zone_get_inst(preset_zone);
|
||||
global_inst_zone = fluid_inst_get_global_zone(inst);
|
||||
|
||||
|
||||
/* run thru all the zones of this instrument */
|
||||
inst_zone = fluid_inst_get_zone(inst);
|
||||
while (inst_zone != NULL) {
|
||||
|
||||
|
||||
/* make sure this instrument zone has a valid sample */
|
||||
sample = fluid_inst_zone_get_sample(inst_zone);
|
||||
if (fluid_sample_in_rom(sample) || (sample == NULL)) {
|
||||
inst_zone = fluid_inst_zone_next(inst_zone);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
/* check if the note falls into the key and velocity range of this
|
||||
instrument */
|
||||
|
||||
if (fluid_inst_zone_inside_range(inst_zone, key, vel) && (sample != NULL)) {
|
||||
|
||||
|
||||
/* this is a good zone. allocate a new synthesis process and
|
||||
initialize it */
|
||||
|
||||
voice = fluid_synth_alloc_voice(synth, sample, chan, key, vel);
|
||||
if (voice == NULL) {
|
||||
return FLUID_FAILED;
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
|
||||
|
||||
if (fluid_rampreset_remembervoice(preset, voice) != FLUID_OK) {
|
||||
return FLUID_FAILED;
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
|
||||
|
||||
z = inst_zone;
|
||||
|
||||
|
||||
/* Instrument level, generators */
|
||||
|
||||
|
||||
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
|
||||
* 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);
|
||||
|
||||
} 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 {
|
||||
/* 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 */
|
||||
|
||||
|
||||
/* global instrument zone, modulators: Put them all into a
|
||||
* list. */
|
||||
|
||||
@@ -874,7 +876,7 @@ fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan
|
||||
mod = mod->next;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/* local instrument zone, modulators.
|
||||
* Replace modulators with the same definition in the list:
|
||||
* 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;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/* Finally add the new modulator to to the list. */
|
||||
mod_list[mod_list_count++] = mod;
|
||||
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
|
||||
* encountered at preset level, they should be ignored */
|
||||
if ((i != GEN_STARTADDROFS)
|
||||
&& (i != GEN_ENDADDROFS)
|
||||
&& (i != GEN_STARTLOOPADDROFS)
|
||||
&& (i != GEN_ENDLOOPADDROFS)
|
||||
&& (i != GEN_STARTADDRCOARSEOFS)
|
||||
&& (i != GEN_ENDADDRCOARSEOFS)
|
||||
if ((i != GEN_STARTADDROFS)
|
||||
&& (i != GEN_ENDADDROFS)
|
||||
&& (i != GEN_STARTLOOPADDROFS)
|
||||
&& (i != GEN_ENDLOOPADDROFS)
|
||||
&& (i != GEN_STARTADDRCOARSEOFS)
|
||||
&& (i != GEN_ENDADDRCOARSEOFS)
|
||||
&& (i != GEN_STARTLOOPADDRCOARSEOFS)
|
||||
&& (i != GEN_KEYNUM)
|
||||
&& (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 */
|
||||
}; /* for all generators */
|
||||
|
||||
|
||||
|
||||
|
||||
/* Global preset zone, modulators: put them all into a
|
||||
* list. */
|
||||
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;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/* Finally add the new modulator to the list. */
|
||||
mod_list[mod_list_count++] = mod;
|
||||
mod = mod->next;
|
||||
};
|
||||
|
||||
|
||||
/* Add preset modulators (global / local) to the voice. */
|
||||
for (i = 0; i < mod_list_count; i++){
|
||||
mod = mod_list[i];
|
||||
@@ -979,7 +981,7 @@ fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan
|
||||
* page */
|
||||
fluid_voice_add_mod(voice, mod, FLUID_VOICE_ADD);
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/* add the synthesis process to the synthesis loop. */
|
||||
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 */
|
||||
/* in all cases, the sample has ownership of the data : it will release it in the end */
|
||||
unsigned int storedNbFrames;
|
||||
|
||||
|
||||
/* in case we already have some data */
|
||||
if (sample->data != NULL) {
|
||||
FLUID_FREE(sample->data);
|
||||
}
|
||||
|
||||
|
||||
if (copy_data) {
|
||||
|
||||
|
||||
/* nbframes should be >= 48 (SoundFont specs) */
|
||||
storedNbFrames = nbframes;
|
||||
if (storedNbFrames < 48) storedNbFrames = 48;
|
||||
|
||||
|
||||
sample->data = FLUID_MALLOC(storedNbFrames*2 + 4*SAMPLE_LOOP_MARGIN);
|
||||
if (sample->data == NULL) {
|
||||
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), (char*)data + nbframes*2 - 2*SAMPLE_LOOP_MARGIN, 2*SAMPLE_LOOP_MARGIN);
|
||||
#endif
|
||||
|
||||
|
||||
/* pointers */
|
||||
/* all from the start of data */
|
||||
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->end = nbframes;
|
||||
}
|
||||
|
||||
|
||||
/* only used as markers for the LOOP generators : set them on the first real frame */
|
||||
sample->loopstart = sample->start;
|
||||
sample->loopend = sample->end;
|
||||
|
||||
|
||||
sample->samplerate = 44100;
|
||||
sample->origpitch = rootkey;
|
||||
sample->pitchadj = 0;
|
||||
@@ -1082,7 +1084,7 @@ fluid_sample_set_sound_data(fluid_sample_t* sample, short *data, unsigned int nb
|
||||
/*
|
||||
* new_fluid_ramsample
|
||||
*/
|
||||
fluid_sample_t*
|
||||
fluid_sample_t*
|
||||
new_fluid_ramsample()
|
||||
{
|
||||
/* 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);
|
||||
if (sample == NULL) {
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
* REVERB
|
||||
*/
|
||||
|
||||
/* Denormalising:
|
||||
/* Denormalising:
|
||||
*
|
||||
* According to music-dsp thread 'Denormalise', Pentium processors
|
||||
* 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);
|
||||
fluid_real_t fluid_allpass_getfeedback(fluid_allpass* allpass);
|
||||
|
||||
void
|
||||
void
|
||||
fluid_allpass_setbuffer(fluid_allpass* allpass, fluid_real_t *buf, int size)
|
||||
{
|
||||
allpass->bufidx = 0;
|
||||
allpass->buffer = buf;
|
||||
allpass->buffer = buf;
|
||||
allpass->bufsize = size;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
fluid_allpass_init(fluid_allpass* allpass)
|
||||
{
|
||||
int i;
|
||||
@@ -95,13 +95,13 @@ fluid_allpass_init(fluid_allpass* allpass)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
fluid_allpass_setfeedback(fluid_allpass* allpass, fluid_real_t val)
|
||||
{
|
||||
allpass->feedback = val;
|
||||
}
|
||||
|
||||
fluid_real_t
|
||||
fluid_real_t
|
||||
fluid_allpass_getfeedback(fluid_allpass* allpass)
|
||||
{
|
||||
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);
|
||||
fluid_real_t fluid_comb_getfeedback(fluid_comb* comb);
|
||||
|
||||
void
|
||||
fluid_comb_setbuffer(fluid_comb* comb, fluid_real_t *buf, int size)
|
||||
void
|
||||
fluid_comb_setbuffer(fluid_comb* comb, fluid_real_t *buf, int size)
|
||||
{
|
||||
comb->filterstore = 0;
|
||||
comb->bufidx = 0;
|
||||
comb->buffer = buf;
|
||||
comb->buffer = buf;
|
||||
comb->bufsize = size;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
fluid_comb_init(fluid_comb* comb)
|
||||
{
|
||||
int i;
|
||||
@@ -171,27 +171,27 @@ fluid_comb_init(fluid_comb* comb)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
fluid_comb_setdamp(fluid_comb* comb, fluid_real_t val)
|
||||
void
|
||||
fluid_comb_setdamp(fluid_comb* comb, fluid_real_t val)
|
||||
{
|
||||
comb->damp1 = val;
|
||||
comb->damp1 = val;
|
||||
comb->damp2 = 1 - val;
|
||||
}
|
||||
|
||||
fluid_real_t
|
||||
fluid_comb_getdamp(fluid_comb* comb)
|
||||
fluid_real_t
|
||||
fluid_comb_getdamp(fluid_comb* comb)
|
||||
{
|
||||
return comb->damp1;
|
||||
}
|
||||
|
||||
void
|
||||
fluid_comb_setfeedback(fluid_comb* comb, fluid_real_t val)
|
||||
void
|
||||
fluid_comb_setfeedback(fluid_comb* comb, fluid_real_t val)
|
||||
{
|
||||
comb->feedback = val;
|
||||
}
|
||||
|
||||
fluid_real_t
|
||||
fluid_comb_getfeedback(fluid_comb* comb)
|
||||
fluid_real_t
|
||||
fluid_comb_getfeedback(fluid_comb* comb)
|
||||
{
|
||||
return comb->feedback;
|
||||
}
|
||||
@@ -227,11 +227,11 @@ fluid_comb_getfeedback(fluid_comb* comb)
|
||||
#define numallpasses 4
|
||||
#define fixedgain 0.015f
|
||||
#define scalewet 3.0f
|
||||
#define scaledamp 0.4f
|
||||
#define scaledamp 1.0f
|
||||
#define scaleroom 0.28f
|
||||
#define offsetroom 0.7f
|
||||
#define initialroom 0.5f
|
||||
#define initialdamp 0.5f
|
||||
#define initialdamp 0.2f
|
||||
#define initialwet 1
|
||||
#define initialdry 0
|
||||
#define initialwidth 1
|
||||
@@ -275,7 +275,7 @@ struct _fluid_revmodel_t {
|
||||
fluid_real_t width;
|
||||
fluid_real_t gain;
|
||||
/*
|
||||
The following are all declared inline
|
||||
The following are all declared inline
|
||||
to remove the need for dynamic allocation
|
||||
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_init(fluid_revmodel_t* rev);
|
||||
|
||||
fluid_revmodel_t*
|
||||
fluid_revmodel_t*
|
||||
new_fluid_revmodel()
|
||||
{
|
||||
fluid_revmodel_t* rev;
|
||||
@@ -376,13 +376,13 @@ new_fluid_revmodel()
|
||||
return rev;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
delete_fluid_revmodel(fluid_revmodel_t* rev)
|
||||
{
|
||||
FLUID_FREE(rev);
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
fluid_revmodel_init(fluid_revmodel_t* rev)
|
||||
{
|
||||
int i;
|
||||
@@ -396,14 +396,14 @@ fluid_revmodel_init(fluid_revmodel_t* rev)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
fluid_revmodel_reset(fluid_revmodel_t* rev)
|
||||
{
|
||||
fluid_revmodel_init(rev);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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++) {
|
||||
|
||||
outL = outR = 0;
|
||||
|
||||
|
||||
/* The original Freeverb code expects a stereo signal and 'input'
|
||||
* 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
|
||||
@@ -438,10 +438,10 @@ fluid_revmodel_processreplace(fluid_revmodel_t* rev, fluid_real_t *in,
|
||||
left_out[k] = outL * rev->wet1 + outR * rev->wet2;
|
||||
right_out[k] = outR * rev->wet1 + outL * rev->wet2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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++) {
|
||||
|
||||
outL = outR = 0;
|
||||
|
||||
|
||||
/* The original Freeverb code expects a stereo signal and 'input'
|
||||
* 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
|
||||
@@ -478,7 +478,7 @@ fluid_revmodel_processmix(fluid_revmodel_t* rev, fluid_real_t *in,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
fluid_revmodel_update(fluid_revmodel_t* rev)
|
||||
{
|
||||
/* 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->combR[i], rev->roomsize);
|
||||
}
|
||||
|
||||
for (i = 0; i < numcombs; i++) {
|
||||
fluid_comb_setdamp(&rev->combL[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
|
||||
wish to take dynamic action when they are called.
|
||||
*/
|
||||
void
|
||||
void
|
||||
fluid_revmodel_setroomsize(fluid_revmodel_t* rev, fluid_real_t value)
|
||||
{
|
||||
/* 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_real_t
|
||||
fluid_real_t
|
||||
fluid_revmodel_getroomsize(fluid_revmodel_t* rev)
|
||||
{
|
||||
return (rev->roomsize - offsetroom) / scaleroom;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
fluid_revmodel_setdamp(fluid_revmodel_t* rev, fluid_real_t value)
|
||||
{
|
||||
/* 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_real_t
|
||||
fluid_real_t
|
||||
fluid_revmodel_getdamp(fluid_revmodel_t* rev)
|
||||
{
|
||||
return rev->damp / scaledamp;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
fluid_revmodel_setlevel(fluid_revmodel_t* rev, fluid_real_t value)
|
||||
{
|
||||
/* fluid_clip(value, 0.0f, 1.0f); */
|
||||
/* rev->wet = value * scalewet; */
|
||||
/* fluid_revmodel_update(rev); */
|
||||
fluid_clip(value, 0.0f, 1.0f);
|
||||
rev->wet = value * scalewet;
|
||||
fluid_revmodel_update(rev);
|
||||
}
|
||||
|
||||
fluid_real_t
|
||||
fluid_real_t
|
||||
fluid_revmodel_getlevel(fluid_revmodel_t* rev)
|
||||
{
|
||||
return rev->wet / scalewet;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
fluid_revmodel_setwidth(fluid_revmodel_t* rev, fluid_real_t value)
|
||||
{
|
||||
/* 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_real_t
|
||||
fluid_real_t
|
||||
fluid_revmodel_getwidth(fluid_revmodel_t* rev)
|
||||
{
|
||||
return rev->width;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -33,10 +33,10 @@ typedef struct _fluid_revmodel_t fluid_revmodel_t;
|
||||
fluid_revmodel_t* new_fluid_revmodel(void);
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
void fluid_revmodel_reset(fluid_revmodel_t* rev);
|
||||
|
||||
+103
-103
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -19,14 +19,14 @@
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
2002 : API design by Peter Hanappe and Antoine Schmitt
|
||||
August 2002 : Implementation by Antoine Schmitt as@gratin.org
|
||||
as part of the infiniteCD author project
|
||||
http://www.infiniteCD.org/
|
||||
*/
|
||||
|
||||
|
||||
#include "fluid_event_priv.h"
|
||||
#include "fluidsynth_priv.h" // FLUID_NEW, 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 */
|
||||
|
||||
fluid_sequencer_t*
|
||||
fluid_sequencer_t*
|
||||
new_fluid_sequencer()
|
||||
{
|
||||
fluid_sequencer_t* seq;
|
||||
|
||||
|
||||
seq = FLUID_NEW(fluid_sequencer_t);
|
||||
if (seq == NULL) {
|
||||
fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
|
||||
@@ -99,7 +99,7 @@ new_fluid_sequencer()
|
||||
seq->startMs = fluid_curtime();
|
||||
seq->clients = NULL;
|
||||
seq->clientsID = 0;
|
||||
|
||||
|
||||
if (-1 == _fluid_seq_queue_init(seq, FLUID_SEQUENCER_EVENTS_MAX)) {
|
||||
FLUID_FREE(seq);
|
||||
fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
|
||||
@@ -113,7 +113,7 @@ new_fluid_sequencer()
|
||||
_fluid_seq_queue_end(seq);
|
||||
FLUID_FREE(seq);
|
||||
fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
seq->traceptr = seq->tracebuf;
|
||||
#endif
|
||||
@@ -121,16 +121,16 @@ new_fluid_sequencer()
|
||||
return(seq);
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
delete_fluid_sequencer(fluid_sequencer_t* seq)
|
||||
{
|
||||
|
||||
|
||||
if (seq == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
_fluid_seq_queue_end(seq);
|
||||
|
||||
|
||||
/* cleanup clients */
|
||||
if (seq->clients) {
|
||||
fluid_list_t *tmp = seq->clients;
|
||||
@@ -142,9 +142,9 @@ delete_fluid_sequencer(fluid_sequencer_t* seq)
|
||||
delete_fluid_list(seq->clients);
|
||||
seq->clients = NULL;
|
||||
}
|
||||
|
||||
|
||||
#if FLUID_SEQ_WITH_TRACE
|
||||
if (seq->tracebuf != NULL)
|
||||
if (seq->tracebuf != NULL)
|
||||
FLUID_FREE(seq->tracebuf);
|
||||
seq->tracebuf = NULL;
|
||||
#endif
|
||||
@@ -161,7 +161,7 @@ fluid_seq_dotrace(fluid_sequencer_t* seq, char *fmt, ...)
|
||||
va_list args;
|
||||
int len, remain = seq->tracelen - (seq->traceptr - seq->tracebuf);
|
||||
if (remain <= 0) return;
|
||||
|
||||
|
||||
va_start (args, fmt);
|
||||
len = vsnprintf(seq->traceptr, remain, fmt, args);
|
||||
va_end (args);
|
||||
@@ -175,7 +175,7 @@ fluid_seq_dotrace(fluid_sequencer_t* seq, char *fmt, ...)
|
||||
seq->traceptr = seq->tracebuf + seq->tracelen;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -198,12 +198,12 @@ void fluid_seq_dotrace(fluid_sequencer_t* seq, char *fmt, ...) {}
|
||||
|
||||
/* 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_sequencer_client_t * client;
|
||||
char * nameCopy;
|
||||
|
||||
|
||||
client = FLUID_NEW(fluid_sequencer_client_t);
|
||||
if (client == NULL) {
|
||||
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");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
seq->clientsID++;
|
||||
|
||||
client->name = nameCopy;
|
||||
client->id = seq->clientsID;
|
||||
client->callback = callback;
|
||||
client->data = data;
|
||||
|
||||
|
||||
seq->clients = fluid_list_append(seq->clients, (void *)client);
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
fluid_list_t *tmp;
|
||||
|
||||
|
||||
if (seq->clients == NULL) return;
|
||||
|
||||
|
||||
tmp = seq->clients;
|
||||
while (tmp) {
|
||||
fluid_sequencer_client_t *client = (fluid_sequencer_client_t*)tmp->data;
|
||||
|
||||
|
||||
if (client->id == id) {
|
||||
if (client->name)
|
||||
if (client->name)
|
||||
FLUID_FREE(client->name);
|
||||
seq->clients = fluid_list_remove_link(seq->clients, 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)
|
||||
{
|
||||
if (seq->clients == NULL)
|
||||
if (seq->clients == NULL)
|
||||
return 0;
|
||||
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)
|
||||
{
|
||||
fluid_list_t *tmp;
|
||||
|
||||
if (seq->clients == NULL)
|
||||
|
||||
if (seq->clients == NULL)
|
||||
return NULL;
|
||||
|
||||
|
||||
tmp = seq->clients;
|
||||
while (tmp) {
|
||||
fluid_sequencer_client_t *client = (fluid_sequencer_client_t*)tmp->data;
|
||||
|
||||
|
||||
if (client->id == id)
|
||||
return client->name;
|
||||
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
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)
|
||||
{
|
||||
fluid_list_t *tmp;
|
||||
|
||||
|
||||
if (seq->clients == NULL) return 0;
|
||||
|
||||
|
||||
tmp = seq->clients;
|
||||
while (tmp) {
|
||||
fluid_sequencer_client_t *client = (fluid_sequencer_client_t*)tmp->data;
|
||||
|
||||
|
||||
if (client->id == id)
|
||||
return (client->callback != NULL);
|
||||
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
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)
|
||||
{
|
||||
short destID = fluid_event_get_dest(evt);
|
||||
|
||||
|
||||
/* find callback */
|
||||
fluid_list_t *tmp = seq->clients;
|
||||
while (tmp) {
|
||||
fluid_sequencer_client_t *dest = (fluid_sequencer_client_t*)tmp->data;
|
||||
|
||||
|
||||
if (dest->id == destID) {
|
||||
if (dest->callback)
|
||||
(dest->callback)(fluid_sequencer_get_tick(seq),
|
||||
(dest->callback)(fluid_sequencer_get_tick(seq),
|
||||
evt, seq, dest->data);
|
||||
return;
|
||||
}
|
||||
@@ -336,24 +336,24 @@ fluid_sequencer_send_at(fluid_sequencer_t* seq, fluid_event_t* evt, unsigned int
|
||||
/* set absolute */
|
||||
if (!absolute)
|
||||
time = now + time;
|
||||
|
||||
|
||||
/* time stamp event */
|
||||
fluid_event_set_time(evt, time);
|
||||
|
||||
|
||||
/* process late */
|
||||
if (time < now) {
|
||||
fluid_sequencer_send_now(seq, evt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* process now */
|
||||
if (time == now) {
|
||||
fluid_sequencer_send_now(seq, evt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* queue for processing later */
|
||||
return _fluid_seq_queue_pre_insert(seq, evt);
|
||||
return _fluid_seq_queue_pre_insert(seq, evt);
|
||||
}
|
||||
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (scale > 1000.0)
|
||||
// Otherwise : problems with the timer = 0ms...
|
||||
scale = 1000.0;
|
||||
|
||||
if (seq->scale != scale) {
|
||||
double oldScale = seq->scale;
|
||||
|
||||
|
||||
// stop timer
|
||||
if (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;
|
||||
tmp = seq->preQueue;
|
||||
while (tmp) {
|
||||
while (tmp) {
|
||||
if (tmp->entryType == FLUID_EVT_ENTRY_INSERT)
|
||||
tmp->evt.time = tmp->evt.time*seq->scale/oldScale;
|
||||
|
||||
|
||||
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.
|
||||
|
||||
|
||||
Data structures
|
||||
|
||||
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
|
||||
tick=1ms). Inserting later events is more slow, but this is a
|
||||
realtime engine, isn't it ?
|
||||
|
||||
|
||||
The queue0 starts at queue0StartTime. When 256 ticks have
|
||||
elapsed, the queue0 array is emptied, and the first cell of
|
||||
the queue1 array is expanded in the queue0 array, according to
|
||||
the time of each event. The queue1 array is shifted to the
|
||||
left, and the first events of the queueLater list are inserte
|
||||
in the last cell of the queue1 array.
|
||||
|
||||
|
||||
We remember the previously managed cell in queue0 in the
|
||||
prevCellNb variable. When processing the current cell, we
|
||||
process the events in between (late events).
|
||||
|
||||
Functions
|
||||
|
||||
|
||||
The main thread functions first get an event entry from the
|
||||
heap, and copy the given event into it, then merely enqueue it
|
||||
in a preQueue. This is in order to protect the data structure:
|
||||
everything is managed in the callback (thread or interrupt,
|
||||
depending on the architecture).
|
||||
|
||||
|
||||
All queue data structure management is done in a timer
|
||||
callback: '_fluid_seq_queue_process'. The
|
||||
_fluid_seq_queue_process function first process the preQueue,
|
||||
inserting or removing event entrys from the queue, then
|
||||
processes the queue, by sending events ready to be sent at the
|
||||
current time.
|
||||
|
||||
|
||||
Critical sections between the main thread (or app) and the
|
||||
sequencer thread (or interrupt) are:
|
||||
|
||||
@@ -530,11 +530,11 @@ _fluid_seq_queue_init(fluid_sequencer_t* seq, int maxEvents)
|
||||
seq->queueLater = NULL;
|
||||
seq->queue0StartTime = fluid_sequencer_get_tick(seq);
|
||||
seq->prevCellNb = -1;
|
||||
|
||||
|
||||
fluid_mutex_init(seq->mutex);
|
||||
|
||||
/* 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);
|
||||
return (0);
|
||||
}
|
||||
@@ -546,7 +546,7 @@ _fluid_seq_queue_end(fluid_sequencer_t* seq)
|
||||
delete_fluid_timer(seq->timer);
|
||||
seq->timer = NULL;
|
||||
}
|
||||
|
||||
|
||||
if (seq->heap) {
|
||||
_fluid_evt_heap_free(seq->heap);
|
||||
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");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
evtentry->next = NULL;
|
||||
evtentry->entryType = FLUID_EVT_ENTRY_INSERT;
|
||||
FLUID_MEMCPY(&(evtentry->evt), evt, sizeof(fluid_event_t));
|
||||
|
||||
|
||||
fluid_mutex_lock(seq->mutex);
|
||||
|
||||
/* append to preQueue */
|
||||
@@ -588,7 +588,7 @@ _fluid_seq_queue_pre_insert(fluid_sequencer_t* seq, fluid_event_t * evt)
|
||||
seq->preQueueLast = evtentry;
|
||||
|
||||
fluid_mutex_unlock(seq->mutex);
|
||||
|
||||
|
||||
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");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
evtentry->next = NULL;
|
||||
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);
|
||||
evt->type = type;
|
||||
}
|
||||
|
||||
|
||||
fluid_mutex_lock(seq->mutex);
|
||||
|
||||
/* 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->preQueueLast = evtentry;
|
||||
|
||||
|
||||
fluid_mutex_unlock(seq->mutex);
|
||||
return;
|
||||
}
|
||||
@@ -632,7 +632,7 @@ _fluid_seq_queue_pre_remove(fluid_sequencer_t* seq, short src, short dest, int t
|
||||
/***********************
|
||||
* callback from timer
|
||||
* (may be in a different thread, or in an interrupt)
|
||||
*
|
||||
*
|
||||
***********************/
|
||||
int
|
||||
_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;
|
||||
|
||||
fluid_mutex_unlock(seq->mutex);
|
||||
|
||||
|
||||
/* walk all the preQueue and process them in order : inserts and removes */
|
||||
while (tmp) {
|
||||
next = tmp->next;
|
||||
|
||||
|
||||
if (tmp->entryType == FLUID_EVT_ENTRY_REMOVE) {
|
||||
_fluid_seq_queue_remove_entries_matching(seq, tmp);
|
||||
} else {
|
||||
_fluid_seq_queue_insert_entry(seq, tmp);
|
||||
}
|
||||
|
||||
|
||||
tmp = next;
|
||||
}
|
||||
|
||||
|
||||
/* send queued events */
|
||||
_fluid_seq_queue_send_queued_events(seq);
|
||||
|
||||
|
||||
/* continue timer */
|
||||
return 1;
|
||||
}
|
||||
@@ -680,7 +680,7 @@ _fluid_seq_queue_print_later(fluid_sequencer_t* seq)
|
||||
fluid_evt_entry* tmp = seq->queueLater;
|
||||
|
||||
printf("queueLater:\n");
|
||||
|
||||
|
||||
while (tmp) {
|
||||
unsigned int delay = tmp->evt.time - seq->queue0StartTime;
|
||||
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* tmp;
|
||||
unsigned int time = evtentry->evt.time;
|
||||
unsigned int time = evtentry->evt.time;
|
||||
|
||||
/* insert in 'queueLater', after the ones that have the same
|
||||
* time */
|
||||
|
||||
|
||||
/* first? */
|
||||
if ((seq->queueLater == NULL)
|
||||
if ((seq->queueLater == NULL)
|
||||
|| (seq->queueLater->evt.time > time)) {
|
||||
evtentry->next = seq->queueLater;
|
||||
seq->queueLater = evtentry;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* walk queueLater */
|
||||
/* this is the only slow thing : if the event is more
|
||||
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 */
|
||||
evtentry->next = NULL;
|
||||
prev->next = evtentry;
|
||||
prev->next = evtentry;
|
||||
}
|
||||
|
||||
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 */
|
||||
fluid_event_t * evt = &(evtentry->evt);
|
||||
unsigned int time = evt->time;
|
||||
unsigned int time = evt->time;
|
||||
unsigned int delay;
|
||||
|
||||
|
||||
if (seq->queue0StartTime > 0) {
|
||||
/* 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) {
|
||||
/* we are late, send now */
|
||||
fluid_sequencer_send_now(seq, evt);
|
||||
|
||||
|
||||
_fluid_seq_heap_set_free(seq->heap, evtentry);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (seq->prevCellNb >= 0) {
|
||||
/* 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() */
|
||||
if (time <= (unsigned int)(seq->queue0StartTime + seq->prevCellNb)) {
|
||||
/* we are late, send now */
|
||||
fluid_sequencer_send_now(seq, evt);
|
||||
|
||||
|
||||
_fluid_seq_heap_set_free(seq->heap, evtentry);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
delay = time - seq->queue0StartTime;
|
||||
|
||||
|
||||
if (delay > 65535) {
|
||||
_fluid_seq_queue_insert_queue_later(seq, evtentry);
|
||||
|
||||
|
||||
} else if (delay > 255) {
|
||||
_fluid_seq_queue_insert_queue1(seq, evtentry, delay/256 - 1);
|
||||
|
||||
|
||||
} else {
|
||||
_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)
|
||||
{
|
||||
int eventType;
|
||||
|
||||
|
||||
if (templSrc != -1 && templSrc != fluid_event_get_source(evt))
|
||||
return 0;
|
||||
|
||||
|
||||
if (templDest != -1 && templDest != fluid_event_get_dest(evt))
|
||||
return 0;
|
||||
|
||||
|
||||
if (templType == -1)
|
||||
return 1;
|
||||
|
||||
|
||||
eventType = fluid_event_get_type(evt);
|
||||
|
||||
|
||||
if (templType == eventType)
|
||||
return 1;
|
||||
|
||||
|
||||
if (templType == FLUID_SEQ_ANYCONTROLCHANGE)
|
||||
if (eventType == FLUID_SEQ_PITCHBEND ||
|
||||
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 */
|
||||
int i, type;
|
||||
short src, dest;
|
||||
|
||||
|
||||
src = templ->evt.src;
|
||||
dest = templ->evt.dest;
|
||||
type = templ->evt.type;
|
||||
|
||||
/* we can set it free now */
|
||||
_fluid_seq_heap_set_free(seq->heap, templ);
|
||||
|
||||
|
||||
/* queue0 */
|
||||
for (i = 0 ; i < 256 ; i++) {
|
||||
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 {
|
||||
prev = tmp;
|
||||
tmp = prev->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* queue1 */
|
||||
for (i = 0 ; i < 255 ; i++) {
|
||||
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 {
|
||||
prev = tmp;
|
||||
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);
|
||||
tmp = next;
|
||||
}
|
||||
}
|
||||
seq->queue0[cellNb][0] = NULL;
|
||||
seq->queue0[cellNb][1] = NULL;
|
||||
seq->queue0[cellNb][1] = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -989,7 +989,7 @@ _fluid_seq_queue_slide(fluid_sequencer_t* seq)
|
||||
}
|
||||
seq->queue1[254][0] = NULL;
|
||||
seq->queue1[254][1] = NULL;
|
||||
|
||||
|
||||
|
||||
/* append queueLater to queue1[254] */
|
||||
count = 0;
|
||||
@@ -1003,9 +1003,9 @@ _fluid_seq_queue_slide(fluid_sequencer_t* seq)
|
||||
|
||||
next = tmp->next;
|
||||
|
||||
/* append it */
|
||||
/* append it */
|
||||
_fluid_seq_queue_insert_queue1(seq, tmp, 254);
|
||||
tmp = next;
|
||||
tmp = next;
|
||||
count++;
|
||||
}
|
||||
|
||||
@@ -1024,14 +1024,14 @@ _fluid_seq_queue_send_queued_events(fluid_sequencer_t* seq)
|
||||
cellNb = 0;
|
||||
_fluid_seq_queue_slide(seq);
|
||||
} /* slide */
|
||||
|
||||
|
||||
|
||||
|
||||
/* process queue0[cellNb] */
|
||||
_fluid_seq_queue_send_cell_events(seq, cellNb);
|
||||
|
||||
/* next cell */
|
||||
cellNb++;
|
||||
}
|
||||
|
||||
|
||||
seq->prevCellNb = cellNb - 1;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -28,7 +28,7 @@
|
||||
*/
|
||||
|
||||
#include "fluidsynth_priv.h"
|
||||
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
fluid_synth_t* synth = (fluid_synth_t *)data;
|
||||
|
||||
|
||||
switch (fluid_event_get_type(evt)) {
|
||||
|
||||
case FLUID_SEQ_NOTEON:
|
||||
fluid_synth_noteon(synth, fluid_event_get_channel(evt), fluid_event_get_key(evt), fluid_event_get_velocity(evt));
|
||||
break;
|
||||
|
||||
|
||||
case FLUID_SEQ_NOTEOFF:
|
||||
fluid_synth_noteoff(synth, fluid_event_get_channel(evt), fluid_event_get_key(evt));
|
||||
break;
|
||||
|
||||
|
||||
case FLUID_SEQ_NOTE:
|
||||
{
|
||||
unsigned int dur;
|
||||
@@ -75,28 +75,28 @@ void fluid_seq_fluidsynth_callback(unsigned int time, fluid_event_t* evt, fluid_
|
||||
case FLUID_SEQ_ALLNOTESOFF:
|
||||
fluid_synth_cc(synth, fluid_event_get_channel(evt), 0x7B, 0);
|
||||
break;
|
||||
|
||||
|
||||
case FLUID_SEQ_BANKSELECT:
|
||||
fluid_synth_bank_select(synth, fluid_event_get_channel(evt), fluid_event_get_bank(evt));
|
||||
break;
|
||||
|
||||
|
||||
case FLUID_SEQ_PROGRAMCHANGE:
|
||||
fluid_synth_program_change(synth, fluid_event_get_channel(evt), fluid_event_get_program(evt));
|
||||
break;
|
||||
|
||||
|
||||
case FLUID_SEQ_PROGRAMSELECT:
|
||||
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));
|
||||
break;
|
||||
|
||||
|
||||
case FLUID_SEQ_ANYCONTROLCHANGE:
|
||||
/* nothing = only used by remove_events */
|
||||
break;
|
||||
|
||||
|
||||
case FLUID_SEQ_PITCHBEND:
|
||||
fluid_synth_pitch_bend(synth, fluid_event_get_channel(evt), fluid_event_get_pitch(evt));
|
||||
break;
|
||||
|
||||
|
||||
case FLUID_SEQ_PITCHWHHELSENS:
|
||||
fluid_synth_pitch_wheel_sens(synth, fluid_event_get_channel(evt), fluid_event_get_value(evt));
|
||||
break;
|
||||
@@ -104,53 +104,53 @@ void fluid_seq_fluidsynth_callback(unsigned int time, fluid_event_t* evt, fluid_
|
||||
case FLUID_SEQ_CONTROLCHANGE:
|
||||
fluid_synth_cc(synth, fluid_event_get_channel(evt), fluid_event_get_control(evt), fluid_event_get_value(evt));
|
||||
break;
|
||||
|
||||
|
||||
case FLUID_SEQ_MODULATION:
|
||||
{
|
||||
short ctrl = 0x01; // MODULATION_MSB
|
||||
fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case FLUID_SEQ_SUSTAIN:
|
||||
{
|
||||
short ctrl = 0x40; // SUSTAIN_SWITCH
|
||||
fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case FLUID_SEQ_PAN:
|
||||
{
|
||||
short ctrl = 0x0A; // PAN_MSB
|
||||
fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case FLUID_SEQ_VOLUME:
|
||||
{
|
||||
short ctrl = 0x07; // VOLUME_MSB
|
||||
fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case FLUID_SEQ_REVERBSEND:
|
||||
{
|
||||
short ctrl = 0x5B; // EFFECTS_DEPTH1
|
||||
fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case FLUID_SEQ_CHORUSSEND:
|
||||
{
|
||||
short ctrl = 0x5D; // EFFECTS_DEPTH3
|
||||
fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case FLUID_SEQ_TIMER:
|
||||
/* nothing in fluidsynth */
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -19,18 +19,21 @@
|
||||
*/
|
||||
|
||||
#include "fluidsynth_priv.h"
|
||||
#include "fluid_settings.h"
|
||||
#include "fluid_sys.h"
|
||||
#include "fluid_hash.h"
|
||||
#include "fluid_strtok.h"
|
||||
#include "fluid_synth.h"
|
||||
#include "fluid_cmd.h"
|
||||
#include "fluid_adriver.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_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 {
|
||||
@@ -42,7 +45,7 @@ typedef struct {
|
||||
void* data;
|
||||
} 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)
|
||||
{
|
||||
fluid_str_setting_t* str;
|
||||
@@ -60,13 +63,20 @@ static void delete_fluid_str_setting(fluid_str_setting_t* str)
|
||||
{
|
||||
if (str) {
|
||||
if (str->value) {
|
||||
FLUID_FREE(str->value);
|
||||
FLUID_FREE(str->value);
|
||||
}
|
||||
if (str->def) {
|
||||
FLUID_FREE(str->def);
|
||||
FLUID_FREE(str->def);
|
||||
}
|
||||
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);
|
||||
}
|
||||
@@ -86,7 +96,7 @@ typedef struct {
|
||||
} fluid_num_setting_t;
|
||||
|
||||
|
||||
static fluid_num_setting_t*
|
||||
static fluid_num_setting_t*
|
||||
new_fluid_num_setting(double min, double max, double def,
|
||||
int hints, fluid_num_update_t fun, void* data)
|
||||
{
|
||||
@@ -123,7 +133,7 @@ typedef struct {
|
||||
} fluid_int_setting_t;
|
||||
|
||||
|
||||
static fluid_int_setting_t*
|
||||
static fluid_int_setting_t*
|
||||
new_fluid_int_setting(int min, int max, int def,
|
||||
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);
|
||||
}
|
||||
|
||||
static fluid_strtok_t* fluid_settings_strtok = NULL;
|
||||
|
||||
int fluid_settings_tokenize(char* s, char* buf, char** ptr)
|
||||
static int fluid_settings_tokenize(char* s, char *buf, char** ptr)
|
||||
{
|
||||
char *tokstr, *tok;
|
||||
int n = 0;
|
||||
|
||||
FLUID_STRCPY(buf, s);
|
||||
|
||||
if (fluid_settings_strtok == NULL) {
|
||||
fluid_settings_strtok = new_fluid_strtok(buf, ".");
|
||||
} else {
|
||||
fluid_strtok_set(fluid_settings_strtok, buf, ".");
|
||||
if (strlen (s) > MAX_SETTINGS_LABEL)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Setting variable name exceeded max length of %d chars",
|
||||
MAX_SETTINGS_LABEL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (fluid_strtok_has_more(fluid_settings_strtok)) {
|
||||
ptr[n++] = fluid_strtok_next_token(fluid_settings_strtok);
|
||||
FLUID_STRCPY(buf, s); /* copy string to buffer, since it gets modified */
|
||||
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;
|
||||
}
|
||||
|
||||
/** returns 1 if the value exists, 0 otherwise */
|
||||
static int fluid_settings_get(fluid_settings_t* settings,
|
||||
char** name, int len,
|
||||
static int fluid_settings_get(fluid_settings_t* settings,
|
||||
char** name, int len,
|
||||
void** value, int* type)
|
||||
{
|
||||
fluid_hashtable_t* table = settings;
|
||||
int t;
|
||||
void* v;
|
||||
int n;
|
||||
|
||||
|
||||
for (n = 0; n < len; n++) {
|
||||
|
||||
if (table == NULL) {
|
||||
@@ -244,10 +263,9 @@ static int fluid_settings_get(fluid_settings_t* settings,
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/** returns 1 if the value has been set, zero otherwise */
|
||||
static int fluid_settings_set(fluid_settings_t* settings,
|
||||
char** name, int len,
|
||||
static int fluid_settings_set(fluid_settings_t* settings,
|
||||
char** name, int len,
|
||||
void* value, int type)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/** returns 1 if the value has been resgister correctly, 0
|
||||
/** returns 1 if the value has been registered correctly, 0
|
||||
otherwise */
|
||||
int fluid_settings_register_str(fluid_settings_t* settings, char* name, char* def, int hints,
|
||||
fluid_str_update_t fun, void* data)
|
||||
{
|
||||
int type;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
fluid_str_setting_t* setting;
|
||||
|
||||
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);
|
||||
return fluid_settings_set(settings, tokens, ntokens, setting, FLUID_STR_TYPE);
|
||||
|
||||
|
||||
} else {
|
||||
/* if variable already exists, don't change its value. */
|
||||
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
|
||||
otherwise */
|
||||
int fluid_settings_register_num(fluid_settings_t* settings, char* name, double def,
|
||||
double min, double max, int hints,
|
||||
int fluid_settings_register_num(fluid_settings_t* settings, char* name, double def,
|
||||
double min, double max, int hints,
|
||||
fluid_num_update_t fun, void* data)
|
||||
{
|
||||
int type;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
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
|
||||
otherwise */
|
||||
int fluid_settings_register_int(fluid_settings_t* settings, char* name, int def,
|
||||
int min, int max, int hints,
|
||||
int fluid_settings_register_int(fluid_settings_t* settings, char* name, int def,
|
||||
int min, int max, int hints,
|
||||
fluid_int_update_t fun, void* data)
|
||||
{
|
||||
int type;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
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 type;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
int fluid_settings_get_hints(fluid_settings_t* settings, char* name)
|
||||
{
|
||||
int type;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
@@ -439,8 +455,8 @@ int fluid_settings_is_realtime(fluid_settings_t* settings, char* name)
|
||||
{
|
||||
int type;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
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)
|
||||
{
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
int type;
|
||||
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);
|
||||
|
||||
if (fluid_settings_get(settings, tokens, ntokens, &value, &type)) {
|
||||
|
||||
|
||||
if (type != FLUID_STR_TYPE) {
|
||||
return 0;
|
||||
}
|
||||
@@ -485,14 +500,14 @@ int fluid_settings_setstr(fluid_settings_t* settings, char* name, char* str)
|
||||
FLUID_FREE(setting->value);
|
||||
}
|
||||
setting->value = str? FLUID_STRDUP(str) : NULL;
|
||||
|
||||
|
||||
if (setting->update) {
|
||||
(*setting->update)(setting->data, name, setting->value);
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
|
||||
} else {
|
||||
} else {
|
||||
/* insert a new setting */
|
||||
fluid_str_setting_t* setting;
|
||||
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;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
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)) {
|
||||
fluid_str_setting_t* setting = (fluid_str_setting_t*) value;
|
||||
*str = setting->value;
|
||||
@@ -520,18 +535,17 @@ int fluid_settings_getstr(fluid_settings_t* settings, char* name, char** str)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int fluid_settings_str_equal(fluid_settings_t* settings, char* name, char* s)
|
||||
{
|
||||
int type;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
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)) {
|
||||
fluid_str_setting_t* setting = (fluid_str_setting_t*) value;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
char*
|
||||
fluid_settings_getstr_default(fluid_settings_t* settings, char* name)
|
||||
{
|
||||
int type;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
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)) {
|
||||
fluid_str_setting_t* setting = (fluid_str_setting_t*) value;
|
||||
return setting->def;
|
||||
@@ -564,13 +577,13 @@ int fluid_settings_add_option(fluid_settings_t* settings, char* name, char* s)
|
||||
{
|
||||
int type;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
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)) {
|
||||
fluid_str_setting_t* setting = (fluid_str_setting_t*) value;
|
||||
char* copy = FLUID_STRDUP(s);
|
||||
@@ -578,20 +591,20 @@ int fluid_settings_add_option(fluid_settings_t* settings, char* name, char* s)
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int fluid_settings_remove_option(fluid_settings_t* settings, char* name, char* s)
|
||||
{
|
||||
int type;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
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)) {
|
||||
|
||||
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) {
|
||||
char* option = (char*) fluid_list_get(list);
|
||||
if (FLUID_STRCMP(s, option) == 0) {
|
||||
FLUID_FREE (option);
|
||||
setting->options = fluid_list_remove_link(setting->options, list);
|
||||
return 1;
|
||||
}
|
||||
@@ -609,17 +623,16 @@ int fluid_settings_remove_option(fluid_settings_t* settings, char* name, char* s
|
||||
return 0;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int fluid_settings_setnum(fluid_settings_t* settings, char* name, double val)
|
||||
{
|
||||
int type;
|
||||
void* value;
|
||||
fluid_num_setting_t* setting;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
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;
|
||||
|
||||
|
||||
if (val < setting->min) {
|
||||
val = setting->min;
|
||||
} else if (val > setting->max) {
|
||||
val = setting->max;
|
||||
}
|
||||
|
||||
|
||||
setting->value = val;
|
||||
|
||||
|
||||
if (setting->update) {
|
||||
(*setting->update)(setting->data, name, val);
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
|
||||
} else {
|
||||
} else {
|
||||
/* insert a new setting */
|
||||
fluid_num_setting_t* setting;
|
||||
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;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
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)) {
|
||||
fluid_num_setting_t* setting = (fluid_num_setting_t*) value;
|
||||
*val = setting->value;
|
||||
@@ -679,13 +692,13 @@ void fluid_settings_getnum_range(fluid_settings_t* settings, char* name, double*
|
||||
{
|
||||
int type;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
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)) {
|
||||
fluid_num_setting_t* setting = (fluid_num_setting_t*) value;
|
||||
*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)
|
||||
{
|
||||
int type;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
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)) {
|
||||
fluid_num_setting_t* setting = (fluid_num_setting_t*) value;
|
||||
return setting->def;
|
||||
@@ -719,8 +732,8 @@ int fluid_settings_setint(fluid_settings_t* settings, char* name, int val)
|
||||
int type;
|
||||
void* value;
|
||||
fluid_int_setting_t* setting;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
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;
|
||||
|
||||
|
||||
if (val < setting->min) {
|
||||
val = setting->min;
|
||||
} else if (val > setting->max) {
|
||||
val = setting->max;
|
||||
}
|
||||
|
||||
|
||||
setting->value = val;
|
||||
|
||||
|
||||
if (setting->update) {
|
||||
(*setting->update)(setting->data, name, val);
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
|
||||
} else {
|
||||
} else {
|
||||
/* insert a new setting */
|
||||
fluid_int_setting_t* setting;
|
||||
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;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
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)) {
|
||||
fluid_int_setting_t* setting = (fluid_int_setting_t*) value;
|
||||
*val = setting->value;
|
||||
@@ -780,13 +793,13 @@ void fluid_settings_getint_range(fluid_settings_t* settings, char* name, int* mi
|
||||
{
|
||||
int type;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
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)) {
|
||||
fluid_int_setting_t* setting = (fluid_int_setting_t*) value;
|
||||
*min = setting->min;
|
||||
@@ -799,13 +812,13 @@ fluid_settings_getint_default(fluid_settings_t* settings, char* name)
|
||||
{
|
||||
int type;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
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)) {
|
||||
fluid_int_setting_t* setting = (fluid_int_setting_t*) value;
|
||||
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)
|
||||
{
|
||||
int type;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
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);
|
||||
|
||||
if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
|
||||
if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
|
||||
&& (type == FLUID_STR_TYPE)) {
|
||||
|
||||
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);
|
||||
list = fluid_list_next(list);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -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
|
||||
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);
|
||||
|
||||
|
||||
/** returns 0 if the value has been resgister correctly, non-zero
|
||||
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);
|
||||
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -61,7 +61,7 @@
|
||||
#define fluid_sample_decr_ref(_sample) \
|
||||
(_sample)->refcount--; \
|
||||
if (((_sample)->refcount == 0) && ((_sample)->notify)) \
|
||||
(*(_sample)->notify)(_sample, FLUID_SAMPLE_DONE);
|
||||
(*(_sample)->notify)(_sample, FLUID_SAMPLE_DONE);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -98,7 +98,7 @@ struct _fluid_synth_t
|
||||
double sample_rate; /** The sample rate */
|
||||
int midi_channels; /** the number of MIDI channels (>= 16) */
|
||||
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. */
|
||||
int effects_channels; /** the number of effects channels (= 2) */
|
||||
unsigned int state; /** the synthesizer state */
|
||||
@@ -120,7 +120,7 @@ struct _fluid_synth_t
|
||||
int nvoice; /** the length of the synthesis process array */
|
||||
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 storeid;
|
||||
unsigned int storeid;
|
||||
int nbuf; /** How many audio buffers are used? (depends on nr of audio channels / groups)*/
|
||||
|
||||
fluid_real_t** left_buf;
|
||||
@@ -128,23 +128,19 @@ struct _fluid_synth_t
|
||||
fluid_real_t** fx_left_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_chorus_t* chorus;
|
||||
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 */
|
||||
double cpu_load;
|
||||
|
||||
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*** tuning; /** 128 banks of 128 programs for the tunings */
|
||||
fluid_tuning_t* cur_tuning; /** current tuning in the iteration */
|
||||
|
||||
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
|
||||
* thread problems, for example from MIDI thread and shell thread
|
||||
*/
|
||||
@@ -153,7 +149,6 @@ struct _fluid_synth_t
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
/** returns 1 if the value has been set, 0 otherwise */
|
||||
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);
|
||||
|
||||
fluid_preset_t* fluid_synth_get_preset(fluid_synth_t* synth,
|
||||
unsigned int sfontnum,
|
||||
unsigned int banknum,
|
||||
fluid_preset_t* fluid_synth_get_preset(fluid_synth_t* synth,
|
||||
unsigned int sfontnum,
|
||||
unsigned int banknum,
|
||||
unsigned int prognum);
|
||||
|
||||
fluid_preset_t* fluid_synth_find_preset(fluid_synth_t* synth,
|
||||
unsigned int banknum,
|
||||
fluid_preset_t* fluid_synth_find_preset(fluid_synth_t* synth,
|
||||
unsigned int banknum,
|
||||
unsigned int prognum);
|
||||
|
||||
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);
|
||||
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
|
||||
*/
|
||||
|
||||
+201
-112
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -20,7 +20,6 @@
|
||||
|
||||
|
||||
#include "fluid_sys.h"
|
||||
//#include <fpu_control.h>
|
||||
|
||||
static char fluid_errbuf[512]; /* buffer for error message */
|
||||
|
||||
@@ -34,7 +33,7 @@ static char* fluid_libname = "fluidsynth";
|
||||
void fluid_sys_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) {
|
||||
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);
|
||||
va_end (args);
|
||||
va_end (args);
|
||||
|
||||
fun = fluid_log_function[FLUID_DBG];
|
||||
if (fun != NULL) {
|
||||
(*fun)(level, fluid_errbuf, fluid_log_user_data[FLUID_DBG]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#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_log_function_t old = NULL;
|
||||
@@ -79,10 +82,13 @@ fluid_set_log_function(int level, fluid_log_function_t fun, void* data)
|
||||
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)
|
||||
{
|
||||
FILE* out;
|
||||
@@ -92,25 +98,25 @@ fluid_default_log_function(int level, char* message, void* data)
|
||||
#else
|
||||
out = stderr;
|
||||
#endif
|
||||
|
||||
|
||||
if (fluid_log_initialized == 0) {
|
||||
fluid_log_config();
|
||||
}
|
||||
|
||||
switch (level) {
|
||||
case FLUID_PANIC:
|
||||
case FLUID_PANIC:
|
||||
FLUID_FPRINTF(out, "%s: panic: %s\n", fluid_libname, message);
|
||||
break;
|
||||
case FLUID_ERR:
|
||||
case FLUID_ERR:
|
||||
FLUID_FPRINTF(out, "%s: error: %s\n", fluid_libname, message);
|
||||
break;
|
||||
case FLUID_WARN:
|
||||
case FLUID_WARN:
|
||||
FLUID_FPRINTF(out, "%s: warning: %s\n", fluid_libname, message);
|
||||
break;
|
||||
case FLUID_INFO:
|
||||
case FLUID_INFO:
|
||||
FLUID_FPRINTF(out, "%s: %s\n", fluid_libname, message);
|
||||
break;
|
||||
case FLUID_DBG:
|
||||
case FLUID_DBG:
|
||||
#if DEBUG
|
||||
FLUID_FPRINTF(out, "%s: debug: %s\n", fluid_libname, message);
|
||||
#endif
|
||||
@@ -125,7 +131,7 @@ fluid_default_log_function(int level, char* message, void* data)
|
||||
/*
|
||||
* fluid_init_log
|
||||
*/
|
||||
void
|
||||
void
|
||||
fluid_log_config(void)
|
||||
{
|
||||
if (fluid_log_initialized == 0) {
|
||||
@@ -135,37 +141,41 @@ fluid_log_config(void)
|
||||
if (fluid_log_function[FLUID_PANIC] == NULL) {
|
||||
fluid_set_log_function(FLUID_PANIC, fluid_default_log_function, NULL);
|
||||
}
|
||||
|
||||
|
||||
if (fluid_log_function[FLUID_ERR] == NULL) {
|
||||
fluid_set_log_function(FLUID_ERR, fluid_default_log_function, NULL);
|
||||
}
|
||||
|
||||
|
||||
if (fluid_log_function[FLUID_WARN] == NULL) {
|
||||
fluid_set_log_function(FLUID_WARN, fluid_default_log_function, NULL);
|
||||
}
|
||||
|
||||
|
||||
if (fluid_log_function[FLUID_INFO] == NULL) {
|
||||
fluid_set_log_function(FLUID_INFO, fluid_default_log_function, NULL);
|
||||
}
|
||||
|
||||
|
||||
if (fluid_log_function[FLUID_DBG] == 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_function_t fun = NULL;
|
||||
|
||||
va_list args;
|
||||
va_start (args, fmt);
|
||||
va_list args;
|
||||
va_start (args, fmt);
|
||||
vsnprintf(fluid_errbuf, sizeof (fluid_errbuf), fmt, args);
|
||||
va_end (args);
|
||||
va_end (args);
|
||||
|
||||
if ((level >= 0) && (level < LAST_LOG_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]);
|
||||
}
|
||||
}
|
||||
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
|
||||
*/
|
||||
char*
|
||||
char*
|
||||
fluid_error()
|
||||
{
|
||||
return fluid_errbuf;
|
||||
@@ -188,9 +267,9 @@ fluid_error()
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
* fluid_is_midifile
|
||||
*/
|
||||
*/
|
||||
int
|
||||
fluid_is_midifile(char* filename)
|
||||
{
|
||||
@@ -205,14 +284,14 @@ fluid_is_midifile(char* filename)
|
||||
return 0;
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
|
||||
return strncmp(id, "MThd", 4) == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* fluid_is_soundfont
|
||||
*
|
||||
*/
|
||||
* fluid_is_soundfont
|
||||
*
|
||||
*/
|
||||
int
|
||||
fluid_is_soundfont(char* filename)
|
||||
{
|
||||
@@ -227,7 +306,7 @@ fluid_is_soundfont(char* filename)
|
||||
return 0;
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
|
||||
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;
|
||||
fluid_timer_callback_t callback;
|
||||
@@ -259,13 +338,13 @@ struct _fluid_timer_t
|
||||
static int fluid_timer_count = 0;
|
||||
DWORD WINAPI fluid_timer_run(LPVOID data);
|
||||
|
||||
fluid_timer_t*
|
||||
new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data,
|
||||
fluid_timer_t*
|
||||
new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data,
|
||||
int new_thread, int auto_destroy)
|
||||
{
|
||||
fluid_timer_t* timer = FLUID_NEW(fluid_timer_t);
|
||||
if (timer == NULL) {
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -279,18 +358,18 @@ new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data,
|
||||
if (new_thread) {
|
||||
timer->thread = CreateThread(NULL, 0, fluid_timer_run, (LPVOID) timer, 0, &timer->thread_id);
|
||||
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);
|
||||
return NULL;
|
||||
}
|
||||
SetThreadPriority(timer->thread, THREAD_PRIORITY_TIME_CRITICAL);
|
||||
} else {
|
||||
fluid_timer_run((LPVOID) timer);
|
||||
fluid_timer_run((LPVOID) timer);
|
||||
}
|
||||
return timer;
|
||||
}
|
||||
|
||||
DWORD WINAPI
|
||||
DWORD WINAPI
|
||||
fluid_timer_run(LPVOID data)
|
||||
{
|
||||
int count = 0;
|
||||
@@ -337,16 +416,16 @@ fluid_timer_run(LPVOID data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
delete_fluid_timer(fluid_timer_t* timer)
|
||||
{
|
||||
timer->cont = 0;
|
||||
fluid_timer_join(timer);
|
||||
fluid_timer_join(timer);
|
||||
FLUID_FREE(timer);
|
||||
return FLUID_OK;
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
fluid_timer_join(fluid_timer_t* timer)
|
||||
{
|
||||
DWORD wait_result;
|
||||
@@ -371,7 +450,7 @@ static double fluid_cpu_frequency = -1.0;
|
||||
void fluid_time_config(void)
|
||||
{
|
||||
if (fluid_cpu_frequency < 0.0) {
|
||||
fluid_cpu_frequency = fluid_estimate_cpu_frequency() / 1000000.0;
|
||||
fluid_cpu_frequency = fluid_estimate_cpu_frequency() / 1000000.0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -422,7 +501,7 @@ double fluid_estimate_cpu_frequency(void)
|
||||
QueryPerformanceCounter(&start);
|
||||
|
||||
Sleep(1000);
|
||||
|
||||
|
||||
after = fluid_curtime();
|
||||
QueryPerformanceCounter(&stop);
|
||||
|
||||
@@ -445,7 +524,7 @@ double fluid_estimate_cpu_frequency(void)
|
||||
* Timer
|
||||
*/
|
||||
|
||||
struct _fluid_timer_t
|
||||
struct _fluid_timer_t
|
||||
{
|
||||
TMTask myTmTask;
|
||||
long msec;
|
||||
@@ -472,13 +551,13 @@ _timerCallback(fluid_timer_t *timer)
|
||||
timer->count++;
|
||||
}
|
||||
|
||||
fluid_timer_t*
|
||||
new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data,
|
||||
fluid_timer_t*
|
||||
new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data,
|
||||
int new_thread, int auto_destroy)
|
||||
{
|
||||
fluid_timer_t* timer = FLUID_NEW(fluid_timer_t);
|
||||
if (timer == NULL) {
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -501,14 +580,14 @@ new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data,
|
||||
timer->isInstalled = 1;
|
||||
timer->count = 0;
|
||||
timer->auto_destroy = auto_destroy;
|
||||
|
||||
|
||||
InsXTime((QElemPtr)timer);
|
||||
PrimeTime((QElemPtr)timer, msec);
|
||||
|
||||
return timer;
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
delete_fluid_timer(fluid_timer_t* timer)
|
||||
{
|
||||
if (timer->isInstalled) {
|
||||
@@ -518,7 +597,7 @@ delete_fluid_timer(fluid_timer_t* timer)
|
||||
return FLUID_OK;
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
fluid_timer_join(fluid_timer_t* timer)
|
||||
{
|
||||
if (timer->isInstalled) {
|
||||
@@ -545,16 +624,17 @@ unsigned int fluid_curtime()
|
||||
UnsignedWide uS;
|
||||
double mSf;
|
||||
unsigned int ms;
|
||||
|
||||
|
||||
Microseconds(&uS);
|
||||
|
||||
|
||||
mSf = ((((double) uS.hi) * kTwoPower32) + uS.lo)/1000.0f;
|
||||
|
||||
|
||||
ms = mSf;
|
||||
|
||||
|
||||
return (ms);
|
||||
}
|
||||
|
||||
|
||||
#elif __BEOS__
|
||||
|
||||
struct _fluid_timer_t
|
||||
@@ -660,8 +740,8 @@ double fluid_utime(void)
|
||||
*
|
||||
* Timer
|
||||
*/
|
||||
|
||||
struct _fluid_timer_t
|
||||
|
||||
struct _fluid_timer_t
|
||||
{
|
||||
long msec;
|
||||
fluid_timer_callback_t callback;
|
||||
@@ -671,7 +751,7 @@ struct _fluid_timer_t
|
||||
int auto_destroy;
|
||||
};
|
||||
|
||||
void*
|
||||
void*
|
||||
fluid_timer_start(void *data)
|
||||
{
|
||||
int count = 0;
|
||||
@@ -714,8 +794,8 @@ fluid_timer_start(void *data)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fluid_timer_t*
|
||||
new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data,
|
||||
fluid_timer_t*
|
||||
new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data,
|
||||
int new_thread, int auto_destroy)
|
||||
{
|
||||
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);
|
||||
if (timer == NULL) {
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
return NULL;
|
||||
}
|
||||
timer->msec = msec;
|
||||
@@ -736,7 +816,7 @@ new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data,
|
||||
timer->thread = 0;
|
||||
timer->auto_destroy = auto_destroy;
|
||||
|
||||
err = pthread_attr_init(&rt_attr);
|
||||
err = pthread_attr_init(&rt_attr);
|
||||
if (err == 0) {
|
||||
err = pthread_attr_setschedpolicy(&rt_attr, SCHED_FIFO);
|
||||
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);
|
||||
if (err == 0) {
|
||||
attr = &rt_attr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (new_thread) {
|
||||
err = pthread_create(&timer->thread, attr, fluid_timer_start, (void*) timer);
|
||||
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 {
|
||||
/* Create the thread with default attributes */
|
||||
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;
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
delete_fluid_timer(fluid_timer_t* timer)
|
||||
{
|
||||
timer->cont = 0;
|
||||
@@ -779,7 +859,7 @@ delete_fluid_timer(fluid_timer_t* timer)
|
||||
return FLUID_OK;
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
fluid_timer_join(fluid_timer_t* timer)
|
||||
{
|
||||
int err = 0;
|
||||
@@ -805,7 +885,8 @@ double fluid_estimate_cpu_frequency(void);
|
||||
void fluid_time_config(void)
|
||||
{
|
||||
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 before, after;
|
||||
|
||||
before = fluid_curtime();
|
||||
before = fluid_curtime();
|
||||
__asm__ ("rdtsc" : "=a" (a0), "=d" (b0));
|
||||
|
||||
sleep(1);
|
||||
|
||||
|
||||
after = fluid_curtime();
|
||||
__asm__ ("rdtsc" : "=a" (a1), "=d" (b1));
|
||||
|
||||
@@ -866,7 +947,7 @@ double fluid_estimate_cpu_frequency(void)
|
||||
#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
|
||||
* 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
|
||||
* this up again some time later.
|
||||
@@ -900,7 +981,8 @@ double fluid_estimate_cpu_frequency(void)
|
||||
#define _FPU_CLR_SW() __asm__ ("fnclex" : : )
|
||||
|
||||
/* 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)
|
||||
{
|
||||
@@ -909,11 +991,10 @@ unsigned int fluid_check_fpe_i386(char* explanation)
|
||||
_FPU_GET_SW(s);
|
||||
_FPU_CLR_SW();
|
||||
|
||||
if ((s & _FPU_STATUS_IE)
|
||||
|| (s & _FPU_STATUS_DE)
|
||||
|| (s & _FPU_STATUS_ZE)
|
||||
|| (s & _FPU_STATUS_OE)
|
||||
|| (s & _FPU_STATUS_UE)) {
|
||||
s &= _FPU_STATUS_IE | _FPU_STATUS_DE | _FPU_STATUS_ZE | _FPU_STATUS_OE | _FPU_STATUS_UE;
|
||||
|
||||
if (s)
|
||||
{
|
||||
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_DE) ? "Denormal number " : "",
|
||||
@@ -921,14 +1002,22 @@ unsigned int fluid_check_fpe_i386(char* explanation)
|
||||
(s & _FPU_STATUS_OE) ? "Overflow " : "",
|
||||
(s & _FPU_STATUS_UE) ? "Underflow " : "");
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
|
||||
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_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_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_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;
|
||||
|
||||
printf("fluid_profiling_print\n");
|
||||
|
||||
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 CPU frequency: %.0f MHz", fluid_cpu_frequency);
|
||||
FLUID_LOG(FLUID_INFO, "Estimated times: min/avg/max (micro seconds)");
|
||||
|
||||
for (i = 0; i < FLUID_PROF_LAST; i++) {
|
||||
if (fluid_profile_data[i].count > 0) {
|
||||
FLUID_LOG(FLUID_INFO, "%s: %.3f/%.3f/%.3f",
|
||||
fluid_profile_data[i].description,
|
||||
fluid_profile_data[i].min,
|
||||
fluid_profile_data[i].total / fluid_profile_data[i].count,
|
||||
FLUID_LOG(FLUID_INFO, "%s: %.3f/%.3f/%.3f",
|
||||
fluid_profile_data[i].description,
|
||||
fluid_profile_data[i].min,
|
||||
fluid_profile_data[i].total / fluid_profile_data[i].count,
|
||||
fluid_profile_data[i].max);
|
||||
} else {
|
||||
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);
|
||||
|
||||
if (thread->detached) {
|
||||
FLUID_FREE(thread);
|
||||
FLUID_FREE(thread);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (func == NULL) {
|
||||
FLUID_LOG(FLUID_ERR, "Invalid thread function");
|
||||
FLUID_LOG(FLUID_ERR, "Invalid thread function");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
thread = FLUID_NEW(fluid_thread_t);
|
||||
if (thread == NULL) {
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
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->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);
|
||||
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);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
return thread;
|
||||
}
|
||||
|
||||
int delete_fluid_thread(fluid_thread_t* 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);
|
||||
|
||||
if (thread->detached) {
|
||||
FLUID_FREE(thread);
|
||||
FLUID_FREE(thread);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (func == NULL) {
|
||||
FLUID_LOG(FLUID_ERR, "Invalid thread function");
|
||||
FLUID_LOG(FLUID_ERR, "Invalid thread function");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
thread = FLUID_NEW(fluid_thread_t);
|
||||
if (thread == NULL) {
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1124,14 +1213,14 @@ fluid_thread_t* new_fluid_thread(fluid_thread_func_t func, void* data, int detac
|
||||
FLUID_FREE(thread);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
return thread;
|
||||
}
|
||||
|
||||
int delete_fluid_thread(fluid_thread_t* thread)
|
||||
{
|
||||
FLUID_FREE(thread);
|
||||
return FLUID_OK;
|
||||
return FLUID_OK;
|
||||
}
|
||||
|
||||
int fluid_thread_join(fluid_thread_t* thread)
|
||||
@@ -1235,7 +1324,7 @@ static void fluid_server_socket_run(void* data)
|
||||
while (server_socket->cont) {
|
||||
|
||||
client_socket = accept(server_socket->socket, (struct sockaddr*) &addr, &addrlen);
|
||||
|
||||
|
||||
FLUID_LOG(FLUID_DBG, "New client connection");
|
||||
|
||||
if (client_socket == INVALID_SOCKET) {
|
||||
@@ -1250,13 +1339,13 @@ static void fluid_server_socket_run(void* data)
|
||||
if (r != 0) {
|
||||
fluid_socket_close(client_socket);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
if (server_socket == NULL) {
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
fluid_socket_close(sock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -43,8 +43,15 @@ void fluid_sys_config(void);
|
||||
void fluid_log_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
|
||||
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, ...);
|
||||
|
||||
#else
|
||||
#define fluid_debug
|
||||
#define fluid_debug
|
||||
#endif
|
||||
|
||||
|
||||
@@ -98,7 +105,7 @@ double fluid_utime(void);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
Timers
|
||||
|
||||
*/
|
||||
@@ -109,25 +116,25 @@ typedef int (*fluid_timer_callback_t)(void* data, unsigned int msec);
|
||||
|
||||
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);
|
||||
|
||||
int delete_fluid_timer(fluid_timer_t* timer);
|
||||
int fluid_timer_join(fluid_timer_t* timer);
|
||||
int fluid_timer_stop(fluid_timer_t* timer);
|
||||
|
||||
/**
|
||||
/**
|
||||
|
||||
Muteces
|
||||
Muteces
|
||||
|
||||
*/
|
||||
|
||||
#if defined(MACOS9)
|
||||
typedef int fluid_mutex_t;
|
||||
#define fluid_mutex_init(_m) { (_m) = 0; }
|
||||
#define fluid_mutex_destroy(_m)
|
||||
#define fluid_mutex_lock(_m)
|
||||
#define fluid_mutex_unlock(_m)
|
||||
#define fluid_mutex_destroy(_m)
|
||||
#define fluid_mutex_lock(_m)
|
||||
#define fluid_mutex_unlock(_m)
|
||||
|
||||
#elif defined(WIN32)
|
||||
typedef HANDLE fluid_mutex_t;
|
||||
@@ -140,7 +147,7 @@ typedef HANDLE fluid_mutex_t;
|
||||
#ifndef HAIKU_TARGET_PLATFORM_HAIKU
|
||||
typedef sem_id fluid_mutex_t;
|
||||
#define fluid_mutex_init(_m) { (_m) = create_sem(1, "fs_sem"); }
|
||||
#define fluid_mutex_destroy(_m) delete_sem(_m);
|
||||
#define fluid_mutex_destroy(_m) delete_sem(_m);
|
||||
#define fluid_mutex_lock(_m) acquire_sem(_m);
|
||||
#define fluid_mutex_unlock(_m) release_sem(_m);
|
||||
|
||||
@@ -153,6 +160,7 @@ typedef pthread_mutex_t fluid_mutex_t;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
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
|
||||
here. Be sure to add an entry in the fluid_profile_data table in
|
||||
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
|
||||
sample data.
|
||||
@@ -280,26 +288,26 @@ extern fluid_profile_data_t fluid_profile_data[];
|
||||
#define fluid_munlock(_p,_n) munlock(_p,_n)
|
||||
#else
|
||||
#define fluid_mlock(_p,_n) 0
|
||||
#define fluid_munlock(_p,_n)
|
||||
#define fluid_munlock(_p,_n)
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
|
||||
Floating point exceptions
|
||||
Floating point exceptions
|
||||
|
||||
fluid_check_fpe() checks for "unnormalized numbers" and other
|
||||
exceptions of the floating point processsor.
|
||||
*/
|
||||
#if 0
|
||||
/* Enable FPE exception check */
|
||||
#ifdef FPE_CHECK
|
||||
#define fluid_check_fpe(expl) fluid_check_fpe_i386(expl)
|
||||
#define fluid_clear_fpe() fluid_clear_fpe_i386()
|
||||
#else
|
||||
/* Disable FPE exception check */
|
||||
#define fluid_check_fpe(expl)
|
||||
#define fluid_clear_fpe()
|
||||
#endif
|
||||
|
||||
unsigned int fluid_check_fpe_i386(char * explanation_in_case_of_fpe);
|
||||
void fluid_clear_fpe_i386(void);
|
||||
|
||||
#endif /* _FLUID_SYS_H */
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -38,7 +38,7 @@ fluid_tuning_t* new_fluid_tuning(char* name, int bank, int prog)
|
||||
|
||||
if (name != NULL) {
|
||||
tuning->name = FLUID_STRDUP(name);
|
||||
}
|
||||
}
|
||||
|
||||
tuning->bank = bank;
|
||||
tuning->prog = prog;
|
||||
@@ -69,7 +69,7 @@ void fluid_tuning_set_name(fluid_tuning_t* tuning, char* name)
|
||||
}
|
||||
if (name != NULL) {
|
||||
tuning->name = FLUID_STRDUP(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char* fluid_tuning_get_name(fluid_tuning_t* tuning)
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -43,9 +43,9 @@ enum fluid_voice_status
|
||||
struct _fluid_env_data_t {
|
||||
unsigned int count;
|
||||
fluid_real_t coeff;
|
||||
fluid_real_t incr;
|
||||
fluid_real_t min;
|
||||
fluid_real_t max;
|
||||
fluid_real_t incr;
|
||||
fluid_real_t min;
|
||||
fluid_real_t max;
|
||||
};
|
||||
|
||||
/* Indices for envelope tables */
|
||||
@@ -60,20 +60,12 @@ enum fluid_voice_envelope_index_t{
|
||||
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
|
||||
*/
|
||||
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 */
|
||||
unsigned char status;
|
||||
unsigned char chan; /* the channel number, quick access for channel messages */
|
||||
@@ -85,7 +77,7 @@ struct _fluid_voice_t
|
||||
int mod_count;
|
||||
int has_looped; /* Flag that is set as soon as the first loop is completed. */
|
||||
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. */
|
||||
#if 0
|
||||
/* 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 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 */
|
||||
|
||||
#if 0
|
||||
fluid_real_t incr; /* the phase increment for the next 64 samples [NEW, PH] */
|
||||
#endif
|
||||
/* Temporary variables used in fluid_voice_write() */
|
||||
|
||||
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 */
|
||||
fluid_real_t pitch; /* the pitch in midicents */
|
||||
@@ -134,7 +130,7 @@ struct _fluid_voice_t
|
||||
int start;
|
||||
int end;
|
||||
int loopstart;
|
||||
int loopend;
|
||||
int loopend; /* Note: first point following the loop (superimposed on loopstart) */
|
||||
|
||||
/* master gain */
|
||||
fluid_real_t synth_gain;
|
||||
@@ -152,22 +148,22 @@ struct _fluid_voice_t
|
||||
unsigned int modenv_count;
|
||||
int modenv_section;
|
||||
fluid_real_t modenv_val; /* the value of the modulation envelope */
|
||||
fluid_real_t modenv_to_fc;
|
||||
fluid_real_t modenv_to_pitch;
|
||||
fluid_real_t modenv_to_fc;
|
||||
fluid_real_t modenv_to_pitch;
|
||||
|
||||
/* mod lfo */
|
||||
fluid_real_t modlfo_val; /* the value of the modulation LFO */
|
||||
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_to_fc;
|
||||
fluid_real_t modlfo_to_pitch;
|
||||
fluid_real_t modlfo_to_vol;
|
||||
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_pitch;
|
||||
fluid_real_t modlfo_to_vol;
|
||||
|
||||
/* vib lfo */
|
||||
fluid_real_t viblfo_val; /* the value of the vibrato LFO */
|
||||
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_to_pitch;
|
||||
fluid_real_t viblfo_incr; /* the lfo frequency is converted to a per-buffer increment */
|
||||
fluid_real_t viblfo_to_pitch;
|
||||
|
||||
/* resonant filter */
|
||||
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 filter_gain; /* Gain correction factor, depends on q */
|
||||
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. */
|
||||
|
||||
/* filter coefficients */
|
||||
@@ -219,14 +215,14 @@ struct _fluid_voice_t
|
||||
fluid_voice_t* new_fluid_voice(fluid_real_t output_rate);
|
||||
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,
|
||||
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);
|
||||
|
||||
int fluid_voice_init(fluid_voice_t* voice, fluid_sample_t* sample,
|
||||
fluid_channel_t* channel, int key, int vel,
|
||||
int fluid_voice_init(fluid_voice_t* voice, fluid_sample_t* sample,
|
||||
fluid_channel_t* channel, int key, int vel,
|
||||
unsigned int id, unsigned int time, fluid_real_t gain);
|
||||
|
||||
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_calculate_runtime_synthesis_parameters(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 fluid_voice_kill_excl(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_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 */
|
||||
|
||||
@@ -11,14 +11,16 @@
|
||||
* 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
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
@@ -37,10 +39,6 @@
|
||||
|
||||
#include "fluidsynth.h"
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#if defined(WIN32) && !defined(MINGW32)
|
||||
#include "config_win32.h"
|
||||
#endif
|
||||
@@ -88,7 +86,7 @@ extern int optind, opterr, optopt;
|
||||
/* process_o_cmd_line_option
|
||||
*
|
||||
* Purpose:
|
||||
* Process a command line option -o setting=value,
|
||||
* Process a command line option -o setting=value,
|
||||
* for example: -o synth.polyhony=16
|
||||
*/
|
||||
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:
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -180,7 +178,7 @@ settings_foreach_func (void *data, char *name, int type)
|
||||
|
||||
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
/*
|
||||
/*
|
||||
* handle_signal
|
||||
*/
|
||||
void handle_signal(int sig_num)
|
||||
@@ -192,7 +190,7 @@ void handle_signal(int sig_num)
|
||||
/*
|
||||
* main
|
||||
*/
|
||||
int main(int argc, char** argv)
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
fluid_settings_t* settings;
|
||||
int arg1 = 1;
|
||||
@@ -200,7 +198,7 @@ int main(int argc, char** argv)
|
||||
int c, i, fragcount = DEFAULT_FRAG_COUNT;
|
||||
int interactive = 1;
|
||||
int midi_in = 1;
|
||||
fluid_player_t* player = NULL;
|
||||
fluid_player_t* player = NULL;
|
||||
fluid_midi_router_t* router = NULL;
|
||||
fluid_midi_driver_t* mdriver = NULL;
|
||||
fluid_audio_driver_t* adriver = NULL;
|
||||
@@ -354,7 +352,7 @@ int main(int argc, char** argv)
|
||||
case 'n':
|
||||
midi_in = 0;
|
||||
break;
|
||||
case 'o':
|
||||
case 'o':
|
||||
process_o_cmd_line_option(settings, optarg);
|
||||
break;
|
||||
case 'R':
|
||||
@@ -433,16 +431,16 @@ int main(int argc, char** argv)
|
||||
*/
|
||||
if ((audio_groups == 0) && (audio_channels != 0)) {
|
||||
audio_groups = audio_channels;
|
||||
}
|
||||
}
|
||||
fluid_settings_setint(settings, "synth.audio-groups", audio_groups);
|
||||
|
||||
|
||||
/* create the synthesizer */
|
||||
synth = new_fluid_synth(settings);
|
||||
if (synth == NULL) {
|
||||
fprintf(stderr, "Failed to create the synthesizer\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
||||
cmd_handler = new_fluid_cmd_handler(synth);
|
||||
if (cmd_handler == NULL) {
|
||||
fprintf(stderr, "Failed to create the command handler\n");
|
||||
@@ -458,13 +456,16 @@ int main(int argc, char** argv)
|
||||
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++) {
|
||||
if ((argv[i][0] != '-') && fluid_is_soundfont(argv[i])) {
|
||||
if (fluid_synth_sfload(synth, argv[i], 1) == -1) {
|
||||
if (fluid_is_soundfont(argv[i]))
|
||||
{
|
||||
if (fluid_synth_sfload(synth, argv[i], 1) == -1)
|
||||
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
|
||||
@@ -487,10 +488,10 @@ int main(int argc, char** argv)
|
||||
*/
|
||||
|
||||
router = new_fluid_midi_router(
|
||||
settings,
|
||||
dump ? fluid_midi_dump_postrouter : fluid_synth_handle_midi_event,
|
||||
settings,
|
||||
dump ? fluid_midi_dump_postrouter : fluid_synth_handle_midi_event,
|
||||
(void*)synth);
|
||||
|
||||
|
||||
if (router == NULL) {
|
||||
fprintf(stderr, "Failed to create the MIDI input router; no MIDI input\n"
|
||||
"will be available. You can access the synthesizer \n"
|
||||
@@ -498,7 +499,7 @@ int main(int argc, char** argv)
|
||||
} else {
|
||||
fluid_synth_set_midi_router(synth, router); /* Fixme, needed for command handler */
|
||||
mdriver = new_fluid_midi_driver(
|
||||
settings,
|
||||
settings,
|
||||
dump ? fluid_midi_dump_prerouter : fluid_midi_router_handle_midi_event,
|
||||
(void*) router);
|
||||
if (mdriver == NULL) {
|
||||
@@ -561,7 +562,7 @@ int main(int argc, char** argv)
|
||||
* 0.
|
||||
*/
|
||||
fluid_settings_setstr(settings, "shell.prompt", dump ? "" : "> ");
|
||||
fluid_usershell(settings, cmd_handler);
|
||||
fluid_usershell(settings, cmd_handler);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
@@ -584,7 +585,7 @@ int main(int argc, char** argv)
|
||||
/* if the user typed 'quit' in the shell, stop the player */
|
||||
if (interactive) {
|
||||
fluid_player_stop(player);
|
||||
}
|
||||
}
|
||||
fluid_player_join(player);
|
||||
delete_fluid_player(player);
|
||||
}
|
||||
@@ -623,8 +624,8 @@ static fluid_cmd_handler_t* newclient(void* data, char* addr)
|
||||
/*
|
||||
* print_usage
|
||||
*/
|
||||
void
|
||||
print_usage()
|
||||
void
|
||||
print_usage()
|
||||
{
|
||||
print_welcome ();
|
||||
fprintf(stderr, "Usage: fluidsynth [options] [soundfonts]\n");
|
||||
@@ -635,8 +636,8 @@ print_usage()
|
||||
/*
|
||||
* print_welcome
|
||||
*/
|
||||
void
|
||||
print_welcome()
|
||||
void
|
||||
print_welcome()
|
||||
{
|
||||
printf("FluidSynth version %s\n"
|
||||
"Copyright (C) 2000-2006 Peter Hanappe and others.\n"
|
||||
@@ -648,8 +649,8 @@ print_welcome()
|
||||
/*
|
||||
* print_help
|
||||
*/
|
||||
void
|
||||
print_help()
|
||||
void
|
||||
print_help()
|
||||
{
|
||||
print_welcome ();
|
||||
printf("Usage: \n");
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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
|
||||
@@ -26,9 +26,9 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
//#if defined(__POWERPC__) && !(defined(__APPLE__) && defined(__MACH__))
|
||||
//#include "config_maxmsp43.h"
|
||||
//#endif
|
||||
#if defined(__POWERPC__) && !(defined(__APPLE__) && defined(__MACH__))
|
||||
#include "config_maxmsp43.h"
|
||||
#endif
|
||||
|
||||
#if defined(WIN32) && !defined(MINGW32)
|
||||
#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_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
|
||||
@@ -267,7 +267,7 @@ typedef FILE* fluid_file;
|
||||
#define FLUID_FSEEK(_f,_n,_set) fseek(_f,_n,_set)
|
||||
#define FLUID_MEMCPY(_dst,_src,_n) memcpy(_dst,_src,_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_STRNCMP(_s,_t,_n) strncmp(_s,_t,_n)
|
||||
#define FLUID_STRCPY(_dst,_src) strcpy(_dst,_src)
|
||||
@@ -276,31 +276,16 @@ typedef FILE* fluid_file;
|
||||
#define FLUID_STRDUP(s) strdup(s)
|
||||
#else
|
||||
#define FLUID_STRDUP(s) FLUID_STRCPY(FLUID_MALLOC(FLUID_STRLEN(s) + 1), s)
|
||||
#endif
|
||||
#endif
|
||||
#define FLUID_SPRINTF sprintf
|
||||
#define FLUID_FPRINTF fprintf
|
||||
|
||||
#define fluid_clip(_val, _min, _max) \
|
||||
{ (_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
|
||||
#define FLUID_PRINTF post
|
||||
#define FLUID_FLUSH()
|
||||
#define FLUID_FLUSH()
|
||||
#else
|
||||
#define FLUID_PRINTF printf
|
||||
#define FLUID_FLUSH() fflush(stdout)
|
||||
|
||||
Reference in New Issue
Block a user