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
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @file fluidsynth.h
|
||||||
\file fluidsynth.h
|
* @brief FluidSynth is a real-time synthesizer designed for SoundFont(R) files.
|
||||||
|
*
|
||||||
\brief fluidsynth is a real-time SoundFont(R) synthesizer. This is
|
* This is the header of the fluidsynth library and contains the
|
||||||
the header of the fluidsynth library and contains the
|
* synthesizer's public API.
|
||||||
synthesizer's public API.
|
*
|
||||||
|
* Depending on how you want to use or extend the synthesizer you
|
||||||
Depending on how you want to use or extend the synthesizer you
|
* will need different API functions. You probably do not need all
|
||||||
will need different API functions. You probably do not need all
|
* of them. Here is what you might want to do:
|
||||||
of them. Here is what you might want to do:
|
*
|
||||||
|
* o Embedded synthesizer: create a new synthesizer and send MIDI
|
||||||
o Embedded synthesizer: create a new synthesizer and send MIDI
|
* events to it. The sound goes directly to the audio output of
|
||||||
events to it. The sound goes directly to the audio output of
|
* your system.
|
||||||
your system.
|
*
|
||||||
|
* o Plugin synthesizer: create a synthesizer and send MIDI events
|
||||||
o Plugin synthesizer: create a synthesizer and send MIDI events
|
* but pull the audio back into your application.
|
||||||
but pull the audio back into your application.
|
*
|
||||||
|
* o SoundFont plugin: create a new type of "SoundFont" and allow
|
||||||
o SoundFont plugin: create a new type of "SoundFont" and allow
|
* the synthesizer to load your type of SoundFonts.
|
||||||
the synthesizer to load your type of SoundFonts.
|
*
|
||||||
|
* o MIDI input: Create a MIDI handler to read the MIDI input on your
|
||||||
o MIDI input: Create a MIDI handler to read the MIDI input on your
|
* machine and send the MIDI events directly to the synthesizer.
|
||||||
machine and send the MIDI events directly to the synthesizer.
|
*
|
||||||
|
* o MIDI files: Open MIDI files and send the MIDI events to the
|
||||||
o MIDI files: Open MIDI files and send the MIDI events to the
|
* synthesizer.
|
||||||
synthesizer.
|
*
|
||||||
|
* o Command lines: You can send textual commands to the synthesizer.
|
||||||
o Command lines: You can send textual commands to the synthesizer.
|
*
|
||||||
|
* SoundFont(R) is a registered trademark of E-mu Systems, Inc.
|
||||||
|
*/
|
||||||
SoundFont(R) is a registered trademark of E-mu Systems, Inc.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "fluidsynth/types.h"
|
#include "fluidsynth/types.h"
|
||||||
#include "fluidsynth/settings.h"
|
#include "fluidsynth/settings.h"
|
||||||
|
|||||||
@@ -25,15 +25,29 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file audio.h
|
||||||
|
* @brief Functions for audio driver output.
|
||||||
|
*
|
||||||
|
* Defines functions for creating audio driver output. Use
|
||||||
|
* new_fluid_audio_driver() to create a new audio driver for a given synth
|
||||||
|
* and configuration settings. The function new_fluid_audio_driver2() can be
|
||||||
|
* used if custom audio processing is desired before the audio is sent to the
|
||||||
|
* audio driver (although it is not as efficient).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
/** Audio driver
|
* Callback function type used with new_fluid_audio_driver2() to allow for
|
||||||
*
|
* custom user audio processing before the audio is sent to the driver. This
|
||||||
*
|
* function is responsible for rendering the audio to the buffers.
|
||||||
*/
|
* @param data The user data parameter as passed to new_fluid_audio_driver2().
|
||||||
|
* @param len Length of the audio in frames.
|
||||||
|
* @param nin Count of buffers in 'in'
|
||||||
/** The function should return non-zero if an error occured. */
|
* @param in FIXME - Not used currently?
|
||||||
|
* @param nout Count of arrays in 'out' (i.e., channel count)
|
||||||
|
* @param out Output buffers, one for each channel
|
||||||
|
* @return Should return 0 on success, non-zero if an error occured.
|
||||||
|
*/
|
||||||
typedef int (*fluid_audio_func_t)(void* data, int len,
|
typedef int (*fluid_audio_func_t)(void* data, int len,
|
||||||
int nin, float** in,
|
int nin, float** in,
|
||||||
int nout, float** out);
|
int nout, float** out);
|
||||||
|
|||||||
@@ -25,28 +25,37 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file event.h
|
||||||
|
* @brief Sequencer event functions and defines.
|
||||||
|
*
|
||||||
|
* Functions and constants for creating/processing sequencer events.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sequencer event type enumeration.
|
||||||
|
*/
|
||||||
enum fluid_seq_event_type {
|
enum fluid_seq_event_type {
|
||||||
FLUID_SEQ_NOTE = 0,
|
FLUID_SEQ_NOTE = 0, /**< Note event (DOCME) */
|
||||||
FLUID_SEQ_NOTEON,
|
FLUID_SEQ_NOTEON, /**< Note on event */
|
||||||
FLUID_SEQ_NOTEOFF,
|
FLUID_SEQ_NOTEOFF, /**< Note off event */
|
||||||
FLUID_SEQ_ALLSOUNDSOFF,
|
FLUID_SEQ_ALLSOUNDSOFF, /**< All sounds off event */
|
||||||
FLUID_SEQ_ALLNOTESOFF,
|
FLUID_SEQ_ALLNOTESOFF, /**< All notes off event */
|
||||||
FLUID_SEQ_BANKSELECT,
|
FLUID_SEQ_BANKSELECT, /**< Bank select message */
|
||||||
FLUID_SEQ_PROGRAMCHANGE,
|
FLUID_SEQ_PROGRAMCHANGE, /**< Program change message */
|
||||||
FLUID_SEQ_PROGRAMSELECT,
|
FLUID_SEQ_PROGRAMSELECT, /**< Program select message (DOCME) */
|
||||||
FLUID_SEQ_PITCHBEND,
|
FLUID_SEQ_PITCHBEND, /**< Pitch bend message */
|
||||||
FLUID_SEQ_PITCHWHHELSENS,
|
FLUID_SEQ_PITCHWHHELSENS, /**< Pitch wheel sensitivity set message */
|
||||||
FLUID_SEQ_MODULATION,
|
FLUID_SEQ_MODULATION, /**< Modulation controller event */
|
||||||
FLUID_SEQ_SUSTAIN,
|
FLUID_SEQ_SUSTAIN, /**< Sustain controller event */
|
||||||
FLUID_SEQ_CONTROLCHANGE,
|
FLUID_SEQ_CONTROLCHANGE, /**< MIDI control change event */
|
||||||
FLUID_SEQ_PAN,
|
FLUID_SEQ_PAN, /**< Stereo pan set event */
|
||||||
FLUID_SEQ_VOLUME,
|
FLUID_SEQ_VOLUME, /**< Volume set event */
|
||||||
FLUID_SEQ_REVERBSEND,
|
FLUID_SEQ_REVERBSEND, /**< Reverb send set event */
|
||||||
FLUID_SEQ_CHORUSSEND,
|
FLUID_SEQ_CHORUSSEND, /**< Chorus send set event */
|
||||||
FLUID_SEQ_TIMER,
|
FLUID_SEQ_TIMER, /**< Timer event (DOCME) */
|
||||||
FLUID_SEQ_ANYCONTROLCHANGE, // used for remove_events only
|
FLUID_SEQ_ANYCONTROLCHANGE, /**< DOCME (used for remove_events only) */
|
||||||
FLUID_SEQ_LASTEVENT
|
FLUID_SEQ_LASTEVENT /**< Defines the count of event enums */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Event alloc/free */
|
/* Event alloc/free */
|
||||||
|
|||||||
@@ -25,99 +25,105 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file gen.h
|
||||||
|
* @brief Functions and defines for SoundFont generator effects.
|
||||||
|
*/
|
||||||
|
|
||||||
/** List of generator numbers
|
/**
|
||||||
Soundfont 2.01 specifications section 8.1.3 */
|
* Generator (effect) numbers (Soundfont 2.01 specifications section 8.1.3)
|
||||||
|
*/
|
||||||
enum fluid_gen_type {
|
enum fluid_gen_type {
|
||||||
GEN_STARTADDROFS,
|
GEN_STARTADDROFS, /**< Sample start address offset (0-32767) */
|
||||||
GEN_ENDADDROFS,
|
GEN_ENDADDROFS, /**< Sample end address offset (-32767-0) */
|
||||||
GEN_STARTLOOPADDROFS,
|
GEN_STARTLOOPADDROFS, /**< Sample loop start address offset (-32767-32767) */
|
||||||
GEN_ENDLOOPADDROFS,
|
GEN_ENDLOOPADDROFS, /**< Sample loop end address offset (-32767-32767) */
|
||||||
GEN_STARTADDRCOARSEOFS,
|
GEN_STARTADDRCOARSEOFS, /**< Sample start address coarse offset (X 32768) */
|
||||||
GEN_MODLFOTOPITCH,
|
GEN_MODLFOTOPITCH, /**< Modulation LFO to pitch */
|
||||||
GEN_VIBLFOTOPITCH,
|
GEN_VIBLFOTOPITCH, /**< Vibrato LFO to pitch */
|
||||||
GEN_MODENVTOPITCH,
|
GEN_MODENVTOPITCH, /**< Modulation envelope to pitch */
|
||||||
GEN_FILTERFC,
|
GEN_FILTERFC, /**< Filter cutoff */
|
||||||
GEN_FILTERQ,
|
GEN_FILTERQ, /**< Filter Q */
|
||||||
GEN_MODLFOTOFILTERFC,
|
GEN_MODLFOTOFILTERFC, /**< Modulation LFO to filter cutoff */
|
||||||
GEN_MODENVTOFILTERFC,
|
GEN_MODENVTOFILTERFC, /**< Modulation envelope to filter cutoff */
|
||||||
GEN_ENDADDRCOARSEOFS,
|
GEN_ENDADDRCOARSEOFS, /**< Sample end address coarse offset (X 32768) */
|
||||||
GEN_MODLFOTOVOL,
|
GEN_MODLFOTOVOL, /**< Modulation LFO to volume */
|
||||||
GEN_UNUSED1,
|
GEN_UNUSED1, /**< Unused */
|
||||||
GEN_CHORUSSEND,
|
GEN_CHORUSSEND, /**< Chorus send amount */
|
||||||
GEN_REVERBSEND,
|
GEN_REVERBSEND, /**< Reverb send amount */
|
||||||
GEN_PAN,
|
GEN_PAN, /**< Stereo panning */
|
||||||
GEN_UNUSED2,
|
GEN_UNUSED2, /**< Unused */
|
||||||
GEN_UNUSED3,
|
GEN_UNUSED3, /**< Unused */
|
||||||
GEN_UNUSED4,
|
GEN_UNUSED4, /**< Unused */
|
||||||
GEN_MODLFODELAY,
|
GEN_MODLFODELAY, /**< Modulation LFO delay */
|
||||||
GEN_MODLFOFREQ,
|
GEN_MODLFOFREQ, /**< Modulation LFO frequency */
|
||||||
GEN_VIBLFODELAY,
|
GEN_VIBLFODELAY, /**< Vibrato LFO delay */
|
||||||
GEN_VIBLFOFREQ,
|
GEN_VIBLFOFREQ, /**< Vibrato LFO frequency */
|
||||||
GEN_MODENVDELAY,
|
GEN_MODENVDELAY, /**< Modulation envelope delay */
|
||||||
GEN_MODENVATTACK,
|
GEN_MODENVATTACK, /**< Modulation envelope attack */
|
||||||
GEN_MODENVHOLD,
|
GEN_MODENVHOLD, /**< Modulation envelope hold */
|
||||||
GEN_MODENVDECAY,
|
GEN_MODENVDECAY, /**< Modulation envelope decay */
|
||||||
GEN_MODENVSUSTAIN,
|
GEN_MODENVSUSTAIN, /**< Modulation envelope sustain */
|
||||||
GEN_MODENVRELEASE,
|
GEN_MODENVRELEASE, /**< Modulation envelope release */
|
||||||
GEN_KEYTOMODENVHOLD,
|
GEN_KEYTOMODENVHOLD, /**< Key to modulation envelope hold */
|
||||||
GEN_KEYTOMODENVDECAY,
|
GEN_KEYTOMODENVDECAY, /**< Key to modulation envelope decay */
|
||||||
GEN_VOLENVDELAY,
|
GEN_VOLENVDELAY, /**< Volume envelope delay */
|
||||||
GEN_VOLENVATTACK,
|
GEN_VOLENVATTACK, /**< Volume envelope attack */
|
||||||
GEN_VOLENVHOLD,
|
GEN_VOLENVHOLD, /**< Volume envelope hold */
|
||||||
GEN_VOLENVDECAY,
|
GEN_VOLENVDECAY, /**< Volume envelope decay */
|
||||||
GEN_VOLENVSUSTAIN,
|
GEN_VOLENVSUSTAIN, /**< Volume envelope sustain */
|
||||||
GEN_VOLENVRELEASE,
|
GEN_VOLENVRELEASE, /**< Volume envelope release */
|
||||||
GEN_KEYTOVOLENVHOLD,
|
GEN_KEYTOVOLENVHOLD, /**< Key to volume envelope hold */
|
||||||
GEN_KEYTOVOLENVDECAY,
|
GEN_KEYTOVOLENVDECAY, /**< Key to volume envelope decay */
|
||||||
GEN_INSTRUMENT,
|
GEN_INSTRUMENT, /**< Instrument ID (shouldn't be set by user) */
|
||||||
GEN_RESERVED1,
|
GEN_RESERVED1, /**< Reserved */
|
||||||
GEN_KEYRANGE,
|
GEN_KEYRANGE, /**< MIDI note range */
|
||||||
GEN_VELRANGE,
|
GEN_VELRANGE, /**< MIDI velocity range */
|
||||||
GEN_STARTLOOPADDRCOARSEOFS,
|
GEN_STARTLOOPADDRCOARSEOFS, /**< Sample start loop address coarse offset (X 32768) */
|
||||||
GEN_KEYNUM,
|
GEN_KEYNUM, /**< Fixed MIDI note number */
|
||||||
GEN_VELOCITY,
|
GEN_VELOCITY, /**< Fixed MIDI velocity value */
|
||||||
GEN_ATTENUATION,
|
GEN_ATTENUATION, /**< Initial volume attenuation */
|
||||||
GEN_RESERVED2,
|
GEN_RESERVED2, /**< Reserved */
|
||||||
GEN_ENDLOOPADDRCOARSEOFS,
|
GEN_ENDLOOPADDRCOARSEOFS, /**< Sample end loop address coarse offset (X 32768) */
|
||||||
GEN_COARSETUNE,
|
GEN_COARSETUNE, /**< Coarse tuning */
|
||||||
GEN_FINETUNE,
|
GEN_FINETUNE, /**< Fine tuning */
|
||||||
GEN_SAMPLEID,
|
GEN_SAMPLEID, /**< Sample ID (shouldn't be set by user) */
|
||||||
GEN_SAMPLEMODE,
|
GEN_SAMPLEMODE, /**< Sample mode flags */
|
||||||
GEN_RESERVED3,
|
GEN_RESERVED3, /**< Reserved */
|
||||||
GEN_SCALETUNE,
|
GEN_SCALETUNE, /**< Scale tuning */
|
||||||
GEN_EXCLUSIVECLASS,
|
GEN_EXCLUSIVECLASS, /**< Exclusive class number */
|
||||||
GEN_OVERRIDEROOTKEY,
|
GEN_OVERRIDEROOTKEY, /**< Sample root note override */
|
||||||
|
|
||||||
/* the initial pitch is not a "standard" generator. It is not
|
/* the initial pitch is not a "standard" generator. It is not
|
||||||
* mentioned in the list of generator in the SF2 specifications. It
|
* mentioned in the list of generator in the SF2 specifications. It
|
||||||
* is used, however, as the destination for the default pitch wheel
|
* is used, however, as the destination for the default pitch wheel
|
||||||
* modulator. */
|
* modulator. */
|
||||||
GEN_PITCH,
|
GEN_PITCH, /**< Pitch (NOTE: Not a real SoundFont generator) */
|
||||||
GEN_LAST
|
GEN_LAST /**< Value defines the count of generators (#fluid_gen_type) */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* fluid_gen_t
|
* SoundFont generator structure.
|
||||||
* Sound font generator
|
*/
|
||||||
*/
|
|
||||||
typedef struct _fluid_gen_t
|
typedef struct _fluid_gen_t
|
||||||
{
|
{
|
||||||
unsigned char flags; /* is it used or not */
|
unsigned char flags; /**< Is the generator set or not (#fluid_gen_flags) */
|
||||||
double val; /* The nominal value */
|
double val; /**< The nominal value */
|
||||||
double mod; /* Change by modulators */
|
double mod; /**< Change by modulators */
|
||||||
double nrpn; /* Change by NRPN messages */
|
double nrpn; /**< Change by NRPN messages */
|
||||||
} fluid_gen_t;
|
} fluid_gen_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum value for 'flags' field of #_fluid_gen_t (not really flags).
|
||||||
|
*/
|
||||||
enum fluid_gen_flags
|
enum fluid_gen_flags
|
||||||
{
|
{
|
||||||
GEN_UNUSED,
|
GEN_UNUSED, /**< Generator value is not set */
|
||||||
GEN_SET,
|
GEN_SET, /**< Generator value is set */
|
||||||
GEN_ABS_NRPN
|
GEN_ABS_NRPN /**< DOCME */
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Reset an array of generators to the SF2.01 default values */
|
|
||||||
FLUIDSYNTH_API int fluid_gen_set_default_values(fluid_gen_t* gen);
|
FLUIDSYNTH_API int fluid_gen_set_default_values(fluid_gen_t* gen);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -27,57 +27,55 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @file log.h
|
||||||
* Logging interface
|
* @brief Logging interface
|
||||||
*
|
*
|
||||||
* The default logging function of the fluidsynth prints its messages
|
* The default logging function of the fluidsynth prints its messages
|
||||||
* to the stderr. The synthesizer uses four level of messages: FLUID_PANIC,
|
* to the stderr. The synthesizer uses five level of messages: #FLUID_PANIC,
|
||||||
* ERR, WARN, and FLUID_DBG. They are commented in the definition below.
|
* #FLUID_ERR, #FLUID_WARN, #FLUID_INFO, and #FLUID_DBG.
|
||||||
*
|
*
|
||||||
* A client application can install a new log function to handle the
|
* A client application can install a new log function to handle the
|
||||||
* messages differently. In the following example, the application
|
* messages differently. In the following example, the application
|
||||||
* sets a callback function to display "FLUID_PANIC" messages in a dialog,
|
* sets a callback function to display #FLUID_PANIC messages in a dialog,
|
||||||
* and ignores all other messages by setting the log function to
|
* and ignores all other messages by setting the log function to
|
||||||
* NULL:
|
* NULL:
|
||||||
*
|
*
|
||||||
* ...
|
* DOCME (formatting)
|
||||||
* fluid_set_log_function(FLUID_PANIC, show_dialog, (void*) root_window);
|
* fluid_set_log_function(FLUID_PANIC, show_dialog, (void*) root_window);
|
||||||
* fluid_set_log_function(ERR, NULL, NULL);
|
* fluid_set_log_function(FLUID_ERR, NULL, NULL);
|
||||||
* fluid_set_log_function(WARN, NULL, NULL);
|
* fluid_set_log_function(FLUID_WARN, NULL, NULL);
|
||||||
* fluid_set_log_function(FLUID_DBG, NULL, NULL);
|
* fluid_set_log_function(FLUID_DBG, NULL, NULL);
|
||||||
* ...
|
*/
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FluidSynth log levels.
|
||||||
|
*/
|
||||||
enum fluid_log_level {
|
enum fluid_log_level {
|
||||||
FLUID_PANIC, /* the synth can't function correctly any more */
|
FLUID_PANIC, /**< The synth can't function correctly any more */
|
||||||
FLUID_ERR, /* the synth can function, but with serious limitation */
|
FLUID_ERR, /**< Serious error occurred */
|
||||||
FLUID_WARN, /* the synth might not function as expected */
|
FLUID_WARN, /**< Warning */
|
||||||
FLUID_INFO, /* verbose messages */
|
FLUID_INFO, /**< Verbose informational messages */
|
||||||
FLUID_DBG, /* debugging messages */
|
FLUID_DBG, /**< Debugging messages */
|
||||||
LAST_LOG_LEVEL
|
LAST_LOG_LEVEL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log function handler callback type used by fluid_set_log_function().
|
||||||
|
* @param level Log level (#fluid_log_level)
|
||||||
|
* @param message Log message text
|
||||||
|
* @param data User data pointer supplied to fluid_set_log_function().
|
||||||
|
*/
|
||||||
typedef void (*fluid_log_function_t)(int level, char* message, void* data);
|
typedef void (*fluid_log_function_t)(int level, char* message, void* data);
|
||||||
|
|
||||||
/** fluid_set_log_function installs a new log function for the
|
|
||||||
* specified level. It returns the previously installed function.
|
|
||||||
*/
|
|
||||||
FLUIDSYNTH_API
|
FLUIDSYNTH_API
|
||||||
fluid_log_function_t fluid_set_log_function(int level, fluid_log_function_t fun, void* data);
|
fluid_log_function_t fluid_set_log_function(int level, fluid_log_function_t fun, void* data);
|
||||||
|
|
||||||
|
|
||||||
/** fluid_default_log_function is the fluid's default log function. It
|
|
||||||
* prints to the stderr. */
|
|
||||||
FLUIDSYNTH_API void fluid_default_log_function(int level, char* message, void* data);
|
FLUIDSYNTH_API void fluid_default_log_function(int level, char* message, void* data);
|
||||||
|
|
||||||
/** print a message to the log */
|
|
||||||
FLUIDSYNTH_API int fluid_log(int level, char * fmt, ...);
|
FLUIDSYNTH_API int fluid_log(int level, char * fmt, ...);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -25,7 +25,10 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file midi.h
|
||||||
|
* @brief Functions for MIDI events, drivers and MIDI file playback.
|
||||||
|
*/
|
||||||
|
|
||||||
FLUIDSYNTH_API fluid_midi_event_t* new_fluid_midi_event(void);
|
FLUIDSYNTH_API fluid_midi_event_t* new_fluid_midi_event(void);
|
||||||
FLUIDSYNTH_API int delete_fluid_midi_event(fluid_midi_event_t* event);
|
FLUIDSYNTH_API int delete_fluid_midi_event(fluid_midi_event_t* event);
|
||||||
@@ -48,58 +51,41 @@ FLUIDSYNTH_API int fluid_midi_event_get_pitch(fluid_midi_event_t* evt);
|
|||||||
FLUIDSYNTH_API int fluid_midi_event_set_pitch(fluid_midi_event_t* evt, int val);
|
FLUIDSYNTH_API int fluid_midi_event_set_pitch(fluid_midi_event_t* evt, int val);
|
||||||
|
|
||||||
|
|
||||||
/* Generic callback function for MIDI events.
|
/**
|
||||||
* Will be used between
|
* Generic callback function for MIDI events.
|
||||||
* - MIDI driver and MIDI router
|
* @param data User defined data pointer
|
||||||
* - MIDI router and synth
|
* @param event The MIDI event
|
||||||
* to communicate events.
|
* @return DOCME
|
||||||
* In the not-so-far future...
|
*
|
||||||
*/
|
* Will be used between
|
||||||
|
* - MIDI driver and MIDI router
|
||||||
|
* - MIDI router and synth
|
||||||
|
* to communicate events.
|
||||||
|
* In the not-so-far future...
|
||||||
|
*/
|
||||||
typedef int (*handle_midi_event_func_t)(void* data, fluid_midi_event_t* event);
|
typedef int (*handle_midi_event_func_t)(void* data, fluid_midi_event_t* event);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
* MIDI router
|
||||||
* MIDI router
|
*
|
||||||
*
|
* The MIDI handler forwards incoming MIDI events to the synthesizer
|
||||||
* The MIDI handler forwards incoming MIDI events to the synthesizer
|
*/
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** Create a new midi router. A midi handler connects to a midi input
|
|
||||||
* device and forwards incoming midi events to the synthesizer.
|
|
||||||
*/
|
|
||||||
FLUIDSYNTH_API fluid_midi_router_t* new_fluid_midi_router(fluid_settings_t* settings,
|
FLUIDSYNTH_API fluid_midi_router_t* new_fluid_midi_router(fluid_settings_t* settings,
|
||||||
handle_midi_event_func_t handler,
|
handle_midi_event_func_t handler,
|
||||||
void* event_handler_data);
|
void* event_handler_data);
|
||||||
|
|
||||||
/** Delete the midi router.
|
|
||||||
*
|
|
||||||
* \param handler a pointer to the midi handler
|
|
||||||
* \return 0 if no error occured, -1 otherwise
|
|
||||||
*/
|
|
||||||
FLUIDSYNTH_API int delete_fluid_midi_router(fluid_midi_router_t* handler);
|
FLUIDSYNTH_API int delete_fluid_midi_router(fluid_midi_router_t* handler);
|
||||||
|
|
||||||
/** The standard handler function. Every MIDI event goes through
|
|
||||||
this. */
|
|
||||||
FLUIDSYNTH_API int fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event);
|
FLUIDSYNTH_API int fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event);
|
||||||
|
|
||||||
/** An optional link in the MIDI chain to dump MIDI data between MIDI
|
|
||||||
driver and router */
|
|
||||||
FLUIDSYNTH_API int fluid_midi_dump_prerouter(void* data, fluid_midi_event_t* event);
|
FLUIDSYNTH_API int fluid_midi_dump_prerouter(void* data, fluid_midi_event_t* event);
|
||||||
|
|
||||||
/** An optional link in the MIDI chain to dump MIDI data between MIDI
|
|
||||||
router and the synthesizer */
|
|
||||||
FLUIDSYNTH_API int fluid_midi_dump_postrouter(void* data, fluid_midi_event_t* event);
|
FLUIDSYNTH_API int fluid_midi_dump_postrouter(void* data, fluid_midi_event_t* event);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
|
||||||
* MIDI driver
|
* MIDI driver
|
||||||
*
|
*
|
||||||
* The MIDI handler forwards incoming MIDI events to the synthesizer
|
* The MIDI handler forwards incoming MIDI events to the synthesizer
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
FLUIDSYNTH_API
|
FLUIDSYNTH_API
|
||||||
fluid_midi_driver_t* new_fluid_midi_driver(fluid_settings_t* settings,
|
fluid_midi_driver_t* new_fluid_midi_driver(fluid_settings_t* settings,
|
||||||
handle_midi_event_func_t handler,
|
handle_midi_event_func_t handler,
|
||||||
@@ -110,11 +96,9 @@ FLUIDSYNTH_API void delete_fluid_midi_driver(fluid_midi_driver_t* driver);
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
|
||||||
* MIDI file player
|
* MIDI file player
|
||||||
*
|
*
|
||||||
* The MIDI player allows you to play MIDI files with the FLUID Synth
|
* The MIDI player allows you to play MIDI files with the FLUID Synth
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
FLUIDSYNTH_API fluid_player_t* new_fluid_player(fluid_synth_t* synth);
|
FLUIDSYNTH_API fluid_player_t* new_fluid_player(fluid_synth_t* synth);
|
||||||
|
|||||||
@@ -144,9 +144,9 @@ struct _fluid_sample_t
|
|||||||
{
|
{
|
||||||
char name[21];
|
char name[21];
|
||||||
unsigned int start;
|
unsigned int start;
|
||||||
unsigned int end;
|
unsigned int end; /* Note: Index of last valid sample point (contrary to SF spec) */
|
||||||
unsigned int loopstart;
|
unsigned int loopstart;
|
||||||
unsigned int loopend;
|
unsigned int loopend; /* Note: first point following the loop (superimposed on loopstart) */
|
||||||
unsigned int samplerate;
|
unsigned int samplerate;
|
||||||
int origpitch;
|
int origpitch;
|
||||||
int pitchadj;
|
int pitchadj;
|
||||||
|
|||||||
@@ -26,10 +26,10 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define FLUIDSYNTH_VERSION "1.0.7"
|
#define FLUIDSYNTH_VERSION "1.0.8"
|
||||||
#define FLUIDSYNTH_VERSION_MAJOR 1
|
#define FLUIDSYNTH_VERSION_MAJOR 1
|
||||||
#define FLUIDSYNTH_VERSION_MINOR 0
|
#define FLUIDSYNTH_VERSION_MINOR 0
|
||||||
#define FLUIDSYNTH_VERSION_MICRO 7
|
#define FLUIDSYNTH_VERSION_MICRO 8
|
||||||
|
|
||||||
|
|
||||||
FLUIDSYNTH_API void fluid_version(int *major, int *minor, int *micro);
|
FLUIDSYNTH_API void fluid_version(int *major, int *minor, int *micro);
|
||||||
|
|||||||
@@ -6,10 +6,10 @@
|
|||||||
|
|
||||||
[:Development:]
|
[:Development:]
|
||||||
|
|
||||||
Many people contributed to FluidSynth, send suggestions or bug
|
Many people contributed to FluidSynth, sent suggestions or bug
|
||||||
fixes. The project was started by Peter Hanappe who is the main
|
fixes. The project was started by Peter Hanappe who is the main
|
||||||
author. Josh Green is the current maintainer. Below you'll find a
|
author. Josh Green is the current maintainer. Below you'll find a
|
||||||
summery of contributions.
|
summary of contributions.
|
||||||
|
|
||||||
|
|
||||||
* Peter Hanappe. Initiated the project. files: sticked his nose in all
|
* Peter Hanappe. Initiated the project. files: sticked his nose in all
|
||||||
@@ -24,10 +24,6 @@ summery of contributions.
|
|||||||
(the blue waves with FluidSynth letters partially submerged).
|
(the blue waves with FluidSynth letters partially submerged).
|
||||||
files: iiwu_defsfont.{c,h}, iiwu_alsa{c,h} and others.
|
files: iiwu_defsfont.{c,h}, iiwu_alsa{c,h} and others.
|
||||||
|
|
||||||
* Stephane Letz from Grame wrote most of the MidiShare driver, all of
|
|
||||||
the PortAudio driver, ported iiwusynth to MacOS X, and sent in many
|
|
||||||
fixes. files: iiwu_midishare.c, iiwu_portaudio.c
|
|
||||||
|
|
||||||
* Markus Nentwig (re-)designed the resonant filter, the chorus, the
|
* Markus Nentwig (re-)designed the resonant filter, the chorus, the
|
||||||
LADSPA subsystem, the MIDI router, optimized for SSE, made many
|
LADSPA subsystem, the MIDI router, optimized for SSE, made many
|
||||||
changes and bug fixes and got the synthesizer to actually work. Most
|
changes and bug fixes and got the synthesizer to actually work. Most
|
||||||
@@ -36,6 +32,10 @@ summery of contributions.
|
|||||||
iiwu_sse.h, iiwu_dsp_core.h, iiwu_rev.{c,h}, and basically all the
|
iiwu_sse.h, iiwu_dsp_core.h, iiwu_rev.{c,h}, and basically all the
|
||||||
other files.
|
other files.
|
||||||
|
|
||||||
|
* Stephane Letz from Grame wrote most of the MidiShare driver, all of
|
||||||
|
the PortAudio driver, ported iiwusynth to MacOS X, and sent in many
|
||||||
|
fixes. files: iiwu_midishare.c, iiwu_portaudio.c
|
||||||
|
|
||||||
* Antoine Schmitt added the sequencer support, support for sample
|
* Antoine Schmitt added the sequencer support, support for sample
|
||||||
loading (RAM Sfont), developed the
|
loading (RAM Sfont), developed the
|
||||||
MacroMedia Director Xtra, and send in many many bug reports. Thanks
|
MacroMedia Director Xtra, and send in many many bug reports. Thanks
|
||||||
@@ -67,8 +67,7 @@ summery of contributions.
|
|||||||
portability.
|
portability.
|
||||||
|
|
||||||
* The midi device uses code from jMax's alsarawmidi.c file and from
|
* The midi device uses code from jMax's alsarawmidi.c file and from
|
||||||
Smurf's midi_alsaraw.c by Josh Green. Josh also added support for
|
Smurf's midi_alsaraw.c by Josh Green. file: iiwu_alsa.c
|
||||||
the alsa sequencer interface. file: iiwu_alsa.c
|
|
||||||
|
|
||||||
* The reverb algorithm was written by Jezar
|
* The reverb algorithm was written by Jezar
|
||||||
(http://www.dreampoint.co.uk). His code is public domain. The code
|
(http://www.dreampoint.co.uk). His code is public domain. The code
|
||||||
@@ -115,3 +114,7 @@ Gerald Pye
|
|||||||
Rui Nuno Capela
|
Rui Nuno Capela
|
||||||
Frieder Bürzele
|
Frieder Bürzele
|
||||||
Henri Manson
|
Henri Manson
|
||||||
|
Mihail Zenkov
|
||||||
|
Paul Millar
|
||||||
|
Nick Daly
|
||||||
|
David Hilvert
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ SharedLibrary libfluidsynth.so :
|
|||||||
fluid_cmd.c
|
fluid_cmd.c
|
||||||
fluid_conv.c
|
fluid_conv.c
|
||||||
fluid_defsfont.c
|
fluid_defsfont.c
|
||||||
|
fluid_dsp_float.c
|
||||||
fluid_event.c
|
fluid_event.c
|
||||||
fluid_gen.c
|
fluid_gen.c
|
||||||
fluid_hash.c
|
fluid_hash.c
|
||||||
@@ -28,7 +29,6 @@ SharedLibrary libfluidsynth.so :
|
|||||||
fluid_seq.c
|
fluid_seq.c
|
||||||
fluid_seqbind.c
|
fluid_seqbind.c
|
||||||
fluid_settings.c
|
fluid_settings.c
|
||||||
fluid_strtok.c
|
|
||||||
fluid_synth.c
|
fluid_synth.c
|
||||||
fluid_sys.c
|
fluid_sys.c
|
||||||
fluid_tuning.c
|
fluid_tuning.c
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -25,12 +25,12 @@
|
|||||||
* fluid_adriver_definition_t
|
* fluid_adriver_definition_t
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct _fluid_audriver_definition_t
|
typedef struct _fluid_audriver_definition_t
|
||||||
{
|
{
|
||||||
char* name;
|
char* name;
|
||||||
fluid_audio_driver_t* (*new)(fluid_settings_t* settings, fluid_synth_t* synth);
|
fluid_audio_driver_t* (*new)(fluid_settings_t* settings, fluid_synth_t* synth);
|
||||||
fluid_audio_driver_t* (*new2)(fluid_settings_t* settings,
|
fluid_audio_driver_t* (*new2)(fluid_settings_t* settings,
|
||||||
fluid_audio_func_t func,
|
fluid_audio_func_t func,
|
||||||
void* data);
|
void* data);
|
||||||
int (*free)(fluid_audio_driver_t* driver);
|
int (*free)(fluid_audio_driver_t* driver);
|
||||||
void (*settings)(fluid_settings_t* settings);
|
void (*settings)(fluid_settings_t* settings);
|
||||||
@@ -48,57 +48,57 @@ void fluid_alsa_audio_driver_settings(fluid_settings_t* settings);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if OSS_SUPPORT
|
#if OSS_SUPPORT
|
||||||
fluid_audio_driver_t* new_fluid_oss_audio_driver(fluid_settings_t* settings,
|
fluid_audio_driver_t* new_fluid_oss_audio_driver(fluid_settings_t* settings,
|
||||||
fluid_synth_t* synth);
|
fluid_synth_t* synth);
|
||||||
fluid_audio_driver_t* new_fluid_oss_audio_driver2(fluid_settings_t* settings,
|
fluid_audio_driver_t* new_fluid_oss_audio_driver2(fluid_settings_t* settings,
|
||||||
fluid_audio_func_t func, void* data);
|
fluid_audio_func_t func, void* data);
|
||||||
int delete_fluid_oss_audio_driver(fluid_audio_driver_t* p);
|
int delete_fluid_oss_audio_driver(fluid_audio_driver_t* p);
|
||||||
void fluid_oss_audio_driver_settings(fluid_settings_t* settings);
|
void fluid_oss_audio_driver_settings(fluid_settings_t* settings);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if COREAUDIO_SUPPORT
|
#if COREAUDIO_SUPPORT
|
||||||
fluid_audio_driver_t* new_fluid_core_audio_driver(fluid_settings_t* settings,
|
fluid_audio_driver_t* new_fluid_core_audio_driver(fluid_settings_t* settings,
|
||||||
fluid_synth_t* synth);
|
fluid_synth_t* synth);
|
||||||
fluid_audio_driver_t* new_fluid_core_audio_driver2(fluid_settings_t* settings,
|
fluid_audio_driver_t* new_fluid_core_audio_driver2(fluid_settings_t* settings,
|
||||||
fluid_audio_func_t func,
|
fluid_audio_func_t func,
|
||||||
void* data);
|
void* data);
|
||||||
int delete_fluid_core_audio_driver(fluid_audio_driver_t* p);
|
int delete_fluid_core_audio_driver(fluid_audio_driver_t* p);
|
||||||
void fluid_core_audio_driver_settings(fluid_settings_t* settings);
|
void fluid_core_audio_driver_settings(fluid_settings_t* settings);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if DSOUND_SUPPORT
|
#if DSOUND_SUPPORT
|
||||||
fluid_audio_driver_t* new_fluid_dsound_audio_driver(fluid_settings_t* settings,
|
fluid_audio_driver_t* new_fluid_dsound_audio_driver(fluid_settings_t* settings,
|
||||||
fluid_synth_t* synth);
|
fluid_synth_t* synth);
|
||||||
int delete_fluid_dsound_audio_driver(fluid_audio_driver_t* p);
|
int delete_fluid_dsound_audio_driver(fluid_audio_driver_t* p);
|
||||||
void fluid_dsound_audio_driver_settings(fluid_settings_t* settings);
|
void fluid_dsound_audio_driver_settings(fluid_settings_t* settings);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if PORTAUDIO_SUPPORT
|
#if PORTAUDIO_SUPPORT
|
||||||
fluid_audio_driver_t* new_fluid_portaudio_driver(fluid_settings_t* settings,
|
fluid_audio_driver_t* new_fluid_portaudio_driver(fluid_settings_t* settings,
|
||||||
fluid_synth_t* synth);
|
fluid_synth_t* synth);
|
||||||
int delete_fluid_portaudio_driver(fluid_audio_driver_t* p);
|
int delete_fluid_portaudio_driver(fluid_audio_driver_t* p);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if JACK_SUPPORT
|
#if JACK_SUPPORT
|
||||||
fluid_audio_driver_t* new_fluid_jack_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth);
|
fluid_audio_driver_t* new_fluid_jack_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth);
|
||||||
fluid_audio_driver_t* new_fluid_jack_audio_driver2(fluid_settings_t* settings,
|
fluid_audio_driver_t* new_fluid_jack_audio_driver2(fluid_settings_t* settings,
|
||||||
fluid_audio_func_t func, void* data);
|
fluid_audio_func_t func, void* data);
|
||||||
int delete_fluid_jack_audio_driver(fluid_audio_driver_t* p);
|
int delete_fluid_jack_audio_driver(fluid_audio_driver_t* p);
|
||||||
void fluid_jack_audio_driver_settings(fluid_settings_t* settings);
|
void fluid_jack_audio_driver_settings(fluid_settings_t* settings);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SNDMAN_SUPPORT
|
#if SNDMAN_SUPPORT
|
||||||
fluid_audio_driver_t* new_fluid_sndmgr_audio_driver(fluid_settings_t* settings,
|
fluid_audio_driver_t* new_fluid_sndmgr_audio_driver(fluid_settings_t* settings,
|
||||||
fluid_synth_t* synth);
|
fluid_synth_t* synth);
|
||||||
fluid_audio_driver_t* new_fluid_sndmgr_audio_driver2(fluid_settings_t* settings,
|
fluid_audio_driver_t* new_fluid_sndmgr_audio_driver2(fluid_settings_t* settings,
|
||||||
fluid_audio_func_t func,
|
fluid_audio_func_t func,
|
||||||
void* data);
|
void* data);
|
||||||
int delete_fluid_sndmgr_audio_driver(fluid_audio_driver_t* p);
|
int delete_fluid_sndmgr_audio_driver(fluid_audio_driver_t* p);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define AUFILE_SUPPORT 1
|
#define AUFILE_SUPPORT 1
|
||||||
#if AUFILE_SUPPORT
|
#if AUFILE_SUPPORT
|
||||||
fluid_audio_driver_t* new_fluid_file_audio_driver(fluid_settings_t* settings,
|
fluid_audio_driver_t* new_fluid_file_audio_driver(fluid_settings_t* settings,
|
||||||
fluid_synth_t* synth);
|
fluid_synth_t* synth);
|
||||||
int delete_fluid_file_audio_driver(fluid_audio_driver_t* p);
|
int delete_fluid_file_audio_driver(fluid_audio_driver_t* p);
|
||||||
void fluid_file_audio_driver_settings(fluid_settings_t* settings);
|
void fluid_file_audio_driver_settings(fluid_settings_t* settings);
|
||||||
@@ -106,10 +106,10 @@ void fluid_file_audio_driver_settings(fluid_settings_t* settings);
|
|||||||
|
|
||||||
fluid_audriver_definition_t fluid_audio_drivers[] = {
|
fluid_audriver_definition_t fluid_audio_drivers[] = {
|
||||||
#if OSS_SUPPORT
|
#if OSS_SUPPORT
|
||||||
{ "oss",
|
{ "oss",
|
||||||
new_fluid_oss_audio_driver,
|
new_fluid_oss_audio_driver,
|
||||||
new_fluid_oss_audio_driver2,
|
new_fluid_oss_audio_driver2,
|
||||||
delete_fluid_oss_audio_driver,
|
delete_fluid_oss_audio_driver,
|
||||||
fluid_oss_audio_driver_settings },
|
fluid_oss_audio_driver_settings },
|
||||||
#endif
|
#endif
|
||||||
#if ALSA_SUPPORT
|
#if ALSA_SUPPORT
|
||||||
@@ -120,45 +120,45 @@ fluid_audriver_definition_t fluid_audio_drivers[] = {
|
|||||||
fluid_alsa_audio_driver_settings },
|
fluid_alsa_audio_driver_settings },
|
||||||
#endif
|
#endif
|
||||||
#if COREAUDIO_SUPPORT
|
#if COREAUDIO_SUPPORT
|
||||||
{ "coreaudio",
|
{ "coreaudio",
|
||||||
new_fluid_core_audio_driver,
|
new_fluid_core_audio_driver,
|
||||||
new_fluid_core_audio_driver2,
|
new_fluid_core_audio_driver2,
|
||||||
delete_fluid_core_audio_driver,
|
delete_fluid_core_audio_driver,
|
||||||
fluid_core_audio_driver_settings },
|
fluid_core_audio_driver_settings },
|
||||||
#endif
|
#endif
|
||||||
#if DSOUND_SUPPORT
|
#if DSOUND_SUPPORT
|
||||||
{ "dsound",
|
{ "dsound",
|
||||||
new_fluid_dsound_audio_driver,
|
new_fluid_dsound_audio_driver,
|
||||||
NULL,
|
NULL,
|
||||||
delete_fluid_dsound_audio_driver,
|
delete_fluid_dsound_audio_driver,
|
||||||
fluid_dsound_audio_driver_settings },
|
fluid_dsound_audio_driver_settings },
|
||||||
#endif
|
#endif
|
||||||
#if PORTAUDIO_SUPPORT
|
#if PORTAUDIO_SUPPORT
|
||||||
{ "portaudio",
|
{ "portaudio",
|
||||||
new_fluid_portaudio_driver,
|
new_fluid_portaudio_driver,
|
||||||
NULL,
|
NULL,
|
||||||
delete_fluid_portaudio_driver,
|
delete_fluid_portaudio_driver,
|
||||||
NULL },
|
NULL },
|
||||||
#endif
|
#endif
|
||||||
#if SNDMAN_SUPPORT
|
#if SNDMAN_SUPPORT
|
||||||
{ "sndman",
|
{ "sndman",
|
||||||
new_fluid_sndmgr_audio_driver,
|
new_fluid_sndmgr_audio_driver,
|
||||||
new_fluid_sndmgr_audio_driver2,
|
new_fluid_sndmgr_audio_driver2,
|
||||||
delete_fluid_sndmgr_audio_driver,
|
delete_fluid_sndmgr_audio_driver,
|
||||||
NULL },
|
NULL },
|
||||||
#endif
|
#endif
|
||||||
#if JACK_SUPPORT
|
#if JACK_SUPPORT
|
||||||
{ "jack",
|
{ "jack",
|
||||||
new_fluid_jack_audio_driver,
|
new_fluid_jack_audio_driver,
|
||||||
new_fluid_jack_audio_driver2,
|
new_fluid_jack_audio_driver2,
|
||||||
delete_fluid_jack_audio_driver,
|
delete_fluid_jack_audio_driver,
|
||||||
fluid_jack_audio_driver_settings },
|
fluid_jack_audio_driver_settings },
|
||||||
#endif
|
#endif
|
||||||
#if AUFILE_SUPPORT
|
#if AUFILE_SUPPORT
|
||||||
{ "file",
|
{ "file",
|
||||||
new_fluid_file_audio_driver,
|
new_fluid_file_audio_driver,
|
||||||
NULL,
|
NULL,
|
||||||
delete_fluid_file_audio_driver,
|
delete_fluid_file_audio_driver,
|
||||||
fluid_file_audio_driver_settings },
|
fluid_file_audio_driver_settings },
|
||||||
#endif
|
#endif
|
||||||
{ NULL, NULL, NULL, NULL, NULL }
|
{ NULL, NULL, NULL, NULL, NULL }
|
||||||
@@ -241,11 +241,21 @@ void fluid_audio_driver_settings(fluid_settings_t* settings)
|
|||||||
if (fluid_audio_drivers[i].settings != NULL) {
|
if (fluid_audio_drivers[i].settings != NULL) {
|
||||||
fluid_audio_drivers[i].settings(settings);
|
fluid_audio_drivers[i].settings(settings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fluid_audio_driver_t*
|
/**
|
||||||
|
* Create a new audio driver.
|
||||||
|
* @param settings Configuration settings used to select and create the audio
|
||||||
|
* driver.
|
||||||
|
* @param synth Synthesizer instance for which the audio driver is created for.
|
||||||
|
* @return The new audio driver instance.
|
||||||
|
*
|
||||||
|
* Creates a new audio driver for a given 'synth' instance with a defined set
|
||||||
|
* of configuration 'settings'.
|
||||||
|
*/
|
||||||
|
fluid_audio_driver_t*
|
||||||
new_fluid_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth)
|
new_fluid_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -260,7 +270,7 @@ new_fluid_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth)
|
|||||||
driver = (*fluid_audio_drivers[i].new)(settings, synth);
|
driver = (*fluid_audio_drivers[i].new)(settings, synth);
|
||||||
if (driver) {
|
if (driver) {
|
||||||
driver->name = fluid_audio_drivers[i].name;
|
driver->name = fluid_audio_drivers[i].name;
|
||||||
}
|
}
|
||||||
return driver;
|
return driver;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -269,7 +279,20 @@ new_fluid_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
fluid_audio_driver_t*
|
/**
|
||||||
|
* Create a new audio driver.
|
||||||
|
* @param settings Configuration settings used to select and create the audio
|
||||||
|
* driver.
|
||||||
|
* @param func Function called to fill audio buffers for audio playback
|
||||||
|
* @param data User defined data pointer to pass to 'func'
|
||||||
|
* @return The new audio driver instance.
|
||||||
|
*
|
||||||
|
* Like new_fluid_audio_driver() but allows for custom audio processing before
|
||||||
|
* audio is sent to audio driver. It is the responsibility of the callback
|
||||||
|
* 'func' to render the audio into the buffers.
|
||||||
|
* NOTE: Not as efficient as new_fluid_audio_driver().
|
||||||
|
*/
|
||||||
|
fluid_audio_driver_t*
|
||||||
new_fluid_audio_driver2(fluid_settings_t* settings, fluid_audio_func_t func, void* data)
|
new_fluid_audio_driver2(fluid_settings_t* settings, fluid_audio_func_t func, void* data)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -285,7 +308,7 @@ new_fluid_audio_driver2(fluid_settings_t* settings, fluid_audio_func_t func, voi
|
|||||||
driver = (*fluid_audio_drivers[i].new2)(settings, func, data);
|
driver = (*fluid_audio_drivers[i].new2)(settings, func, data);
|
||||||
if (driver) {
|
if (driver) {
|
||||||
driver->name = fluid_audio_drivers[i].name;
|
driver->name = fluid_audio_drivers[i].name;
|
||||||
}
|
}
|
||||||
return driver;
|
return driver;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -294,7 +317,13 @@ new_fluid_audio_driver2(fluid_settings_t* settings, fluid_audio_func_t func, voi
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
/**
|
||||||
|
* Deletes an audio driver instance.
|
||||||
|
* @param driver Audio driver instance to delete
|
||||||
|
*
|
||||||
|
* Shuts down an audio driver and deletes its instance.
|
||||||
|
*/
|
||||||
|
void
|
||||||
delete_fluid_audio_driver(fluid_audio_driver_t* driver)
|
delete_fluid_audio_driver(fluid_audio_driver_t* driver)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -30,7 +30,7 @@ void fluid_audio_driver_settings(fluid_settings_t* settings);
|
|||||||
* fluid_audio_driver_t
|
* fluid_audio_driver_t
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct _fluid_audio_driver_t
|
struct _fluid_audio_driver_t
|
||||||
{
|
{
|
||||||
char* name;
|
char* name;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
/* fluid_aufile.c
|
/* fluid_aufile.c
|
||||||
*
|
*
|
||||||
* Audio driver, outputs the audio to a file (non real-time)
|
* Audio driver, outputs the audio to a file (non real-time)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -31,9 +31,9 @@
|
|||||||
|
|
||||||
|
|
||||||
/** fluid_file_audio_driver_t
|
/** fluid_file_audio_driver_t
|
||||||
*
|
*
|
||||||
* This structure should not be accessed directly. Use audio port
|
* This structure should not be accessed directly. Use audio port
|
||||||
* functions instead.
|
* functions instead.
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
fluid_audio_driver_t driver;
|
fluid_audio_driver_t driver;
|
||||||
@@ -70,7 +70,7 @@ void fluid_file_audio_driver_settings(fluid_settings_t* settings)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fluid_audio_driver_t*
|
fluid_audio_driver_t*
|
||||||
new_fluid_file_audio_driver(fluid_settings_t* settings,
|
new_fluid_file_audio_driver(fluid_settings_t* settings,
|
||||||
fluid_synth_t* synth)
|
fluid_synth_t* synth)
|
||||||
{
|
{
|
||||||
@@ -82,7 +82,7 @@ new_fluid_file_audio_driver(fluid_settings_t* settings,
|
|||||||
dev = FLUID_NEW(fluid_file_audio_driver_t);
|
dev = FLUID_NEW(fluid_file_audio_driver_t);
|
||||||
if (dev == NULL) {
|
if (dev == NULL) {
|
||||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
FLUID_MEMSET(dev, 0, sizeof(fluid_file_audio_driver_t));
|
FLUID_MEMSET(dev, 0, sizeof(fluid_file_audio_driver_t));
|
||||||
|
|
||||||
@@ -125,7 +125,7 @@ new_fluid_file_audio_driver(fluid_settings_t* settings,
|
|||||||
int delete_fluid_file_audio_driver(fluid_audio_driver_t* p)
|
int delete_fluid_file_audio_driver(fluid_audio_driver_t* p)
|
||||||
{
|
{
|
||||||
fluid_file_audio_driver_t* dev = (fluid_file_audio_driver_t*) p;
|
fluid_file_audio_driver_t* dev = (fluid_file_audio_driver_t*) p;
|
||||||
|
|
||||||
if (dev == NULL) {
|
if (dev == NULL) {
|
||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
@@ -157,48 +157,27 @@ int delete_fluid_file_audio_driver(fluid_audio_driver_t* p)
|
|||||||
static int fluid_file_audio_run_s16(void* d, unsigned int clock_time)
|
static int fluid_file_audio_run_s16(void* d, unsigned int clock_time)
|
||||||
{
|
{
|
||||||
fluid_file_audio_driver_t* dev = (fluid_file_audio_driver_t*) d;
|
fluid_file_audio_driver_t* dev = (fluid_file_audio_driver_t*) d;
|
||||||
float* handle[2];
|
int n, offset;
|
||||||
int i, k, n, offset;
|
|
||||||
float s;
|
|
||||||
unsigned int sample_time;
|
unsigned int sample_time;
|
||||||
|
|
||||||
handle[0] = dev->left;
|
|
||||||
handle[1] = dev->right;
|
|
||||||
|
|
||||||
|
|
||||||
sample_time = (unsigned int) (dev->samples / dev->sample_rate * 1000.0);
|
sample_time = (unsigned int) (dev->samples / dev->sample_rate * 1000.0);
|
||||||
if (sample_time > clock_time) {
|
if (sample_time > clock_time) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
(*dev->callback)(dev->data, dev->period_size, 0, NULL, 2, handle);
|
fluid_synth_write_s16(dev->data, dev->period_size, dev->buf, 0, 2, dev->buf, 1, 2);
|
||||||
|
|
||||||
for (i = 0, k = 0; i < dev->period_size; i++, k += 2) {
|
|
||||||
s = 32768.0f * dev->left[i];
|
|
||||||
fluid_clip(s, -32768.0f, 32767.0f);
|
|
||||||
dev->buf[k] = (short) s;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0, k = 1; i < dev->period_size; i++, k += 2) {
|
|
||||||
s = 32768.0f * dev->right[i];
|
|
||||||
fluid_clip(s, -32768.0f, 32767.0f);
|
|
||||||
dev->buf[k] = (short) s;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (offset = 0; offset < dev->buf_size; offset += n) {
|
for (offset = 0; offset < dev->buf_size; offset += n) {
|
||||||
|
|
||||||
n = fwrite((char*) dev->buf + offset, 1, dev->buf_size - offset, dev->file);
|
n = fwrite((char*) dev->buf + offset, 1, dev->buf_size - offset, dev->file);
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
FLUID_LOG(FLUID_ERR, "Audio file error");
|
FLUID_LOG(FLUID_ERR, "Audio output file write error: %s",
|
||||||
return 0;
|
strerror (errno));
|
||||||
}
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->samples += dev->period_size;
|
dev->samples += dev->period_size;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
error_recovery:
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
/*
|
/*
|
||||||
* new_fluid_channel
|
* new_fluid_channel
|
||||||
*/
|
*/
|
||||||
fluid_channel_t*
|
fluid_channel_t*
|
||||||
new_fluid_channel(fluid_synth_t* synth, int num)
|
new_fluid_channel(fluid_synth_t* synth, int num)
|
||||||
{
|
{
|
||||||
fluid_channel_t* chan;
|
fluid_channel_t* chan;
|
||||||
@@ -41,6 +41,7 @@ new_fluid_channel(fluid_synth_t* synth, int num)
|
|||||||
|
|
||||||
chan->synth = synth;
|
chan->synth = synth;
|
||||||
chan->channum = num;
|
chan->channum = num;
|
||||||
|
chan->preset = NULL;
|
||||||
|
|
||||||
fluid_channel_init(chan);
|
fluid_channel_init(chan);
|
||||||
fluid_channel_init_ctrl(chan);
|
fluid_channel_init_ctrl(chan);
|
||||||
@@ -48,19 +49,22 @@ new_fluid_channel(fluid_synth_t* synth, int num)
|
|||||||
return chan;
|
return chan;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fluid_channel_init(fluid_channel_t* chan)
|
fluid_channel_init(fluid_channel_t* chan)
|
||||||
{
|
{
|
||||||
chan->prognum = (chan->channum == 9)? 0 : chan->channum;
|
chan->prognum = (chan->channum == 9)? 0 : chan->channum;
|
||||||
chan->banknum = (chan->channum == 9)? 128 : 0;
|
chan->banknum = (chan->channum == 9)? 128 : 0;
|
||||||
chan->sfontnum = 0;
|
chan->sfontnum = 0;
|
||||||
|
|
||||||
|
if (chan->preset) delete_fluid_preset (chan->preset);
|
||||||
chan->preset = fluid_synth_find_preset(chan->synth, chan->banknum, chan->prognum);
|
chan->preset = fluid_synth_find_preset(chan->synth, chan->banknum, chan->prognum);
|
||||||
|
|
||||||
chan->interp_method = FLUID_INTERP_DEFAULT;
|
chan->interp_method = FLUID_INTERP_DEFAULT;
|
||||||
chan->tuning = NULL;
|
chan->tuning = NULL;
|
||||||
chan->nrpn_select = 0;
|
chan->nrpn_select = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fluid_channel_init_ctrl(fluid_channel_t* chan)
|
fluid_channel_init_ctrl(fluid_channel_t* chan)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -79,21 +83,21 @@ fluid_channel_init_ctrl(fluid_channel_t* chan)
|
|||||||
for (i = 0; i < 128; i++) {
|
for (i = 0; i < 128; i++) {
|
||||||
SETCC(chan, i, 0);
|
SETCC(chan, i, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Volume / initial attenuation (MSB & LSB) */
|
/* Volume / initial attenuation (MSB & LSB) */
|
||||||
SETCC(chan, 7, 127);
|
SETCC(chan, 7, 127);
|
||||||
SETCC(chan, 39, 0);
|
SETCC(chan, 39, 0);
|
||||||
|
|
||||||
/* Pan (MSB & LSB) */
|
/* Pan (MSB & LSB) */
|
||||||
SETCC(chan, 10, 64);
|
SETCC(chan, 10, 64);
|
||||||
SETCC(chan, 10, 64);
|
SETCC(chan, 10, 64);
|
||||||
|
|
||||||
/* Expression (MSB & LSB) */
|
/* Expression (MSB & LSB) */
|
||||||
SETCC(chan, 11, 127);
|
SETCC(chan, 11, 127);
|
||||||
SETCC(chan, 43, 127);
|
SETCC(chan, 43, 127);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fluid_channel_reset(fluid_channel_t* chan)
|
fluid_channel_reset(fluid_channel_t* chan)
|
||||||
{
|
{
|
||||||
fluid_channel_init(chan);
|
fluid_channel_init(chan);
|
||||||
@@ -103,9 +107,10 @@ fluid_channel_reset(fluid_channel_t* chan)
|
|||||||
/*
|
/*
|
||||||
* delete_fluid_channel
|
* delete_fluid_channel
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
delete_fluid_channel(fluid_channel_t* chan)
|
delete_fluid_channel(fluid_channel_t* chan)
|
||||||
{
|
{
|
||||||
|
if (chan->preset) delete_fluid_preset (chan->preset);
|
||||||
FLUID_FREE(chan);
|
FLUID_FREE(chan);
|
||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
@@ -113,12 +118,13 @@ delete_fluid_channel(fluid_channel_t* chan)
|
|||||||
/*
|
/*
|
||||||
* fluid_channel_set_preset
|
* fluid_channel_set_preset
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
fluid_channel_set_preset(fluid_channel_t* chan, fluid_preset_t* preset)
|
fluid_channel_set_preset(fluid_channel_t* chan, fluid_preset_t* preset)
|
||||||
{
|
{
|
||||||
fluid_preset_notify(chan->preset, FLUID_PRESET_UNSELECTED, chan->channum);
|
fluid_preset_notify(chan->preset, FLUID_PRESET_UNSELECTED, chan->channum);
|
||||||
fluid_preset_notify(preset, FLUID_PRESET_SELECTED, chan->channum);
|
fluid_preset_notify(preset, FLUID_PRESET_SELECTED, chan->channum);
|
||||||
|
|
||||||
|
if (chan->preset) delete_fluid_preset (chan->preset);
|
||||||
chan->preset = preset;
|
chan->preset = preset;
|
||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
@@ -126,7 +132,7 @@ fluid_channel_set_preset(fluid_channel_t* chan, fluid_preset_t* preset)
|
|||||||
/*
|
/*
|
||||||
* fluid_channel_get_preset
|
* fluid_channel_get_preset
|
||||||
*/
|
*/
|
||||||
fluid_preset_t*
|
fluid_preset_t*
|
||||||
fluid_channel_get_preset(fluid_channel_t* chan)
|
fluid_channel_get_preset(fluid_channel_t* chan)
|
||||||
{
|
{
|
||||||
return chan->preset;
|
return chan->preset;
|
||||||
@@ -135,7 +141,7 @@ fluid_channel_get_preset(fluid_channel_t* chan)
|
|||||||
/*
|
/*
|
||||||
* fluid_channel_get_banknum
|
* fluid_channel_get_banknum
|
||||||
*/
|
*/
|
||||||
unsigned int
|
unsigned int
|
||||||
fluid_channel_get_banknum(fluid_channel_t* chan)
|
fluid_channel_get_banknum(fluid_channel_t* chan)
|
||||||
{
|
{
|
||||||
return chan->banknum;
|
return chan->banknum;
|
||||||
@@ -144,7 +150,7 @@ fluid_channel_get_banknum(fluid_channel_t* chan)
|
|||||||
/*
|
/*
|
||||||
* fluid_channel_set_prognum
|
* fluid_channel_set_prognum
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
fluid_channel_set_prognum(fluid_channel_t* chan, int prognum)
|
fluid_channel_set_prognum(fluid_channel_t* chan, int prognum)
|
||||||
{
|
{
|
||||||
chan->prognum = prognum;
|
chan->prognum = prognum;
|
||||||
@@ -154,7 +160,7 @@ fluid_channel_set_prognum(fluid_channel_t* chan, int prognum)
|
|||||||
/*
|
/*
|
||||||
* fluid_channel_get_prognum
|
* fluid_channel_get_prognum
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
fluid_channel_get_prognum(fluid_channel_t* chan)
|
fluid_channel_get_prognum(fluid_channel_t* chan)
|
||||||
{
|
{
|
||||||
return chan->prognum;
|
return chan->prognum;
|
||||||
@@ -163,7 +169,7 @@ fluid_channel_get_prognum(fluid_channel_t* chan)
|
|||||||
/*
|
/*
|
||||||
* fluid_channel_set_banknum
|
* fluid_channel_set_banknum
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
fluid_channel_set_banknum(fluid_channel_t* chan, unsigned int banknum)
|
fluid_channel_set_banknum(fluid_channel_t* chan, unsigned int banknum)
|
||||||
{
|
{
|
||||||
chan->banknum = banknum;
|
chan->banknum = banknum;
|
||||||
@@ -173,14 +179,14 @@ fluid_channel_set_banknum(fluid_channel_t* chan, unsigned int banknum)
|
|||||||
/*
|
/*
|
||||||
* fluid_channel_cc
|
* fluid_channel_cc
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
fluid_channel_cc(fluid_channel_t* chan, int num, int value)
|
fluid_channel_cc(fluid_channel_t* chan, int num, int value)
|
||||||
{
|
{
|
||||||
chan->cc[num] = value;
|
chan->cc[num] = value;
|
||||||
|
|
||||||
switch (num) {
|
switch (num) {
|
||||||
|
|
||||||
case SUSTAIN_SWITCH:
|
case SUSTAIN_SWITCH:
|
||||||
{
|
{
|
||||||
if (value < 64) {
|
if (value < 64) {
|
||||||
/* printf("** sustain off\n"); */
|
/* printf("** sustain off\n"); */
|
||||||
@@ -190,7 +196,7 @@ fluid_channel_cc(fluid_channel_t* chan, int num, int value)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BANK_SELECT_MSB:
|
case BANK_SELECT_MSB:
|
||||||
{
|
{
|
||||||
chan->bank_msb = (unsigned char) (value & 0x7f);
|
chan->bank_msb = (unsigned char) (value & 0x7f);
|
||||||
@@ -207,17 +213,17 @@ fluid_channel_cc(fluid_channel_t* chan, int num, int value)
|
|||||||
fluid_channel_set_banknum(chan, (unsigned int)(value & 0x7f)); /* KLE */
|
fluid_channel_set_banknum(chan, (unsigned int)(value & 0x7f)); /* KLE */
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BANK_SELECT_LSB:
|
case BANK_SELECT_LSB:
|
||||||
{
|
{
|
||||||
/* FIXME: according to the Downloadable Sounds II specification,
|
/* FIXME: according to the Downloadable Sounds II specification,
|
||||||
bit 31 should be set when we receive the message on channel
|
bit 31 should be set when we receive the message on channel
|
||||||
10 (drum channel) */
|
10 (drum channel) */
|
||||||
fluid_channel_set_banknum(chan, (((unsigned int) value & 0x7f)
|
fluid_channel_set_banknum(chan, (((unsigned int) value & 0x7f)
|
||||||
+ ((unsigned int) chan->bank_msb << 7)));
|
+ ((unsigned int) chan->bank_msb << 7)));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ALL_NOTES_OFF:
|
case ALL_NOTES_OFF:
|
||||||
fluid_synth_all_notes_off(chan->synth, chan->channum);
|
fluid_synth_all_notes_off(chan->synth, chan->channum);
|
||||||
break;
|
break;
|
||||||
@@ -231,7 +237,7 @@ fluid_channel_cc(fluid_channel_t* chan, int num, int value)
|
|||||||
fluid_synth_modulate_voices_all(chan->synth, chan->channum);
|
fluid_synth_modulate_voices_all(chan->synth, chan->channum);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DATA_ENTRY_MSB:
|
case DATA_ENTRY_MSB:
|
||||||
{
|
{
|
||||||
int data = (value << 7) + chan->cc[DATA_ENTRY_LSB];
|
int data = (value << 7) + chan->cc[DATA_ENTRY_LSB];
|
||||||
|
|
||||||
@@ -239,7 +245,7 @@ fluid_channel_cc(fluid_channel_t* chan, int num, int value)
|
|||||||
if ((chan->cc[NRPN_MSB] == 120) && (chan->cc[NRPN_LSB] < 100)) {
|
if ((chan->cc[NRPN_MSB] == 120) && (chan->cc[NRPN_LSB] < 100)) {
|
||||||
float val = fluid_gen_scale_nrpn(chan->nrpn_select, data);
|
float val = fluid_gen_scale_nrpn(chan->nrpn_select, data);
|
||||||
FLUID_LOG(FLUID_WARN, "%s: %d: Data = %d, value = %f", __FILE__, __LINE__, data, val);
|
FLUID_LOG(FLUID_WARN, "%s: %d: Data = %d, value = %f", __FILE__, __LINE__, data, val);
|
||||||
fluid_synth_set_gen(chan->synth, chan->channum, chan->nrpn_select, val);
|
fluid_synth_set_gen(chan->synth, chan->channum, chan->nrpn_select, val);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -262,7 +268,7 @@ fluid_channel_cc(fluid_channel_t* chan, int num, int value)
|
|||||||
chan->nrpn_select += value;
|
chan->nrpn_select += value;
|
||||||
FLUID_LOG(FLUID_WARN, "%s: %d: NRPN Select = %d", __FILE__, __LINE__, chan->nrpn_select);
|
FLUID_LOG(FLUID_WARN, "%s: %d: NRPN Select = %d", __FILE__, __LINE__, chan->nrpn_select);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RPN_MSB:
|
case RPN_MSB:
|
||||||
@@ -278,14 +284,14 @@ fluid_channel_cc(fluid_channel_t* chan, int num, int value)
|
|||||||
default:
|
default:
|
||||||
fluid_synth_modulate_voices(chan->synth, chan->channum, 1, num);
|
fluid_synth_modulate_voices(chan->synth, chan->channum, 1, num);
|
||||||
}
|
}
|
||||||
|
|
||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* fluid_channel_get_cc
|
* fluid_channel_get_cc
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
fluid_channel_get_cc(fluid_channel_t* chan, int num)
|
fluid_channel_get_cc(fluid_channel_t* chan, int num)
|
||||||
{
|
{
|
||||||
return ((num >= 0) && (num < 128))? chan->cc[num] : 0;
|
return ((num >= 0) && (num < 128))? chan->cc[num] : 0;
|
||||||
@@ -294,7 +300,7 @@ fluid_channel_get_cc(fluid_channel_t* chan, int num)
|
|||||||
/*
|
/*
|
||||||
* fluid_channel_pitch_bend
|
* fluid_channel_pitch_bend
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
fluid_channel_pitch_bend(fluid_channel_t* chan, int val)
|
fluid_channel_pitch_bend(fluid_channel_t* chan, int val)
|
||||||
{
|
{
|
||||||
chan->pitch_bend = val;
|
chan->pitch_bend = val;
|
||||||
@@ -305,7 +311,7 @@ fluid_channel_pitch_bend(fluid_channel_t* chan, int val)
|
|||||||
/*
|
/*
|
||||||
* fluid_channel_pitch_wheel_sens
|
* fluid_channel_pitch_wheel_sens
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
fluid_channel_pitch_wheel_sens(fluid_channel_t* chan, int val)
|
fluid_channel_pitch_wheel_sens(fluid_channel_t* chan, int val)
|
||||||
{
|
{
|
||||||
chan->pitch_wheel_sensitivity = val;
|
chan->pitch_wheel_sensitivity = val;
|
||||||
@@ -316,7 +322,7 @@ fluid_channel_pitch_wheel_sens(fluid_channel_t* chan, int val)
|
|||||||
/*
|
/*
|
||||||
* fluid_channel_get_num
|
* fluid_channel_get_num
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
fluid_channel_get_num(fluid_channel_t* chan)
|
fluid_channel_get_num(fluid_channel_t* chan)
|
||||||
{
|
{
|
||||||
return chan->channum;
|
return chan->channum;
|
||||||
@@ -324,7 +330,7 @@ fluid_channel_get_num(fluid_channel_t* chan)
|
|||||||
|
|
||||||
/* Purpose:
|
/* Purpose:
|
||||||
* Sets the index of the interpolation method used on this channel,
|
* Sets the index of the interpolation method used on this channel,
|
||||||
* as in fluid_interp in fluidsynth.h
|
* as in fluid_interp in fluidsynth.h
|
||||||
*/
|
*/
|
||||||
void fluid_channel_set_interp_method(fluid_channel_t* chan, int new_method)
|
void fluid_channel_set_interp_method(fluid_channel_t* chan, int new_method)
|
||||||
{
|
{
|
||||||
@@ -333,7 +339,7 @@ void fluid_channel_set_interp_method(fluid_channel_t* chan, int new_method)
|
|||||||
|
|
||||||
/* Purpose:
|
/* Purpose:
|
||||||
* Returns the index of the interpolation method used on this channel,
|
* Returns the index of the interpolation method used on this channel,
|
||||||
* as in fluid_interp in fluidsynth.h
|
* as in fluid_interp in fluidsynth.h
|
||||||
*/
|
*/
|
||||||
int fluid_channel_get_interp_method(fluid_channel_t* chan)
|
int fluid_channel_get_interp_method(fluid_channel_t* chan)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -64,7 +64,7 @@ struct _fluid_channel_t
|
|||||||
* generators set in the SoundFont. For example, if the NRPN
|
* generators set in the SoundFont. For example, if the NRPN
|
||||||
* specifies an attack of 100 msec then 100 msec will be added to the
|
* specifies an attack of 100 msec then 100 msec will be added to the
|
||||||
* combined attack time of the sound font and the modulators.
|
* combined attack time of the sound font and the modulators.
|
||||||
*
|
*
|
||||||
* However, it is useful to be able to specify the generator value
|
* However, it is useful to be able to specify the generator value
|
||||||
* absolutely, completely ignoring the generators of the sound font
|
* absolutely, completely ignoring the generators of the sound font
|
||||||
* and the values of modulators. The gen_abs field, is a boolean
|
* and the values of modulators. The gen_abs field, is a boolean
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
* August 24, 1998
|
* August 24, 1998
|
||||||
* Copyright (C) 1998 Juergen Mueller And Sundry Contributors
|
* Copyright (C) 1998 Juergen Mueller And Sundry Contributors
|
||||||
* This source code is freely redistributable and may be used for
|
* This source code is freely redistributable and may be used for
|
||||||
* any purpose. This copyright notice must be maintained.
|
* any purpose. This copyright notice must be maintained.
|
||||||
* Juergen Mueller And Sundry Contributors are not responsible for
|
* Juergen Mueller And Sundry Contributors are not responsible for
|
||||||
* the consequences of using this software.
|
* the consequences of using this software.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
CHANGES
|
CHANGES
|
||||||
|
|
||||||
- Adapted for fluidsynth, Peter Hanappe, March 2002
|
- Adapted for fluidsynth, Peter Hanappe, March 2002
|
||||||
|
|
||||||
- Variable delay line implementation using bandlimited
|
- Variable delay line implementation using bandlimited
|
||||||
interpolation, code reorganization: Markus Nentwig May 2002
|
interpolation, code reorganization: Markus Nentwig May 2002
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Chorus effect.
|
* Chorus effect.
|
||||||
*
|
*
|
||||||
* Flow diagram scheme for n delays ( 1 <= n <= MAX_CHORUS ):
|
* Flow diagram scheme for n delays ( 1 <= n <= MAX_CHORUS ):
|
||||||
*
|
*
|
||||||
* * gain-in ___
|
* * gain-in ___
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
* +---->| delay n |----------------------------->| |
|
* +---->| delay n |----------------------------->| |
|
||||||
* |_________| | |
|
* |_________| | |
|
||||||
* /|\ |___|
|
* /|\ |___|
|
||||||
* | |
|
* | |
|
||||||
* +-----------------+ +--------------+ | * gain-out
|
* +-----------------+ +--------------+ | * gain-out
|
||||||
* | Delay control n |<--| mod. speed n | |
|
* | Delay control n |<--| mod. speed n | |
|
||||||
* +-----------------+ +--------------+ +----->obuff
|
* +-----------------+ +--------------+ +----->obuff
|
||||||
@@ -74,10 +74,10 @@
|
|||||||
#define MIN_SPEED_HZ 0.29
|
#define MIN_SPEED_HZ 0.29
|
||||||
#define MAX_SPEED_HZ 5
|
#define MAX_SPEED_HZ 5
|
||||||
|
|
||||||
/* Length of one delay line in samples:
|
/* Length of one delay line in samples:
|
||||||
* Set through MAX_SAMPLES_LN2.
|
* Set through MAX_SAMPLES_LN2.
|
||||||
* For example:
|
* For example:
|
||||||
* MAX_SAMPLES_LN2=12
|
* MAX_SAMPLES_LN2=12
|
||||||
* => MAX_SAMPLES=pow(2,12)=4096
|
* => MAX_SAMPLES=pow(2,12)=4096
|
||||||
* => MAX_SAMPLES_ANDMASK=4095
|
* => MAX_SAMPLES_ANDMASK=4095
|
||||||
*/
|
*/
|
||||||
@@ -89,7 +89,7 @@
|
|||||||
|
|
||||||
/* Interpolate how many steps between samples? Must be power of two
|
/* Interpolate how many steps between samples? Must be power of two
|
||||||
For example: 8 => use a resolution of 256 steps between any two
|
For example: 8 => use a resolution of 256 steps between any two
|
||||||
samples
|
samples
|
||||||
*/
|
*/
|
||||||
#define INTERPOLATION_SUBSAMPLES_LN2 8
|
#define INTERPOLATION_SUBSAMPLES_LN2 8
|
||||||
#define INTERPOLATION_SUBSAMPLES (1 << (INTERPOLATION_SUBSAMPLES_LN2-1))
|
#define INTERPOLATION_SUBSAMPLES (1 << (INTERPOLATION_SUBSAMPLES_LN2-1))
|
||||||
@@ -98,13 +98,13 @@
|
|||||||
/* Use how many samples for interpolation? Must be odd. '7' sounds
|
/* Use how many samples for interpolation? Must be odd. '7' sounds
|
||||||
relatively clean, when listening to the modulated delay signal
|
relatively clean, when listening to the modulated delay signal
|
||||||
alone. For a demo on aliasing try '1' With '3', the aliasing is
|
alone. For a demo on aliasing try '1' With '3', the aliasing is
|
||||||
still quite pronounced for some input frequencies
|
still quite pronounced for some input frequencies
|
||||||
*/
|
*/
|
||||||
#define INTERPOLATION_SAMPLES 5
|
#define INTERPOLATION_SAMPLES 5
|
||||||
|
|
||||||
/* Private data for SKEL file */
|
/* Private data for SKEL file */
|
||||||
struct _fluid_chorus_t {
|
struct _fluid_chorus_t {
|
||||||
/* Store the values between fluid_chorus_set_xxx and fluid_chorus_update
|
/* Store the values between fluid_chorus_set_xxx and fluid_chorus_update
|
||||||
* Logic behind this:
|
* Logic behind this:
|
||||||
* - both 'parameter' and 'new_parameter' hold the same value.
|
* - both 'parameter' and 'new_parameter' hold the same value.
|
||||||
* - To change the chorus settings, 'new_parameter' is modified and
|
* - To change the chorus settings, 'new_parameter' is modified and
|
||||||
@@ -124,7 +124,7 @@ struct _fluid_chorus_t {
|
|||||||
int new_number_blocks; /* next value, if parameter check is OK */
|
int new_number_blocks; /* next value, if parameter check is OK */
|
||||||
|
|
||||||
fluid_real_t *chorusbuf;
|
fluid_real_t *chorusbuf;
|
||||||
int counter;
|
int counter;
|
||||||
long phase[MAX_CHORUS];
|
long phase[MAX_CHORUS];
|
||||||
long modulation_period_samples;
|
long modulation_period_samples;
|
||||||
int *lookup_tab;
|
int *lookup_tab;
|
||||||
@@ -137,12 +137,12 @@ struct _fluid_chorus_t {
|
|||||||
void fluid_chorus_triangle(int *buf, int len, int depth);
|
void fluid_chorus_triangle(int *buf, int len, int depth);
|
||||||
void fluid_chorus_sine(int *buf, int len, int depth);
|
void fluid_chorus_sine(int *buf, int len, int depth);
|
||||||
|
|
||||||
fluid_chorus_t*
|
fluid_chorus_t*
|
||||||
new_fluid_chorus(fluid_real_t sample_rate)
|
new_fluid_chorus(fluid_real_t sample_rate)
|
||||||
{
|
{
|
||||||
int i; int ii;
|
int i; int ii;
|
||||||
fluid_chorus_t* chorus;
|
fluid_chorus_t* chorus;
|
||||||
|
|
||||||
chorus = FLUID_NEW(fluid_chorus_t);
|
chorus = FLUID_NEW(fluid_chorus_t);
|
||||||
if (chorus == NULL) {
|
if (chorus == NULL) {
|
||||||
fluid_log(FLUID_PANIC, "chorus: Out of memory");
|
fluid_log(FLUID_PANIC, "chorus: Out of memory");
|
||||||
@@ -157,7 +157,7 @@ new_fluid_chorus(fluid_real_t sample_rate)
|
|||||||
|
|
||||||
/* i: Offset in terms of whole samples */
|
/* i: Offset in terms of whole samples */
|
||||||
for (i = 0; i < INTERPOLATION_SAMPLES; i++){
|
for (i = 0; i < INTERPOLATION_SAMPLES; i++){
|
||||||
|
|
||||||
/* ii: Offset in terms of fractional samples ('subsamples') */
|
/* ii: Offset in terms of fractional samples ('subsamples') */
|
||||||
for (ii = 0; ii < INTERPOLATION_SUBSAMPLES; ii++){
|
for (ii = 0; ii < INTERPOLATION_SUBSAMPLES; ii++){
|
||||||
/* Move the origin into the center of the table */
|
/* Move the origin into the center of the table */
|
||||||
@@ -182,7 +182,7 @@ new_fluid_chorus(fluid_real_t sample_rate)
|
|||||||
fluid_log(FLUID_PANIC, "chorus: Out of memory");
|
fluid_log(FLUID_PANIC, "chorus: Out of memory");
|
||||||
goto error_recovery;
|
goto error_recovery;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate sample buffer */
|
/* allocate sample buffer */
|
||||||
|
|
||||||
chorus->chorusbuf = FLUID_ARRAY(fluid_real_t, MAX_SAMPLES);
|
chorus->chorusbuf = FLUID_ARRAY(fluid_real_t, MAX_SAMPLES);
|
||||||
@@ -194,7 +194,7 @@ new_fluid_chorus(fluid_real_t sample_rate)
|
|||||||
if (fluid_chorus_init(chorus) != FLUID_OK){
|
if (fluid_chorus_init(chorus) != FLUID_OK){
|
||||||
goto error_recovery;
|
goto error_recovery;
|
||||||
};
|
};
|
||||||
|
|
||||||
return chorus;
|
return chorus;
|
||||||
|
|
||||||
error_recovery:
|
error_recovery:
|
||||||
@@ -203,7 +203,7 @@ new_fluid_chorus(fluid_real_t sample_rate)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
fluid_chorus_init(fluid_chorus_t* chorus)
|
fluid_chorus_init(fluid_chorus_t* chorus)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -306,7 +306,7 @@ int fluid_chorus_get_type(fluid_chorus_t* chorus)
|
|||||||
return chorus->type;
|
return chorus->type;
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
delete_fluid_chorus(fluid_chorus_t* chorus)
|
delete_fluid_chorus(fluid_chorus_t* chorus)
|
||||||
{
|
{
|
||||||
if (chorus == NULL) {
|
if (chorus == NULL) {
|
||||||
@@ -320,7 +320,7 @@ delete_fluid_chorus(fluid_chorus_t* chorus)
|
|||||||
if (chorus->lookup_tab != NULL) {
|
if (chorus->lookup_tab != NULL) {
|
||||||
FLUID_FREE(chorus->lookup_tab);
|
FLUID_FREE(chorus->lookup_tab);
|
||||||
}
|
}
|
||||||
|
|
||||||
FLUID_FREE(chorus);
|
FLUID_FREE(chorus);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,12 +328,12 @@ delete_fluid_chorus(fluid_chorus_t* chorus)
|
|||||||
/* Purpose:
|
/* Purpose:
|
||||||
* Calculates the internal chorus parameters using the settings from
|
* Calculates the internal chorus parameters using the settings from
|
||||||
* fluid_chorus_set_xxx. */
|
* fluid_chorus_set_xxx. */
|
||||||
int
|
int
|
||||||
fluid_chorus_update(fluid_chorus_t* chorus)
|
fluid_chorus_update(fluid_chorus_t* chorus)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int modulation_depth_samples;
|
int modulation_depth_samples;
|
||||||
|
|
||||||
if (chorus->new_number_blocks < 0) {
|
if (chorus->new_number_blocks < 0) {
|
||||||
fluid_log(FLUID_WARN, "chorus: number blocks must be >=0! Setting value to 0.");
|
fluid_log(FLUID_WARN, "chorus: number blocks must be >=0! Setting value to 0.");
|
||||||
chorus->new_number_blocks = 0;
|
chorus->new_number_blocks = 0;
|
||||||
@@ -342,13 +342,13 @@ fluid_chorus_update(fluid_chorus_t* chorus)
|
|||||||
MAX_CHORUS);
|
MAX_CHORUS);
|
||||||
chorus->new_number_blocks = MAX_CHORUS;
|
chorus->new_number_blocks = MAX_CHORUS;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (chorus->new_speed_Hz < MIN_SPEED_HZ) {
|
if (chorus->new_speed_Hz < MIN_SPEED_HZ) {
|
||||||
fluid_log(FLUID_WARN, "chorus: speed is too low (min %f)! Setting value to min.",
|
fluid_log(FLUID_WARN, "chorus: speed is too low (min %f)! Setting value to min.",
|
||||||
(double) MIN_SPEED_HZ);
|
(double) MIN_SPEED_HZ);
|
||||||
chorus->new_speed_Hz = MIN_SPEED_HZ;
|
chorus->new_speed_Hz = MIN_SPEED_HZ;
|
||||||
} else if (chorus->new_speed_Hz > MAX_SPEED_HZ) {
|
} else if (chorus->new_speed_Hz > MAX_SPEED_HZ) {
|
||||||
fluid_log(FLUID_WARN, "chorus: speed must be below %f Hz! Setting value to max.",
|
fluid_log(FLUID_WARN, "chorus: speed must be below %f Hz! Setting value to max.",
|
||||||
(double) MAX_SPEED_HZ);
|
(double) MAX_SPEED_HZ);
|
||||||
chorus->new_speed_Hz = MAX_SPEED_HZ;
|
chorus->new_speed_Hz = MAX_SPEED_HZ;
|
||||||
}
|
}
|
||||||
@@ -357,7 +357,7 @@ fluid_chorus_update(fluid_chorus_t* chorus)
|
|||||||
chorus->new_depth_ms = 0.0;
|
chorus->new_depth_ms = 0.0;
|
||||||
}
|
}
|
||||||
/* Depth: Check for too high value through modulation_depth_samples. */
|
/* Depth: Check for too high value through modulation_depth_samples. */
|
||||||
|
|
||||||
if (chorus->new_level < 0.0) {
|
if (chorus->new_level < 0.0) {
|
||||||
fluid_log(FLUID_WARN, "chorus: level must be positive! Setting value to 0.");
|
fluid_log(FLUID_WARN, "chorus: level must be positive! Setting value to 0.");
|
||||||
chorus->new_level = 0.0;
|
chorus->new_level = 0.0;
|
||||||
@@ -366,40 +366,40 @@ fluid_chorus_update(fluid_chorus_t* chorus)
|
|||||||
"Setting it to 0.1.");
|
"Setting it to 0.1.");
|
||||||
chorus->new_level = 0.1;
|
chorus->new_level = 0.1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The modulating LFO goes through a full period every x samples: */
|
/* The modulating LFO goes through a full period every x samples: */
|
||||||
chorus->modulation_period_samples = chorus->sample_rate / chorus->new_speed_Hz;
|
chorus->modulation_period_samples = chorus->sample_rate / chorus->new_speed_Hz;
|
||||||
|
|
||||||
/* The variation in delay time is x: */
|
/* The variation in delay time is x: */
|
||||||
modulation_depth_samples = (int)
|
modulation_depth_samples = (int)
|
||||||
(chorus->new_depth_ms / 1000.0 /* convert modulation depth in ms to s*/
|
(chorus->new_depth_ms / 1000.0 /* convert modulation depth in ms to s*/
|
||||||
* chorus->sample_rate);
|
* chorus->sample_rate);
|
||||||
|
|
||||||
if (modulation_depth_samples > MAX_SAMPLES) {
|
if (modulation_depth_samples > MAX_SAMPLES) {
|
||||||
fluid_log(FLUID_WARN, "chorus: Too high depth. Setting it to max (%d).", MAX_SAMPLES);
|
fluid_log(FLUID_WARN, "chorus: Too high depth. Setting it to max (%d).", MAX_SAMPLES);
|
||||||
modulation_depth_samples = MAX_SAMPLES;
|
modulation_depth_samples = MAX_SAMPLES;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* initialize LFO table */
|
/* initialize LFO table */
|
||||||
if (chorus->type == FLUID_CHORUS_MOD_SINE) {
|
if (chorus->type == FLUID_CHORUS_MOD_SINE) {
|
||||||
fluid_chorus_sine(chorus->lookup_tab, chorus->modulation_period_samples,
|
fluid_chorus_sine(chorus->lookup_tab, chorus->modulation_period_samples,
|
||||||
modulation_depth_samples);
|
modulation_depth_samples);
|
||||||
} else if (chorus->type == FLUID_CHORUS_MOD_TRIANGLE) {
|
} else if (chorus->type == FLUID_CHORUS_MOD_TRIANGLE) {
|
||||||
fluid_chorus_triangle(chorus->lookup_tab, chorus->modulation_period_samples,
|
fluid_chorus_triangle(chorus->lookup_tab, chorus->modulation_period_samples,
|
||||||
modulation_depth_samples);
|
modulation_depth_samples);
|
||||||
} else {
|
} else {
|
||||||
fluid_log(FLUID_WARN, "chorus: Unknown modulation type. Using sinewave.");
|
fluid_log(FLUID_WARN, "chorus: Unknown modulation type. Using sinewave.");
|
||||||
chorus->type = FLUID_CHORUS_MOD_SINE;
|
chorus->type = FLUID_CHORUS_MOD_SINE;
|
||||||
fluid_chorus_sine(chorus->lookup_tab, chorus->modulation_period_samples,
|
fluid_chorus_sine(chorus->lookup_tab, chorus->modulation_period_samples,
|
||||||
modulation_depth_samples);
|
modulation_depth_samples);
|
||||||
};
|
};
|
||||||
|
|
||||||
for (i = 0; i < chorus->number_blocks; i++) {
|
for (i = 0; i < chorus->number_blocks; i++) {
|
||||||
/* Set the phase of the chorus blocks equally spaced */
|
/* Set the phase of the chorus blocks equally spaced */
|
||||||
chorus->phase[i] = (int) ((double) chorus->modulation_period_samples
|
chorus->phase[i] = (int) ((double) chorus->modulation_period_samples
|
||||||
* (double) i / (double) chorus->number_blocks);
|
* (double) i / (double) chorus->number_blocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start of the circular buffer */
|
/* Start of the circular buffer */
|
||||||
chorus->counter = 0;
|
chorus->counter = 0;
|
||||||
|
|
||||||
@@ -409,7 +409,7 @@ fluid_chorus_update(fluid_chorus_t* chorus)
|
|||||||
chorus->speed_Hz = chorus->new_speed_Hz;
|
chorus->speed_Hz = chorus->new_speed_Hz;
|
||||||
chorus->number_blocks = chorus->new_number_blocks;
|
chorus->number_blocks = chorus->new_number_blocks;
|
||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
|
|
||||||
/* failure: */
|
/* failure: */
|
||||||
/* Note: This lives on the assumption, that the last chorus values were correct.
|
/* Note: This lives on the assumption, that the last chorus values were correct.
|
||||||
* If not, this will loop forever and a day. */
|
* If not, this will loop forever and a day. */
|
||||||
@@ -423,7 +423,7 @@ fluid_chorus_update(fluid_chorus_t* chorus)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void fluid_chorus_processmix(fluid_chorus_t* chorus, fluid_real_t *in,
|
void fluid_chorus_processmix(fluid_chorus_t* chorus, fluid_real_t *in,
|
||||||
fluid_real_t *left_out, fluid_real_t *right_out)
|
fluid_real_t *left_out, fluid_real_t *right_out)
|
||||||
{
|
{
|
||||||
int sample_index;
|
int sample_index;
|
||||||
@@ -447,19 +447,19 @@ void fluid_chorus_processmix(fluid_chorus_t* chorus, fluid_real_t *in,
|
|||||||
for (i = 0; i < chorus->number_blocks; i++) {
|
for (i = 0; i < chorus->number_blocks; i++) {
|
||||||
int ii;
|
int ii;
|
||||||
/* Calculate the delay in subsamples for the delay line of chorus block nr. */
|
/* Calculate the delay in subsamples for the delay line of chorus block nr. */
|
||||||
|
|
||||||
/* The value in the lookup table is so, that this expression
|
/* The value in the lookup table is so, that this expression
|
||||||
* will always be positive. It will always include a number of
|
* will always be positive. It will always include a number of
|
||||||
* full periods of MAX_SAMPLES*INTERPOLATION_SUBSAMPLES to
|
* full periods of MAX_SAMPLES*INTERPOLATION_SUBSAMPLES to
|
||||||
* remain positive at all times. */
|
* remain positive at all times. */
|
||||||
int pos_subsamples = (INTERPOLATION_SUBSAMPLES * chorus->counter
|
int pos_subsamples = (INTERPOLATION_SUBSAMPLES * chorus->counter
|
||||||
- chorus->lookup_tab[chorus->phase[i]]);
|
- chorus->lookup_tab[chorus->phase[i]]);
|
||||||
|
|
||||||
int pos_samples = pos_subsamples/INTERPOLATION_SUBSAMPLES;
|
int pos_samples = pos_subsamples/INTERPOLATION_SUBSAMPLES;
|
||||||
|
|
||||||
/* modulo divide by INTERPOLATION_SUBSAMPLES */
|
/* modulo divide by INTERPOLATION_SUBSAMPLES */
|
||||||
pos_subsamples &= INTERPOLATION_SUBSAMPLES_ANDMASK;
|
pos_subsamples &= INTERPOLATION_SUBSAMPLES_ANDMASK;
|
||||||
|
|
||||||
for (ii = 0; ii < INTERPOLATION_SAMPLES; ii++){
|
for (ii = 0; ii < INTERPOLATION_SAMPLES; ii++){
|
||||||
/* Add the delayed signal to the chorus sum d_out Note: The
|
/* Add the delayed signal to the chorus sum d_out Note: The
|
||||||
* delay in the delay line moves backwards for increasing
|
* delay in the delay line moves backwards for increasing
|
||||||
@@ -467,8 +467,8 @@ void fluid_chorus_processmix(fluid_chorus_t* chorus, fluid_real_t *in,
|
|||||||
|
|
||||||
/* The & in chorusbuf[...] is equivalent to a division modulo
|
/* The & in chorusbuf[...] is equivalent to a division modulo
|
||||||
MAX_SAMPLES, only faster. */
|
MAX_SAMPLES, only faster. */
|
||||||
d_out += (chorus->chorusbuf[pos_samples & MAX_SAMPLES_ANDMASK]
|
d_out += chorus->chorusbuf[pos_samples & MAX_SAMPLES_ANDMASK]
|
||||||
* chorus->sinc_table[ii][pos_subsamples]);
|
* chorus->sinc_table[ii][pos_subsamples];
|
||||||
|
|
||||||
pos_samples--;
|
pos_samples--;
|
||||||
};
|
};
|
||||||
@@ -478,11 +478,11 @@ void fluid_chorus_processmix(fluid_chorus_t* chorus, fluid_real_t *in,
|
|||||||
} /* foreach chorus block */
|
} /* foreach chorus block */
|
||||||
|
|
||||||
d_out *= chorus->level;
|
d_out *= chorus->level;
|
||||||
|
|
||||||
/* Add the chorus sum d_out to output */
|
/* Add the chorus sum d_out to output */
|
||||||
left_out[sample_index] += d_out;
|
left_out[sample_index] += d_out;
|
||||||
right_out[sample_index] += d_out;
|
right_out[sample_index] += d_out;
|
||||||
|
|
||||||
/* Move forward in circular buffer */
|
/* Move forward in circular buffer */
|
||||||
chorus->counter++;
|
chorus->counter++;
|
||||||
chorus->counter %= MAX_SAMPLES;
|
chorus->counter %= MAX_SAMPLES;
|
||||||
@@ -490,8 +490,8 @@ void fluid_chorus_processmix(fluid_chorus_t* chorus, fluid_real_t *in,
|
|||||||
} /* foreach sample */
|
} /* foreach sample */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Duplication of code ... */
|
/* Duplication of code ... (replaces sample data instead of mixing) */
|
||||||
void fluid_chorus_processreplace(fluid_chorus_t* chorus, fluid_real_t *in,
|
void fluid_chorus_processreplace(fluid_chorus_t* chorus, fluid_real_t *in,
|
||||||
fluid_real_t *left_out, fluid_real_t *right_out)
|
fluid_real_t *left_out, fluid_real_t *right_out)
|
||||||
{
|
{
|
||||||
int sample_index;
|
int sample_index;
|
||||||
@@ -515,19 +515,19 @@ void fluid_chorus_processreplace(fluid_chorus_t* chorus, fluid_real_t *in,
|
|||||||
for (i = 0; i < chorus->number_blocks; i++) {
|
for (i = 0; i < chorus->number_blocks; i++) {
|
||||||
int ii;
|
int ii;
|
||||||
/* Calculate the delay in subsamples for the delay line of chorus block nr. */
|
/* Calculate the delay in subsamples for the delay line of chorus block nr. */
|
||||||
|
|
||||||
/* The value in the lookup table is so, that this expression
|
/* The value in the lookup table is so, that this expression
|
||||||
* will always be positive. It will always include a number of
|
* will always be positive. It will always include a number of
|
||||||
* full periods of MAX_SAMPLES*INTERPOLATION_SUBSAMPLES to
|
* full periods of MAX_SAMPLES*INTERPOLATION_SUBSAMPLES to
|
||||||
* remain positive at all times. */
|
* remain positive at all times. */
|
||||||
int pos_subsamples = (INTERPOLATION_SUBSAMPLES * chorus->counter
|
int pos_subsamples = (INTERPOLATION_SUBSAMPLES * chorus->counter
|
||||||
- chorus->lookup_tab[chorus->phase[i]]);
|
- chorus->lookup_tab[chorus->phase[i]]);
|
||||||
|
|
||||||
int pos_samples = pos_subsamples / INTERPOLATION_SUBSAMPLES;
|
int pos_samples = pos_subsamples / INTERPOLATION_SUBSAMPLES;
|
||||||
|
|
||||||
/* modulo divide by INTERPOLATION_SUBSAMPLES */
|
/* modulo divide by INTERPOLATION_SUBSAMPLES */
|
||||||
pos_subsamples &= INTERPOLATION_SUBSAMPLES_ANDMASK;
|
pos_subsamples &= INTERPOLATION_SUBSAMPLES_ANDMASK;
|
||||||
|
|
||||||
for (ii = 0; ii < INTERPOLATION_SAMPLES; ii++){
|
for (ii = 0; ii < INTERPOLATION_SAMPLES; ii++){
|
||||||
/* Add the delayed signal to the chorus sum d_out Note: The
|
/* Add the delayed signal to the chorus sum d_out Note: The
|
||||||
* delay in the delay line moves backwards for increasing
|
* delay in the delay line moves backwards for increasing
|
||||||
@@ -535,7 +535,8 @@ void fluid_chorus_processreplace(fluid_chorus_t* chorus, fluid_real_t *in,
|
|||||||
|
|
||||||
/* The & in chorusbuf[...] is equivalent to a division modulo
|
/* The & in chorusbuf[...] is equivalent to a division modulo
|
||||||
MAX_SAMPLES, only faster. */
|
MAX_SAMPLES, only faster. */
|
||||||
d_out += chorus->chorusbuf[pos_samples & MAX_SAMPLES_ANDMASK] * chorus->sinc_table[ii][pos_subsamples];
|
d_out += chorus->chorusbuf[pos_samples & MAX_SAMPLES_ANDMASK]
|
||||||
|
* chorus->sinc_table[ii][pos_subsamples];
|
||||||
|
|
||||||
pos_samples--;
|
pos_samples--;
|
||||||
};
|
};
|
||||||
@@ -545,11 +546,11 @@ void fluid_chorus_processreplace(fluid_chorus_t* chorus, fluid_real_t *in,
|
|||||||
} /* foreach chorus block */
|
} /* foreach chorus block */
|
||||||
|
|
||||||
d_out *= chorus->level;
|
d_out *= chorus->level;
|
||||||
|
|
||||||
/* Add the chorus sum d_out to output */
|
/* Store the chorus sum d_out to output */
|
||||||
left_out[sample_index] = d_out;
|
left_out[sample_index] = d_out;
|
||||||
right_out[sample_index] = d_out;
|
right_out[sample_index] = d_out;
|
||||||
|
|
||||||
/* Move forward in circular buffer */
|
/* Move forward in circular buffer */
|
||||||
chorus->counter++;
|
chorus->counter++;
|
||||||
chorus->counter %= MAX_SAMPLES;
|
chorus->counter %= MAX_SAMPLES;
|
||||||
@@ -598,7 +599,7 @@ void fluid_chorus_triangle(int *buf, int len, int depth)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fluid_chorus_reset(fluid_chorus_t* chorus)
|
fluid_chorus_reset(fluid_chorus_t* chorus)
|
||||||
{
|
{
|
||||||
fluid_chorus_init(chorus);
|
fluid_chorus_init(chorus);
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -32,9 +32,9 @@ typedef struct _fluid_chorus_t fluid_chorus_t;
|
|||||||
*/
|
*/
|
||||||
fluid_chorus_t* new_fluid_chorus(fluid_real_t sample_rate);
|
fluid_chorus_t* new_fluid_chorus(fluid_real_t sample_rate);
|
||||||
void delete_fluid_chorus(fluid_chorus_t* chorus);
|
void delete_fluid_chorus(fluid_chorus_t* chorus);
|
||||||
void fluid_chorus_processmix(fluid_chorus_t* chorus, fluid_real_t *in,
|
void fluid_chorus_processmix(fluid_chorus_t* chorus, fluid_real_t *in,
|
||||||
fluid_real_t *left_out, fluid_real_t *right_out);
|
fluid_real_t *left_out, fluid_real_t *right_out);
|
||||||
void fluid_chorus_processreplace(fluid_chorus_t* chorus, fluid_real_t *in,
|
void fluid_chorus_processreplace(fluid_chorus_t* chorus, fluid_real_t *in,
|
||||||
fluid_real_t *left_out, fluid_real_t *right_out);
|
fluid_real_t *left_out, fluid_real_t *right_out);
|
||||||
|
|
||||||
int fluid_chorus_init(fluid_chorus_t* chorus);
|
int fluid_chorus_init(fluid_chorus_t* chorus);
|
||||||
|
|||||||
+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
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -80,8 +80,8 @@ int fluid_handle_settings(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
|||||||
fluid_cmd_t* fluid_cmd_copy(fluid_cmd_t* cmd);
|
fluid_cmd_t* fluid_cmd_copy(fluid_cmd_t* cmd);
|
||||||
void delete_fluid_cmd(fluid_cmd_t* cmd);
|
void delete_fluid_cmd(fluid_cmd_t* cmd);
|
||||||
|
|
||||||
int fluid_cmd_handler_handle(fluid_cmd_handler_t* handler,
|
int fluid_cmd_handler_handle(fluid_cmd_handler_t* handler,
|
||||||
int ac, char** av,
|
int ac, char** av,
|
||||||
fluid_ostream_t out);
|
fluid_ostream_t out);
|
||||||
|
|
||||||
|
|
||||||
@@ -90,9 +90,9 @@ void fluid_server_remove_client(fluid_server_t* server, fluid_client_t* client);
|
|||||||
void fluid_server_add_client(fluid_server_t* server, fluid_client_t* client);
|
void fluid_server_add_client(fluid_server_t* server, fluid_client_t* client);
|
||||||
|
|
||||||
|
|
||||||
fluid_client_t* new_fluid_client(fluid_server_t* server,
|
fluid_client_t* new_fluid_client(fluid_server_t* server,
|
||||||
fluid_settings_t* settings,
|
fluid_settings_t* settings,
|
||||||
fluid_cmd_handler_t* handler,
|
fluid_cmd_handler_t* handler,
|
||||||
fluid_socket_t sock);
|
fluid_socket_t sock);
|
||||||
|
|
||||||
void delete_fluid_client(fluid_client_t* client);
|
void delete_fluid_client(fluid_client_t* client);
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -35,7 +35,7 @@ fluid_real_t fluid_pan_tab[FLUID_PAN_SIZE];
|
|||||||
*
|
*
|
||||||
* Does all the initialization for this module.
|
* Does all the initialization for this module.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
fluid_conversion_config(void)
|
fluid_conversion_config(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -44,7 +44,7 @@ fluid_conversion_config(void)
|
|||||||
for (i = 0; i < FLUID_CENTS_HZ_SIZE; i++) {
|
for (i = 0; i < FLUID_CENTS_HZ_SIZE; i++) {
|
||||||
fluid_ct2hz_tab[i] = (fluid_real_t) pow(2.0, (double) i / 1200.0);
|
fluid_ct2hz_tab[i] = (fluid_real_t) pow(2.0, (double) i / 1200.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* centibels to amplitude conversion
|
/* centibels to amplitude conversion
|
||||||
* Note: SF2.01 section 8.1.3: Initial attenuation range is
|
* Note: SF2.01 section 8.1.3: Initial attenuation range is
|
||||||
* between 0 and 144 dB. Therefore a negative attenuation is
|
* between 0 and 144 dB. Therefore a negative attenuation is
|
||||||
@@ -75,7 +75,7 @@ fluid_conversion_config(void)
|
|||||||
fluid_convex_tab[0] = 0;
|
fluid_convex_tab[0] = 0;
|
||||||
fluid_convex_tab[127] = 1.0;
|
fluid_convex_tab[127] = 1.0;
|
||||||
x = log10(128.0 / 127.0);
|
x = log10(128.0 / 127.0);
|
||||||
|
|
||||||
/* There seems to be an error in the specs. The equations are
|
/* There seems to be an error in the specs. The equations are
|
||||||
implemented according to the pictures on SF2.01 page 73. */
|
implemented according to the pictures on SF2.01 page 73. */
|
||||||
|
|
||||||
@@ -95,11 +95,11 @@ fluid_conversion_config(void)
|
|||||||
/*
|
/*
|
||||||
* fluid_ct2hz
|
* fluid_ct2hz
|
||||||
*/
|
*/
|
||||||
fluid_real_t
|
fluid_real_t
|
||||||
fluid_ct2hz_real(fluid_real_t cents)
|
fluid_ct2hz_real(fluid_real_t cents)
|
||||||
{
|
{
|
||||||
if (cents < 0)
|
if (cents < 0)
|
||||||
return (fluid_real_t) 1.0;
|
return (fluid_real_t) 1.0;
|
||||||
else if (cents < 900) {
|
else if (cents < 900) {
|
||||||
return (fluid_real_t) 6.875 * fluid_ct2hz_tab[(int) (cents + 300)];
|
return (fluid_real_t) 6.875 * fluid_ct2hz_tab[(int) (cents + 300)];
|
||||||
} else if (cents < 2100) {
|
} else if (cents < 2100) {
|
||||||
@@ -132,8 +132,8 @@ fluid_ct2hz_real(fluid_real_t cents)
|
|||||||
/*
|
/*
|
||||||
* fluid_ct2hz
|
* fluid_ct2hz
|
||||||
*/
|
*/
|
||||||
fluid_real_t
|
fluid_real_t
|
||||||
fluid_ct2hz(fluid_real_t cents)
|
fluid_ct2hz(fluid_real_t cents)
|
||||||
{
|
{
|
||||||
/* Filter fc limit: SF2.01 page 48 # 8 */
|
/* Filter fc limit: SF2.01 page 48 # 8 */
|
||||||
if (cents >= 13500){
|
if (cents >= 13500){
|
||||||
@@ -150,15 +150,15 @@ fluid_ct2hz(fluid_real_t cents)
|
|||||||
* in: a value between 0 and 960, 0 is no attenuation
|
* in: a value between 0 and 960, 0 is no attenuation
|
||||||
* out: a value between 1 and 0
|
* out: a value between 1 and 0
|
||||||
*/
|
*/
|
||||||
fluid_real_t
|
fluid_real_t
|
||||||
fluid_cb2amp(fluid_real_t cb)
|
fluid_cb2amp(fluid_real_t cb)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* cb: an attenuation in 'centibels' (1/10 dB)
|
* cb: an attenuation in 'centibels' (1/10 dB)
|
||||||
* SF2.01 page 49 # 48 limits it to 144 dB.
|
* SF2.01 page 49 # 48 limits it to 144 dB.
|
||||||
* 96 dB is reasonable for 16 bit systems, 144 would make sense for 24 bit.
|
* 96 dB is reasonable for 16 bit systems, 144 would make sense for 24 bit.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* minimum attenuation: 0 dB */
|
/* minimum attenuation: 0 dB */
|
||||||
if (cb < 0) {
|
if (cb < 0) {
|
||||||
return 1.0;
|
return 1.0;
|
||||||
@@ -166,7 +166,7 @@ fluid_cb2amp(fluid_real_t cb)
|
|||||||
if (cb >= FLUID_CB_AMP_SIZE) {
|
if (cb >= FLUID_CB_AMP_SIZE) {
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
return fluid_cb2amp_tab[(int) cb];
|
return fluid_cb2amp_tab[(int) cb];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -178,7 +178,7 @@ fluid_cb2amp(fluid_real_t cb)
|
|||||||
* Note: Volume attenuation is supposed to be centibels but EMU8k/10k don't
|
* Note: Volume attenuation is supposed to be centibels but EMU8k/10k don't
|
||||||
* follow this. Thats the reason for separate fluid_cb2amp and fluid_atten2amp.
|
* follow this. Thats the reason for separate fluid_cb2amp and fluid_atten2amp.
|
||||||
*/
|
*/
|
||||||
fluid_real_t
|
fluid_real_t
|
||||||
fluid_atten2amp(fluid_real_t atten)
|
fluid_atten2amp(fluid_real_t atten)
|
||||||
{
|
{
|
||||||
if (atten < 0) return 1.0;
|
if (atten < 0) return 1.0;
|
||||||
@@ -189,7 +189,7 @@ fluid_atten2amp(fluid_real_t atten)
|
|||||||
/*
|
/*
|
||||||
* fluid_tc2sec_delay
|
* fluid_tc2sec_delay
|
||||||
*/
|
*/
|
||||||
fluid_real_t
|
fluid_real_t
|
||||||
fluid_tc2sec_delay(fluid_real_t tc)
|
fluid_tc2sec_delay(fluid_real_t tc)
|
||||||
{
|
{
|
||||||
/* SF2.01 section 8.1.2 items 21, 23, 25, 33
|
/* SF2.01 section 8.1.2 items 21, 23, 25, 33
|
||||||
@@ -212,7 +212,7 @@ fluid_tc2sec_delay(fluid_real_t tc)
|
|||||||
/*
|
/*
|
||||||
* fluid_tc2sec_attack
|
* fluid_tc2sec_attack
|
||||||
*/
|
*/
|
||||||
fluid_real_t
|
fluid_real_t
|
||||||
fluid_tc2sec_attack(fluid_real_t tc)
|
fluid_tc2sec_attack(fluid_real_t tc)
|
||||||
{
|
{
|
||||||
/* SF2.01 section 8.1.2 items 26, 34
|
/* SF2.01 section 8.1.2 items 26, 34
|
||||||
@@ -228,7 +228,7 @@ fluid_tc2sec_attack(fluid_real_t tc)
|
|||||||
/*
|
/*
|
||||||
* fluid_tc2sec
|
* fluid_tc2sec
|
||||||
*/
|
*/
|
||||||
fluid_real_t
|
fluid_real_t
|
||||||
fluid_tc2sec(fluid_real_t tc)
|
fluid_tc2sec(fluid_real_t tc)
|
||||||
{
|
{
|
||||||
/* No range checking here! */
|
/* No range checking here! */
|
||||||
@@ -238,7 +238,7 @@ fluid_tc2sec(fluid_real_t tc)
|
|||||||
/*
|
/*
|
||||||
* fluid_tc2sec_release
|
* fluid_tc2sec_release
|
||||||
*/
|
*/
|
||||||
fluid_real_t
|
fluid_real_t
|
||||||
fluid_tc2sec_release(fluid_real_t tc)
|
fluid_tc2sec_release(fluid_real_t tc)
|
||||||
{
|
{
|
||||||
/* SF2.01 section 8.1.2 items 30, 38
|
/* SF2.01 section 8.1.2 items 30, 38
|
||||||
@@ -256,7 +256,7 @@ fluid_tc2sec_release(fluid_real_t tc)
|
|||||||
*
|
*
|
||||||
* Convert from absolute cents to Hertz
|
* Convert from absolute cents to Hertz
|
||||||
*/
|
*/
|
||||||
fluid_real_t
|
fluid_real_t
|
||||||
fluid_act2hz(fluid_real_t c)
|
fluid_act2hz(fluid_real_t c)
|
||||||
{
|
{
|
||||||
return (fluid_real_t) (8.176 * pow(2.0, (double) c / 1200.0));
|
return (fluid_real_t) (8.176 * pow(2.0, (double) c / 1200.0));
|
||||||
@@ -267,7 +267,7 @@ fluid_act2hz(fluid_real_t c)
|
|||||||
*
|
*
|
||||||
* Convert from Hertz to cents
|
* Convert from Hertz to cents
|
||||||
*/
|
*/
|
||||||
fluid_real_t
|
fluid_real_t
|
||||||
fluid_hz2ct(fluid_real_t f)
|
fluid_hz2ct(fluid_real_t f)
|
||||||
{
|
{
|
||||||
return (fluid_real_t) (6900 + 1200 * log(f / 440.0) / log(2.0));
|
return (fluid_real_t) (6900 + 1200 * log(f / 440.0) / log(2.0));
|
||||||
@@ -276,7 +276,7 @@ fluid_hz2ct(fluid_real_t f)
|
|||||||
/*
|
/*
|
||||||
* fluid_pan
|
* fluid_pan
|
||||||
*/
|
*/
|
||||||
fluid_real_t
|
fluid_real_t
|
||||||
fluid_pan(fluid_real_t c, int left)
|
fluid_pan(fluid_real_t c, int left)
|
||||||
{
|
{
|
||||||
if (left) {
|
if (left) {
|
||||||
@@ -294,7 +294,7 @@ fluid_pan(fluid_real_t c, int left)
|
|||||||
/*
|
/*
|
||||||
* fluid_concave
|
* fluid_concave
|
||||||
*/
|
*/
|
||||||
fluid_real_t
|
fluid_real_t
|
||||||
fluid_concave(fluid_real_t val)
|
fluid_concave(fluid_real_t val)
|
||||||
{
|
{
|
||||||
if (val < 0) {
|
if (val < 0) {
|
||||||
@@ -308,7 +308,7 @@ fluid_concave(fluid_real_t val)
|
|||||||
/*
|
/*
|
||||||
* fluid_convex
|
* fluid_convex
|
||||||
*/
|
*/
|
||||||
fluid_real_t
|
fluid_real_t
|
||||||
fluid_convex(fluid_real_t val)
|
fluid_convex(fluid_real_t val)
|
||||||
{
|
{
|
||||||
if (val < 0) {
|
if (val < 0) {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -13,7 +13,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -218,7 +218,6 @@ extern unsigned short badpgen[]; /* list of bad preset generators */
|
|||||||
void sfont_init_chunks (void);
|
void sfont_init_chunks (void);
|
||||||
|
|
||||||
void sfont_close (SFData * sf);
|
void sfont_close (SFData * sf);
|
||||||
void sfont_free_data (SFData * sf);
|
|
||||||
void sfont_free_zone (SFZone * zone);
|
void sfont_free_zone (SFZone * zone);
|
||||||
int sfont_preset_compare_func (void* a, void* b);
|
int sfont_preset_compare_func (void* a, void* b);
|
||||||
|
|
||||||
@@ -230,8 +229,8 @@ int gen_validp (int gen);
|
|||||||
|
|
||||||
|
|
||||||
/*-----------------------------------sffile.h----------------------------*/
|
/*-----------------------------------sffile.h----------------------------*/
|
||||||
/*
|
/*
|
||||||
File structures and routines (used to be in sffile.h)
|
File structures and routines (used to be in sffile.h)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define CHNKIDSTR(id) &idlist[(id - 1) * 4]
|
#define CHNKIDSTR(id) &idlist[(id - 1) * 4]
|
||||||
@@ -427,7 +426,6 @@ enum
|
|||||||
#define ErrnoEnd ErrWrite
|
#define ErrnoEnd ErrWrite
|
||||||
|
|
||||||
int gerr (int ev, char * fmt, ...);
|
int gerr (int ev, char * fmt, ...);
|
||||||
void *safe_malloc (size_t size);
|
|
||||||
int safe_fread (void *buf, int count, FILE * fd);
|
int safe_fread (void *buf, int count, FILE * fd);
|
||||||
int safe_fwrite (void *buf, int count, FILE * fd);
|
int safe_fwrite (void *buf, int count, FILE * fd);
|
||||||
int safe_fseek (FILE * fd, long ofs, int whence);
|
int safe_fseek (FILE * fd, long ofs, int whence);
|
||||||
@@ -443,7 +441,7 @@ int safe_fseek (FILE * fd, long ofs, int whence);
|
|||||||
|
|
||||||
/***************************************************************
|
/***************************************************************
|
||||||
*
|
*
|
||||||
* FORWARD DECLARATIONS
|
* FORWARD DECLARATIONS
|
||||||
*/
|
*/
|
||||||
typedef struct _fluid_defsfont_t fluid_defsfont_t;
|
typedef struct _fluid_defsfont_t fluid_defsfont_t;
|
||||||
typedef struct _fluid_defpreset_t fluid_defpreset_t;
|
typedef struct _fluid_defpreset_t fluid_defpreset_t;
|
||||||
|
|||||||
@@ -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
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
* 02111-1307, USA
|
* 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "fluidsynth_priv.h"
|
||||||
|
#include "fluid_phase.h"
|
||||||
|
|
||||||
/* Purpose:
|
/* Purpose:
|
||||||
* Low-level voice processing:
|
|
||||||
*
|
*
|
||||||
* - interpolates (obtains values between the samples of the original waveform data)
|
* Interpolates audio data (obtains values between the samples of the original
|
||||||
* - filters (applies a lowpass filter with variable cutoff frequency and quality factor)
|
* waveform data).
|
||||||
* - mixes the processed sample to left and right output using the pan setting
|
|
||||||
* - sends the processed sample to chorus and reverb
|
|
||||||
*
|
*
|
||||||
*
|
* Variables loaded from the voice structure (assigned in fluid_voice_write()):
|
||||||
* This file does -not- generate an object file.
|
|
||||||
* Instead, it is #included in several places in fluid_voice.c.
|
|
||||||
* The motivation for this is
|
|
||||||
* - Calling it as a subroutine may be time consuming, especially with optimization off
|
|
||||||
* - The previous implementation as a macro was clumsy to handle
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Fluid_voice.c sets a couple of variables before #including this:
|
|
||||||
* - dsp_data: Pointer to the original waveform data
|
* - dsp_data: Pointer to the original waveform data
|
||||||
* - dsp_left_buf: The generated signal goes here, left channel
|
|
||||||
* - dsp_right_buf: right channel
|
|
||||||
* - dsp_reverb_buf: Send to reverb unit
|
|
||||||
* - dsp_chorus_buf: Send to chorus unit
|
|
||||||
* - dsp_start: Start processing at this output buffer index
|
|
||||||
* - dsp_end: End processing just before this output buffer index
|
|
||||||
* - dsp_a1: Coefficient for the filter
|
|
||||||
* - dsp_a2: same
|
|
||||||
* - dsp_b0: same
|
|
||||||
* - dsp_b1: same
|
|
||||||
* - dsp_b2: same
|
|
||||||
* - dsp_filter_flag: Set, the filter is needed (many sound fonts don't use
|
|
||||||
* the filter at all. If it is left at its default setting
|
|
||||||
* of roughly 20 kHz, there is no need to apply filterling.)
|
|
||||||
* - dsp_interp_method: Which interpolation method to use.
|
|
||||||
* - voice holds the voice structure
|
|
||||||
*
|
|
||||||
* Some variables are set and modified:
|
|
||||||
* - dsp_phase: The position in the original waveform data.
|
* - dsp_phase: The position in the original waveform data.
|
||||||
* This has an integer and a fractional part (between samples).
|
* This has an integer and a fractional part (between samples).
|
||||||
* - dsp_phase_incr: For each output sample, the position in the original
|
* - dsp_phase_incr: For each output sample, the position in the original
|
||||||
* waveform advances by dsp_phase_incr. This also has an integer
|
* waveform advances by dsp_phase_incr. This also has an integer
|
||||||
* part and a fractional part.
|
* part and a fractional part.
|
||||||
* If a sample is played at root pitch (no pitch change),
|
* If a sample is played at root pitch (no pitch change),
|
||||||
* dsp_phase_incr is integer=1 and fractional=0.
|
* dsp_phase_incr is integer=1 and fractional=0.
|
||||||
* - dsp_amp: The current amplitude envelope value.
|
* - dsp_amp: The current amplitude envelope value.
|
||||||
* - dsp_amp_incr: The changing rate of the amplitude envelope.
|
* - dsp_amp_incr: The changing rate of the amplitude envelope.
|
||||||
*
|
*
|
||||||
* A couple of variables are used internally, their results are discarded:
|
* A couple of variables are used internally, their results are discarded:
|
||||||
* - dsp_i: Index through the output buffer
|
* - dsp_i: Index through the output buffer
|
||||||
* - dsp_phase_fractional: The fractional part of dsp_phase
|
* - dsp_buf: Output buffer of floating point values (FLUID_BUFSIZE in length)
|
||||||
* - dsp_coeff: A table of four coefficients, depending on the fractional phase.
|
|
||||||
* Used to interpolate between samples.
|
|
||||||
* - dsp_process_buffer: Holds the processed signal between stages
|
|
||||||
* - dsp_centernode: delay line for the IIR filter
|
|
||||||
* - dsp_hist1: same
|
|
||||||
* - dsp_hist2: same
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Purpose:
|
#include "fluidsynth_priv.h"
|
||||||
* zap_almost_zero will return a number, as long as its
|
#include "fluid_synth.h"
|
||||||
* absolute value is over a certain threshold. Otherwise 0. See
|
#include "fluid_voice.h"
|
||||||
* fluid_rev.c for documentation (denormal numbers)
|
|
||||||
*/
|
|
||||||
|
|
||||||
# if defined(WITH_FLOAT)
|
|
||||||
# define zap_almost_zero(_sample) \
|
|
||||||
((((*(unsigned int*)&(_sample))&0x7f800000) < 0x08000000)? 0.0f : (_sample))
|
|
||||||
# else
|
|
||||||
/* 1e-20 was chosen as an arbitrary (small) threshold. */
|
|
||||||
#define zap_almost_zero(_sample) ((abs(_sample) < 1e-20)? 0.0f : (_sample))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Interpolation (find a value between two samples of the original waveform) */
|
/* Interpolation (find a value between two samples of the original waveform) */
|
||||||
|
|
||||||
if ((fluid_phase_fract(dsp_phase) == 0)
|
/* Linear interpolation table (2 coefficients centered on 1st) */
|
||||||
&& (fluid_phase_fract(dsp_phase_incr) == 0)
|
static fluid_real_t interp_coeff_linear[FLUID_INTERP_MAX][2];
|
||||||
&& (fluid_phase_index(dsp_phase_incr) == 1)) {
|
|
||||||
|
|
||||||
/* Check for a special case: The current phase falls directly on an
|
/* 4th order (cubic) interpolation table (4 coefficients centered on 2nd) */
|
||||||
* original sample. Also, the stepsize per output sample is exactly
|
static fluid_real_t interp_coeff[FLUID_INTERP_MAX][4];
|
||||||
* one sample, no fractional part. In other words: The sample is
|
|
||||||
* played back at normal phase and root pitch. => No interpolation
|
|
||||||
* needed.
|
|
||||||
*/
|
|
||||||
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) {
|
|
||||||
/* Mix to the buffer and advance the phase by one sample */
|
|
||||||
dsp_buf[dsp_i] = dsp_amp * dsp_data[fluid_phase_index_plusplus(dsp_phase)];
|
|
||||||
dsp_amp += dsp_amp_incr;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
/* 7th order interpolation (7 coefficients centered on 3rd) */
|
||||||
|
static fluid_real_t sinc_table7[FLUID_INTERP_MAX][7];
|
||||||
/* wave table interpolation: Choose the interpolation method */
|
|
||||||
|
|
||||||
switch(dsp_interp_method){
|
|
||||||
case FLUID_INTERP_NONE:
|
|
||||||
/* No interpolation. Just take the sample, which is closest to
|
|
||||||
* the playback pointer. Questionable quality, but very
|
|
||||||
* efficient. */
|
|
||||||
|
|
||||||
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) {
|
|
||||||
dsp_phase_index = fluid_phase_index(dsp_phase);
|
|
||||||
dsp_buf[dsp_i] = dsp_amp * dsp_data[dsp_phase_index];
|
|
||||||
|
|
||||||
/* increment phase and amplitude */
|
|
||||||
fluid_phase_incr(dsp_phase, dsp_phase_incr);
|
|
||||||
dsp_amp += dsp_amp_incr;
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FLUID_INTERP_LINEAR:
|
|
||||||
/* Straight line interpolation. */
|
|
||||||
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) {
|
|
||||||
dsp_coeff = &interp_coeff_linear[fluid_phase_fract_to_tablerow(dsp_phase)];
|
|
||||||
dsp_phase_index = fluid_phase_index(dsp_phase);
|
|
||||||
dsp_buf[dsp_i] = (dsp_amp *
|
|
||||||
(dsp_coeff->a0 * dsp_data[dsp_phase_index]
|
|
||||||
+ dsp_coeff->a1 * dsp_data[dsp_phase_index+1]));
|
|
||||||
|
|
||||||
/* increment phase and amplitude */
|
|
||||||
fluid_phase_incr(dsp_phase, dsp_phase_incr);
|
|
||||||
dsp_amp += dsp_amp_incr;
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FLUID_INTERP_4THORDER:
|
|
||||||
default:
|
|
||||||
/* Default interpolation loop using floats */
|
|
||||||
|
|
||||||
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) {
|
|
||||||
dsp_coeff = &interp_coeff[fluid_phase_fract_to_tablerow(dsp_phase)];
|
|
||||||
|
|
||||||
dsp_phase_index = fluid_phase_index(dsp_phase);
|
|
||||||
dsp_buf[dsp_i] = (dsp_amp *
|
|
||||||
(dsp_coeff->a0 * dsp_data[dsp_phase_index]
|
|
||||||
+ dsp_coeff->a1 * dsp_data[dsp_phase_index+1]
|
|
||||||
+ dsp_coeff->a2 * dsp_data[dsp_phase_index+2]
|
|
||||||
+ dsp_coeff->a3 * dsp_data[dsp_phase_index+3]));
|
|
||||||
|
|
||||||
/* increment phase and amplitude */
|
|
||||||
fluid_phase_incr(dsp_phase, dsp_phase_incr);
|
|
||||||
dsp_amp += dsp_amp_incr;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
case FLUID_INTERP_7THORDER:
|
#define SINC_INTERP_ORDER 7 /* 7th order constant */
|
||||||
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) {
|
|
||||||
int fract = fluid_phase_fract_to_tablerow(dsp_phase);
|
|
||||||
dsp_phase_index = fluid_phase_index(dsp_phase);
|
|
||||||
dsp_buf[dsp_i] = (dsp_amp *
|
|
||||||
(sinc_table7[0][fract] * (fluid_real_t) dsp_data[dsp_phase_index]
|
|
||||||
+ sinc_table7[1][fract] * (fluid_real_t) dsp_data[dsp_phase_index+1]
|
|
||||||
+ sinc_table7[2][fract] * (fluid_real_t) dsp_data[dsp_phase_index+2]
|
|
||||||
+ sinc_table7[3][fract] * (fluid_real_t) dsp_data[dsp_phase_index+3]
|
|
||||||
+ sinc_table7[4][fract] * (fluid_real_t) dsp_data[dsp_phase_index+4]
|
|
||||||
+ sinc_table7[5][fract] * (fluid_real_t) dsp_data[dsp_phase_index+5]
|
|
||||||
+ sinc_table7[6][fract] * (fluid_real_t) dsp_data[dsp_phase_index+6]));
|
|
||||||
|
|
||||||
/* increment phase and amplitude */
|
|
||||||
fluid_phase_incr(dsp_phase, dsp_phase_incr);
|
|
||||||
dsp_amp += dsp_amp_incr;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
} /* switch interpolation method */
|
|
||||||
} /* If interpolation is needed */
|
|
||||||
|
|
||||||
/* filter (implement the voice filter according to Soundfont standard) */
|
|
||||||
if (dsp_use_filter_flag) {
|
|
||||||
|
|
||||||
/* Check for denormal number (too close to zero) once in a
|
|
||||||
* while. This is not a big concern here - why would someone play a
|
|
||||||
* sample with an empty tail? */
|
|
||||||
dsp_hist1 = zap_almost_zero(dsp_hist1);
|
|
||||||
|
|
||||||
/* Two versions of the filter loop. One, while the filter is
|
|
||||||
* changing towards its new setting. The other, if the filter
|
|
||||||
* doesn't change.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (dsp_filter_coeff_incr_count > 0) {
|
|
||||||
/* The increment is added to each filter coefficient
|
|
||||||
filter_coeff_incr_count times. */
|
|
||||||
|
|
||||||
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) {
|
|
||||||
/* The filter is implemented in Direct-II form. */
|
|
||||||
dsp_centernode = dsp_buf[dsp_i] - dsp_a1 * dsp_hist1 - dsp_a2 * dsp_hist2;
|
|
||||||
dsp_buf[dsp_i] = dsp_b02 * (dsp_centernode + dsp_hist2) + dsp_b1 * dsp_hist1;
|
|
||||||
dsp_hist2 = dsp_hist1;
|
|
||||||
dsp_hist1 = dsp_centernode;
|
|
||||||
|
|
||||||
if (dsp_filter_coeff_incr_count-- > 0){
|
|
||||||
dsp_a1 += dsp_a1_incr;
|
|
||||||
dsp_a2 += dsp_a2_incr;
|
|
||||||
dsp_b02 += dsp_b02_incr;
|
|
||||||
dsp_b1 += dsp_b1_incr;
|
|
||||||
}
|
|
||||||
} /* for dsp_i */
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* The filter parameters are constant. This is duplicated to save
|
|
||||||
* time. */
|
|
||||||
|
|
||||||
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) {
|
|
||||||
/* The filter is implemented in Direct-II form. */
|
|
||||||
dsp_centernode = dsp_buf[dsp_i] - dsp_a1 * dsp_hist1 - dsp_a2 * dsp_hist2;
|
|
||||||
dsp_buf[dsp_i] = dsp_b02 * (dsp_centernode + dsp_hist2) + dsp_b1 * dsp_hist1;
|
|
||||||
dsp_hist2 = dsp_hist1;
|
|
||||||
dsp_hist1 = dsp_centernode;
|
|
||||||
}
|
|
||||||
} /* if filter is fixed */
|
|
||||||
} /* if filter is enabled */
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Initializes interpolation tables */
|
||||||
|
void fluid_dsp_float_config (void)
|
||||||
|
{
|
||||||
|
int i, i2;
|
||||||
|
double x, v;
|
||||||
|
double i_shifted;
|
||||||
|
|
||||||
/* pan (Copy the signal to the left and right output buffer) The voice
|
/* Initialize the coefficients for the interpolation. The math comes
|
||||||
* panning generator has a range of -500 .. 500. If it is centered,
|
* from a mail, posted by Olli Niemitalo to the music-dsp mailing
|
||||||
* it's close to 0. voice->amp_left and voice->amp_right are then the
|
* list (I found it in the music-dsp archives
|
||||||
* same, and we can save one multiplication per voice and sample.
|
* http://www.smartelectronix.com/musicdsp/). */
|
||||||
*/
|
|
||||||
if ((-0.5 < voice->pan) && (voice->pan < 0.5)) {
|
|
||||||
|
|
||||||
/* The voice is centered. Use voice->amp_left twice. */
|
|
||||||
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) {
|
|
||||||
float v = voice->amp_left * dsp_buf[dsp_i];
|
|
||||||
dsp_left_buf[dsp_i] += v;
|
|
||||||
dsp_right_buf[dsp_i] += v;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
for (i = 0; i < FLUID_INTERP_MAX; i++)
|
||||||
|
{
|
||||||
|
x = (double) i / (double) FLUID_INTERP_MAX;
|
||||||
|
|
||||||
/* The voice is not centered. For stereo samples, one of the
|
interp_coeff[i][0] = (fluid_real_t)(x * (-0.5 + x * (1 - 0.5 * x)));
|
||||||
* amplitudes will be zero. */
|
interp_coeff[i][1] = (fluid_real_t)(1.0 + x * x * (1.5 * x - 2.5));
|
||||||
if (voice->amp_left != 0.0){
|
interp_coeff[i][2] = (fluid_real_t)(x * (0.5 + x * (2.0 - 1.5 * x)));
|
||||||
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) {
|
interp_coeff[i][3] = (fluid_real_t)(0.5 * x * x * (x - 1.0));
|
||||||
dsp_left_buf[dsp_i] += voice->amp_left * dsp_buf[dsp_i];
|
|
||||||
}
|
interp_coeff_linear[i][0] = (fluid_real_t)(1.0 - x);
|
||||||
}
|
interp_coeff_linear[i][1] = (fluid_real_t)x;
|
||||||
if (voice->amp_right != 0.0){
|
}
|
||||||
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) {
|
|
||||||
dsp_right_buf[dsp_i] += voice->amp_right * dsp_buf[dsp_i];
|
/* i: Offset in terms of whole samples */
|
||||||
}
|
for (i = 0; i < SINC_INTERP_ORDER; i++)
|
||||||
}
|
{ /* i2: Offset in terms of fractional samples ('subsamples') */
|
||||||
|
for (i2 = 0; i2 < FLUID_INTERP_MAX; i2++)
|
||||||
|
{
|
||||||
|
/* center on middle of table */
|
||||||
|
i_shifted = (double)i - ((double)SINC_INTERP_ORDER / 2.0)
|
||||||
|
+ (double)i2 / (double)FLUID_INTERP_MAX;
|
||||||
|
|
||||||
|
/* sinc(0) cannot be calculated straightforward (limit needed for 0/0) */
|
||||||
|
if (fabs (i_shifted) > 0.000001)
|
||||||
|
{
|
||||||
|
v = (fluid_real_t)sin (i_shifted * M_PI) / (M_PI * i_shifted);
|
||||||
|
/* Hamming window */
|
||||||
|
v *= (fluid_real_t)0.5 * (1.0 + cos (2.0 * M_PI * i_shifted / (fluid_real_t)SINC_INTERP_ORDER));
|
||||||
|
}
|
||||||
|
else v = 1.0;
|
||||||
|
|
||||||
|
sinc_table7[FLUID_INTERP_MAX - i2 - 1][i] = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
for (i = 0; i < FLUID_INTERP_MAX; i++)
|
||||||
|
{
|
||||||
|
printf ("%d %0.3f %0.3f %0.3f %0.3f %0.3f %0.3f %0.3f\n",
|
||||||
|
i, sinc_table7[0][i], sinc_table7[1][i], sinc_table7[2][i],
|
||||||
|
sinc_table7[3][i], sinc_table7[4][i], sinc_table7[5][i], sinc_table7[6][i]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fluid_check_fpe("interpolation table calculation");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reverb send. Buffer may be NULL. */
|
|
||||||
if ((dsp_reverb_buf != NULL) && (voice->amp_reverb != 0.0)) {
|
/* No interpolation. Just take the sample, which is closest to
|
||||||
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) {
|
* the playback pointer. Questionable quality, but very
|
||||||
dsp_reverb_buf[dsp_i] += voice->amp_reverb * dsp_buf[dsp_i];
|
* efficient. */
|
||||||
}
|
int
|
||||||
|
fluid_dsp_float_interpolate_none (fluid_voice_t *voice)
|
||||||
|
{
|
||||||
|
fluid_phase_t dsp_phase = voice->phase;
|
||||||
|
fluid_phase_t dsp_phase_incr, end_phase;
|
||||||
|
short int *dsp_data = voice->sample->data;
|
||||||
|
fluid_real_t *dsp_buf = voice->dsp_buf;
|
||||||
|
fluid_real_t dsp_amp = voice->amp;
|
||||||
|
fluid_real_t dsp_amp_incr = voice->amp_incr;
|
||||||
|
unsigned int dsp_i = 0;
|
||||||
|
unsigned int dsp_phase_index;
|
||||||
|
unsigned int end_index;
|
||||||
|
int looping;
|
||||||
|
|
||||||
|
/* Convert playback "speed" floating point value to phase index/fract */
|
||||||
|
fluid_phase_set_float (dsp_phase_incr, voice->phase_incr);
|
||||||
|
|
||||||
|
/* voice is currently looping? */
|
||||||
|
looping = _SAMPLEMODE (voice) == FLUID_LOOP_DURING_RELEASE
|
||||||
|
|| (_SAMPLEMODE (voice) == FLUID_LOOP_UNTIL_RELEASE
|
||||||
|
&& voice->volenv_section < FLUID_VOICE_ENVRELEASE);
|
||||||
|
|
||||||
|
end_index = looping ? voice->loopend - 1 : voice->end;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
dsp_phase_index = fluid_phase_index_round (dsp_phase); /* round to nearest point */
|
||||||
|
|
||||||
|
/* interpolate sequence of sample points */
|
||||||
|
for ( ; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++)
|
||||||
|
{
|
||||||
|
dsp_buf[dsp_i] = dsp_amp * dsp_data[dsp_phase_index];
|
||||||
|
|
||||||
|
/* increment phase and amplitude */
|
||||||
|
fluid_phase_incr (dsp_phase, dsp_phase_incr);
|
||||||
|
dsp_phase_index = fluid_phase_index_round (dsp_phase); /* round to nearest point */
|
||||||
|
dsp_amp += dsp_amp_incr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* break out if not looping (buffer may not be full) */
|
||||||
|
if (!looping) break;
|
||||||
|
|
||||||
|
/* go back to loop start */
|
||||||
|
if (dsp_phase_index > end_index)
|
||||||
|
{
|
||||||
|
fluid_phase_sub_int (dsp_phase, voice->loopend - voice->loopstart);
|
||||||
|
voice->has_looped = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* break out if filled buffer */
|
||||||
|
if (dsp_i >= FLUID_BUFSIZE) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
voice->phase = dsp_phase;
|
||||||
|
voice->amp = dsp_amp;
|
||||||
|
|
||||||
|
return (dsp_i);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* chorus send. Buffer may be NULL. */
|
/* Straight line interpolation.
|
||||||
if ((dsp_chorus_buf != NULL) && (voice->amp_chorus != 0)) {
|
* Returns number of samples processed (usually FLUID_BUFSIZE but could be
|
||||||
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) {
|
* smaller if end of sample occurs).
|
||||||
dsp_chorus_buf[dsp_i] += voice->amp_chorus * dsp_buf[dsp_i];
|
*/
|
||||||
}
|
int
|
||||||
|
fluid_dsp_float_interpolate_linear (fluid_voice_t *voice)
|
||||||
|
{
|
||||||
|
fluid_phase_t dsp_phase = voice->phase;
|
||||||
|
fluid_phase_t dsp_phase_incr, end_phase;
|
||||||
|
short int *dsp_data = voice->sample->data;
|
||||||
|
fluid_real_t *dsp_buf = voice->dsp_buf;
|
||||||
|
fluid_real_t dsp_amp = voice->amp;
|
||||||
|
fluid_real_t dsp_amp_incr = voice->amp_incr;
|
||||||
|
unsigned int dsp_i = 0;
|
||||||
|
unsigned int dsp_phase_index;
|
||||||
|
unsigned int end_index;
|
||||||
|
short int point;
|
||||||
|
fluid_real_t *coeffs;
|
||||||
|
int looping;
|
||||||
|
|
||||||
|
/* Convert playback "speed" floating point value to phase index/fract */
|
||||||
|
fluid_phase_set_float (dsp_phase_incr, voice->phase_incr);
|
||||||
|
|
||||||
|
/* voice is currently looping? */
|
||||||
|
looping = _SAMPLEMODE (voice) == FLUID_LOOP_DURING_RELEASE
|
||||||
|
|| (_SAMPLEMODE (voice) == FLUID_LOOP_UNTIL_RELEASE
|
||||||
|
&& voice->volenv_section < FLUID_VOICE_ENVRELEASE);
|
||||||
|
|
||||||
|
/* last index before 2nd interpolation point must be specially handled */
|
||||||
|
end_index = (looping ? voice->loopend - 1 : voice->end) - 1;
|
||||||
|
|
||||||
|
/* 2nd interpolation point to use at end of loop or sample */
|
||||||
|
if (looping) point = dsp_data[voice->loopstart]; /* loop start */
|
||||||
|
else point = dsp_data[voice->end]; /* duplicate end for samples no longer looping */
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
dsp_phase_index = fluid_phase_index (dsp_phase);
|
||||||
|
|
||||||
|
/* interpolate the sequence of sample points */
|
||||||
|
for ( ; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++)
|
||||||
|
{
|
||||||
|
coeffs = interp_coeff_linear[fluid_phase_fract_to_tablerow (dsp_phase)];
|
||||||
|
dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * dsp_data[dsp_phase_index]
|
||||||
|
+ coeffs[1] * dsp_data[dsp_phase_index+1]);
|
||||||
|
|
||||||
|
/* increment phase and amplitude */
|
||||||
|
fluid_phase_incr (dsp_phase, dsp_phase_incr);
|
||||||
|
dsp_phase_index = fluid_phase_index (dsp_phase);
|
||||||
|
dsp_amp += dsp_amp_incr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* break out if buffer filled */
|
||||||
|
if (dsp_i >= FLUID_BUFSIZE) break;
|
||||||
|
|
||||||
|
end_index++; /* we're now interpolating the last point */
|
||||||
|
|
||||||
|
/* interpolate within last point */
|
||||||
|
for (; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
|
||||||
|
{
|
||||||
|
coeffs = interp_coeff_linear[fluid_phase_fract_to_tablerow (dsp_phase)];
|
||||||
|
dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * dsp_data[dsp_phase_index]
|
||||||
|
+ coeffs[1] * point);
|
||||||
|
|
||||||
|
/* increment phase and amplitude */
|
||||||
|
fluid_phase_incr (dsp_phase, dsp_phase_incr);
|
||||||
|
dsp_phase_index = fluid_phase_index (dsp_phase);
|
||||||
|
dsp_amp += dsp_amp_incr; /* increment amplitude */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!looping) break; /* break out if not looping (end of sample) */
|
||||||
|
|
||||||
|
/* go back to loop start (if past */
|
||||||
|
if (dsp_phase_index > end_index)
|
||||||
|
{
|
||||||
|
fluid_phase_sub_int (dsp_phase, voice->loopend - voice->loopstart);
|
||||||
|
voice->has_looped = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* break out if filled buffer */
|
||||||
|
if (dsp_i >= FLUID_BUFSIZE) break;
|
||||||
|
|
||||||
|
end_index--; /* set end back to second to last sample point */
|
||||||
|
}
|
||||||
|
|
||||||
|
voice->phase = dsp_phase;
|
||||||
|
voice->amp = dsp_amp;
|
||||||
|
|
||||||
|
return (dsp_i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 4th order (cubic) interpolation.
|
||||||
|
* Returns number of samples processed (usually FLUID_BUFSIZE but could be
|
||||||
|
* smaller if end of sample occurs).
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fluid_dsp_float_interpolate_4th_order (fluid_voice_t *voice)
|
||||||
|
{
|
||||||
|
fluid_phase_t dsp_phase = voice->phase;
|
||||||
|
fluid_phase_t dsp_phase_incr, end_phase;
|
||||||
|
short int *dsp_data = voice->sample->data;
|
||||||
|
fluid_real_t *dsp_buf = voice->dsp_buf;
|
||||||
|
fluid_real_t dsp_amp = voice->amp;
|
||||||
|
fluid_real_t dsp_amp_incr = voice->amp_incr;
|
||||||
|
unsigned int dsp_i = 0;
|
||||||
|
unsigned int dsp_phase_index;
|
||||||
|
unsigned int start_index, end_index;
|
||||||
|
short int start_point, end_point1, end_point2;
|
||||||
|
fluid_real_t *coeffs;
|
||||||
|
int looping;
|
||||||
|
|
||||||
|
/* Convert playback "speed" floating point value to phase index/fract */
|
||||||
|
fluid_phase_set_float (dsp_phase_incr, voice->phase_incr);
|
||||||
|
|
||||||
|
/* voice is currently looping? */
|
||||||
|
looping = _SAMPLEMODE (voice) == FLUID_LOOP_DURING_RELEASE
|
||||||
|
|| (_SAMPLEMODE (voice) == FLUID_LOOP_UNTIL_RELEASE
|
||||||
|
&& voice->volenv_section < FLUID_VOICE_ENVRELEASE);
|
||||||
|
|
||||||
|
/* last index before 4th interpolation point must be specially handled */
|
||||||
|
end_index = (looping ? voice->loopend - 1 : voice->end) - 2;
|
||||||
|
|
||||||
|
if (voice->has_looped) /* set start_index and start point if looped or not */
|
||||||
|
{
|
||||||
|
start_index = voice->loopstart;
|
||||||
|
start_point = dsp_data[voice->loopend - 1]; /* last point in loop (wrap around) */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
start_index = voice->start;
|
||||||
|
start_point = dsp_data[voice->start]; /* just duplicate the point */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get points off the end (loop start if looping, duplicate point if end) */
|
||||||
|
if (looping)
|
||||||
|
{
|
||||||
|
end_point1 = dsp_data[voice->loopstart];
|
||||||
|
end_point2 = dsp_data[voice->loopstart + 1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
end_point1 = dsp_data[voice->end];
|
||||||
|
end_point2 = end_point1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
dsp_phase_index = fluid_phase_index (dsp_phase);
|
||||||
|
|
||||||
|
/* interpolate first sample point (start or loop start) if needed */
|
||||||
|
for ( ; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
|
||||||
|
{
|
||||||
|
coeffs = interp_coeff[fluid_phase_fract_to_tablerow (dsp_phase)];
|
||||||
|
dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * start_point
|
||||||
|
+ coeffs[1] * dsp_data[dsp_phase_index]
|
||||||
|
+ coeffs[2] * dsp_data[dsp_phase_index+1]
|
||||||
|
+ coeffs[3] * dsp_data[dsp_phase_index+2]);
|
||||||
|
|
||||||
|
/* increment phase and amplitude */
|
||||||
|
fluid_phase_incr (dsp_phase, dsp_phase_incr);
|
||||||
|
dsp_phase_index = fluid_phase_index (dsp_phase);
|
||||||
|
dsp_amp += dsp_amp_incr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* interpolate the sequence of sample points */
|
||||||
|
for ( ; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++)
|
||||||
|
{
|
||||||
|
coeffs = interp_coeff[fluid_phase_fract_to_tablerow (dsp_phase)];
|
||||||
|
dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * dsp_data[dsp_phase_index-1]
|
||||||
|
+ coeffs[1] * dsp_data[dsp_phase_index]
|
||||||
|
+ coeffs[2] * dsp_data[dsp_phase_index+1]
|
||||||
|
+ coeffs[3] * dsp_data[dsp_phase_index+2]);
|
||||||
|
|
||||||
|
/* increment phase and amplitude */
|
||||||
|
fluid_phase_incr (dsp_phase, dsp_phase_incr);
|
||||||
|
dsp_phase_index = fluid_phase_index (dsp_phase);
|
||||||
|
dsp_amp += dsp_amp_incr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* break out if buffer filled */
|
||||||
|
if (dsp_i >= FLUID_BUFSIZE) break;
|
||||||
|
|
||||||
|
end_index++; /* we're now interpolating the 2nd to last point */
|
||||||
|
|
||||||
|
/* interpolate within 2nd to last point */
|
||||||
|
for (; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
|
||||||
|
{
|
||||||
|
coeffs = interp_coeff[fluid_phase_fract_to_tablerow (dsp_phase)];
|
||||||
|
dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * dsp_data[dsp_phase_index-1]
|
||||||
|
+ coeffs[1] * dsp_data[dsp_phase_index]
|
||||||
|
+ coeffs[2] * dsp_data[dsp_phase_index+1]
|
||||||
|
+ coeffs[3] * end_point1);
|
||||||
|
|
||||||
|
/* increment phase and amplitude */
|
||||||
|
fluid_phase_incr (dsp_phase, dsp_phase_incr);
|
||||||
|
dsp_phase_index = fluid_phase_index (dsp_phase);
|
||||||
|
dsp_amp += dsp_amp_incr;
|
||||||
|
}
|
||||||
|
|
||||||
|
end_index++; /* we're now interpolating the last point */
|
||||||
|
|
||||||
|
/* interpolate within the last point */
|
||||||
|
for (; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
|
||||||
|
{
|
||||||
|
coeffs = interp_coeff[fluid_phase_fract_to_tablerow (dsp_phase)];
|
||||||
|
dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * dsp_data[dsp_phase_index-1]
|
||||||
|
+ coeffs[1] * dsp_data[dsp_phase_index]
|
||||||
|
+ coeffs[2] * end_point1
|
||||||
|
+ coeffs[3] * end_point2);
|
||||||
|
|
||||||
|
/* increment phase and amplitude */
|
||||||
|
fluid_phase_incr (dsp_phase, dsp_phase_incr);
|
||||||
|
dsp_phase_index = fluid_phase_index (dsp_phase);
|
||||||
|
dsp_amp += dsp_amp_incr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!looping) break; /* break out if not looping (end of sample) */
|
||||||
|
|
||||||
|
/* go back to loop start */
|
||||||
|
if (dsp_phase_index > end_index)
|
||||||
|
{
|
||||||
|
fluid_phase_sub_int (dsp_phase, voice->loopend - voice->loopstart);
|
||||||
|
|
||||||
|
if (!voice->has_looped)
|
||||||
|
{
|
||||||
|
voice->has_looped = 1;
|
||||||
|
start_index = voice->loopstart;
|
||||||
|
start_point = dsp_data[voice->loopend - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* break out if filled buffer */
|
||||||
|
if (dsp_i >= FLUID_BUFSIZE) break;
|
||||||
|
|
||||||
|
end_index -= 2; /* set end back to third to last sample point */
|
||||||
|
}
|
||||||
|
|
||||||
|
voice->phase = dsp_phase;
|
||||||
|
voice->amp = dsp_amp;
|
||||||
|
|
||||||
|
return (dsp_i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 7th order interpolation.
|
||||||
|
* Returns number of samples processed (usually FLUID_BUFSIZE but could be
|
||||||
|
* smaller if end of sample occurs).
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fluid_dsp_float_interpolate_7th_order (fluid_voice_t *voice)
|
||||||
|
{
|
||||||
|
fluid_phase_t dsp_phase = voice->phase;
|
||||||
|
fluid_phase_t dsp_phase_incr, end_phase;
|
||||||
|
short int *dsp_data = voice->sample->data;
|
||||||
|
fluid_real_t *dsp_buf = voice->dsp_buf;
|
||||||
|
fluid_real_t dsp_amp = voice->amp;
|
||||||
|
fluid_real_t dsp_amp_incr = voice->amp_incr;
|
||||||
|
unsigned int dsp_i = 0;
|
||||||
|
unsigned int dsp_phase_index;
|
||||||
|
unsigned int start_index, end_index;
|
||||||
|
short int start_points[3];
|
||||||
|
short int end_points[3];
|
||||||
|
fluid_real_t *coeffs;
|
||||||
|
int looping;
|
||||||
|
|
||||||
|
/* Convert playback "speed" floating point value to phase index/fract */
|
||||||
|
fluid_phase_set_float (dsp_phase_incr, voice->phase_incr);
|
||||||
|
|
||||||
|
/* add 1/2 sample to dsp_phase since 7th order interpolation is centered on
|
||||||
|
* the 4th sample point */
|
||||||
|
fluid_phase_incr (dsp_phase, (fluid_phase_t)0x80000000);
|
||||||
|
|
||||||
|
/* voice is currently looping? */
|
||||||
|
looping = _SAMPLEMODE (voice) == FLUID_LOOP_DURING_RELEASE
|
||||||
|
|| (_SAMPLEMODE (voice) == FLUID_LOOP_UNTIL_RELEASE
|
||||||
|
&& voice->volenv_section < FLUID_VOICE_ENVRELEASE);
|
||||||
|
|
||||||
|
/* last index before 7th interpolation point must be specially handled */
|
||||||
|
end_index = (looping ? voice->loopend - 1 : voice->end) - 3;
|
||||||
|
|
||||||
|
if (voice->has_looped) /* set start_index and start point if looped or not */
|
||||||
|
{
|
||||||
|
start_index = voice->loopstart;
|
||||||
|
start_points[0] = dsp_data[voice->loopend - 1];
|
||||||
|
start_points[1] = dsp_data[voice->loopend - 2];
|
||||||
|
start_points[2] = dsp_data[voice->loopend - 3];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
start_index = voice->start;
|
||||||
|
start_points[0] = dsp_data[voice->start]; /* just duplicate the start point */
|
||||||
|
start_points[1] = start_points[0];
|
||||||
|
start_points[2] = start_points[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the 3 points off the end (loop start if looping, duplicate point if end) */
|
||||||
|
if (looping)
|
||||||
|
{
|
||||||
|
end_points[0] = dsp_data[voice->loopstart];
|
||||||
|
end_points[1] = dsp_data[voice->loopstart + 1];
|
||||||
|
end_points[2] = dsp_data[voice->loopstart + 2];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
end_points[0] = dsp_data[voice->end];
|
||||||
|
end_points[1] = end_points[0];
|
||||||
|
end_points[2] = end_points[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
dsp_phase_index = fluid_phase_index (dsp_phase);
|
||||||
|
|
||||||
|
/* interpolate first sample point (start or loop start) if needed */
|
||||||
|
for ( ; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
|
||||||
|
{
|
||||||
|
coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)];
|
||||||
|
|
||||||
|
dsp_buf[dsp_i] = dsp_amp
|
||||||
|
* (coeffs[0] * (fluid_real_t)start_points[2]
|
||||||
|
+ coeffs[1] * (fluid_real_t)start_points[1]
|
||||||
|
+ coeffs[2] * (fluid_real_t)start_points[0]
|
||||||
|
+ coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
|
||||||
|
+ coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1]
|
||||||
|
+ coeffs[5] * (fluid_real_t)dsp_data[dsp_phase_index+2]
|
||||||
|
+ coeffs[6] * (fluid_real_t)dsp_data[dsp_phase_index+3]);
|
||||||
|
|
||||||
|
/* increment phase and amplitude */
|
||||||
|
fluid_phase_incr (dsp_phase, dsp_phase_incr);
|
||||||
|
dsp_phase_index = fluid_phase_index (dsp_phase);
|
||||||
|
dsp_amp += dsp_amp_incr;
|
||||||
|
}
|
||||||
|
|
||||||
|
start_index++;
|
||||||
|
|
||||||
|
/* interpolate 2nd to first sample point (start or loop start) if needed */
|
||||||
|
for ( ; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
|
||||||
|
{
|
||||||
|
coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)];
|
||||||
|
|
||||||
|
dsp_buf[dsp_i] = dsp_amp
|
||||||
|
* (coeffs[0] * (fluid_real_t)start_points[1]
|
||||||
|
+ coeffs[1] * (fluid_real_t)start_points[0]
|
||||||
|
+ coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1]
|
||||||
|
+ coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
|
||||||
|
+ coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1]
|
||||||
|
+ coeffs[5] * (fluid_real_t)dsp_data[dsp_phase_index+2]
|
||||||
|
+ coeffs[6] * (fluid_real_t)dsp_data[dsp_phase_index+3]);
|
||||||
|
|
||||||
|
/* increment phase and amplitude */
|
||||||
|
fluid_phase_incr (dsp_phase, dsp_phase_incr);
|
||||||
|
dsp_phase_index = fluid_phase_index (dsp_phase);
|
||||||
|
dsp_amp += dsp_amp_incr;
|
||||||
|
}
|
||||||
|
|
||||||
|
start_index++;
|
||||||
|
|
||||||
|
/* interpolate 3rd to first sample point (start or loop start) if needed */
|
||||||
|
for ( ; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
|
||||||
|
{
|
||||||
|
coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)];
|
||||||
|
|
||||||
|
dsp_buf[dsp_i] = dsp_amp
|
||||||
|
* (coeffs[0] * (fluid_real_t)start_points[0]
|
||||||
|
+ coeffs[1] * (fluid_real_t)dsp_data[dsp_phase_index-2]
|
||||||
|
+ coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1]
|
||||||
|
+ coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
|
||||||
|
+ coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1]
|
||||||
|
+ coeffs[5] * (fluid_real_t)dsp_data[dsp_phase_index+2]
|
||||||
|
+ coeffs[6] * (fluid_real_t)dsp_data[dsp_phase_index+3]);
|
||||||
|
|
||||||
|
/* increment phase and amplitude */
|
||||||
|
fluid_phase_incr (dsp_phase, dsp_phase_incr);
|
||||||
|
dsp_phase_index = fluid_phase_index (dsp_phase);
|
||||||
|
dsp_amp += dsp_amp_incr;
|
||||||
|
}
|
||||||
|
|
||||||
|
start_index -= 2; /* set back to original start index */
|
||||||
|
|
||||||
|
|
||||||
|
/* interpolate the sequence of sample points */
|
||||||
|
for ( ; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++)
|
||||||
|
{
|
||||||
|
coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)];
|
||||||
|
|
||||||
|
dsp_buf[dsp_i] = dsp_amp
|
||||||
|
* (coeffs[0] * (fluid_real_t)dsp_data[dsp_phase_index-3]
|
||||||
|
+ coeffs[1] * (fluid_real_t)dsp_data[dsp_phase_index-2]
|
||||||
|
+ coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1]
|
||||||
|
+ coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
|
||||||
|
+ coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1]
|
||||||
|
+ coeffs[5] * (fluid_real_t)dsp_data[dsp_phase_index+2]
|
||||||
|
+ coeffs[6] * (fluid_real_t)dsp_data[dsp_phase_index+3]);
|
||||||
|
|
||||||
|
/* increment phase and amplitude */
|
||||||
|
fluid_phase_incr (dsp_phase, dsp_phase_incr);
|
||||||
|
dsp_phase_index = fluid_phase_index (dsp_phase);
|
||||||
|
dsp_amp += dsp_amp_incr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* break out if buffer filled */
|
||||||
|
if (dsp_i >= FLUID_BUFSIZE) break;
|
||||||
|
|
||||||
|
end_index++; /* we're now interpolating the 3rd to last point */
|
||||||
|
|
||||||
|
/* interpolate within 3rd to last point */
|
||||||
|
for (; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
|
||||||
|
{
|
||||||
|
coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)];
|
||||||
|
|
||||||
|
dsp_buf[dsp_i] = dsp_amp
|
||||||
|
* (coeffs[0] * (fluid_real_t)dsp_data[dsp_phase_index-3]
|
||||||
|
+ coeffs[1] * (fluid_real_t)dsp_data[dsp_phase_index-2]
|
||||||
|
+ coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1]
|
||||||
|
+ coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
|
||||||
|
+ coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1]
|
||||||
|
+ coeffs[5] * (fluid_real_t)dsp_data[dsp_phase_index+2]
|
||||||
|
+ coeffs[6] * (fluid_real_t)end_points[0]);
|
||||||
|
|
||||||
|
/* increment phase and amplitude */
|
||||||
|
fluid_phase_incr (dsp_phase, dsp_phase_incr);
|
||||||
|
dsp_phase_index = fluid_phase_index (dsp_phase);
|
||||||
|
dsp_amp += dsp_amp_incr;
|
||||||
|
}
|
||||||
|
|
||||||
|
end_index++; /* we're now interpolating the 2nd to last point */
|
||||||
|
|
||||||
|
/* interpolate within 2nd to last point */
|
||||||
|
for (; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
|
||||||
|
{
|
||||||
|
coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)];
|
||||||
|
|
||||||
|
dsp_buf[dsp_i] = dsp_amp
|
||||||
|
* (coeffs[0] * (fluid_real_t)dsp_data[dsp_phase_index-3]
|
||||||
|
+ coeffs[1] * (fluid_real_t)dsp_data[dsp_phase_index-2]
|
||||||
|
+ coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1]
|
||||||
|
+ coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
|
||||||
|
+ coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1]
|
||||||
|
+ coeffs[5] * (fluid_real_t)end_points[0]
|
||||||
|
+ coeffs[6] * (fluid_real_t)end_points[1]);
|
||||||
|
|
||||||
|
/* increment phase and amplitude */
|
||||||
|
fluid_phase_incr (dsp_phase, dsp_phase_incr);
|
||||||
|
dsp_phase_index = fluid_phase_index (dsp_phase);
|
||||||
|
dsp_amp += dsp_amp_incr;
|
||||||
|
}
|
||||||
|
|
||||||
|
end_index++; /* we're now interpolating the last point */
|
||||||
|
|
||||||
|
/* interpolate within last point */
|
||||||
|
for (; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++)
|
||||||
|
{
|
||||||
|
coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)];
|
||||||
|
|
||||||
|
dsp_buf[dsp_i] = dsp_amp
|
||||||
|
* (coeffs[0] * (fluid_real_t)dsp_data[dsp_phase_index-3]
|
||||||
|
+ coeffs[1] * (fluid_real_t)dsp_data[dsp_phase_index-2]
|
||||||
|
+ coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1]
|
||||||
|
+ coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index]
|
||||||
|
+ coeffs[4] * (fluid_real_t)end_points[0]
|
||||||
|
+ coeffs[5] * (fluid_real_t)end_points[1]
|
||||||
|
+ coeffs[6] * (fluid_real_t)end_points[2]);
|
||||||
|
|
||||||
|
/* increment phase and amplitude */
|
||||||
|
fluid_phase_incr (dsp_phase, dsp_phase_incr);
|
||||||
|
dsp_phase_index = fluid_phase_index (dsp_phase);
|
||||||
|
dsp_amp += dsp_amp_incr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!looping) break; /* break out if not looping (end of sample) */
|
||||||
|
|
||||||
|
/* go back to loop start */
|
||||||
|
if (dsp_phase_index > end_index)
|
||||||
|
{
|
||||||
|
fluid_phase_sub_int (dsp_phase, voice->loopend - voice->loopstart);
|
||||||
|
|
||||||
|
if (!voice->has_looped)
|
||||||
|
{
|
||||||
|
voice->has_looped = 1;
|
||||||
|
start_index = voice->loopstart;
|
||||||
|
start_points[0] = dsp_data[voice->loopend - 1];
|
||||||
|
start_points[1] = dsp_data[voice->loopend - 2];
|
||||||
|
start_points[2] = dsp_data[voice->loopend - 3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* break out if filled buffer */
|
||||||
|
if (dsp_i >= FLUID_BUFSIZE) break;
|
||||||
|
|
||||||
|
end_index -= 3; /* set end back to 4th to last sample point */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sub 1/2 sample from dsp_phase since 7th order interpolation is centered on
|
||||||
|
* the 4th sample point (correct back to real value) */
|
||||||
|
fluid_phase_decr (dsp_phase, (fluid_phase_t)0x80000000);
|
||||||
|
|
||||||
|
voice->phase = dsp_phase;
|
||||||
|
voice->amp = dsp_amp;
|
||||||
|
|
||||||
|
return (dsp_i);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/* Purpose:
|
/* Purpose:
|
||||||
* Low-level voice processing:
|
* Low-level voice processing:
|
||||||
*
|
*
|
||||||
* - interpolates (obtains values between the samples of the original waveform data)
|
* - interpolates (obtains values between the samples of the original waveform data)
|
||||||
@@ -60,7 +60,7 @@
|
|||||||
* - dsp_phase_incr: For each output sample, the position in the original
|
* - dsp_phase_incr: For each output sample, the position in the original
|
||||||
* waveform advances by dsp_phase_incr. This also has an integer
|
* waveform advances by dsp_phase_incr. This also has an integer
|
||||||
* part and a fractional part.
|
* part and a fractional part.
|
||||||
* If a sample is played at root pitch (no pitch change),
|
* If a sample is played at root pitch (no pitch change),
|
||||||
* dsp_phase_incr is integer=1 and fractional=0.
|
* dsp_phase_incr is integer=1 and fractional=0.
|
||||||
* - dsp_amp: The current amplitude envelope value.
|
* - dsp_amp: The current amplitude envelope value.
|
||||||
* - dsp_amp_incr: The changing rate of the amplitude envelope.
|
* - dsp_amp_incr: The changing rate of the amplitude envelope.
|
||||||
@@ -74,37 +74,37 @@
|
|||||||
* - dsp_centernode: delay line for the IIR filter
|
* - dsp_centernode: delay line for the IIR filter
|
||||||
* - dsp_hist1: same
|
* - dsp_hist1: same
|
||||||
* - dsp_hist2: same
|
* - dsp_hist2: same
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/* Nonoptimized DSP loop */
|
/* Nonoptimized DSP loop */
|
||||||
#warning "This code is meant for experiments only.";
|
#warning "This code is meant for experiments only.";
|
||||||
|
|
||||||
/* wave table interpolation */
|
/* wave table interpolation */
|
||||||
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) {
|
for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) {
|
||||||
|
|
||||||
dsp_coeff = &interp_coeff[fluid_phase_fract_to_tablerow(dsp_phase)];
|
dsp_coeff = &interp_coeff[fluid_phase_fract_to_tablerow(dsp_phase)];
|
||||||
dsp_phase_index = fluid_phase_index(dsp_phase);
|
dsp_phase_index = fluid_phase_index(dsp_phase);
|
||||||
dsp_sample = (dsp_amp *
|
dsp_sample = (dsp_amp *
|
||||||
(dsp_coeff->a0 * dsp_data[dsp_phase_index]
|
(dsp_coeff->a0 * dsp_data[dsp_phase_index]
|
||||||
+ dsp_coeff->a1 * dsp_data[dsp_phase_index+1]
|
+ dsp_coeff->a1 * dsp_data[dsp_phase_index+1]
|
||||||
+ dsp_coeff->a2 * dsp_data[dsp_phase_index+2]
|
+ dsp_coeff->a2 * dsp_data[dsp_phase_index+2]
|
||||||
+ dsp_coeff->a3 * dsp_data[dsp_phase_index+3]));
|
+ dsp_coeff->a3 * dsp_data[dsp_phase_index+3]));
|
||||||
|
|
||||||
/* increment phase and amplitude */
|
/* increment phase and amplitude */
|
||||||
fluid_phase_incr(dsp_phase, dsp_phase_incr);
|
fluid_phase_incr(dsp_phase, dsp_phase_incr);
|
||||||
dsp_amp += dsp_amp_incr;
|
dsp_amp += dsp_amp_incr;
|
||||||
|
|
||||||
/* filter */
|
/* filter */
|
||||||
/* The filter is implemented in Direct-II form. */
|
/* The filter is implemented in Direct-II form. */
|
||||||
dsp_centernode = dsp_sample - dsp_a1 * dsp_hist1 - dsp_a2 * dsp_hist2;
|
dsp_centernode = dsp_sample - dsp_a1 * dsp_hist1 - dsp_a2 * dsp_hist2;
|
||||||
dsp_sample = dsp_b0 * dsp_centernode + dsp_b1 * dsp_hist1 + dsp_b2 * dsp_hist2;
|
dsp_sample = dsp_b0 * dsp_centernode + dsp_b1 * dsp_hist1 + dsp_b2 * dsp_hist2;
|
||||||
dsp_hist2 = dsp_hist1;
|
dsp_hist2 = dsp_hist1;
|
||||||
dsp_hist1 = dsp_centernode;
|
dsp_hist1 = dsp_centernode;
|
||||||
|
|
||||||
/* pan */
|
/* pan */
|
||||||
dsp_left_buf[dsp_i] += voice->amp_left * dsp_sample;
|
dsp_left_buf[dsp_i] += voice->amp_left * dsp_sample;
|
||||||
dsp_right_buf[dsp_i] += voice->amp_right * dsp_sample;
|
dsp_right_buf[dsp_i] += voice->amp_right * dsp_sample;
|
||||||
|
|
||||||
/* reverb */
|
/* reverb */
|
||||||
|
|||||||
@@ -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
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
* 02111-1307, USA
|
* 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
2002 : API design by Peter Hanappe and Antoine Schmitt
|
2002 : API design by Peter Hanappe and Antoine Schmitt
|
||||||
August 2002 : Implementation by Antoine Schmitt as@gratin.org
|
August 2002 : Implementation by Antoine Schmitt as@gratin.org
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
Oct4.2002 : AS : corrected bug in heap allocation, that caused a crash during sequencer free.
|
Oct4.2002 : AS : corrected bug in heap allocation, that caused a crash during sequencer free.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "fluid_event_priv.h"
|
#include "fluid_event_priv.h"
|
||||||
#include "fluidsynth_priv.h"
|
#include "fluidsynth_priv.h"
|
||||||
|
|
||||||
@@ -38,11 +38,15 @@
|
|||||||
|
|
||||||
/* Event alloc/free */
|
/* Event alloc/free */
|
||||||
|
|
||||||
fluid_event_t*
|
/**
|
||||||
|
* Create a new sequencer event structure.
|
||||||
|
* @return New sequencer event structure or NULL if out of memory
|
||||||
|
*/
|
||||||
|
fluid_event_t*
|
||||||
new_fluid_event()
|
new_fluid_event()
|
||||||
{
|
{
|
||||||
fluid_event_t* evt;
|
fluid_event_t* evt;
|
||||||
|
|
||||||
evt = FLUID_NEW(fluid_event_t);
|
evt = FLUID_NEW(fluid_event_t);
|
||||||
if (evt == NULL) {
|
if (evt == NULL) {
|
||||||
fluid_log(FLUID_PANIC, "event: Out of memory\n");
|
fluid_log(FLUID_PANIC, "event: Out of memory\n");
|
||||||
@@ -50,46 +54,69 @@ new_fluid_event()
|
|||||||
}
|
}
|
||||||
|
|
||||||
FLUID_MEMSET(evt, 0, sizeof(fluid_event_t));
|
FLUID_MEMSET(evt, 0, sizeof(fluid_event_t));
|
||||||
|
|
||||||
// by default, no type
|
// by default, no type
|
||||||
evt->dest = -1;
|
evt->dest = -1;
|
||||||
evt->src = -1;
|
evt->src = -1;
|
||||||
evt->type = -1;
|
evt->type = -1;
|
||||||
|
|
||||||
return(evt);
|
return(evt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
/**
|
||||||
|
* Delete a sequencer event structure.
|
||||||
|
* @param evt Sequencer event structure created by new_fluid_event().
|
||||||
|
*/
|
||||||
|
void
|
||||||
delete_fluid_event(fluid_event_t* evt)
|
delete_fluid_event(fluid_event_t* evt)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (evt == NULL) {
|
if (evt == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FLUID_FREE(evt);
|
FLUID_FREE(evt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initializing events */
|
/**
|
||||||
|
* Set the time field of a sequencer event.
|
||||||
|
* @internal
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @param time Time value to assign
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
fluid_event_set_time(fluid_event_t* evt, unsigned int time)
|
fluid_event_set_time(fluid_event_t* evt, unsigned int time)
|
||||||
{
|
{
|
||||||
evt->time = time;
|
evt->time = time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set source of a sequencer event (DOCME).
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @param src DOCME
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
fluid_event_set_source(fluid_event_t* evt, short src)
|
fluid_event_set_source(fluid_event_t* evt, short src)
|
||||||
{
|
{
|
||||||
evt->src = src;
|
evt->src = src;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set destination of a sequencer event (DOCME).
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @param dest DOCME
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
fluid_event_set_dest(fluid_event_t* evt, short dest)
|
fluid_event_set_dest(fluid_event_t* evt, short dest)
|
||||||
{
|
{
|
||||||
evt->dest = dest;
|
evt->dest = dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Timer events */
|
/**
|
||||||
|
* Set a sequencer event to be a timer event.
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @param data DOCME
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
fluid_event_timer(fluid_event_t* evt, void* data)
|
fluid_event_timer(fluid_event_t* evt, void* data)
|
||||||
{
|
{
|
||||||
@@ -97,8 +124,13 @@ fluid_event_timer(fluid_event_t* evt, void* data)
|
|||||||
evt->data = data;
|
evt->data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
/* Note events */
|
* Set a sequencer event to be a note on event.
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @param channel MIDI channel number
|
||||||
|
* @param key MIDI note number (0-127)
|
||||||
|
* @param vel MIDI velocity value (0-127)
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
fluid_event_noteon(fluid_event_t* evt, int channel, short key, short vel)
|
fluid_event_noteon(fluid_event_t* evt, int channel, short key, short vel)
|
||||||
{
|
{
|
||||||
@@ -108,6 +140,12 @@ fluid_event_noteon(fluid_event_t* evt, int channel, short key, short vel)
|
|||||||
evt->vel = vel;
|
evt->vel = vel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a sequencer event to be a note off event.
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @param channel MIDI channel number
|
||||||
|
* @param key MIDI note number (0-127)
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
fluid_event_noteoff(fluid_event_t* evt, int channel, short key)
|
fluid_event_noteoff(fluid_event_t* evt, int channel, short key)
|
||||||
{
|
{
|
||||||
@@ -116,6 +154,14 @@ fluid_event_noteoff(fluid_event_t* evt, int channel, short key)
|
|||||||
evt->key = key;
|
evt->key = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a sequencer event to be a note duration event.
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @param channel MIDI channel number
|
||||||
|
* @param key MIDI note number (0-127)
|
||||||
|
* @param vel MIDI velocity value (0-127)
|
||||||
|
* @param duration Duration of note (DOCME units?)
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
fluid_event_note(fluid_event_t* evt, int channel, short key, short vel, unsigned int duration)
|
fluid_event_note(fluid_event_t* evt, int channel, short key, short vel, unsigned int duration)
|
||||||
{
|
{
|
||||||
@@ -126,6 +172,11 @@ fluid_event_note(fluid_event_t* evt, int channel, short key, short vel, unsigned
|
|||||||
evt->duration = duration;
|
evt->duration = duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a sequencer event to be an all sounds off event.
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @param channel MIDI channel number
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
fluid_event_all_sounds_off(fluid_event_t* evt, int channel)
|
fluid_event_all_sounds_off(fluid_event_t* evt, int channel)
|
||||||
{
|
{
|
||||||
@@ -133,6 +184,11 @@ fluid_event_all_sounds_off(fluid_event_t* evt, int channel)
|
|||||||
evt->channel = channel;
|
evt->channel = channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a sequencer event to be a all notes off event.
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @param channel MIDI channel number
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
fluid_event_all_notes_off(fluid_event_t* evt, int channel)
|
fluid_event_all_notes_off(fluid_event_t* evt, int channel)
|
||||||
{
|
{
|
||||||
@@ -140,6 +196,12 @@ fluid_event_all_notes_off(fluid_event_t* evt, int channel)
|
|||||||
evt->channel = channel;
|
evt->channel = channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a sequencer event to be a bank select event.
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @param channel MIDI channel number
|
||||||
|
* @param bank_num MIDI bank number (0-16383)
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
fluid_event_bank_select(fluid_event_t* evt, int channel, short bank_num)
|
fluid_event_bank_select(fluid_event_t* evt, int channel, short bank_num)
|
||||||
{
|
{
|
||||||
@@ -148,6 +210,12 @@ fluid_event_bank_select(fluid_event_t* evt, int channel, short bank_num)
|
|||||||
evt->control = bank_num;
|
evt->control = bank_num;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a sequencer event to be a program change event.
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @param channel MIDI channel number
|
||||||
|
* @param val MIDI program number (0-127)
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
fluid_event_program_change(fluid_event_t* evt, int channel, short val)
|
fluid_event_program_change(fluid_event_t* evt, int channel, short val)
|
||||||
{
|
{
|
||||||
@@ -156,6 +224,14 @@ fluid_event_program_change(fluid_event_t* evt, int channel, short val)
|
|||||||
evt->value = val;
|
evt->value = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a sequencer event to be a program select event.
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @param channel MIDI channel number
|
||||||
|
* @param sfont_id SoundFont ID number
|
||||||
|
* @param bank_num MIDI bank number (0-16383)
|
||||||
|
* @param preset_num MIDI preset number (0-127)
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
fluid_event_program_select(fluid_event_t* evt, int channel,
|
fluid_event_program_select(fluid_event_t* evt, int channel,
|
||||||
unsigned int sfont_id, short bank_num, short preset_num)
|
unsigned int sfont_id, short bank_num, short preset_num)
|
||||||
@@ -167,6 +243,12 @@ fluid_event_program_select(fluid_event_t* evt, int channel,
|
|||||||
evt->control = bank_num;
|
evt->control = bank_num;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a sequencer event to be an any control change event.
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @param channel MIDI channel number
|
||||||
|
* DOCME
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
fluid_event_any_control_change(fluid_event_t* evt, int channel)
|
fluid_event_any_control_change(fluid_event_t* evt, int channel)
|
||||||
{
|
{
|
||||||
@@ -174,6 +256,12 @@ fluid_event_any_control_change(fluid_event_t* evt, int channel)
|
|||||||
evt->channel = channel;
|
evt->channel = channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a sequencer event to be a pitch bend event.
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @param channel MIDI channel number
|
||||||
|
* @param pitch MIDI pitch bend value (0-16383, 8192 = no bend)
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
fluid_event_pitch_bend(fluid_event_t* evt, int channel, int pitch)
|
fluid_event_pitch_bend(fluid_event_t* evt, int channel, int pitch)
|
||||||
{
|
{
|
||||||
@@ -184,6 +272,12 @@ fluid_event_pitch_bend(fluid_event_t* evt, int channel, int pitch)
|
|||||||
evt->pitch = pitch;
|
evt->pitch = pitch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a sequencer event to be a pitch wheel sensitivity event.
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @param channel MIDI channel number
|
||||||
|
* @param value MIDI pitch wheel sensitivity value (DOCME units?)
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
fluid_event_pitch_wheelsens(fluid_event_t* evt, int channel, short value)
|
fluid_event_pitch_wheelsens(fluid_event_t* evt, int channel, short value)
|
||||||
{
|
{
|
||||||
@@ -192,6 +286,12 @@ fluid_event_pitch_wheelsens(fluid_event_t* evt, int channel, short value)
|
|||||||
evt->value = value;
|
evt->value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a sequencer event to be a modulation event.
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @param channel MIDI channel number
|
||||||
|
* @param val MIDI modulation value (0-127)
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
fluid_event_modulation(fluid_event_t* evt, int channel, short val)
|
fluid_event_modulation(fluid_event_t* evt, int channel, short val)
|
||||||
{
|
{
|
||||||
@@ -202,6 +302,12 @@ fluid_event_modulation(fluid_event_t* evt, int channel, short val)
|
|||||||
evt->value = val;
|
evt->value = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a sequencer event to be a MIDI sustain event.
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @param channel MIDI channel number
|
||||||
|
* @param val MIDI sustain value (0-127)
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
fluid_event_sustain(fluid_event_t* evt, int channel, short val)
|
fluid_event_sustain(fluid_event_t* evt, int channel, short val)
|
||||||
{
|
{
|
||||||
@@ -212,6 +318,13 @@ fluid_event_sustain(fluid_event_t* evt, int channel, short val)
|
|||||||
evt->value = val;
|
evt->value = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a sequencer event to be a MIDI control change event.
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @param channel MIDI channel number
|
||||||
|
* @param control MIDI control number (0-127)
|
||||||
|
* @param val MIDI control value (0-16383 DOCME is that true?)
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
fluid_event_control_change(fluid_event_t* evt, int channel, short control, short val)
|
fluid_event_control_change(fluid_event_t* evt, int channel, short control, short val)
|
||||||
{
|
{
|
||||||
@@ -221,6 +334,12 @@ fluid_event_control_change(fluid_event_t* evt, int channel, short control, short
|
|||||||
evt->value = val;
|
evt->value = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a sequencer event to be a stereo pan event.
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @param channel MIDI channel number
|
||||||
|
* @param val MIDI panning value (0-127, 0=left, 64 = middle, 127 = right)
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
fluid_event_pan(fluid_event_t* evt, int channel, short val)
|
fluid_event_pan(fluid_event_t* evt, int channel, short val)
|
||||||
{
|
{
|
||||||
@@ -231,6 +350,12 @@ fluid_event_pan(fluid_event_t* evt, int channel, short val)
|
|||||||
evt->value = val;
|
evt->value = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a sequencer event to be a volume event.
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @param channel MIDI channel number
|
||||||
|
* @param val Volume value (0-127)
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
fluid_event_volume(fluid_event_t* evt, int channel, short val)
|
fluid_event_volume(fluid_event_t* evt, int channel, short val)
|
||||||
{
|
{
|
||||||
@@ -241,6 +366,12 @@ fluid_event_volume(fluid_event_t* evt, int channel, short val)
|
|||||||
evt->value = val;
|
evt->value = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a sequencer event to be a reverb send event.
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @param channel MIDI channel number
|
||||||
|
* @param val Reverb amount (0-127)
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
fluid_event_reverb_send(fluid_event_t* evt, int channel, short val)
|
fluid_event_reverb_send(fluid_event_t* evt, int channel, short val)
|
||||||
{
|
{
|
||||||
@@ -251,6 +382,12 @@ fluid_event_reverb_send(fluid_event_t* evt, int channel, short val)
|
|||||||
evt->value = val;
|
evt->value = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a sequencer event to be a chorus send event.
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @param channel MIDI channel number
|
||||||
|
* @param val Chorus amount (0-127)
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
fluid_event_chorus_send(fluid_event_t* evt, int channel, short val)
|
fluid_event_chorus_send(fluid_event_t* evt, int channel, short val)
|
||||||
{
|
{
|
||||||
@@ -261,76 +398,179 @@ fluid_event_chorus_send(fluid_event_t* evt, int channel, short val)
|
|||||||
evt->value = val;
|
evt->value = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Accessing event data */
|
|
||||||
|
/*
|
||||||
|
* Accessing event data
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the event type (#fluid_seq_event_type) field from a sequencer event structure.
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @return Event type (#fluid_seq_event_type).
|
||||||
|
*/
|
||||||
int fluid_event_get_type(fluid_event_t* evt)
|
int fluid_event_get_type(fluid_event_t* evt)
|
||||||
{
|
{
|
||||||
return evt->type;
|
return evt->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the time field from a sequencer event structure.
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @return Time value (DOCME units?)
|
||||||
|
*/
|
||||||
unsigned int fluid_event_get_time(fluid_event_t* evt)
|
unsigned int fluid_event_get_time(fluid_event_t* evt)
|
||||||
{
|
{
|
||||||
return evt->time;
|
return evt->time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the source field from a sequencer event structure.
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @return DOCME
|
||||||
|
*/
|
||||||
short fluid_event_get_source(fluid_event_t* evt)
|
short fluid_event_get_source(fluid_event_t* evt)
|
||||||
{
|
{
|
||||||
return evt->src;
|
return evt->src;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the dest field from a sequencer event structure.
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @return DOCME
|
||||||
|
*/
|
||||||
short fluid_event_get_dest(fluid_event_t* evt)
|
short fluid_event_get_dest(fluid_event_t* evt)
|
||||||
{
|
{
|
||||||
return evt->dest;
|
return evt->dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the MIDI channel field from a sequencer event structure.
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @return MIDI channel number (DOCME 0-15 or more?)
|
||||||
|
*/
|
||||||
int fluid_event_get_channel(fluid_event_t* evt)
|
int fluid_event_get_channel(fluid_event_t* evt)
|
||||||
{
|
{
|
||||||
return evt->channel;
|
return evt->channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the MIDI note field from a sequencer event structure.
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @return MIDI note number (0-127)
|
||||||
|
*/
|
||||||
short fluid_event_get_key(fluid_event_t* evt)
|
short fluid_event_get_key(fluid_event_t* evt)
|
||||||
{
|
{
|
||||||
return evt->key;
|
return evt->key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the MIDI velocity field from a sequencer event structure.
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @return MIDI velocity value (0-127)
|
||||||
|
*/
|
||||||
short fluid_event_get_velocity(fluid_event_t* evt)
|
short fluid_event_get_velocity(fluid_event_t* evt)
|
||||||
|
|
||||||
{
|
{
|
||||||
return evt->vel;
|
return evt->vel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the MIDI control number field from a sequencer event structure.
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @return MIDI control number (0-127)
|
||||||
|
*/
|
||||||
short fluid_event_get_control(fluid_event_t* evt)
|
short fluid_event_get_control(fluid_event_t* evt)
|
||||||
{
|
{
|
||||||
return evt->control;
|
return evt->control;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value field from a sequencer event structure.
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @return Value field of event.
|
||||||
|
*
|
||||||
|
* The Value field is used by the following event types:
|
||||||
|
* #FLUID_SEQ_PROGRAMCHANGE, #FLUID_SEQ_PROGRAMSELECT (preset_num),
|
||||||
|
* #FLUID_SEQ_PITCHWHHELSENS, #FLUID_SEQ_MODULATION, #FLUID_SEQ_SUSTAIN,
|
||||||
|
* #FLUID_SEQ_CONTROLCHANGE, #FLUID_SEQ_PAN, #FLUID_SEQ_VOLUME,
|
||||||
|
* #FLUID_SEQ_REVERBSEND, #FLUID_SEQ_CHORUSSEND.
|
||||||
|
*/
|
||||||
short fluid_event_get_value(fluid_event_t* evt)
|
short fluid_event_get_value(fluid_event_t* evt)
|
||||||
{
|
{
|
||||||
return evt->value;
|
return evt->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the data field from a sequencer event structure.
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @return Data field of event.
|
||||||
|
*
|
||||||
|
* Used by the #FLUID_SEQ_TIMER event type.
|
||||||
|
*/
|
||||||
void* fluid_event_get_data(fluid_event_t* evt)
|
void* fluid_event_get_data(fluid_event_t* evt)
|
||||||
{
|
{
|
||||||
return evt->data;
|
return evt->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the duration field from a sequencer event structure.
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @return Note duration value (DOCME units?)
|
||||||
|
*
|
||||||
|
* Used by the #FLUID_SEQ_NOTE event type.
|
||||||
|
*/
|
||||||
unsigned int fluid_event_get_duration(fluid_event_t* evt)
|
unsigned int fluid_event_get_duration(fluid_event_t* evt)
|
||||||
{
|
{
|
||||||
return evt->duration;
|
return evt->duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the MIDI bank field from a sequencer event structure.
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @return MIDI bank number (0-16383)
|
||||||
|
*
|
||||||
|
* Used by the #FLUID_SEQ_BANKSELECT and #FLUID_SEQ_PROGRAMSELECT
|
||||||
|
* event types.
|
||||||
|
*/
|
||||||
short fluid_event_get_bank(fluid_event_t* evt)
|
short fluid_event_get_bank(fluid_event_t* evt)
|
||||||
{
|
{
|
||||||
return evt->control;
|
return evt->control;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the pitch field from a sequencer event structure.
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @return MIDI pitch bend pitch value (0-16383, 8192 = no bend)
|
||||||
|
*
|
||||||
|
* Used by the #FLUID_SEQ_PITCHBEND event type.
|
||||||
|
*/
|
||||||
int fluid_event_get_pitch(fluid_event_t* evt)
|
int fluid_event_get_pitch(fluid_event_t* evt)
|
||||||
{
|
{
|
||||||
return evt->pitch;
|
return evt->pitch;
|
||||||
}
|
}
|
||||||
short
|
|
||||||
|
/**
|
||||||
|
* Get the MIDI program field from a sequencer event structure.
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @return MIDI program number (0-127)
|
||||||
|
*
|
||||||
|
* Used by the #FLUID_SEQ_PROGRAMCHANGE and #FLUID_SEQ_PROGRAMSELECT
|
||||||
|
* event types.
|
||||||
|
*/
|
||||||
|
short
|
||||||
fluid_event_get_program(fluid_event_t* evt)
|
fluid_event_get_program(fluid_event_t* evt)
|
||||||
{
|
{
|
||||||
return evt->value;
|
return evt->value;
|
||||||
}
|
}
|
||||||
unsigned int
|
|
||||||
|
/**
|
||||||
|
* Get the SoundFont ID field from a sequencer event structure.
|
||||||
|
* @param evt Sequencer event structure
|
||||||
|
* @return SoundFont identifier value.
|
||||||
|
*
|
||||||
|
* Used by the #FLUID_SEQ_PROGRAMSELECT event type.
|
||||||
|
*/
|
||||||
|
unsigned int
|
||||||
fluid_event_get_sfont_id(fluid_event_t* evt)
|
fluid_event_get_sfont_id(fluid_event_t* evt)
|
||||||
{
|
{
|
||||||
return evt->duration;
|
return evt->duration;
|
||||||
@@ -378,21 +618,21 @@ _fluid_evt_heap_init(int nbEvents)
|
|||||||
int i;
|
int i;
|
||||||
fluid_evt_heap_t* heap;
|
fluid_evt_heap_t* heap;
|
||||||
int siz = 2*sizeof(fluid_evt_entry *) + sizeof(fluid_evt_entry)*nbEvents;
|
int siz = 2*sizeof(fluid_evt_entry *) + sizeof(fluid_evt_entry)*nbEvents;
|
||||||
|
|
||||||
heap = (fluid_evt_heap_t *)FLUID_MALLOC(siz);
|
heap = (fluid_evt_heap_t *)FLUID_MALLOC(siz);
|
||||||
if (heap == NULL) {
|
if (heap == NULL) {
|
||||||
fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
|
fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
FLUID_MEMSET(heap, 0, siz);
|
FLUID_MEMSET(heap, 0, siz);
|
||||||
|
|
||||||
/* link all heap events */
|
/* link all heap events */
|
||||||
{
|
{
|
||||||
fluid_evt_entry *tmp = &(heap->pool);
|
fluid_evt_entry *tmp = &(heap->pool);
|
||||||
for (i = 0 ; i < nbEvents - 1 ; i++)
|
for (i = 0 ; i < nbEvents - 1 ; i++)
|
||||||
tmp[i].next = &(tmp[i+1]);
|
tmp[i].next = &(tmp[i+1]);
|
||||||
tmp[nbEvents-1].next = NULL;
|
tmp[nbEvents-1].next = NULL;
|
||||||
|
|
||||||
/* set head & tail */
|
/* set head & tail */
|
||||||
heap->tail = &(tmp[nbEvents-1]);
|
heap->tail = &(tmp[nbEvents-1]);
|
||||||
heap->head = &(heap->pool);
|
heap->head = &(heap->pool);
|
||||||
@@ -422,7 +662,7 @@ _fluid_evt_heap_free(fluid_evt_heap_t* heap)
|
|||||||
fluid_mutex_destroy(heap->mutex);
|
fluid_mutex_destroy(heap->mutex);
|
||||||
|
|
||||||
FLUID_FREE(heap);
|
FLUID_FREE(heap);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
FLUID_FREE(heap);
|
FLUID_FREE(heap);
|
||||||
#endif
|
#endif
|
||||||
@@ -461,12 +701,12 @@ _fluid_seq_heap_get_free(fluid_evt_heap_t* heap)
|
|||||||
#else
|
#else
|
||||||
fluid_evt_entry* evt;
|
fluid_evt_entry* evt;
|
||||||
if (heap->head == NULL) return NULL;
|
if (heap->head == NULL) return NULL;
|
||||||
|
|
||||||
/* take from head of the heap */
|
/* take from head of the heap */
|
||||||
/* critical - should threadlock ? */
|
/* critical - should threadlock ? */
|
||||||
evt = heap->head;
|
evt = heap->head;
|
||||||
heap->head = heap->head->next;
|
heap->head = heap->head->next;
|
||||||
|
|
||||||
return evt;
|
return evt;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,14 +11,14 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
* 02111-1307, USA
|
* 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef _FLUID_EVENT_PRIV_H
|
#ifndef _FLUID_EVENT_PRIV_H
|
||||||
#define _FLUID_EVENT_PRIV_H
|
#define _FLUID_EVENT_PRIV_H
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -89,11 +89,12 @@ fluid_gen_info_t fluid_gen_info[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* fluid_gen_set_default_values
|
/**
|
||||||
*
|
* Set an array of generators to their default values.
|
||||||
* Set an array of generators to their initial value
|
* @param gen Array of generators (should be #GEN_LAST in size).
|
||||||
|
* @return Always returns 0
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
fluid_gen_set_default_values(fluid_gen_t* gen)
|
fluid_gen_set_default_values(fluid_gen_t* gen)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -111,9 +112,9 @@ fluid_gen_set_default_values(fluid_gen_t* gen)
|
|||||||
|
|
||||||
/* fluid_gen_init
|
/* fluid_gen_init
|
||||||
*
|
*
|
||||||
* Set an array of generators to their initial value
|
* Set an array of generators to their initial value
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
fluid_gen_init(fluid_gen_t* gen, fluid_channel_t* channel)
|
fluid_gen_init(fluid_gen_t* gen, fluid_channel_t* channel)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -135,8 +136,8 @@ fluid_gen_init(fluid_gen_t* gen, fluid_channel_t* channel)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fluid_real_t fluid_gen_scale(int gen, float value)
|
fluid_real_t fluid_gen_scale(int gen, float value)
|
||||||
{
|
{
|
||||||
return (fluid_gen_info[gen].min
|
return (fluid_gen_info[gen].min
|
||||||
+ value * (fluid_gen_info[gen].max - fluid_gen_info[gen].min));
|
+ value * (fluid_gen_info[gen].max - fluid_gen_info[gen].min));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
|||||||
@@ -21,10 +21,10 @@
|
|||||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||||
* file for a list of people on the GLib Team. See the ChangeLog
|
* file for a list of people on the GLib Team. See the ChangeLog
|
||||||
* files for a list of changes. These files are distributed with
|
* files for a list of changes. These files are distributed with
|
||||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MT safe
|
* MT safe
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ struct _fluid_hashtable_t {
|
|||||||
if ((3 * hash_table->size <= hash_table->nnodes) \
|
if ((3 * hash_table->size <= hash_table->nnodes) \
|
||||||
&& (hash_table->size < HASH_TABLE_MAX_SIZE)) { \
|
&& (hash_table->size < HASH_TABLE_MAX_SIZE)) { \
|
||||||
fluid_hashtable_resize(hash_table); \
|
fluid_hashtable_resize(hash_table); \
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fluid_hashtable_resize(fluid_hashtable_t *hash_table);
|
static void fluid_hashtable_resize(fluid_hashtable_t *hash_table);
|
||||||
static fluid_hashnode_t** fluid_hashtable_lookup_node(fluid_hashtable_t *hash_table, char* key);
|
static fluid_hashnode_t** fluid_hashtable_lookup_node(fluid_hashtable_t *hash_table, char* key);
|
||||||
@@ -69,7 +69,7 @@ static fluid_hashnode_t** fluid_hashtable_lookup_node(fluid_hashtable_t *hash_ta
|
|||||||
* new_fluid_hashtable:
|
* new_fluid_hashtable:
|
||||||
*
|
*
|
||||||
* Creates a new #fluid_hashtable_t.
|
* Creates a new #fluid_hashtable_t.
|
||||||
*
|
*
|
||||||
* Return value: a new #fluid_hashtable_t.
|
* Return value: a new #fluid_hashtable_t.
|
||||||
**/
|
**/
|
||||||
fluid_hashtable_t*
|
fluid_hashtable_t*
|
||||||
@@ -94,22 +94,22 @@ new_fluid_hashtable(fluid_hash_delete_t del)
|
|||||||
/**
|
/**
|
||||||
* delete_fluid_hashtable:
|
* delete_fluid_hashtable:
|
||||||
* @hash_table: a #fluid_hashtable_t.
|
* @hash_table: a #fluid_hashtable_t.
|
||||||
*
|
*
|
||||||
* Destroys the #fluid_hashtable_t. If keys and/or values are dynamically
|
* Destroys the #fluid_hashtable_t. If keys and/or values are dynamically
|
||||||
* allocated, you should either free them first or create the #fluid_hashtable_t
|
* allocated, you should either free them first or create the #fluid_hashtable_t
|
||||||
* using fluid_hashtable_new_full(). In the latter case the destroy functions
|
* using fluid_hashtable_new_full(). In the latter case the destroy functions
|
||||||
* you supplied will be called on all keys and values before destroying
|
* you supplied will be called on all keys and values before destroying
|
||||||
* the #fluid_hashtable_t.
|
* the #fluid_hashtable_t.
|
||||||
**/
|
**/
|
||||||
void
|
void
|
||||||
delete_fluid_hashtable(fluid_hashtable_t *hash_table)
|
delete_fluid_hashtable(fluid_hashtable_t *hash_table)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
if (hash_table == NULL) {
|
if (hash_table == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < hash_table->size; i++) {
|
for (i = 0; i < hash_table->size; i++) {
|
||||||
delete_fluid_hashnodes(hash_table->nodes[i], hash_table->del);
|
delete_fluid_hashnodes(hash_table->nodes[i], hash_table->del);
|
||||||
}
|
}
|
||||||
@@ -123,13 +123,13 @@ static /*inline*/ fluid_hashnode_t**
|
|||||||
fluid_hashtable_lookup_node (fluid_hashtable_t* hash_table, char* key)
|
fluid_hashtable_lookup_node (fluid_hashtable_t* hash_table, char* key)
|
||||||
{
|
{
|
||||||
fluid_hashnode_t **node;
|
fluid_hashnode_t **node;
|
||||||
|
|
||||||
node = &hash_table->nodes[fluid_str_hash(key) % hash_table->size];
|
node = &hash_table->nodes[fluid_str_hash(key) % hash_table->size];
|
||||||
|
|
||||||
while (*node && (FLUID_STRCMP((*node)->key, key) != 0)) {
|
while (*node && (FLUID_STRCMP((*node)->key, key) != 0)) {
|
||||||
node = &(*node)->next;
|
node = &(*node)->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,16 +137,16 @@ fluid_hashtable_lookup_node (fluid_hashtable_t* hash_table, char* key)
|
|||||||
* fluid_hashtable_lookup:
|
* fluid_hashtable_lookup:
|
||||||
* @hash_table: a #fluid_hashtable_t.
|
* @hash_table: a #fluid_hashtable_t.
|
||||||
* @key: the key to look up.
|
* @key: the key to look up.
|
||||||
*
|
*
|
||||||
* Looks up a key in a #fluid_hashtable_t.
|
* Looks up a key in a #fluid_hashtable_t.
|
||||||
*
|
*
|
||||||
* Return value: the associated value, or %NULL if the key is not found.
|
* Return value: the associated value, or %NULL if the key is not found.
|
||||||
**/
|
**/
|
||||||
int
|
int
|
||||||
fluid_hashtable_lookup(fluid_hashtable_t *hash_table, char* key, void** value, int* type)
|
fluid_hashtable_lookup(fluid_hashtable_t *hash_table, char* key, void** value, int* type)
|
||||||
{
|
{
|
||||||
fluid_hashnode_t *node;
|
fluid_hashnode_t *node;
|
||||||
|
|
||||||
node = *fluid_hashtable_lookup_node(hash_table, key);
|
node = *fluid_hashtable_lookup_node(hash_table, key);
|
||||||
|
|
||||||
if (node) {
|
if (node) {
|
||||||
@@ -167,22 +167,22 @@ fluid_hashtable_lookup(fluid_hashtable_t *hash_table, char* key, void** value, i
|
|||||||
* @hash_table: a #fluid_hashtable_t.
|
* @hash_table: a #fluid_hashtable_t.
|
||||||
* @key: a key to insert.
|
* @key: a key to insert.
|
||||||
* @value: the value to associate with the key.
|
* @value: the value to associate with the key.
|
||||||
*
|
*
|
||||||
* Inserts a new key and value into a #fluid_hashtable_t.
|
* Inserts a new key and value into a #fluid_hashtable_t.
|
||||||
*
|
*
|
||||||
* If the key already exists in the #fluid_hashtable_t its current value is replaced
|
* If the key already exists in the #fluid_hashtable_t its current value is replaced
|
||||||
* with the new value. If you supplied a @value_destroy_func when creating the
|
* with the new value. If you supplied a @value_destroy_func when creating the
|
||||||
* #fluid_hashtable_t, the old value is freed using that function. If you supplied
|
* #fluid_hashtable_t, the old value is freed using that function. If you supplied
|
||||||
* a @key_destroy_func when creating the #fluid_hashtable_t, the passed key is freed
|
* a @key_destroy_func when creating the #fluid_hashtable_t, the passed key is freed
|
||||||
* using that function.
|
* using that function.
|
||||||
**/
|
**/
|
||||||
void
|
void
|
||||||
fluid_hashtable_insert(fluid_hashtable_t *hash_table, char* key, void* value, int type)
|
fluid_hashtable_insert(fluid_hashtable_t *hash_table, char* key, void* value, int type)
|
||||||
{
|
{
|
||||||
fluid_hashnode_t **node;
|
fluid_hashnode_t **node;
|
||||||
|
|
||||||
node = fluid_hashtable_lookup_node(hash_table, key);
|
node = fluid_hashtable_lookup_node(hash_table, key);
|
||||||
|
|
||||||
if (*node) {
|
if (*node) {
|
||||||
(*node)->value = value;
|
(*node)->value = value;
|
||||||
(*node)->type = type;
|
(*node)->type = type;
|
||||||
@@ -199,21 +199,21 @@ fluid_hashtable_insert(fluid_hashtable_t *hash_table, char* key, void* value, in
|
|||||||
* @hash_table: a #GHashTable.
|
* @hash_table: a #GHashTable.
|
||||||
* @key: a key to insert.
|
* @key: a key to insert.
|
||||||
* @value: the value to associate with the key.
|
* @value: the value to associate with the key.
|
||||||
*
|
*
|
||||||
* Inserts a new key and value into a #GHashTable similar to
|
* Inserts a new key and value into a #GHashTable similar to
|
||||||
* fluid_hashtable_insert(). The difference is that if the key already exists
|
* fluid_hashtable_insert(). The difference is that if the key already exists
|
||||||
* in the #GHashTable, it gets replaced by the new key. If you supplied a
|
* in the #GHashTable, it gets replaced by the new key. If you supplied a
|
||||||
* @value_destroy_func when creating the #GHashTable, the old value is freed
|
* @value_destroy_func when creating the #GHashTable, the old value is freed
|
||||||
* using that function. If you supplied a @key_destroy_func when creating the
|
* using that function. If you supplied a @key_destroy_func when creating the
|
||||||
* #GHashTable, the old key is freed using that function.
|
* #GHashTable, the old key is freed using that function.
|
||||||
**/
|
**/
|
||||||
void
|
void
|
||||||
fluid_hashtable_replace(fluid_hashtable_t *hash_table, char* key, void* value, int type)
|
fluid_hashtable_replace(fluid_hashtable_t *hash_table, char* key, void* value, int type)
|
||||||
{
|
{
|
||||||
fluid_hashnode_t **node;
|
fluid_hashnode_t **node;
|
||||||
|
|
||||||
node = fluid_hashtable_lookup_node(hash_table, key);
|
node = fluid_hashtable_lookup_node(hash_table, key);
|
||||||
|
|
||||||
if (*node) {
|
if (*node) {
|
||||||
if (hash_table->del) {
|
if (hash_table->del) {
|
||||||
hash_table->del((*node)->value, (*node)->type);
|
hash_table->del((*node)->value, (*node)->type);
|
||||||
@@ -231,30 +231,30 @@ fluid_hashtable_replace(fluid_hashtable_t *hash_table, char* key, void* value, i
|
|||||||
* fluid_hashtable_remove:
|
* fluid_hashtable_remove:
|
||||||
* @hash_table: a #fluid_hashtable_t.
|
* @hash_table: a #fluid_hashtable_t.
|
||||||
* @key: the key to remove.
|
* @key: the key to remove.
|
||||||
*
|
*
|
||||||
* Removes a key and its associated value from a #fluid_hashtable_t.
|
* Removes a key and its associated value from a #fluid_hashtable_t.
|
||||||
*
|
*
|
||||||
* If the #fluid_hashtable_t was created using fluid_hashtable_new_full(), the
|
* If the #fluid_hashtable_t was created using fluid_hashtable_new_full(), the
|
||||||
* key and value are freed using the supplied destroy functions, otherwise
|
* key and value are freed using the supplied destroy functions, otherwise
|
||||||
* you have to make sure that any dynamically allocated values are freed
|
* you have to make sure that any dynamically allocated values are freed
|
||||||
* yourself.
|
* yourself.
|
||||||
*
|
*
|
||||||
* Return value: %TRUE if the key was found and removed from the #fluid_hashtable_t.
|
* Return value: %TRUE if the key was found and removed from the #fluid_hashtable_t.
|
||||||
**/
|
**/
|
||||||
int
|
int
|
||||||
fluid_hashtable_remove (fluid_hashtable_t *hash_table, char* key)
|
fluid_hashtable_remove (fluid_hashtable_t *hash_table, char* key)
|
||||||
{
|
{
|
||||||
fluid_hashnode_t **node, *dest;
|
fluid_hashnode_t **node, *dest;
|
||||||
|
|
||||||
node = fluid_hashtable_lookup_node(hash_table, key);
|
node = fluid_hashtable_lookup_node(hash_table, key);
|
||||||
if (*node) {
|
if (*node) {
|
||||||
dest = *node;
|
dest = *node;
|
||||||
(*node) = dest->next;
|
(*node) = dest->next;
|
||||||
delete_fluid_hashnode(dest, hash_table->del);
|
delete_fluid_hashnode(dest, hash_table->del);
|
||||||
hash_table->nnodes--;
|
hash_table->nnodes--;
|
||||||
|
|
||||||
FLUID_HASHTABLE_RESIZE (hash_table);
|
FLUID_HASHTABLE_RESIZE (hash_table);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -266,7 +266,7 @@ fluid_hashtable_remove (fluid_hashtable_t *hash_table, char* key)
|
|||||||
* @hash_table: a #fluid_hashtable_t.
|
* @hash_table: a #fluid_hashtable_t.
|
||||||
* @func: the function to call for each key/value pair.
|
* @func: the function to call for each key/value pair.
|
||||||
* @user_data: user data to pass to the function.
|
* @user_data: user data to pass to the function.
|
||||||
*
|
*
|
||||||
* Calls the given function for each of the key/value pairs in the
|
* Calls the given function for each of the key/value pairs in the
|
||||||
* #fluid_hashtable_t. The function is passed the key and value of each
|
* #fluid_hashtable_t. The function is passed the key and value of each
|
||||||
* pair, and the given @user_data parameter. The hash table may not
|
* pair, and the given @user_data parameter. The hash table may not
|
||||||
@@ -290,9 +290,9 @@ fluid_hashtable_foreach(fluid_hashtable_t *hash_table, fluid_hash_iter_t func, v
|
|||||||
/**
|
/**
|
||||||
* fluid_hashtable_size:
|
* fluid_hashtable_size:
|
||||||
* @hash_table: a #fluid_hashtable_t.
|
* @hash_table: a #fluid_hashtable_t.
|
||||||
*
|
*
|
||||||
* Returns the number of elements contained in the #fluid_hashtable_t.
|
* Returns the number of elements contained in the #fluid_hashtable_t.
|
||||||
*
|
*
|
||||||
* Return value: the number of key/value pairs in the #fluid_hashtable_t.
|
* Return value: the number of key/value pairs in the #fluid_hashtable_t.
|
||||||
**/
|
**/
|
||||||
unsigned int
|
unsigned int
|
||||||
@@ -315,14 +315,14 @@ fluid_hashtable_resize(fluid_hashtable_t *hash_table)
|
|||||||
new_size = (new_size > HASH_TABLE_MAX_SIZE)? HASH_TABLE_MAX_SIZE : new_size;
|
new_size = (new_size > HASH_TABLE_MAX_SIZE)? HASH_TABLE_MAX_SIZE : new_size;
|
||||||
|
|
||||||
/* printf("%s: %d: resizing, new size = %d\n", __FILE__, __LINE__, new_size); */
|
/* printf("%s: %d: resizing, new size = %d\n", __FILE__, __LINE__, new_size); */
|
||||||
|
|
||||||
new_nodes = FLUID_ARRAY(fluid_hashnode_t*, new_size);
|
new_nodes = FLUID_ARRAY(fluid_hashnode_t*, new_size);
|
||||||
FLUID_MEMSET(new_nodes, 0, new_size * sizeof(fluid_hashnode_t*));
|
FLUID_MEMSET(new_nodes, 0, new_size * sizeof(fluid_hashnode_t*));
|
||||||
|
|
||||||
for (i = 0; i < hash_table->size; i++) {
|
for (i = 0; i < hash_table->size; i++) {
|
||||||
for (node = hash_table->nodes[i]; node; node = next) {
|
for (node = hash_table->nodes[i]; node; node = next) {
|
||||||
next = node->next;
|
next = node->next;
|
||||||
hash_val = fluid_str_hash(node->key) % new_size;
|
hash_val = fluid_str_hash(node->key) % new_size;
|
||||||
node->next = new_nodes[hash_val];
|
node->next = new_nodes[hash_val];
|
||||||
new_nodes[hash_val] = node;
|
new_nodes[hash_val] = node;
|
||||||
}
|
}
|
||||||
@@ -337,14 +337,14 @@ static fluid_hashnode_t*
|
|||||||
new_fluid_hashnode(char* key, void* value, int type)
|
new_fluid_hashnode(char* key, void* value, int type)
|
||||||
{
|
{
|
||||||
fluid_hashnode_t *hash_node;
|
fluid_hashnode_t *hash_node;
|
||||||
|
|
||||||
hash_node = FLUID_NEW(fluid_hashnode_t);
|
hash_node = FLUID_NEW(fluid_hashnode_t);
|
||||||
|
|
||||||
hash_node->key = FLUID_STRDUP(key);
|
hash_node->key = FLUID_STRDUP(key);
|
||||||
hash_node->value = value;
|
hash_node->value = value;
|
||||||
hash_node->type = type;
|
hash_node->type = type;
|
||||||
hash_node->next = NULL;
|
hash_node->next = NULL;
|
||||||
|
|
||||||
return hash_node;
|
return hash_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,7 +367,7 @@ delete_fluid_hashnodes(fluid_hashnode_t *hash_node, fluid_hash_delete_t del)
|
|||||||
fluid_hashnode_t *next = hash_node->next;
|
fluid_hashnode_t *next = hash_node->next;
|
||||||
delete_fluid_hashnode(hash_node, del);
|
delete_fluid_hashnode(hash_node, del);
|
||||||
hash_node = next;
|
hash_node = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||||
* file for a list of people on the GLib Team. See the ChangeLog
|
* file for a list of people on the GLib Team. See the ChangeLog
|
||||||
* files for a list of changes. These files are distributed with
|
* files for a list of changes. These files are distributed with
|
||||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -52,15 +52,15 @@ int fluid_istream_readline(fluid_istream_t in, char* prompt, char* buf, int len)
|
|||||||
#if WITH_READLINE
|
#if WITH_READLINE
|
||||||
if (in == fluid_get_stdin()) {
|
if (in == fluid_get_stdin()) {
|
||||||
char* line;
|
char* line;
|
||||||
|
|
||||||
line = readline(prompt);
|
line = readline(prompt);
|
||||||
if (line == NULL) {
|
if (line == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(buf, len, "%s", line);
|
snprintf(buf, len, "%s", line);
|
||||||
buf[len - 1] = 0;
|
buf[len - 1] = 0;
|
||||||
|
|
||||||
free(line);
|
free(line);
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
@@ -78,19 +78,19 @@ int fluid_istream_gets(fluid_istream_t in, char* buf, int len)
|
|||||||
int n;
|
int n;
|
||||||
|
|
||||||
buf[len - 1] = 0;
|
buf[len - 1] = 0;
|
||||||
|
|
||||||
while (--len > 0) {
|
while (--len > 0) {
|
||||||
n = read(in, &c, 1);
|
n = read(in, &c, 1);
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
*buf++ = 0;
|
*buf++ = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
if ((c == '\n') || (c == '\r')) {
|
if ((c == '\n') || (c == '\r')) {
|
||||||
*buf++ = 0;
|
*buf++ = 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
*buf++ = c;
|
*buf++ = c;
|
||||||
}
|
}
|
||||||
@@ -102,12 +102,12 @@ int fluid_istream_gets(fluid_istream_t in, char* buf, int len)
|
|||||||
int fluid_ostream_printf(fluid_ostream_t out, char* format, ...)
|
int fluid_ostream_printf(fluid_ostream_t out, char* format, ...)
|
||||||
{
|
{
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
va_list args;
|
va_list args;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
len = vsnprintf(buf, 4095, format, args);
|
len = vsnprintf(buf, 4095, format, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
if (len <= 0) {
|
if (len <= 0) {
|
||||||
printf("fluid_ostream_printf: buffer overflow");
|
printf("fluid_ostream_printf: buffer overflow");
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -23,15 +23,15 @@
|
|||||||
#define _FLUID_IO_H
|
#define _FLUID_IO_H
|
||||||
|
|
||||||
|
|
||||||
/** Read a line from the input stream.
|
/** Read a line from the input stream.
|
||||||
|
|
||||||
\returns 0 if end-of-stream, -1 if error, non zero otherwise
|
\returns 0 if end-of-stream, -1 if error, non zero otherwise
|
||||||
*/
|
*/
|
||||||
int fluid_istream_readline(fluid_istream_t in, char* prompt, char* buf, int len);
|
int fluid_istream_readline(fluid_istream_t in, char* prompt, char* buf, int len);
|
||||||
|
|
||||||
|
|
||||||
/** Read a line from the input stream.
|
/** Read a line from the input stream.
|
||||||
|
|
||||||
\returns The number of bytes written. If an error occured, -1 is
|
\returns The number of bytes written. If an error occured, -1 is
|
||||||
returned.
|
returned.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -57,17 +57,17 @@ fluid_LADSPA_FxUnit_t* new_fluid_LADSPA_FxUnit(fluid_synth_t* synth){
|
|||||||
return FxUnit;
|
return FxUnit;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Purpose:
|
/* Purpose:
|
||||||
* Creates the system nodes to get data into and out of the Fx unit.
|
* Creates the system nodes to get data into and out of the Fx unit.
|
||||||
*/
|
*/
|
||||||
void fluid_LADSPA_CreateSystemNodes(fluid_LADSPA_FxUnit_t* FxUnit){
|
void fluid_LADSPA_CreateSystemNodes(fluid_LADSPA_FxUnit_t* FxUnit){
|
||||||
char str[99];
|
char str[99];
|
||||||
int nr_input_nodes;
|
int nr_input_nodes;
|
||||||
int nr_fx_input_nodes;
|
int nr_fx_input_nodes;
|
||||||
int nr_output_nodes;
|
int nr_output_nodes;
|
||||||
int temp;
|
int temp;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Retrieve the number of synth / audio out / Fx send nodes */
|
/* Retrieve the number of synth / audio out / Fx send nodes */
|
||||||
assert(fluid_settings_getint(FxUnit->synth->settings, "synth.audio-groups", &temp));
|
assert(fluid_settings_getint(FxUnit->synth->settings, "synth.audio-groups", &temp));
|
||||||
nr_input_nodes=(int) temp;
|
nr_input_nodes=(int) temp;
|
||||||
@@ -78,7 +78,7 @@ void fluid_LADSPA_CreateSystemNodes(fluid_LADSPA_FxUnit_t* FxUnit){
|
|||||||
|
|
||||||
assert(fluid_settings_getint(FxUnit->synth->settings, "synth.effects-channels", &temp));
|
assert(fluid_settings_getint(FxUnit->synth->settings, "synth.effects-channels", &temp));
|
||||||
nr_fx_input_nodes=temp;
|
nr_fx_input_nodes=temp;
|
||||||
|
|
||||||
/* Create regular input nodes (associated with audio groups) */
|
/* Create regular input nodes (associated with audio groups) */
|
||||||
for (i=0; i < nr_input_nodes; i++){
|
for (i=0; i < nr_input_nodes; i++){
|
||||||
sprintf(str, "in%i_L",(i+1));
|
sprintf(str, "in%i_L",(i+1));
|
||||||
@@ -104,13 +104,13 @@ void fluid_LADSPA_CreateSystemNodes(fluid_LADSPA_FxUnit_t* FxUnit){
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Purpose:
|
/* Purpose:
|
||||||
* Creates predeclared nodes for control of the Fx unit during operation.
|
* Creates predeclared nodes for control of the Fx unit during operation.
|
||||||
*/
|
*/
|
||||||
void fluid_LADSPA_CreateUserControlNodes(fluid_LADSPA_FxUnit_t* FxUnit){
|
void fluid_LADSPA_CreateUserControlNodes(fluid_LADSPA_FxUnit_t* FxUnit){
|
||||||
int i;
|
int i;
|
||||||
fluid_LADSPA_Node_t* CurrentNode;
|
fluid_LADSPA_Node_t* CurrentNode;
|
||||||
|
|
||||||
for (i=0; i<FxUnit->NumberUserControlNodes; i++){
|
for (i=0; i<FxUnit->NumberUserControlNodes; i++){
|
||||||
CurrentNode=fluid_LADSPA_CreateNode(FxUnit,FxUnit->UserControlNodeNames[i],fluid_LADSPA_node_is_control);
|
CurrentNode=fluid_LADSPA_CreateNode(FxUnit,FxUnit->UserControlNodeNames[i],fluid_LADSPA_node_is_control);
|
||||||
assert(CurrentNode);
|
assert(CurrentNode);
|
||||||
@@ -120,10 +120,10 @@ void fluid_LADSPA_CreateUserControlNodes(fluid_LADSPA_FxUnit_t* FxUnit){
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Purpose:
|
/* Purpose:
|
||||||
* Returns the pointer to the shared library loaded using 'LibraryFilename' (if it has been loaded).
|
* Returns the pointer to the shared library loaded using 'LibraryFilename' (if it has been loaded).
|
||||||
* Return NULL otherwise.
|
* Return NULL otherwise.
|
||||||
* If not: Clear Fx and abort.
|
* If not: Clear Fx and abort.
|
||||||
*/
|
*/
|
||||||
void * fluid_LADSPA_RetrieveSharedLibrary(fluid_LADSPA_FxUnit_t* FxUnit, char * LibraryFilename){
|
void * fluid_LADSPA_RetrieveSharedLibrary(fluid_LADSPA_FxUnit_t* FxUnit, char * LibraryFilename){
|
||||||
void * CurrentLib=NULL;
|
void * CurrentLib=NULL;
|
||||||
@@ -137,15 +137,15 @@ void * fluid_LADSPA_RetrieveSharedLibrary(fluid_LADSPA_FxUnit_t* FxUnit, char *
|
|||||||
return CurrentLib;
|
return CurrentLib;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Purpose:
|
/* Purpose:
|
||||||
* Loads a shared LADSPA library.
|
* Loads a shared LADSPA library.
|
||||||
* Return NULL, if failed.
|
* Return NULL, if failed.
|
||||||
* TODO: use LADSPA_PATH
|
* TODO: use LADSPA_PATH
|
||||||
*/
|
*/
|
||||||
void * fluid_LADSPA_LoadSharedLibrary(fluid_LADSPA_FxUnit_t* FxUnit, char * LibraryFilename){
|
void * fluid_LADSPA_LoadSharedLibrary(fluid_LADSPA_FxUnit_t* FxUnit, char * LibraryFilename){
|
||||||
void * LoadedLib;
|
void * LoadedLib;
|
||||||
assert(LibraryFilename);
|
assert(LibraryFilename);
|
||||||
LoadedLib=dlopen(LibraryFilename,RTLD_NOW);
|
LoadedLib=dlopen(LibraryFilename,RTLD_NOW);
|
||||||
if (!LoadedLib){
|
if (!LoadedLib){
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
@@ -155,7 +155,7 @@ void * fluid_LADSPA_LoadSharedLibrary(fluid_LADSPA_FxUnit_t* FxUnit, char * Libr
|
|||||||
return LoadedLib;
|
return LoadedLib;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Purpose:
|
/* Purpose:
|
||||||
* Retrieves a descriptor to the plugin labeled 'PluginLabel' from the shared library.
|
* Retrieves a descriptor to the plugin labeled 'PluginLabel' from the shared library.
|
||||||
*/
|
*/
|
||||||
const LADSPA_Descriptor * fluid_LADSPA_Retrieve_Plugin_Descriptor(void * CurrentLib, char * PluginLabel){
|
const LADSPA_Descriptor * fluid_LADSPA_Retrieve_Plugin_Descriptor(void * CurrentLib, char * PluginLabel){
|
||||||
@@ -164,16 +164,16 @@ const LADSPA_Descriptor * fluid_LADSPA_Retrieve_Plugin_Descriptor(void * Current
|
|||||||
const LADSPA_Descriptor * psDescriptor;
|
const LADSPA_Descriptor * psDescriptor;
|
||||||
pfDescriptorFunction = (LADSPA_Descriptor_Function)dlsym(CurrentLib,"ladspa_descriptor");
|
pfDescriptorFunction = (LADSPA_Descriptor_Function)dlsym(CurrentLib,"ladspa_descriptor");
|
||||||
while (pfDescriptorFunction(lPluginIndex)){
|
while (pfDescriptorFunction(lPluginIndex)){
|
||||||
psDescriptor = pfDescriptorFunction(lPluginIndex);
|
psDescriptor = pfDescriptorFunction(lPluginIndex);
|
||||||
if (FLUID_STRCMP(psDescriptor->Label, PluginLabel) == 0){
|
if (FLUID_STRCMP(psDescriptor->Label, PluginLabel) == 0){
|
||||||
return psDescriptor;
|
return psDescriptor;
|
||||||
};
|
};
|
||||||
lPluginIndex++;
|
lPluginIndex++;
|
||||||
};
|
};
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Purpose:
|
/* Purpose:
|
||||||
* Finds out, if 'PortName' starts with 'PluginPort'.
|
* Finds out, if 'PortName' starts with 'PluginPort'.
|
||||||
* Spaces and underscore mean the same.
|
* Spaces and underscore mean the same.
|
||||||
* The comparison is not case sensitive.
|
* The comparison is not case sensitive.
|
||||||
@@ -203,7 +203,7 @@ fluid_LADSPA_Stringmatch_t fluid_LADSPA_Check_SubString_Match(const char * Plugi
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Purpose:
|
/* Purpose:
|
||||||
* Load the plugins added with 'ladspa_add' and then start the Fx unit.
|
* Load the plugins added with 'ladspa_add' and then start the Fx unit.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -214,7 +214,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
|||||||
char * PluginLabel;
|
char * PluginLabel;
|
||||||
char ** TokenSequence;
|
char ** TokenSequence;
|
||||||
void * CurrentLib;
|
void * CurrentLib;
|
||||||
int NodeCount; //x
|
int NodeCount; //x
|
||||||
int IngoingSignalCount; // Count signals going into LADSPA Fx section
|
int IngoingSignalCount; // Count signals going into LADSPA Fx section
|
||||||
int OutgoingSignalCount; // Count signals going out of LADSPA Fx section
|
int OutgoingSignalCount; // Count signals going out of LADSPA Fx section
|
||||||
int ReturnVal=FLUID_OK; /* If warnings occur, this is set to -1. */
|
int ReturnVal=FLUID_OK; /* If warnings occur, this is set to -1. */
|
||||||
@@ -223,7 +223,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
|||||||
L(fluid_ostream_printf(out,"ladspa_start: starting..."));
|
L(fluid_ostream_printf(out,"ladspa_start: starting..."));
|
||||||
assert(synth);
|
assert(synth);
|
||||||
FxUnit=synth->LADSPA_FxUnit; assert(FxUnit);
|
FxUnit=synth->LADSPA_FxUnit; assert(FxUnit);
|
||||||
|
|
||||||
/* When calling fluid_ladspastart, the Fx unit must be 'cleared' (no plugins, no libs, no nodes). Verify this here. */
|
/* When calling fluid_ladspastart, the Fx unit must be 'cleared' (no plugins, no libs, no nodes). Verify this here. */
|
||||||
if (FxUnit->NumberPlugins || FxUnit->NumberLibs){
|
if (FxUnit->NumberPlugins || FxUnit->NumberLibs){
|
||||||
fluid_ostream_printf(out, "***Error006***\n"
|
fluid_ostream_printf(out, "***Error006***\n"
|
||||||
@@ -238,12 +238,12 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
|||||||
"Use ladspa_add first!\n");
|
"Use ladspa_add first!\n");
|
||||||
fluid_LADSPA_clear(FxUnit);
|
fluid_LADSPA_clear(FxUnit);
|
||||||
return(PrintErrorMessage);
|
return(PrintErrorMessage);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Create predefined nodes */
|
/* Create predefined nodes */
|
||||||
L(fluid_ostream_printf(out,"ladspa_start: creating predefined nodes..."));
|
L(fluid_ostream_printf(out,"ladspa_start: creating predefined nodes..."));
|
||||||
fluid_LADSPA_CreateSystemNodes(FxUnit);
|
fluid_LADSPA_CreateSystemNodes(FxUnit);
|
||||||
|
|
||||||
/* Create predeclared nodes, that will allow to control the Fx unit during operation */
|
/* Create predeclared nodes, that will allow to control the Fx unit during operation */
|
||||||
L(fluid_ostream_printf(out,"ladspa_start: creating user control nodes..."));
|
L(fluid_ostream_printf(out,"ladspa_start: creating user control nodes..."));
|
||||||
fluid_LADSPA_CreateUserControlNodes(FxUnit);
|
fluid_LADSPA_CreateUserControlNodes(FxUnit);
|
||||||
@@ -251,14 +251,14 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
|||||||
L(fluid_ostream_printf(out,"ladspa_start: Processing command lines..."));
|
L(fluid_ostream_printf(out,"ladspa_start: Processing command lines..."));
|
||||||
for (CommandLineCount=0; CommandLineCount<FxUnit->NumberCommands; CommandLineCount++){
|
for (CommandLineCount=0; CommandLineCount<FxUnit->NumberCommands; CommandLineCount++){
|
||||||
int CurrentPlugin_PortConnected[FLUID_LADSPA_MaxTokens/3]; /* For example: 100 tokens corresponds to roughly 30 ports. */
|
int CurrentPlugin_PortConnected[FLUID_LADSPA_MaxTokens/3]; /* For example: 100 tokens corresponds to roughly 30 ports. */
|
||||||
char LibFullPath[FLUID_LADSPA_MaxPathLength];
|
char LibFullPath[FLUID_LADSPA_MaxPathLength];
|
||||||
const LADSPA_Descriptor * CurrentPluginDescriptor;
|
const LADSPA_Descriptor * CurrentPluginDescriptor;
|
||||||
LADSPA_Handle CurrentPlugin;
|
LADSPA_Handle CurrentPlugin;
|
||||||
unsigned long PortCount;
|
unsigned long PortCount;
|
||||||
int TokenCount=0;
|
int TokenCount=0;
|
||||||
char * Search;
|
char * Search;
|
||||||
int HasASlash=0;
|
int HasASlash=0;
|
||||||
|
|
||||||
if (FxUnit->NumberPlugins>=FLUID_LADSPA_MaxPlugins){
|
if (FxUnit->NumberPlugins>=FLUID_LADSPA_MaxPlugins){
|
||||||
fluid_ostream_printf(out, "***Error003***\n"
|
fluid_ostream_printf(out, "***Error003***\n"
|
||||||
"Too many plugins at the same time (%i).\n"
|
"Too many plugins at the same time (%i).\n"
|
||||||
@@ -269,13 +269,13 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
|||||||
};
|
};
|
||||||
|
|
||||||
L(fluid_ostream_printf(out,"Processing plugin nr. %i",FxUnit->NumberPlugins));
|
L(fluid_ostream_printf(out,"Processing plugin nr. %i",FxUnit->NumberPlugins));
|
||||||
|
|
||||||
TokenSequence=FxUnit->LADSPA_Command_Sequence[CommandLineCount];
|
TokenSequence=FxUnit->LADSPA_Command_Sequence[CommandLineCount];
|
||||||
assert(TokenSequence);
|
assert(TokenSequence);
|
||||||
|
|
||||||
/* Check, if the library is already loaded. If not, load. */
|
/* Check, if the library is already loaded. If not, load. */
|
||||||
LibraryFilename=TokenSequence[TokenCount++]; assert(LibraryFilename);
|
LibraryFilename=TokenSequence[TokenCount++]; assert(LibraryFilename);
|
||||||
|
|
||||||
L(fluid_ostream_printf(out,"Library name from ladspa_add: %s",LibraryFilename));
|
L(fluid_ostream_printf(out,"Library name from ladspa_add: %s",LibraryFilename));
|
||||||
/* A slash-free filename refers to the LADSPA_PATH directory. Add that path, if needed. */
|
/* A slash-free filename refers to the LADSPA_PATH directory. Add that path, if needed. */
|
||||||
|
|
||||||
@@ -286,7 +286,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
|||||||
* If that fails, signal error.
|
* If that fails, signal error.
|
||||||
* Otherwise leave the filename as it is.
|
* Otherwise leave the filename as it is.
|
||||||
*/;
|
*/;
|
||||||
|
|
||||||
/* Determine, if the library name is just the filename, or a path (including a slash) */
|
/* Determine, if the library name is just the filename, or a path (including a slash) */
|
||||||
Search=LibraryFilename;
|
Search=LibraryFilename;
|
||||||
while (*Search != '\0') {
|
while (*Search != '\0') {
|
||||||
@@ -295,9 +295,9 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
|||||||
};
|
};
|
||||||
Search++;
|
Search++;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!HasASlash){
|
if (!HasASlash){
|
||||||
if (!LADSPA_Path){
|
if (!LADSPA_Path){
|
||||||
fluid_ostream_printf(out, "***Error018***\n"
|
fluid_ostream_printf(out, "***Error018***\n"
|
||||||
"The library file name %s does not include a path.\n"
|
"The library file name %s does not include a path.\n"
|
||||||
"The environment variable LADSPA_PATH is not set.\n"
|
"The environment variable LADSPA_PATH is not set.\n"
|
||||||
@@ -319,7 +319,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
|||||||
|
|
||||||
CurrentLib=fluid_LADSPA_RetrieveSharedLibrary(FxUnit, LibFullPath);
|
CurrentLib=fluid_LADSPA_RetrieveSharedLibrary(FxUnit, LibFullPath);
|
||||||
if (!CurrentLib){
|
if (!CurrentLib){
|
||||||
LADSPA_Descriptor_Function pfDescriptorFunction;
|
LADSPA_Descriptor_Function pfDescriptorFunction;
|
||||||
|
|
||||||
L(fluid_ostream_printf(out,"Library %s not yet loaded. Loading.",LibFullPath));
|
L(fluid_ostream_printf(out,"Library %s not yet loaded. Loading.",LibFullPath));
|
||||||
|
|
||||||
@@ -330,7 +330,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
|||||||
fluid_LADSPA_clear(FxUnit);
|
fluid_LADSPA_clear(FxUnit);
|
||||||
return(PrintErrorMessage);
|
return(PrintErrorMessage);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Load a LADSPA plugin library and store it for future use.*/
|
/* Load a LADSPA plugin library and store it for future use.*/
|
||||||
CurrentLib=fluid_LADSPA_LoadSharedLibrary(FxUnit, LibFullPath);
|
CurrentLib=fluid_LADSPA_LoadSharedLibrary(FxUnit, LibFullPath);
|
||||||
|
|
||||||
@@ -350,23 +350,23 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
|||||||
if (!pcError) {pcError="Huh?! No error from lib!";};
|
if (!pcError) {pcError="Huh?! No error from lib!";};
|
||||||
fluid_ostream_printf(out, "***Error015***\n"
|
fluid_ostream_printf(out, "***Error015***\n"
|
||||||
"Unable to find ladspa_descriptor() function in plugin library file \"%s\": %s.\n"
|
"Unable to find ladspa_descriptor() function in plugin library file \"%s\": %s.\n"
|
||||||
"Are you sure this is a LADSPA plugin file?\n",
|
"Are you sure this is a LADSPA plugin file?\n",
|
||||||
LibraryFilename,
|
LibraryFilename,
|
||||||
pcError);
|
pcError);
|
||||||
fluid_LADSPA_clear(FxUnit);
|
fluid_LADSPA_clear(FxUnit);
|
||||||
return(PrintErrorMessage);
|
return(PrintErrorMessage);
|
||||||
};
|
};
|
||||||
|
|
||||||
L(fluid_ostream_printf(out,"Library loaded."));
|
L(fluid_ostream_printf(out,"Library loaded."));
|
||||||
};
|
};
|
||||||
|
|
||||||
PluginLabel=TokenSequence[TokenCount++]; assert(PluginLabel);
|
PluginLabel=TokenSequence[TokenCount++]; assert(PluginLabel);
|
||||||
L(fluid_ostream_printf(out,"Plugin Label from ladspa_add: %s",PluginLabel));
|
L(fluid_ostream_printf(out,"Plugin Label from ladspa_add: %s",PluginLabel));
|
||||||
/* Retrieve a 'plugin descriptor' from the library. */
|
/* Retrieve a 'plugin descriptor' from the library. */
|
||||||
L(fluid_ostream_printf(out,"Looking for the plugin labeled %s",PluginLabel));
|
L(fluid_ostream_printf(out,"Looking for the plugin labeled %s",PluginLabel));
|
||||||
|
|
||||||
CurrentPluginDescriptor=fluid_LADSPA_Retrieve_Plugin_Descriptor(CurrentLib, PluginLabel);
|
CurrentPluginDescriptor=fluid_LADSPA_Retrieve_Plugin_Descriptor(CurrentLib, PluginLabel);
|
||||||
|
|
||||||
|
|
||||||
/* Check, that the plugin was actually found.*/
|
/* Check, that the plugin was actually found.*/
|
||||||
if (CurrentPluginDescriptor==NULL){
|
if (CurrentPluginDescriptor==NULL){
|
||||||
@@ -379,30 +379,30 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
|||||||
fluid_LADSPA_clear(FxUnit);
|
fluid_LADSPA_clear(FxUnit);
|
||||||
return(PrintErrorMessage);
|
return(PrintErrorMessage);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Create an instance of the plugin type from the descriptor */
|
/* Create an instance of the plugin type from the descriptor */
|
||||||
L(fluid_ostream_printf(out,"instantiating plugin %s",PluginLabel));
|
L(fluid_ostream_printf(out,"instantiating plugin %s",PluginLabel));
|
||||||
CurrentPlugin=CurrentPluginDescriptor
|
CurrentPlugin=CurrentPluginDescriptor
|
||||||
->instantiate(CurrentPluginDescriptor,44100); /* Sample rate hardcoded */
|
->instantiate(CurrentPluginDescriptor,44100); /* Sample rate hardcoded */
|
||||||
assert(CurrentPlugin);
|
assert(CurrentPlugin);
|
||||||
|
|
||||||
/* The descriptor ("type of plugin") and the instance are stored for each plugin instantiation.
|
/* The descriptor ("type of plugin") and the instance are stored for each plugin instantiation.
|
||||||
If one plugin type is instantiated several times, they will have the same descriptor, only
|
If one plugin type is instantiated several times, they will have the same descriptor, only
|
||||||
different instances.*/
|
different instances.*/
|
||||||
FxUnit->PluginDescriptorTable[FxUnit->NumberPlugins]=CurrentPluginDescriptor;
|
FxUnit->PluginDescriptorTable[FxUnit->NumberPlugins]=CurrentPluginDescriptor;
|
||||||
FxUnit->PluginInstanceTable[FxUnit->NumberPlugins]=CurrentPlugin;
|
FxUnit->PluginInstanceTable[FxUnit->NumberPlugins]=CurrentPlugin;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Wire up the inputs and outputs
|
* Wire up the inputs and outputs
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* List for checking, that each plugin port is exactly connected once */
|
/* List for checking, that each plugin port is exactly connected once */
|
||||||
for (PortCount=0; PortCount<CurrentPluginDescriptor->PortCount; PortCount++){
|
for (PortCount=0; PortCount<CurrentPluginDescriptor->PortCount; PortCount++){
|
||||||
CurrentPlugin_PortConnected[PortCount]=0;
|
CurrentPlugin_PortConnected[PortCount]=0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Note: There are three NULL tokens at the end. The last condition may be evaluated even if the first one already detects the end. */
|
/* Note: There are three NULL tokens at the end. The last condition may be evaluated even if the first one already detects the end. */
|
||||||
while (TokenSequence[TokenCount] && TokenSequence[TokenCount+1] && TokenSequence[TokenCount+2]){
|
while (TokenSequence[TokenCount] && TokenSequence[TokenCount+1] && TokenSequence[TokenCount+2]){
|
||||||
int CurrentPort_StringMatchCount;
|
int CurrentPort_StringMatchCount;
|
||||||
@@ -418,11 +418,11 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
|||||||
CurrentPort_StringMatchCount=0;
|
CurrentPort_StringMatchCount=0;
|
||||||
|
|
||||||
L(fluid_ostream_printf(out,"Wiring %s %s %s",Plugin_Port, Direction, FLUID_Node));
|
L(fluid_ostream_printf(out,"Wiring %s %s %s",Plugin_Port, Direction, FLUID_Node));
|
||||||
|
|
||||||
/* Find the port number on the plugin, that belongs to "Plugin_Port".
|
/* Find the port number on the plugin, that belongs to "Plugin_Port".
|
||||||
* Match the identifier specified by the user against the first characters
|
* Match the identifier specified by the user against the first characters
|
||||||
* of the port name.
|
* of the port name.
|
||||||
*
|
*
|
||||||
* If the given identifier matches several port names only partly, then the input is ambiguous, an error
|
* If the given identifier matches several port names only partly, then the input is ambiguous, an error
|
||||||
* message results.
|
* message results.
|
||||||
*
|
*
|
||||||
@@ -430,19 +430,19 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
|||||||
* - Output Envelope Attack (s)
|
* - Output Envelope Attack (s)
|
||||||
* - Output Envelope Decay (s)
|
* - Output Envelope Decay (s)
|
||||||
* - Output
|
* - Output
|
||||||
*
|
*
|
||||||
* The user input 'Output' matches the first two labels partly, the third fully. This will be accepted.
|
* The user input 'Output' matches the first two labels partly, the third fully. This will be accepted.
|
||||||
* The user input 'Out' matches all three only partly, this results in an error message.
|
* The user input 'Out' matches all three only partly, this results in an error message.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for (PortCount=0; PortCount<CurrentPluginDescriptor->PortCount; PortCount++){
|
for (PortCount=0; PortCount<CurrentPluginDescriptor->PortCount; PortCount++){
|
||||||
PortName=CurrentPluginDescriptor->PortNames[PortCount];
|
PortName=CurrentPluginDescriptor->PortNames[PortCount];
|
||||||
|
|
||||||
StringMatchType=fluid_LADSPA_Check_SubString_Match(Plugin_Port, PortName);
|
StringMatchType=fluid_LADSPA_Check_SubString_Match(Plugin_Port, PortName);
|
||||||
/* If a full-string match has been found earlier, reject all partial matches. */
|
/* If a full-string match has been found earlier, reject all partial matches. */
|
||||||
if (StringMatchType==fluid_LADSPA_FullMatch ||
|
if (StringMatchType==fluid_LADSPA_FullMatch ||
|
||||||
(StringMatchType==fluid_LADSPA_PartialMatch && CurrentPort_StringMatchType != fluid_LADSPA_FullMatch)){
|
(StringMatchType==fluid_LADSPA_PartialMatch && CurrentPort_StringMatchType != fluid_LADSPA_FullMatch)){
|
||||||
|
|
||||||
if(StringMatchType==fluid_LADSPA_FullMatch && CurrentPort_StringMatchType==fluid_LADSPA_FullMatch){
|
if(StringMatchType==fluid_LADSPA_FullMatch && CurrentPort_StringMatchType==fluid_LADSPA_FullMatch){
|
||||||
fluid_ostream_printf(out, "***Error027***\n"
|
fluid_ostream_printf(out, "***Error027***\n"
|
||||||
"While processing plugin %s: The port label %s appears more than once!\n"
|
"While processing plugin %s: The port label %s appears more than once!\n"
|
||||||
@@ -450,14 +450,14 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
|||||||
fluid_LADSPA_clear(FxUnit);
|
fluid_LADSPA_clear(FxUnit);
|
||||||
return(PrintErrorMessage);
|
return(PrintErrorMessage);
|
||||||
};
|
};
|
||||||
|
|
||||||
CurrentPort_Index=PortCount;
|
CurrentPort_Index=PortCount;
|
||||||
CurrentPort_StringMatchType=StringMatchType;
|
CurrentPort_StringMatchType=StringMatchType;
|
||||||
CurrentPort_StringMatchCount++;
|
CurrentPort_StringMatchCount++;
|
||||||
|
|
||||||
}; /* if suitable match */
|
}; /* if suitable match */
|
||||||
}; /* For port count */
|
}; /* For port count */
|
||||||
|
|
||||||
/* Several partial matches? Then the identifier is not unique. */
|
/* Several partial matches? Then the identifier is not unique. */
|
||||||
if (CurrentPort_StringMatchCount > 1 && CurrentPort_StringMatchType == fluid_LADSPA_PartialMatch){
|
if (CurrentPort_StringMatchCount > 1 && CurrentPort_StringMatchType == fluid_LADSPA_PartialMatch){
|
||||||
fluid_ostream_printf(out, "***Error019***\n"
|
fluid_ostream_printf(out, "***Error019***\n"
|
||||||
@@ -467,7 +467,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
|||||||
fluid_LADSPA_clear(FxUnit);
|
fluid_LADSPA_clear(FxUnit);
|
||||||
return(PrintErrorMessage);
|
return(PrintErrorMessage);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (CurrentPort_Index<0){
|
if (CurrentPort_Index<0){
|
||||||
fluid_ostream_printf(out, "***Error017***\n"
|
fluid_ostream_printf(out, "***Error017***\n"
|
||||||
"Unable to find port '%s' on plugin %s\n"
|
"Unable to find port '%s' on plugin %s\n"
|
||||||
@@ -479,13 +479,13 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
|||||||
fluid_LADSPA_clear(FxUnit);
|
fluid_LADSPA_clear(FxUnit);
|
||||||
return(PrintErrorMessage);
|
return(PrintErrorMessage);
|
||||||
};
|
};
|
||||||
CurrentPort_Descriptor=CurrentPluginDescriptor->PortDescriptors[CurrentPort_Index];
|
CurrentPort_Descriptor=CurrentPluginDescriptor->PortDescriptors[CurrentPort_Index];
|
||||||
assert(CurrentPort_Descriptor);
|
assert(CurrentPort_Descriptor);
|
||||||
|
|
||||||
/* Retrieve the node with the right name. */
|
/* Retrieve the node with the right name. */
|
||||||
Current_Node=fluid_LADSPA_RetrieveNode(FxUnit,FLUID_Node);
|
Current_Node=fluid_LADSPA_RetrieveNode(FxUnit,FLUID_Node);
|
||||||
#define PortIsAudio LADSPA_IS_PORT_AUDIO(CurrentPort_Descriptor) && !(LADSPA_IS_PORT_CONTROL(CurrentPort_Descriptor))
|
#define PortIsAudio LADSPA_IS_PORT_AUDIO(CurrentPort_Descriptor) && !(LADSPA_IS_PORT_CONTROL(CurrentPort_Descriptor))
|
||||||
#define PortIsControl LADSPA_IS_PORT_CONTROL(CurrentPort_Descriptor) && !(LADSPA_IS_PORT_AUDIO(CurrentPort_Descriptor))
|
#define PortIsControl LADSPA_IS_PORT_CONTROL(CurrentPort_Descriptor) && !(LADSPA_IS_PORT_AUDIO(CurrentPort_Descriptor))
|
||||||
if (!Current_Node){
|
if (!Current_Node){
|
||||||
/* Doesn't exist? Then create it. */
|
/* Doesn't exist? Then create it. */
|
||||||
if (FxUnit->NumberNodes>=FLUID_LADSPA_MaxNodes){
|
if (FxUnit->NumberNodes>=FLUID_LADSPA_MaxNodes){
|
||||||
@@ -504,21 +504,21 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
|||||||
"Plugin port number %i is neither input nor output!\n"
|
"Plugin port number %i is neither input nor output!\n"
|
||||||
"This is an error in the plugin.\n"
|
"This is an error in the plugin.\n"
|
||||||
"Please check plugin sourcecode.\n",
|
"Please check plugin sourcecode.\n",
|
||||||
CurrentPort_Index);
|
CurrentPort_Index);
|
||||||
fluid_LADSPA_clear(FxUnit);
|
fluid_LADSPA_clear(FxUnit);
|
||||||
return(PrintErrorMessage);
|
return(PrintErrorMessage);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
assert(Current_Node);
|
assert(Current_Node);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Check flowgraph for some possible errors.
|
* Check flowgraph for some possible errors.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (FLUID_STRCMP(Direction,"->")==0){
|
if (FLUID_STRCMP(Direction,"->")==0){
|
||||||
/* Data from plugin to FLUID, into node
|
/* Data from plugin to FLUID, into node
|
||||||
*
|
*
|
||||||
* *** Rule: ****
|
* *** Rule: ****
|
||||||
* A node may not have more than one data source.*/
|
* A node may not have more than one data source.*/
|
||||||
@@ -530,11 +530,11 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
|||||||
};
|
};
|
||||||
Current_Node->InCount++;
|
Current_Node->InCount++;
|
||||||
} else if (FLUID_STRCMP(Direction,"<-")==0){
|
} else if (FLUID_STRCMP(Direction,"<-")==0){
|
||||||
/* Data from FLUID to plugin, out of node
|
/* Data from FLUID to plugin, out of node
|
||||||
*
|
*
|
||||||
* This check verifies the integrity of the flow graph:
|
* This check verifies the integrity of the flow graph:
|
||||||
* *** Rule ***
|
* *** Rule ***
|
||||||
* The execution order of the plugins is the order, in which they are programmed.
|
* The execution order of the plugins is the order, in which they are programmed.
|
||||||
* The plugins must be ordered so, that the input of a plugin is already computed at the time of its execution.
|
* The plugins must be ordered so, that the input of a plugin is already computed at the time of its execution.
|
||||||
* If the user tries to read data out of a node that has not yet an input, then something is wrong.*/
|
* If the user tries to read data out of a node that has not yet an input, then something is wrong.*/
|
||||||
assert(Current_Node->InCount<=1);
|
assert(Current_Node->InCount<=1);
|
||||||
@@ -542,7 +542,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
|||||||
fluid_ostream_printf(out, "***Error010***\n"
|
fluid_ostream_printf(out, "***Error010***\n"
|
||||||
"Plugin %s tries to read data through input %s from node %s.\n"
|
"Plugin %s tries to read data through input %s from node %s.\n"
|
||||||
"But at this point there is no valid data at that node.\n"
|
"But at this point there is no valid data at that node.\n"
|
||||||
"Please check the flowgraph and especially the execution order!\n",PluginLabel,Plugin_Port,FLUID_Node);
|
"Please check the flowgraph and especially the execution order!\n",PluginLabel,Plugin_Port,FLUID_Node);
|
||||||
fluid_LADSPA_clear(FxUnit);
|
fluid_LADSPA_clear(FxUnit);
|
||||||
return(PrintErrorMessage);
|
return(PrintErrorMessage);
|
||||||
};
|
};
|
||||||
@@ -550,7 +550,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
|||||||
} else {
|
} else {
|
||||||
fluid_ostream_printf(out, "***Error024***\n"
|
fluid_ostream_printf(out, "***Error024***\n"
|
||||||
"Syntax error: Illegal `arrow' `%s', expecting -> or <-\n",
|
"Syntax error: Illegal `arrow' `%s', expecting -> or <-\n",
|
||||||
Direction);
|
Direction);
|
||||||
fluid_LADSPA_clear(FxUnit);
|
fluid_LADSPA_clear(FxUnit);
|
||||||
return(PrintErrorMessage);
|
return(PrintErrorMessage);
|
||||||
};
|
};
|
||||||
@@ -558,7 +558,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
|||||||
/* In any case, there must be a valid data source for the port at this time. */
|
/* In any case, there must be a valid data source for the port at this time. */
|
||||||
assert(Current_Node->InCount==1);
|
assert(Current_Node->InCount==1);
|
||||||
|
|
||||||
/* Keep track on the number of connections to each port.
|
/* Keep track on the number of connections to each port.
|
||||||
* This error occurs only, if an attempt is made to connect one port twice (i.e. ladspa_add libname pluginname port <- nodex port <- nodey) */
|
* This error occurs only, if an attempt is made to connect one port twice (i.e. ladspa_add libname pluginname port <- nodex port <- nodey) */
|
||||||
if (CurrentPlugin_PortConnected[CurrentPort_Index]){
|
if (CurrentPlugin_PortConnected[CurrentPort_Index]){
|
||||||
fluid_ostream_printf(out, "***Error011***\n"
|
fluid_ostream_printf(out, "***Error011***\n"
|
||||||
@@ -570,9 +570,9 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
|||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Connect the port
|
* Connect the port
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
L(fluid_ostream_printf(out,"Connecting %i",CurrentPort_Index));
|
L(fluid_ostream_printf(out,"Connecting %i",CurrentPort_Index));
|
||||||
CurrentPluginDescriptor->connect_port
|
CurrentPluginDescriptor->connect_port
|
||||||
(CurrentPlugin,
|
(CurrentPlugin,
|
||||||
@@ -580,7 +580,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
|||||||
Current_Node->buf
|
Current_Node->buf
|
||||||
);
|
);
|
||||||
CurrentPlugin_PortConnected[CurrentPort_Index]++;
|
CurrentPlugin_PortConnected[CurrentPort_Index]++;
|
||||||
|
|
||||||
}; /* While Tokensequence (more connections) */
|
}; /* While Tokensequence (more connections) */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -588,7 +588,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
|||||||
* Check for left-over tokens
|
* Check for left-over tokens
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (TokenSequence[TokenCount]){
|
if (TokenSequence[TokenCount]){
|
||||||
char * T1="";char * T2="";char * T3="";
|
char * T1="";char * T2="";char * T3="";
|
||||||
if (TokenSequence[TokenCount]){T1=TokenSequence[TokenCount];};
|
if (TokenSequence[TokenCount]){T1=TokenSequence[TokenCount];};
|
||||||
@@ -599,7 +599,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
|||||||
fluid_LADSPA_clear(FxUnit);
|
fluid_LADSPA_clear(FxUnit);
|
||||||
return(PrintErrorMessage);
|
return(PrintErrorMessage);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Check, that all plugin ports are connected
|
* Check, that all plugin ports are connected
|
||||||
@@ -615,7 +615,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
|||||||
return(PrintErrorMessage);
|
return(PrintErrorMessage);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
*Run activate function on plugin, where possible
|
*Run activate function on plugin, where possible
|
||||||
@@ -625,21 +625,21 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
|||||||
if (CurrentPluginDescriptor->activate !=NULL){
|
if (CurrentPluginDescriptor->activate !=NULL){
|
||||||
CurrentPluginDescriptor->activate(CurrentPlugin);
|
CurrentPluginDescriptor->activate(CurrentPlugin);
|
||||||
};
|
};
|
||||||
|
|
||||||
FxUnit->NumberPlugins++;
|
FxUnit->NumberPlugins++;
|
||||||
}; /* For CommandLineCount: once for each new command (i.e. plugin instantiation request from user */
|
}; /* For CommandLineCount: once for each new command (i.e. plugin instantiation request from user */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Further flow graph checks
|
* Further flow graph checks
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
L(fluid_ostream_printf(out,"Checking flow graph"));
|
L(fluid_ostream_printf(out,"Checking flow graph"));
|
||||||
|
|
||||||
IngoingSignalCount=0;
|
IngoingSignalCount=0;
|
||||||
OutgoingSignalCount=0;
|
OutgoingSignalCount=0;
|
||||||
|
|
||||||
for (NodeCount=0; NodeCount<FxUnit->NumberNodes; NodeCount++){
|
for (NodeCount=0; NodeCount<FxUnit->NumberNodes; NodeCount++){
|
||||||
fluid_LADSPA_Node_t* Current_Node;
|
fluid_LADSPA_Node_t* Current_Node;
|
||||||
Current_Node=FxUnit->Nodelist[NodeCount];
|
Current_Node=FxUnit->Nodelist[NodeCount];
|
||||||
@@ -649,8 +649,8 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
|||||||
} else if (Current_Node->flags & fluid_LADSPA_node_is_sink){
|
} else if (Current_Node->flags & fluid_LADSPA_node_is_sink){
|
||||||
OutgoingSignalCount+=Current_Node->InCount;
|
OutgoingSignalCount+=Current_Node->InCount;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* A node without any input doesn't make sense.
|
/* A node without any input doesn't make sense.
|
||||||
* The flow graph check aborts with an error. This case cannot happen.
|
* The flow graph check aborts with an error. This case cannot happen.
|
||||||
*/
|
*/
|
||||||
if (Current_Node->InCount==0 && !Current_Node->flags & fluid_LADSPA_node_is_dummy){ /* There can only be one warning at a time. */
|
if (Current_Node->InCount==0 && !Current_Node->flags & fluid_LADSPA_node_is_dummy){ /* There can only be one warning at a time. */
|
||||||
@@ -658,12 +658,12 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
|||||||
"No input into node %s.\n"
|
"No input into node %s.\n"
|
||||||
"Use '_' as first char in nodename to suppress this warning.\n"
|
"Use '_' as first char in nodename to suppress this warning.\n"
|
||||||
"Hint: Check for typos in the node name.\n",Current_Node->Name);
|
"Hint: Check for typos in the node name.\n",Current_Node->Name);
|
||||||
/* A warning can also be printed as an error message (check fluid_cmd.c). The only difference between
|
/* A warning can also be printed as an error message (check fluid_cmd.c). The only difference between
|
||||||
the return values -1 and 0 is, that -1 prints the result. */
|
the return values -1 and 0 is, that -1 prints the result. */
|
||||||
};
|
};
|
||||||
ReturnVal=PrintErrorMessage;
|
ReturnVal=PrintErrorMessage;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* A node without any output doesn't make sense. */
|
/* A node without any output doesn't make sense. */
|
||||||
if (Current_Node->OutCount==0 && !Current_Node->flags & fluid_LADSPA_node_is_dummy){
|
if (Current_Node->OutCount==0 && !Current_Node->flags & fluid_LADSPA_node_is_dummy){
|
||||||
fluid_ostream_printf(out, "***Warning021***\n"
|
fluid_ostream_printf(out, "***Warning021***\n"
|
||||||
@@ -675,27 +675,27 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream
|
|||||||
/* A free-flying node simply cannot happen. */
|
/* A free-flying node simply cannot happen. */
|
||||||
assert(Current_Node->OutCount+Current_Node->InCount);
|
assert(Current_Node->OutCount+Current_Node->InCount);
|
||||||
}; /* Foreach node */
|
}; /* Foreach node */
|
||||||
|
|
||||||
/* Issue a warning, if no signal goes into the Fx section. */
|
/* Issue a warning, if no signal goes into the Fx section. */
|
||||||
if (IngoingSignalCount==0){
|
if (IngoingSignalCount==0){
|
||||||
fluid_ostream_printf(out, "***Warning022***\n"
|
fluid_ostream_printf(out, "***Warning022***\n"
|
||||||
"You have not connected anything to the synthesizer section (in1_L, in1_R).\n");
|
"You have not connected anything to the synthesizer section (in1_L, in1_R).\n");
|
||||||
ReturnVal=PrintErrorMessage;
|
ReturnVal=PrintErrorMessage;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Issue a warning, if no signal leaves the Fx section. */
|
/* Issue a warning, if no signal leaves the Fx section. */
|
||||||
if (OutgoingSignalCount==0){
|
if (OutgoingSignalCount==0){
|
||||||
fluid_ostream_printf(out, "***Warning023***\n"
|
fluid_ostream_printf(out, "***Warning023***\n"
|
||||||
"You have not connected anything to the output (out1_L, out1_R).\n");
|
"You have not connected anything to the output (out1_L, out1_R).\n");
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Finally turn on the Fx unit. */
|
/* Finally turn on the Fx unit. */
|
||||||
FxUnit->Bypass=fluid_LADSPA_Active;
|
FxUnit->Bypass=fluid_LADSPA_Active;
|
||||||
L(fluid_ostream_printf(out,"LADSPA Init OK"));
|
L(fluid_ostream_printf(out,"LADSPA Init OK"));
|
||||||
return(ReturnVal);
|
return(ReturnVal);
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
fluid_LADSPA_run(fluid_LADSPA_FxUnit_t* FxUnit, fluid_real_t* left_buf[], fluid_real_t* right_buf[], fluid_real_t* fx_left_buf[], fluid_real_t* fx_right_buf[]){
|
fluid_LADSPA_run(fluid_LADSPA_FxUnit_t* FxUnit, fluid_real_t* left_buf[], fluid_real_t* right_buf[], fluid_real_t* fx_left_buf[], fluid_real_t* fx_right_buf[]){
|
||||||
int i;
|
int i;
|
||||||
int ii;
|
int ii;
|
||||||
@@ -719,10 +719,10 @@ fluid_LADSPA_run(fluid_LADSPA_FxUnit_t* FxUnit, fluid_real_t* left_buf[], fluid_
|
|||||||
assert(fluid_settings_getint(FxUnit->synth->settings, "synth.effects-channels", &temp));
|
assert(fluid_settings_getint(FxUnit->synth->settings, "synth.effects-channels", &temp));
|
||||||
nr_fx_sends=temp;
|
nr_fx_sends=temp;
|
||||||
|
|
||||||
/* Fixme: Retrieving nodes via names is inefficient
|
/* Fixme: Retrieving nodes via names is inefficient
|
||||||
* (but not that bad, because the interesting nodes are always at the start of the list).
|
* (but not that bad, because the interesting nodes are always at the start of the list).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Input and output are processed via the same buffers. Therefore the effect is bypassed by just skipping everything else. */
|
/* Input and output are processed via the same buffers. Therefore the effect is bypassed by just skipping everything else. */
|
||||||
if (FxUnit->Bypass==fluid_LADSPA_Bypassed){
|
if (FxUnit->Bypass==fluid_LADSPA_Bypassed){
|
||||||
return;
|
return;
|
||||||
@@ -736,7 +736,7 @@ fluid_LADSPA_run(fluid_LADSPA_FxUnit_t* FxUnit, fluid_real_t* left_buf[], fluid_
|
|||||||
L(printf("LADSPA_Run: Command line asked for bypass of Fx unit. Acknowledged."));
|
L(printf("LADSPA_Run: Command line asked for bypass of Fx unit. Acknowledged."));
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
assert(FxUnit);
|
assert(FxUnit);
|
||||||
|
|
||||||
/* Clear the output buffers, if they are not connected anywhere */
|
/* Clear the output buffers, if they are not connected anywhere */
|
||||||
@@ -756,16 +756,16 @@ fluid_LADSPA_run(fluid_LADSPA_FxUnit_t* FxUnit, fluid_real_t* left_buf[], fluid_
|
|||||||
FLUID_MEMSET(n->buf, 0, byte_size);
|
FLUID_MEMSET(n->buf, 0, byte_size);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Prepare the incoming data:
|
/* Prepare the incoming data:
|
||||||
* Convert fluid_real_t data type to LADSPA_Data type */
|
* Convert fluid_real_t data type to LADSPA_Data type */
|
||||||
for (ii=0; ii < nr_groups; ii++){
|
for (ii=0; ii < nr_groups; ii++){
|
||||||
fluid_real_t* src_buf=left_buf[ii];
|
fluid_real_t* src_buf=left_buf[ii];
|
||||||
sprintf(str, "in%i_L",(ii+1));
|
sprintf(str, "in%i_L",(ii+1));
|
||||||
n=fluid_LADSPA_RetrieveNode(FxUnit, str); assert(n);
|
n=fluid_LADSPA_RetrieveNode(FxUnit, str); assert(n);
|
||||||
|
|
||||||
assert(FLUID_BUFSIZE % 2 == 0);
|
assert(FLUID_BUFSIZE % 2 == 0);
|
||||||
|
|
||||||
/* Add a very small high frequency signal. This avoids denormal number problems. */
|
/* Add a very small high frequency signal. This avoids denormal number problems. */
|
||||||
for (i=0; i<FLUID_BUFSIZE;){
|
for (i=0; i<FLUID_BUFSIZE;){
|
||||||
n->buf[i]=(LADSPA_Data)(src_buf[i]+1.e-15);
|
n->buf[i]=(LADSPA_Data)(src_buf[i]+1.e-15);
|
||||||
@@ -816,7 +816,7 @@ fluid_LADSPA_run(fluid_LADSPA_FxUnit_t* FxUnit, fluid_real_t* left_buf[], fluid_
|
|||||||
for (i=0; i<FLUID_BUFSIZE; i++){
|
for (i=0; i<FLUID_BUFSIZE; i++){
|
||||||
dest_buf[i]=(fluid_real_t)n->buf[i];
|
dest_buf[i]=(fluid_real_t)n->buf[i];
|
||||||
};
|
};
|
||||||
|
|
||||||
dest_buf=right_buf[ii];
|
dest_buf=right_buf[ii];
|
||||||
sprintf(str, "out%i_R",(ii+1));
|
sprintf(str, "out%i_R",(ii+1));
|
||||||
n=fluid_LADSPA_RetrieveNode(FxUnit, str); assert(n);
|
n=fluid_LADSPA_RetrieveNode(FxUnit, str); assert(n);
|
||||||
@@ -826,7 +826,7 @@ fluid_LADSPA_run(fluid_LADSPA_FxUnit_t* FxUnit, fluid_real_t* left_buf[], fluid_
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
fluid_LADSPA_Node_t*
|
fluid_LADSPA_Node_t*
|
||||||
fluid_LADSPA_RetrieveNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name){
|
fluid_LADSPA_RetrieveNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name){
|
||||||
int i=0;
|
int i=0;
|
||||||
assert(FxUnit);assert(Name);
|
assert(FxUnit);assert(Name);
|
||||||
@@ -840,12 +840,12 @@ fluid_LADSPA_RetrieveNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name){
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Purpose:
|
/* Purpose:
|
||||||
* Creates a new node from the node name given by the user.
|
* Creates a new node from the node name given by the user.
|
||||||
*/
|
*/
|
||||||
fluid_LADSPA_Node_t*
|
fluid_LADSPA_Node_t*
|
||||||
fluid_LADSPA_CreateNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name, int flags){
|
fluid_LADSPA_CreateNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name, int flags){
|
||||||
int Dummy=0;
|
int Dummy=0;
|
||||||
fluid_LADSPA_Node_t* NewNode;
|
fluid_LADSPA_Node_t* NewNode;
|
||||||
assert(FxUnit);
|
assert(FxUnit);
|
||||||
assert(Name);
|
assert(Name);
|
||||||
@@ -858,7 +858,7 @@ fluid_LADSPA_CreateNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name, int flags){
|
|||||||
fluid_LADSPA_clear(FxUnit);
|
fluid_LADSPA_clear(FxUnit);
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Don't allow node names, which start with -, 0..9 */
|
/* Don't allow node names, which start with -, 0..9 */
|
||||||
if (Name[0] == '-' || (Name[0]>='0' && Name[0]<='9')){
|
if (Name[0] == '-' || (Name[0]>='0' && Name[0]<='9')){
|
||||||
printf( "***Error026***\n"
|
printf( "***Error026***\n"
|
||||||
@@ -870,7 +870,7 @@ fluid_LADSPA_CreateNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name, int flags){
|
|||||||
fluid_LADSPA_clear(FxUnit);
|
fluid_LADSPA_clear(FxUnit);
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* A nodename starting with "_" is a possible dummy node, which may (but need not) act as a data sink or source (dummy node). */
|
/* A nodename starting with "_" is a possible dummy node, which may (but need not) act as a data sink or source (dummy node). */
|
||||||
if (Name[0] == ' '){ /* ??? Should be '_' ??? */
|
if (Name[0] == ' '){ /* ??? Should be '_' ??? */
|
||||||
Dummy=1;
|
Dummy=1;
|
||||||
@@ -880,7 +880,7 @@ fluid_LADSPA_CreateNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name, int flags){
|
|||||||
/* Audio node contains buffer. */
|
/* Audio node contains buffer. */
|
||||||
NewNode->buf=FLUID_ARRAY(LADSPA_Data, (FLUID_BUFSIZE));assert(NewNode->buf);
|
NewNode->buf=FLUID_ARRAY(LADSPA_Data, (FLUID_BUFSIZE));assert(NewNode->buf);
|
||||||
/* It is permitted to use a dummy node without input. Therefore clear all node buffers at startup. */
|
/* It is permitted to use a dummy node without input. Therefore clear all node buffers at startup. */
|
||||||
FLUID_MEMSET(NewNode->buf, 0, (FLUID_BUFSIZE*sizeof(LADSPA_Data)));
|
FLUID_MEMSET(NewNode->buf, 0, (FLUID_BUFSIZE*sizeof(LADSPA_Data)));
|
||||||
} else if (flags & fluid_LADSPA_node_is_control){
|
} else if (flags & fluid_LADSPA_node_is_control){
|
||||||
/* Control node contains single value. */
|
/* Control node contains single value. */
|
||||||
NewNode->buf=FLUID_ARRAY(LADSPA_Data, 1);assert(NewNode->buf);
|
NewNode->buf=FLUID_ARRAY(LADSPA_Data, 1);assert(NewNode->buf);
|
||||||
@@ -939,7 +939,7 @@ void fluid_LADSPA_clear(fluid_LADSPA_FxUnit_t* FxUnit){
|
|||||||
FLUID_FREE(FxUnit->UserControlNodeNames[i]);
|
FLUID_FREE(FxUnit->UserControlNodeNames[i]);
|
||||||
};
|
};
|
||||||
FxUnit->NumberUserControlNodes=0;
|
FxUnit->NumberUserControlNodes=0;
|
||||||
|
|
||||||
L(printf("Clear all plugin instances"));
|
L(printf("Clear all plugin instances"));
|
||||||
for (i=0; i<FxUnit->NumberPlugins; i++){
|
for (i=0; i<FxUnit->NumberPlugins; i++){
|
||||||
assert(FxUnit->PluginDescriptorTable[i]);
|
assert(FxUnit->PluginDescriptorTable[i]);
|
||||||
@@ -952,14 +952,14 @@ void fluid_LADSPA_clear(fluid_LADSPA_FxUnit_t* FxUnit){
|
|||||||
FxUnit->PluginDescriptorTable[i]->cleanup(FxUnit->PluginInstanceTable[i]);
|
FxUnit->PluginDescriptorTable[i]->cleanup(FxUnit->PluginInstanceTable[i]);
|
||||||
};
|
};
|
||||||
FxUnit->NumberPlugins=0;
|
FxUnit->NumberPlugins=0;
|
||||||
|
|
||||||
L(printf("Clear all nodes")); /* Only after removing plugins! */
|
L(printf("Clear all nodes")); /* Only after removing plugins! */
|
||||||
for (i=0; i<FxUnit->NumberNodes; i++){
|
for (i=0; i<FxUnit->NumberNodes; i++){
|
||||||
FLUID_FREE(FxUnit->Nodelist[i]->buf);
|
FLUID_FREE(FxUnit->Nodelist[i]->buf);
|
||||||
FLUID_FREE(FxUnit->Nodelist[i]);
|
FLUID_FREE(FxUnit->Nodelist[i]);
|
||||||
};
|
};
|
||||||
FxUnit->NumberNodes=0;
|
FxUnit->NumberNodes=0;
|
||||||
|
|
||||||
|
|
||||||
L(printf("Clear all plugin libraries"));
|
L(printf("Clear all plugin libraries"));
|
||||||
for (i=0; i<FxUnit->NumberLibs; i++){
|
for (i=0; i<FxUnit->NumberLibs; i++){
|
||||||
@@ -1012,7 +1012,7 @@ int fluid_LADSPA_handle_add(fluid_synth_t* synth, int ac, char** av, fluid_ostre
|
|||||||
fluid_LADSPA_clear(FxUnit);
|
fluid_LADSPA_clear(FxUnit);
|
||||||
return(PrintErrorMessage);
|
return(PrintErrorMessage);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* CommandLine (token sequence) is terminated with NULL.
|
/* CommandLine (token sequence) is terminated with NULL.
|
||||||
* Add two more NULLs, so that a chunk of three tokens can be checked later without risk.*/
|
* Add two more NULLs, so that a chunk of three tokens can be checked later without risk.*/
|
||||||
|
|
||||||
@@ -1052,7 +1052,7 @@ int fluid_LADSPA_handle_declnode(fluid_synth_t* synth, int ac, char** av, fluid_
|
|||||||
fluid_LADSPA_clear(FxUnit);
|
fluid_LADSPA_clear(FxUnit);
|
||||||
return(PrintErrorMessage);
|
return(PrintErrorMessage);
|
||||||
};
|
};
|
||||||
|
|
||||||
NodeName=FLUID_STRDUP(av[0]); assert(NodeName);
|
NodeName=FLUID_STRDUP(av[0]); assert(NodeName);
|
||||||
NodeValue=atof(av[1]);
|
NodeValue=atof(av[1]);
|
||||||
FxUnit->UserControlNodeNames[FxUnit->NumberUserControlNodes]=NodeName;
|
FxUnit->UserControlNodeNames[FxUnit->NumberUserControlNodes]=NodeName;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -79,7 +79,7 @@ typedef enum {
|
|||||||
fluid_LADSPA_node_is_user_ctrl=32
|
fluid_LADSPA_node_is_user_ctrl=32
|
||||||
} fluid_LADSPA_nodeflags;
|
} fluid_LADSPA_nodeflags;
|
||||||
|
|
||||||
/* fluid_LADSPA_Node_t
|
/* fluid_LADSPA_Node_t
|
||||||
* An internal node of the Fx unit.
|
* An internal node of the Fx unit.
|
||||||
* A 'node' is the 'glue' that connects several LADSPA plugins.
|
* A 'node' is the 'glue' that connects several LADSPA plugins.
|
||||||
* Basically it's a real-valued variable (control node) or a real-valued buffer (audio node).
|
* Basically it's a real-valued variable (control node) or a real-valued buffer (audio node).
|
||||||
@@ -107,11 +107,11 @@ typedef struct {
|
|||||||
int NumberLibs;
|
int NumberLibs;
|
||||||
void * ppvPluginLibs[FLUID_LADSPA_MaxLibs];
|
void * ppvPluginLibs[FLUID_LADSPA_MaxLibs];
|
||||||
char * ppvPluginLibNames[FLUID_LADSPA_MaxLibs];
|
char * ppvPluginLibNames[FLUID_LADSPA_MaxLibs];
|
||||||
|
|
||||||
/*List of plugins (descriptor and instance)
|
/*List of plugins (descriptor and instance)
|
||||||
* A LADSPA plugin descriptor points to the code, which is executed, when a plugin is run.
|
* A LADSPA plugin descriptor points to the code, which is executed, when a plugin is run.
|
||||||
* The plugin instance is given as a parameter, when calling.
|
* The plugin instance is given as a parameter, when calling.
|
||||||
*/
|
*/
|
||||||
int NumberPlugins;
|
int NumberPlugins;
|
||||||
const LADSPA_Descriptor * PluginDescriptorTable[FLUID_LADSPA_MaxPlugins];
|
const LADSPA_Descriptor * PluginDescriptorTable[FLUID_LADSPA_MaxPlugins];
|
||||||
LADSPA_Handle * PluginInstanceTable[FLUID_LADSPA_MaxPlugins];
|
LADSPA_Handle * PluginInstanceTable[FLUID_LADSPA_MaxPlugins];
|
||||||
@@ -119,12 +119,12 @@ typedef struct {
|
|||||||
/* List of nodes */
|
/* List of nodes */
|
||||||
int NumberNodes;
|
int NumberNodes;
|
||||||
fluid_LADSPA_Node_t * Nodelist[FLUID_LADSPA_MaxNodes];
|
fluid_LADSPA_Node_t * Nodelist[FLUID_LADSPA_MaxNodes];
|
||||||
|
|
||||||
/* List of Command lines
|
/* List of Command lines
|
||||||
* During the setup phase, each ladspa_add command creates one command sequence. For example:
|
* During the setup phase, each ladspa_add command creates one command sequence. For example:
|
||||||
* ./aw.so alienwah_stereo Input <- Master_L_Synth Output -> Master_R_Synth Parameter <- #42.0
|
* ./aw.so alienwah_stereo Input <- Master_L_Synth Output -> Master_R_Synth Parameter <- #42.0
|
||||||
* Those lists are stored in LADSPA_Command_Sequence.
|
* Those lists are stored in LADSPA_Command_Sequence.
|
||||||
* One command line results in one plugin => size MaxPlugins.
|
* One command line results in one plugin => size MaxPlugins.
|
||||||
*/
|
*/
|
||||||
int NumberCommands;
|
int NumberCommands;
|
||||||
char ** LADSPA_Command_Sequence[FLUID_LADSPA_MaxPlugins];
|
char ** LADSPA_Command_Sequence[FLUID_LADSPA_MaxPlugins];
|
||||||
@@ -138,11 +138,11 @@ typedef struct {
|
|||||||
|
|
||||||
/* Bypass switch
|
/* Bypass switch
|
||||||
* If set, the LADSPA Fx unit does not touch the signal.*/
|
* If set, the LADSPA Fx unit does not touch the signal.*/
|
||||||
fluid_LADSPA_BypassState Bypass;
|
fluid_LADSPA_BypassState Bypass;
|
||||||
|
|
||||||
/* Communication between the 'command line' process and the synthesis process.
|
/* Communication between the 'command line' process and the synthesis process.
|
||||||
* A possible conflict situation arises, when fluid_clear is called, and starts to destroy
|
* A possible conflict situation arises, when fluid_clear is called, and starts to destroy
|
||||||
* the plugins. But the synthesis thread still processes plugins at the same time. The consequences are ugly.
|
* the plugins. But the synthesis thread still processes plugins at the same time. The consequences are ugly.
|
||||||
* Therefore ladspa_clear waits for acknowledgement from the synthesis thread, that the Fx unit is bypassed.
|
* Therefore ladspa_clear waits for acknowledgement from the synthesis thread, that the Fx unit is bypassed.
|
||||||
* 'cond' is used for the communication, the mutex is required for changing the condition.
|
* 'cond' is used for the communication, the mutex is required for changing the condition.
|
||||||
*/
|
*/
|
||||||
@@ -168,13 +168,13 @@ fluid_LADSPA_FxUnit_t* new_fluid_LADSPA_FxUnit(fluid_synth_t* synth);
|
|||||||
*/
|
*/
|
||||||
void fluid_LADSPA_run(fluid_LADSPA_FxUnit_t* Fx_unit, fluid_real_t* left_buf[], fluid_real_t* right_buf[], fluid_real_t* fx_left_buf[], fluid_real_t* fx_right_buf[]);
|
void fluid_LADSPA_run(fluid_LADSPA_FxUnit_t* Fx_unit, fluid_real_t* left_buf[], fluid_real_t* right_buf[], fluid_real_t* fx_left_buf[], fluid_real_t* fx_right_buf[]);
|
||||||
|
|
||||||
/* Purpose:
|
/* Purpose:
|
||||||
* Returns the node belonging to Name or NULL, if not found
|
* Returns the node belonging to Name or NULL, if not found
|
||||||
*/
|
*/
|
||||||
fluid_LADSPA_Node_t* fluid_LADSPA_RetrieveNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name);
|
fluid_LADSPA_Node_t* fluid_LADSPA_RetrieveNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name);
|
||||||
|
|
||||||
/* Purpose:
|
/* Purpose:
|
||||||
* Creates a new node with the given characteristics.
|
* Creates a new node with the given characteristics.
|
||||||
*/
|
*/
|
||||||
fluid_LADSPA_Node_t* fluid_LADSPA_CreateNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name, int flags);
|
fluid_LADSPA_Node_t* fluid_LADSPA_CreateNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name, int flags);
|
||||||
|
|
||||||
@@ -196,8 +196,8 @@ void fluid_LADSPA_shutdown(fluid_LADSPA_FxUnit_t* FxUnit);
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* fluid_handle_LADSPA_XXX
|
* fluid_handle_LADSPA_XXX
|
||||||
* Those functions are called from fluid_cmd, when a command is entered on the command line.
|
* Those functions are called from fluid_cmd, when a command is entered on the command line.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Purpose:
|
/* Purpose:
|
||||||
@@ -226,12 +226,12 @@ int fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ost
|
|||||||
int fluid_LADSPA_handle_add(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out);
|
int fluid_LADSPA_handle_add(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out);
|
||||||
|
|
||||||
/* Purpose:
|
/* Purpose:
|
||||||
* Declares a user control node and a value; for further processing in ladspa_start.
|
* Declares a user control node and a value; for further processing in ladspa_start.
|
||||||
*/
|
*/
|
||||||
int fluid_LADSPA_handle_declnode(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out);
|
int fluid_LADSPA_handle_declnode(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out);
|
||||||
|
|
||||||
/* Purpose:
|
/* Purpose:
|
||||||
* Assigns a value to the a user control node
|
* Assigns a value to the a user control node
|
||||||
*/
|
*/
|
||||||
int fluid_LADSPA_handle_setnode(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out);
|
int fluid_LADSPA_handle_setnode(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out);
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -73,7 +73,7 @@ fluid_lash_save (fluid_synth_t * synth)
|
|||||||
fluid_sfont_t * sfont;
|
fluid_sfont_t * sfont;
|
||||||
lash_config_t * config;
|
lash_config_t * config;
|
||||||
char num[32];
|
char num[32];
|
||||||
|
|
||||||
sfcount = fluid_synth_sfcount (synth);
|
sfcount = fluid_synth_sfcount (synth);
|
||||||
|
|
||||||
config = lash_config_new ();
|
config = lash_config_new ();
|
||||||
@@ -85,12 +85,12 @@ fluid_lash_save (fluid_synth_t * synth)
|
|||||||
{
|
{
|
||||||
sfont = fluid_synth_get_sfont (synth, i);
|
sfont = fluid_synth_get_sfont (synth, i);
|
||||||
config = lash_config_new ();
|
config = lash_config_new ();
|
||||||
|
|
||||||
sprintf (num, "%d", i);
|
sprintf (num, "%d", i);
|
||||||
|
|
||||||
lash_config_set_key (config, num);
|
lash_config_set_key (config, num);
|
||||||
lash_config_set_value_string (config, sfont->get_name (sfont));
|
lash_config_set_value_string (config, sfont->get_name (sfont));
|
||||||
|
|
||||||
lash_send_config (fluid_lash_client, config);
|
lash_send_config (fluid_lash_client, config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -110,11 +110,11 @@ fluid_lash_run (void * data)
|
|||||||
int done = 0;
|
int done = 0;
|
||||||
int err;
|
int err;
|
||||||
int pending_restores = 0;
|
int pending_restores = 0;
|
||||||
|
|
||||||
synth = (fluid_synth_t *) data;
|
synth = (fluid_synth_t *) data;
|
||||||
|
|
||||||
while (!done)
|
while (!done)
|
||||||
{
|
{
|
||||||
while ( (event = lash_get_event (fluid_lash_client)) )
|
while ( (event = lash_get_event (fluid_lash_client)) )
|
||||||
{
|
{
|
||||||
switch (lash_event_get_type (event))
|
switch (lash_event_get_type (event))
|
||||||
@@ -144,7 +144,7 @@ fluid_lash_run (void * data)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while ( (config = lash_get_config (fluid_lash_client)) )
|
while ( (config = lash_get_config (fluid_lash_client)) )
|
||||||
{
|
{
|
||||||
if (strcmp (lash_config_get_key (config), "soundfont count") == 0)
|
if (strcmp (lash_config_get_key (config), "soundfont count") == 0)
|
||||||
@@ -162,10 +162,10 @@ fluid_lash_run (void * data)
|
|||||||
lash_send_event (fluid_lash_client, event);
|
lash_send_event (fluid_lash_client, event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
usleep (10000);
|
usleep (10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,7 +200,7 @@ fluid_lash_save (fluid_synth_t * synth)
|
|||||||
fluid_sfont_t * sfont;
|
fluid_sfont_t * sfont;
|
||||||
cca_config_t * config;
|
cca_config_t * config;
|
||||||
char num[32];
|
char num[32];
|
||||||
|
|
||||||
sfcount = fluid_synth_sfcount (synth);
|
sfcount = fluid_synth_sfcount (synth);
|
||||||
|
|
||||||
config = cca_config_new ();
|
config = cca_config_new ();
|
||||||
@@ -212,12 +212,12 @@ fluid_lash_save (fluid_synth_t * synth)
|
|||||||
{
|
{
|
||||||
sfont = fluid_synth_get_sfont (synth, i);
|
sfont = fluid_synth_get_sfont (synth, i);
|
||||||
config = cca_config_new ();
|
config = cca_config_new ();
|
||||||
|
|
||||||
sprintf (num, "%d", i);
|
sprintf (num, "%d", i);
|
||||||
|
|
||||||
cca_config_set_key (config, num);
|
cca_config_set_key (config, num);
|
||||||
cca_config_set_value_string (config, sfont->get_name (sfont));
|
cca_config_set_value_string (config, sfont->get_name (sfont));
|
||||||
|
|
||||||
cca_send_config (fluid_lash_client, config);
|
cca_send_config (fluid_lash_client, config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -238,9 +238,9 @@ fluid_lash_run (void * data)
|
|||||||
int done = 0;
|
int done = 0;
|
||||||
int err;
|
int err;
|
||||||
int pending_restores = 0;
|
int pending_restores = 0;
|
||||||
|
|
||||||
synth = (fluid_synth_t *) data;
|
synth = (fluid_synth_t *) data;
|
||||||
|
|
||||||
while (!done)
|
while (!done)
|
||||||
{
|
{
|
||||||
while ( (event = cca_get_event (fluid_lash_client)) )
|
while ( (event = cca_get_event (fluid_lash_client)) )
|
||||||
@@ -272,7 +272,7 @@ fluid_lash_run (void * data)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while ( (config = cca_get_config (fluid_lash_client)) )
|
while ( (config = cca_get_config (fluid_lash_client)) )
|
||||||
{
|
{
|
||||||
if (strcmp (cca_config_get_key (config), "soundfont count") == 0)
|
if (strcmp (cca_config_get_key (config), "soundfont count") == 0)
|
||||||
@@ -290,10 +290,10 @@ fluid_lash_run (void * data)
|
|||||||
cca_send_event (fluid_lash_client, event);
|
cca_send_event (fluid_lash_client, event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
usleep (10000);
|
usleep (10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,13 +11,15 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
* 02111-1307, USA
|
* 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_LASH) || defined(HAVE_LADCCA)
|
#if defined(HAVE_LASH) || defined(HAVE_LADCCA)
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
* Modified by the GLib Team and others 1997-1999. See the AUTHORS
|
* Modified by the GLib Team and others 1997-1999. See the AUTHORS
|
||||||
* file for a list of people on the GLib Team. See the ChangeLog
|
* file for a list of people on the GLib Team. See the ChangeLog
|
||||||
* files for a list of changes. These files are distributed with
|
* files for a list of changes. These files are distributed with
|
||||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -120,10 +120,10 @@ fluid_list_remove(fluid_list_t *list, void* data)
|
|||||||
}
|
}
|
||||||
tmp->next = NULL;
|
tmp->next = NULL;
|
||||||
delete_fluid_list(tmp);
|
delete_fluid_list(tmp);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
prev = tmp;
|
prev = tmp;
|
||||||
tmp = tmp->next;
|
tmp = tmp->next;
|
||||||
}
|
}
|
||||||
@@ -151,15 +151,15 @@ fluid_list_remove_link(fluid_list_t *list, fluid_list_t *link)
|
|||||||
tmp->next = NULL;
|
tmp->next = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
prev = tmp;
|
prev = tmp;
|
||||||
tmp = tmp->next;
|
tmp = tmp->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fluid_list_t*
|
static fluid_list_t*
|
||||||
fluid_list_sort_merge(fluid_list_t *l1, fluid_list_t *l2, fluid_compare_func_t compare_func)
|
fluid_list_sort_merge(fluid_list_t *l1, fluid_list_t *l2, fluid_compare_func_t compare_func)
|
||||||
{
|
{
|
||||||
fluid_list_t list, *l;
|
fluid_list_t list, *l;
|
||||||
@@ -176,11 +176,11 @@ fluid_list_sort_merge(fluid_list_t *l1, fluid_list_t *l2, fluid_compare_func_t c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
l->next= l1 ? l1 : l2;
|
l->next= l1 ? l1 : l2;
|
||||||
|
|
||||||
return list.next;
|
return list.next;
|
||||||
}
|
}
|
||||||
|
|
||||||
fluid_list_t*
|
fluid_list_t*
|
||||||
fluid_list_sort(fluid_list_t *list, fluid_compare_func_t compare_func)
|
fluid_list_sort(fluid_list_t *list, fluid_compare_func_t compare_func)
|
||||||
{
|
{
|
||||||
fluid_list_t *l1, *l2;
|
fluid_list_t *l1, *l2;
|
||||||
@@ -192,15 +192,15 @@ fluid_list_sort(fluid_list_t *list, fluid_compare_func_t compare_func)
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
l1 = list;
|
l1 = list;
|
||||||
l2 = list->next;
|
l2 = list->next;
|
||||||
|
|
||||||
while ((l2 = l2->next) != NULL) {
|
while ((l2 = l2->next) != NULL) {
|
||||||
if ((l2 = l2->next) == NULL)
|
if ((l2 = l2->next) == NULL)
|
||||||
break;
|
break;
|
||||||
l1=l1->next;
|
l1=l1->next;
|
||||||
}
|
}
|
||||||
l2 = l1->next;
|
l2 = l1->next;
|
||||||
l1->next = NULL;
|
l1->next = NULL;
|
||||||
|
|
||||||
return fluid_list_sort_merge(fluid_list_sort(list, compare_func),
|
return fluid_list_sort_merge(fluid_list_sort(list, compare_func),
|
||||||
@@ -220,7 +220,7 @@ fluid_list_last(fluid_list_t *list)
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
fluid_list_size(fluid_list_t *list)
|
fluid_list_size(fluid_list_t *list)
|
||||||
{
|
{
|
||||||
int n = 0;
|
int n = 0;
|
||||||
@@ -249,7 +249,7 @@ fluid_list_t* fluid_list_insert_at(fluid_list_t *list, int n, void* data)
|
|||||||
new_list->next = cur;
|
new_list->next = cur;
|
||||||
|
|
||||||
if (prev) {
|
if (prev) {
|
||||||
prev->next = new_list;
|
prev->next = new_list;
|
||||||
return list;
|
return list;
|
||||||
} else {
|
} else {
|
||||||
return new_list;
|
return new_list;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -25,13 +25,13 @@
|
|||||||
/* ALSA */
|
/* ALSA */
|
||||||
#if ALSA_SUPPORT
|
#if ALSA_SUPPORT
|
||||||
fluid_midi_driver_t* new_fluid_alsa_rawmidi_driver(fluid_settings_t* settings,
|
fluid_midi_driver_t* new_fluid_alsa_rawmidi_driver(fluid_settings_t* settings,
|
||||||
handle_midi_event_func_t handler,
|
handle_midi_event_func_t handler,
|
||||||
void* event_handler_data);
|
void* event_handler_data);
|
||||||
int delete_fluid_alsa_rawmidi_driver(fluid_midi_driver_t* p);
|
int delete_fluid_alsa_rawmidi_driver(fluid_midi_driver_t* p);
|
||||||
void fluid_alsa_rawmidi_driver_settings(fluid_settings_t* settings);
|
void fluid_alsa_rawmidi_driver_settings(fluid_settings_t* settings);
|
||||||
|
|
||||||
fluid_midi_driver_t* new_fluid_alsa_seq_driver(fluid_settings_t* settings,
|
fluid_midi_driver_t* new_fluid_alsa_seq_driver(fluid_settings_t* settings,
|
||||||
handle_midi_event_func_t handler,
|
handle_midi_event_func_t handler,
|
||||||
void* event_handler_data);
|
void* event_handler_data);
|
||||||
int delete_fluid_alsa_seq_driver(fluid_midi_driver_t* p);
|
int delete_fluid_alsa_seq_driver(fluid_midi_driver_t* p);
|
||||||
void fluid_alsa_seq_driver_settings(fluid_settings_t* settings);
|
void fluid_alsa_seq_driver_settings(fluid_settings_t* settings);
|
||||||
@@ -40,7 +40,7 @@ void fluid_alsa_seq_driver_settings(fluid_settings_t* settings);
|
|||||||
/* OSS */
|
/* OSS */
|
||||||
#if OSS_SUPPORT
|
#if OSS_SUPPORT
|
||||||
fluid_midi_driver_t* new_fluid_oss_midi_driver(fluid_settings_t* settings,
|
fluid_midi_driver_t* new_fluid_oss_midi_driver(fluid_settings_t* settings,
|
||||||
handle_midi_event_func_t handler,
|
handle_midi_event_func_t handler,
|
||||||
void* event_handler_data);
|
void* event_handler_data);
|
||||||
int delete_fluid_oss_midi_driver(fluid_midi_driver_t* p);
|
int delete_fluid_oss_midi_driver(fluid_midi_driver_t* p);
|
||||||
void fluid_oss_midi_driver_settings(fluid_settings_t* settings);
|
void fluid_oss_midi_driver_settings(fluid_settings_t* settings);
|
||||||
@@ -49,7 +49,7 @@ void fluid_oss_midi_driver_settings(fluid_settings_t* settings);
|
|||||||
/* Windows MIDI service */
|
/* Windows MIDI service */
|
||||||
#if WINMIDI_SUPPORT
|
#if WINMIDI_SUPPORT
|
||||||
fluid_midi_driver_t* new_fluid_winmidi_driver(fluid_settings_t* settings,
|
fluid_midi_driver_t* new_fluid_winmidi_driver(fluid_settings_t* settings,
|
||||||
handle_midi_event_func_t handler,
|
handle_midi_event_func_t handler,
|
||||||
void* event_handler_data);
|
void* event_handler_data);
|
||||||
int delete_fluid_winmidi_driver(fluid_midi_driver_t* p);
|
int delete_fluid_winmidi_driver(fluid_midi_driver_t* p);
|
||||||
#endif
|
#endif
|
||||||
@@ -57,7 +57,7 @@ int delete_fluid_winmidi_driver(fluid_midi_driver_t* p);
|
|||||||
/* definitions for the MidiShare driver */
|
/* definitions for the MidiShare driver */
|
||||||
#if MIDISHARE_SUPPORT
|
#if MIDISHARE_SUPPORT
|
||||||
fluid_midi_driver_t* new_fluid_midishare_midi_driver(fluid_settings_t* settings,
|
fluid_midi_driver_t* new_fluid_midishare_midi_driver(fluid_settings_t* settings,
|
||||||
void* event_handler_data,
|
void* event_handler_data,
|
||||||
handle_midi_event_func_t handler);
|
handle_midi_event_func_t handler);
|
||||||
int delete_fluid_midishare_midi_driver(fluid_midi_driver_t* p);
|
int delete_fluid_midishare_midi_driver(fluid_midi_driver_t* p);
|
||||||
#endif
|
#endif
|
||||||
@@ -69,8 +69,8 @@ int delete_fluid_midishare_midi_driver(fluid_midi_driver_t* p);
|
|||||||
*/
|
*/
|
||||||
struct fluid_mdriver_definition_t {
|
struct fluid_mdriver_definition_t {
|
||||||
char* name;
|
char* name;
|
||||||
fluid_midi_driver_t* (*new)(fluid_settings_t* settings,
|
fluid_midi_driver_t* (*new)(fluid_settings_t* settings,
|
||||||
handle_midi_event_func_t event_handler,
|
handle_midi_event_func_t event_handler,
|
||||||
void* event_handler_data);
|
void* event_handler_data);
|
||||||
int (*free)(fluid_midi_driver_t* p);
|
int (*free)(fluid_midi_driver_t* p);
|
||||||
void (*settings)(fluid_settings_t* settings);
|
void (*settings)(fluid_settings_t* settings);
|
||||||
@@ -79,31 +79,31 @@ struct fluid_mdriver_definition_t {
|
|||||||
|
|
||||||
struct fluid_mdriver_definition_t fluid_midi_drivers[] = {
|
struct fluid_mdriver_definition_t fluid_midi_drivers[] = {
|
||||||
#if OSS_SUPPORT
|
#if OSS_SUPPORT
|
||||||
{ "oss",
|
{ "oss",
|
||||||
new_fluid_oss_midi_driver,
|
new_fluid_oss_midi_driver,
|
||||||
delete_fluid_oss_midi_driver,
|
delete_fluid_oss_midi_driver,
|
||||||
fluid_oss_midi_driver_settings },
|
fluid_oss_midi_driver_settings },
|
||||||
#endif
|
#endif
|
||||||
#if ALSA_SUPPORT
|
#if ALSA_SUPPORT
|
||||||
{ "alsa_raw",
|
{ "alsa_raw",
|
||||||
new_fluid_alsa_rawmidi_driver,
|
new_fluid_alsa_rawmidi_driver,
|
||||||
delete_fluid_alsa_rawmidi_driver,
|
delete_fluid_alsa_rawmidi_driver,
|
||||||
fluid_alsa_rawmidi_driver_settings },
|
fluid_alsa_rawmidi_driver_settings },
|
||||||
{ "alsa_seq",
|
{ "alsa_seq",
|
||||||
new_fluid_alsa_seq_driver,
|
new_fluid_alsa_seq_driver,
|
||||||
delete_fluid_alsa_seq_driver,
|
delete_fluid_alsa_seq_driver,
|
||||||
fluid_alsa_seq_driver_settings },
|
fluid_alsa_seq_driver_settings },
|
||||||
#endif
|
#endif
|
||||||
#if WINMIDI_SUPPORT
|
#if WINMIDI_SUPPORT
|
||||||
{ "winmidi",
|
{ "winmidi",
|
||||||
new_fluid_winmidi_driver,
|
new_fluid_winmidi_driver,
|
||||||
delete_fluid_winmidi_driver,
|
delete_fluid_winmidi_driver,
|
||||||
NULL },
|
NULL },
|
||||||
#endif
|
#endif
|
||||||
#if MIDISHARE_SUPPORT
|
#if MIDISHARE_SUPPORT
|
||||||
{ "midishare",
|
{ "midishare",
|
||||||
new_fluid_midishare_midi_driver,
|
new_fluid_midishare_midi_driver,
|
||||||
delete_fluid_midishare_midi_driver,
|
delete_fluid_midishare_midi_driver,
|
||||||
NULL },
|
NULL },
|
||||||
#endif
|
#endif
|
||||||
{ NULL, NULL, NULL, NULL }
|
{ NULL, NULL, NULL, NULL }
|
||||||
@@ -112,7 +112,7 @@ struct fluid_mdriver_definition_t fluid_midi_drivers[] = {
|
|||||||
|
|
||||||
|
|
||||||
void fluid_midi_driver_settings(fluid_settings_t* settings)
|
void fluid_midi_driver_settings(fluid_settings_t* settings)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Set the default driver */
|
/* Set the default driver */
|
||||||
@@ -147,11 +147,18 @@ void fluid_midi_driver_settings(fluid_settings_t* settings)
|
|||||||
if (fluid_midi_drivers[i].settings != NULL) {
|
if (fluid_midi_drivers[i].settings != NULL) {
|
||||||
fluid_midi_drivers[i].settings(settings);
|
fluid_midi_drivers[i].settings(settings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new MIDI driver instance.
|
||||||
|
* @param settings Settings used to configure new MIDI driver.
|
||||||
|
* @param handler MIDI handler callback (for example: fluid_midi_router_handle_midi_event()
|
||||||
|
* for MIDI router)
|
||||||
|
* @param event_handler_data Caller defined data to pass to 'handler'
|
||||||
|
* @return New MIDI driver instance or NULL on error
|
||||||
|
*/
|
||||||
fluid_midi_driver_t* new_fluid_midi_driver(fluid_settings_t* settings, handle_midi_event_func_t handler, void* event_handler_data)
|
fluid_midi_driver_t* new_fluid_midi_driver(fluid_settings_t* settings, handle_midi_event_func_t handler, void* event_handler_data)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -171,6 +178,10 @@ fluid_midi_driver_t* new_fluid_midi_driver(fluid_settings_t* settings, handle_mi
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a MIDI driver instance.
|
||||||
|
* @param driver MIDI driver to delete
|
||||||
|
*/
|
||||||
void delete_fluid_midi_driver(fluid_midi_driver_t* driver)
|
void delete_fluid_midi_driver(fluid_midi_driver_t* driver)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -180,5 +191,5 @@ void delete_fluid_midi_driver(fluid_midi_driver_t* driver)
|
|||||||
fluid_midi_drivers[i].free(driver);
|
fluid_midi_drivers[i].free(driver);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -30,7 +30,7 @@ void fluid_midi_driver_settings(fluid_settings_t* settings);
|
|||||||
* fluid_midi_driver_t
|
* fluid_midi_driver_t
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct _fluid_midi_driver_t
|
struct _fluid_midi_driver_t
|
||||||
{
|
{
|
||||||
char* name;
|
char* name;
|
||||||
handle_midi_event_func_t handler;
|
handle_midi_event_func_t handler;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -55,8 +55,12 @@ static int remains_80e0[] = {
|
|||||||
*
|
*
|
||||||
* MIDIFILE
|
* MIDIFILE
|
||||||
*/
|
*/
|
||||||
/*
|
|
||||||
* new_fluid_midi_file
|
/**
|
||||||
|
* Open a MIDI file and return a new MIDI file handle.
|
||||||
|
* @internal
|
||||||
|
* @param filename Path of file to open.
|
||||||
|
* @return New MIDI file handle or NULL on error.
|
||||||
*/
|
*/
|
||||||
fluid_midi_file* new_fluid_midi_file(char* filename)
|
fluid_midi_file* new_fluid_midi_file(char* filename)
|
||||||
{
|
{
|
||||||
@@ -76,7 +80,7 @@ fluid_midi_file* new_fluid_midi_file(char* filename)
|
|||||||
if (mf->fp == NULL) {
|
if (mf->fp == NULL) {
|
||||||
FLUID_LOG(FLUID_ERR, "Couldn't open the MIDI file");
|
FLUID_LOG(FLUID_ERR, "Couldn't open the MIDI file");
|
||||||
FLUID_FREE(mf);
|
FLUID_FREE(mf);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fluid_midi_file_read_mthd(mf) != FLUID_OK) {
|
if (fluid_midi_file_read_mthd(mf) != FLUID_OK) {
|
||||||
@@ -86,8 +90,10 @@ fluid_midi_file* new_fluid_midi_file(char* filename)
|
|||||||
return mf;
|
return mf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* delete_fluid_midi_file
|
* Delete a MIDI file handle.
|
||||||
|
* @internal
|
||||||
|
* @param mf MIDI file handle to close and free.
|
||||||
*/
|
*/
|
||||||
void delete_fluid_midi_file(fluid_midi_file* mf)
|
void delete_fluid_midi_file(fluid_midi_file* mf)
|
||||||
{
|
{
|
||||||
@@ -102,7 +108,7 @@ void delete_fluid_midi_file(fluid_midi_file* mf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* fluid_midi_file_getc
|
* Get the next byte in a MIDI file.
|
||||||
*/
|
*/
|
||||||
int fluid_midi_file_getc(fluid_midi_file* mf)
|
int fluid_midi_file_getc(fluid_midi_file* mf)
|
||||||
{
|
{
|
||||||
@@ -150,7 +156,7 @@ int fluid_midi_file_skip(fluid_midi_file* mf, int skip)
|
|||||||
int err = FLUID_FSEEK(mf->fp, skip, SEEK_CUR);
|
int err = FLUID_FSEEK(mf->fp, skip, SEEK_CUR);
|
||||||
if (err) {
|
if (err) {
|
||||||
FLUID_LOG(FLUID_ERR, "Failed to seek position in file");
|
FLUID_LOG(FLUID_ERR, "Failed to seek position in file");
|
||||||
return FLUID_FAILED;
|
return FLUID_FAILED;
|
||||||
}
|
}
|
||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
@@ -289,7 +295,7 @@ int fluid_midi_file_read_track(fluid_midi_file* mf, fluid_player_t* player, int
|
|||||||
|
|
||||||
while (!fluid_midi_file_eot(mf)) {
|
while (!fluid_midi_file_eot(mf)) {
|
||||||
if (fluid_midi_file_read_event(mf, track) != FLUID_OK) {
|
if (fluid_midi_file_read_event(mf, track) != FLUID_OK) {
|
||||||
return FLUID_FAILED;
|
return FLUID_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,7 +324,7 @@ int fluid_midi_file_read_track(fluid_midi_file* mf, fluid_player_t* player, int
|
|||||||
* fluid_midi_file_read_varlen
|
* fluid_midi_file_read_varlen
|
||||||
*/
|
*/
|
||||||
int fluid_midi_file_read_varlen(fluid_midi_file* mf)
|
int fluid_midi_file_read_varlen(fluid_midi_file* mf)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int c;
|
int c;
|
||||||
mf->varlen = 0;
|
mf->varlen = 0;
|
||||||
@@ -338,7 +344,7 @@ int fluid_midi_file_read_varlen(fluid_midi_file* mf)
|
|||||||
} else {
|
} else {
|
||||||
mf->varlen += c;
|
mf->varlen += c;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
@@ -382,7 +388,7 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track)
|
|||||||
}
|
}
|
||||||
fluid_midi_file_push(mf, status);
|
fluid_midi_file_push(mf, status);
|
||||||
status = mf->running_status;
|
status = mf->running_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check what message we have */
|
/* check what message we have */
|
||||||
if (status & 0x80) {
|
if (status & 0x80) {
|
||||||
@@ -426,7 +432,7 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
|
|
||||||
} else if (status == MIDI_META_EVENT) { /* meta events */
|
} else if (status == MIDI_META_EVENT) { /* meta events */
|
||||||
|
|
||||||
int result = FLUID_OK;
|
int result = FLUID_OK;
|
||||||
@@ -498,7 +504,7 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
mf->eot = 1;
|
mf->eot = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MIDI_SET_TEMPO:
|
case MIDI_SET_TEMPO:
|
||||||
if (mf->varlen != 3) {
|
if (mf->varlen != 3) {
|
||||||
@@ -519,7 +525,7 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track)
|
|||||||
evt->param1 = tempo;
|
evt->param1 = tempo;
|
||||||
evt->param2 = 0;
|
evt->param2 = 0;
|
||||||
fluid_track_add_event(track, evt);
|
fluid_track_add_event(track, evt);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MIDI_SMPTE_OFFSET:
|
case MIDI_SMPTE_OFFSET:
|
||||||
if (mf->varlen != 5) {
|
if (mf->varlen != 5) {
|
||||||
@@ -527,7 +533,7 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track)
|
|||||||
result = FLUID_FAILED;
|
result = FLUID_FAILED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break; /* we don't use smtp */
|
break; /* we don't use smtp */
|
||||||
|
|
||||||
case MIDI_TIME_SIGNATURE:
|
case MIDI_TIME_SIGNATURE:
|
||||||
if (mf->varlen != 4) {
|
if (mf->varlen != 4) {
|
||||||
@@ -540,7 +546,7 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track)
|
|||||||
clocks = metadata[2];
|
clocks = metadata[2];
|
||||||
notes = metadata[3];
|
notes = metadata[3];
|
||||||
|
|
||||||
FLUID_LOG(FLUID_DBG, "signature=%d/%d, metronome=%d, 32nd-notes=%d",
|
FLUID_LOG(FLUID_DBG, "signature=%d/%d, metronome=%d, 32nd-notes=%d",
|
||||||
nominator, denominator, clocks, notes);
|
nominator, denominator, clocks, notes);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -568,7 +574,7 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
} else { /* channel messages */
|
} else { /* channel messages */
|
||||||
|
|
||||||
type = status & 0xf0;
|
type = status & 0xf0;
|
||||||
@@ -589,7 +595,7 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NOTE_OFF:
|
case NOTE_OFF:
|
||||||
if ((param2 = fluid_midi_file_getc(mf)) < 0) {
|
if ((param2 = fluid_midi_file_getc(mf)) < 0) {
|
||||||
FLUID_LOG(FLUID_ERR, "Unexpected end of file");
|
FLUID_LOG(FLUID_ERR, "Unexpected end of file");
|
||||||
return FLUID_FAILED;
|
return FLUID_FAILED;
|
||||||
@@ -629,7 +635,7 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track)
|
|||||||
default:
|
default:
|
||||||
/* Can't possibly happen !? */
|
/* Can't possibly happen !? */
|
||||||
FLUID_LOG(FLUID_ERR, "Unrecognized MIDI event");
|
FLUID_LOG(FLUID_ERR, "Unrecognized MIDI event");
|
||||||
return FLUID_FAILED;
|
return FLUID_FAILED;
|
||||||
}
|
}
|
||||||
evt = new_fluid_midi_event();
|
evt = new_fluid_midi_event();
|
||||||
if (evt == NULL) {
|
if (evt == NULL) {
|
||||||
@@ -660,8 +666,9 @@ int fluid_midi_file_get_division(fluid_midi_file* midifile)
|
|||||||
* fluid_track_t
|
* fluid_track_t
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* new_fluid_midi_event
|
* Create a MIDI event structure.
|
||||||
|
* @return New MIDI event structure or NULL when out of memory.
|
||||||
*/
|
*/
|
||||||
fluid_midi_event_t* new_fluid_midi_event()
|
fluid_midi_event_t* new_fluid_midi_event()
|
||||||
{
|
{
|
||||||
@@ -680,8 +687,10 @@ fluid_midi_event_t* new_fluid_midi_event()
|
|||||||
return evt;
|
return evt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* delete_fluid_midi_event
|
* Delete MIDI event structure.
|
||||||
|
* @param evt MIDI event structure
|
||||||
|
* @return Always returns 0
|
||||||
*/
|
*/
|
||||||
int delete_fluid_midi_event(fluid_midi_event_t* evt)
|
int delete_fluid_midi_event(fluid_midi_event_t* evt)
|
||||||
{
|
{
|
||||||
@@ -696,16 +705,23 @@ int delete_fluid_midi_event(fluid_midi_event_t* evt)
|
|||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* fluid_midi_event_get_type
|
* Get the event type field of a MIDI event structure.
|
||||||
|
* DOCME - Event type enum appears to be internal (fluid_midi.h)
|
||||||
|
* @param evt MIDI event structure
|
||||||
|
* @return Event type field
|
||||||
*/
|
*/
|
||||||
int fluid_midi_event_get_type(fluid_midi_event_t* evt)
|
int fluid_midi_event_get_type(fluid_midi_event_t* evt)
|
||||||
{
|
{
|
||||||
return evt->type;
|
return evt->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* fluid_midi_event_set_type
|
* Set the event type field of a MIDI event structure.
|
||||||
|
* DOCME - Event type enum appears to be internal (fluid_midi.h)
|
||||||
|
* @param evt MIDI event structure
|
||||||
|
* @param type Event type field
|
||||||
|
* @return Always returns 0
|
||||||
*/
|
*/
|
||||||
int fluid_midi_event_set_type(fluid_midi_event_t* evt, int type)
|
int fluid_midi_event_set_type(fluid_midi_event_t* evt, int type)
|
||||||
{
|
{
|
||||||
@@ -713,16 +729,21 @@ int fluid_midi_event_set_type(fluid_midi_event_t* evt, int type)
|
|||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* fluid_midi_event_get_channel
|
* Get the channel field of a MIDI event structure.
|
||||||
|
* @param evt MIDI event structure
|
||||||
|
* @return Channel field
|
||||||
*/
|
*/
|
||||||
int fluid_midi_event_get_channel(fluid_midi_event_t* evt)
|
int fluid_midi_event_get_channel(fluid_midi_event_t* evt)
|
||||||
{
|
{
|
||||||
return evt->channel;
|
return evt->channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* fluid_midi_event_set_channel
|
* Set the channel field of a MIDI event structure.
|
||||||
|
* @param evt MIDI event structure
|
||||||
|
* @param chan MIDI channel field
|
||||||
|
* @return Always returns 0
|
||||||
*/
|
*/
|
||||||
int fluid_midi_event_set_channel(fluid_midi_event_t* evt, int chan)
|
int fluid_midi_event_set_channel(fluid_midi_event_t* evt, int chan)
|
||||||
{
|
{
|
||||||
@@ -730,16 +751,21 @@ int fluid_midi_event_set_channel(fluid_midi_event_t* evt, int chan)
|
|||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* fluid_midi_event_get_key
|
* Get the key field of a MIDI event structure.
|
||||||
|
* @param evt MIDI event structure
|
||||||
|
* @return MIDI note number (0-127)
|
||||||
*/
|
*/
|
||||||
int fluid_midi_event_get_key(fluid_midi_event_t* evt)
|
int fluid_midi_event_get_key(fluid_midi_event_t* evt)
|
||||||
{
|
{
|
||||||
return evt->param1;
|
return evt->param1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* fluid_midi_event_set_key
|
* Set the key field of a MIDI event structure.
|
||||||
|
* @param evt MIDI event structure
|
||||||
|
* @param v MIDI note number (0-127)
|
||||||
|
* @return Always returns 0
|
||||||
*/
|
*/
|
||||||
int fluid_midi_event_set_key(fluid_midi_event_t* evt, int v)
|
int fluid_midi_event_set_key(fluid_midi_event_t* evt, int v)
|
||||||
{
|
{
|
||||||
@@ -747,16 +773,21 @@ int fluid_midi_event_set_key(fluid_midi_event_t* evt, int v)
|
|||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* fluid_midi_event_get_velocity
|
* Get the velocity field of a MIDI event structure.
|
||||||
|
* @param evt MIDI event structure
|
||||||
|
* @return MIDI velocity number (0-127)
|
||||||
*/
|
*/
|
||||||
int fluid_midi_event_get_velocity(fluid_midi_event_t* evt)
|
int fluid_midi_event_get_velocity(fluid_midi_event_t* evt)
|
||||||
{
|
{
|
||||||
return evt->param2;
|
return evt->param2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* fluid_midi_event_set_velocity
|
* Set the velocity field of a MIDI event structure.
|
||||||
|
* @param evt MIDI event structure
|
||||||
|
* @param v MIDI velocity value
|
||||||
|
* @return Always returns 0
|
||||||
*/
|
*/
|
||||||
int fluid_midi_event_set_velocity(fluid_midi_event_t* evt, int v)
|
int fluid_midi_event_set_velocity(fluid_midi_event_t* evt, int v)
|
||||||
{
|
{
|
||||||
@@ -764,16 +795,21 @@ int fluid_midi_event_set_velocity(fluid_midi_event_t* evt, int v)
|
|||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* fluid_midi_event_get_control
|
* Get the control number of a MIDI event structure.
|
||||||
|
* @param evt MIDI event structure
|
||||||
|
* @return MIDI control number
|
||||||
*/
|
*/
|
||||||
int fluid_midi_event_get_control(fluid_midi_event_t* evt)
|
int fluid_midi_event_get_control(fluid_midi_event_t* evt)
|
||||||
{
|
{
|
||||||
return evt->param1;
|
return evt->param1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* fluid_midi_event_set_control
|
* Set the control field of a MIDI event structure.
|
||||||
|
* @param evt MIDI event structure
|
||||||
|
* @param v MIDI control number
|
||||||
|
* @return Always returns 0
|
||||||
*/
|
*/
|
||||||
int fluid_midi_event_set_control(fluid_midi_event_t* evt, int v)
|
int fluid_midi_event_set_control(fluid_midi_event_t* evt, int v)
|
||||||
{
|
{
|
||||||
@@ -781,16 +817,21 @@ int fluid_midi_event_set_control(fluid_midi_event_t* evt, int v)
|
|||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* fluid_midi_event_get_value
|
* Get the value field from a MIDI event structure.
|
||||||
|
* @param evt MIDI event structure
|
||||||
|
* @return Value field
|
||||||
*/
|
*/
|
||||||
int fluid_midi_event_get_value(fluid_midi_event_t* evt)
|
int fluid_midi_event_get_value(fluid_midi_event_t* evt)
|
||||||
{
|
{
|
||||||
return evt->param2;
|
return evt->param2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* fluid_midi_event_set_value
|
* Set the value field of a MIDI event structure.
|
||||||
|
* @param evt MIDI event structure
|
||||||
|
* @param v Value to assign
|
||||||
|
* @return Always returns 0
|
||||||
*/
|
*/
|
||||||
int fluid_midi_event_set_value(fluid_midi_event_t* evt, int v)
|
int fluid_midi_event_set_value(fluid_midi_event_t* evt, int v)
|
||||||
{
|
{
|
||||||
@@ -798,22 +839,44 @@ int fluid_midi_event_set_value(fluid_midi_event_t* evt, int v)
|
|||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the program field of a MIDI event structure.
|
||||||
|
* @param evt MIDI event structure
|
||||||
|
* @return MIDI program number (0-127)
|
||||||
|
*/
|
||||||
int fluid_midi_event_get_program(fluid_midi_event_t* evt)
|
int fluid_midi_event_get_program(fluid_midi_event_t* evt)
|
||||||
{
|
{
|
||||||
return evt->param1;
|
return evt->param1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the program field of a MIDI event structure.
|
||||||
|
* @param evt MIDI event structure
|
||||||
|
* @param val MIDI program number (0-127)
|
||||||
|
* @return Always returns 0
|
||||||
|
*/
|
||||||
int fluid_midi_event_set_program(fluid_midi_event_t* evt, int val)
|
int fluid_midi_event_set_program(fluid_midi_event_t* evt, int val)
|
||||||
{
|
{
|
||||||
evt->param1 = val;
|
evt->param1 = val;
|
||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the pitch field of a MIDI event structure.
|
||||||
|
* @param evt MIDI event structure
|
||||||
|
* @return Pitch value (DOCME units?)
|
||||||
|
*/
|
||||||
int fluid_midi_event_get_pitch(fluid_midi_event_t* evt)
|
int fluid_midi_event_get_pitch(fluid_midi_event_t* evt)
|
||||||
{
|
{
|
||||||
return evt->param1;
|
return evt->param1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the pitch field of a MIDI event structure.
|
||||||
|
* @param evt MIDI event structure
|
||||||
|
* @param val Pitch value (DOCME units?)
|
||||||
|
* @return Always returns 0
|
||||||
|
*/
|
||||||
int fluid_midi_event_set_pitch(fluid_midi_event_t* evt, int val)
|
int fluid_midi_event_set_pitch(fluid_midi_event_t* evt, int val)
|
||||||
{
|
{
|
||||||
evt->param1 = val;
|
evt->param1 = val;
|
||||||
@@ -904,7 +967,7 @@ int fluid_track_set_name(fluid_track_t* track, char* name)
|
|||||||
}
|
}
|
||||||
if (name == NULL) {
|
if (name == NULL) {
|
||||||
track->name = NULL;
|
track->name = NULL;
|
||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
len = FLUID_STRLEN(name);
|
len = FLUID_STRLEN(name);
|
||||||
track->name = FLUID_MALLOC(len + 1);
|
track->name = FLUID_MALLOC(len + 1);
|
||||||
@@ -913,7 +976,7 @@ int fluid_track_set_name(fluid_track_t* track, char* name)
|
|||||||
return FLUID_FAILED;
|
return FLUID_FAILED;
|
||||||
}
|
}
|
||||||
FLUID_STRCPY(track->name, name);
|
FLUID_STRCPY(track->name, name);
|
||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -995,7 +1058,7 @@ fluid_midi_event_t* fluid_track_next_event(fluid_track_t* track)
|
|||||||
/*
|
/*
|
||||||
* fluid_track_reset
|
* fluid_track_reset
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
fluid_track_reset(fluid_track_t* track)
|
fluid_track_reset(fluid_track_t* track)
|
||||||
{
|
{
|
||||||
track->ticks = 0;
|
track->ticks = 0;
|
||||||
@@ -1006,8 +1069,8 @@ fluid_track_reset(fluid_track_t* track)
|
|||||||
/*
|
/*
|
||||||
* fluid_track_send_events
|
* fluid_track_send_events
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
fluid_track_send_events(fluid_track_t* track,
|
fluid_track_send_events(fluid_track_t* track,
|
||||||
fluid_synth_t* synth,
|
fluid_synth_t* synth,
|
||||||
fluid_player_t* player,
|
fluid_player_t* player,
|
||||||
unsigned int ticks)
|
unsigned int ticks)
|
||||||
@@ -1046,8 +1109,11 @@ fluid_track_send_events(fluid_track_t* track,
|
|||||||
*
|
*
|
||||||
* fluid_player
|
* fluid_player
|
||||||
*/
|
*/
|
||||||
/*
|
|
||||||
* new_fluid_player
|
/**
|
||||||
|
* Create a new MIDI player.
|
||||||
|
* @param synth Fluid synthesizer instance to create player for
|
||||||
|
* @return New MIDI player instance or NULL on error (out of memory)
|
||||||
*/
|
*/
|
||||||
fluid_player_t* new_fluid_player(fluid_synth_t* synth)
|
fluid_player_t* new_fluid_player(fluid_synth_t* synth)
|
||||||
{
|
{
|
||||||
@@ -1075,8 +1141,10 @@ fluid_player_t* new_fluid_player(fluid_synth_t* synth)
|
|||||||
return player;
|
return player;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* delete_fluid_player
|
* Delete a MIDI player instance.
|
||||||
|
* @param player MIDI player instance
|
||||||
|
* @return Always returns 0
|
||||||
*/
|
*/
|
||||||
int delete_fluid_player(fluid_player_t* player)
|
int delete_fluid_player(fluid_player_t* player)
|
||||||
{
|
{
|
||||||
@@ -1157,7 +1225,7 @@ int fluid_player_load(fluid_player_t* player, char *filename)
|
|||||||
{
|
{
|
||||||
fluid_midi_file* midifile;
|
fluid_midi_file* midifile;
|
||||||
|
|
||||||
midifile = new_fluid_midi_file(filename);
|
midifile = new_fluid_midi_file(filename);
|
||||||
if (midifile == NULL) {
|
if (midifile == NULL) {
|
||||||
return FLUID_FAILED;
|
return FLUID_FAILED;
|
||||||
}
|
}
|
||||||
@@ -1169,7 +1237,7 @@ int fluid_player_load(fluid_player_t* player, char *filename)
|
|||||||
return FLUID_FAILED;
|
return FLUID_FAILED;
|
||||||
}
|
}
|
||||||
delete_fluid_midi_file(midifile);
|
delete_fluid_midi_file(midifile);
|
||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1217,9 +1285,9 @@ int fluid_player_callback(void* data, unsigned int msec)
|
|||||||
}
|
}
|
||||||
|
|
||||||
player->cur_msec = msec;
|
player->cur_msec = msec;
|
||||||
player->cur_ticks = (player->start_ticks +
|
player->cur_ticks = (player->start_ticks +
|
||||||
(int) ((double) (player->cur_msec - player->start_msec) / player->deltatime));
|
(int) ((double) (player->cur_msec - player->start_msec) / player->deltatime));
|
||||||
|
|
||||||
for (i = 0; i < player->ntracks; i++) {
|
for (i = 0; i < player->ntracks; i++) {
|
||||||
if (!fluid_track_eot(player->track[i])) {
|
if (!fluid_track_eot(player->track[i])) {
|
||||||
status = FLUID_PLAYER_PLAYING;
|
status = FLUID_PLAYER_PLAYING;
|
||||||
@@ -1232,30 +1300,32 @@ int fluid_player_callback(void* data, unsigned int msec)
|
|||||||
player->status = status;
|
player->status = status;
|
||||||
|
|
||||||
if (player->status == FLUID_PLAYER_DONE) {
|
if (player->status == FLUID_PLAYER_DONE) {
|
||||||
FLUID_LOG(FLUID_DBG, "%s: %d: Duration=%.3f sec",
|
FLUID_LOG(FLUID_DBG, "%s: %d: Duration=%.3f sec",
|
||||||
__FILE__, __LINE__, (msec - player->begin_msec) / 1000.0);
|
__FILE__, __LINE__, (msec - player->begin_msec) / 1000.0);
|
||||||
player->current_file = NULL;
|
player->current_file = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* fluid_player_play
|
* Activates play mode for a MIDI player if not already playing.
|
||||||
|
* @param player MIDI player instance
|
||||||
|
* @return 0 on success, -1 on failure
|
||||||
*/
|
*/
|
||||||
int fluid_player_play(fluid_player_t* player)
|
int fluid_player_play(fluid_player_t* player)
|
||||||
{
|
{
|
||||||
if (player->status == FLUID_PLAYER_PLAYING) {
|
if (player->status == FLUID_PLAYER_PLAYING) {
|
||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player->playlist == NULL) {
|
if (player->playlist == NULL) {
|
||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
player->status = FLUID_PLAYER_PLAYING;
|
player->status = FLUID_PLAYER_PLAYING;
|
||||||
|
|
||||||
player->timer = new_fluid_timer((int) player->deltatime, fluid_player_callback,
|
player->timer = new_fluid_timer((int) player->deltatime, fluid_player_callback,
|
||||||
(void*) player, 1, 0);
|
(void*) player, 1, 0);
|
||||||
if (player->timer == NULL) {
|
if (player->timer == NULL) {
|
||||||
return FLUID_FAILED;
|
return FLUID_FAILED;
|
||||||
@@ -1263,8 +1333,10 @@ int fluid_player_play(fluid_player_t* player)
|
|||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* fluid_player_stop
|
* Stops a MIDI player.
|
||||||
|
* @param player MIDI player instance
|
||||||
|
* @return Always returns 0
|
||||||
*/
|
*/
|
||||||
int fluid_player_stop(fluid_player_t* player)
|
int fluid_player_stop(fluid_player_t* player)
|
||||||
{
|
{
|
||||||
@@ -1276,8 +1348,13 @@ int fluid_player_stop(fluid_player_t* player)
|
|||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* FIXME - Looping seems to not actually be implemented? */
|
||||||
* fluid_player_set_loop
|
|
||||||
|
/**
|
||||||
|
* Enable looping of a MIDI player (DOCME - Does this actually work?)
|
||||||
|
* @param player MIDI player instance
|
||||||
|
* @param loop Value for looping (DOCME - What would this value be, boolean/time index?)
|
||||||
|
* @return Always returns 0
|
||||||
*/
|
*/
|
||||||
int fluid_player_set_loop(fluid_player_t* player, int loop)
|
int fluid_player_set_loop(fluid_player_t* player, int loop)
|
||||||
{
|
{
|
||||||
@@ -1285,8 +1362,12 @@ int fluid_player_set_loop(fluid_player_t* player, int loop)
|
|||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* fluid_player_set_midi_tempo
|
* Set the tempo of a MIDI player.
|
||||||
|
* @param player MIDI player instance
|
||||||
|
* @param tempo Tempo to set playback speed to (DOCME - Units?)
|
||||||
|
* @return Always returns 0
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
int fluid_player_set_midi_tempo(fluid_player_t* player, int tempo)
|
int fluid_player_set_midi_tempo(fluid_player_t* player, int tempo)
|
||||||
{
|
{
|
||||||
@@ -1294,23 +1375,29 @@ int fluid_player_set_midi_tempo(fluid_player_t* player, int tempo)
|
|||||||
player->deltatime = (double) tempo / player->division / 1000.0; /* in milliseconds */
|
player->deltatime = (double) tempo / player->division / 1000.0; /* in milliseconds */
|
||||||
player->start_msec = player->cur_msec;
|
player->start_msec = player->cur_msec;
|
||||||
player->start_ticks = player->cur_ticks;
|
player->start_ticks = player->cur_ticks;
|
||||||
|
|
||||||
FLUID_LOG(FLUID_DBG,"tempo=%d, tick time=%f msec, cur time=%d msec, cur tick=%d",
|
FLUID_LOG(FLUID_DBG,"tempo=%d, tick time=%f msec, cur time=%d msec, cur tick=%d",
|
||||||
tempo, player->deltatime, player->cur_msec, player->cur_ticks);
|
tempo, player->deltatime, player->cur_msec, player->cur_ticks);
|
||||||
|
|
||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* fluid_player_set_bpm
|
* Set the tempo of a MIDI player in beats per minute.
|
||||||
|
* @param player MIDI player instance
|
||||||
|
* @param bpm Tempo in beats per minute
|
||||||
|
* @return Always returns 0
|
||||||
*/
|
*/
|
||||||
int fluid_player_set_bpm(fluid_player_t* player, int bpm)
|
int fluid_player_set_bpm(fluid_player_t* player, int bpm)
|
||||||
{
|
{
|
||||||
return fluid_player_set_midi_tempo(player, (int)((double) 60 * 1e6 / bpm));
|
return fluid_player_set_midi_tempo(player, (int)((double) 60 * 1e6 / bpm));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* fluid_player_join
|
* Wait for a MIDI player to terminate (when done playing).
|
||||||
|
* @param player MIDI player instance
|
||||||
|
* @return 0 on success, -1 otherwise
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
int fluid_player_join(fluid_player_t* player)
|
int fluid_player_join(fluid_player_t* player)
|
||||||
{
|
{
|
||||||
@@ -1360,10 +1447,10 @@ fluid_midi_event_t* fluid_midi_parser_parse(fluid_midi_parser_t* parser, unsigne
|
|||||||
/* 'Process' system real-time messages */
|
/* 'Process' system real-time messages */
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
/* There are not too many real-time messages that are of interest here.
|
/* There are not too many real-time messages that are of interest here.
|
||||||
* They can occur anywhere, even in the middle of a noteon message!
|
* They can occur anywhere, even in the middle of a noteon message!
|
||||||
* Real-time range: 0xF8 .. 0xFF
|
* Real-time range: 0xF8 .. 0xFF
|
||||||
* Note: Real-time does not affect (running) status.
|
* Note: Real-time does not affect (running) status.
|
||||||
*/
|
*/
|
||||||
if (c >= 0xF8){
|
if (c >= 0xF8){
|
||||||
if (c == MIDI_SYSTEM_RESET){
|
if (c == MIDI_SYSTEM_RESET){
|
||||||
parser->event.type = c;
|
parser->event.type = c;
|
||||||
@@ -1372,23 +1459,23 @@ fluid_midi_event_t* fluid_midi_parser_parse(fluid_midi_parser_t* parser, unsigne
|
|||||||
};
|
};
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
/* 'Process' system common messages (again, just skip them) */
|
/* 'Process' system common messages (again, just skip them) */
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
/* There are no system common messages that are of interest here.
|
/* There are no system common messages that are of interest here.
|
||||||
* System common range: 0xF0 .. 0xF7
|
* System common range: 0xF0 .. 0xF7
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (c > 0xF0){
|
if (c > 0xF0){
|
||||||
/* MIDI specs say: To ignore a non-real-time message, just discard all data up to
|
/* MIDI specs say: To ignore a non-real-time message, just discard all data up to
|
||||||
* the next status byte.
|
* the next status byte.
|
||||||
* And our parser will ignore data that is received without a valid status.
|
* And our parser will ignore data that is received without a valid status.
|
||||||
* Note: system common cancels running status. */
|
* Note: system common cancels running status. */
|
||||||
parser->status = 0;
|
parser->status = 0;
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
/* Process voice category messages: */
|
/* Process voice category messages: */
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
@@ -1399,7 +1486,7 @@ fluid_midi_event_t* fluid_midi_parser_parse(fluid_midi_parser_t* parser, unsigne
|
|||||||
* as soon as a byte >= 0x80 comes in, we are dealing with a status byte
|
* as soon as a byte >= 0x80 comes in, we are dealing with a status byte
|
||||||
* and start a new event.
|
* and start a new event.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (c & 0x80){
|
if (c & 0x80){
|
||||||
parser->channel = c & 0x0F;
|
parser->channel = c & 0x0F;
|
||||||
parser->status = c & 0xF0;
|
parser->status = c & 0xF0;
|
||||||
@@ -1431,12 +1518,12 @@ fluid_midi_event_t* fluid_midi_parser_parse(fluid_midi_parser_t* parser, unsigne
|
|||||||
if (parser->nr_bytes < parser->nr_bytes_total){
|
if (parser->nr_bytes < parser->nr_bytes_total){
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
/* Send the event */
|
/* Send the event */
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
/* The event is ready-to-go.
|
/* The event is ready-to-go.
|
||||||
* About 'running status':
|
* About 'running status':
|
||||||
* The MIDI protocol has a built-in compression mechanism. If several similar events are sent
|
* The MIDI protocol has a built-in compression mechanism. If several similar events are sent
|
||||||
* in-a-row, for example note-ons, then the event type is only sent once. For this case,
|
* in-a-row, for example note-ons, then the event type is only sent once. For this case,
|
||||||
* the last event type (status) is remembered.
|
* the last event type (status) is remembered.
|
||||||
@@ -1459,14 +1546,14 @@ fluid_midi_event_t* fluid_midi_parser_parse(fluid_midi_parser_t* parser, unsigne
|
|||||||
/* Pitch-bend is transmitted with 14-bit precision. */
|
/* Pitch-bend is transmitted with 14-bit precision. */
|
||||||
parser->event.param1 = ((parser->p[1] << 7) | parser->p[0]); /* Note: '|' does here the same as '+' (no common bits), but might be faster */
|
parser->event.param1 = ((parser->p[1] << 7) | parser->p[0]); /* Note: '|' does here the same as '+' (no common bits), but might be faster */
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Unlikely */
|
/* Unlikely */
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
return &parser->event;
|
return &parser->event;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Purpose:
|
/* Purpose:
|
||||||
* Returns the length of the MIDI message starting with c.
|
* Returns the length of the MIDI message starting with c.
|
||||||
* Taken from Nagano Daisuke's USB-MIDI driver */
|
* Taken from Nagano Daisuke's USB-MIDI driver */
|
||||||
int fluid_midi_event_length(unsigned char event){
|
int fluid_midi_event_length(unsigned char event){
|
||||||
@@ -1525,5 +1612,3 @@ int fluid_midi_send_event(fluid_synth_t* synth, fluid_player_t* player, fluid_mi
|
|||||||
}
|
}
|
||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -161,14 +161,14 @@ enum midi_meta_event {
|
|||||||
MIDI_SEQUENCER_EVENT = 0x7f
|
MIDI_SEQUENCER_EVENT = 0x7f
|
||||||
};
|
};
|
||||||
|
|
||||||
enum fluid_player_status
|
enum fluid_player_status
|
||||||
{
|
{
|
||||||
FLUID_PLAYER_READY,
|
FLUID_PLAYER_READY,
|
||||||
FLUID_PLAYER_PLAYING,
|
FLUID_PLAYER_PLAYING,
|
||||||
FLUID_PLAYER_DONE
|
FLUID_PLAYER_DONE
|
||||||
};
|
};
|
||||||
|
|
||||||
enum fluid_driver_status
|
enum fluid_driver_status
|
||||||
{
|
{
|
||||||
FLUID_MIDI_READY,
|
FLUID_MIDI_READY,
|
||||||
FLUID_MIDI_LISTENING,
|
FLUID_MIDI_LISTENING,
|
||||||
@@ -181,7 +181,7 @@ enum fluid_driver_status
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* From ctype.h */
|
/* From ctype.h */
|
||||||
#define fluid_isascii(c) (((c) & ~0x7f) == 0)
|
#define fluid_isascii(c) (((c) & ~0x7f) == 0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -222,7 +222,7 @@ fluid_midi_event_t* fluid_track_next_event(fluid_track_t* track);
|
|||||||
int fluid_track_get_duration(fluid_track_t* track);
|
int fluid_track_get_duration(fluid_track_t* track);
|
||||||
int fluid_track_reset(fluid_track_t* track);
|
int fluid_track_reset(fluid_track_t* track);
|
||||||
|
|
||||||
int fluid_track_send_events(fluid_track_t* track,
|
int fluid_track_send_events(fluid_track_t* track,
|
||||||
fluid_synth_t* synth,
|
fluid_synth_t* synth,
|
||||||
fluid_player_t* player,
|
fluid_player_t* player,
|
||||||
unsigned int ticks);
|
unsigned int ticks);
|
||||||
@@ -273,7 +273,7 @@ typedef struct {
|
|||||||
int uses_smpte;
|
int uses_smpte;
|
||||||
unsigned int smpte_fps;
|
unsigned int smpte_fps;
|
||||||
unsigned int smpte_res;
|
unsigned int smpte_res;
|
||||||
unsigned int division; /* If uses_SMPTE == 0 then division is
|
unsigned int division; /* If uses_SMPTE == 0 then division is
|
||||||
ticks per beat (quarter-note) */
|
ticks per beat (quarter-note) */
|
||||||
double tempo; /* Beats per second (SI rules =) */
|
double tempo; /* Beats per second (SI rules =) */
|
||||||
int tracklen;
|
int tracklen;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -26,21 +26,29 @@
|
|||||||
#include "fluid_synth.h"
|
#include "fluid_synth.h"
|
||||||
#include "fluid_io.h"
|
#include "fluid_io.h"
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* new_fluid_midi_router
|
* Create a new midi router.
|
||||||
|
* @param settings Settings used to configure MIDI router
|
||||||
|
* @param handler MIDI event callback
|
||||||
|
* @param event_handler_data Caller defined data pointer which gets passed to 'handler'
|
||||||
|
* @return New MIDI router instance or NULL on error
|
||||||
|
*
|
||||||
|
* A midi handler connects to a midi input
|
||||||
|
* device and forwards incoming midi events to the synthesizer.
|
||||||
*/
|
*/
|
||||||
fluid_midi_router_t*
|
fluid_midi_router_t*
|
||||||
new_fluid_midi_router(fluid_settings_t* settings, handle_midi_event_func_t handler, void* event_handler_data)
|
new_fluid_midi_router(fluid_settings_t* settings, handle_midi_event_func_t handler, void* event_handler_data)
|
||||||
{
|
{
|
||||||
fluid_midi_router_t* router=NULL;
|
fluid_midi_router_t* router=NULL;
|
||||||
fluid_midi_router_rule_t* rule=NULL;;
|
fluid_midi_router_rule_t* rule=NULL;
|
||||||
|
|
||||||
/* create the router */
|
/* create the router */
|
||||||
router = FLUID_NEW(fluid_midi_router_t); if (router == NULL){
|
router = FLUID_NEW(fluid_midi_router_t); if (router == NULL){
|
||||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Clear the router, so that error_recovery can safely free all the rules.
|
/* Clear the router, so that error_recovery can safely free all the rules.
|
||||||
* Dump functions are also NULLed.
|
* Dump functions are also NULLed.
|
||||||
*/
|
*/
|
||||||
FLUID_MEMSET(router, 0, sizeof(fluid_midi_router_t));
|
FLUID_MEMSET(router, 0, sizeof(fluid_midi_router_t));
|
||||||
@@ -53,12 +61,12 @@ new_fluid_midi_router(fluid_settings_t* settings, handle_midi_event_func_t handl
|
|||||||
router->event_handler=handler;
|
router->event_handler=handler;
|
||||||
router->event_handler_data=event_handler_data;
|
router->event_handler_data=event_handler_data;
|
||||||
|
|
||||||
/* Create the default routing rules
|
/* Create the default routing rules
|
||||||
* They accept events on any channel for any range of parameters,
|
* They accept events on any channel for any range of parameters,
|
||||||
* and route them unchanged ("result=par*1.0+0") */
|
* and route them unchanged ("result=par*1.0+0") */
|
||||||
|
|
||||||
if (fluid_midi_router_create_default_rules(router) != FLUID_OK) goto error_recovery;
|
if (fluid_midi_router_create_default_rules(router) != FLUID_OK) goto error_recovery;
|
||||||
|
|
||||||
return router;
|
return router;
|
||||||
|
|
||||||
error_recovery:
|
error_recovery:
|
||||||
@@ -68,10 +76,12 @@ new_fluid_midi_router(fluid_settings_t* settings, handle_midi_event_func_t handl
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* delete_fluid_midi_router
|
* Delete a MIDI router instance.
|
||||||
|
* @param router MIDI router to delete
|
||||||
|
* @return Always returns 0
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
delete_fluid_midi_router(fluid_midi_router_t* router)
|
delete_fluid_midi_router(fluid_midi_router_t* router)
|
||||||
{
|
{
|
||||||
if (router == NULL) {
|
if (router == NULL) {
|
||||||
@@ -84,7 +94,7 @@ delete_fluid_midi_router(fluid_midi_router_t* router)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* fluid_midi_router_destroy_all_rules(fluid_midi_router_t* router)
|
* fluid_midi_router_destroy_all_rules(fluid_midi_router_t* router)
|
||||||
* Purpose:
|
* Purpose:
|
||||||
* Frees the used memory. This is used only for shutdown!
|
* Frees the used memory. This is used only for shutdown!
|
||||||
*/
|
*/
|
||||||
void fluid_midi_router_destroy_all_rules(fluid_midi_router_t* router){
|
void fluid_midi_router_destroy_all_rules(fluid_midi_router_t* router){
|
||||||
@@ -127,7 +137,7 @@ fluid_midi_router_rule_t* new_fluid_midi_router_rule(void)
|
|||||||
/*
|
/*
|
||||||
* delete_fluid_midi_router_rule
|
* delete_fluid_midi_router_rule
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
delete_fluid_midi_router_rule(fluid_midi_router_rule_t* rule)
|
delete_fluid_midi_router_rule(fluid_midi_router_rule_t* rule)
|
||||||
{
|
{
|
||||||
FLUID_FREE(rule);
|
FLUID_FREE(rule);
|
||||||
@@ -139,7 +149,7 @@ int fluid_midi_router_create_default_rules(fluid_midi_router_t* router)
|
|||||||
{
|
{
|
||||||
fluid_midi_router_rule_t** rules[6];
|
fluid_midi_router_rule_t** rules[6];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
rules[0]=&router->note_rules;
|
rules[0]=&router->note_rules;
|
||||||
rules[1]=&router->cc_rules;
|
rules[1]=&router->cc_rules;
|
||||||
rules[2]=&router->progchange_rules;
|
rules[2]=&router->progchange_rules;
|
||||||
@@ -238,18 +248,22 @@ int fluid_midi_router_end(fluid_midi_router_t* router){
|
|||||||
delete_fluid_midi_router_rule(rule);
|
delete_fluid_midi_router_rule(rule);
|
||||||
return FLUID_FAILED;
|
return FLUID_FAILED;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* fluid_midi_router_send_event
|
* Handle a MIDI event through a MIDI router instance.
|
||||||
|
* @param data MIDI router instance #fluid_midi_router_t (DOCME why is it a void *?)
|
||||||
|
* @param event MIDI event to handle
|
||||||
|
* @return 0 on success, -1 otherwise
|
||||||
|
*
|
||||||
* Purpose: The midi router is called for each event, that is received
|
* Purpose: The midi router is called for each event, that is received
|
||||||
* via the 'physical' midi input. Each event can trigger an arbitrary number
|
* via the 'physical' midi input. Each event can trigger an arbitrary number
|
||||||
* of generated events.
|
* of generated events.
|
||||||
*
|
*
|
||||||
* In default mode, a noteon event is just forwarded to the synth's 'noteon' function,
|
* In default mode, a noteon event is just forwarded to the synth's 'noteon' function,
|
||||||
* a 'CC' event to the synth's 'CC' function and so on.
|
* a 'CC' event to the synth's 'CC' function and so on.
|
||||||
*
|
*
|
||||||
* The router can be used to
|
* The router can be used to
|
||||||
* - filter messages (for example: Pass sustain pedal CCs only to selected channels),
|
* - filter messages (for example: Pass sustain pedal CCs only to selected channels),
|
||||||
* - split the keyboard (noteon with notenr < x: to ch 1, >x to ch 2),
|
* - split the keyboard (noteon with notenr < x: to ch 1, >x to ch 2),
|
||||||
* - layer sounds (for each noteon received on ch 1, create a noteon on ch1, ch2, ch3,...)
|
* - layer sounds (for each noteon received on ch 1, create a noteon on ch1, ch2, ch3,...)
|
||||||
* - velocity scaling (for each noteon event, scale the velocity by 1.27 to give DX7 users
|
* - velocity scaling (for each noteon event, scale the velocity by 1.27 to give DX7 users
|
||||||
@@ -258,7 +272,7 @@ int fluid_midi_router_end(fluid_midi_router_t* router){
|
|||||||
* - get rid of aftertouch
|
* - get rid of aftertouch
|
||||||
* - ...
|
* - ...
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event)
|
fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event)
|
||||||
{
|
{
|
||||||
fluid_midi_router_t* router=(fluid_midi_router_t*)data;
|
fluid_midi_router_t* router=(fluid_midi_router_t*)data;
|
||||||
@@ -276,12 +290,12 @@ fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event)
|
|||||||
if (event->type == NOTE_ON && event->param2 == 0) {
|
if (event->type == NOTE_ON && event->param2 == 0) {
|
||||||
/* Channel: Remains the same
|
/* Channel: Remains the same
|
||||||
* Param 1: Note number, remains the same
|
* Param 1: Note number, remains the same
|
||||||
* Param 2: release velocity), set to max
|
* Param 2: release velocity), set to max
|
||||||
*/
|
*/
|
||||||
event->type = NOTE_OFF;
|
event->type = NOTE_OFF;
|
||||||
event->param2=127;
|
event->param2=127;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Lock the rules table, so that for example the shell thread doesn't
|
/* Lock the rules table, so that for example the shell thread doesn't
|
||||||
* clear the rules we are just working with */
|
* clear the rules we are just working with */
|
||||||
fluid_mutex_lock(router->ruletables_mutex);
|
fluid_mutex_lock(router->ruletables_mutex);
|
||||||
@@ -324,26 +338,26 @@ fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event)
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* At this point 'rule' contains the first rule in a linked list.
|
/* At this point 'rule' contains the first rule in a linked list.
|
||||||
* Check for all rules, whether channel and parameter ranges match.
|
* Check for all rules, whether channel and parameter ranges match.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
while (rule){
|
while (rule){
|
||||||
int chan; /* Channel of the generated event */
|
int chan; /* Channel of the generated event */
|
||||||
int par1; /* par1 of the generated event */
|
int par1; /* par1 of the generated event */
|
||||||
int par2=0;
|
int par2=0;
|
||||||
int event_par1=(int)event->param1;
|
int event_par1=(int)event->param1;
|
||||||
int event_par2=(int)event->param2;
|
int event_par2=(int)event->param2;
|
||||||
fluid_midi_event_t new_event;
|
fluid_midi_event_t new_event;
|
||||||
|
|
||||||
/* Store the pointer to the next rule right now. If the rule is later flagged for destruction,
|
/* Store the pointer to the next rule right now. If the rule is later flagged for destruction,
|
||||||
* it may not be accessed anymore.
|
* it may not be accessed anymore.
|
||||||
*/
|
*/
|
||||||
next_rule=rule->next;
|
next_rule=rule->next;
|
||||||
|
|
||||||
/* Check, whether the rule is still active. Expired rules cannot be removed immediately,
|
/* Check, whether the rule is still active. Expired rules cannot be removed immediately,
|
||||||
* because freeing memory in a realtime thread is no good idea. And the MIDI thread,
|
* because freeing memory in a realtime thread is no good idea. And the MIDI thread,
|
||||||
* which calls us here, has raised priority.*/
|
* which calls us here, has raised priority.*/
|
||||||
if (rule->state == MIDIRULE_DONE){
|
if (rule->state == MIDIRULE_DONE){
|
||||||
goto do_next_rule;
|
goto do_next_rule;
|
||||||
@@ -374,11 +388,11 @@ fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event)
|
|||||||
goto do_next_rule;
|
goto do_next_rule;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Par 2 window (only applies to event types, which have 2 pars)
|
/* Par 2 window (only applies to event types, which have 2 pars)
|
||||||
* For noteoff events, velocity switching doesn't make any sense.
|
* For noteoff events, velocity switching doesn't make any sense.
|
||||||
* Velocity scaling might be useful, though.
|
* Velocity scaling might be useful, though.
|
||||||
*/
|
*/
|
||||||
if (event_has_par2 && event->type != NOTE_OFF){
|
if (event_has_par2 && event->type != NOTE_OFF){
|
||||||
if (rule->par2_min > rule->par2_max){
|
if (rule->par2_min > rule->par2_max){
|
||||||
/* Inverted rule: Exclude everything between max and min (but not min/max) */
|
/* Inverted rule: Exclude everything between max and min (but not min/max) */
|
||||||
@@ -392,9 +406,9 @@ fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event)
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Channel scaling / offset
|
/* Channel scaling / offset
|
||||||
* Note: rule->chan_mul will probably be 0 or 1. If it's 0, input from all
|
* Note: rule->chan_mul will probably be 0 or 1. If it's 0, input from all
|
||||||
* input channels is mapped to the same synth channel.
|
* input channels is mapped to the same synth channel.
|
||||||
*/
|
*/
|
||||||
chan=(int)((fluid_real_t)event->channel * (fluid_real_t)rule->chan_mul + (fluid_real_t)rule->chan_add + 0.5);
|
chan=(int)((fluid_real_t)event->channel * (fluid_real_t)rule->chan_mul + (fluid_real_t)rule->chan_add + 0.5);
|
||||||
@@ -406,7 +420,7 @@ fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event)
|
|||||||
if (event_has_par2){
|
if (event_has_par2){
|
||||||
par2=(int)((fluid_real_t)event_par2 * (fluid_real_t)rule->par2_mul + (fluid_real_t)rule->par2_add + 0.5);
|
par2=(int)((fluid_real_t)event_par2 * (fluid_real_t)rule->par2_mul + (fluid_real_t)rule->par2_add + 0.5);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Channel range limiting */
|
/* Channel range limiting */
|
||||||
if (chan < 0){
|
if (chan < 0){
|
||||||
chan=0;
|
chan=0;
|
||||||
@@ -437,7 +451,7 @@ fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (
|
if (
|
||||||
event->type == NOTE_ON
|
event->type == NOTE_ON
|
||||||
|| (event->type == CONTROL_CHANGE && par1 == SUSTAIN_SWITCH && par2 >= 64)
|
|| (event->type == CONTROL_CHANGE && par1 == SUSTAIN_SWITCH && par2 >= 64)
|
||||||
){
|
){
|
||||||
/* Noteon or sustain pedal down event generated */
|
/* Noteon or sustain pedal down event generated */
|
||||||
@@ -446,7 +460,7 @@ fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event)
|
|||||||
rule->pending_events++;
|
rule->pending_events++;
|
||||||
};
|
};
|
||||||
} else if (
|
} else if (
|
||||||
event->type == NOTE_OFF
|
event->type == NOTE_OFF
|
||||||
|| (event->type == CONTROL_CHANGE && par1 == SUSTAIN_SWITCH && par2 < 64)
|
|| (event->type == CONTROL_CHANGE && par1 == SUSTAIN_SWITCH && par2 < 64)
|
||||||
){
|
){
|
||||||
/* Noteoff or sustain pedal up event generated */
|
/* Noteoff or sustain pedal up event generated */
|
||||||
@@ -463,7 +477,7 @@ fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event)
|
|||||||
/* There are no more pending events in the rule - all keys are up.
|
/* There are no more pending events in the rule - all keys are up.
|
||||||
* Change its state to 'unused', it will be cleared up at the next
|
* Change its state to 'unused', it will be cleared up at the next
|
||||||
* opportunity to run 'free' safely.
|
* opportunity to run 'free' safely.
|
||||||
* Note: After this, the rule may disappear at any time
|
* Note: After this, the rule may disappear at any time
|
||||||
*/
|
*/
|
||||||
rule->state=MIDIRULE_DONE;
|
rule->state=MIDIRULE_DONE;
|
||||||
};
|
};
|
||||||
@@ -477,9 +491,9 @@ fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event)
|
|||||||
goto do_next_rule;
|
goto do_next_rule;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/* At this point it is decided, what is sent to the synth.
|
/* At this point it is decided, what is sent to the synth.
|
||||||
* Create a new event and make the appropriate call
|
* Create a new event and make the appropriate call
|
||||||
*/
|
*/
|
||||||
|
|
||||||
fluid_midi_event_set_type(&new_event, event->type);
|
fluid_midi_event_set_type(&new_event, event->type);
|
||||||
@@ -516,8 +530,8 @@ int fluid_midi_router_handle_clear(fluid_synth_t* synth, int ac, char** av, flui
|
|||||||
if (ac != 0) {
|
if (ac != 0) {
|
||||||
fluid_ostream_printf(out, "router_clear needs no arguments.\n");
|
fluid_ostream_printf(out, "router_clear needs no arguments.\n");
|
||||||
goto error_recovery;
|
goto error_recovery;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Disable rules and mark for destruction */
|
/* Disable rules and mark for destruction */
|
||||||
fluid_midi_router_disable_all_rules(router);
|
fluid_midi_router_disable_all_rules(router);
|
||||||
|
|
||||||
@@ -536,8 +550,8 @@ int fluid_midi_router_handle_default(fluid_synth_t* synth, int ac, char** av, fl
|
|||||||
if (ac != 0) {
|
if (ac != 0) {
|
||||||
fluid_ostream_printf(out, "router_default needs no arguments.\n");
|
fluid_ostream_printf(out, "router_default needs no arguments.\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Disable rules and mark for destruction */
|
/* Disable rules and mark for destruction */
|
||||||
fluid_midi_router_disable_all_rules(router);
|
fluid_midi_router_disable_all_rules(router);
|
||||||
|
|
||||||
@@ -564,7 +578,7 @@ int fluid_midi_router_handle_begin(fluid_synth_t* synth, int ac, char** av, flui
|
|||||||
fluid_ostream_printf(out, "router_begin needs no arguments.\n");
|
fluid_ostream_printf(out, "router_begin needs no arguments.\n");
|
||||||
goto error_recovery;
|
goto error_recovery;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FLUID_STRCMP(av[0],"note") == 0){
|
if (FLUID_STRCMP(av[0],"note") == 0){
|
||||||
dest=& router->note_rules;
|
dest=& router->note_rules;
|
||||||
} else if (FLUID_STRCMP(av[0],"cc") == 0){
|
} else if (FLUID_STRCMP(av[0],"cc") == 0){
|
||||||
@@ -578,12 +592,12 @@ int fluid_midi_router_handle_begin(fluid_synth_t* synth, int ac, char** av, flui
|
|||||||
} else if (FLUID_STRCMP(av[0],"kpress") == 0){
|
} else if (FLUID_STRCMP(av[0],"kpress") == 0){
|
||||||
dest=& router->key_pressure_rules;
|
dest=& router->key_pressure_rules;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (dest == NULL){
|
if (dest == NULL){
|
||||||
fluid_ostream_printf(out, "router_begin args: note, cc, prog, pbend, cpress, kpress\n");
|
fluid_ostream_printf(out, "router_begin args: note, cc, prog, pbend, cpress, kpress\n");
|
||||||
goto error_recovery;
|
goto error_recovery;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (fluid_midi_router_begin(router, dest) != FLUID_OK){
|
if (fluid_midi_router_begin(router, dest) != FLUID_OK){
|
||||||
goto error_recovery;
|
goto error_recovery;
|
||||||
};
|
};
|
||||||
@@ -609,8 +623,8 @@ int fluid_midi_router_handle_end(fluid_synth_t* synth, int ac, char** av, fluid_
|
|||||||
if (fluid_midi_router_end(router) != FLUID_OK){
|
if (fluid_midi_router_end(router) != FLUID_OK){
|
||||||
FLUID_LOG(FLUID_ERR, "midi_router_end failed");
|
FLUID_LOG(FLUID_ERR, "midi_router_end failed");
|
||||||
goto error_recovery;
|
goto error_recovery;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Free unused rules (give it a try) */
|
/* Free unused rules (give it a try) */
|
||||||
fluid_midi_router_free_unused_rules(router);
|
fluid_midi_router_free_unused_rules(router);
|
||||||
|
|
||||||
@@ -658,7 +672,7 @@ int fluid_midi_router_handle_par1(fluid_synth_t* synth, int ac, char** av, fluid
|
|||||||
router->new_rule_par1_add=atoi(av[3]);
|
router->new_rule_par1_add=atoi(av[3]);
|
||||||
|
|
||||||
/* Free unused rules (give it a try) */
|
/* Free unused rules (give it a try) */
|
||||||
fluid_midi_router_free_unused_rules(router);
|
fluid_midi_router_free_unused_rules(router);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -760,23 +774,23 @@ void fluid_midi_router_free_unused_rules(fluid_midi_router_t* router)
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
while (*p){
|
while (*p){
|
||||||
fluid_midi_router_rule_t* current_rule=*p;
|
fluid_midi_router_rule_t* current_rule=*p;
|
||||||
fluid_midi_router_rule_t* next_rule=current_rule->next;
|
fluid_midi_router_rule_t* next_rule=current_rule->next;
|
||||||
|
|
||||||
if (current_rule->state == MIDIRULE_DONE){
|
if (current_rule->state == MIDIRULE_DONE){
|
||||||
/* p points to current_rule.
|
/* p points to current_rule.
|
||||||
* current_rule->next points to next_rule.
|
* current_rule->next points to next_rule.
|
||||||
* Unlink current_rule from the chain by setting the content
|
* Unlink current_rule from the chain by setting the content
|
||||||
* of p to next_rule.
|
* of p to next_rule.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
*p=next_rule;
|
*p=next_rule;
|
||||||
|
|
||||||
/* Now the rule is not in the chain anymore. Destroy it. */
|
/* Now the rule is not in the chain anymore. Destroy it. */
|
||||||
delete_fluid_midi_router_rule(current_rule);
|
delete_fluid_midi_router_rule(current_rule);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* We have to keep the rule, there is still unfinished business. */
|
/* We have to keep the rule, there is still unfinished business. */
|
||||||
p = ¤t_rule->next;
|
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);
|
fluid_mutex_unlock(router->ruletables_mutex);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Purpose:
|
/**
|
||||||
* This function demonstrates, how to access incoming MIDI messages.
|
* MIDI event callback function to display event information to stdout
|
||||||
* It prints a message to stdout (which can be used to hook up an external user interface),
|
* @param data MIDI router instance
|
||||||
* and hands the event on to the MIDI router.
|
* @param event MIDI event data
|
||||||
* It is not a part of the MIDI router, but an added link in the MIDI chain.
|
* @return 0 on success, -1 otherwise
|
||||||
|
*
|
||||||
|
* An implementation of the #handle_midi_event_func_t function type, used for
|
||||||
|
* displaying MIDI event information between the MIDI driver and router to
|
||||||
|
* stdout. Useful for adding into a MIDI router chain for debugging MIDI events.
|
||||||
*/
|
*/
|
||||||
int fluid_midi_dump_prerouter(void* data, fluid_midi_event_t* event)
|
int fluid_midi_dump_prerouter(void* data, fluid_midi_event_t* event)
|
||||||
{
|
{
|
||||||
switch (event->type) {
|
switch (event->type) {
|
||||||
case NOTE_ON:
|
case NOTE_ON:
|
||||||
fprintf(stdout, "event_pre_noteon %i %i %i\n",
|
fprintf(stdout, "event_pre_noteon %i %i %i\n",
|
||||||
event->channel, event->param1, event->param2);
|
event->channel, event->param1, event->param2);
|
||||||
fflush(stdout);
|
|
||||||
break;
|
break;
|
||||||
case NOTE_OFF:
|
case NOTE_OFF:
|
||||||
fprintf(stdout, "event_pre_noteoff %i %i %i\n",
|
fprintf(stdout, "event_pre_noteoff %i %i %i\n",
|
||||||
event->channel, event->param1, event->param2);
|
event->channel, event->param1, event->param2);
|
||||||
fflush(stdout);
|
|
||||||
break;
|
|
||||||
break;
|
break;
|
||||||
case CONTROL_CHANGE:
|
case CONTROL_CHANGE:
|
||||||
fprintf(stdout, "event_pre_cc %i %i %i\n",
|
fprintf(stdout, "event_pre_cc %i %i %i\n",
|
||||||
event->channel, event->param1, event->param2);
|
event->channel, event->param1, event->param2);
|
||||||
fflush(stdout);
|
|
||||||
break;
|
break;
|
||||||
case PROGRAM_CHANGE:
|
case PROGRAM_CHANGE:
|
||||||
fprintf(stdout, "event_pre_prog %i %i\n", event->channel, event->param1);
|
fprintf(stdout, "event_pre_prog %i %i\n", event->channel, event->param1);
|
||||||
fflush(stdout);
|
|
||||||
break;
|
break;
|
||||||
case PITCH_BEND:
|
case PITCH_BEND:
|
||||||
fprintf(stdout, "event_pre_pitch %i %i\n", event->channel, event->param1);
|
fprintf(stdout, "event_pre_pitch %i %i\n", event->channel, event->param1);
|
||||||
fflush(stdout);
|
|
||||||
break;
|
break;
|
||||||
case CHANNEL_PRESSURE:
|
case CHANNEL_PRESSURE:
|
||||||
fprintf(stdout, "event_pre_cpress %i %i\n", event->channel, event->param1);
|
fprintf(stdout, "event_pre_cpress %i %i\n", event->channel, event->param1);
|
||||||
fflush(stdout);
|
|
||||||
break;
|
break;
|
||||||
case KEY_PRESSURE:
|
case KEY_PRESSURE:
|
||||||
fprintf(stdout, "event_pre_kpress %i %i %i\n",
|
fprintf(stdout, "event_pre_kpress %i %i %i\n",
|
||||||
event->channel, event->param1, event->param2);
|
event->channel, event->param1, event->param2);
|
||||||
fflush(stdout);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -834,30 +844,30 @@ int fluid_midi_dump_prerouter(void* data, fluid_midi_event_t* event)
|
|||||||
return fluid_midi_router_handle_midi_event((fluid_midi_router_t*) data, event);
|
return fluid_midi_router_handle_midi_event((fluid_midi_router_t*) data, event);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Purpose:
|
/**
|
||||||
* This function demonstrates, how to access MIDI messages going from the MIDI
|
* MIDI event callback function to display event information to stdout
|
||||||
* router to the synth.
|
* @param data MIDI router instance
|
||||||
* Again, it prints a message to stdout and hands the event on to the synth.
|
* @param event MIDI event data
|
||||||
* It is not a part of the MIDI router, but an added link in the MIDI chain.
|
* @return 0 on success, -1 otherwise
|
||||||
|
*
|
||||||
|
* An implementation of the #handle_midi_event_func_t function type, used for
|
||||||
|
* displaying MIDI event information between the MIDI driver and router to
|
||||||
|
* stdout. Useful for adding into a MIDI router chain for debugging MIDI events.
|
||||||
*/
|
*/
|
||||||
int fluid_midi_dump_postrouter(void* data, fluid_midi_event_t* event)
|
int fluid_midi_dump_postrouter(void* data, fluid_midi_event_t* event)
|
||||||
{
|
{
|
||||||
switch (event->type) {
|
switch (event->type) {
|
||||||
case NOTE_ON:
|
case NOTE_ON:
|
||||||
fprintf(stdout, "event_post_noteon %i %i %i\n",
|
fprintf(stdout, "event_post_noteon %i %i %i\n",
|
||||||
event->channel, event->param1, event->param2);
|
event->channel, event->param1, event->param2);
|
||||||
fflush(stdout);
|
|
||||||
break;
|
break;
|
||||||
case NOTE_OFF:
|
case NOTE_OFF:
|
||||||
fprintf(stdout, "event_post_noteoff %i %i %i\n",
|
fprintf(stdout, "event_post_noteoff %i %i %i\n",
|
||||||
event->channel, event->param1, event->param2);
|
event->channel, event->param1, event->param2);
|
||||||
fflush(stdout);
|
|
||||||
break;
|
|
||||||
break;
|
break;
|
||||||
case CONTROL_CHANGE:
|
case CONTROL_CHANGE:
|
||||||
fprintf(stdout, "event_post_cc %i %i %i\n",
|
fprintf(stdout, "event_post_cc %i %i %i\n",
|
||||||
event->channel, event->param1, event->param2);
|
event->channel, event->param1, event->param2);
|
||||||
fflush(stdout);
|
|
||||||
break;
|
break;
|
||||||
case PROGRAM_CHANGE:
|
case PROGRAM_CHANGE:
|
||||||
fprintf(stdout, "event_post_prog %i %i\n", event->channel, event->param1);
|
fprintf(stdout, "event_post_prog %i %i\n", event->channel, event->param1);
|
||||||
@@ -869,7 +879,7 @@ int fluid_midi_dump_postrouter(void* data, fluid_midi_event_t* event)
|
|||||||
fprintf(stdout, "event_post_cpress %i %i\n", event->channel, event->param1);
|
fprintf(stdout, "event_post_cpress %i %i\n", event->channel, event->param1);
|
||||||
break;
|
break;
|
||||||
case KEY_PRESSURE:
|
case KEY_PRESSURE:
|
||||||
fprintf(stdout, "event_post_kpress %i %i %i\n",
|
fprintf(stdout, "event_post_kpress %i %i %i\n",
|
||||||
event->channel, event->param1, event->param2);
|
event->channel, event->param1, event->param2);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -79,7 +79,7 @@ struct _fluid_midi_router_t {
|
|||||||
void* event_handler_data; /* One arg for the callback */
|
void* event_handler_data; /* One arg for the callback */
|
||||||
|
|
||||||
int nr_midi_channels; /* For clipping the midi channel */
|
int nr_midi_channels; /* For clipping the midi channel */
|
||||||
fluid_mutex_t ruletables_mutex;
|
fluid_mutex_t ruletables_mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _fluid_midi_router_rule_t {
|
struct _fluid_midi_router_rule_t {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -25,56 +25,56 @@
|
|||||||
/*
|
/*
|
||||||
* fluid_mod_clone
|
* fluid_mod_clone
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
fluid_mod_clone(fluid_mod_t* mod, fluid_mod_t* src)
|
fluid_mod_clone(fluid_mod_t* mod, fluid_mod_t* src)
|
||||||
{
|
{
|
||||||
mod->dest = src->dest;
|
mod->dest = src->dest;
|
||||||
mod->src1 = src->src1;
|
mod->src1 = src->src1;
|
||||||
mod->flags1 = src->flags1;
|
mod->flags1 = src->flags1;
|
||||||
mod->src2 = src->src2;
|
mod->src2 = src->src2;
|
||||||
mod->flags2 = src->flags2;
|
mod->flags2 = src->flags2;
|
||||||
mod->amount = src->amount;
|
mod->amount = src->amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* fluid_mod_set_source1
|
* fluid_mod_set_source1
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
fluid_mod_set_source1(fluid_mod_t* mod, int src, int flags)
|
fluid_mod_set_source1(fluid_mod_t* mod, int src, int flags)
|
||||||
{
|
{
|
||||||
mod->src1 = src;
|
mod->src1 = src;
|
||||||
mod->flags1 = flags;
|
mod->flags1 = flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* fluid_mod_set_source2
|
* fluid_mod_set_source2
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
fluid_mod_set_source2(fluid_mod_t* mod, int src, int flags)
|
fluid_mod_set_source2(fluid_mod_t* mod, int src, int flags)
|
||||||
{
|
{
|
||||||
mod->src2 = src;
|
mod->src2 = src;
|
||||||
mod->flags2 = flags;
|
mod->flags2 = flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* fluid_mod_set_dest
|
* fluid_mod_set_dest
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
fluid_mod_set_dest(fluid_mod_t* mod, int dest)
|
fluid_mod_set_dest(fluid_mod_t* mod, int dest)
|
||||||
{
|
{
|
||||||
mod->dest = dest;
|
mod->dest = dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* fluid_mod_set_amount
|
* fluid_mod_set_amount
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
fluid_mod_set_amount(fluid_mod_t* mod, double amount)
|
fluid_mod_set_amount(fluid_mod_t* mod, double amount)
|
||||||
{
|
{
|
||||||
mod->amount = (double) amount;
|
mod->amount = (double) amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fluid_mod_get_source1(fluid_mod_t* mod)
|
int fluid_mod_get_source1(fluid_mod_t* mod)
|
||||||
{
|
{
|
||||||
return mod->src1;
|
return mod->src1;
|
||||||
}
|
}
|
||||||
@@ -108,7 +108,7 @@ double fluid_mod_get_amount(fluid_mod_t* mod)
|
|||||||
/*
|
/*
|
||||||
* fluid_mod_get_value
|
* fluid_mod_get_value
|
||||||
*/
|
*/
|
||||||
fluid_real_t
|
fluid_real_t
|
||||||
fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voice)
|
fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voice)
|
||||||
{
|
{
|
||||||
fluid_real_t v1 = 0.0, v2 = 1.0;
|
fluid_real_t v1 = 0.0, v2 = 1.0;
|
||||||
@@ -117,9 +117,9 @@ fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voic
|
|||||||
if (chan == NULL) {
|
if (chan == NULL) {
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 'special treatment' for default controller
|
/* 'special treatment' for default controller
|
||||||
*
|
*
|
||||||
* Reference: SF2.01 section 8.4.2
|
* Reference: SF2.01 section 8.4.2
|
||||||
*
|
*
|
||||||
* The GM default controller 'vel-to-filter cut off' is not clearly
|
* The GM default controller 'vel-to-filter cut off' is not clearly
|
||||||
@@ -140,10 +140,10 @@ fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voic
|
|||||||
* several SF2.1 sound fonts (where it is used only to turn it off).
|
* several SF2.1 sound fonts (where it is used only to turn it off).
|
||||||
* */
|
* */
|
||||||
if ((mod->src2 == FLUID_MOD_VELOCITY) &&
|
if ((mod->src2 == FLUID_MOD_VELOCITY) &&
|
||||||
(mod->src1 == FLUID_MOD_VELOCITY) &&
|
(mod->src1 == FLUID_MOD_VELOCITY) &&
|
||||||
(mod->flags1 == (FLUID_MOD_GC | FLUID_MOD_UNIPOLAR
|
(mod->flags1 == (FLUID_MOD_GC | FLUID_MOD_UNIPOLAR
|
||||||
| FLUID_MOD_NEGATIVE | FLUID_MOD_LINEAR)) &&
|
| FLUID_MOD_NEGATIVE | FLUID_MOD_LINEAR)) &&
|
||||||
(mod->flags2 == (FLUID_MOD_GC | FLUID_MOD_UNIPOLAR
|
(mod->flags2 == (FLUID_MOD_GC | FLUID_MOD_UNIPOLAR
|
||||||
| FLUID_MOD_POSITIVE | FLUID_MOD_SWITCH)) &&
|
| FLUID_MOD_POSITIVE | FLUID_MOD_SWITCH)) &&
|
||||||
(mod->dest == GEN_FILTERFC)) {
|
(mod->dest == GEN_FILTERFC)) {
|
||||||
if (voice->vel < 64){
|
if (voice->vel < 64){
|
||||||
@@ -152,37 +152,37 @@ fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voic
|
|||||||
return (fluid_real_t) mod->amount * (127 - voice->vel) / 127;
|
return (fluid_real_t) mod->amount * (127 - voice->vel) / 127;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get the initial value of the first source */
|
/* get the initial value of the first source */
|
||||||
if (mod->src1 > 0) {
|
if (mod->src1 > 0) {
|
||||||
if (mod->flags1 & FLUID_MOD_CC) {
|
if (mod->flags1 & FLUID_MOD_CC) {
|
||||||
v1 = fluid_channel_get_cc(chan, mod->src1);
|
v1 = fluid_channel_get_cc(chan, mod->src1);
|
||||||
} else { /* source 1 is one of the direct controllers */
|
} else { /* source 1 is one of the direct controllers */
|
||||||
switch (mod->src1) {
|
switch (mod->src1) {
|
||||||
case FLUID_MOD_NONE: /* SF 2.01 8.2.1 item 0: src enum=0 => value is 1 */
|
case FLUID_MOD_NONE: /* SF 2.01 8.2.1 item 0: src enum=0 => value is 1 */
|
||||||
v1 = range1;
|
v1 = range1;
|
||||||
break;
|
break;
|
||||||
case FLUID_MOD_VELOCITY:
|
case FLUID_MOD_VELOCITY:
|
||||||
v1 = voice->vel;
|
v1 = voice->vel;
|
||||||
break;
|
break;
|
||||||
case FLUID_MOD_KEY:
|
case FLUID_MOD_KEY:
|
||||||
v1 = voice->key;
|
v1 = voice->key;
|
||||||
break;
|
break;
|
||||||
case FLUID_MOD_KEYPRESSURE:
|
case FLUID_MOD_KEYPRESSURE:
|
||||||
v1 = chan->key_pressure;
|
v1 = chan->key_pressure;
|
||||||
break;
|
break;
|
||||||
case FLUID_MOD_CHANNELPRESSURE:
|
case FLUID_MOD_CHANNELPRESSURE:
|
||||||
v1 = chan->channel_pressure;
|
v1 = chan->channel_pressure;
|
||||||
break;
|
break;
|
||||||
case FLUID_MOD_PITCHWHEEL:
|
case FLUID_MOD_PITCHWHEEL:
|
||||||
v1 = chan->pitch_bend;
|
v1 = chan->pitch_bend;
|
||||||
range1 = 0x4000;
|
range1 = 0x4000;
|
||||||
break;
|
break;
|
||||||
case FLUID_MOD_PITCHWHEELSENS:
|
case FLUID_MOD_PITCHWHEELSENS:
|
||||||
v1 = chan->pitch_wheel_sensitivity;
|
v1 = chan->pitch_wheel_sensitivity;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
v1 = 0.0;
|
v1 = 0.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,7 +192,7 @@ fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voic
|
|||||||
v1 /= range1;
|
v1 /= range1;
|
||||||
break;
|
break;
|
||||||
case 1: /* linear, unipolar, negative */
|
case 1: /* linear, unipolar, negative */
|
||||||
v1 = 1.0f - v1 / range1;
|
v1 = 1.0f - v1 / range1;
|
||||||
break;
|
break;
|
||||||
case 2: /* linear, bipolar, positive */
|
case 2: /* linear, bipolar, positive */
|
||||||
v1 = -1.0f + 2.0f * v1 / range1;
|
v1 = -1.0f + 2.0f * v1 / range1;
|
||||||
@@ -252,29 +252,29 @@ fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voic
|
|||||||
v2 = fluid_channel_get_cc(chan, mod->src2);
|
v2 = fluid_channel_get_cc(chan, mod->src2);
|
||||||
} else {
|
} else {
|
||||||
switch (mod->src2) {
|
switch (mod->src2) {
|
||||||
case FLUID_MOD_NONE: /* SF 2.01 8.2.1 item 0: src enum=0 => value is 1 */
|
case FLUID_MOD_NONE: /* SF 2.01 8.2.1 item 0: src enum=0 => value is 1 */
|
||||||
v2 = range2;
|
v2 = range2;
|
||||||
break;
|
break;
|
||||||
case FLUID_MOD_VELOCITY:
|
case FLUID_MOD_VELOCITY:
|
||||||
v2 = voice->vel;
|
v2 = voice->vel;
|
||||||
break;
|
break;
|
||||||
case FLUID_MOD_KEY:
|
case FLUID_MOD_KEY:
|
||||||
v2 = voice->key;
|
v2 = voice->key;
|
||||||
break;
|
break;
|
||||||
case FLUID_MOD_KEYPRESSURE:
|
case FLUID_MOD_KEYPRESSURE:
|
||||||
v2 = chan->key_pressure;
|
v2 = chan->key_pressure;
|
||||||
break;
|
break;
|
||||||
case FLUID_MOD_CHANNELPRESSURE:
|
case FLUID_MOD_CHANNELPRESSURE:
|
||||||
v2 = chan->channel_pressure;
|
v2 = chan->channel_pressure;
|
||||||
break;
|
break;
|
||||||
case FLUID_MOD_PITCHWHEEL:
|
case FLUID_MOD_PITCHWHEEL:
|
||||||
v2 = chan->pitch_bend;
|
v2 = chan->pitch_bend;
|
||||||
break;
|
break;
|
||||||
case FLUID_MOD_PITCHWHEELSENS:
|
case FLUID_MOD_PITCHWHEELSENS:
|
||||||
v2 = chan->pitch_wheel_sensitivity;
|
v2 = chan->pitch_wheel_sensitivity;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
v1 = 0.0f;
|
v1 = 0.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,7 +284,7 @@ fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voic
|
|||||||
v2 /= range2;
|
v2 /= range2;
|
||||||
break;
|
break;
|
||||||
case 1: /* linear, unipolar, negative */
|
case 1: /* linear, unipolar, negative */
|
||||||
v2 = 1.0f - v2 / range2;
|
v2 = 1.0f - v2 / range2;
|
||||||
break;
|
break;
|
||||||
case 2: /* linear, bipolar, positive */
|
case 2: /* linear, bipolar, positive */
|
||||||
v2 = -1.0f + 2.0f * v2 / range2;
|
v2 = -1.0f + 2.0f * v2 / range2;
|
||||||
@@ -340,12 +340,12 @@ fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voic
|
|||||||
/*
|
/*
|
||||||
* fluid_mod_new
|
* fluid_mod_new
|
||||||
*/
|
*/
|
||||||
fluid_mod_t*
|
fluid_mod_t*
|
||||||
fluid_mod_new()
|
fluid_mod_new()
|
||||||
{
|
{
|
||||||
fluid_mod_t* mod = FLUID_NEW(fluid_mod_t);
|
fluid_mod_t* mod = FLUID_NEW(fluid_mod_t);
|
||||||
if (mod == NULL) {
|
if (mod == NULL) {
|
||||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return mod;
|
return mod;
|
||||||
@@ -362,7 +362,7 @@ fluid_mod_delete(fluid_mod_t * mod)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* fluid_mod_test_identity
|
* fluid_mod_test_identity
|
||||||
*/
|
*/
|
||||||
/* Purpose:
|
/* Purpose:
|
||||||
* Checks, if two modulators are identical.
|
* Checks, if two modulators are identical.
|
||||||
* SF2.01 section 9.5.1 page 69, 'bullet' 3 defines 'identical'.
|
* SF2.01 section 9.5.1 page 69, 'bullet' 3 defines 'identical'.
|
||||||
@@ -384,7 +384,7 @@ void fluid_dump_modulator(fluid_mod_t * mod){
|
|||||||
int flags1=mod->flags1;
|
int flags1=mod->flags1;
|
||||||
int flags2=mod->flags2;
|
int flags2=mod->flags2;
|
||||||
fluid_real_t amount=(fluid_real_t)mod->amount;
|
fluid_real_t amount=(fluid_real_t)mod->amount;
|
||||||
|
|
||||||
printf("Src: ");
|
printf("Src: ");
|
||||||
if (flags1 & FLUID_MOD_CC){
|
if (flags1 & FLUID_MOD_CC){
|
||||||
printf("MIDI CC=%i",src1);
|
printf("MIDI CC=%i",src1);
|
||||||
@@ -408,8 +408,8 @@ void fluid_dump_modulator(fluid_mod_t * mod){
|
|||||||
printf("(unknown: %i)", src1);
|
printf("(unknown: %i)", src1);
|
||||||
}; /* switch src1 */
|
}; /* switch src1 */
|
||||||
}; /* if not CC */
|
}; /* if not CC */
|
||||||
if (flags1 & FLUID_MOD_NEGATIVE){printf("- ");} else {printf("+ ");};
|
if (flags1 & FLUID_MOD_NEGATIVE){printf("- ");} else {printf("+ ");};
|
||||||
if (flags1 & FLUID_MOD_BIPOLAR){printf("bip ");} else {printf("unip ");};
|
if (flags1 & FLUID_MOD_BIPOLAR){printf("bip ");} else {printf("unip ");};
|
||||||
printf("-> ");
|
printf("-> ");
|
||||||
switch(dest){
|
switch(dest){
|
||||||
case GEN_FILTERQ: printf("Q"); break;
|
case GEN_FILTERQ: printf("Q"); break;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
#include "fluid_conv.h"
|
#include "fluid_conv.h"
|
||||||
|
|
||||||
void fluid_mod_clone(fluid_mod_t* mod, fluid_mod_t* src);
|
void fluid_mod_clone(fluid_mod_t* mod, fluid_mod_t* src);
|
||||||
fluid_real_t fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voice);
|
fluid_real_t fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voice);
|
||||||
void fluid_dump_modulator(fluid_mod_t * mod);
|
void fluid_dump_modulator(fluid_mod_t * mod);
|
||||||
|
|
||||||
#define fluid_mod_has_source(mod,cc,ctrl) \
|
#define fluid_mod_has_source(mod,cc,ctrl) \
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -37,141 +37,81 @@
|
|||||||
|
|
||||||
#define FLUID_FRACT_MAX ((double)4294967296.0)
|
#define FLUID_FRACT_MAX ((double)4294967296.0)
|
||||||
|
|
||||||
/* fluid_phase_t
|
/* fluid_phase_t
|
||||||
* Purpose:
|
* Purpose:
|
||||||
* Playing pointer for voice playback
|
* Playing pointer for voice playback
|
||||||
*
|
*
|
||||||
* When a sample is played back at a different pitch, the playing pointer in the
|
* When a sample is played back at a different pitch, the playing pointer in the
|
||||||
* source sample will not advance exactly one sample per output sample.
|
* source sample will not advance exactly one sample per output sample.
|
||||||
* This playing pointer is implemented using fluid_phase_t.
|
* This playing pointer is implemented using fluid_phase_t.
|
||||||
* It is a 64 bit number. The higher 32 bits contain the 'index' (number of
|
* It is a 64 bit number. The higher 32 bits contain the 'index' (number of
|
||||||
* the current sample), the lower 32 bits the fractional part.
|
* the current sample), the lower 32 bits the fractional part.
|
||||||
* Access is possible in two ways:
|
|
||||||
* -through the 64 bit part 'b64', if the architecture supports 64 bit integers
|
|
||||||
* -through 'index' and 'fract'
|
|
||||||
* Note: b64 and index / fract share the same memory location!
|
|
||||||
*/
|
*/
|
||||||
typedef union {
|
typedef unsigned long long fluid_phase_t;
|
||||||
struct{
|
|
||||||
/* Note, that the two 32-bit ints form a 64-bit int! */
|
|
||||||
#ifdef WORDS_BIGENDIAN
|
|
||||||
sint32 index;
|
|
||||||
uint32 fract;
|
|
||||||
#else
|
|
||||||
uint32 fract;
|
|
||||||
sint32 index;
|
|
||||||
#endif
|
|
||||||
} b32;
|
|
||||||
#ifdef USE_LONGLONG
|
|
||||||
long long b64;
|
|
||||||
#endif
|
|
||||||
} fluid_phase_t;
|
|
||||||
|
|
||||||
/* Purpose:
|
/* Purpose:
|
||||||
* Set a to b.
|
* Set a to b.
|
||||||
* a: fluid_phase_t
|
* a: fluid_phase_t
|
||||||
* b: fluid_phase_t
|
* b: fluid_phase_t
|
||||||
*/
|
*/
|
||||||
#ifdef USE_LONGLONG
|
|
||||||
#define fluid_phase_set(a,b) a=b;
|
#define fluid_phase_set(a,b) a=b;
|
||||||
#else
|
|
||||||
#define fluid_phase_set(a, b) { \
|
|
||||||
(a).b32.fract = (b).b32.fract; \
|
|
||||||
(a).b32.index = (b).b32.index; \
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define fluid_phase_set_int(a, b) { \
|
#define fluid_phase_set_int(a, b) ((a) = ((unsigned long long)(b)) << 32)
|
||||||
(a).b32.index = (sint32) (b); \
|
|
||||||
(a).b32.fract = 0; \
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Purpose:
|
/* Purpose:
|
||||||
* Sets the phase a to a phase increment given in b.
|
* Sets the phase a to a phase increment given in b.
|
||||||
* For example, assume b is 0.9. After setting a to it, adding a to
|
* For example, assume b is 0.9. After setting a to it, adding a to
|
||||||
* the playing pointer will advance it by 0.9 samples. */
|
* the playing pointer will advance it by 0.9 samples. */
|
||||||
#define fluid_phase_set_float(a, b) { \
|
#define fluid_phase_set_float(a, b) \
|
||||||
(a).b32.index = (sint32) (b); \
|
(a) = (((unsigned long long)(b)) << 32) \
|
||||||
(a).b32.fract = (uint32) (((double)(b) - (double)((a).b32.index)) * (double)FLUID_FRACT_MAX); \
|
| (uint32) (((double)(b) - (int)(b)) * (double)FLUID_FRACT_MAX)
|
||||||
}
|
|
||||||
|
/* create a fluid_phase_t from an index and a fraction value */
|
||||||
|
#define fluid_phase_from_index_fract(index, fract) \
|
||||||
|
((((unsigned long long)(index)) << 32) + (fract))
|
||||||
|
|
||||||
/* Purpose:
|
/* Purpose:
|
||||||
* Return the index and the fractional part, respectively. */
|
* Return the index and the fractional part, respectively. */
|
||||||
#define fluid_phase_index(_x) \
|
#define fluid_phase_index(_x) \
|
||||||
((int)(_x).b32.index)
|
((unsigned int)((_x) >> 32))
|
||||||
#define fluid_phase_fract(_x) \
|
#define fluid_phase_fract(_x) \
|
||||||
((_x).b32.fract)
|
((uint32)((_x) & 0xFFFFFFFF))
|
||||||
|
|
||||||
|
/* Get the phase index with fractional rounding */
|
||||||
|
#define fluid_phase_index_round(_x) \
|
||||||
|
((unsigned int)(((_x) + 0x80000000) >> 32))
|
||||||
|
|
||||||
|
|
||||||
/* Purpose:
|
/* Purpose:
|
||||||
* Takes the fractional part of the argument phase and
|
* Takes the fractional part of the argument phase and
|
||||||
* calculates the corresponding position in the interpolation table.
|
* calculates the corresponding position in the interpolation table.
|
||||||
* The fractional position of the playing pointer is calculated with a quite high
|
* The fractional position of the playing pointer is calculated with a quite high
|
||||||
* resolution (32 bits). It would be unpractical to keep a set of interpolation
|
* resolution (32 bits). It would be unpractical to keep a set of interpolation
|
||||||
* coefficients for each possible fractional part...
|
* coefficients for each possible fractional part...
|
||||||
*/
|
*/
|
||||||
#define fluid_phase_fract_to_tablerow(_x) \
|
#define fluid_phase_fract_to_tablerow(_x) \
|
||||||
((int)(((_x).b32.fract & FLUID_INTERP_BITS_MASK) >> FLUID_INTERP_BITS_SHIFT))
|
((unsigned int)(fluid_phase_fract(_x) & FLUID_INTERP_BITS_MASK) >> FLUID_INTERP_BITS_SHIFT)
|
||||||
|
|
||||||
#define fluid_phase_double(_x) \
|
#define fluid_phase_double(_x) \
|
||||||
((double)((_x).b32.index) + ((double)((_x).b32.fract) / FLUID_FRACT_MAX))
|
((double)(fluid_phase_index(_x)) + ((double)fluid_phase_fract(_x) / FLUID_FRACT_MAX))
|
||||||
|
|
||||||
/* Purpose:
|
/* Purpose:
|
||||||
* Advance a by a step of b (both are fluid_phase_t).
|
* Advance a by a step of b (both are fluid_phase_t).
|
||||||
*/
|
*/
|
||||||
#ifdef USE_LONGLONG
|
#define fluid_phase_incr(a, b) a += b
|
||||||
#define fluid_phase_incr(a, b) (a).b64 += (b).b64;
|
|
||||||
#else
|
|
||||||
/* The idea to use (a).index += (b).index + ((a).fract < (b).fract) to
|
|
||||||
handle wrap-arounds comes from Mozilla's macros to handle 64-bit
|
|
||||||
integer on 32-bit platforms. Header prlong.h in the NSPR
|
|
||||||
library. www.mozilla.org. */
|
|
||||||
#define fluid_phase_incr(a, b) { \
|
|
||||||
(a).b32.fract += (b).b32.fract; \
|
|
||||||
(a).b32.index += (b).b32.index + ((a).b32.fract < (b).b32.fract); \
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Purpose:
|
/* Purpose:
|
||||||
* Subtract b from a (both are fluid_phase_t).
|
* Subtract b from a (both are fluid_phase_t).
|
||||||
*/
|
*/
|
||||||
#ifdef USE_LONGLONG
|
#define fluid_phase_decr(a, b) a -= b
|
||||||
#define fluid_phase_decr(a, b) a-=b;
|
|
||||||
#else
|
|
||||||
#define fluid_phase_decr(a, b) { \
|
|
||||||
(a).b32.index -= b.b32.index - ((a).b32.fract < (b).b32.fract); \
|
|
||||||
(a).b32.fract -= b.b32.fract; \
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Purpose:
|
/* Purpose:
|
||||||
* Subtract b samples from a.
|
* Subtract b samples from a.
|
||||||
*/
|
*/
|
||||||
#define fluid_phase_sub_int(a, b) { (a).b32.index -= b; }
|
#define fluid_phase_sub_int(a, b) ((a) -= (unsigned long long)(b) << 32)
|
||||||
|
|
||||||
#if 0
|
|
||||||
#define fluid_phase_fract(_x) \
|
|
||||||
((fluid_real_t)((double)((_x).fract) / FLUID_FRACT_MAX))
|
|
||||||
|
|
||||||
#define fluid_phase_lt(a, b) \
|
|
||||||
(((a).index < (b).index) || (((a).index == (b).index) && ((a).fract < (b).fract)))
|
|
||||||
|
|
||||||
#define fluid_phase_gt(a, b) \
|
|
||||||
(((a).index > (b).index) || (((a).index == (b).index) && ((a).fract > (b).fract)))
|
|
||||||
|
|
||||||
#define fluid_phase_eq(a, b) \
|
|
||||||
(((a).index == (b).index) && ((a).fract == (b).fract))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Purpose:
|
/* Purpose:
|
||||||
* The playing pointer is _phase. How many output samples are produced, until the point _p1 in the sample is reached,
|
* Creates the expression a.index++. */
|
||||||
* if _phase advances in steps of _incr?
|
#define fluid_phase_index_plusplus(a) (((a) += 0x100000000LL)
|
||||||
*/
|
|
||||||
#define fluid_phase_steps(_phase,_index,_incr) \
|
|
||||||
(int)(((double)(_index) - fluid_phase_double(_phase)) / (double)_incr)
|
|
||||||
|
|
||||||
/* Purpose:
|
|
||||||
* Creates the expression a.index++.
|
|
||||||
* It is slightly different, when USE_LONGLONG is turned on. */
|
|
||||||
#define fluid_phase_index_plusplus(a) (((a).b32.index)++)
|
|
||||||
|
|
||||||
#endif /* _FLUID_PHASE_H */
|
#endif /* _FLUID_PHASE_H */
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
#include "fluid_ramsfont.h"
|
#include "fluid_ramsfont.h"
|
||||||
#include "fluid_sys.h"
|
#include "fluid_sys.h"
|
||||||
#include "fluid_synth.h"
|
#include "fluid_synth.h"
|
||||||
|
|
||||||
/* thenumber of samples before the start and after the end */
|
/* thenumber of samples before the start and after the end */
|
||||||
#define SAMPLE_LOOP_MARGIN 8
|
#define SAMPLE_LOOP_MARGIN 8
|
||||||
|
|
||||||
@@ -40,12 +40,12 @@ fluid_ramsfont_create_sfont()
|
|||||||
{
|
{
|
||||||
fluid_sfont_t* sfont;
|
fluid_sfont_t* sfont;
|
||||||
fluid_ramsfont_t* ramsfont;
|
fluid_ramsfont_t* ramsfont;
|
||||||
|
|
||||||
ramsfont = new_fluid_ramsfont();
|
ramsfont = new_fluid_ramsfont();
|
||||||
if (ramsfont == NULL) {
|
if (ramsfont == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
sfont = FLUID_NEW(fluid_sfont_t);
|
sfont = FLUID_NEW(fluid_sfont_t);
|
||||||
if (sfont == NULL) {
|
if (sfont == NULL) {
|
||||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||||
@@ -130,33 +130,35 @@ int fluid_ramsfont_sfont_iteration_next(fluid_sfont_t* sfont, fluid_preset_t* pr
|
|||||||
int fluid_rampreset_preset_delete(fluid_preset_t* preset)
|
int fluid_rampreset_preset_delete(fluid_preset_t* preset)
|
||||||
{
|
{
|
||||||
FLUID_FREE(preset);
|
FLUID_FREE(preset);
|
||||||
printf("TODO: free modulators\n");
|
|
||||||
|
/* TODO: free modulators */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* fluid_rampreset_preset_get_name(fluid_preset_t* preset)
|
char* fluid_rampreset_preset_get_name(fluid_preset_t* preset)
|
||||||
{
|
{
|
||||||
return fluid_rampreset_get_name((fluid_rampreset_t*) preset->data);
|
return fluid_rampreset_get_name((fluid_rampreset_t*) preset->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fluid_rampreset_preset_get_banknum(fluid_preset_t* preset)
|
int fluid_rampreset_preset_get_banknum(fluid_preset_t* preset)
|
||||||
{
|
{
|
||||||
return fluid_rampreset_get_banknum((fluid_rampreset_t*) preset->data);
|
return fluid_rampreset_get_banknum((fluid_rampreset_t*) preset->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fluid_rampreset_preset_get_num(fluid_preset_t* preset)
|
int fluid_rampreset_preset_get_num(fluid_preset_t* preset)
|
||||||
{
|
{
|
||||||
return fluid_rampreset_get_num((fluid_rampreset_t*) preset->data);
|
return fluid_rampreset_get_num((fluid_rampreset_t*) preset->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fluid_rampreset_preset_noteon(fluid_preset_t* preset, fluid_synth_t* synth, int chan, int key, int vel)
|
int fluid_rampreset_preset_noteon(fluid_preset_t* preset, fluid_synth_t* synth, int chan, int key, int vel)
|
||||||
{
|
{
|
||||||
return fluid_rampreset_noteon((fluid_rampreset_t*) preset->data, synth, chan, key, vel);
|
return fluid_rampreset_noteon((fluid_rampreset_t*) preset->data, synth, chan, key, vel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************
|
/***************************************************************
|
||||||
*
|
*
|
||||||
* SFONT
|
* SFONT
|
||||||
@@ -214,7 +216,7 @@ int delete_fluid_ramsfont(fluid_ramsfont_t* sfont)
|
|||||||
delete_fluid_rampreset(preset);
|
delete_fluid_rampreset(preset);
|
||||||
preset = sfont->preset;
|
preset = sfont->preset;
|
||||||
}
|
}
|
||||||
|
|
||||||
FLUID_FREE(sfont);
|
FLUID_FREE(sfont);
|
||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
@@ -242,7 +244,7 @@ fluid_ramsfont_set_name(fluid_ramsfont_t* sfont, char * name)
|
|||||||
*
|
*
|
||||||
* Add a preset to the SoundFont
|
* Add a preset to the SoundFont
|
||||||
*/
|
*/
|
||||||
int fluid_ramsfont_add_preset(fluid_ramsfont_t* sfont, fluid_rampreset_t* preset)
|
int fluid_ramsfont_add_preset(fluid_ramsfont_t* sfont, fluid_rampreset_t* preset)
|
||||||
{
|
{
|
||||||
fluid_rampreset_t *cur, *prev;
|
fluid_rampreset_t *cur, *prev;
|
||||||
if (sfont->preset == NULL) {
|
if (sfont->preset == NULL) {
|
||||||
@@ -253,7 +255,7 @@ int fluid_ramsfont_add_preset(fluid_ramsfont_t* sfont, fluid_rampreset_t* preset
|
|||||||
cur = sfont->preset;
|
cur = sfont->preset;
|
||||||
prev = NULL;
|
prev = NULL;
|
||||||
while (cur != NULL) {
|
while (cur != NULL) {
|
||||||
if ((preset->bank < cur->bank)
|
if ((preset->bank < cur->bank)
|
||||||
|| ((preset->bank == cur->bank) && (preset->num < cur->num))) {
|
|| ((preset->bank == cur->bank) && (preset->num < cur->num))) {
|
||||||
if (prev == NULL) {
|
if (prev == NULL) {
|
||||||
preset->next = cur;
|
preset->next = cur;
|
||||||
@@ -285,7 +287,7 @@ int fluid_ramsfont_add_izone(fluid_ramsfont_t* sfont,
|
|||||||
- add the sample to the list of samples
|
- add the sample to the list of samples
|
||||||
*/
|
*/
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
fluid_rampreset_t* preset = fluid_ramsfont_get_preset(sfont, bank, num);
|
fluid_rampreset_t* preset = fluid_ramsfont_get_preset(sfont, bank, num);
|
||||||
if (preset == NULL) {
|
if (preset == NULL) {
|
||||||
// Create it
|
// Create it
|
||||||
@@ -293,27 +295,27 @@ int fluid_ramsfont_add_izone(fluid_ramsfont_t* sfont,
|
|||||||
if (preset == NULL) {
|
if (preset == NULL) {
|
||||||
return FLUID_FAILED;
|
return FLUID_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
preset->bank = bank;
|
preset->bank = bank;
|
||||||
preset->num = num;
|
preset->num = num;
|
||||||
|
|
||||||
err = fluid_rampreset_add_sample(preset, sample, lokey, hikey);
|
err = fluid_rampreset_add_sample(preset, sample, lokey, hikey);
|
||||||
if (err != FLUID_OK) {
|
if (err != FLUID_OK) {
|
||||||
return FLUID_FAILED;
|
return FLUID_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort the preset
|
// sort the preset
|
||||||
fluid_ramsfont_add_preset(sfont, preset);
|
fluid_ramsfont_add_preset(sfont, preset);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// just add it
|
// just add it
|
||||||
err = fluid_rampreset_add_sample(preset, sample, lokey, hikey);
|
err = fluid_rampreset_add_sample(preset, sample, lokey, hikey);
|
||||||
if (err != FLUID_OK) {
|
if (err != FLUID_OK) {
|
||||||
return FLUID_FAILED;
|
return FLUID_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sfont->sample = fluid_list_append(sfont->sample, sample);
|
sfont->sample = fluid_list_append(sfont->sample, sample);
|
||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
@@ -343,12 +345,12 @@ int fluid_ramsfont_remove_izone(fluid_ramsfont_t* sfont,
|
|||||||
int fluid_ramsfont_izone_set_gen(fluid_ramsfont_t* sfont,
|
int fluid_ramsfont_izone_set_gen(fluid_ramsfont_t* sfont,
|
||||||
unsigned int bank, unsigned int num, fluid_sample_t* sample,
|
unsigned int bank, unsigned int num, fluid_sample_t* sample,
|
||||||
int gen_type, float value) {
|
int gen_type, float value) {
|
||||||
|
|
||||||
fluid_rampreset_t* preset = fluid_ramsfont_get_preset(sfont, bank, num);
|
fluid_rampreset_t* preset = fluid_ramsfont_get_preset(sfont, bank, num);
|
||||||
if (preset == NULL) {
|
if (preset == NULL) {
|
||||||
return FLUID_FAILED;
|
return FLUID_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
return fluid_rampreset_izone_set_gen(preset, sample, gen_type, value);
|
return fluid_rampreset_izone_set_gen(preset, sample, gen_type, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,14 +362,14 @@ int fluid_ramsfont_izone_set_loop(fluid_ramsfont_t* sfont,
|
|||||||
if (preset == NULL) {
|
if (preset == NULL) {
|
||||||
return FLUID_FAILED;
|
return FLUID_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
return fluid_rampreset_izone_set_loop(preset, sample, on, loopstart, loopend);
|
return fluid_rampreset_izone_set_loop(preset, sample, on, loopstart, loopend);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* fluid_ramsfont_get_preset
|
* fluid_ramsfont_get_preset
|
||||||
*/
|
*/
|
||||||
fluid_rampreset_t* fluid_ramsfont_get_preset(fluid_ramsfont_t* sfont, unsigned int bank, unsigned int num)
|
fluid_rampreset_t* fluid_ramsfont_get_preset(fluid_ramsfont_t* sfont, unsigned int bank, unsigned int num)
|
||||||
{
|
{
|
||||||
fluid_rampreset_t* preset = sfont->preset;
|
fluid_rampreset_t* preset = sfont->preset;
|
||||||
while (preset != NULL) {
|
while (preset != NULL) {
|
||||||
@@ -415,12 +417,12 @@ struct _fluid_rampreset_voice_t {
|
|||||||
/*
|
/*
|
||||||
* new_fluid_rampreset
|
* new_fluid_rampreset
|
||||||
*/
|
*/
|
||||||
fluid_rampreset_t*
|
fluid_rampreset_t*
|
||||||
new_fluid_rampreset(fluid_ramsfont_t* sfont)
|
new_fluid_rampreset(fluid_ramsfont_t* sfont)
|
||||||
{
|
{
|
||||||
fluid_rampreset_t* preset = FLUID_NEW(fluid_rampreset_t);
|
fluid_rampreset_t* preset = FLUID_NEW(fluid_rampreset_t);
|
||||||
if (preset == NULL) {
|
if (preset == NULL) {
|
||||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
preset->next = NULL;
|
preset->next = NULL;
|
||||||
@@ -437,13 +439,13 @@ new_fluid_rampreset(fluid_ramsfont_t* sfont)
|
|||||||
/*
|
/*
|
||||||
* delete_fluid_rampreset
|
* delete_fluid_rampreset
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
delete_fluid_rampreset(fluid_rampreset_t* preset)
|
delete_fluid_rampreset(fluid_rampreset_t* preset)
|
||||||
{
|
{
|
||||||
int err = FLUID_OK;
|
int err = FLUID_OK;
|
||||||
fluid_preset_zone_t* zone;
|
fluid_preset_zone_t* zone;
|
||||||
fluid_rampreset_voice_t *data;
|
fluid_rampreset_voice_t *data;
|
||||||
|
|
||||||
if (preset->global_zone != NULL) {
|
if (preset->global_zone != NULL) {
|
||||||
if (delete_fluid_preset_zone(preset->global_zone) != FLUID_OK) {
|
if (delete_fluid_preset_zone(preset->global_zone) != FLUID_OK) {
|
||||||
err = FLUID_FAILED;
|
err = FLUID_FAILED;
|
||||||
@@ -458,37 +460,37 @@ delete_fluid_rampreset(fluid_rampreset_t* preset)
|
|||||||
}
|
}
|
||||||
zone = preset->zone;
|
zone = preset->zone;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preset->presetvoices != NULL) {
|
if (preset->presetvoices != NULL) {
|
||||||
fluid_list_t *tmp = preset->presetvoices, *next;
|
fluid_list_t *tmp = preset->presetvoices, *next;
|
||||||
while (tmp) {
|
while (tmp) {
|
||||||
data = (fluid_rampreset_voice_t *)(tmp->data);
|
data = (fluid_rampreset_voice_t *)(tmp->data);
|
||||||
FLUID_FREE(data);
|
FLUID_FREE(data);
|
||||||
|
|
||||||
next = tmp->next;
|
next = tmp->next;
|
||||||
FLUID_FREE(tmp);
|
FLUID_FREE(tmp);
|
||||||
tmp = next;
|
tmp = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
preset->presetvoices = NULL;
|
preset->presetvoices = NULL;
|
||||||
|
|
||||||
FLUID_FREE(preset);
|
FLUID_FREE(preset);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
fluid_rampreset_get_banknum(fluid_rampreset_t* preset)
|
fluid_rampreset_get_banknum(fluid_rampreset_t* preset)
|
||||||
{
|
{
|
||||||
return preset->bank;
|
return preset->bank;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
fluid_rampreset_get_num(fluid_rampreset_t* preset)
|
fluid_rampreset_get_num(fluid_rampreset_t* preset)
|
||||||
{
|
{
|
||||||
return preset->num;
|
return preset->num;
|
||||||
}
|
}
|
||||||
|
|
||||||
char*
|
char*
|
||||||
fluid_rampreset_get_name(fluid_rampreset_t* preset)
|
fluid_rampreset_get_name(fluid_rampreset_t* preset)
|
||||||
{
|
{
|
||||||
return preset->name;
|
return preset->name;
|
||||||
@@ -497,7 +499,7 @@ fluid_rampreset_get_name(fluid_rampreset_t* preset)
|
|||||||
/*
|
/*
|
||||||
* fluid_rampreset_next
|
* fluid_rampreset_next
|
||||||
*/
|
*/
|
||||||
fluid_rampreset_t*
|
fluid_rampreset_t*
|
||||||
fluid_rampreset_next(fluid_rampreset_t* preset)
|
fluid_rampreset_next(fluid_rampreset_t* preset)
|
||||||
{
|
{
|
||||||
return preset->next;
|
return preset->next;
|
||||||
@@ -507,7 +509,7 @@ fluid_rampreset_next(fluid_rampreset_t* preset)
|
|||||||
/*
|
/*
|
||||||
* fluid_rampreset_add_zone
|
* fluid_rampreset_add_zone
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
fluid_rampreset_add_zone(fluid_rampreset_t* preset, fluid_preset_zone_t* zone)
|
fluid_rampreset_add_zone(fluid_rampreset_t* preset, fluid_preset_zone_t* zone)
|
||||||
{
|
{
|
||||||
if (preset->zone == NULL) {
|
if (preset->zone == NULL) {
|
||||||
@@ -527,7 +529,7 @@ fluid_rampreset_add_zone(fluid_rampreset_t* preset, fluid_preset_zone_t* zone)
|
|||||||
int fluid_rampreset_add_sample(fluid_rampreset_t* preset, fluid_sample_t* sample, int lokey, int hikey)
|
int fluid_rampreset_add_sample(fluid_rampreset_t* preset, fluid_sample_t* sample, int lokey, int hikey)
|
||||||
{
|
{
|
||||||
/* create a new instrument zone, with the given sample */
|
/* create a new instrument zone, with the given sample */
|
||||||
|
|
||||||
/* one preset zone */
|
/* one preset zone */
|
||||||
if (preset->zone == NULL) {
|
if (preset->zone == NULL) {
|
||||||
fluid_preset_zone_t* zone;
|
fluid_preset_zone_t* zone;
|
||||||
@@ -535,17 +537,17 @@ int fluid_rampreset_add_sample(fluid_rampreset_t* preset, fluid_sample_t* sample
|
|||||||
if (zone == NULL) {
|
if (zone == NULL) {
|
||||||
return FLUID_FAILED;
|
return FLUID_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* its instrument */
|
/* its instrument */
|
||||||
zone->inst = (fluid_inst_t*) new_fluid_inst();
|
zone->inst = (fluid_inst_t*) new_fluid_inst();
|
||||||
if (zone->inst == NULL) {
|
if (zone->inst == NULL) {
|
||||||
delete_fluid_preset_zone(zone);
|
delete_fluid_preset_zone(zone);
|
||||||
return FLUID_FAILED;
|
return FLUID_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
fluid_rampreset_add_zone(preset, zone);
|
fluid_rampreset_add_zone(preset, zone);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add an instrument zone for each sample */
|
/* add an instrument zone for each sample */
|
||||||
{
|
{
|
||||||
fluid_inst_t* inst = fluid_preset_zone_get_inst(preset->zone);
|
fluid_inst_t* inst = fluid_preset_zone_get_inst(preset->zone);
|
||||||
@@ -553,20 +555,20 @@ int fluid_rampreset_add_sample(fluid_rampreset_t* preset, fluid_sample_t* sample
|
|||||||
if (izone == NULL) {
|
if (izone == NULL) {
|
||||||
return FLUID_FAILED;
|
return FLUID_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fluid_inst_add_zone(inst, izone) != FLUID_OK) {
|
if (fluid_inst_add_zone(inst, izone) != FLUID_OK) {
|
||||||
delete_fluid_inst_zone(izone);
|
delete_fluid_inst_zone(izone);
|
||||||
return FLUID_FAILED;
|
return FLUID_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
izone->sample = sample;
|
izone->sample = sample;
|
||||||
izone->keylo = lokey;
|
izone->keylo = lokey;
|
||||||
izone->keyhi = hikey;
|
izone->keyhi = hikey;
|
||||||
|
|
||||||
// give the preset the name of the sample
|
// give the preset the name of the sample
|
||||||
FLUID_MEMCPY(preset->name, sample->name, 20);
|
FLUID_MEMCPY(preset->name, sample->name, 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -574,9 +576,9 @@ fluid_inst_zone_t* fluid_rampreset_izoneforsample(fluid_rampreset_t* preset, flu
|
|||||||
{
|
{
|
||||||
fluid_inst_t* inst;
|
fluid_inst_t* inst;
|
||||||
fluid_inst_zone_t* izone;
|
fluid_inst_zone_t* izone;
|
||||||
|
|
||||||
if (preset->zone == NULL) return NULL;
|
if (preset->zone == NULL) return NULL;
|
||||||
|
|
||||||
inst = fluid_preset_zone_get_inst(preset->zone);
|
inst = fluid_preset_zone_get_inst(preset->zone);
|
||||||
izone = inst->zone;
|
izone = inst->zone;
|
||||||
while (izone) {
|
while (izone) {
|
||||||
@@ -591,17 +593,17 @@ int fluid_rampreset_izone_set_loop(fluid_rampreset_t* preset, fluid_sample_t* sa
|
|||||||
int on, float loopstart, float loopend) {
|
int on, float loopstart, float loopend) {
|
||||||
fluid_inst_zone_t* izone = fluid_rampreset_izoneforsample(preset, sample);
|
fluid_inst_zone_t* izone = fluid_rampreset_izoneforsample(preset, sample);
|
||||||
short coarse, fine;
|
short coarse, fine;
|
||||||
|
|
||||||
if (izone == NULL)
|
if (izone == NULL)
|
||||||
return FLUID_FAILED;
|
return FLUID_FAILED;
|
||||||
|
|
||||||
if (!on) {
|
if (!on) {
|
||||||
izone->gen[GEN_SAMPLEMODE].flags = GEN_SET;
|
izone->gen[GEN_SAMPLEMODE].flags = GEN_SET;
|
||||||
izone->gen[GEN_SAMPLEMODE].val = FLUID_UNLOOPED;
|
izone->gen[GEN_SAMPLEMODE].val = FLUID_UNLOOPED;
|
||||||
fluid_rampreset_updatevoices(preset, GEN_SAMPLEMODE, FLUID_UNLOOPED);
|
fluid_rampreset_updatevoices(preset, GEN_SAMPLEMODE, FLUID_UNLOOPED);
|
||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NOTE : We should check that (sample->startloop + loopStart <= sample->endloop - loopend - 32) */
|
/* NOTE : We should check that (sample->startloop + loopStart <= sample->endloop - loopend - 32) */
|
||||||
|
|
||||||
/* loopstart */
|
/* loopstart */
|
||||||
@@ -645,12 +647,12 @@ int fluid_rampreset_izone_set_loop(fluid_rampreset_t* preset, fluid_sample_t* sa
|
|||||||
izone->gen[GEN_SAMPLEMODE].flags = GEN_SET;
|
izone->gen[GEN_SAMPLEMODE].flags = GEN_SET;
|
||||||
izone->gen[GEN_SAMPLEMODE].val = FLUID_LOOP_DURING_RELEASE;
|
izone->gen[GEN_SAMPLEMODE].val = FLUID_LOOP_DURING_RELEASE;
|
||||||
fluid_rampreset_updatevoices(preset, GEN_SAMPLEMODE, FLUID_LOOP_DURING_RELEASE);
|
fluid_rampreset_updatevoices(preset, GEN_SAMPLEMODE, FLUID_LOOP_DURING_RELEASE);
|
||||||
|
|
||||||
/* If the loop points are the whole samples, we are supposed to
|
/* If the loop points are the whole samples, we are supposed to
|
||||||
copy the frames around in the margins (the start to the end margin and
|
copy the frames around in the margins (the start to the end margin and
|
||||||
the end to the start margin), but it works fine without this. Maybe some time
|
the end to the start margin), but it works fine without this. Maybe some time
|
||||||
it will be needed (see SAMPLE_LOOP_MARGIN) -- Antoie Schmitt May 2003 */
|
it will be needed (see SAMPLE_LOOP_MARGIN) -- Antoie Schmitt May 2003 */
|
||||||
|
|
||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -659,12 +661,12 @@ int fluid_rampreset_izone_set_gen(fluid_rampreset_t* preset, fluid_sample_t* sam
|
|||||||
fluid_inst_zone_t* izone = fluid_rampreset_izoneforsample(preset, sample);
|
fluid_inst_zone_t* izone = fluid_rampreset_izoneforsample(preset, sample);
|
||||||
if (izone == NULL)
|
if (izone == NULL)
|
||||||
return FLUID_FAILED;
|
return FLUID_FAILED;
|
||||||
|
|
||||||
izone->gen[gen_type].flags = GEN_SET;
|
izone->gen[gen_type].flags = GEN_SET;
|
||||||
izone->gen[gen_type].val = value;
|
izone->gen[gen_type].val = value;
|
||||||
|
|
||||||
fluid_rampreset_updatevoices(preset, gen_type, value);
|
fluid_rampreset_updatevoices(preset, gen_type, value);
|
||||||
|
|
||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -672,7 +674,7 @@ int fluid_rampreset_remove_izone(fluid_rampreset_t* preset, fluid_sample_t* samp
|
|||||||
fluid_inst_t* inst;
|
fluid_inst_t* inst;
|
||||||
fluid_inst_zone_t* izone, * prev;
|
fluid_inst_zone_t* izone, * prev;
|
||||||
int found = 0;
|
int found = 0;
|
||||||
|
|
||||||
if (preset->zone == NULL) return FLUID_FAILED;
|
if (preset->zone == NULL) return FLUID_FAILED;
|
||||||
inst = fluid_preset_zone_get_inst(preset->zone);
|
inst = fluid_preset_zone_get_inst(preset->zone);
|
||||||
izone = inst->zone;
|
izone = inst->zone;
|
||||||
@@ -694,7 +696,7 @@ int fluid_rampreset_remove_izone(fluid_rampreset_t* preset, fluid_sample_t* samp
|
|||||||
}
|
}
|
||||||
if (!found)
|
if (!found)
|
||||||
return FLUID_FAILED;
|
return FLUID_FAILED;
|
||||||
|
|
||||||
// stop all the voices that use this sample, so that
|
// stop all the voices that use this sample, so that
|
||||||
// the sample can be cleared up
|
// the sample can be cleared up
|
||||||
{
|
{
|
||||||
@@ -719,23 +721,23 @@ int fluid_rampreset_remove_izone(fluid_rampreset_t* preset, fluid_sample_t* samp
|
|||||||
/*
|
/*
|
||||||
* fluid_rampreset_remembervoice
|
* fluid_rampreset_remembervoice
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
fluid_rampreset_remembervoice(fluid_rampreset_t* preset, fluid_voice_t* voice) {
|
fluid_rampreset_remembervoice(fluid_rampreset_t* preset, fluid_voice_t* voice) {
|
||||||
/* stores the voice and the its ID in the preset for later update on gen_set */
|
/* stores the voice and the its ID in the preset for later update on gen_set */
|
||||||
fluid_rampreset_voice_t *presetvoice = FLUID_NEW(fluid_rampreset_voice_t);
|
fluid_rampreset_voice_t *presetvoice = FLUID_NEW(fluid_rampreset_voice_t);
|
||||||
if (presetvoice == NULL) {
|
if (presetvoice == NULL) {
|
||||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||||
return FLUID_FAILED;
|
return FLUID_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
presetvoice->voice = voice;
|
presetvoice->voice = voice;
|
||||||
presetvoice->voiceID = fluid_voice_get_id(voice);
|
presetvoice->voiceID = fluid_voice_get_id(voice);
|
||||||
|
|
||||||
preset->presetvoices = fluid_list_append(preset->presetvoices, (void *)presetvoice);
|
preset->presetvoices = fluid_list_append(preset->presetvoices, (void *)presetvoice);
|
||||||
if (preset->presetvoices == NULL) {
|
if (preset->presetvoices == NULL) {
|
||||||
FLUID_FREE(presetvoice);
|
FLUID_FREE(presetvoice);
|
||||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||||
return FLUID_FAILED;
|
return FLUID_FAILED;
|
||||||
}
|
}
|
||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
@@ -743,10 +745,10 @@ fluid_rampreset_remembervoice(fluid_rampreset_t* preset, fluid_voice_t* voice) {
|
|||||||
/*
|
/*
|
||||||
* fluid_rampreset_updatevoice
|
* fluid_rampreset_updatevoice
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
fluid_rampreset_updatevoices(fluid_rampreset_t* preset, int gen_type, float val) {
|
fluid_rampreset_updatevoices(fluid_rampreset_t* preset, int gen_type, float val) {
|
||||||
fluid_list_t *tmp = preset->presetvoices, *prev = NULL, *next;
|
fluid_list_t *tmp = preset->presetvoices, *prev = NULL, *next;
|
||||||
|
|
||||||
/* walk the presetvoice to update them if they are still active and ours.
|
/* walk the presetvoice to update them if they are still active and ours.
|
||||||
If their ID has changed or their state is not playing, they are not ours, so we forget them
|
If their ID has changed or their state is not playing, they are not ours, so we forget them
|
||||||
*/
|
*/
|
||||||
@@ -756,7 +758,7 @@ fluid_rampreset_updatevoices(fluid_rampreset_t* preset, int gen_type, float val)
|
|||||||
if (!fluid_voice_is_playing(voice) || (fluid_voice_get_id(voice) != presetvoice->voiceID)) {
|
if (!fluid_voice_is_playing(voice) || (fluid_voice_get_id(voice) != presetvoice->voiceID)) {
|
||||||
/* forget it */
|
/* forget it */
|
||||||
FLUID_FREE(presetvoice);
|
FLUID_FREE(presetvoice);
|
||||||
|
|
||||||
/* unlink it */
|
/* unlink it */
|
||||||
next = tmp->next;
|
next = tmp->next;
|
||||||
FLUID_FREE(tmp);
|
FLUID_FREE(tmp);
|
||||||
@@ -764,15 +766,15 @@ fluid_rampreset_updatevoices(fluid_rampreset_t* preset, int gen_type, float val)
|
|||||||
prev->next = next;
|
prev->next = next;
|
||||||
} else {
|
} else {
|
||||||
preset->presetvoices = next;
|
preset->presetvoices = next;
|
||||||
}
|
}
|
||||||
tmp = next;
|
tmp = next;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* update */
|
/* update */
|
||||||
fluid_voice_gen_set(voice, gen_type, val);
|
fluid_voice_gen_set(voice, gen_type, val);
|
||||||
fluid_voice_update_param(voice, gen_type);
|
fluid_voice_update_param(voice, gen_type);
|
||||||
|
|
||||||
/* next */
|
/* next */
|
||||||
prev = tmp;
|
prev = tmp;
|
||||||
tmp = tmp->next;
|
tmp = tmp->next;
|
||||||
@@ -784,8 +786,8 @@ fluid_rampreset_updatevoices(fluid_rampreset_t* preset, int gen_type, float val)
|
|||||||
/*
|
/*
|
||||||
* fluid_rampreset_noteon
|
* fluid_rampreset_noteon
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan, int key, int vel)
|
fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan, int key, int vel)
|
||||||
{
|
{
|
||||||
fluid_preset_zone_t *preset_zone;
|
fluid_preset_zone_t *preset_zone;
|
||||||
fluid_inst_t* inst;
|
fluid_inst_t* inst;
|
||||||
@@ -796,7 +798,7 @@ fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan
|
|||||||
fluid_mod_t * mod_list[FLUID_NUM_MOD]; /* list for 'sorting' preset modulators */
|
fluid_mod_t * mod_list[FLUID_NUM_MOD]; /* list for 'sorting' preset modulators */
|
||||||
int mod_list_count;
|
int mod_list_count;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* run thru all the zones of this preset */
|
/* run thru all the zones of this preset */
|
||||||
preset_zone = preset->zone;
|
preset_zone = preset->zone;
|
||||||
while (preset_zone != NULL) {
|
while (preset_zone != NULL) {
|
||||||
@@ -804,45 +806,45 @@ fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan
|
|||||||
/* check if the note falls into the key and velocity range of this
|
/* check if the note falls into the key and velocity range of this
|
||||||
preset */
|
preset */
|
||||||
if (fluid_preset_zone_inside_range(preset_zone, key, vel)) {
|
if (fluid_preset_zone_inside_range(preset_zone, key, vel)) {
|
||||||
|
|
||||||
inst = fluid_preset_zone_get_inst(preset_zone);
|
inst = fluid_preset_zone_get_inst(preset_zone);
|
||||||
global_inst_zone = fluid_inst_get_global_zone(inst);
|
global_inst_zone = fluid_inst_get_global_zone(inst);
|
||||||
|
|
||||||
/* run thru all the zones of this instrument */
|
/* run thru all the zones of this instrument */
|
||||||
inst_zone = fluid_inst_get_zone(inst);
|
inst_zone = fluid_inst_get_zone(inst);
|
||||||
while (inst_zone != NULL) {
|
while (inst_zone != NULL) {
|
||||||
|
|
||||||
/* make sure this instrument zone has a valid sample */
|
/* make sure this instrument zone has a valid sample */
|
||||||
sample = fluid_inst_zone_get_sample(inst_zone);
|
sample = fluid_inst_zone_get_sample(inst_zone);
|
||||||
if (fluid_sample_in_rom(sample) || (sample == NULL)) {
|
if (fluid_sample_in_rom(sample) || (sample == NULL)) {
|
||||||
inst_zone = fluid_inst_zone_next(inst_zone);
|
inst_zone = fluid_inst_zone_next(inst_zone);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check if the note falls into the key and velocity range of this
|
/* check if the note falls into the key and velocity range of this
|
||||||
instrument */
|
instrument */
|
||||||
|
|
||||||
if (fluid_inst_zone_inside_range(inst_zone, key, vel) && (sample != NULL)) {
|
if (fluid_inst_zone_inside_range(inst_zone, key, vel) && (sample != NULL)) {
|
||||||
|
|
||||||
/* this is a good zone. allocate a new synthesis process and
|
/* this is a good zone. allocate a new synthesis process and
|
||||||
initialize it */
|
initialize it */
|
||||||
|
|
||||||
voice = fluid_synth_alloc_voice(synth, sample, chan, key, vel);
|
voice = fluid_synth_alloc_voice(synth, sample, chan, key, vel);
|
||||||
if (voice == NULL) {
|
if (voice == NULL) {
|
||||||
return FLUID_FAILED;
|
return FLUID_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fluid_rampreset_remembervoice(preset, voice) != FLUID_OK) {
|
if (fluid_rampreset_remembervoice(preset, voice) != FLUID_OK) {
|
||||||
return FLUID_FAILED;
|
return FLUID_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
z = inst_zone;
|
z = inst_zone;
|
||||||
|
|
||||||
/* Instrument level, generators */
|
/* Instrument level, generators */
|
||||||
|
|
||||||
for (i = 0; i < GEN_LAST; i++) {
|
for (i = 0; i < GEN_LAST; i++) {
|
||||||
|
|
||||||
/* SF 2.01 section 9.4 'bullet' 4:
|
/* SF 2.01 section 9.4 'bullet' 4:
|
||||||
*
|
*
|
||||||
* A generator in a local instrument zone supersedes a
|
* A generator in a local instrument zone supersedes a
|
||||||
* global instrument zone generator. Both cases supersede
|
* global instrument zone generator. Both cases supersede
|
||||||
@@ -852,7 +854,7 @@ fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan
|
|||||||
fluid_voice_gen_set(voice, i, inst_zone->gen[i].val);
|
fluid_voice_gen_set(voice, i, inst_zone->gen[i].val);
|
||||||
|
|
||||||
} else if (global_inst_zone != NULL && global_inst_zone->gen[i].flags){
|
} else if (global_inst_zone != NULL && global_inst_zone->gen[i].flags){
|
||||||
fluid_voice_gen_set(voice, i, global_inst_zone->gen[i].val);
|
fluid_voice_gen_set(voice, i, global_inst_zone->gen[i].val);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* The generator has not been defined in this instrument.
|
/* The generator has not been defined in this instrument.
|
||||||
@@ -861,7 +863,7 @@ fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan
|
|||||||
};
|
};
|
||||||
|
|
||||||
}; /* for all generators */
|
}; /* for all generators */
|
||||||
|
|
||||||
/* global instrument zone, modulators: Put them all into a
|
/* global instrument zone, modulators: Put them all into a
|
||||||
* list. */
|
* list. */
|
||||||
|
|
||||||
@@ -874,7 +876,7 @@ fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan
|
|||||||
mod = mod->next;
|
mod = mod->next;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/* local instrument zone, modulators.
|
/* local instrument zone, modulators.
|
||||||
* Replace modulators with the same definition in the list:
|
* Replace modulators with the same definition in the list:
|
||||||
* SF 2.01 page 69, 'bullet' 8
|
* SF 2.01 page 69, 'bullet' 8
|
||||||
@@ -893,7 +895,7 @@ fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan
|
|||||||
mod_list[i] = NULL;
|
mod_list[i] = NULL;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Finally add the new modulator to to the list. */
|
/* Finally add the new modulator to to the list. */
|
||||||
mod_list[mod_list_count++] = mod;
|
mod_list[mod_list_count++] = mod;
|
||||||
mod = mod->next;
|
mod = mod->next;
|
||||||
@@ -918,12 +920,12 @@ fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan
|
|||||||
|
|
||||||
/* SF 2.01 section 8.5 page 58: If some generators are
|
/* SF 2.01 section 8.5 page 58: If some generators are
|
||||||
* encountered at preset level, they should be ignored */
|
* encountered at preset level, they should be ignored */
|
||||||
if ((i != GEN_STARTADDROFS)
|
if ((i != GEN_STARTADDROFS)
|
||||||
&& (i != GEN_ENDADDROFS)
|
&& (i != GEN_ENDADDROFS)
|
||||||
&& (i != GEN_STARTLOOPADDROFS)
|
&& (i != GEN_STARTLOOPADDROFS)
|
||||||
&& (i != GEN_ENDLOOPADDROFS)
|
&& (i != GEN_ENDLOOPADDROFS)
|
||||||
&& (i != GEN_STARTADDRCOARSEOFS)
|
&& (i != GEN_STARTADDRCOARSEOFS)
|
||||||
&& (i != GEN_ENDADDRCOARSEOFS)
|
&& (i != GEN_ENDADDRCOARSEOFS)
|
||||||
&& (i != GEN_STARTLOOPADDRCOARSEOFS)
|
&& (i != GEN_STARTLOOPADDRCOARSEOFS)
|
||||||
&& (i != GEN_KEYNUM)
|
&& (i != GEN_KEYNUM)
|
||||||
&& (i != GEN_VELOCITY)
|
&& (i != GEN_VELOCITY)
|
||||||
@@ -946,8 +948,8 @@ fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan
|
|||||||
};
|
};
|
||||||
}; /* if available at preset level */
|
}; /* if available at preset level */
|
||||||
}; /* for all generators */
|
}; /* for all generators */
|
||||||
|
|
||||||
|
|
||||||
/* Global preset zone, modulators: put them all into a
|
/* Global preset zone, modulators: put them all into a
|
||||||
* list. */
|
* list. */
|
||||||
mod_list_count = 0;
|
mod_list_count = 0;
|
||||||
@@ -963,12 +965,12 @@ fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan
|
|||||||
mod_list[i] = NULL;
|
mod_list[i] = NULL;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Finally add the new modulator to the list. */
|
/* Finally add the new modulator to the list. */
|
||||||
mod_list[mod_list_count++] = mod;
|
mod_list[mod_list_count++] = mod;
|
||||||
mod = mod->next;
|
mod = mod->next;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Add preset modulators (global / local) to the voice. */
|
/* Add preset modulators (global / local) to the voice. */
|
||||||
for (i = 0; i < mod_list_count; i++){
|
for (i = 0; i < mod_list_count; i++){
|
||||||
mod = mod_list[i];
|
mod = mod_list[i];
|
||||||
@@ -979,7 +981,7 @@ fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan
|
|||||||
* page */
|
* page */
|
||||||
fluid_voice_add_mod(voice, mod, FLUID_VOICE_ADD);
|
fluid_voice_add_mod(voice, mod, FLUID_VOICE_ADD);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/* add the synthesis process to the synthesis loop. */
|
/* add the synthesis process to the synthesis loop. */
|
||||||
fluid_synth_start_voice(synth, voice);
|
fluid_synth_start_voice(synth, voice);
|
||||||
@@ -1029,18 +1031,18 @@ fluid_sample_set_sound_data(fluid_sample_t* sample, short *data, unsigned int nb
|
|||||||
/* 16 bit mono 44.1KHz data in */
|
/* 16 bit mono 44.1KHz data in */
|
||||||
/* in all cases, the sample has ownership of the data : it will release it in the end */
|
/* in all cases, the sample has ownership of the data : it will release it in the end */
|
||||||
unsigned int storedNbFrames;
|
unsigned int storedNbFrames;
|
||||||
|
|
||||||
/* in case we already have some data */
|
/* in case we already have some data */
|
||||||
if (sample->data != NULL) {
|
if (sample->data != NULL) {
|
||||||
FLUID_FREE(sample->data);
|
FLUID_FREE(sample->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (copy_data) {
|
if (copy_data) {
|
||||||
|
|
||||||
/* nbframes should be >= 48 (SoundFont specs) */
|
/* nbframes should be >= 48 (SoundFont specs) */
|
||||||
storedNbFrames = nbframes;
|
storedNbFrames = nbframes;
|
||||||
if (storedNbFrames < 48) storedNbFrames = 48;
|
if (storedNbFrames < 48) storedNbFrames = 48;
|
||||||
|
|
||||||
sample->data = FLUID_MALLOC(storedNbFrames*2 + 4*SAMPLE_LOOP_MARGIN);
|
sample->data = FLUID_MALLOC(storedNbFrames*2 + 4*SAMPLE_LOOP_MARGIN);
|
||||||
if (sample->data == NULL) {
|
if (sample->data == NULL) {
|
||||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||||
@@ -1054,7 +1056,7 @@ fluid_sample_set_sound_data(fluid_sample_t* sample, short *data, unsigned int nb
|
|||||||
FLUID_MEMCPY((char*)(sample->data) + 2*SAMPLE_LOOP_MARGIN + storedNbFrames*2, (char*)data, 2*SAMPLE_LOOP_MARGIN);
|
FLUID_MEMCPY((char*)(sample->data) + 2*SAMPLE_LOOP_MARGIN + storedNbFrames*2, (char*)data, 2*SAMPLE_LOOP_MARGIN);
|
||||||
FLUID_MEMCPY((char*)(sample->data), (char*)data + nbframes*2 - 2*SAMPLE_LOOP_MARGIN, 2*SAMPLE_LOOP_MARGIN);
|
FLUID_MEMCPY((char*)(sample->data), (char*)data + nbframes*2 - 2*SAMPLE_LOOP_MARGIN, 2*SAMPLE_LOOP_MARGIN);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* pointers */
|
/* pointers */
|
||||||
/* all from the start of data */
|
/* all from the start of data */
|
||||||
sample->start = SAMPLE_LOOP_MARGIN;
|
sample->start = SAMPLE_LOOP_MARGIN;
|
||||||
@@ -1065,11 +1067,11 @@ fluid_sample_set_sound_data(fluid_sample_t* sample, short *data, unsigned int nb
|
|||||||
sample->start = 0;
|
sample->start = 0;
|
||||||
sample->end = nbframes;
|
sample->end = nbframes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* only used as markers for the LOOP generators : set them on the first real frame */
|
/* only used as markers for the LOOP generators : set them on the first real frame */
|
||||||
sample->loopstart = sample->start;
|
sample->loopstart = sample->start;
|
||||||
sample->loopend = sample->end;
|
sample->loopend = sample->end;
|
||||||
|
|
||||||
sample->samplerate = 44100;
|
sample->samplerate = 44100;
|
||||||
sample->origpitch = rootkey;
|
sample->origpitch = rootkey;
|
||||||
sample->pitchadj = 0;
|
sample->pitchadj = 0;
|
||||||
@@ -1082,7 +1084,7 @@ fluid_sample_set_sound_data(fluid_sample_t* sample, short *data, unsigned int nb
|
|||||||
/*
|
/*
|
||||||
* new_fluid_ramsample
|
* new_fluid_ramsample
|
||||||
*/
|
*/
|
||||||
fluid_sample_t*
|
fluid_sample_t*
|
||||||
new_fluid_ramsample()
|
new_fluid_ramsample()
|
||||||
{
|
{
|
||||||
/* same as new_fluid_sample. Only here so that it is exported */
|
/* same as new_fluid_sample. Only here so that it is exported */
|
||||||
@@ -1090,7 +1092,7 @@ new_fluid_ramsample()
|
|||||||
|
|
||||||
sample = FLUID_NEW(fluid_sample_t);
|
sample = FLUID_NEW(fluid_sample_t);
|
||||||
if (sample == NULL) {
|
if (sample == NULL) {
|
||||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
* REVERB
|
* REVERB
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Denormalising:
|
/* Denormalising:
|
||||||
*
|
*
|
||||||
* According to music-dsp thread 'Denormalise', Pentium processors
|
* According to music-dsp thread 'Denormalise', Pentium processors
|
||||||
* have a hardware 'feature', that is of interest here, related to
|
* have a hardware 'feature', that is of interest here, related to
|
||||||
@@ -76,15 +76,15 @@ void fluid_allpass_init(fluid_allpass* allpass);
|
|||||||
void fluid_allpass_setfeedback(fluid_allpass* allpass, fluid_real_t val);
|
void fluid_allpass_setfeedback(fluid_allpass* allpass, fluid_real_t val);
|
||||||
fluid_real_t fluid_allpass_getfeedback(fluid_allpass* allpass);
|
fluid_real_t fluid_allpass_getfeedback(fluid_allpass* allpass);
|
||||||
|
|
||||||
void
|
void
|
||||||
fluid_allpass_setbuffer(fluid_allpass* allpass, fluid_real_t *buf, int size)
|
fluid_allpass_setbuffer(fluid_allpass* allpass, fluid_real_t *buf, int size)
|
||||||
{
|
{
|
||||||
allpass->bufidx = 0;
|
allpass->bufidx = 0;
|
||||||
allpass->buffer = buf;
|
allpass->buffer = buf;
|
||||||
allpass->bufsize = size;
|
allpass->bufsize = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fluid_allpass_init(fluid_allpass* allpass)
|
fluid_allpass_init(fluid_allpass* allpass)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -95,13 +95,13 @@ fluid_allpass_init(fluid_allpass* allpass)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fluid_allpass_setfeedback(fluid_allpass* allpass, fluid_real_t val)
|
fluid_allpass_setfeedback(fluid_allpass* allpass, fluid_real_t val)
|
||||||
{
|
{
|
||||||
allpass->feedback = val;
|
allpass->feedback = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
fluid_real_t
|
fluid_real_t
|
||||||
fluid_allpass_getfeedback(fluid_allpass* allpass)
|
fluid_allpass_getfeedback(fluid_allpass* allpass)
|
||||||
{
|
{
|
||||||
return allpass->feedback;
|
return allpass->feedback;
|
||||||
@@ -151,16 +151,16 @@ fluid_real_t fluid_comb_getdamp(fluid_comb* comb);
|
|||||||
void fluid_comb_setfeedback(fluid_comb* comb, fluid_real_t val);
|
void fluid_comb_setfeedback(fluid_comb* comb, fluid_real_t val);
|
||||||
fluid_real_t fluid_comb_getfeedback(fluid_comb* comb);
|
fluid_real_t fluid_comb_getfeedback(fluid_comb* comb);
|
||||||
|
|
||||||
void
|
void
|
||||||
fluid_comb_setbuffer(fluid_comb* comb, fluid_real_t *buf, int size)
|
fluid_comb_setbuffer(fluid_comb* comb, fluid_real_t *buf, int size)
|
||||||
{
|
{
|
||||||
comb->filterstore = 0;
|
comb->filterstore = 0;
|
||||||
comb->bufidx = 0;
|
comb->bufidx = 0;
|
||||||
comb->buffer = buf;
|
comb->buffer = buf;
|
||||||
comb->bufsize = size;
|
comb->bufsize = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fluid_comb_init(fluid_comb* comb)
|
fluid_comb_init(fluid_comb* comb)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -171,27 +171,27 @@ fluid_comb_init(fluid_comb* comb)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fluid_comb_setdamp(fluid_comb* comb, fluid_real_t val)
|
fluid_comb_setdamp(fluid_comb* comb, fluid_real_t val)
|
||||||
{
|
{
|
||||||
comb->damp1 = val;
|
comb->damp1 = val;
|
||||||
comb->damp2 = 1 - val;
|
comb->damp2 = 1 - val;
|
||||||
}
|
}
|
||||||
|
|
||||||
fluid_real_t
|
fluid_real_t
|
||||||
fluid_comb_getdamp(fluid_comb* comb)
|
fluid_comb_getdamp(fluid_comb* comb)
|
||||||
{
|
{
|
||||||
return comb->damp1;
|
return comb->damp1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fluid_comb_setfeedback(fluid_comb* comb, fluid_real_t val)
|
fluid_comb_setfeedback(fluid_comb* comb, fluid_real_t val)
|
||||||
{
|
{
|
||||||
comb->feedback = val;
|
comb->feedback = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
fluid_real_t
|
fluid_real_t
|
||||||
fluid_comb_getfeedback(fluid_comb* comb)
|
fluid_comb_getfeedback(fluid_comb* comb)
|
||||||
{
|
{
|
||||||
return comb->feedback;
|
return comb->feedback;
|
||||||
}
|
}
|
||||||
@@ -227,11 +227,11 @@ fluid_comb_getfeedback(fluid_comb* comb)
|
|||||||
#define numallpasses 4
|
#define numallpasses 4
|
||||||
#define fixedgain 0.015f
|
#define fixedgain 0.015f
|
||||||
#define scalewet 3.0f
|
#define scalewet 3.0f
|
||||||
#define scaledamp 0.4f
|
#define scaledamp 1.0f
|
||||||
#define scaleroom 0.28f
|
#define scaleroom 0.28f
|
||||||
#define offsetroom 0.7f
|
#define offsetroom 0.7f
|
||||||
#define initialroom 0.5f
|
#define initialroom 0.5f
|
||||||
#define initialdamp 0.5f
|
#define initialdamp 0.2f
|
||||||
#define initialwet 1
|
#define initialwet 1
|
||||||
#define initialdry 0
|
#define initialdry 0
|
||||||
#define initialwidth 1
|
#define initialwidth 1
|
||||||
@@ -275,7 +275,7 @@ struct _fluid_revmodel_t {
|
|||||||
fluid_real_t width;
|
fluid_real_t width;
|
||||||
fluid_real_t gain;
|
fluid_real_t gain;
|
||||||
/*
|
/*
|
||||||
The following are all declared inline
|
The following are all declared inline
|
||||||
to remove the need for dynamic allocation
|
to remove the need for dynamic allocation
|
||||||
with its subsequent error-checking messiness
|
with its subsequent error-checking messiness
|
||||||
*/
|
*/
|
||||||
@@ -316,7 +316,7 @@ struct _fluid_revmodel_t {
|
|||||||
void fluid_revmodel_update(fluid_revmodel_t* rev);
|
void fluid_revmodel_update(fluid_revmodel_t* rev);
|
||||||
void fluid_revmodel_init(fluid_revmodel_t* rev);
|
void fluid_revmodel_init(fluid_revmodel_t* rev);
|
||||||
|
|
||||||
fluid_revmodel_t*
|
fluid_revmodel_t*
|
||||||
new_fluid_revmodel()
|
new_fluid_revmodel()
|
||||||
{
|
{
|
||||||
fluid_revmodel_t* rev;
|
fluid_revmodel_t* rev;
|
||||||
@@ -376,13 +376,13 @@ new_fluid_revmodel()
|
|||||||
return rev;
|
return rev;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
delete_fluid_revmodel(fluid_revmodel_t* rev)
|
delete_fluid_revmodel(fluid_revmodel_t* rev)
|
||||||
{
|
{
|
||||||
FLUID_FREE(rev);
|
FLUID_FREE(rev);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fluid_revmodel_init(fluid_revmodel_t* rev)
|
fluid_revmodel_init(fluid_revmodel_t* rev)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -396,14 +396,14 @@ fluid_revmodel_init(fluid_revmodel_t* rev)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fluid_revmodel_reset(fluid_revmodel_t* rev)
|
fluid_revmodel_reset(fluid_revmodel_t* rev)
|
||||||
{
|
{
|
||||||
fluid_revmodel_init(rev);
|
fluid_revmodel_init(rev);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fluid_revmodel_processreplace(fluid_revmodel_t* rev, fluid_real_t *in,
|
fluid_revmodel_processreplace(fluid_revmodel_t* rev, fluid_real_t *in,
|
||||||
fluid_real_t *left_out, fluid_real_t *right_out)
|
fluid_real_t *left_out, fluid_real_t *right_out)
|
||||||
{
|
{
|
||||||
int i, k = 0;
|
int i, k = 0;
|
||||||
@@ -412,7 +412,7 @@ fluid_revmodel_processreplace(fluid_revmodel_t* rev, fluid_real_t *in,
|
|||||||
for (k = 0; k < FLUID_BUFSIZE; k++) {
|
for (k = 0; k < FLUID_BUFSIZE; k++) {
|
||||||
|
|
||||||
outL = outR = 0;
|
outL = outR = 0;
|
||||||
|
|
||||||
/* The original Freeverb code expects a stereo signal and 'input'
|
/* The original Freeverb code expects a stereo signal and 'input'
|
||||||
* is set to the sum of the left and right input sample. Since
|
* is set to the sum of the left and right input sample. Since
|
||||||
* this code works on a mono signal, 'input' is set to twice the
|
* this code works on a mono signal, 'input' is set to twice the
|
||||||
@@ -438,10 +438,10 @@ fluid_revmodel_processreplace(fluid_revmodel_t* rev, fluid_real_t *in,
|
|||||||
left_out[k] = outL * rev->wet1 + outR * rev->wet2;
|
left_out[k] = outL * rev->wet1 + outR * rev->wet2;
|
||||||
right_out[k] = outR * rev->wet1 + outL * rev->wet2;
|
right_out[k] = outR * rev->wet1 + outL * rev->wet2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fluid_revmodel_processmix(fluid_revmodel_t* rev, fluid_real_t *in,
|
fluid_revmodel_processmix(fluid_revmodel_t* rev, fluid_real_t *in,
|
||||||
fluid_real_t *left_out, fluid_real_t *right_out)
|
fluid_real_t *left_out, fluid_real_t *right_out)
|
||||||
{
|
{
|
||||||
int i, k = 0;
|
int i, k = 0;
|
||||||
@@ -450,7 +450,7 @@ fluid_revmodel_processmix(fluid_revmodel_t* rev, fluid_real_t *in,
|
|||||||
for (k = 0; k < FLUID_BUFSIZE; k++) {
|
for (k = 0; k < FLUID_BUFSIZE; k++) {
|
||||||
|
|
||||||
outL = outR = 0;
|
outL = outR = 0;
|
||||||
|
|
||||||
/* The original Freeverb code expects a stereo signal and 'input'
|
/* The original Freeverb code expects a stereo signal and 'input'
|
||||||
* is set to the sum of the left and right input sample. Since
|
* is set to the sum of the left and right input sample. Since
|
||||||
* this code works on a mono signal, 'input' is set to twice the
|
* this code works on a mono signal, 'input' is set to twice the
|
||||||
@@ -478,7 +478,7 @@ fluid_revmodel_processmix(fluid_revmodel_t* rev, fluid_real_t *in,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fluid_revmodel_update(fluid_revmodel_t* rev)
|
fluid_revmodel_update(fluid_revmodel_t* rev)
|
||||||
{
|
{
|
||||||
/* Recalculate internal values after parameter change */
|
/* Recalculate internal values after parameter change */
|
||||||
@@ -491,6 +491,7 @@ fluid_revmodel_update(fluid_revmodel_t* rev)
|
|||||||
fluid_comb_setfeedback(&rev->combL[i], rev->roomsize);
|
fluid_comb_setfeedback(&rev->combL[i], rev->roomsize);
|
||||||
fluid_comb_setfeedback(&rev->combR[i], rev->roomsize);
|
fluid_comb_setfeedback(&rev->combR[i], rev->roomsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < numcombs; i++) {
|
for (i = 0; i < numcombs; i++) {
|
||||||
fluid_comb_setdamp(&rev->combL[i], rev->damp);
|
fluid_comb_setdamp(&rev->combL[i], rev->damp);
|
||||||
fluid_comb_setdamp(&rev->combR[i], rev->damp);
|
fluid_comb_setdamp(&rev->combR[i], rev->damp);
|
||||||
@@ -503,7 +504,7 @@ fluid_revmodel_update(fluid_revmodel_t* rev)
|
|||||||
because as you develop the reverb model, you may
|
because as you develop the reverb model, you may
|
||||||
wish to take dynamic action when they are called.
|
wish to take dynamic action when they are called.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
fluid_revmodel_setroomsize(fluid_revmodel_t* rev, fluid_real_t value)
|
fluid_revmodel_setroomsize(fluid_revmodel_t* rev, fluid_real_t value)
|
||||||
{
|
{
|
||||||
/* fluid_clip(value, 0.0f, 1.0f); */
|
/* fluid_clip(value, 0.0f, 1.0f); */
|
||||||
@@ -511,13 +512,13 @@ fluid_revmodel_setroomsize(fluid_revmodel_t* rev, fluid_real_t value)
|
|||||||
fluid_revmodel_update(rev);
|
fluid_revmodel_update(rev);
|
||||||
}
|
}
|
||||||
|
|
||||||
fluid_real_t
|
fluid_real_t
|
||||||
fluid_revmodel_getroomsize(fluid_revmodel_t* rev)
|
fluid_revmodel_getroomsize(fluid_revmodel_t* rev)
|
||||||
{
|
{
|
||||||
return (rev->roomsize - offsetroom) / scaleroom;
|
return (rev->roomsize - offsetroom) / scaleroom;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fluid_revmodel_setdamp(fluid_revmodel_t* rev, fluid_real_t value)
|
fluid_revmodel_setdamp(fluid_revmodel_t* rev, fluid_real_t value)
|
||||||
{
|
{
|
||||||
/* fluid_clip(value, 0.0f, 1.0f); */
|
/* fluid_clip(value, 0.0f, 1.0f); */
|
||||||
@@ -525,27 +526,27 @@ fluid_revmodel_setdamp(fluid_revmodel_t* rev, fluid_real_t value)
|
|||||||
fluid_revmodel_update(rev);
|
fluid_revmodel_update(rev);
|
||||||
}
|
}
|
||||||
|
|
||||||
fluid_real_t
|
fluid_real_t
|
||||||
fluid_revmodel_getdamp(fluid_revmodel_t* rev)
|
fluid_revmodel_getdamp(fluid_revmodel_t* rev)
|
||||||
{
|
{
|
||||||
return rev->damp / scaledamp;
|
return rev->damp / scaledamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fluid_revmodel_setlevel(fluid_revmodel_t* rev, fluid_real_t value)
|
fluid_revmodel_setlevel(fluid_revmodel_t* rev, fluid_real_t value)
|
||||||
{
|
{
|
||||||
/* fluid_clip(value, 0.0f, 1.0f); */
|
fluid_clip(value, 0.0f, 1.0f);
|
||||||
/* rev->wet = value * scalewet; */
|
rev->wet = value * scalewet;
|
||||||
/* fluid_revmodel_update(rev); */
|
fluid_revmodel_update(rev);
|
||||||
}
|
}
|
||||||
|
|
||||||
fluid_real_t
|
fluid_real_t
|
||||||
fluid_revmodel_getlevel(fluid_revmodel_t* rev)
|
fluid_revmodel_getlevel(fluid_revmodel_t* rev)
|
||||||
{
|
{
|
||||||
return rev->wet / scalewet;
|
return rev->wet / scalewet;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fluid_revmodel_setwidth(fluid_revmodel_t* rev, fluid_real_t value)
|
fluid_revmodel_setwidth(fluid_revmodel_t* rev, fluid_real_t value)
|
||||||
{
|
{
|
||||||
/* fluid_clip(value, 0.0f, 1.0f); */
|
/* fluid_clip(value, 0.0f, 1.0f); */
|
||||||
@@ -553,7 +554,7 @@ fluid_revmodel_setwidth(fluid_revmodel_t* rev, fluid_real_t value)
|
|||||||
fluid_revmodel_update(rev);
|
fluid_revmodel_update(rev);
|
||||||
}
|
}
|
||||||
|
|
||||||
fluid_real_t
|
fluid_real_t
|
||||||
fluid_revmodel_getwidth(fluid_revmodel_t* rev)
|
fluid_revmodel_getwidth(fluid_revmodel_t* rev)
|
||||||
{
|
{
|
||||||
return rev->width;
|
return rev->width;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -33,10 +33,10 @@ typedef struct _fluid_revmodel_t fluid_revmodel_t;
|
|||||||
fluid_revmodel_t* new_fluid_revmodel(void);
|
fluid_revmodel_t* new_fluid_revmodel(void);
|
||||||
void delete_fluid_revmodel(fluid_revmodel_t* rev);
|
void delete_fluid_revmodel(fluid_revmodel_t* rev);
|
||||||
|
|
||||||
void fluid_revmodel_processmix(fluid_revmodel_t* rev, fluid_real_t *in,
|
void fluid_revmodel_processmix(fluid_revmodel_t* rev, fluid_real_t *in,
|
||||||
fluid_real_t *left_out, fluid_real_t *right_out);
|
fluid_real_t *left_out, fluid_real_t *right_out);
|
||||||
|
|
||||||
void fluid_revmodel_processreplace(fluid_revmodel_t* rev, fluid_real_t *in,
|
void fluid_revmodel_processreplace(fluid_revmodel_t* rev, fluid_real_t *in,
|
||||||
fluid_real_t *left_out, fluid_real_t *right_out);
|
fluid_real_t *left_out, fluid_real_t *right_out);
|
||||||
|
|
||||||
void fluid_revmodel_reset(fluid_revmodel_t* rev);
|
void fluid_revmodel_reset(fluid_revmodel_t* rev);
|
||||||
|
|||||||
+103
-103
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -19,14 +19,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
2002 : API design by Peter Hanappe and Antoine Schmitt
|
2002 : API design by Peter Hanappe and Antoine Schmitt
|
||||||
August 2002 : Implementation by Antoine Schmitt as@gratin.org
|
August 2002 : Implementation by Antoine Schmitt as@gratin.org
|
||||||
as part of the infiniteCD author project
|
as part of the infiniteCD author project
|
||||||
http://www.infiniteCD.org/
|
http://www.infiniteCD.org/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "fluid_event_priv.h"
|
#include "fluid_event_priv.h"
|
||||||
#include "fluidsynth_priv.h" // FLUID_NEW, etc
|
#include "fluidsynth_priv.h" // FLUID_NEW, etc
|
||||||
#include "fluid_sys.h" // timer, threads, etc...
|
#include "fluid_sys.h" // timer, threads, etc...
|
||||||
@@ -82,11 +82,11 @@ int _fluid_seq_queue_process(void* data, unsigned int msec); // callback from ti
|
|||||||
|
|
||||||
/* API implementation */
|
/* API implementation */
|
||||||
|
|
||||||
fluid_sequencer_t*
|
fluid_sequencer_t*
|
||||||
new_fluid_sequencer()
|
new_fluid_sequencer()
|
||||||
{
|
{
|
||||||
fluid_sequencer_t* seq;
|
fluid_sequencer_t* seq;
|
||||||
|
|
||||||
seq = FLUID_NEW(fluid_sequencer_t);
|
seq = FLUID_NEW(fluid_sequencer_t);
|
||||||
if (seq == NULL) {
|
if (seq == NULL) {
|
||||||
fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
|
fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
|
||||||
@@ -99,7 +99,7 @@ new_fluid_sequencer()
|
|||||||
seq->startMs = fluid_curtime();
|
seq->startMs = fluid_curtime();
|
||||||
seq->clients = NULL;
|
seq->clients = NULL;
|
||||||
seq->clientsID = 0;
|
seq->clientsID = 0;
|
||||||
|
|
||||||
if (-1 == _fluid_seq_queue_init(seq, FLUID_SEQUENCER_EVENTS_MAX)) {
|
if (-1 == _fluid_seq_queue_init(seq, FLUID_SEQUENCER_EVENTS_MAX)) {
|
||||||
FLUID_FREE(seq);
|
FLUID_FREE(seq);
|
||||||
fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
|
fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
|
||||||
@@ -113,7 +113,7 @@ new_fluid_sequencer()
|
|||||||
_fluid_seq_queue_end(seq);
|
_fluid_seq_queue_end(seq);
|
||||||
FLUID_FREE(seq);
|
FLUID_FREE(seq);
|
||||||
fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
|
fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
seq->traceptr = seq->tracebuf;
|
seq->traceptr = seq->tracebuf;
|
||||||
#endif
|
#endif
|
||||||
@@ -121,16 +121,16 @@ new_fluid_sequencer()
|
|||||||
return(seq);
|
return(seq);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
delete_fluid_sequencer(fluid_sequencer_t* seq)
|
delete_fluid_sequencer(fluid_sequencer_t* seq)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (seq == NULL) {
|
if (seq == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_fluid_seq_queue_end(seq);
|
_fluid_seq_queue_end(seq);
|
||||||
|
|
||||||
/* cleanup clients */
|
/* cleanup clients */
|
||||||
if (seq->clients) {
|
if (seq->clients) {
|
||||||
fluid_list_t *tmp = seq->clients;
|
fluid_list_t *tmp = seq->clients;
|
||||||
@@ -142,9 +142,9 @@ delete_fluid_sequencer(fluid_sequencer_t* seq)
|
|||||||
delete_fluid_list(seq->clients);
|
delete_fluid_list(seq->clients);
|
||||||
seq->clients = NULL;
|
seq->clients = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if FLUID_SEQ_WITH_TRACE
|
#if FLUID_SEQ_WITH_TRACE
|
||||||
if (seq->tracebuf != NULL)
|
if (seq->tracebuf != NULL)
|
||||||
FLUID_FREE(seq->tracebuf);
|
FLUID_FREE(seq->tracebuf);
|
||||||
seq->tracebuf = NULL;
|
seq->tracebuf = NULL;
|
||||||
#endif
|
#endif
|
||||||
@@ -161,7 +161,7 @@ fluid_seq_dotrace(fluid_sequencer_t* seq, char *fmt, ...)
|
|||||||
va_list args;
|
va_list args;
|
||||||
int len, remain = seq->tracelen - (seq->traceptr - seq->tracebuf);
|
int len, remain = seq->tracelen - (seq->traceptr - seq->tracebuf);
|
||||||
if (remain <= 0) return;
|
if (remain <= 0) return;
|
||||||
|
|
||||||
va_start (args, fmt);
|
va_start (args, fmt);
|
||||||
len = vsnprintf(seq->traceptr, remain, fmt, args);
|
len = vsnprintf(seq->traceptr, remain, fmt, args);
|
||||||
va_end (args);
|
va_end (args);
|
||||||
@@ -175,7 +175,7 @@ fluid_seq_dotrace(fluid_sequencer_t* seq, char *fmt, ...)
|
|||||||
seq->traceptr = seq->tracebuf + seq->tracelen;
|
seq->traceptr = seq->tracebuf + seq->tracelen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,12 +198,12 @@ void fluid_seq_dotrace(fluid_sequencer_t* seq, char *fmt, ...) {}
|
|||||||
|
|
||||||
/* clients */
|
/* clients */
|
||||||
|
|
||||||
short fluid_sequencer_register_client(fluid_sequencer_t* seq, char* name,
|
short fluid_sequencer_register_client(fluid_sequencer_t* seq, char* name,
|
||||||
fluid_event_callback_t callback, void* data) {
|
fluid_event_callback_t callback, void* data) {
|
||||||
|
|
||||||
fluid_sequencer_client_t * client;
|
fluid_sequencer_client_t * client;
|
||||||
char * nameCopy;
|
char * nameCopy;
|
||||||
|
|
||||||
client = FLUID_NEW(fluid_sequencer_client_t);
|
client = FLUID_NEW(fluid_sequencer_client_t);
|
||||||
if (client == NULL) {
|
if (client == NULL) {
|
||||||
fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
|
fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
|
||||||
@@ -215,16 +215,16 @@ short fluid_sequencer_register_client(fluid_sequencer_t* seq, char* name,
|
|||||||
fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
|
fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
seq->clientsID++;
|
seq->clientsID++;
|
||||||
|
|
||||||
client->name = nameCopy;
|
client->name = nameCopy;
|
||||||
client->id = seq->clientsID;
|
client->id = seq->clientsID;
|
||||||
client->callback = callback;
|
client->callback = callback;
|
||||||
client->data = data;
|
client->data = data;
|
||||||
|
|
||||||
seq->clients = fluid_list_append(seq->clients, (void *)client);
|
seq->clients = fluid_list_append(seq->clients, (void *)client);
|
||||||
|
|
||||||
return (client->id);
|
return (client->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,15 +232,15 @@ short fluid_sequencer_register_client(fluid_sequencer_t* seq, char* name,
|
|||||||
void fluid_sequencer_unregister_client(fluid_sequencer_t* seq, short id)
|
void fluid_sequencer_unregister_client(fluid_sequencer_t* seq, short id)
|
||||||
{
|
{
|
||||||
fluid_list_t *tmp;
|
fluid_list_t *tmp;
|
||||||
|
|
||||||
if (seq->clients == NULL) return;
|
if (seq->clients == NULL) return;
|
||||||
|
|
||||||
tmp = seq->clients;
|
tmp = seq->clients;
|
||||||
while (tmp) {
|
while (tmp) {
|
||||||
fluid_sequencer_client_t *client = (fluid_sequencer_client_t*)tmp->data;
|
fluid_sequencer_client_t *client = (fluid_sequencer_client_t*)tmp->data;
|
||||||
|
|
||||||
if (client->id == id) {
|
if (client->id == id) {
|
||||||
if (client->name)
|
if (client->name)
|
||||||
FLUID_FREE(client->name);
|
FLUID_FREE(client->name);
|
||||||
seq->clients = fluid_list_remove_link(seq->clients, tmp);
|
seq->clients = fluid_list_remove_link(seq->clients, tmp);
|
||||||
delete1_fluid_list(tmp);
|
delete1_fluid_list(tmp);
|
||||||
@@ -253,7 +253,7 @@ void fluid_sequencer_unregister_client(fluid_sequencer_t* seq, short id)
|
|||||||
|
|
||||||
int fluid_sequencer_count_clients(fluid_sequencer_t* seq)
|
int fluid_sequencer_count_clients(fluid_sequencer_t* seq)
|
||||||
{
|
{
|
||||||
if (seq->clients == NULL)
|
if (seq->clients == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
return fluid_list_size(seq->clients);
|
return fluid_list_size(seq->clients);
|
||||||
}
|
}
|
||||||
@@ -274,17 +274,17 @@ short fluid_sequencer_get_client_id(fluid_sequencer_t* seq, int index)
|
|||||||
char* fluid_sequencer_get_client_name(fluid_sequencer_t* seq, int id)
|
char* fluid_sequencer_get_client_name(fluid_sequencer_t* seq, int id)
|
||||||
{
|
{
|
||||||
fluid_list_t *tmp;
|
fluid_list_t *tmp;
|
||||||
|
|
||||||
if (seq->clients == NULL)
|
if (seq->clients == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
tmp = seq->clients;
|
tmp = seq->clients;
|
||||||
while (tmp) {
|
while (tmp) {
|
||||||
fluid_sequencer_client_t *client = (fluid_sequencer_client_t*)tmp->data;
|
fluid_sequencer_client_t *client = (fluid_sequencer_client_t*)tmp->data;
|
||||||
|
|
||||||
if (client->id == id)
|
if (client->id == id)
|
||||||
return client->name;
|
return client->name;
|
||||||
|
|
||||||
tmp = tmp->next;
|
tmp = tmp->next;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -293,16 +293,16 @@ char* fluid_sequencer_get_client_name(fluid_sequencer_t* seq, int id)
|
|||||||
int fluid_sequencer_client_is_dest(fluid_sequencer_t* seq, int id)
|
int fluid_sequencer_client_is_dest(fluid_sequencer_t* seq, int id)
|
||||||
{
|
{
|
||||||
fluid_list_t *tmp;
|
fluid_list_t *tmp;
|
||||||
|
|
||||||
if (seq->clients == NULL) return 0;
|
if (seq->clients == NULL) return 0;
|
||||||
|
|
||||||
tmp = seq->clients;
|
tmp = seq->clients;
|
||||||
while (tmp) {
|
while (tmp) {
|
||||||
fluid_sequencer_client_t *client = (fluid_sequencer_client_t*)tmp->data;
|
fluid_sequencer_client_t *client = (fluid_sequencer_client_t*)tmp->data;
|
||||||
|
|
||||||
if (client->id == id)
|
if (client->id == id)
|
||||||
return (client->callback != NULL);
|
return (client->callback != NULL);
|
||||||
|
|
||||||
tmp = tmp->next;
|
tmp = tmp->next;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -312,15 +312,15 @@ int fluid_sequencer_client_is_dest(fluid_sequencer_t* seq, int id)
|
|||||||
void fluid_sequencer_send_now(fluid_sequencer_t* seq, fluid_event_t* evt)
|
void fluid_sequencer_send_now(fluid_sequencer_t* seq, fluid_event_t* evt)
|
||||||
{
|
{
|
||||||
short destID = fluid_event_get_dest(evt);
|
short destID = fluid_event_get_dest(evt);
|
||||||
|
|
||||||
/* find callback */
|
/* find callback */
|
||||||
fluid_list_t *tmp = seq->clients;
|
fluid_list_t *tmp = seq->clients;
|
||||||
while (tmp) {
|
while (tmp) {
|
||||||
fluid_sequencer_client_t *dest = (fluid_sequencer_client_t*)tmp->data;
|
fluid_sequencer_client_t *dest = (fluid_sequencer_client_t*)tmp->data;
|
||||||
|
|
||||||
if (dest->id == destID) {
|
if (dest->id == destID) {
|
||||||
if (dest->callback)
|
if (dest->callback)
|
||||||
(dest->callback)(fluid_sequencer_get_tick(seq),
|
(dest->callback)(fluid_sequencer_get_tick(seq),
|
||||||
evt, seq, dest->data);
|
evt, seq, dest->data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -336,24 +336,24 @@ fluid_sequencer_send_at(fluid_sequencer_t* seq, fluid_event_t* evt, unsigned int
|
|||||||
/* set absolute */
|
/* set absolute */
|
||||||
if (!absolute)
|
if (!absolute)
|
||||||
time = now + time;
|
time = now + time;
|
||||||
|
|
||||||
/* time stamp event */
|
/* time stamp event */
|
||||||
fluid_event_set_time(evt, time);
|
fluid_event_set_time(evt, time);
|
||||||
|
|
||||||
/* process late */
|
/* process late */
|
||||||
if (time < now) {
|
if (time < now) {
|
||||||
fluid_sequencer_send_now(seq, evt);
|
fluid_sequencer_send_now(seq, evt);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* process now */
|
/* process now */
|
||||||
if (time == now) {
|
if (time == now) {
|
||||||
fluid_sequencer_send_now(seq, evt);
|
fluid_sequencer_send_now(seq, evt);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* queue for processing later */
|
/* queue for processing later */
|
||||||
return _fluid_seq_queue_pre_insert(seq, evt);
|
return _fluid_seq_queue_pre_insert(seq, evt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -382,14 +382,14 @@ void fluid_sequencer_set_time_scale(fluid_sequencer_t* seq, double scale)
|
|||||||
fluid_log(FLUID_WARN, "sequencer: scale <= 0 : %f\n", scale);
|
fluid_log(FLUID_WARN, "sequencer: scale <= 0 : %f\n", scale);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scale > 1000.0)
|
if (scale > 1000.0)
|
||||||
// Otherwise : problems with the timer = 0ms...
|
// Otherwise : problems with the timer = 0ms...
|
||||||
scale = 1000.0;
|
scale = 1000.0;
|
||||||
|
|
||||||
if (seq->scale != scale) {
|
if (seq->scale != scale) {
|
||||||
double oldScale = seq->scale;
|
double oldScale = seq->scale;
|
||||||
|
|
||||||
// stop timer
|
// stop timer
|
||||||
if (seq->timer) {
|
if (seq->timer) {
|
||||||
delete_fluid_timer(seq->timer);
|
delete_fluid_timer(seq->timer);
|
||||||
@@ -405,10 +405,10 @@ void fluid_sequencer_set_time_scale(fluid_sequencer_t* seq, double scale)
|
|||||||
{
|
{
|
||||||
fluid_evt_entry* tmp;
|
fluid_evt_entry* tmp;
|
||||||
tmp = seq->preQueue;
|
tmp = seq->preQueue;
|
||||||
while (tmp) {
|
while (tmp) {
|
||||||
if (tmp->entryType == FLUID_EVT_ENTRY_INSERT)
|
if (tmp->entryType == FLUID_EVT_ENTRY_INSERT)
|
||||||
tmp->evt.time = tmp->evt.time*seq->scale/oldScale;
|
tmp->evt.time = tmp->evt.time*seq->scale/oldScale;
|
||||||
|
|
||||||
tmp = tmp->next;
|
tmp = tmp->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -434,7 +434,7 @@ double fluid_sequencer_get_time_scale(fluid_sequencer_t* seq)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
The queue stores all future events to be processed.
|
The queue stores all future events to be processed.
|
||||||
|
|
||||||
Data structures
|
Data structures
|
||||||
|
|
||||||
There is a heap, allocated at init time, for managing a pool
|
There is a heap, allocated at init time, for managing a pool
|
||||||
@@ -455,33 +455,33 @@ double fluid_sequencer_get_time_scale(fluid_sequencer_t* seq)
|
|||||||
events is fast (below 65535 ticks, that is about 1 minute if 1
|
events is fast (below 65535 ticks, that is about 1 minute if 1
|
||||||
tick=1ms). Inserting later events is more slow, but this is a
|
tick=1ms). Inserting later events is more slow, but this is a
|
||||||
realtime engine, isn't it ?
|
realtime engine, isn't it ?
|
||||||
|
|
||||||
The queue0 starts at queue0StartTime. When 256 ticks have
|
The queue0 starts at queue0StartTime. When 256 ticks have
|
||||||
elapsed, the queue0 array is emptied, and the first cell of
|
elapsed, the queue0 array is emptied, and the first cell of
|
||||||
the queue1 array is expanded in the queue0 array, according to
|
the queue1 array is expanded in the queue0 array, according to
|
||||||
the time of each event. The queue1 array is shifted to the
|
the time of each event. The queue1 array is shifted to the
|
||||||
left, and the first events of the queueLater list are inserte
|
left, and the first events of the queueLater list are inserte
|
||||||
in the last cell of the queue1 array.
|
in the last cell of the queue1 array.
|
||||||
|
|
||||||
We remember the previously managed cell in queue0 in the
|
We remember the previously managed cell in queue0 in the
|
||||||
prevCellNb variable. When processing the current cell, we
|
prevCellNb variable. When processing the current cell, we
|
||||||
process the events in between (late events).
|
process the events in between (late events).
|
||||||
|
|
||||||
Functions
|
Functions
|
||||||
|
|
||||||
The main thread functions first get an event entry from the
|
The main thread functions first get an event entry from the
|
||||||
heap, and copy the given event into it, then merely enqueue it
|
heap, and copy the given event into it, then merely enqueue it
|
||||||
in a preQueue. This is in order to protect the data structure:
|
in a preQueue. This is in order to protect the data structure:
|
||||||
everything is managed in the callback (thread or interrupt,
|
everything is managed in the callback (thread or interrupt,
|
||||||
depending on the architecture).
|
depending on the architecture).
|
||||||
|
|
||||||
All queue data structure management is done in a timer
|
All queue data structure management is done in a timer
|
||||||
callback: '_fluid_seq_queue_process'. The
|
callback: '_fluid_seq_queue_process'. The
|
||||||
_fluid_seq_queue_process function first process the preQueue,
|
_fluid_seq_queue_process function first process the preQueue,
|
||||||
inserting or removing event entrys from the queue, then
|
inserting or removing event entrys from the queue, then
|
||||||
processes the queue, by sending events ready to be sent at the
|
processes the queue, by sending events ready to be sent at the
|
||||||
current time.
|
current time.
|
||||||
|
|
||||||
Critical sections between the main thread (or app) and the
|
Critical sections between the main thread (or app) and the
|
||||||
sequencer thread (or interrupt) are:
|
sequencer thread (or interrupt) are:
|
||||||
|
|
||||||
@@ -530,11 +530,11 @@ _fluid_seq_queue_init(fluid_sequencer_t* seq, int maxEvents)
|
|||||||
seq->queueLater = NULL;
|
seq->queueLater = NULL;
|
||||||
seq->queue0StartTime = fluid_sequencer_get_tick(seq);
|
seq->queue0StartTime = fluid_sequencer_get_tick(seq);
|
||||||
seq->prevCellNb = -1;
|
seq->prevCellNb = -1;
|
||||||
|
|
||||||
fluid_mutex_init(seq->mutex);
|
fluid_mutex_init(seq->mutex);
|
||||||
|
|
||||||
/* start timer */
|
/* start timer */
|
||||||
seq->timer = new_fluid_timer((int)(1000/seq->scale), _fluid_seq_queue_process,
|
seq->timer = new_fluid_timer((int)(1000/seq->scale), _fluid_seq_queue_process,
|
||||||
(void *)seq, 1, 0);
|
(void *)seq, 1, 0);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@@ -546,7 +546,7 @@ _fluid_seq_queue_end(fluid_sequencer_t* seq)
|
|||||||
delete_fluid_timer(seq->timer);
|
delete_fluid_timer(seq->timer);
|
||||||
seq->timer = NULL;
|
seq->timer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (seq->heap) {
|
if (seq->heap) {
|
||||||
_fluid_evt_heap_free(seq->heap);
|
_fluid_evt_heap_free(seq->heap);
|
||||||
seq->heap = NULL;
|
seq->heap = NULL;
|
||||||
@@ -572,11 +572,11 @@ _fluid_seq_queue_pre_insert(fluid_sequencer_t* seq, fluid_event_t * evt)
|
|||||||
fluid_log(FLUID_PANIC, "sequencer: no more free events\n");
|
fluid_log(FLUID_PANIC, "sequencer: no more free events\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
evtentry->next = NULL;
|
evtentry->next = NULL;
|
||||||
evtentry->entryType = FLUID_EVT_ENTRY_INSERT;
|
evtentry->entryType = FLUID_EVT_ENTRY_INSERT;
|
||||||
FLUID_MEMCPY(&(evtentry->evt), evt, sizeof(fluid_event_t));
|
FLUID_MEMCPY(&(evtentry->evt), evt, sizeof(fluid_event_t));
|
||||||
|
|
||||||
fluid_mutex_lock(seq->mutex);
|
fluid_mutex_lock(seq->mutex);
|
||||||
|
|
||||||
/* append to preQueue */
|
/* append to preQueue */
|
||||||
@@ -588,7 +588,7 @@ _fluid_seq_queue_pre_insert(fluid_sequencer_t* seq, fluid_event_t * evt)
|
|||||||
seq->preQueueLast = evtentry;
|
seq->preQueueLast = evtentry;
|
||||||
|
|
||||||
fluid_mutex_unlock(seq->mutex);
|
fluid_mutex_unlock(seq->mutex);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -604,7 +604,7 @@ _fluid_seq_queue_pre_remove(fluid_sequencer_t* seq, short src, short dest, int t
|
|||||||
fluid_log(FLUID_PANIC, "sequencer: no more free events\n");
|
fluid_log(FLUID_PANIC, "sequencer: no more free events\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
evtentry->next = NULL;
|
evtentry->next = NULL;
|
||||||
evtentry->entryType = FLUID_EVT_ENTRY_REMOVE;
|
evtentry->entryType = FLUID_EVT_ENTRY_REMOVE;
|
||||||
{
|
{
|
||||||
@@ -614,7 +614,7 @@ _fluid_seq_queue_pre_remove(fluid_sequencer_t* seq, short src, short dest, int t
|
|||||||
fluid_event_set_dest(evt, dest);
|
fluid_event_set_dest(evt, dest);
|
||||||
evt->type = type;
|
evt->type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
fluid_mutex_lock(seq->mutex);
|
fluid_mutex_lock(seq->mutex);
|
||||||
|
|
||||||
/* append to preQueue */
|
/* append to preQueue */
|
||||||
@@ -624,7 +624,7 @@ _fluid_seq_queue_pre_remove(fluid_sequencer_t* seq, short src, short dest, int t
|
|||||||
seq->preQueue = evtentry;
|
seq->preQueue = evtentry;
|
||||||
}
|
}
|
||||||
seq->preQueueLast = evtentry;
|
seq->preQueueLast = evtentry;
|
||||||
|
|
||||||
fluid_mutex_unlock(seq->mutex);
|
fluid_mutex_unlock(seq->mutex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -632,7 +632,7 @@ _fluid_seq_queue_pre_remove(fluid_sequencer_t* seq, short src, short dest, int t
|
|||||||
/***********************
|
/***********************
|
||||||
* callback from timer
|
* callback from timer
|
||||||
* (may be in a different thread, or in an interrupt)
|
* (may be in a different thread, or in an interrupt)
|
||||||
*
|
*
|
||||||
***********************/
|
***********************/
|
||||||
int
|
int
|
||||||
_fluid_seq_queue_process(void* data, unsigned int msec)
|
_fluid_seq_queue_process(void* data, unsigned int msec)
|
||||||
@@ -651,23 +651,23 @@ _fluid_seq_queue_process(void* data, unsigned int msec)
|
|||||||
seq->preQueueLast = NULL;
|
seq->preQueueLast = NULL;
|
||||||
|
|
||||||
fluid_mutex_unlock(seq->mutex);
|
fluid_mutex_unlock(seq->mutex);
|
||||||
|
|
||||||
/* walk all the preQueue and process them in order : inserts and removes */
|
/* walk all the preQueue and process them in order : inserts and removes */
|
||||||
while (tmp) {
|
while (tmp) {
|
||||||
next = tmp->next;
|
next = tmp->next;
|
||||||
|
|
||||||
if (tmp->entryType == FLUID_EVT_ENTRY_REMOVE) {
|
if (tmp->entryType == FLUID_EVT_ENTRY_REMOVE) {
|
||||||
_fluid_seq_queue_remove_entries_matching(seq, tmp);
|
_fluid_seq_queue_remove_entries_matching(seq, tmp);
|
||||||
} else {
|
} else {
|
||||||
_fluid_seq_queue_insert_entry(seq, tmp);
|
_fluid_seq_queue_insert_entry(seq, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp = next;
|
tmp = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* send queued events */
|
/* send queued events */
|
||||||
_fluid_seq_queue_send_queued_events(seq);
|
_fluid_seq_queue_send_queued_events(seq);
|
||||||
|
|
||||||
/* continue timer */
|
/* continue timer */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -680,7 +680,7 @@ _fluid_seq_queue_print_later(fluid_sequencer_t* seq)
|
|||||||
fluid_evt_entry* tmp = seq->queueLater;
|
fluid_evt_entry* tmp = seq->queueLater;
|
||||||
|
|
||||||
printf("queueLater:\n");
|
printf("queueLater:\n");
|
||||||
|
|
||||||
while (tmp) {
|
while (tmp) {
|
||||||
unsigned int delay = tmp->evt.time - seq->queue0StartTime;
|
unsigned int delay = tmp->evt.time - seq->queue0StartTime;
|
||||||
printf("queueLater: Delay = %i\n", delay);
|
printf("queueLater: Delay = %i\n", delay);
|
||||||
@@ -720,19 +720,19 @@ _fluid_seq_queue_insert_queue_later(fluid_sequencer_t* seq, fluid_evt_entry* evt
|
|||||||
{
|
{
|
||||||
fluid_evt_entry* prev;
|
fluid_evt_entry* prev;
|
||||||
fluid_evt_entry* tmp;
|
fluid_evt_entry* tmp;
|
||||||
unsigned int time = evtentry->evt.time;
|
unsigned int time = evtentry->evt.time;
|
||||||
|
|
||||||
/* insert in 'queueLater', after the ones that have the same
|
/* insert in 'queueLater', after the ones that have the same
|
||||||
* time */
|
* time */
|
||||||
|
|
||||||
/* first? */
|
/* first? */
|
||||||
if ((seq->queueLater == NULL)
|
if ((seq->queueLater == NULL)
|
||||||
|| (seq->queueLater->evt.time > time)) {
|
|| (seq->queueLater->evt.time > time)) {
|
||||||
evtentry->next = seq->queueLater;
|
evtentry->next = seq->queueLater;
|
||||||
seq->queueLater = evtentry;
|
seq->queueLater = evtentry;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* walk queueLater */
|
/* walk queueLater */
|
||||||
/* this is the only slow thing : if the event is more
|
/* this is the only slow thing : if the event is more
|
||||||
than 65535 ticks after the current time */
|
than 65535 ticks after the current time */
|
||||||
@@ -752,7 +752,7 @@ _fluid_seq_queue_insert_queue_later(fluid_sequencer_t* seq, fluid_evt_entry* evt
|
|||||||
|
|
||||||
/* last */
|
/* last */
|
||||||
evtentry->next = NULL;
|
evtentry->next = NULL;
|
||||||
prev->next = evtentry;
|
prev->next = evtentry;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -760,43 +760,43 @@ _fluid_seq_queue_insert_entry(fluid_sequencer_t* seq, fluid_evt_entry * evtentry
|
|||||||
{
|
{
|
||||||
/* time is relative to seq origin, in ticks */
|
/* time is relative to seq origin, in ticks */
|
||||||
fluid_event_t * evt = &(evtentry->evt);
|
fluid_event_t * evt = &(evtentry->evt);
|
||||||
unsigned int time = evt->time;
|
unsigned int time = evt->time;
|
||||||
unsigned int delay;
|
unsigned int delay;
|
||||||
|
|
||||||
if (seq->queue0StartTime > 0) {
|
if (seq->queue0StartTime > 0) {
|
||||||
/* queue0StartTime could be < 0 if the scale changed a
|
/* queue0StartTime could be < 0 if the scale changed a
|
||||||
lot early, breaking the following comparison
|
lot early, breaking the following comparison
|
||||||
*/
|
*/
|
||||||
if (time < (unsigned int)seq->queue0StartTime) {
|
if (time < (unsigned int)seq->queue0StartTime) {
|
||||||
/* we are late, send now */
|
/* we are late, send now */
|
||||||
fluid_sequencer_send_now(seq, evt);
|
fluid_sequencer_send_now(seq, evt);
|
||||||
|
|
||||||
_fluid_seq_heap_set_free(seq->heap, evtentry);
|
_fluid_seq_heap_set_free(seq->heap, evtentry);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (seq->prevCellNb >= 0) {
|
if (seq->prevCellNb >= 0) {
|
||||||
/* prevCellNb could be -1 is seq was just started - unlikely */
|
/* prevCellNb could be -1 is seq was just started - unlikely */
|
||||||
/* prevCellNb can also be -1 if cellNb was reset to 0 in
|
/* prevCellNb can also be -1 if cellNb was reset to 0 in
|
||||||
_fluid_seq_queue_send_queued_events() */
|
_fluid_seq_queue_send_queued_events() */
|
||||||
if (time <= (unsigned int)(seq->queue0StartTime + seq->prevCellNb)) {
|
if (time <= (unsigned int)(seq->queue0StartTime + seq->prevCellNb)) {
|
||||||
/* we are late, send now */
|
/* we are late, send now */
|
||||||
fluid_sequencer_send_now(seq, evt);
|
fluid_sequencer_send_now(seq, evt);
|
||||||
|
|
||||||
_fluid_seq_heap_set_free(seq->heap, evtentry);
|
_fluid_seq_heap_set_free(seq->heap, evtentry);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delay = time - seq->queue0StartTime;
|
delay = time - seq->queue0StartTime;
|
||||||
|
|
||||||
if (delay > 65535) {
|
if (delay > 65535) {
|
||||||
_fluid_seq_queue_insert_queue_later(seq, evtentry);
|
_fluid_seq_queue_insert_queue_later(seq, evtentry);
|
||||||
|
|
||||||
} else if (delay > 255) {
|
} else if (delay > 255) {
|
||||||
_fluid_seq_queue_insert_queue1(seq, evtentry, delay/256 - 1);
|
_fluid_seq_queue_insert_queue1(seq, evtentry, delay/256 - 1);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
_fluid_seq_queue_insert_queue0(seq, evtentry, delay);
|
_fluid_seq_queue_insert_queue0(seq, evtentry, delay);
|
||||||
}
|
}
|
||||||
@@ -806,21 +806,21 @@ int
|
|||||||
_fluid_seq_queue_matchevent(fluid_event_t* evt, int templType, short templSrc, short templDest)
|
_fluid_seq_queue_matchevent(fluid_event_t* evt, int templType, short templSrc, short templDest)
|
||||||
{
|
{
|
||||||
int eventType;
|
int eventType;
|
||||||
|
|
||||||
if (templSrc != -1 && templSrc != fluid_event_get_source(evt))
|
if (templSrc != -1 && templSrc != fluid_event_get_source(evt))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (templDest != -1 && templDest != fluid_event_get_dest(evt))
|
if (templDest != -1 && templDest != fluid_event_get_dest(evt))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (templType == -1)
|
if (templType == -1)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
eventType = fluid_event_get_type(evt);
|
eventType = fluid_event_get_type(evt);
|
||||||
|
|
||||||
if (templType == eventType)
|
if (templType == eventType)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (templType == FLUID_SEQ_ANYCONTROLCHANGE)
|
if (templType == FLUID_SEQ_ANYCONTROLCHANGE)
|
||||||
if (eventType == FLUID_SEQ_PITCHBEND ||
|
if (eventType == FLUID_SEQ_PITCHBEND ||
|
||||||
eventType == FLUID_SEQ_MODULATION ||
|
eventType == FLUID_SEQ_MODULATION ||
|
||||||
@@ -841,14 +841,14 @@ _fluid_seq_queue_remove_entries_matching(fluid_sequencer_t* seq, fluid_evt_entry
|
|||||||
/* we walk everything : this is slow, but that is life */
|
/* we walk everything : this is slow, but that is life */
|
||||||
int i, type;
|
int i, type;
|
||||||
short src, dest;
|
short src, dest;
|
||||||
|
|
||||||
src = templ->evt.src;
|
src = templ->evt.src;
|
||||||
dest = templ->evt.dest;
|
dest = templ->evt.dest;
|
||||||
type = templ->evt.type;
|
type = templ->evt.type;
|
||||||
|
|
||||||
/* we can set it free now */
|
/* we can set it free now */
|
||||||
_fluid_seq_heap_set_free(seq->heap, templ);
|
_fluid_seq_heap_set_free(seq->heap, templ);
|
||||||
|
|
||||||
/* queue0 */
|
/* queue0 */
|
||||||
for (i = 0 ; i < 256 ; i++) {
|
for (i = 0 ; i < 256 ; i++) {
|
||||||
fluid_evt_entry* tmp = seq->queue0[i][0];
|
fluid_evt_entry* tmp = seq->queue0[i][0];
|
||||||
@@ -876,10 +876,10 @@ _fluid_seq_queue_remove_entries_matching(fluid_sequencer_t* seq, fluid_evt_entry
|
|||||||
} else {
|
} else {
|
||||||
prev = tmp;
|
prev = tmp;
|
||||||
tmp = prev->next;
|
tmp = prev->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* queue1 */
|
/* queue1 */
|
||||||
for (i = 0 ; i < 255 ; i++) {
|
for (i = 0 ; i < 255 ; i++) {
|
||||||
fluid_evt_entry* tmp = seq->queue1[i][0];
|
fluid_evt_entry* tmp = seq->queue1[i][0];
|
||||||
@@ -906,7 +906,7 @@ _fluid_seq_queue_remove_entries_matching(fluid_sequencer_t* seq, fluid_evt_entry
|
|||||||
} else {
|
} else {
|
||||||
prev = tmp;
|
prev = tmp;
|
||||||
tmp = prev->next;
|
tmp = prev->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -950,9 +950,9 @@ _fluid_seq_queue_send_cell_events(fluid_sequencer_t* seq, int cellNb)
|
|||||||
|
|
||||||
_fluid_seq_heap_set_free(seq->heap, tmp);
|
_fluid_seq_heap_set_free(seq->heap, tmp);
|
||||||
tmp = next;
|
tmp = next;
|
||||||
}
|
}
|
||||||
seq->queue0[cellNb][0] = NULL;
|
seq->queue0[cellNb][0] = NULL;
|
||||||
seq->queue0[cellNb][1] = NULL;
|
seq->queue0[cellNb][1] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -989,7 +989,7 @@ _fluid_seq_queue_slide(fluid_sequencer_t* seq)
|
|||||||
}
|
}
|
||||||
seq->queue1[254][0] = NULL;
|
seq->queue1[254][0] = NULL;
|
||||||
seq->queue1[254][1] = NULL;
|
seq->queue1[254][1] = NULL;
|
||||||
|
|
||||||
|
|
||||||
/* append queueLater to queue1[254] */
|
/* append queueLater to queue1[254] */
|
||||||
count = 0;
|
count = 0;
|
||||||
@@ -1003,9 +1003,9 @@ _fluid_seq_queue_slide(fluid_sequencer_t* seq)
|
|||||||
|
|
||||||
next = tmp->next;
|
next = tmp->next;
|
||||||
|
|
||||||
/* append it */
|
/* append it */
|
||||||
_fluid_seq_queue_insert_queue1(seq, tmp, 254);
|
_fluid_seq_queue_insert_queue1(seq, tmp, 254);
|
||||||
tmp = next;
|
tmp = next;
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1024,14 +1024,14 @@ _fluid_seq_queue_send_queued_events(fluid_sequencer_t* seq)
|
|||||||
cellNb = 0;
|
cellNb = 0;
|
||||||
_fluid_seq_queue_slide(seq);
|
_fluid_seq_queue_slide(seq);
|
||||||
} /* slide */
|
} /* slide */
|
||||||
|
|
||||||
|
|
||||||
/* process queue0[cellNb] */
|
/* process queue0[cellNb] */
|
||||||
_fluid_seq_queue_send_cell_events(seq, cellNb);
|
_fluid_seq_queue_send_cell_events(seq, cellNb);
|
||||||
|
|
||||||
/* next cell */
|
/* next cell */
|
||||||
cellNb++;
|
cellNb++;
|
||||||
}
|
}
|
||||||
|
|
||||||
seq->prevCellNb = cellNb - 1;
|
seq->prevCellNb = cellNb - 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "fluidsynth_priv.h"
|
#include "fluidsynth_priv.h"
|
||||||
|
|
||||||
/***************************************************************
|
/***************************************************************
|
||||||
*
|
*
|
||||||
* SEQUENCER BINDING
|
* SEQUENCER BINDING
|
||||||
@@ -47,17 +47,17 @@ short fluid_sequencer_register_fluidsynth(fluid_sequencer_t* seq, fluid_synth_t*
|
|||||||
void fluid_seq_fluidsynth_callback(unsigned int time, fluid_event_t* evt, fluid_sequencer_t* seq, void* data)
|
void fluid_seq_fluidsynth_callback(unsigned int time, fluid_event_t* evt, fluid_sequencer_t* seq, void* data)
|
||||||
{
|
{
|
||||||
fluid_synth_t* synth = (fluid_synth_t *)data;
|
fluid_synth_t* synth = (fluid_synth_t *)data;
|
||||||
|
|
||||||
switch (fluid_event_get_type(evt)) {
|
switch (fluid_event_get_type(evt)) {
|
||||||
|
|
||||||
case FLUID_SEQ_NOTEON:
|
case FLUID_SEQ_NOTEON:
|
||||||
fluid_synth_noteon(synth, fluid_event_get_channel(evt), fluid_event_get_key(evt), fluid_event_get_velocity(evt));
|
fluid_synth_noteon(synth, fluid_event_get_channel(evt), fluid_event_get_key(evt), fluid_event_get_velocity(evt));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FLUID_SEQ_NOTEOFF:
|
case FLUID_SEQ_NOTEOFF:
|
||||||
fluid_synth_noteoff(synth, fluid_event_get_channel(evt), fluid_event_get_key(evt));
|
fluid_synth_noteoff(synth, fluid_event_get_channel(evt), fluid_event_get_key(evt));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FLUID_SEQ_NOTE:
|
case FLUID_SEQ_NOTE:
|
||||||
{
|
{
|
||||||
unsigned int dur;
|
unsigned int dur;
|
||||||
@@ -75,28 +75,28 @@ void fluid_seq_fluidsynth_callback(unsigned int time, fluid_event_t* evt, fluid_
|
|||||||
case FLUID_SEQ_ALLNOTESOFF:
|
case FLUID_SEQ_ALLNOTESOFF:
|
||||||
fluid_synth_cc(synth, fluid_event_get_channel(evt), 0x7B, 0);
|
fluid_synth_cc(synth, fluid_event_get_channel(evt), 0x7B, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FLUID_SEQ_BANKSELECT:
|
case FLUID_SEQ_BANKSELECT:
|
||||||
fluid_synth_bank_select(synth, fluid_event_get_channel(evt), fluid_event_get_bank(evt));
|
fluid_synth_bank_select(synth, fluid_event_get_channel(evt), fluid_event_get_bank(evt));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FLUID_SEQ_PROGRAMCHANGE:
|
case FLUID_SEQ_PROGRAMCHANGE:
|
||||||
fluid_synth_program_change(synth, fluid_event_get_channel(evt), fluid_event_get_program(evt));
|
fluid_synth_program_change(synth, fluid_event_get_channel(evt), fluid_event_get_program(evt));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FLUID_SEQ_PROGRAMSELECT:
|
case FLUID_SEQ_PROGRAMSELECT:
|
||||||
fluid_synth_program_select(synth, fluid_event_get_channel(evt), fluid_event_get_sfont_id(evt),
|
fluid_synth_program_select(synth, fluid_event_get_channel(evt), fluid_event_get_sfont_id(evt),
|
||||||
fluid_event_get_bank(evt), fluid_event_get_program(evt));
|
fluid_event_get_bank(evt), fluid_event_get_program(evt));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FLUID_SEQ_ANYCONTROLCHANGE:
|
case FLUID_SEQ_ANYCONTROLCHANGE:
|
||||||
/* nothing = only used by remove_events */
|
/* nothing = only used by remove_events */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FLUID_SEQ_PITCHBEND:
|
case FLUID_SEQ_PITCHBEND:
|
||||||
fluid_synth_pitch_bend(synth, fluid_event_get_channel(evt), fluid_event_get_pitch(evt));
|
fluid_synth_pitch_bend(synth, fluid_event_get_channel(evt), fluid_event_get_pitch(evt));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FLUID_SEQ_PITCHWHHELSENS:
|
case FLUID_SEQ_PITCHWHHELSENS:
|
||||||
fluid_synth_pitch_wheel_sens(synth, fluid_event_get_channel(evt), fluid_event_get_value(evt));
|
fluid_synth_pitch_wheel_sens(synth, fluid_event_get_channel(evt), fluid_event_get_value(evt));
|
||||||
break;
|
break;
|
||||||
@@ -104,53 +104,53 @@ void fluid_seq_fluidsynth_callback(unsigned int time, fluid_event_t* evt, fluid_
|
|||||||
case FLUID_SEQ_CONTROLCHANGE:
|
case FLUID_SEQ_CONTROLCHANGE:
|
||||||
fluid_synth_cc(synth, fluid_event_get_channel(evt), fluid_event_get_control(evt), fluid_event_get_value(evt));
|
fluid_synth_cc(synth, fluid_event_get_channel(evt), fluid_event_get_control(evt), fluid_event_get_value(evt));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FLUID_SEQ_MODULATION:
|
case FLUID_SEQ_MODULATION:
|
||||||
{
|
{
|
||||||
short ctrl = 0x01; // MODULATION_MSB
|
short ctrl = 0x01; // MODULATION_MSB
|
||||||
fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
|
fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FLUID_SEQ_SUSTAIN:
|
case FLUID_SEQ_SUSTAIN:
|
||||||
{
|
{
|
||||||
short ctrl = 0x40; // SUSTAIN_SWITCH
|
short ctrl = 0x40; // SUSTAIN_SWITCH
|
||||||
fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
|
fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FLUID_SEQ_PAN:
|
case FLUID_SEQ_PAN:
|
||||||
{
|
{
|
||||||
short ctrl = 0x0A; // PAN_MSB
|
short ctrl = 0x0A; // PAN_MSB
|
||||||
fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
|
fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FLUID_SEQ_VOLUME:
|
case FLUID_SEQ_VOLUME:
|
||||||
{
|
{
|
||||||
short ctrl = 0x07; // VOLUME_MSB
|
short ctrl = 0x07; // VOLUME_MSB
|
||||||
fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
|
fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FLUID_SEQ_REVERBSEND:
|
case FLUID_SEQ_REVERBSEND:
|
||||||
{
|
{
|
||||||
short ctrl = 0x5B; // EFFECTS_DEPTH1
|
short ctrl = 0x5B; // EFFECTS_DEPTH1
|
||||||
fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
|
fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FLUID_SEQ_CHORUSSEND:
|
case FLUID_SEQ_CHORUSSEND:
|
||||||
{
|
{
|
||||||
short ctrl = 0x5D; // EFFECTS_DEPTH3
|
short ctrl = 0x5D; // EFFECTS_DEPTH3
|
||||||
fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
|
fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FLUID_SEQ_TIMER:
|
case FLUID_SEQ_TIMER:
|
||||||
/* nothing in fluidsynth */
|
/* nothing in fluidsynth */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -19,18 +19,21 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "fluidsynth_priv.h"
|
#include "fluidsynth_priv.h"
|
||||||
#include "fluid_settings.h"
|
#include "fluid_sys.h"
|
||||||
#include "fluid_hash.h"
|
#include "fluid_hash.h"
|
||||||
#include "fluid_strtok.h"
|
|
||||||
#include "fluid_synth.h"
|
#include "fluid_synth.h"
|
||||||
#include "fluid_cmd.h"
|
#include "fluid_cmd.h"
|
||||||
#include "fluid_adriver.h"
|
#include "fluid_adriver.h"
|
||||||
#include "fluid_mdriver.h"
|
#include "fluid_mdriver.h"
|
||||||
|
#include "fluid_settings.h"
|
||||||
|
|
||||||
|
/* maximum allowed components of a settings variable (separated by '.') */
|
||||||
|
#define MAX_SETTINGS_TOKENS 8 /* currently only a max of 3 are used */
|
||||||
|
#define MAX_SETTINGS_LABEL 256 /* max length of a settings variable label */
|
||||||
|
|
||||||
static void fluid_settings_init(fluid_settings_t* settings);
|
static void fluid_settings_init(fluid_settings_t* settings);
|
||||||
static void fluid_settings_hash_delete(void* value, int type);
|
static void fluid_settings_hash_delete(void* value, int type);
|
||||||
static int fluid_settings_tokenize(char* s, char* buf, char** ptr);
|
static int fluid_settings_tokenize(char* s, char *buf, char** ptr);
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -42,7 +45,7 @@ typedef struct {
|
|||||||
void* data;
|
void* data;
|
||||||
} fluid_str_setting_t;
|
} fluid_str_setting_t;
|
||||||
|
|
||||||
static fluid_str_setting_t*
|
static fluid_str_setting_t*
|
||||||
new_fluid_str_setting(char* value, char* def, int hints, fluid_str_update_t fun, void* data)
|
new_fluid_str_setting(char* value, char* def, int hints, fluid_str_update_t fun, void* data)
|
||||||
{
|
{
|
||||||
fluid_str_setting_t* str;
|
fluid_str_setting_t* str;
|
||||||
@@ -60,13 +63,20 @@ static void delete_fluid_str_setting(fluid_str_setting_t* str)
|
|||||||
{
|
{
|
||||||
if (str) {
|
if (str) {
|
||||||
if (str->value) {
|
if (str->value) {
|
||||||
FLUID_FREE(str->value);
|
FLUID_FREE(str->value);
|
||||||
}
|
}
|
||||||
if (str->def) {
|
if (str->def) {
|
||||||
FLUID_FREE(str->def);
|
FLUID_FREE(str->def);
|
||||||
}
|
}
|
||||||
if (str->options) {
|
if (str->options) {
|
||||||
delete_fluid_list(str->options);
|
fluid_list_t* list = str->options;
|
||||||
|
|
||||||
|
while (list) {
|
||||||
|
FLUID_FREE (list->data);
|
||||||
|
list = fluid_list_next(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete_fluid_list(str->options);
|
||||||
}
|
}
|
||||||
FLUID_FREE(str);
|
FLUID_FREE(str);
|
||||||
}
|
}
|
||||||
@@ -86,7 +96,7 @@ typedef struct {
|
|||||||
} fluid_num_setting_t;
|
} fluid_num_setting_t;
|
||||||
|
|
||||||
|
|
||||||
static fluid_num_setting_t*
|
static fluid_num_setting_t*
|
||||||
new_fluid_num_setting(double min, double max, double def,
|
new_fluid_num_setting(double min, double max, double def,
|
||||||
int hints, fluid_num_update_t fun, void* data)
|
int hints, fluid_num_update_t fun, void* data)
|
||||||
{
|
{
|
||||||
@@ -123,7 +133,7 @@ typedef struct {
|
|||||||
} fluid_int_setting_t;
|
} fluid_int_setting_t;
|
||||||
|
|
||||||
|
|
||||||
static fluid_int_setting_t*
|
static fluid_int_setting_t*
|
||||||
new_fluid_int_setting(int min, int max, int def,
|
new_fluid_int_setting(int min, int max, int def,
|
||||||
int hints, fluid_int_update_t fun, void* data)
|
int hints, fluid_int_update_t fun, void* data)
|
||||||
{
|
{
|
||||||
@@ -189,37 +199,46 @@ void fluid_settings_init(fluid_settings_t* settings)
|
|||||||
fluid_midi_driver_settings(settings);
|
fluid_midi_driver_settings(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
static fluid_strtok_t* fluid_settings_strtok = NULL;
|
static int fluid_settings_tokenize(char* s, char *buf, char** ptr)
|
||||||
|
|
||||||
int fluid_settings_tokenize(char* s, char* buf, char** ptr)
|
|
||||||
{
|
{
|
||||||
|
char *tokstr, *tok;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
||||||
FLUID_STRCPY(buf, s);
|
if (strlen (s) > MAX_SETTINGS_LABEL)
|
||||||
|
{
|
||||||
if (fluid_settings_strtok == NULL) {
|
FLUID_LOG(FLUID_ERR, "Setting variable name exceeded max length of %d chars",
|
||||||
fluid_settings_strtok = new_fluid_strtok(buf, ".");
|
MAX_SETTINGS_LABEL);
|
||||||
} else {
|
return 0;
|
||||||
fluid_strtok_set(fluid_settings_strtok, buf, ".");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (fluid_strtok_has_more(fluid_settings_strtok)) {
|
FLUID_STRCPY(buf, s); /* copy string to buffer, since it gets modified */
|
||||||
ptr[n++] = fluid_strtok_next_token(fluid_settings_strtok);
|
tokstr = buf;
|
||||||
|
|
||||||
|
while ((tok = fluid_strtok (&tokstr, ".")))
|
||||||
|
{
|
||||||
|
if (n > MAX_SETTINGS_TOKENS)
|
||||||
|
{
|
||||||
|
FLUID_LOG(FLUID_ERR, "Setting variable name exceeded max token count of %d",
|
||||||
|
MAX_SETTINGS_TOKENS);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr[n++] = tok;
|
||||||
}
|
}
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** returns 1 if the value exists, 0 otherwise */
|
/** returns 1 if the value exists, 0 otherwise */
|
||||||
static int fluid_settings_get(fluid_settings_t* settings,
|
static int fluid_settings_get(fluid_settings_t* settings,
|
||||||
char** name, int len,
|
char** name, int len,
|
||||||
void** value, int* type)
|
void** value, int* type)
|
||||||
{
|
{
|
||||||
fluid_hashtable_t* table = settings;
|
fluid_hashtable_t* table = settings;
|
||||||
int t;
|
int t;
|
||||||
void* v;
|
void* v;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
for (n = 0; n < len; n++) {
|
for (n = 0; n < len; n++) {
|
||||||
|
|
||||||
if (table == NULL) {
|
if (table == NULL) {
|
||||||
@@ -244,10 +263,9 @@ static int fluid_settings_get(fluid_settings_t* settings,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** returns 1 if the value has been set, zero otherwise */
|
/** returns 1 if the value has been set, zero otherwise */
|
||||||
static int fluid_settings_set(fluid_settings_t* settings,
|
static int fluid_settings_set(fluid_settings_t* settings,
|
||||||
char** name, int len,
|
char** name, int len,
|
||||||
void* value, int type)
|
void* value, int type)
|
||||||
{
|
{
|
||||||
fluid_hashtable_t* table = settings;
|
fluid_hashtable_t* table = settings;
|
||||||
@@ -276,29 +294,29 @@ static int fluid_settings_set(fluid_settings_t* settings,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fluid_hashtable_replace(table, name[num], value, type);
|
fluid_hashtable_replace(table, name[num], value, type);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** returns 1 if the value has been resgister correctly, 0
|
/** returns 1 if the value has been registered correctly, 0
|
||||||
otherwise */
|
otherwise */
|
||||||
int fluid_settings_register_str(fluid_settings_t* settings, char* name, char* def, int hints,
|
int fluid_settings_register_str(fluid_settings_t* settings, char* name, char* def, int hints,
|
||||||
fluid_str_update_t fun, void* data)
|
fluid_str_update_t fun, void* data)
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
void* value;
|
void* value;
|
||||||
char buf[1024];
|
char* tokens[MAX_SETTINGS_TOKENS];
|
||||||
char* tokens[16];
|
char buf[MAX_SETTINGS_LABEL+1];
|
||||||
int ntokens;
|
int ntokens;
|
||||||
fluid_str_setting_t* setting;
|
fluid_str_setting_t* setting;
|
||||||
|
|
||||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||||
|
|
||||||
if (!fluid_settings_get(settings, tokens, ntokens, &value, &type)) {
|
if (!fluid_settings_get(settings, tokens, ntokens, &value, &type)) {
|
||||||
setting = new_fluid_str_setting(def, def, hints, fun, data);
|
setting = new_fluid_str_setting(def, def, hints, fun, data);
|
||||||
return fluid_settings_set(settings, tokens, ntokens, setting, FLUID_STR_TYPE);
|
return fluid_settings_set(settings, tokens, ntokens, setting, FLUID_STR_TYPE);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* if variable already exists, don't change its value. */
|
/* if variable already exists, don't change its value. */
|
||||||
if (type == FLUID_STR_TYPE) {
|
if (type == FLUID_STR_TYPE) {
|
||||||
@@ -317,14 +335,14 @@ int fluid_settings_register_str(fluid_settings_t* settings, char* name, char* de
|
|||||||
|
|
||||||
/** returns 1 if the value has been register correctly, zero
|
/** returns 1 if the value has been register correctly, zero
|
||||||
otherwise */
|
otherwise */
|
||||||
int fluid_settings_register_num(fluid_settings_t* settings, char* name, double def,
|
int fluid_settings_register_num(fluid_settings_t* settings, char* name, double def,
|
||||||
double min, double max, int hints,
|
double min, double max, int hints,
|
||||||
fluid_num_update_t fun, void* data)
|
fluid_num_update_t fun, void* data)
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
void* value;
|
void* value;
|
||||||
char buf[1024];
|
char* tokens[MAX_SETTINGS_TOKENS];
|
||||||
char* tokens[16];
|
char buf[MAX_SETTINGS_LABEL+1];
|
||||||
int ntokens;
|
int ntokens;
|
||||||
|
|
||||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||||
@@ -357,14 +375,14 @@ int fluid_settings_register_num(fluid_settings_t* settings, char* name, double d
|
|||||||
|
|
||||||
/** returns 1 if the value has been register correctly, zero
|
/** returns 1 if the value has been register correctly, zero
|
||||||
otherwise */
|
otherwise */
|
||||||
int fluid_settings_register_int(fluid_settings_t* settings, char* name, int def,
|
int fluid_settings_register_int(fluid_settings_t* settings, char* name, int def,
|
||||||
int min, int max, int hints,
|
int min, int max, int hints,
|
||||||
fluid_int_update_t fun, void* data)
|
fluid_int_update_t fun, void* data)
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
void* value;
|
void* value;
|
||||||
char buf[1024];
|
char* tokens[MAX_SETTINGS_TOKENS];
|
||||||
char* tokens[16];
|
char buf[MAX_SETTINGS_LABEL+1];
|
||||||
int ntokens;
|
int ntokens;
|
||||||
|
|
||||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||||
@@ -395,13 +413,12 @@ int fluid_settings_register_int(fluid_settings_t* settings, char* name, int def,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int fluid_settings_get_type(fluid_settings_t* settings, char* name)
|
int fluid_settings_get_type(fluid_settings_t* settings, char* name)
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
void* value;
|
void* value;
|
||||||
char buf[1024];
|
char* tokens[MAX_SETTINGS_TOKENS];
|
||||||
char* tokens[16];
|
char buf[MAX_SETTINGS_LABEL+1];
|
||||||
int ntokens;
|
int ntokens;
|
||||||
|
|
||||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||||
@@ -409,13 +426,12 @@ int fluid_settings_get_type(fluid_settings_t* settings, char* name)
|
|||||||
return (fluid_settings_get(settings, tokens, ntokens, &value, &type))? type : FLUID_NO_TYPE;
|
return (fluid_settings_get(settings, tokens, ntokens, &value, &type))? type : FLUID_NO_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int fluid_settings_get_hints(fluid_settings_t* settings, char* name)
|
int fluid_settings_get_hints(fluid_settings_t* settings, char* name)
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
void* value;
|
void* value;
|
||||||
char buf[1024];
|
char* tokens[MAX_SETTINGS_TOKENS];
|
||||||
char* tokens[16];
|
char buf[MAX_SETTINGS_LABEL+1];
|
||||||
int ntokens;
|
int ntokens;
|
||||||
|
|
||||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||||
@@ -439,8 +455,8 @@ int fluid_settings_is_realtime(fluid_settings_t* settings, char* name)
|
|||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
void* value;
|
void* value;
|
||||||
char buf[1024];
|
char* tokens[MAX_SETTINGS_TOKENS];
|
||||||
char* tokens[16];
|
char buf[MAX_SETTINGS_LABEL+1];
|
||||||
int ntokens;
|
int ntokens;
|
||||||
|
|
||||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||||
@@ -461,11 +477,10 @@ int fluid_settings_is_realtime(fluid_settings_t* settings, char* name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int fluid_settings_setstr(fluid_settings_t* settings, char* name, char* str)
|
int fluid_settings_setstr(fluid_settings_t* settings, char* name, char* str)
|
||||||
{
|
{
|
||||||
char buf[1024];
|
char* tokens[MAX_SETTINGS_TOKENS];
|
||||||
char* tokens[16];
|
char buf[MAX_SETTINGS_LABEL+1];
|
||||||
int ntokens;
|
int ntokens;
|
||||||
int type;
|
int type;
|
||||||
void* value;
|
void* value;
|
||||||
@@ -474,7 +489,7 @@ int fluid_settings_setstr(fluid_settings_t* settings, char* name, char* str)
|
|||||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||||
|
|
||||||
if (fluid_settings_get(settings, tokens, ntokens, &value, &type)) {
|
if (fluid_settings_get(settings, tokens, ntokens, &value, &type)) {
|
||||||
|
|
||||||
if (type != FLUID_STR_TYPE) {
|
if (type != FLUID_STR_TYPE) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -485,14 +500,14 @@ int fluid_settings_setstr(fluid_settings_t* settings, char* name, char* str)
|
|||||||
FLUID_FREE(setting->value);
|
FLUID_FREE(setting->value);
|
||||||
}
|
}
|
||||||
setting->value = str? FLUID_STRDUP(str) : NULL;
|
setting->value = str? FLUID_STRDUP(str) : NULL;
|
||||||
|
|
||||||
if (setting->update) {
|
if (setting->update) {
|
||||||
(*setting->update)(setting->data, name, setting->value);
|
(*setting->update)(setting->data, name, setting->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* insert a new setting */
|
/* insert a new setting */
|
||||||
fluid_str_setting_t* setting;
|
fluid_str_setting_t* setting;
|
||||||
setting = new_fluid_str_setting(str, NULL, 0, NULL, NULL);
|
setting = new_fluid_str_setting(str, NULL, 0, NULL, NULL);
|
||||||
@@ -504,13 +519,13 @@ int fluid_settings_getstr(fluid_settings_t* settings, char* name, char** str)
|
|||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
void* value;
|
void* value;
|
||||||
char buf[1024];
|
char* tokens[MAX_SETTINGS_TOKENS];
|
||||||
char* tokens[16];
|
char buf[MAX_SETTINGS_LABEL+1];
|
||||||
int ntokens;
|
int ntokens;
|
||||||
|
|
||||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||||
|
|
||||||
if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
|
if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
|
||||||
&& (type == FLUID_STR_TYPE)) {
|
&& (type == FLUID_STR_TYPE)) {
|
||||||
fluid_str_setting_t* setting = (fluid_str_setting_t*) value;
|
fluid_str_setting_t* setting = (fluid_str_setting_t*) value;
|
||||||
*str = setting->value;
|
*str = setting->value;
|
||||||
@@ -520,18 +535,17 @@ int fluid_settings_getstr(fluid_settings_t* settings, char* name, char** str)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int fluid_settings_str_equal(fluid_settings_t* settings, char* name, char* s)
|
int fluid_settings_str_equal(fluid_settings_t* settings, char* name, char* s)
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
void* value;
|
void* value;
|
||||||
char buf[1024];
|
char* tokens[MAX_SETTINGS_TOKENS];
|
||||||
char* tokens[16];
|
char buf[MAX_SETTINGS_LABEL+1];
|
||||||
int ntokens;
|
int ntokens;
|
||||||
|
|
||||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||||
|
|
||||||
if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
|
if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
|
||||||
&& (type == FLUID_STR_TYPE)) {
|
&& (type == FLUID_STR_TYPE)) {
|
||||||
fluid_str_setting_t* setting = (fluid_str_setting_t*) value;
|
fluid_str_setting_t* setting = (fluid_str_setting_t*) value;
|
||||||
return FLUID_STRCMP(setting->value, s) == 0;
|
return FLUID_STRCMP(setting->value, s) == 0;
|
||||||
@@ -539,19 +553,18 @@ int fluid_settings_str_equal(fluid_settings_t* settings, char* name, char* s)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char*
|
||||||
char*
|
|
||||||
fluid_settings_getstr_default(fluid_settings_t* settings, char* name)
|
fluid_settings_getstr_default(fluid_settings_t* settings, char* name)
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
void* value;
|
void* value;
|
||||||
char buf[1024];
|
char* tokens[MAX_SETTINGS_TOKENS];
|
||||||
char* tokens[16];
|
char buf[MAX_SETTINGS_LABEL+1];
|
||||||
int ntokens;
|
int ntokens;
|
||||||
|
|
||||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||||
|
|
||||||
if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
|
if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
|
||||||
&& (type == FLUID_STR_TYPE)) {
|
&& (type == FLUID_STR_TYPE)) {
|
||||||
fluid_str_setting_t* setting = (fluid_str_setting_t*) value;
|
fluid_str_setting_t* setting = (fluid_str_setting_t*) value;
|
||||||
return setting->def;
|
return setting->def;
|
||||||
@@ -564,13 +577,13 @@ int fluid_settings_add_option(fluid_settings_t* settings, char* name, char* s)
|
|||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
void* value;
|
void* value;
|
||||||
char buf[1024];
|
char* tokens[MAX_SETTINGS_TOKENS];
|
||||||
char* tokens[16];
|
char buf[MAX_SETTINGS_LABEL+1];
|
||||||
int ntokens;
|
int ntokens;
|
||||||
|
|
||||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||||
|
|
||||||
if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
|
if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
|
||||||
&& (type == FLUID_STR_TYPE)) {
|
&& (type == FLUID_STR_TYPE)) {
|
||||||
fluid_str_setting_t* setting = (fluid_str_setting_t*) value;
|
fluid_str_setting_t* setting = (fluid_str_setting_t*) value;
|
||||||
char* copy = FLUID_STRDUP(s);
|
char* copy = FLUID_STRDUP(s);
|
||||||
@@ -578,20 +591,20 @@ int fluid_settings_add_option(fluid_settings_t* settings, char* name, char* s)
|
|||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int fluid_settings_remove_option(fluid_settings_t* settings, char* name, char* s)
|
int fluid_settings_remove_option(fluid_settings_t* settings, char* name, char* s)
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
void* value;
|
void* value;
|
||||||
char buf[1024];
|
char* tokens[MAX_SETTINGS_TOKENS];
|
||||||
char* tokens[16];
|
char buf[MAX_SETTINGS_LABEL+1];
|
||||||
int ntokens;
|
int ntokens;
|
||||||
|
|
||||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||||
|
|
||||||
if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
|
if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
|
||||||
&& (type == FLUID_STR_TYPE)) {
|
&& (type == FLUID_STR_TYPE)) {
|
||||||
|
|
||||||
fluid_str_setting_t* setting = (fluid_str_setting_t*) value;
|
fluid_str_setting_t* setting = (fluid_str_setting_t*) value;
|
||||||
@@ -600,6 +613,7 @@ int fluid_settings_remove_option(fluid_settings_t* settings, char* name, char* s
|
|||||||
while (list) {
|
while (list) {
|
||||||
char* option = (char*) fluid_list_get(list);
|
char* option = (char*) fluid_list_get(list);
|
||||||
if (FLUID_STRCMP(s, option) == 0) {
|
if (FLUID_STRCMP(s, option) == 0) {
|
||||||
|
FLUID_FREE (option);
|
||||||
setting->options = fluid_list_remove_link(setting->options, list);
|
setting->options = fluid_list_remove_link(setting->options, list);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -609,17 +623,16 @@ int fluid_settings_remove_option(fluid_settings_t* settings, char* name, char* s
|
|||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int fluid_settings_setnum(fluid_settings_t* settings, char* name, double val)
|
int fluid_settings_setnum(fluid_settings_t* settings, char* name, double val)
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
void* value;
|
void* value;
|
||||||
fluid_num_setting_t* setting;
|
fluid_num_setting_t* setting;
|
||||||
char buf[1024];
|
char* tokens[MAX_SETTINGS_TOKENS];
|
||||||
char* tokens[16];
|
char buf[MAX_SETTINGS_LABEL+1];
|
||||||
int ntokens;
|
int ntokens;
|
||||||
|
|
||||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||||
@@ -631,22 +644,22 @@ int fluid_settings_setnum(fluid_settings_t* settings, char* name, double val)
|
|||||||
}
|
}
|
||||||
|
|
||||||
setting = (fluid_num_setting_t*) value;
|
setting = (fluid_num_setting_t*) value;
|
||||||
|
|
||||||
if (val < setting->min) {
|
if (val < setting->min) {
|
||||||
val = setting->min;
|
val = setting->min;
|
||||||
} else if (val > setting->max) {
|
} else if (val > setting->max) {
|
||||||
val = setting->max;
|
val = setting->max;
|
||||||
}
|
}
|
||||||
|
|
||||||
setting->value = val;
|
setting->value = val;
|
||||||
|
|
||||||
if (setting->update) {
|
if (setting->update) {
|
||||||
(*setting->update)(setting->data, name, val);
|
(*setting->update)(setting->data, name, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* insert a new setting */
|
/* insert a new setting */
|
||||||
fluid_num_setting_t* setting;
|
fluid_num_setting_t* setting;
|
||||||
setting = new_fluid_num_setting(-1e10, 1e10, 0.0f, 0, NULL, NULL);
|
setting = new_fluid_num_setting(-1e10, 1e10, 0.0f, 0, NULL, NULL);
|
||||||
@@ -659,13 +672,13 @@ int fluid_settings_getnum(fluid_settings_t* settings, char* name, double* val)
|
|||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
void* value;
|
void* value;
|
||||||
char buf[1024];
|
char* tokens[MAX_SETTINGS_TOKENS];
|
||||||
char* tokens[16];
|
char buf[MAX_SETTINGS_LABEL+1];
|
||||||
int ntokens;
|
int ntokens;
|
||||||
|
|
||||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||||
|
|
||||||
if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
|
if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
|
||||||
&& (type == FLUID_NUM_TYPE)) {
|
&& (type == FLUID_NUM_TYPE)) {
|
||||||
fluid_num_setting_t* setting = (fluid_num_setting_t*) value;
|
fluid_num_setting_t* setting = (fluid_num_setting_t*) value;
|
||||||
*val = setting->value;
|
*val = setting->value;
|
||||||
@@ -679,13 +692,13 @@ void fluid_settings_getnum_range(fluid_settings_t* settings, char* name, double*
|
|||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
void* value;
|
void* value;
|
||||||
char buf[1024];
|
char* tokens[MAX_SETTINGS_TOKENS];
|
||||||
char* tokens[16];
|
char buf[MAX_SETTINGS_LABEL+1];
|
||||||
int ntokens;
|
int ntokens;
|
||||||
|
|
||||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||||
|
|
||||||
if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
|
if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
|
||||||
&& (type == FLUID_NUM_TYPE)) {
|
&& (type == FLUID_NUM_TYPE)) {
|
||||||
fluid_num_setting_t* setting = (fluid_num_setting_t*) value;
|
fluid_num_setting_t* setting = (fluid_num_setting_t*) value;
|
||||||
*min = setting->min;
|
*min = setting->min;
|
||||||
@@ -693,18 +706,18 @@ void fluid_settings_getnum_range(fluid_settings_t* settings, char* name, double*
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double
|
double
|
||||||
fluid_settings_getnum_default(fluid_settings_t* settings, char* name)
|
fluid_settings_getnum_default(fluid_settings_t* settings, char* name)
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
void* value;
|
void* value;
|
||||||
char buf[1024];
|
char* tokens[MAX_SETTINGS_TOKENS];
|
||||||
char* tokens[16];
|
char buf[MAX_SETTINGS_LABEL+1];
|
||||||
int ntokens;
|
int ntokens;
|
||||||
|
|
||||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||||
|
|
||||||
if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
|
if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
|
||||||
&& (type == FLUID_NUM_TYPE)) {
|
&& (type == FLUID_NUM_TYPE)) {
|
||||||
fluid_num_setting_t* setting = (fluid_num_setting_t*) value;
|
fluid_num_setting_t* setting = (fluid_num_setting_t*) value;
|
||||||
return setting->def;
|
return setting->def;
|
||||||
@@ -719,8 +732,8 @@ int fluid_settings_setint(fluid_settings_t* settings, char* name, int val)
|
|||||||
int type;
|
int type;
|
||||||
void* value;
|
void* value;
|
||||||
fluid_int_setting_t* setting;
|
fluid_int_setting_t* setting;
|
||||||
char buf[1024];
|
char* tokens[MAX_SETTINGS_TOKENS];
|
||||||
char* tokens[16];
|
char buf[MAX_SETTINGS_LABEL+1];
|
||||||
int ntokens;
|
int ntokens;
|
||||||
|
|
||||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||||
@@ -732,22 +745,22 @@ int fluid_settings_setint(fluid_settings_t* settings, char* name, int val)
|
|||||||
}
|
}
|
||||||
|
|
||||||
setting = (fluid_int_setting_t*) value;
|
setting = (fluid_int_setting_t*) value;
|
||||||
|
|
||||||
if (val < setting->min) {
|
if (val < setting->min) {
|
||||||
val = setting->min;
|
val = setting->min;
|
||||||
} else if (val > setting->max) {
|
} else if (val > setting->max) {
|
||||||
val = setting->max;
|
val = setting->max;
|
||||||
}
|
}
|
||||||
|
|
||||||
setting->value = val;
|
setting->value = val;
|
||||||
|
|
||||||
if (setting->update) {
|
if (setting->update) {
|
||||||
(*setting->update)(setting->data, name, val);
|
(*setting->update)(setting->data, name, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* insert a new setting */
|
/* insert a new setting */
|
||||||
fluid_int_setting_t* setting;
|
fluid_int_setting_t* setting;
|
||||||
setting = new_fluid_int_setting(INT_MIN, INT_MAX, 0, 0, NULL, NULL);
|
setting = new_fluid_int_setting(INT_MIN, INT_MAX, 0, 0, NULL, NULL);
|
||||||
@@ -760,13 +773,13 @@ int fluid_settings_getint(fluid_settings_t* settings, char* name, int* val)
|
|||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
void* value;
|
void* value;
|
||||||
char buf[1024];
|
char* tokens[MAX_SETTINGS_TOKENS];
|
||||||
char* tokens[16];
|
char buf[MAX_SETTINGS_LABEL+1];
|
||||||
int ntokens;
|
int ntokens;
|
||||||
|
|
||||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||||
|
|
||||||
if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
|
if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
|
||||||
&& (type == FLUID_INT_TYPE)) {
|
&& (type == FLUID_INT_TYPE)) {
|
||||||
fluid_int_setting_t* setting = (fluid_int_setting_t*) value;
|
fluid_int_setting_t* setting = (fluid_int_setting_t*) value;
|
||||||
*val = setting->value;
|
*val = setting->value;
|
||||||
@@ -780,13 +793,13 @@ void fluid_settings_getint_range(fluid_settings_t* settings, char* name, int* mi
|
|||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
void* value;
|
void* value;
|
||||||
char buf[1024];
|
char* tokens[MAX_SETTINGS_TOKENS];
|
||||||
char* tokens[16];
|
char buf[MAX_SETTINGS_LABEL+1];
|
||||||
int ntokens;
|
int ntokens;
|
||||||
|
|
||||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||||
|
|
||||||
if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
|
if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
|
||||||
&& (type == FLUID_INT_TYPE)) {
|
&& (type == FLUID_INT_TYPE)) {
|
||||||
fluid_int_setting_t* setting = (fluid_int_setting_t*) value;
|
fluid_int_setting_t* setting = (fluid_int_setting_t*) value;
|
||||||
*min = setting->min;
|
*min = setting->min;
|
||||||
@@ -799,13 +812,13 @@ fluid_settings_getint_default(fluid_settings_t* settings, char* name)
|
|||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
void* value;
|
void* value;
|
||||||
char buf[1024];
|
char* tokens[MAX_SETTINGS_TOKENS];
|
||||||
char* tokens[16];
|
char buf[MAX_SETTINGS_LABEL+1];
|
||||||
int ntokens;
|
int ntokens;
|
||||||
|
|
||||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||||
|
|
||||||
if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
|
if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
|
||||||
&& (type == FLUID_INT_TYPE)) {
|
&& (type == FLUID_INT_TYPE)) {
|
||||||
fluid_int_setting_t* setting = (fluid_int_setting_t*) value;
|
fluid_int_setting_t* setting = (fluid_int_setting_t*) value;
|
||||||
return setting->def;
|
return setting->def;
|
||||||
@@ -817,13 +830,13 @@ fluid_settings_getint_default(fluid_settings_t* settings, char* name)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void fluid_settings_foreach_option(fluid_settings_t* settings, char* name, void* data,
|
void fluid_settings_foreach_option(fluid_settings_t* settings, char* name, void* data,
|
||||||
fluid_settings_foreach_option_t func)
|
fluid_settings_foreach_option_t func)
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
void* value;
|
void* value;
|
||||||
char buf[1024];
|
char* tokens[MAX_SETTINGS_TOKENS];
|
||||||
char* tokens[16];
|
char buf[MAX_SETTINGS_LABEL+1];
|
||||||
int ntokens;
|
int ntokens;
|
||||||
|
|
||||||
if (!func) {
|
if (!func) {
|
||||||
@@ -832,7 +845,7 @@ void fluid_settings_foreach_option(fluid_settings_t* settings, char* name, void*
|
|||||||
|
|
||||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||||
|
|
||||||
if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
|
if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
|
||||||
&& (type == FLUID_STR_TYPE)) {
|
&& (type == FLUID_STR_TYPE)) {
|
||||||
|
|
||||||
fluid_str_setting_t* setting = (fluid_str_setting_t*) value;
|
fluid_str_setting_t* setting = (fluid_str_setting_t*) value;
|
||||||
@@ -843,7 +856,7 @@ void fluid_settings_foreach_option(fluid_settings_t* settings, char* name, void*
|
|||||||
(*func)(data, name, option);
|
(*func)(data, name, option);
|
||||||
list = fluid_list_next(list);
|
list = fluid_list_next(list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -42,13 +42,13 @@ int fluid_settings_register_str(fluid_settings_t* settings, char* name, char* de
|
|||||||
|
|
||||||
/** returns 0 if the value has been resgister correctly, non-zero
|
/** returns 0 if the value has been resgister correctly, non-zero
|
||||||
otherwise */
|
otherwise */
|
||||||
int fluid_settings_register_num(fluid_settings_t* settings, char* name, double min, double max,
|
int fluid_settings_register_num(fluid_settings_t* settings, char* name, double min, double max,
|
||||||
double def, int hints, fluid_num_update_t fun, void* data);
|
double def, int hints, fluid_num_update_t fun, void* data);
|
||||||
|
|
||||||
|
|
||||||
/** returns 0 if the value has been resgister correctly, non-zero
|
/** returns 0 if the value has been resgister correctly, non-zero
|
||||||
otherwise */
|
otherwise */
|
||||||
int fluid_settings_register_int(fluid_settings_t* settings, char* name, int min, int max,
|
int fluid_settings_register_int(fluid_settings_t* settings, char* name, int min, int max,
|
||||||
int def, int hints, fluid_int_update_t fun, void* data);
|
int def, int hints, fluid_int_update_t fun, void* data);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -61,7 +61,7 @@
|
|||||||
#define fluid_sample_decr_ref(_sample) \
|
#define fluid_sample_decr_ref(_sample) \
|
||||||
(_sample)->refcount--; \
|
(_sample)->refcount--; \
|
||||||
if (((_sample)->refcount == 0) && ((_sample)->notify)) \
|
if (((_sample)->refcount == 0) && ((_sample)->notify)) \
|
||||||
(*(_sample)->notify)(_sample, FLUID_SAMPLE_DONE);
|
(*(_sample)->notify)(_sample, FLUID_SAMPLE_DONE);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -98,7 +98,7 @@ struct _fluid_synth_t
|
|||||||
double sample_rate; /** The sample rate */
|
double sample_rate; /** The sample rate */
|
||||||
int midi_channels; /** the number of MIDI channels (>= 16) */
|
int midi_channels; /** the number of MIDI channels (>= 16) */
|
||||||
int audio_channels; /** the number of audio channels (1 channel=left+right) */
|
int audio_channels; /** the number of audio channels (1 channel=left+right) */
|
||||||
int audio_groups; /** the number of (stereo) 'sub'groups from the synth.
|
int audio_groups; /** the number of (stereo) 'sub'groups from the synth.
|
||||||
Typically equal to audio_channels. */
|
Typically equal to audio_channels. */
|
||||||
int effects_channels; /** the number of effects channels (= 2) */
|
int effects_channels; /** the number of effects channels (= 2) */
|
||||||
unsigned int state; /** the synthesizer state */
|
unsigned int state; /** the synthesizer state */
|
||||||
@@ -120,7 +120,7 @@ struct _fluid_synth_t
|
|||||||
int nvoice; /** the length of the synthesis process array */
|
int nvoice; /** the length of the synthesis process array */
|
||||||
fluid_voice_t** voice; /** the synthesis processes */
|
fluid_voice_t** voice; /** the synthesis processes */
|
||||||
unsigned int noteid; /** the id is incremented for every new note. it's used for noteoff's */
|
unsigned int noteid; /** the id is incremented for every new note. it's used for noteoff's */
|
||||||
unsigned int storeid;
|
unsigned int storeid;
|
||||||
int nbuf; /** How many audio buffers are used? (depends on nr of audio channels / groups)*/
|
int nbuf; /** How many audio buffers are used? (depends on nr of audio channels / groups)*/
|
||||||
|
|
||||||
fluid_real_t** left_buf;
|
fluid_real_t** left_buf;
|
||||||
@@ -128,23 +128,19 @@ struct _fluid_synth_t
|
|||||||
fluid_real_t** fx_left_buf;
|
fluid_real_t** fx_left_buf;
|
||||||
fluid_real_t** fx_right_buf;
|
fluid_real_t** fx_right_buf;
|
||||||
|
|
||||||
fluid_real_t** left_ubuf; /* Stores the unaligned buffers (see new_fluid_synth) */
|
|
||||||
fluid_real_t** right_ubuf; /* Stores the unaligned buffers (see new_fluid_synth) */
|
|
||||||
fluid_real_t** fx_left_ubuf; /* Stores the unaligned buffers (see new_fluid_synth) */
|
|
||||||
fluid_real_t** fx_right_ubuf; /* Stores the unaligned buffers (see new_fluid_synth) */
|
|
||||||
|
|
||||||
fluid_revmodel_t* reverb;
|
fluid_revmodel_t* reverb;
|
||||||
fluid_chorus_t* chorus;
|
fluid_chorus_t* chorus;
|
||||||
int cur; /** the current sample in the audio buffers to be output */
|
int cur; /** the current sample in the audio buffers to be output */
|
||||||
|
int dither_index; /* current index in random dither value buffer: fluid_synth_(write_s16|dither_s16) */
|
||||||
|
|
||||||
char outbuf[256]; /** buffer for message output */
|
char outbuf[256]; /** buffer for message output */
|
||||||
double cpu_load;
|
double cpu_load;
|
||||||
|
|
||||||
fluid_tuning_t*** tuning; /** 128 banks of 128 programs for the tunings */
|
fluid_tuning_t*** tuning; /** 128 banks of 128 programs for the tunings */
|
||||||
fluid_tuning_t* cur_tuning; /** current tuning in the iteration */
|
fluid_tuning_t* cur_tuning; /** current tuning in the iteration */
|
||||||
|
|
||||||
fluid_midi_router_t* midi_router; /* The midi router. Could be done nicer. */
|
fluid_midi_router_t* midi_router; /* The midi router. Could be done nicer. */
|
||||||
fluid_mutex_t busy; /* Indicates, whether the audio thread is currently running.
|
fluid_mutex_t busy; /* Indicates, whether the audio thread is currently running.
|
||||||
* Note: This simple scheme does -not- provide 100 % protection against
|
* Note: This simple scheme does -not- provide 100 % protection against
|
||||||
* thread problems, for example from MIDI thread and shell thread
|
* thread problems, for example from MIDI thread and shell thread
|
||||||
*/
|
*/
|
||||||
@@ -153,7 +149,6 @@ struct _fluid_synth_t
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/** returns 1 if the value has been set, 0 otherwise */
|
/** returns 1 if the value has been set, 0 otherwise */
|
||||||
int fluid_synth_setstr(fluid_synth_t* synth, char* name, char* str);
|
int fluid_synth_setstr(fluid_synth_t* synth, char* name, char* str);
|
||||||
|
|
||||||
@@ -177,13 +172,13 @@ int fluid_synth_set_reverb_preset(fluid_synth_t* synth, int num);
|
|||||||
|
|
||||||
int fluid_synth_one_block(fluid_synth_t* synth, int do_not_mix_fx_to_out);
|
int fluid_synth_one_block(fluid_synth_t* synth, int do_not_mix_fx_to_out);
|
||||||
|
|
||||||
fluid_preset_t* fluid_synth_get_preset(fluid_synth_t* synth,
|
fluid_preset_t* fluid_synth_get_preset(fluid_synth_t* synth,
|
||||||
unsigned int sfontnum,
|
unsigned int sfontnum,
|
||||||
unsigned int banknum,
|
unsigned int banknum,
|
||||||
unsigned int prognum);
|
unsigned int prognum);
|
||||||
|
|
||||||
fluid_preset_t* fluid_synth_find_preset(fluid_synth_t* synth,
|
fluid_preset_t* fluid_synth_find_preset(fluid_synth_t* synth,
|
||||||
unsigned int banknum,
|
unsigned int banknum,
|
||||||
unsigned int prognum);
|
unsigned int prognum);
|
||||||
|
|
||||||
int fluid_synth_all_notes_off(fluid_synth_t* synth, int chan);
|
int fluid_synth_all_notes_off(fluid_synth_t* synth, int chan);
|
||||||
@@ -210,8 +205,9 @@ int fluid_synth_update_polyphony(fluid_synth_t* synth, char* name, int value);
|
|||||||
fluid_bank_offset_t* fluid_synth_get_bank_offset0(fluid_synth_t* synth, int sfont_id);
|
fluid_bank_offset_t* fluid_synth_get_bank_offset0(fluid_synth_t* synth, int sfont_id);
|
||||||
void fluid_synth_remove_bank_offset(fluid_synth_t* synth, int sfont_id);
|
void fluid_synth_remove_bank_offset(fluid_synth_t* synth, int sfont_id);
|
||||||
|
|
||||||
|
void fluid_synth_dither_s16(int *dither_index, int len, float* lin, float* rin,
|
||||||
|
void* lout, int loff, int lincr,
|
||||||
|
void* rout, int roff, int rincr);
|
||||||
/*
|
/*
|
||||||
* misc
|
* misc
|
||||||
*/
|
*/
|
||||||
|
|||||||
+201
-112
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -20,7 +20,6 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "fluid_sys.h"
|
#include "fluid_sys.h"
|
||||||
//#include <fpu_control.h>
|
|
||||||
|
|
||||||
static char fluid_errbuf[512]; /* buffer for error message */
|
static char fluid_errbuf[512]; /* buffer for error message */
|
||||||
|
|
||||||
@@ -34,7 +33,7 @@ static char* fluid_libname = "fluidsynth";
|
|||||||
void fluid_sys_config()
|
void fluid_sys_config()
|
||||||
{
|
{
|
||||||
fluid_log_config();
|
fluid_log_config();
|
||||||
fluid_time_config();
|
fluid_time_config();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -48,25 +47,29 @@ int fluid_debug(int level, char * fmt, ...)
|
|||||||
{
|
{
|
||||||
if (fluid_debug_flags & level) {
|
if (fluid_debug_flags & level) {
|
||||||
fluid_log_function_t fun;
|
fluid_log_function_t fun;
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
||||||
va_start (args, fmt);
|
va_start (args, fmt);
|
||||||
vsnprintf(fluid_errbuf, sizeof (fluid_errbuf), fmt, args);
|
vsnprintf(fluid_errbuf, sizeof (fluid_errbuf), fmt, args);
|
||||||
va_end (args);
|
va_end (args);
|
||||||
|
|
||||||
fun = fluid_log_function[FLUID_DBG];
|
fun = fluid_log_function[FLUID_DBG];
|
||||||
if (fun != NULL) {
|
if (fun != NULL) {
|
||||||
(*fun)(level, fluid_errbuf, fluid_log_user_data[FLUID_DBG]);
|
(*fun)(level, fluid_errbuf, fluid_log_user_data[FLUID_DBG]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* fluid_set_log_function
|
* Installs a new log function for a specified log level.
|
||||||
|
* @param level Log level to install handler for.
|
||||||
|
* @param fun Callback function handler to call for logged messages
|
||||||
|
* @param data User supplied data pointer to pass to log function
|
||||||
|
* @return The previously installed function.
|
||||||
*/
|
*/
|
||||||
fluid_log_function_t
|
fluid_log_function_t
|
||||||
fluid_set_log_function(int level, fluid_log_function_t fun, void* data)
|
fluid_set_log_function(int level, fluid_log_function_t fun, void* data)
|
||||||
{
|
{
|
||||||
fluid_log_function_t old = NULL;
|
fluid_log_function_t old = NULL;
|
||||||
@@ -79,10 +82,13 @@ fluid_set_log_function(int level, fluid_log_function_t fun, void* data)
|
|||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* fluid_default_log_function
|
* Default log function which prints to the stderr.
|
||||||
|
* @param level Log level
|
||||||
|
* @param message Log message
|
||||||
|
* @param data User supplied data (not used)
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
fluid_default_log_function(int level, char* message, void* data)
|
fluid_default_log_function(int level, char* message, void* data)
|
||||||
{
|
{
|
||||||
FILE* out;
|
FILE* out;
|
||||||
@@ -92,25 +98,25 @@ fluid_default_log_function(int level, char* message, void* data)
|
|||||||
#else
|
#else
|
||||||
out = stderr;
|
out = stderr;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (fluid_log_initialized == 0) {
|
if (fluid_log_initialized == 0) {
|
||||||
fluid_log_config();
|
fluid_log_config();
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (level) {
|
switch (level) {
|
||||||
case FLUID_PANIC:
|
case FLUID_PANIC:
|
||||||
FLUID_FPRINTF(out, "%s: panic: %s\n", fluid_libname, message);
|
FLUID_FPRINTF(out, "%s: panic: %s\n", fluid_libname, message);
|
||||||
break;
|
break;
|
||||||
case FLUID_ERR:
|
case FLUID_ERR:
|
||||||
FLUID_FPRINTF(out, "%s: error: %s\n", fluid_libname, message);
|
FLUID_FPRINTF(out, "%s: error: %s\n", fluid_libname, message);
|
||||||
break;
|
break;
|
||||||
case FLUID_WARN:
|
case FLUID_WARN:
|
||||||
FLUID_FPRINTF(out, "%s: warning: %s\n", fluid_libname, message);
|
FLUID_FPRINTF(out, "%s: warning: %s\n", fluid_libname, message);
|
||||||
break;
|
break;
|
||||||
case FLUID_INFO:
|
case FLUID_INFO:
|
||||||
FLUID_FPRINTF(out, "%s: %s\n", fluid_libname, message);
|
FLUID_FPRINTF(out, "%s: %s\n", fluid_libname, message);
|
||||||
break;
|
break;
|
||||||
case FLUID_DBG:
|
case FLUID_DBG:
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
FLUID_FPRINTF(out, "%s: debug: %s\n", fluid_libname, message);
|
FLUID_FPRINTF(out, "%s: debug: %s\n", fluid_libname, message);
|
||||||
#endif
|
#endif
|
||||||
@@ -125,7 +131,7 @@ fluid_default_log_function(int level, char* message, void* data)
|
|||||||
/*
|
/*
|
||||||
* fluid_init_log
|
* fluid_init_log
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
fluid_log_config(void)
|
fluid_log_config(void)
|
||||||
{
|
{
|
||||||
if (fluid_log_initialized == 0) {
|
if (fluid_log_initialized == 0) {
|
||||||
@@ -135,37 +141,41 @@ fluid_log_config(void)
|
|||||||
if (fluid_log_function[FLUID_PANIC] == NULL) {
|
if (fluid_log_function[FLUID_PANIC] == NULL) {
|
||||||
fluid_set_log_function(FLUID_PANIC, fluid_default_log_function, NULL);
|
fluid_set_log_function(FLUID_PANIC, fluid_default_log_function, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fluid_log_function[FLUID_ERR] == NULL) {
|
if (fluid_log_function[FLUID_ERR] == NULL) {
|
||||||
fluid_set_log_function(FLUID_ERR, fluid_default_log_function, NULL);
|
fluid_set_log_function(FLUID_ERR, fluid_default_log_function, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fluid_log_function[FLUID_WARN] == NULL) {
|
if (fluid_log_function[FLUID_WARN] == NULL) {
|
||||||
fluid_set_log_function(FLUID_WARN, fluid_default_log_function, NULL);
|
fluid_set_log_function(FLUID_WARN, fluid_default_log_function, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fluid_log_function[FLUID_INFO] == NULL) {
|
if (fluid_log_function[FLUID_INFO] == NULL) {
|
||||||
fluid_set_log_function(FLUID_INFO, fluid_default_log_function, NULL);
|
fluid_set_log_function(FLUID_INFO, fluid_default_log_function, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fluid_log_function[FLUID_DBG] == NULL) {
|
if (fluid_log_function[FLUID_DBG] == NULL) {
|
||||||
fluid_set_log_function(FLUID_DBG, fluid_default_log_function, NULL);
|
fluid_set_log_function(FLUID_DBG, fluid_default_log_function, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* fluid_log
|
* Print a message to the log.
|
||||||
|
* @param level Log level (#fluid_log_level).
|
||||||
|
* @param fmt Printf style format string for log message
|
||||||
|
* @param ... Arguments for printf 'fmt' message string
|
||||||
|
* @return Always returns -1
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
fluid_log(int level, char* fmt, ...)
|
fluid_log(int level, char* fmt, ...)
|
||||||
{
|
{
|
||||||
fluid_log_function_t fun = NULL;
|
fluid_log_function_t fun = NULL;
|
||||||
|
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start (args, fmt);
|
va_start (args, fmt);
|
||||||
vsnprintf(fluid_errbuf, sizeof (fluid_errbuf), fmt, args);
|
vsnprintf(fluid_errbuf, sizeof (fluid_errbuf), fmt, args);
|
||||||
va_end (args);
|
va_end (args);
|
||||||
|
|
||||||
if ((level >= 0) && (level < LAST_LOG_LEVEL)) {
|
if ((level >= 0) && (level < LAST_LOG_LEVEL)) {
|
||||||
fun = fluid_log_function[level];
|
fun = fluid_log_function[level];
|
||||||
@@ -173,14 +183,83 @@ fluid_log(int level, char* fmt, ...)
|
|||||||
(*fun)(level, fluid_errbuf, fluid_log_user_data[level]);
|
(*fun)(level, fluid_errbuf, fluid_log_user_data[level]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return FLUID_FAILED;
|
return FLUID_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An improved strtok, still trashes the input string, but is portable and
|
||||||
|
* thread safe. Also skips token chars at beginning of token string and never
|
||||||
|
* returns an empty token (will return NULL if source ends in token chars though).
|
||||||
|
* NOTE: NOT part of public API
|
||||||
|
* @internal
|
||||||
|
* @param str Pointer to a string pointer of source to tokenize. Pointer gets
|
||||||
|
* updated on each invocation to point to beginning of next token. Note that
|
||||||
|
* token char get's overwritten with a 0 byte. String pointer is set to NULL
|
||||||
|
* when final token is returned.
|
||||||
|
* @param delim String of delimiter chars.
|
||||||
|
* @return Pointer to the next token or NULL if no more tokens.
|
||||||
|
*/
|
||||||
|
char *fluid_strtok (char **str, char *delim)
|
||||||
|
{
|
||||||
|
char *s, *d, *token;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
if (str == NULL || delim == NULL || !*delim)
|
||||||
|
{
|
||||||
|
FLUID_LOG(FLUID_ERR, "Null pointer");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
s = *str;
|
||||||
|
if (!s) return NULL; /* str points to a NULL pointer? (tokenize already ended) */
|
||||||
|
|
||||||
|
/* skip delimiter chars at beginning of token */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
c = *s;
|
||||||
|
if (!c) /* end of source string? */
|
||||||
|
{
|
||||||
|
*str = NULL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (d = delim; *d; d++) /* is source char a token char? */
|
||||||
|
{
|
||||||
|
if (c == *d) /* token char match? */
|
||||||
|
{
|
||||||
|
s++; /* advance to next source char */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (*d); /* while token char match */
|
||||||
|
|
||||||
|
token = s; /* start of token found */
|
||||||
|
|
||||||
|
/* search for next token char or end of source string */
|
||||||
|
for (s = s+1; *s; s++)
|
||||||
|
{
|
||||||
|
c = *s;
|
||||||
|
|
||||||
|
for (d = delim; *d; d++) /* is source char a token char? */
|
||||||
|
{
|
||||||
|
if (c == *d) /* token char match? */
|
||||||
|
{
|
||||||
|
*s = '\0'; /* overwrite token char with zero byte to terminate token */
|
||||||
|
*str = s+1; /* update str to point to beginning of next token */
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we get here only if source string ended */
|
||||||
|
*str = NULL;
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* fluid_error
|
* fluid_error
|
||||||
*/
|
*/
|
||||||
char*
|
char*
|
||||||
fluid_error()
|
fluid_error()
|
||||||
{
|
{
|
||||||
return fluid_errbuf;
|
return fluid_errbuf;
|
||||||
@@ -188,9 +267,9 @@ fluid_error()
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* fluid_is_midifile
|
* fluid_is_midifile
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
fluid_is_midifile(char* filename)
|
fluid_is_midifile(char* filename)
|
||||||
{
|
{
|
||||||
@@ -205,14 +284,14 @@ fluid_is_midifile(char* filename)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
return strncmp(id, "MThd", 4) == 0;
|
return strncmp(id, "MThd", 4) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* fluid_is_soundfont
|
* fluid_is_soundfont
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
fluid_is_soundfont(char* filename)
|
fluid_is_soundfont(char* filename)
|
||||||
{
|
{
|
||||||
@@ -227,7 +306,7 @@ fluid_is_soundfont(char* filename)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
return strncmp(id, "RIFF", 4) == 0;
|
return strncmp(id, "RIFF", 4) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,7 +324,7 @@ fluid_is_soundfont(char* filename)
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct _fluid_timer_t
|
struct _fluid_timer_t
|
||||||
{
|
{
|
||||||
long msec;
|
long msec;
|
||||||
fluid_timer_callback_t callback;
|
fluid_timer_callback_t callback;
|
||||||
@@ -259,13 +338,13 @@ struct _fluid_timer_t
|
|||||||
static int fluid_timer_count = 0;
|
static int fluid_timer_count = 0;
|
||||||
DWORD WINAPI fluid_timer_run(LPVOID data);
|
DWORD WINAPI fluid_timer_run(LPVOID data);
|
||||||
|
|
||||||
fluid_timer_t*
|
fluid_timer_t*
|
||||||
new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data,
|
new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data,
|
||||||
int new_thread, int auto_destroy)
|
int new_thread, int auto_destroy)
|
||||||
{
|
{
|
||||||
fluid_timer_t* timer = FLUID_NEW(fluid_timer_t);
|
fluid_timer_t* timer = FLUID_NEW(fluid_timer_t);
|
||||||
if (timer == NULL) {
|
if (timer == NULL) {
|
||||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,18 +358,18 @@ new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data,
|
|||||||
if (new_thread) {
|
if (new_thread) {
|
||||||
timer->thread = CreateThread(NULL, 0, fluid_timer_run, (LPVOID) timer, 0, &timer->thread_id);
|
timer->thread = CreateThread(NULL, 0, fluid_timer_run, (LPVOID) timer, 0, &timer->thread_id);
|
||||||
if (timer->thread == NULL) {
|
if (timer->thread == NULL) {
|
||||||
FLUID_LOG(FLUID_ERR, "Couldn't create timer thread");
|
FLUID_LOG(FLUID_ERR, "Couldn't create timer thread");
|
||||||
FLUID_FREE(timer);
|
FLUID_FREE(timer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
SetThreadPriority(timer->thread, THREAD_PRIORITY_TIME_CRITICAL);
|
SetThreadPriority(timer->thread, THREAD_PRIORITY_TIME_CRITICAL);
|
||||||
} else {
|
} else {
|
||||||
fluid_timer_run((LPVOID) timer);
|
fluid_timer_run((LPVOID) timer);
|
||||||
}
|
}
|
||||||
return timer;
|
return timer;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD WINAPI
|
DWORD WINAPI
|
||||||
fluid_timer_run(LPVOID data)
|
fluid_timer_run(LPVOID data)
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@@ -337,16 +416,16 @@ fluid_timer_run(LPVOID data)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
delete_fluid_timer(fluid_timer_t* timer)
|
delete_fluid_timer(fluid_timer_t* timer)
|
||||||
{
|
{
|
||||||
timer->cont = 0;
|
timer->cont = 0;
|
||||||
fluid_timer_join(timer);
|
fluid_timer_join(timer);
|
||||||
FLUID_FREE(timer);
|
FLUID_FREE(timer);
|
||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
fluid_timer_join(fluid_timer_t* timer)
|
fluid_timer_join(fluid_timer_t* timer)
|
||||||
{
|
{
|
||||||
DWORD wait_result;
|
DWORD wait_result;
|
||||||
@@ -371,7 +450,7 @@ static double fluid_cpu_frequency = -1.0;
|
|||||||
void fluid_time_config(void)
|
void fluid_time_config(void)
|
||||||
{
|
{
|
||||||
if (fluid_cpu_frequency < 0.0) {
|
if (fluid_cpu_frequency < 0.0) {
|
||||||
fluid_cpu_frequency = fluid_estimate_cpu_frequency() / 1000000.0;
|
fluid_cpu_frequency = fluid_estimate_cpu_frequency() / 1000000.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -422,7 +501,7 @@ double fluid_estimate_cpu_frequency(void)
|
|||||||
QueryPerformanceCounter(&start);
|
QueryPerformanceCounter(&start);
|
||||||
|
|
||||||
Sleep(1000);
|
Sleep(1000);
|
||||||
|
|
||||||
after = fluid_curtime();
|
after = fluid_curtime();
|
||||||
QueryPerformanceCounter(&stop);
|
QueryPerformanceCounter(&stop);
|
||||||
|
|
||||||
@@ -445,7 +524,7 @@ double fluid_estimate_cpu_frequency(void)
|
|||||||
* Timer
|
* Timer
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct _fluid_timer_t
|
struct _fluid_timer_t
|
||||||
{
|
{
|
||||||
TMTask myTmTask;
|
TMTask myTmTask;
|
||||||
long msec;
|
long msec;
|
||||||
@@ -472,13 +551,13 @@ _timerCallback(fluid_timer_t *timer)
|
|||||||
timer->count++;
|
timer->count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
fluid_timer_t*
|
fluid_timer_t*
|
||||||
new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data,
|
new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data,
|
||||||
int new_thread, int auto_destroy)
|
int new_thread, int auto_destroy)
|
||||||
{
|
{
|
||||||
fluid_timer_t* timer = FLUID_NEW(fluid_timer_t);
|
fluid_timer_t* timer = FLUID_NEW(fluid_timer_t);
|
||||||
if (timer == NULL) {
|
if (timer == NULL) {
|
||||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -501,14 +580,14 @@ new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data,
|
|||||||
timer->isInstalled = 1;
|
timer->isInstalled = 1;
|
||||||
timer->count = 0;
|
timer->count = 0;
|
||||||
timer->auto_destroy = auto_destroy;
|
timer->auto_destroy = auto_destroy;
|
||||||
|
|
||||||
InsXTime((QElemPtr)timer);
|
InsXTime((QElemPtr)timer);
|
||||||
PrimeTime((QElemPtr)timer, msec);
|
PrimeTime((QElemPtr)timer, msec);
|
||||||
|
|
||||||
return timer;
|
return timer;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
delete_fluid_timer(fluid_timer_t* timer)
|
delete_fluid_timer(fluid_timer_t* timer)
|
||||||
{
|
{
|
||||||
if (timer->isInstalled) {
|
if (timer->isInstalled) {
|
||||||
@@ -518,7 +597,7 @@ delete_fluid_timer(fluid_timer_t* timer)
|
|||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
fluid_timer_join(fluid_timer_t* timer)
|
fluid_timer_join(fluid_timer_t* timer)
|
||||||
{
|
{
|
||||||
if (timer->isInstalled) {
|
if (timer->isInstalled) {
|
||||||
@@ -545,16 +624,17 @@ unsigned int fluid_curtime()
|
|||||||
UnsignedWide uS;
|
UnsignedWide uS;
|
||||||
double mSf;
|
double mSf;
|
||||||
unsigned int ms;
|
unsigned int ms;
|
||||||
|
|
||||||
Microseconds(&uS);
|
Microseconds(&uS);
|
||||||
|
|
||||||
mSf = ((((double) uS.hi) * kTwoPower32) + uS.lo)/1000.0f;
|
mSf = ((((double) uS.hi) * kTwoPower32) + uS.lo)/1000.0f;
|
||||||
|
|
||||||
ms = mSf;
|
ms = mSf;
|
||||||
|
|
||||||
return (ms);
|
return (ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#elif __BEOS__
|
#elif __BEOS__
|
||||||
|
|
||||||
struct _fluid_timer_t
|
struct _fluid_timer_t
|
||||||
@@ -660,8 +740,8 @@ double fluid_utime(void)
|
|||||||
*
|
*
|
||||||
* Timer
|
* Timer
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct _fluid_timer_t
|
struct _fluid_timer_t
|
||||||
{
|
{
|
||||||
long msec;
|
long msec;
|
||||||
fluid_timer_callback_t callback;
|
fluid_timer_callback_t callback;
|
||||||
@@ -671,7 +751,7 @@ struct _fluid_timer_t
|
|||||||
int auto_destroy;
|
int auto_destroy;
|
||||||
};
|
};
|
||||||
|
|
||||||
void*
|
void*
|
||||||
fluid_timer_start(void *data)
|
fluid_timer_start(void *data)
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@@ -714,8 +794,8 @@ fluid_timer_start(void *data)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
fluid_timer_t*
|
fluid_timer_t*
|
||||||
new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data,
|
new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data,
|
||||||
int new_thread, int auto_destroy)
|
int new_thread, int auto_destroy)
|
||||||
{
|
{
|
||||||
pthread_attr_t *attr = NULL;
|
pthread_attr_t *attr = NULL;
|
||||||
@@ -726,7 +806,7 @@ new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data,
|
|||||||
|
|
||||||
fluid_timer_t* timer = FLUID_NEW(fluid_timer_t);
|
fluid_timer_t* timer = FLUID_NEW(fluid_timer_t);
|
||||||
if (timer == NULL) {
|
if (timer == NULL) {
|
||||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
timer->msec = msec;
|
timer->msec = msec;
|
||||||
@@ -736,7 +816,7 @@ new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data,
|
|||||||
timer->thread = 0;
|
timer->thread = 0;
|
||||||
timer->auto_destroy = auto_destroy;
|
timer->auto_destroy = auto_destroy;
|
||||||
|
|
||||||
err = pthread_attr_init(&rt_attr);
|
err = pthread_attr_init(&rt_attr);
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
err = pthread_attr_setschedpolicy(&rt_attr, SCHED_FIFO);
|
err = pthread_attr_setschedpolicy(&rt_attr, SCHED_FIFO);
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
@@ -744,14 +824,14 @@ new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data,
|
|||||||
err = pthread_attr_setschedparam(&rt_attr, &priority);
|
err = pthread_attr_setschedparam(&rt_attr, &priority);
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
attr = &rt_attr;
|
attr = &rt_attr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_thread) {
|
if (new_thread) {
|
||||||
err = pthread_create(&timer->thread, attr, fluid_timer_start, (void*) timer);
|
err = pthread_create(&timer->thread, attr, fluid_timer_start, (void*) timer);
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
FLUID_LOG(FLUID_DBG, "The timer thread was created with real-time priority");
|
FLUID_LOG(FLUID_DBG, "The timer thread was created with real-time priority");
|
||||||
} else {
|
} else {
|
||||||
/* Create the thread with default attributes */
|
/* Create the thread with default attributes */
|
||||||
err = pthread_create(&timer->thread, NULL, fluid_timer_start, (void*) timer);
|
err = pthread_create(&timer->thread, NULL, fluid_timer_start, (void*) timer);
|
||||||
@@ -769,7 +849,7 @@ new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data,
|
|||||||
return timer;
|
return timer;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
delete_fluid_timer(fluid_timer_t* timer)
|
delete_fluid_timer(fluid_timer_t* timer)
|
||||||
{
|
{
|
||||||
timer->cont = 0;
|
timer->cont = 0;
|
||||||
@@ -779,7 +859,7 @@ delete_fluid_timer(fluid_timer_t* timer)
|
|||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
fluid_timer_join(fluid_timer_t* timer)
|
fluid_timer_join(fluid_timer_t* timer)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
@@ -805,7 +885,8 @@ double fluid_estimate_cpu_frequency(void);
|
|||||||
void fluid_time_config(void)
|
void fluid_time_config(void)
|
||||||
{
|
{
|
||||||
if (fluid_cpu_frequency < 0.0) {
|
if (fluid_cpu_frequency < 0.0) {
|
||||||
fluid_cpu_frequency = fluid_estimate_cpu_frequency() / 1000000.0;
|
fluid_cpu_frequency = fluid_estimate_cpu_frequency() / 1000000.0;
|
||||||
|
if (fluid_cpu_frequency == 0.0) fluid_cpu_frequency = 1.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -849,11 +930,11 @@ double fluid_estimate_cpu_frequency(void)
|
|||||||
unsigned int a0, b0, a1, b1;
|
unsigned int a0, b0, a1, b1;
|
||||||
unsigned int before, after;
|
unsigned int before, after;
|
||||||
|
|
||||||
before = fluid_curtime();
|
before = fluid_curtime();
|
||||||
__asm__ ("rdtsc" : "=a" (a0), "=d" (b0));
|
__asm__ ("rdtsc" : "=a" (a0), "=d" (b0));
|
||||||
|
|
||||||
sleep(1);
|
sleep(1);
|
||||||
|
|
||||||
after = fluid_curtime();
|
after = fluid_curtime();
|
||||||
__asm__ ("rdtsc" : "=a" (a1), "=d" (b1));
|
__asm__ ("rdtsc" : "=a" (a1), "=d" (b1));
|
||||||
|
|
||||||
@@ -866,7 +947,7 @@ double fluid_estimate_cpu_frequency(void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
#ifdef FPE_CHECK
|
||||||
|
|
||||||
/***************************************************************
|
/***************************************************************
|
||||||
*
|
*
|
||||||
@@ -875,7 +956,7 @@ double fluid_estimate_cpu_frequency(void)
|
|||||||
* The floating point exception functions were taken from Ircam's
|
* The floating point exception functions were taken from Ircam's
|
||||||
* jMax source code. http://www.ircam.fr/jmax
|
* jMax source code. http://www.ircam.fr/jmax
|
||||||
*
|
*
|
||||||
* FIXME: check in config for i386 machine
|
* FIXME: check in config for i386 machine
|
||||||
*
|
*
|
||||||
* Currently not used. I leave the code here in case we want to pick
|
* Currently not used. I leave the code here in case we want to pick
|
||||||
* this up again some time later.
|
* this up again some time later.
|
||||||
@@ -900,7 +981,8 @@ double fluid_estimate_cpu_frequency(void)
|
|||||||
#define _FPU_CLR_SW() __asm__ ("fnclex" : : )
|
#define _FPU_CLR_SW() __asm__ ("fnclex" : : )
|
||||||
|
|
||||||
/* Purpose:
|
/* Purpose:
|
||||||
* Checks, if the floating point unit has produced an exception in the meantime.
|
* Checks, if the floating point unit has produced an exception, print a message
|
||||||
|
* if so and clear the exception.
|
||||||
*/
|
*/
|
||||||
unsigned int fluid_check_fpe_i386(char* explanation)
|
unsigned int fluid_check_fpe_i386(char* explanation)
|
||||||
{
|
{
|
||||||
@@ -909,11 +991,10 @@ unsigned int fluid_check_fpe_i386(char* explanation)
|
|||||||
_FPU_GET_SW(s);
|
_FPU_GET_SW(s);
|
||||||
_FPU_CLR_SW();
|
_FPU_CLR_SW();
|
||||||
|
|
||||||
if ((s & _FPU_STATUS_IE)
|
s &= _FPU_STATUS_IE | _FPU_STATUS_DE | _FPU_STATUS_ZE | _FPU_STATUS_OE | _FPU_STATUS_UE;
|
||||||
|| (s & _FPU_STATUS_DE)
|
|
||||||
|| (s & _FPU_STATUS_ZE)
|
if (s)
|
||||||
|| (s & _FPU_STATUS_OE)
|
{
|
||||||
|| (s & _FPU_STATUS_UE)) {
|
|
||||||
FLUID_LOG(FLUID_WARN, "FPE exception (before or in %s): %s%s%s%s%s", explanation,
|
FLUID_LOG(FLUID_WARN, "FPE exception (before or in %s): %s%s%s%s%s", explanation,
|
||||||
(s & _FPU_STATUS_IE) ? "Invalid operation " : "",
|
(s & _FPU_STATUS_IE) ? "Invalid operation " : "",
|
||||||
(s & _FPU_STATUS_DE) ? "Denormal number " : "",
|
(s & _FPU_STATUS_DE) ? "Denormal number " : "",
|
||||||
@@ -921,14 +1002,22 @@ unsigned int fluid_check_fpe_i386(char* explanation)
|
|||||||
(s & _FPU_STATUS_OE) ? "Overflow " : "",
|
(s & _FPU_STATUS_OE) ? "Overflow " : "",
|
||||||
(s & _FPU_STATUS_UE) ? "Underflow " : "");
|
(s & _FPU_STATUS_UE) ? "Underflow " : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
/* Purpose:
|
||||||
|
* Clear floating point exception.
|
||||||
|
*/
|
||||||
|
void fluid_clear_fpe_i386 (void)
|
||||||
|
{
|
||||||
|
_FPU_CLR_SW();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ifdef FPE_CHECK
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif // #else (its POSIX)
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************
|
/***************************************************************
|
||||||
@@ -939,7 +1028,7 @@ unsigned int fluid_check_fpe_i386(char* explanation)
|
|||||||
|
|
||||||
#if WITH_PROFILING
|
#if WITH_PROFILING
|
||||||
|
|
||||||
fluid_profile_data_t fluid_profile_data[] =
|
fluid_profile_data_t fluid_profile_data[] =
|
||||||
{
|
{
|
||||||
{ FLUID_PROF_WRITE_S16, "fluid_synth_write_s16 ", 1e10, 0.0, 0.0, 0},
|
{ FLUID_PROF_WRITE_S16, "fluid_synth_write_s16 ", 1e10, 0.0, 0.0, 0},
|
||||||
{ FLUID_PROF_ONE_BLOCK, "fluid_synth_one_block ", 1e10, 0.0, 0.0, 0},
|
{ FLUID_PROF_ONE_BLOCK, "fluid_synth_one_block ", 1e10, 0.0, 0.0, 0},
|
||||||
@@ -950,7 +1039,7 @@ fluid_profile_data_t fluid_profile_data[] =
|
|||||||
{ FLUID_PROF_ONE_BLOCK_CHORUS, "fluid_synth_one_block:chorus ", 1e10, 0.0, 0.0, 0},
|
{ FLUID_PROF_ONE_BLOCK_CHORUS, "fluid_synth_one_block:chorus ", 1e10, 0.0, 0.0, 0},
|
||||||
{ FLUID_PROF_VOICE_NOTE, "fluid_voice:note ", 1e10, 0.0, 0.0, 0},
|
{ FLUID_PROF_VOICE_NOTE, "fluid_voice:note ", 1e10, 0.0, 0.0, 0},
|
||||||
{ FLUID_PROF_VOICE_RELEASE, "fluid_voice:release ", 1e10, 0.0, 0.0, 0},
|
{ FLUID_PROF_VOICE_RELEASE, "fluid_voice:release ", 1e10, 0.0, 0.0, 0},
|
||||||
{ FLUID_PROF_LAST, "last", 1e100, 0.0, 0.0, 0}
|
{ FLUID_PROF_LAST, "last", 1e100, 0.0, 0.0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -959,16 +1048,16 @@ void fluid_profiling_print(void)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
printf("fluid_profiling_print\n");
|
printf("fluid_profiling_print\n");
|
||||||
|
|
||||||
FLUID_LOG(FLUID_INFO, "Estimated CPU frequency: %.0f MHz", fluid_cpu_frequency);
|
FLUID_LOG(FLUID_INFO, "Estimated CPU frequency: %.0f MHz", fluid_cpu_frequency);
|
||||||
FLUID_LOG(FLUID_INFO, "Estimated times: min/avg/max (micro seconds)");
|
FLUID_LOG(FLUID_INFO, "Estimated times: min/avg/max (micro seconds)");
|
||||||
|
|
||||||
for (i = 0; i < FLUID_PROF_LAST; i++) {
|
for (i = 0; i < FLUID_PROF_LAST; i++) {
|
||||||
if (fluid_profile_data[i].count > 0) {
|
if (fluid_profile_data[i].count > 0) {
|
||||||
FLUID_LOG(FLUID_INFO, "%s: %.3f/%.3f/%.3f",
|
FLUID_LOG(FLUID_INFO, "%s: %.3f/%.3f/%.3f",
|
||||||
fluid_profile_data[i].description,
|
fluid_profile_data[i].description,
|
||||||
fluid_profile_data[i].min,
|
fluid_profile_data[i].min,
|
||||||
fluid_profile_data[i].total / fluid_profile_data[i].count,
|
fluid_profile_data[i].total / fluid_profile_data[i].count,
|
||||||
fluid_profile_data[i].max);
|
fluid_profile_data[i].max);
|
||||||
} else {
|
} else {
|
||||||
FLUID_LOG(FLUID_DBG, "%s: no profiling available", fluid_profile_data[i].description);
|
FLUID_LOG(FLUID_DBG, "%s: no profiling available", fluid_profile_data[i].description);
|
||||||
@@ -1010,7 +1099,7 @@ static DWORD WINAPI fluid_thread_start(LPVOID data)
|
|||||||
thread->func(thread->data);
|
thread->func(thread->data);
|
||||||
|
|
||||||
if (thread->detached) {
|
if (thread->detached) {
|
||||||
FLUID_FREE(thread);
|
FLUID_FREE(thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1022,13 +1111,13 @@ fluid_thread_t* new_fluid_thread(fluid_thread_func_t func, void* data, int detac
|
|||||||
fluid_thread_t* thread;
|
fluid_thread_t* thread;
|
||||||
|
|
||||||
if (func == NULL) {
|
if (func == NULL) {
|
||||||
FLUID_LOG(FLUID_ERR, "Invalid thread function");
|
FLUID_LOG(FLUID_ERR, "Invalid thread function");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
thread = FLUID_NEW(fluid_thread_t);
|
thread = FLUID_NEW(fluid_thread_t);
|
||||||
if (thread == NULL) {
|
if (thread == NULL) {
|
||||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1036,21 +1125,21 @@ fluid_thread_t* new_fluid_thread(fluid_thread_func_t func, void* data, int detac
|
|||||||
thread->func = func;
|
thread->func = func;
|
||||||
thread->detached = detach;
|
thread->detached = detach;
|
||||||
|
|
||||||
thread->thread = CreateThread(NULL, 0, fluid_thread_start, (LPVOID) thread,
|
thread->thread = CreateThread(NULL, 0, fluid_thread_start, (LPVOID) thread,
|
||||||
0, &thread->thread_id);
|
0, &thread->thread_id);
|
||||||
if (thread->thread == NULL) {
|
if (thread->thread == NULL) {
|
||||||
FLUID_LOG(FLUID_ERR, "Couldn't create the thread");
|
FLUID_LOG(FLUID_ERR, "Couldn't create the thread");
|
||||||
FLUID_FREE(thread);
|
FLUID_FREE(thread);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
int delete_fluid_thread(fluid_thread_t* thread)
|
int delete_fluid_thread(fluid_thread_t* thread)
|
||||||
{
|
{
|
||||||
FLUID_FREE(thread);
|
FLUID_FREE(thread);
|
||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1087,7 +1176,7 @@ static void* fluid_thread_start(void *data)
|
|||||||
thread->func(thread->data);
|
thread->func(thread->data);
|
||||||
|
|
||||||
if (thread->detached) {
|
if (thread->detached) {
|
||||||
FLUID_FREE(thread);
|
FLUID_FREE(thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1099,13 +1188,13 @@ fluid_thread_t* new_fluid_thread(fluid_thread_func_t func, void* data, int detac
|
|||||||
pthread_attr_t attr;
|
pthread_attr_t attr;
|
||||||
|
|
||||||
if (func == NULL) {
|
if (func == NULL) {
|
||||||
FLUID_LOG(FLUID_ERR, "Invalid thread function");
|
FLUID_LOG(FLUID_ERR, "Invalid thread function");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
thread = FLUID_NEW(fluid_thread_t);
|
thread = FLUID_NEW(fluid_thread_t);
|
||||||
if (thread == NULL) {
|
if (thread == NULL) {
|
||||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1124,14 +1213,14 @@ fluid_thread_t* new_fluid_thread(fluid_thread_func_t func, void* data, int detac
|
|||||||
FLUID_FREE(thread);
|
FLUID_FREE(thread);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
int delete_fluid_thread(fluid_thread_t* thread)
|
int delete_fluid_thread(fluid_thread_t* thread)
|
||||||
{
|
{
|
||||||
FLUID_FREE(thread);
|
FLUID_FREE(thread);
|
||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fluid_thread_join(fluid_thread_t* thread)
|
int fluid_thread_join(fluid_thread_t* thread)
|
||||||
@@ -1235,7 +1324,7 @@ static void fluid_server_socket_run(void* data)
|
|||||||
while (server_socket->cont) {
|
while (server_socket->cont) {
|
||||||
|
|
||||||
client_socket = accept(server_socket->socket, (struct sockaddr*) &addr, &addrlen);
|
client_socket = accept(server_socket->socket, (struct sockaddr*) &addr, &addrlen);
|
||||||
|
|
||||||
FLUID_LOG(FLUID_DBG, "New client connection");
|
FLUID_LOG(FLUID_DBG, "New client connection");
|
||||||
|
|
||||||
if (client_socket == INVALID_SOCKET) {
|
if (client_socket == INVALID_SOCKET) {
|
||||||
@@ -1250,13 +1339,13 @@ static void fluid_server_socket_run(void* data)
|
|||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
fluid_socket_close(client_socket);
|
fluid_socket_close(client_socket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FLUID_LOG(FLUID_DBG, "Server closing");
|
FLUID_LOG(FLUID_DBG, "Server closing");
|
||||||
}
|
}
|
||||||
|
|
||||||
fluid_server_socket_t*
|
fluid_server_socket_t*
|
||||||
new_fluid_server_socket(int port, fluid_server_func_t func, void* data)
|
new_fluid_server_socket(int port, fluid_server_func_t func, void* data)
|
||||||
{
|
{
|
||||||
fluid_server_socket_t* server_socket;
|
fluid_server_socket_t* server_socket;
|
||||||
@@ -1293,7 +1382,7 @@ new_fluid_server_socket(int port, fluid_server_func_t func, void* data)
|
|||||||
|
|
||||||
server_socket = FLUID_NEW(fluid_server_socket_t);
|
server_socket = FLUID_NEW(fluid_server_socket_t);
|
||||||
if (server_socket == NULL) {
|
if (server_socket == NULL) {
|
||||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||||
fluid_socket_close(sock);
|
fluid_socket_close(sock);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -43,8 +43,15 @@ void fluid_sys_config(void);
|
|||||||
void fluid_log_config(void);
|
void fluid_log_config(void);
|
||||||
void fluid_time_config(void);
|
void fluid_time_config(void);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Utility functions
|
||||||
|
*/
|
||||||
|
char *fluid_strtok (char **str, char *delim);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
||||||
Additional debugging system, separate from the log system. This
|
Additional debugging system, separate from the log system. This
|
||||||
allows to print selected debug messages of a specific subsystem.
|
allows to print selected debug messages of a specific subsystem.
|
||||||
|
|
||||||
@@ -61,7 +68,7 @@ enum fluid_debug_level {
|
|||||||
int fluid_debug(int level, char * fmt, ...);
|
int fluid_debug(int level, char * fmt, ...);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#define fluid_debug
|
#define fluid_debug
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -98,7 +105,7 @@ double fluid_utime(void);
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Timers
|
Timers
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@@ -109,25 +116,25 @@ typedef int (*fluid_timer_callback_t)(void* data, unsigned int msec);
|
|||||||
|
|
||||||
typedef struct _fluid_timer_t fluid_timer_t;
|
typedef struct _fluid_timer_t fluid_timer_t;
|
||||||
|
|
||||||
fluid_timer_t* new_fluid_timer(int msec, fluid_timer_callback_t callback,
|
fluid_timer_t* new_fluid_timer(int msec, fluid_timer_callback_t callback,
|
||||||
void* data, int new_thread, int auto_destroy);
|
void* data, int new_thread, int auto_destroy);
|
||||||
|
|
||||||
int delete_fluid_timer(fluid_timer_t* timer);
|
int delete_fluid_timer(fluid_timer_t* timer);
|
||||||
int fluid_timer_join(fluid_timer_t* timer);
|
int fluid_timer_join(fluid_timer_t* timer);
|
||||||
int fluid_timer_stop(fluid_timer_t* timer);
|
int fluid_timer_stop(fluid_timer_t* timer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
||||||
Muteces
|
Muteces
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(MACOS9)
|
#if defined(MACOS9)
|
||||||
typedef int fluid_mutex_t;
|
typedef int fluid_mutex_t;
|
||||||
#define fluid_mutex_init(_m) { (_m) = 0; }
|
#define fluid_mutex_init(_m) { (_m) = 0; }
|
||||||
#define fluid_mutex_destroy(_m)
|
#define fluid_mutex_destroy(_m)
|
||||||
#define fluid_mutex_lock(_m)
|
#define fluid_mutex_lock(_m)
|
||||||
#define fluid_mutex_unlock(_m)
|
#define fluid_mutex_unlock(_m)
|
||||||
|
|
||||||
#elif defined(WIN32)
|
#elif defined(WIN32)
|
||||||
typedef HANDLE fluid_mutex_t;
|
typedef HANDLE fluid_mutex_t;
|
||||||
@@ -140,7 +147,7 @@ typedef HANDLE fluid_mutex_t;
|
|||||||
#ifndef HAIKU_TARGET_PLATFORM_HAIKU
|
#ifndef HAIKU_TARGET_PLATFORM_HAIKU
|
||||||
typedef sem_id fluid_mutex_t;
|
typedef sem_id fluid_mutex_t;
|
||||||
#define fluid_mutex_init(_m) { (_m) = create_sem(1, "fs_sem"); }
|
#define fluid_mutex_init(_m) { (_m) = create_sem(1, "fs_sem"); }
|
||||||
#define fluid_mutex_destroy(_m) delete_sem(_m);
|
#define fluid_mutex_destroy(_m) delete_sem(_m);
|
||||||
#define fluid_mutex_lock(_m) acquire_sem(_m);
|
#define fluid_mutex_lock(_m) acquire_sem(_m);
|
||||||
#define fluid_mutex_unlock(_m) release_sem(_m);
|
#define fluid_mutex_unlock(_m) release_sem(_m);
|
||||||
|
|
||||||
@@ -153,6 +160,7 @@ typedef pthread_mutex_t fluid_mutex_t;
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Threads
|
Threads
|
||||||
|
|
||||||
@@ -199,13 +207,13 @@ fluid_ostream_t fluid_socket_get_ostream(fluid_socket_t sock);
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
||||||
Profiling
|
Profiling
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Profile numbers. List all the pieces of code you want to profile
|
Profile numbers. List all the pieces of code you want to profile
|
||||||
here. Be sure to add an entry in the fluid_profile_data table in
|
here. Be sure to add an entry in the fluid_profile_data table in
|
||||||
fluid_sys.c
|
fluid_sys.c
|
||||||
@@ -267,9 +275,9 @@ extern fluid_profile_data_t fluid_profile_data[];
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
||||||
Memory locking
|
Memory locking
|
||||||
|
|
||||||
Memory locking is used to avoid swapping of the large block of
|
Memory locking is used to avoid swapping of the large block of
|
||||||
sample data.
|
sample data.
|
||||||
@@ -280,26 +288,26 @@ extern fluid_profile_data_t fluid_profile_data[];
|
|||||||
#define fluid_munlock(_p,_n) munlock(_p,_n)
|
#define fluid_munlock(_p,_n) munlock(_p,_n)
|
||||||
#else
|
#else
|
||||||
#define fluid_mlock(_p,_n) 0
|
#define fluid_mlock(_p,_n) 0
|
||||||
#define fluid_munlock(_p,_n)
|
#define fluid_munlock(_p,_n)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
||||||
Floating point exceptions
|
Floating point exceptions
|
||||||
|
|
||||||
fluid_check_fpe() checks for "unnormalized numbers" and other
|
fluid_check_fpe() checks for "unnormalized numbers" and other
|
||||||
exceptions of the floating point processsor.
|
exceptions of the floating point processsor.
|
||||||
*/
|
*/
|
||||||
#if 0
|
#ifdef FPE_CHECK
|
||||||
/* Enable FPE exception check */
|
|
||||||
#define fluid_check_fpe(expl) fluid_check_fpe_i386(expl)
|
#define fluid_check_fpe(expl) fluid_check_fpe_i386(expl)
|
||||||
|
#define fluid_clear_fpe() fluid_clear_fpe_i386()
|
||||||
#else
|
#else
|
||||||
/* Disable FPE exception check */
|
|
||||||
#define fluid_check_fpe(expl)
|
#define fluid_check_fpe(expl)
|
||||||
|
#define fluid_clear_fpe()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
unsigned int fluid_check_fpe_i386(char * explanation_in_case_of_fpe);
|
unsigned int fluid_check_fpe_i386(char * explanation_in_case_of_fpe);
|
||||||
|
void fluid_clear_fpe_i386(void);
|
||||||
|
|
||||||
#endif /* _FLUID_SYS_H */
|
#endif /* _FLUID_SYS_H */
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -38,7 +38,7 @@ fluid_tuning_t* new_fluid_tuning(char* name, int bank, int prog)
|
|||||||
|
|
||||||
if (name != NULL) {
|
if (name != NULL) {
|
||||||
tuning->name = FLUID_STRDUP(name);
|
tuning->name = FLUID_STRDUP(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
tuning->bank = bank;
|
tuning->bank = bank;
|
||||||
tuning->prog = prog;
|
tuning->prog = prog;
|
||||||
@@ -69,7 +69,7 @@ void fluid_tuning_set_name(fluid_tuning_t* tuning, char* name)
|
|||||||
}
|
}
|
||||||
if (name != NULL) {
|
if (name != NULL) {
|
||||||
tuning->name = FLUID_STRDUP(name);
|
tuning->name = FLUID_STRDUP(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char* fluid_tuning_get_name(fluid_tuning_t* tuning)
|
char* fluid_tuning_get_name(fluid_tuning_t* tuning)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -43,9 +43,9 @@ enum fluid_voice_status
|
|||||||
struct _fluid_env_data_t {
|
struct _fluid_env_data_t {
|
||||||
unsigned int count;
|
unsigned int count;
|
||||||
fluid_real_t coeff;
|
fluid_real_t coeff;
|
||||||
fluid_real_t incr;
|
fluid_real_t incr;
|
||||||
fluid_real_t min;
|
fluid_real_t min;
|
||||||
fluid_real_t max;
|
fluid_real_t max;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Indices for envelope tables */
|
/* Indices for envelope tables */
|
||||||
@@ -60,20 +60,12 @@ enum fluid_voice_envelope_index_t{
|
|||||||
FLUID_VOICE_ENVLAST
|
FLUID_VOICE_ENVLAST
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* interpolation data
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
fluid_real_t a0, a1, a2, a3;
|
|
||||||
/* signed int c0, c1, c2, c3; */
|
|
||||||
} fluid_interp_coeff_t;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* fluid_voice_t
|
* fluid_voice_t
|
||||||
*/
|
*/
|
||||||
struct _fluid_voice_t
|
struct _fluid_voice_t
|
||||||
{
|
{
|
||||||
unsigned int id; /* the id is incremented for every new noteon.
|
unsigned int id; /* the id is incremented for every new noteon.
|
||||||
it's used for noteoff's */
|
it's used for noteoff's */
|
||||||
unsigned char status;
|
unsigned char status;
|
||||||
unsigned char chan; /* the channel number, quick access for channel messages */
|
unsigned char chan; /* the channel number, quick access for channel messages */
|
||||||
@@ -85,7 +77,7 @@ struct _fluid_voice_t
|
|||||||
int mod_count;
|
int mod_count;
|
||||||
int has_looped; /* Flag that is set as soon as the first loop is completed. */
|
int has_looped; /* Flag that is set as soon as the first loop is completed. */
|
||||||
fluid_sample_t* sample;
|
fluid_sample_t* sample;
|
||||||
int check_sample_sanity_flag; /* Flag that initiates, that sample-related parameters
|
int check_sample_sanity_flag; /* Flag that initiates, that sample-related parameters
|
||||||
have to be checked. */
|
have to be checked. */
|
||||||
#if 0
|
#if 0
|
||||||
/* Instead of keeping a pointer to a fluid_sample_t structure,
|
/* Instead of keeping a pointer to a fluid_sample_t structure,
|
||||||
@@ -116,12 +108,16 @@ struct _fluid_voice_t
|
|||||||
unsigned int start_time;
|
unsigned int start_time;
|
||||||
unsigned int ticks;
|
unsigned int ticks;
|
||||||
|
|
||||||
fluid_real_t amp; /* the linear amplitude */
|
fluid_real_t amp; /* current linear amplitude */
|
||||||
fluid_phase_t phase; /* the phase of the sample wave */
|
fluid_phase_t phase; /* the phase of the sample wave */
|
||||||
|
|
||||||
#if 0
|
/* Temporary variables used in fluid_voice_write() */
|
||||||
fluid_real_t incr; /* the phase increment for the next 64 samples [NEW, PH] */
|
|
||||||
#endif
|
fluid_real_t phase_incr; /* the phase increment for the next 64 samples */
|
||||||
|
fluid_real_t amp_incr; /* amplitude increment value */
|
||||||
|
fluid_real_t *dsp_buf; /* buffer to store interpolated sample data to */
|
||||||
|
|
||||||
|
/* End temporary variables */
|
||||||
|
|
||||||
/* basic parameters */
|
/* basic parameters */
|
||||||
fluid_real_t pitch; /* the pitch in midicents */
|
fluid_real_t pitch; /* the pitch in midicents */
|
||||||
@@ -134,7 +130,7 @@ struct _fluid_voice_t
|
|||||||
int start;
|
int start;
|
||||||
int end;
|
int end;
|
||||||
int loopstart;
|
int loopstart;
|
||||||
int loopend;
|
int loopend; /* Note: first point following the loop (superimposed on loopstart) */
|
||||||
|
|
||||||
/* master gain */
|
/* master gain */
|
||||||
fluid_real_t synth_gain;
|
fluid_real_t synth_gain;
|
||||||
@@ -152,22 +148,22 @@ struct _fluid_voice_t
|
|||||||
unsigned int modenv_count;
|
unsigned int modenv_count;
|
||||||
int modenv_section;
|
int modenv_section;
|
||||||
fluid_real_t modenv_val; /* the value of the modulation envelope */
|
fluid_real_t modenv_val; /* the value of the modulation envelope */
|
||||||
fluid_real_t modenv_to_fc;
|
fluid_real_t modenv_to_fc;
|
||||||
fluid_real_t modenv_to_pitch;
|
fluid_real_t modenv_to_pitch;
|
||||||
|
|
||||||
/* mod lfo */
|
/* mod lfo */
|
||||||
fluid_real_t modlfo_val; /* the value of the modulation LFO */
|
fluid_real_t modlfo_val; /* the value of the modulation LFO */
|
||||||
unsigned int modlfo_delay; /* the delay of the lfo in samples */
|
unsigned int modlfo_delay; /* the delay of the lfo in samples */
|
||||||
fluid_real_t modlfo_incr; /* the lfo frequency is converted to a per-buffer increment */
|
fluid_real_t modlfo_incr; /* the lfo frequency is converted to a per-buffer increment */
|
||||||
fluid_real_t modlfo_to_fc;
|
fluid_real_t modlfo_to_fc;
|
||||||
fluid_real_t modlfo_to_pitch;
|
fluid_real_t modlfo_to_pitch;
|
||||||
fluid_real_t modlfo_to_vol;
|
fluid_real_t modlfo_to_vol;
|
||||||
|
|
||||||
/* vib lfo */
|
/* vib lfo */
|
||||||
fluid_real_t viblfo_val; /* the value of the vibrato LFO */
|
fluid_real_t viblfo_val; /* the value of the vibrato LFO */
|
||||||
unsigned int viblfo_delay; /* the delay of the lfo in samples */
|
unsigned int viblfo_delay; /* the delay of the lfo in samples */
|
||||||
fluid_real_t viblfo_incr; /* the lfo frequency is converted to a per-buffer increment */
|
fluid_real_t viblfo_incr; /* the lfo frequency is converted to a per-buffer increment */
|
||||||
fluid_real_t viblfo_to_pitch;
|
fluid_real_t viblfo_to_pitch;
|
||||||
|
|
||||||
/* resonant filter */
|
/* resonant filter */
|
||||||
fluid_real_t fres; /* the resonance frequency, in cents (not absolute cents) */
|
fluid_real_t fres; /* the resonance frequency, in cents (not absolute cents) */
|
||||||
@@ -177,7 +173,7 @@ struct _fluid_voice_t
|
|||||||
fluid_real_t q_lin; /* the q-factor on a linear scale */
|
fluid_real_t q_lin; /* the q-factor on a linear scale */
|
||||||
fluid_real_t filter_gain; /* Gain correction factor, depends on q */
|
fluid_real_t filter_gain; /* Gain correction factor, depends on q */
|
||||||
fluid_real_t hist1, hist2; /* Sample history for the IIR filter */
|
fluid_real_t hist1, hist2; /* Sample history for the IIR filter */
|
||||||
int filter_startup; /* Flag: If set, the filter will be set directly.
|
int filter_startup; /* Flag: If set, the filter will be set directly.
|
||||||
Else it changes smoothly. */
|
Else it changes smoothly. */
|
||||||
|
|
||||||
/* filter coefficients */
|
/* filter coefficients */
|
||||||
@@ -219,14 +215,14 @@ struct _fluid_voice_t
|
|||||||
fluid_voice_t* new_fluid_voice(fluid_real_t output_rate);
|
fluid_voice_t* new_fluid_voice(fluid_real_t output_rate);
|
||||||
int delete_fluid_voice(fluid_voice_t* voice);
|
int delete_fluid_voice(fluid_voice_t* voice);
|
||||||
|
|
||||||
void fluid_voice_start(fluid_voice_t* voice);
|
void fluid_voice_start(fluid_voice_t* voice);
|
||||||
|
|
||||||
int fluid_voice_write(fluid_voice_t* voice,
|
int fluid_voice_write(fluid_voice_t* voice,
|
||||||
fluid_real_t* left, fluid_real_t* right,
|
fluid_real_t* left, fluid_real_t* right,
|
||||||
fluid_real_t* reverb_buf, fluid_real_t* chorus_buf);
|
fluid_real_t* reverb_buf, fluid_real_t* chorus_buf);
|
||||||
|
|
||||||
int fluid_voice_init(fluid_voice_t* voice, fluid_sample_t* sample,
|
int fluid_voice_init(fluid_voice_t* voice, fluid_sample_t* sample,
|
||||||
fluid_channel_t* channel, int key, int vel,
|
fluid_channel_t* channel, int key, int vel,
|
||||||
unsigned int id, unsigned int time, fluid_real_t gain);
|
unsigned int id, unsigned int time, fluid_real_t gain);
|
||||||
|
|
||||||
int fluid_voice_modulate(fluid_voice_t* voice, int cc, int ctrl);
|
int fluid_voice_modulate(fluid_voice_t* voice, int cc, int ctrl);
|
||||||
@@ -250,7 +246,7 @@ int fluid_voice_noteoff(fluid_voice_t* voice);
|
|||||||
int fluid_voice_off(fluid_voice_t* voice);
|
int fluid_voice_off(fluid_voice_t* voice);
|
||||||
int fluid_voice_calculate_runtime_synthesis_parameters(fluid_voice_t* voice);
|
int fluid_voice_calculate_runtime_synthesis_parameters(fluid_voice_t* voice);
|
||||||
fluid_channel_t* fluid_voice_get_channel(fluid_voice_t* voice);
|
fluid_channel_t* fluid_voice_get_channel(fluid_voice_t* voice);
|
||||||
int calculate_hold_decay_buffers(fluid_voice_t* voice, int gen_base,
|
int calculate_hold_decay_buffers(fluid_voice_t* voice, int gen_base,
|
||||||
int gen_key2base, int is_decay);
|
int gen_key2base, int is_decay);
|
||||||
int fluid_voice_kill_excl(fluid_voice_t* voice);
|
int fluid_voice_kill_excl(fluid_voice_t* voice);
|
||||||
fluid_real_t fluid_voice_get_lower_boundary_for_attenuation(fluid_voice_t* voice);
|
fluid_real_t fluid_voice_get_lower_boundary_for_attenuation(fluid_voice_t* voice);
|
||||||
@@ -282,7 +278,14 @@ fluid_real_t fluid_voice_gen_value(fluid_voice_t* voice, int num);
|
|||||||
|
|
||||||
#define FLUID_SAMPLESANITY_CHECK (1 << 0)
|
#define FLUID_SAMPLESANITY_CHECK (1 << 0)
|
||||||
#define FLUID_SAMPLESANITY_STARTUP (1 << 1)
|
#define FLUID_SAMPLESANITY_STARTUP (1 << 1)
|
||||||
void fluid_voice_config(void);
|
|
||||||
|
|
||||||
|
|
||||||
|
/* defined in fluid_dsp_float.c */
|
||||||
|
|
||||||
|
void fluid_dsp_float_config (void);
|
||||||
|
int fluid_dsp_float_interpolate_none (fluid_voice_t *voice);
|
||||||
|
int fluid_dsp_float_interpolate_linear (fluid_voice_t *voice);
|
||||||
|
int fluid_dsp_float_interpolate_4th_order (fluid_voice_t *voice);
|
||||||
|
int fluid_dsp_float_interpolate_7th_order (fluid_voice_t *voice);
|
||||||
|
|
||||||
#endif /* _FLUID_VOICE_H */
|
#endif /* _FLUID_VOICE_H */
|
||||||
|
|||||||
@@ -11,14 +11,16 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
* 02111-1307, USA
|
* 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -37,10 +39,6 @@
|
|||||||
|
|
||||||
#include "fluidsynth.h"
|
#include "fluidsynth.h"
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(WIN32) && !defined(MINGW32)
|
#if defined(WIN32) && !defined(MINGW32)
|
||||||
#include "config_win32.h"
|
#include "config_win32.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -88,7 +86,7 @@ extern int optind, opterr, optopt;
|
|||||||
/* process_o_cmd_line_option
|
/* process_o_cmd_line_option
|
||||||
*
|
*
|
||||||
* Purpose:
|
* Purpose:
|
||||||
* Process a command line option -o setting=value,
|
* Process a command line option -o setting=value,
|
||||||
* for example: -o synth.polyhony=16
|
* for example: -o synth.polyhony=16
|
||||||
*/
|
*/
|
||||||
void process_o_cmd_line_option(fluid_settings_t* settings, char* optarg){
|
void process_o_cmd_line_option(fluid_settings_t* settings, char* optarg){
|
||||||
@@ -127,7 +125,7 @@ void process_o_cmd_line_option(fluid_settings_t* settings, char* optarg){
|
|||||||
default:
|
default:
|
||||||
fprintf (stderr, "Settings argument on command line: Failed to set \"%s\" to \"%s\".\n"
|
fprintf (stderr, "Settings argument on command line: Failed to set \"%s\" to \"%s\".\n"
|
||||||
"Most likely the parameter \"%s\" does not exist.\n", optarg, val, optarg);
|
"Most likely the parameter \"%s\" does not exist.\n", optarg, val, optarg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -180,7 +178,7 @@ settings_foreach_func (void *data, char *name, int type)
|
|||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_SIGNAL_H
|
#ifdef HAVE_SIGNAL_H
|
||||||
/*
|
/*
|
||||||
* handle_signal
|
* handle_signal
|
||||||
*/
|
*/
|
||||||
void handle_signal(int sig_num)
|
void handle_signal(int sig_num)
|
||||||
@@ -192,7 +190,7 @@ void handle_signal(int sig_num)
|
|||||||
/*
|
/*
|
||||||
* main
|
* main
|
||||||
*/
|
*/
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
fluid_settings_t* settings;
|
fluid_settings_t* settings;
|
||||||
int arg1 = 1;
|
int arg1 = 1;
|
||||||
@@ -200,7 +198,7 @@ int main(int argc, char** argv)
|
|||||||
int c, i, fragcount = DEFAULT_FRAG_COUNT;
|
int c, i, fragcount = DEFAULT_FRAG_COUNT;
|
||||||
int interactive = 1;
|
int interactive = 1;
|
||||||
int midi_in = 1;
|
int midi_in = 1;
|
||||||
fluid_player_t* player = NULL;
|
fluid_player_t* player = NULL;
|
||||||
fluid_midi_router_t* router = NULL;
|
fluid_midi_router_t* router = NULL;
|
||||||
fluid_midi_driver_t* mdriver = NULL;
|
fluid_midi_driver_t* mdriver = NULL;
|
||||||
fluid_audio_driver_t* adriver = NULL;
|
fluid_audio_driver_t* adriver = NULL;
|
||||||
@@ -354,7 +352,7 @@ int main(int argc, char** argv)
|
|||||||
case 'n':
|
case 'n':
|
||||||
midi_in = 0;
|
midi_in = 0;
|
||||||
break;
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
process_o_cmd_line_option(settings, optarg);
|
process_o_cmd_line_option(settings, optarg);
|
||||||
break;
|
break;
|
||||||
case 'R':
|
case 'R':
|
||||||
@@ -433,16 +431,16 @@ int main(int argc, char** argv)
|
|||||||
*/
|
*/
|
||||||
if ((audio_groups == 0) && (audio_channels != 0)) {
|
if ((audio_groups == 0) && (audio_channels != 0)) {
|
||||||
audio_groups = audio_channels;
|
audio_groups = audio_channels;
|
||||||
}
|
}
|
||||||
fluid_settings_setint(settings, "synth.audio-groups", audio_groups);
|
fluid_settings_setint(settings, "synth.audio-groups", audio_groups);
|
||||||
|
|
||||||
/* create the synthesizer */
|
/* create the synthesizer */
|
||||||
synth = new_fluid_synth(settings);
|
synth = new_fluid_synth(settings);
|
||||||
if (synth == NULL) {
|
if (synth == NULL) {
|
||||||
fprintf(stderr, "Failed to create the synthesizer\n");
|
fprintf(stderr, "Failed to create the synthesizer\n");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd_handler = new_fluid_cmd_handler(synth);
|
cmd_handler = new_fluid_cmd_handler(synth);
|
||||||
if (cmd_handler == NULL) {
|
if (cmd_handler == NULL) {
|
||||||
fprintf(stderr, "Failed to create the command handler\n");
|
fprintf(stderr, "Failed to create the command handler\n");
|
||||||
@@ -458,13 +456,16 @@ int main(int argc, char** argv)
|
|||||||
fluid_source(cmd_handler, buf);
|
fluid_source(cmd_handler, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* load the soundfonts */
|
/* load the soundfonts (check that all non options are SoundFont or MIDI files) */
|
||||||
for (i = arg1; i < argc; i++) {
|
for (i = arg1; i < argc; i++) {
|
||||||
if ((argv[i][0] != '-') && fluid_is_soundfont(argv[i])) {
|
if (fluid_is_soundfont(argv[i]))
|
||||||
if (fluid_synth_sfload(synth, argv[i], 1) == -1) {
|
{
|
||||||
|
if (fluid_synth_sfload(synth, argv[i], 1) == -1)
|
||||||
fprintf(stderr, "Failed to load the SoundFont %s\n", argv[i]);
|
fprintf(stderr, "Failed to load the SoundFont %s\n", argv[i]);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else if (!fluid_is_midifile(argv[i]))
|
||||||
|
fprintf (stderr, "Parameter '%s' not a SoundFont or MIDI file or error occurred identifying it.\n",
|
||||||
|
argv[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_SIGNAL_H
|
#ifdef HAVE_SIGNAL_H
|
||||||
@@ -487,10 +488,10 @@ int main(int argc, char** argv)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
router = new_fluid_midi_router(
|
router = new_fluid_midi_router(
|
||||||
settings,
|
settings,
|
||||||
dump ? fluid_midi_dump_postrouter : fluid_synth_handle_midi_event,
|
dump ? fluid_midi_dump_postrouter : fluid_synth_handle_midi_event,
|
||||||
(void*)synth);
|
(void*)synth);
|
||||||
|
|
||||||
if (router == NULL) {
|
if (router == NULL) {
|
||||||
fprintf(stderr, "Failed to create the MIDI input router; no MIDI input\n"
|
fprintf(stderr, "Failed to create the MIDI input router; no MIDI input\n"
|
||||||
"will be available. You can access the synthesizer \n"
|
"will be available. You can access the synthesizer \n"
|
||||||
@@ -498,7 +499,7 @@ int main(int argc, char** argv)
|
|||||||
} else {
|
} else {
|
||||||
fluid_synth_set_midi_router(synth, router); /* Fixme, needed for command handler */
|
fluid_synth_set_midi_router(synth, router); /* Fixme, needed for command handler */
|
||||||
mdriver = new_fluid_midi_driver(
|
mdriver = new_fluid_midi_driver(
|
||||||
settings,
|
settings,
|
||||||
dump ? fluid_midi_dump_prerouter : fluid_midi_router_handle_midi_event,
|
dump ? fluid_midi_dump_prerouter : fluid_midi_router_handle_midi_event,
|
||||||
(void*) router);
|
(void*) router);
|
||||||
if (mdriver == NULL) {
|
if (mdriver == NULL) {
|
||||||
@@ -561,7 +562,7 @@ int main(int argc, char** argv)
|
|||||||
* 0.
|
* 0.
|
||||||
*/
|
*/
|
||||||
fluid_settings_setstr(settings, "shell.prompt", dump ? "" : "> ");
|
fluid_settings_setstr(settings, "shell.prompt", dump ? "" : "> ");
|
||||||
fluid_usershell(settings, cmd_handler);
|
fluid_usershell(settings, cmd_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
@@ -584,7 +585,7 @@ int main(int argc, char** argv)
|
|||||||
/* if the user typed 'quit' in the shell, stop the player */
|
/* if the user typed 'quit' in the shell, stop the player */
|
||||||
if (interactive) {
|
if (interactive) {
|
||||||
fluid_player_stop(player);
|
fluid_player_stop(player);
|
||||||
}
|
}
|
||||||
fluid_player_join(player);
|
fluid_player_join(player);
|
||||||
delete_fluid_player(player);
|
delete_fluid_player(player);
|
||||||
}
|
}
|
||||||
@@ -623,8 +624,8 @@ static fluid_cmd_handler_t* newclient(void* data, char* addr)
|
|||||||
/*
|
/*
|
||||||
* print_usage
|
* print_usage
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
print_usage()
|
print_usage()
|
||||||
{
|
{
|
||||||
print_welcome ();
|
print_welcome ();
|
||||||
fprintf(stderr, "Usage: fluidsynth [options] [soundfonts]\n");
|
fprintf(stderr, "Usage: fluidsynth [options] [soundfonts]\n");
|
||||||
@@ -635,8 +636,8 @@ print_usage()
|
|||||||
/*
|
/*
|
||||||
* print_welcome
|
* print_welcome
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
print_welcome()
|
print_welcome()
|
||||||
{
|
{
|
||||||
printf("FluidSynth version %s\n"
|
printf("FluidSynth version %s\n"
|
||||||
"Copyright (C) 2000-2006 Peter Hanappe and others.\n"
|
"Copyright (C) 2000-2006 Peter Hanappe and others.\n"
|
||||||
@@ -648,8 +649,8 @@ print_welcome()
|
|||||||
/*
|
/*
|
||||||
* print_help
|
* print_help
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
print_help()
|
print_help()
|
||||||
{
|
{
|
||||||
print_welcome ();
|
print_welcome ();
|
||||||
printf("Usage: \n");
|
printf("Usage: \n");
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Library General Public License for more details.
|
* Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the Free
|
* License along with this library; if not, write to the Free
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
@@ -26,9 +26,9 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//#if defined(__POWERPC__) && !(defined(__APPLE__) && defined(__MACH__))
|
#if defined(__POWERPC__) && !(defined(__APPLE__) && defined(__MACH__))
|
||||||
//#include "config_maxmsp43.h"
|
#include "config_maxmsp43.h"
|
||||||
//#endif
|
#endif
|
||||||
|
|
||||||
#if defined(WIN32) && !defined(MINGW32)
|
#if defined(WIN32) && !defined(MINGW32)
|
||||||
#include "config_win32.h"
|
#include "config_win32.h"
|
||||||
@@ -229,7 +229,7 @@ typedef u_int64_t uint64;
|
|||||||
|
|
||||||
/***************************************************************
|
/***************************************************************
|
||||||
*
|
*
|
||||||
* FORWARD DECLARATIONS
|
* FORWARD DECLARATIONS
|
||||||
*/
|
*/
|
||||||
typedef struct _fluid_env_data_t fluid_env_data_t;
|
typedef struct _fluid_env_data_t fluid_env_data_t;
|
||||||
typedef struct _fluid_adriver_definition_t fluid_adriver_definition_t;
|
typedef struct _fluid_adriver_definition_t fluid_adriver_definition_t;
|
||||||
@@ -241,7 +241,7 @@ typedef struct _fluid_server_socket_t fluid_server_socket_t;
|
|||||||
|
|
||||||
/***************************************************************
|
/***************************************************************
|
||||||
*
|
*
|
||||||
* CONSTANTS
|
* CONSTANTS
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define FLUID_BUFSIZE 64
|
#define FLUID_BUFSIZE 64
|
||||||
@@ -267,7 +267,7 @@ typedef FILE* fluid_file;
|
|||||||
#define FLUID_FSEEK(_f,_n,_set) fseek(_f,_n,_set)
|
#define FLUID_FSEEK(_f,_n,_set) fseek(_f,_n,_set)
|
||||||
#define FLUID_MEMCPY(_dst,_src,_n) memcpy(_dst,_src,_n)
|
#define FLUID_MEMCPY(_dst,_src,_n) memcpy(_dst,_src,_n)
|
||||||
#define FLUID_MEMSET(_s,_c,_n) memset(_s,_c,_n)
|
#define FLUID_MEMSET(_s,_c,_n) memset(_s,_c,_n)
|
||||||
#define FLUID_STRLEN(_s) strlen(_s)
|
#define FLUID_STRLEN(_s) strlen(_s)
|
||||||
#define FLUID_STRCMP(_s,_t) strcmp(_s,_t)
|
#define FLUID_STRCMP(_s,_t) strcmp(_s,_t)
|
||||||
#define FLUID_STRNCMP(_s,_t,_n) strncmp(_s,_t,_n)
|
#define FLUID_STRNCMP(_s,_t,_n) strncmp(_s,_t,_n)
|
||||||
#define FLUID_STRCPY(_dst,_src) strcpy(_dst,_src)
|
#define FLUID_STRCPY(_dst,_src) strcpy(_dst,_src)
|
||||||
@@ -276,31 +276,16 @@ typedef FILE* fluid_file;
|
|||||||
#define FLUID_STRDUP(s) strdup(s)
|
#define FLUID_STRDUP(s) strdup(s)
|
||||||
#else
|
#else
|
||||||
#define FLUID_STRDUP(s) FLUID_STRCPY(FLUID_MALLOC(FLUID_STRLEN(s) + 1), s)
|
#define FLUID_STRDUP(s) FLUID_STRCPY(FLUID_MALLOC(FLUID_STRLEN(s) + 1), s)
|
||||||
#endif
|
#endif
|
||||||
#define FLUID_SPRINTF sprintf
|
#define FLUID_SPRINTF sprintf
|
||||||
#define FLUID_FPRINTF fprintf
|
#define FLUID_FPRINTF fprintf
|
||||||
|
|
||||||
#define fluid_clip(_val, _min, _max) \
|
#define fluid_clip(_val, _min, _max) \
|
||||||
{ (_val) = ((_val) < (_min))? (_min) : (((_val) > (_max))? (_max) : (_val)); }
|
{ (_val) = ((_val) < (_min))? (_min) : (((_val) > (_max))? (_max) : (_val)); }
|
||||||
|
|
||||||
/* Purpose:
|
|
||||||
* Some commands (SSE extensions on Pentium) need aligned data(
|
|
||||||
* The address must be ...xxx0.
|
|
||||||
* Take a pointer, and round it up to the next suitable address.
|
|
||||||
* Obviously, one has to allocate 15 bytes of additional memory.
|
|
||||||
* As soon as proper alignment is supported by the compiler, this
|
|
||||||
* can be removed.
|
|
||||||
*/
|
|
||||||
#ifdef ENABLE_SSE
|
|
||||||
/* FIXME - This is broken on AMD 64 - only used if SSE enabled */
|
|
||||||
#define FLUID_ALIGN16BYTE(ptr)(((int)(ptr)+15) & (~0xFL))
|
|
||||||
#else
|
|
||||||
#define FLUID_ALIGN16BYTE(ptr) ptr
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if WITH_FTS
|
#if WITH_FTS
|
||||||
#define FLUID_PRINTF post
|
#define FLUID_PRINTF post
|
||||||
#define FLUID_FLUSH()
|
#define FLUID_FLUSH()
|
||||||
#else
|
#else
|
||||||
#define FLUID_PRINTF printf
|
#define FLUID_PRINTF printf
|
||||||
#define FLUID_FLUSH() fflush(stdout)
|
#define FLUID_FLUSH() fflush(stdout)
|
||||||
|
|||||||
Reference in New Issue
Block a user