mirror of
https://github.com/ZDoom/fluidsynth.git
synced 2025-04-08 00:31:11 +00:00
Documentation updates, optimizations in audio drivers for non user
callback case, more leaks plugged, warn when SF file on command line not found, replacement of string tokenizer, other improvements (hopefully).
This commit is contained in:
parent
1077f672f7
commit
932e87f1b7
31 changed files with 1155 additions and 655 deletions
|
@ -114,4 +114,6 @@ Gerald Pye
|
|||
Rui Nuno Capela
|
||||
Frieder Bürzele
|
||||
Henri Manson
|
||||
Mihail Zenkov (Audio bit depth conversion dithering patch)
|
||||
Mihail Zenkov
|
||||
Paul Miller
|
||||
Nick Daly
|
||||
|
|
|
@ -1,3 +1,35 @@
|
|||
2006-12-10 Josh Green <jgreen@users.sourceforge.net>
|
||||
|
||||
Lots of documentation updates.
|
||||
* doc/Doxyfile: No longer including functions by default, only those
|
||||
listed in the listed header files.
|
||||
* src/fluid_strtok.[ch]: Removed, since it was crap. Replaced with
|
||||
fluid_strtok() in fluid_sys.c which doesn't require an allocated
|
||||
tokenizing instance.
|
||||
* src/fluid_alsa.c: Audio processing is more optimized in the case where
|
||||
no user defined audio callback is used (removal of unneeded buffer copy),
|
||||
fluid_alsa_handle_write_error() added for centralized ALSA audio error
|
||||
handling,
|
||||
* src/fluid_aufile.c: Now also doing 16 bit dithering.
|
||||
* src/fluid_cmd.c: Removed use of old tokenizer instance.
|
||||
* src/fluid_coreaudio.c: User defined callback function is now honored.
|
||||
* src/fluid_defsfont.c: More leaks plugged (thanks to Paul Miller for
|
||||
the patch), removed sfont_free_data() since sfont_close() should be
|
||||
used instead (don't want to leak a file handle).
|
||||
* src/fluid_midi_router.c: Took out uses of fflush() since sending a
|
||||
line of text (with newline) should display it.
|
||||
* src/fluid_oss.c: Using fluid_synth_dither_s16() in place of old
|
||||
16 bit conversion code.
|
||||
* src/fluid_settings.c: Replaced strtok stuff with new function, some
|
||||
other improvements.
|
||||
* src/fluid_synth.c (delete_fluid_synth): Turning off all voices so that
|
||||
SoundFont data will be freed correctly (thanks to patch from
|
||||
Paul Miller).
|
||||
* src/fluid_sys.c (fluid_strtok): New function to replace old tokenizing
|
||||
functions which required a token instance.
|
||||
* src/fluidsynth.c: Warning message printed if a non option is not a
|
||||
valid SoundFont or MIDI file (thanks to Nick Daly for the patch).
|
||||
|
||||
2006-11-22 Josh Green <jgreen@users.sourceforge.net>
|
||||
|
||||
* src/fluid_alsa.c (new_fluid_alsa_audio_driver2): Removed some ALSA
|
||||
|
|
|
@ -1,39 +1,53 @@
|
|||
New features
|
||||
------------
|
||||
- 24 bit sample support
|
||||
- Non-realtime MIDI file rendering
|
||||
- Sample streaming, load/unload sample on demand
|
||||
- Synth sample rate change after initial creation
|
||||
- handle tuning sysex messages
|
||||
- Audio level metering
|
||||
- Active voice count monitoring
|
||||
|
||||
Synthesis
|
||||
---------
|
||||
- Improve voice stealing algorithm
|
||||
- Dynamic voice killing (based on CPU usage)
|
||||
- Batch voice activation (stereo synch. as per SoundFont spec)
|
||||
- Pitch control on stereo samples not managed as should
|
||||
- soft clipping, compressor, limitor, or automatic gain control
|
||||
|
||||
Drivers
|
||||
-------
|
||||
- libao audio output driver
|
||||
- MacOS X MidiCore component
|
||||
- Windows DirectMusic component
|
||||
- ASIO driver
|
||||
- DirectSound 3D and EAX
|
||||
|
||||
Bugs to mash
|
||||
------------
|
||||
- Fix warnings on 64 bit platforms and type-puned pointer warning
|
||||
- Add byte swapping support (on synthesis or sample load?)
|
||||
- Build win32 package
|
||||
- Investigate why MIDI rendering causes burst of notes at start
|
||||
- libao audio output driver
|
||||
|
||||
Bugs and incomplete code
|
||||
------------------------
|
||||
|
||||
- Get TCP server working for windows
|
||||
- The synth consumes too much CPU when no voices are playing.
|
||||
- Add daemon mode
|
||||
|
||||
Validation
|
||||
----------
|
||||
|
||||
- Validation tests: create soundfont with basic wave forms [sine,
|
||||
square, triangle]; make test midi file; compare with SBLive output;
|
||||
"regression" test
|
||||
- Validate chorus
|
||||
- Validate chorus (often sounds rather crappy)
|
||||
- Analyse performance
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
- Write documention on tuning
|
||||
- fluid_synth_program_select2() with name of soundfont instead of font_id
|
||||
- fluid_synth_set_gen2()
|
||||
- Web site
|
||||
- Documentation and announcement Virtools and Director
|
||||
- Add usage scenarios in the documentation
|
||||
- User and system configuration file
|
||||
|
||||
Binaries
|
||||
--------
|
||||
|
||||
- FluidSynth
|
||||
* Linux
|
||||
* Win
|
||||
|
@ -42,54 +56,25 @@ Binaries
|
|||
- fluidsynth~ (MaxMSP/MacOSX, MaxMSP/Windows)
|
||||
- FluidXtra
|
||||
|
||||
- old distributions
|
||||
|
||||
Requests
|
||||
--------
|
||||
|
||||
- Improve non-realtime rendering of MIDI to WAV files
|
||||
Misc
|
||||
----
|
||||
- Remove dependency of settings on audio driver and other (see
|
||||
fluid_settings_init())
|
||||
- Add "unselect" command to shell to set a MIDI channel to not sound.
|
||||
- When specifying -i -s (no console and TCP server) log to TCP clients
|
||||
with easier parsable messages ("warning:", "error:", etc)
|
||||
- GM soundfont?
|
||||
- MacOS X MidiCore component
|
||||
- Windows DirectMusic component
|
||||
- add function to get initial soundfont generator value
|
||||
- ASIO driver
|
||||
- DirectSound 3D and EAX
|
||||
- Pause and resume the synthesizer/audio thread (run synthesizer as a daemon)
|
||||
|
||||
- set loop on/off on a sample (1 - with name sample, 2 - name sf and name preset)
|
||||
|
||||
Use set_gen?
|
||||
|
||||
set_gen: GEN_SAMPLEMODE (54):
|
||||
Loop during release: 1,
|
||||
Loop: 3
|
||||
No loop: 0 and all other values,
|
||||
- set loop on/off on a sample (set_gen GEN_SAMPLEMODE?)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Fluid 1.1:
|
||||
FluidSynth Next Generation
|
||||
--------------------------------------------
|
||||
|
||||
Top of the list
|
||||
- Use FIFOs to send events to the audio thread
|
||||
- Redo sfloader api using "interface" api
|
||||
- Clean multi-channel audio implementation
|
||||
- 3D audio output
|
||||
- Sample streaming, load/unload sample on demand
|
||||
|
||||
|
||||
SFLoader API:
|
||||
- redo sfloader api using "interface" api
|
||||
|
||||
Sample streaming
|
||||
- sample streaming, load/unload sample on demand
|
||||
|
||||
Design
|
||||
- turn ladspa fx unit and router in indepedent
|
||||
|
@ -106,26 +91,16 @@ Shell & command handler
|
|||
- Allow settings to be loaded before the synthesizer is created
|
||||
|
||||
SoundFont Specs:
|
||||
- pitch control on stereo samples not managed as should
|
||||
|
||||
MIDI Specs
|
||||
- handle tuning sysex messages
|
||||
- Omni and poly modes
|
||||
- sample dump
|
||||
- MIDI thru
|
||||
- Scalable Polyphony MIDI (SP-MIDI)
|
||||
- Downloadable Sounds ("DLS")
|
||||
- RMID (SMF w/DLS) File Format Specification
|
||||
|
||||
|
||||
Unsorted
|
||||
- Analyse/improve voice stealing algorithm (soft and hard limits?)
|
||||
- change sample rate dynamically after jack driver instantiation, or
|
||||
create audio driver before initiating the synth
|
||||
- include readline in project
|
||||
- additional aux buses
|
||||
- rewrite midi file using new sequencer
|
||||
- direct access to audio buffer
|
||||
- soft clipping, compressor, limitor, or automatic gain control
|
||||
- 96kHz/24bits
|
||||
- OpenSoundControl
|
||||
|
|
|
@ -8,7 +8,7 @@ dnl *** NOTE *** Don't forget to update library version below also
|
|||
|
||||
FLUIDSYNTH_VERSION_MAJOR=1
|
||||
FLUIDSYNTH_VERSION_MINOR=0
|
||||
FLUIDSYNTH_VERSION_MICRO=7
|
||||
FLUIDSYNTH_VERSION_MICRO=8
|
||||
FLUIDSYNTH_VERSION=$FLUIDSYNTH_VERSION_MAJOR.$FLUIDSYNTH_VERSION_MINOR.$FLUIDSYNTH_VERSION_MICRO
|
||||
|
||||
AC_SUBST(FLUIDSYNTH_VERSION_MAJOR)
|
||||
|
|
|
@ -7,18 +7,18 @@ PROJECT_NAME = libfluidsynth
|
|||
PROJECT_NUMBER =
|
||||
OUTPUT_DIRECTORY = api
|
||||
OUTPUT_LANGUAGE = English
|
||||
EXTRACT_ALL = YES
|
||||
EXTRACT_ALL = NO
|
||||
EXTRACT_PRIVATE = NO
|
||||
EXTRACT_STATIC = YES
|
||||
EXTRACT_LOCAL_CLASSES = NO
|
||||
HIDE_UNDOC_MEMBERS = NO
|
||||
HIDE_UNDOC_CLASSES = NO
|
||||
HIDE_UNDOC_MEMBERS = YES
|
||||
HIDE_UNDOC_CLASSES = YES
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
REPEAT_BRIEF = YES
|
||||
ALWAYS_DETAILED_SEC = NO
|
||||
INLINE_INHERITED_MEMB = NO
|
||||
FULL_PATH_NAMES = NO
|
||||
STRIP_FROM_PATH =
|
||||
FULL_PATH_NAMES = YES
|
||||
STRIP_FROM_PATH = ../
|
||||
INTERNAL_DOCS = NO
|
||||
STRIP_CODE_COMMENTS = YES
|
||||
CASE_SENSE_NAMES = YES
|
||||
|
@ -29,7 +29,7 @@ SHOW_INCLUDE_FILES = NO
|
|||
JAVADOC_AUTOBRIEF = YES
|
||||
INHERIT_DOCS = YES
|
||||
INLINE_INFO = YES
|
||||
SORT_MEMBER_DOCS = YES
|
||||
SORT_MEMBER_DOCS = NO
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
TAB_SIZE = 8
|
||||
GENERATE_TODOLIST = NO
|
||||
|
@ -52,17 +52,50 @@ WARN_LOGFILE =
|
|||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
INPUT = ../include/
|
||||
FILE_PATTERNS = *.h
|
||||
RECURSIVE = YES
|
||||
EXCLUDE =
|
||||
INPUT = \
|
||||
../include/fluidsynth.h \
|
||||
../include/fluidsynth/audio.h \
|
||||
../include/fluidsynth/event.h \
|
||||
../include/fluidsynth/gen.h \
|
||||
../include/fluidsynth/log.h \
|
||||
../include/fluidsynth/midi.h \
|
||||
../include/fluidsynth/misc.h \
|
||||
../include/fluidsynth/mod.h \
|
||||
../include/fluidsynth/ramsfont.h \
|
||||
../include/fluidsynth/seq.h \
|
||||
../include/fluidsynth/seqbind.h \
|
||||
../include/fluidsynth/settings.h \
|
||||
../include/fluidsynth/sfont.h \
|
||||
../include/fluidsynth/shell.h \
|
||||
../include/fluidsynth/synth.h \
|
||||
../include/fluidsynth/types.h \
|
||||
../include/fluidsynth/version.h \
|
||||
../include/fluidsynth/voice.h \
|
||||
../src/fluid_adriver.c \
|
||||
../src/fluid_event.c \
|
||||
../src/fluid_gen.c \
|
||||
../src/fluid_sys.c \
|
||||
../src/fluid_mdriver.c \
|
||||
../src/fluid_midi.c \
|
||||
../src/fluid_midi_router.c \
|
||||
../src/fluid_mod.c \
|
||||
../src/fluid_ramsfont.c \
|
||||
../src/fluid_seq.c \
|
||||
../src/fluid_seqbind.c \
|
||||
../src/fluid_settings.c \
|
||||
../src/fluid_synth.c \
|
||||
../src/fluid_voice.c
|
||||
|
||||
FILE_PATTERNS =
|
||||
RECURSIVE = NO
|
||||
EXCLUDE =
|
||||
EXCLUDE_SYMLINKS = NO
|
||||
EXCLUDE_PATTERNS =
|
||||
EXAMPLE_PATH =
|
||||
EXAMPLE_PATTERNS =
|
||||
EXAMPLE_RECURSIVE = NO
|
||||
IMAGE_PATH =
|
||||
INPUT_FILTER =
|
||||
INPUT_FILTER =
|
||||
FILTER_SOURCE_FILES = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to source browsing
|
||||
|
|
|
@ -44,40 +44,37 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
|
||||
/**
|
||||
|
||||
\file fluidsynth.h
|
||||
|
||||
\brief fluidsynth is a real-time SoundFont(R) synthesizer. This is
|
||||
the header of the fluidsynth library and contains the
|
||||
synthesizer's public API.
|
||||
|
||||
Depending on how you want to use or extend the synthesizer you
|
||||
will need different API functions. You probably do not need all
|
||||
of them. Here is what you might want to do:
|
||||
|
||||
o Embedded synthesizer: create a new synthesizer and send MIDI
|
||||
events to it. The sound goes directly to the audio output of
|
||||
your system.
|
||||
|
||||
o Plugin synthesizer: create a synthesizer and send MIDI events
|
||||
but pull the audio back into your application.
|
||||
|
||||
o SoundFont plugin: create a new type of "SoundFont" and allow
|
||||
the synthesizer to load your type of SoundFonts.
|
||||
|
||||
o MIDI input: Create a MIDI handler to read the MIDI input on your
|
||||
machine and send the MIDI events directly to the synthesizer.
|
||||
|
||||
o MIDI files: Open MIDI files and send the MIDI events to the
|
||||
synthesizer.
|
||||
|
||||
o Command lines: You can send textual commands to the synthesizer.
|
||||
|
||||
|
||||
SoundFont(R) is a registered trademark of E-mu Systems, Inc.
|
||||
|
||||
*/
|
||||
/**
|
||||
* @file fluidsynth.h
|
||||
* @brief FluidSynth is a real-time synthesizer designed for SoundFont(R) files.
|
||||
*
|
||||
* This is the header of the fluidsynth library and contains the
|
||||
* synthesizer's public API.
|
||||
*
|
||||
* Depending on how you want to use or extend the synthesizer you
|
||||
* will need different API functions. You probably do not need all
|
||||
* of them. Here is what you might want to do:
|
||||
*
|
||||
* o Embedded synthesizer: create a new synthesizer and send MIDI
|
||||
* events to it. The sound goes directly to the audio output of
|
||||
* your system.
|
||||
*
|
||||
* o Plugin synthesizer: create a synthesizer and send MIDI events
|
||||
* but pull the audio back into your application.
|
||||
*
|
||||
* o SoundFont plugin: create a new type of "SoundFont" and allow
|
||||
* the synthesizer to load your type of SoundFonts.
|
||||
*
|
||||
* o MIDI input: Create a MIDI handler to read the MIDI input on your
|
||||
* machine and send the MIDI events directly to the synthesizer.
|
||||
*
|
||||
* o MIDI files: Open MIDI files and send the MIDI events to the
|
||||
* synthesizer.
|
||||
*
|
||||
* o Command lines: You can send textual commands to the synthesizer.
|
||||
*
|
||||
* SoundFont(R) is a registered trademark of E-mu Systems, Inc.
|
||||
*/
|
||||
|
||||
#include "fluidsynth/types.h"
|
||||
#include "fluidsynth/settings.h"
|
||||
|
|
|
@ -25,15 +25,29 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @file audio.h
|
||||
* @brief Functions for audio driver output.
|
||||
*
|
||||
* Defines functions for creating audio driver output. Use
|
||||
* new_fluid_audio_driver() to create a new audio driver for a given synth
|
||||
* and configuration settings. The function new_fluid_audio_driver2() can be
|
||||
* used if custom audio processing is desired before the audio is sent to the
|
||||
* audio driver (although it is not as efficient).
|
||||
*/
|
||||
|
||||
|
||||
/** Audio driver
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/** The function should return non-zero if an error occured. */
|
||||
/**
|
||||
* Callback function type used with new_fluid_audio_driver2() to allow for
|
||||
* custom user audio processing before the audio is sent to the driver. This
|
||||
* function is responsible for rendering the audio to the buffers.
|
||||
* @param data The user data parameter as passed to new_fluid_audio_driver2().
|
||||
* @param len Length of the audio in frames.
|
||||
* @param nin Count of buffers in 'in'
|
||||
* @param in FIXME - Not used currently?
|
||||
* @param nout Count of arrays in 'out' (i.e., channel count)
|
||||
* @param out Output buffers, one for each channel
|
||||
* @return Should return 0 on success, non-zero if an error occured.
|
||||
*/
|
||||
typedef int (*fluid_audio_func_t)(void* data, int len,
|
||||
int nin, float** in,
|
||||
int nout, float** out);
|
||||
|
|
|
@ -25,28 +25,37 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @file event.h
|
||||
* @brief Sequencer event functions and defines.
|
||||
*
|
||||
* Functions and constants for creating/processing sequencer events.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sequencer event type enumeration.
|
||||
*/
|
||||
enum fluid_seq_event_type {
|
||||
FLUID_SEQ_NOTE = 0,
|
||||
FLUID_SEQ_NOTEON,
|
||||
FLUID_SEQ_NOTEOFF,
|
||||
FLUID_SEQ_ALLSOUNDSOFF,
|
||||
FLUID_SEQ_ALLNOTESOFF,
|
||||
FLUID_SEQ_BANKSELECT,
|
||||
FLUID_SEQ_PROGRAMCHANGE,
|
||||
FLUID_SEQ_PROGRAMSELECT,
|
||||
FLUID_SEQ_PITCHBEND,
|
||||
FLUID_SEQ_PITCHWHHELSENS,
|
||||
FLUID_SEQ_MODULATION,
|
||||
FLUID_SEQ_SUSTAIN,
|
||||
FLUID_SEQ_CONTROLCHANGE,
|
||||
FLUID_SEQ_PAN,
|
||||
FLUID_SEQ_VOLUME,
|
||||
FLUID_SEQ_REVERBSEND,
|
||||
FLUID_SEQ_CHORUSSEND,
|
||||
FLUID_SEQ_TIMER,
|
||||
FLUID_SEQ_ANYCONTROLCHANGE, // used for remove_events only
|
||||
FLUID_SEQ_LASTEVENT
|
||||
FLUID_SEQ_NOTE = 0, /**< Note event (DOCME) */
|
||||
FLUID_SEQ_NOTEON, /**< Note on event */
|
||||
FLUID_SEQ_NOTEOFF, /**< Note off event */
|
||||
FLUID_SEQ_ALLSOUNDSOFF, /**< All sounds off event */
|
||||
FLUID_SEQ_ALLNOTESOFF, /**< All notes off event */
|
||||
FLUID_SEQ_BANKSELECT, /**< Bank select message */
|
||||
FLUID_SEQ_PROGRAMCHANGE, /**< Program change message */
|
||||
FLUID_SEQ_PROGRAMSELECT, /**< Program select message (DOCME) */
|
||||
FLUID_SEQ_PITCHBEND, /**< Pitch bend message */
|
||||
FLUID_SEQ_PITCHWHHELSENS, /**< Pitch wheel sensitivity set message */
|
||||
FLUID_SEQ_MODULATION, /**< Modulation controller event */
|
||||
FLUID_SEQ_SUSTAIN, /**< Sustain controller event */
|
||||
FLUID_SEQ_CONTROLCHANGE, /**< MIDI control change event */
|
||||
FLUID_SEQ_PAN, /**< Stereo pan set event */
|
||||
FLUID_SEQ_VOLUME, /**< Volume set event */
|
||||
FLUID_SEQ_REVERBSEND, /**< Reverb send set event */
|
||||
FLUID_SEQ_CHORUSSEND, /**< Chorus send set event */
|
||||
FLUID_SEQ_TIMER, /**< Timer event (DOCME) */
|
||||
FLUID_SEQ_ANYCONTROLCHANGE, /**< DOCME (used for remove_events only) */
|
||||
FLUID_SEQ_LASTEVENT /**< Defines the count of event enums */
|
||||
};
|
||||
|
||||
/* Event alloc/free */
|
||||
|
|
|
@ -25,99 +25,105 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @file gen.h
|
||||
* @brief Functions and defines for SoundFont generator effects.
|
||||
*/
|
||||
|
||||
/** List of generator numbers
|
||||
Soundfont 2.01 specifications section 8.1.3 */
|
||||
/**
|
||||
* Generator (effect) numbers (Soundfont 2.01 specifications section 8.1.3)
|
||||
*/
|
||||
enum fluid_gen_type {
|
||||
GEN_STARTADDROFS,
|
||||
GEN_ENDADDROFS,
|
||||
GEN_STARTLOOPADDROFS,
|
||||
GEN_ENDLOOPADDROFS,
|
||||
GEN_STARTADDRCOARSEOFS,
|
||||
GEN_MODLFOTOPITCH,
|
||||
GEN_VIBLFOTOPITCH,
|
||||
GEN_MODENVTOPITCH,
|
||||
GEN_FILTERFC,
|
||||
GEN_FILTERQ,
|
||||
GEN_MODLFOTOFILTERFC,
|
||||
GEN_MODENVTOFILTERFC,
|
||||
GEN_ENDADDRCOARSEOFS,
|
||||
GEN_MODLFOTOVOL,
|
||||
GEN_UNUSED1,
|
||||
GEN_CHORUSSEND,
|
||||
GEN_REVERBSEND,
|
||||
GEN_PAN,
|
||||
GEN_UNUSED2,
|
||||
GEN_UNUSED3,
|
||||
GEN_UNUSED4,
|
||||
GEN_MODLFODELAY,
|
||||
GEN_MODLFOFREQ,
|
||||
GEN_VIBLFODELAY,
|
||||
GEN_VIBLFOFREQ,
|
||||
GEN_MODENVDELAY,
|
||||
GEN_MODENVATTACK,
|
||||
GEN_MODENVHOLD,
|
||||
GEN_MODENVDECAY,
|
||||
GEN_MODENVSUSTAIN,
|
||||
GEN_MODENVRELEASE,
|
||||
GEN_KEYTOMODENVHOLD,
|
||||
GEN_KEYTOMODENVDECAY,
|
||||
GEN_VOLENVDELAY,
|
||||
GEN_VOLENVATTACK,
|
||||
GEN_VOLENVHOLD,
|
||||
GEN_VOLENVDECAY,
|
||||
GEN_VOLENVSUSTAIN,
|
||||
GEN_VOLENVRELEASE,
|
||||
GEN_KEYTOVOLENVHOLD,
|
||||
GEN_KEYTOVOLENVDECAY,
|
||||
GEN_INSTRUMENT,
|
||||
GEN_RESERVED1,
|
||||
GEN_KEYRANGE,
|
||||
GEN_VELRANGE,
|
||||
GEN_STARTLOOPADDRCOARSEOFS,
|
||||
GEN_KEYNUM,
|
||||
GEN_VELOCITY,
|
||||
GEN_ATTENUATION,
|
||||
GEN_RESERVED2,
|
||||
GEN_ENDLOOPADDRCOARSEOFS,
|
||||
GEN_COARSETUNE,
|
||||
GEN_FINETUNE,
|
||||
GEN_SAMPLEID,
|
||||
GEN_SAMPLEMODE,
|
||||
GEN_RESERVED3,
|
||||
GEN_SCALETUNE,
|
||||
GEN_EXCLUSIVECLASS,
|
||||
GEN_OVERRIDEROOTKEY,
|
||||
GEN_STARTADDROFS, /**< Sample start address offset (0-32767) */
|
||||
GEN_ENDADDROFS, /**< Sample end address offset (-32767-0) */
|
||||
GEN_STARTLOOPADDROFS, /**< Sample loop start address offset (-32767-32767) */
|
||||
GEN_ENDLOOPADDROFS, /**< Sample loop end address offset (-32767-32767) */
|
||||
GEN_STARTADDRCOARSEOFS, /**< Sample start address coarse offset (X 32768) */
|
||||
GEN_MODLFOTOPITCH, /**< Modulation LFO to pitch */
|
||||
GEN_VIBLFOTOPITCH, /**< Vibrato LFO to pitch */
|
||||
GEN_MODENVTOPITCH, /**< Modulation envelope to pitch */
|
||||
GEN_FILTERFC, /**< Filter cutoff */
|
||||
GEN_FILTERQ, /**< Filter Q */
|
||||
GEN_MODLFOTOFILTERFC, /**< Modulation LFO to filter cutoff */
|
||||
GEN_MODENVTOFILTERFC, /**< Modulation envelope to filter cutoff */
|
||||
GEN_ENDADDRCOARSEOFS, /**< Sample end address coarse offset (X 32768) */
|
||||
GEN_MODLFOTOVOL, /**< Modulation LFO to volume */
|
||||
GEN_UNUSED1, /**< Unused */
|
||||
GEN_CHORUSSEND, /**< Chorus send amount */
|
||||
GEN_REVERBSEND, /**< Reverb send amount */
|
||||
GEN_PAN, /**< Stereo panning */
|
||||
GEN_UNUSED2, /**< Unused */
|
||||
GEN_UNUSED3, /**< Unused */
|
||||
GEN_UNUSED4, /**< Unused */
|
||||
GEN_MODLFODELAY, /**< Modulation LFO delay */
|
||||
GEN_MODLFOFREQ, /**< Modulation LFO frequency */
|
||||
GEN_VIBLFODELAY, /**< Vibrato LFO delay */
|
||||
GEN_VIBLFOFREQ, /**< Vibrato LFO frequency */
|
||||
GEN_MODENVDELAY, /**< Modulation envelope delay */
|
||||
GEN_MODENVATTACK, /**< Modulation envelope attack */
|
||||
GEN_MODENVHOLD, /**< Modulation envelope hold */
|
||||
GEN_MODENVDECAY, /**< Modulation envelope decay */
|
||||
GEN_MODENVSUSTAIN, /**< Modulation envelope sustain */
|
||||
GEN_MODENVRELEASE, /**< Modulation envelope release */
|
||||
GEN_KEYTOMODENVHOLD, /**< Key to modulation envelope hold */
|
||||
GEN_KEYTOMODENVDECAY, /**< Key to modulation envelope decay */
|
||||
GEN_VOLENVDELAY, /**< Volume envelope delay */
|
||||
GEN_VOLENVATTACK, /**< Volume envelope attack */
|
||||
GEN_VOLENVHOLD, /**< Volume envelope hold */
|
||||
GEN_VOLENVDECAY, /**< Volume envelope decay */
|
||||
GEN_VOLENVSUSTAIN, /**< Volume envelope sustain */
|
||||
GEN_VOLENVRELEASE, /**< Volume envelope release */
|
||||
GEN_KEYTOVOLENVHOLD, /**< Key to volume envelope hold */
|
||||
GEN_KEYTOVOLENVDECAY, /**< Key to volume envelope decay */
|
||||
GEN_INSTRUMENT, /**< Instrument ID (shouldn't be set by user) */
|
||||
GEN_RESERVED1, /**< Reserved */
|
||||
GEN_KEYRANGE, /**< MIDI note range */
|
||||
GEN_VELRANGE, /**< MIDI velocity range */
|
||||
GEN_STARTLOOPADDRCOARSEOFS, /**< Sample start loop address coarse offset (X 32768) */
|
||||
GEN_KEYNUM, /**< Fixed MIDI note number */
|
||||
GEN_VELOCITY, /**< Fixed MIDI velocity value */
|
||||
GEN_ATTENUATION, /**< Initial volume attenuation */
|
||||
GEN_RESERVED2, /**< Reserved */
|
||||
GEN_ENDLOOPADDRCOARSEOFS, /**< Sample end loop address coarse offset (X 32768) */
|
||||
GEN_COARSETUNE, /**< Coarse tuning */
|
||||
GEN_FINETUNE, /**< Fine tuning */
|
||||
GEN_SAMPLEID, /**< Sample ID (shouldn't be set by user) */
|
||||
GEN_SAMPLEMODE, /**< Sample mode flags */
|
||||
GEN_RESERVED3, /**< Reserved */
|
||||
GEN_SCALETUNE, /**< Scale tuning */
|
||||
GEN_EXCLUSIVECLASS, /**< Exclusive class number */
|
||||
GEN_OVERRIDEROOTKEY, /**< Sample root note override */
|
||||
|
||||
/* the initial pitch is not a "standard" generator. It is not
|
||||
* mentioned in the list of generator in the SF2 specifications. It
|
||||
* is used, however, as the destination for the default pitch wheel
|
||||
* modulator. */
|
||||
GEN_PITCH,
|
||||
GEN_LAST
|
||||
GEN_PITCH, /**< Pitch (NOTE: Not a real SoundFont generator) */
|
||||
GEN_LAST /**< Value defines the count of generators (#fluid_gen_type) */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* fluid_gen_t
|
||||
* Sound font generator
|
||||
*/
|
||||
/**
|
||||
* SoundFont generator structure.
|
||||
*/
|
||||
typedef struct _fluid_gen_t
|
||||
{
|
||||
unsigned char flags; /* is it used or not */
|
||||
double val; /* The nominal value */
|
||||
double mod; /* Change by modulators */
|
||||
double nrpn; /* Change by NRPN messages */
|
||||
unsigned char flags; /**< Is the generator set or not (#fluid_gen_flags) */
|
||||
double val; /**< The nominal value */
|
||||
double mod; /**< Change by modulators */
|
||||
double nrpn; /**< Change by NRPN messages */
|
||||
} fluid_gen_t;
|
||||
|
||||
/**
|
||||
* Enum value for 'flags' field of #_fluid_gen_t (not really flags).
|
||||
*/
|
||||
enum fluid_gen_flags
|
||||
{
|
||||
GEN_UNUSED,
|
||||
GEN_SET,
|
||||
GEN_ABS_NRPN
|
||||
GEN_UNUSED, /**< Generator value is not set */
|
||||
GEN_SET, /**< Generator value is set */
|
||||
GEN_ABS_NRPN /**< DOCME */
|
||||
};
|
||||
|
||||
/** Reset an array of generators to the SF2.01 default values */
|
||||
FLUIDSYNTH_API int fluid_gen_set_default_values(fluid_gen_t* gen);
|
||||
|
||||
|
||||
|
|
|
@ -27,57 +27,55 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Logging interface
|
||||
*
|
||||
* The default logging function of the fluidsynth prints its messages
|
||||
* to the stderr. The synthesizer uses four level of messages: FLUID_PANIC,
|
||||
* ERR, WARN, and FLUID_DBG. They are commented in the definition below.
|
||||
*
|
||||
* A client application can install a new log function to handle the
|
||||
* messages differently. In the following example, the application
|
||||
* sets a callback function to display "FLUID_PANIC" messages in a dialog,
|
||||
* and ignores all other messages by setting the log function to
|
||||
* NULL:
|
||||
*
|
||||
* ...
|
||||
* fluid_set_log_function(FLUID_PANIC, show_dialog, (void*) root_window);
|
||||
* fluid_set_log_function(ERR, NULL, NULL);
|
||||
* fluid_set_log_function(WARN, NULL, NULL);
|
||||
* fluid_set_log_function(FLUID_DBG, NULL, NULL);
|
||||
* ...
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* @file log.h
|
||||
* @brief Logging interface
|
||||
*
|
||||
* The default logging function of the fluidsynth prints its messages
|
||||
* to the stderr. The synthesizer uses five level of messages: #FLUID_PANIC,
|
||||
* #FLUID_ERR, #FLUID_WARN, #FLUID_INFO, and #FLUID_DBG.
|
||||
*
|
||||
* A client application can install a new log function to handle the
|
||||
* messages differently. In the following example, the application
|
||||
* sets a callback function to display #FLUID_PANIC messages in a dialog,
|
||||
* and ignores all other messages by setting the log function to
|
||||
* NULL:
|
||||
*
|
||||
* DOCME (formatting)
|
||||
* fluid_set_log_function(FLUID_PANIC, show_dialog, (void*) root_window);
|
||||
* fluid_set_log_function(FLUID_ERR, NULL, NULL);
|
||||
* fluid_set_log_function(FLUID_WARN, NULL, NULL);
|
||||
* fluid_set_log_function(FLUID_DBG, NULL, NULL);
|
||||
*/
|
||||
|
||||
/**
|
||||
* FluidSynth log levels.
|
||||
*/
|
||||
enum fluid_log_level {
|
||||
FLUID_PANIC, /* the synth can't function correctly any more */
|
||||
FLUID_ERR, /* the synth can function, but with serious limitation */
|
||||
FLUID_WARN, /* the synth might not function as expected */
|
||||
FLUID_INFO, /* verbose messages */
|
||||
FLUID_DBG, /* debugging messages */
|
||||
FLUID_PANIC, /**< The synth can't function correctly any more */
|
||||
FLUID_ERR, /**< Serious error occurred */
|
||||
FLUID_WARN, /**< Warning */
|
||||
FLUID_INFO, /**< Verbose informational messages */
|
||||
FLUID_DBG, /**< Debugging messages */
|
||||
LAST_LOG_LEVEL
|
||||
};
|
||||
|
||||
/**
|
||||
* Log function handler callback type used by fluid_set_log_function().
|
||||
* @param level Log level (#fluid_log_level)
|
||||
* @param message Log message text
|
||||
* @param data User data pointer supplied to fluid_set_log_function().
|
||||
*/
|
||||
typedef void (*fluid_log_function_t)(int level, char* message, void* data);
|
||||
|
||||
/** fluid_set_log_function installs a new log function for the
|
||||
* specified level. It returns the previously installed function.
|
||||
*/
|
||||
FLUIDSYNTH_API
|
||||
fluid_log_function_t fluid_set_log_function(int level, fluid_log_function_t fun, void* data);
|
||||
|
||||
|
||||
/** fluid_default_log_function is the fluid's default log function. It
|
||||
* prints to the stderr. */
|
||||
FLUIDSYNTH_API void fluid_default_log_function(int level, char* message, void* data);
|
||||
|
||||
/** print a message to the log */
|
||||
FLUIDSYNTH_API int fluid_log(int level, char * fmt, ...);
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -25,7 +25,10 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @file midi.h
|
||||
* @brief Functions for MIDI events, drivers and MIDI file playback.
|
||||
*/
|
||||
|
||||
FLUIDSYNTH_API fluid_midi_event_t* new_fluid_midi_event(void);
|
||||
FLUIDSYNTH_API int delete_fluid_midi_event(fluid_midi_event_t* event);
|
||||
|
@ -48,58 +51,41 @@ FLUIDSYNTH_API int fluid_midi_event_get_pitch(fluid_midi_event_t* evt);
|
|||
FLUIDSYNTH_API int fluid_midi_event_set_pitch(fluid_midi_event_t* evt, int val);
|
||||
|
||||
|
||||
/* Generic callback function for MIDI events.
|
||||
* Will be used between
|
||||
* - MIDI driver and MIDI router
|
||||
* - MIDI router and synth
|
||||
* to communicate events.
|
||||
* In the not-so-far future...
|
||||
*/
|
||||
/**
|
||||
* Generic callback function for MIDI events.
|
||||
* @param data User defined data pointer
|
||||
* @param event The MIDI event
|
||||
* @return DOCME
|
||||
*
|
||||
* Will be used between
|
||||
* - MIDI driver and MIDI router
|
||||
* - MIDI router and synth
|
||||
* to communicate events.
|
||||
* In the not-so-far future...
|
||||
*/
|
||||
typedef int (*handle_midi_event_func_t)(void* data, fluid_midi_event_t* event);
|
||||
|
||||
/*
|
||||
*
|
||||
* MIDI router
|
||||
*
|
||||
* The MIDI handler forwards incoming MIDI events to the synthesizer
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* MIDI router
|
||||
*
|
||||
* The MIDI handler forwards incoming MIDI events to the synthesizer
|
||||
*/
|
||||
|
||||
/** Create a new midi router. A midi handler connects to a midi input
|
||||
* device and forwards incoming midi events to the synthesizer.
|
||||
*/
|
||||
FLUIDSYNTH_API fluid_midi_router_t* new_fluid_midi_router(fluid_settings_t* settings,
|
||||
handle_midi_event_func_t handler,
|
||||
void* event_handler_data);
|
||||
|
||||
/** Delete the midi router.
|
||||
*
|
||||
* \param handler a pointer to the midi handler
|
||||
* \return 0 if no error occured, -1 otherwise
|
||||
*/
|
||||
FLUIDSYNTH_API int delete_fluid_midi_router(fluid_midi_router_t* handler);
|
||||
|
||||
/** The standard handler function. Every MIDI event goes through
|
||||
this. */
|
||||
FLUIDSYNTH_API int fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event);
|
||||
|
||||
/** An optional link in the MIDI chain to dump MIDI data between MIDI
|
||||
driver and router */
|
||||
FLUIDSYNTH_API int fluid_midi_dump_prerouter(void* data, fluid_midi_event_t* event);
|
||||
|
||||
/** An optional link in the MIDI chain to dump MIDI data between MIDI
|
||||
router and the synthesizer */
|
||||
FLUIDSYNTH_API int fluid_midi_dump_postrouter(void* data, fluid_midi_event_t* event);
|
||||
|
||||
/*
|
||||
*
|
||||
* MIDI driver
|
||||
*
|
||||
* The MIDI handler forwards incoming MIDI events to the synthesizer
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
FLUIDSYNTH_API
|
||||
fluid_midi_driver_t* new_fluid_midi_driver(fluid_settings_t* settings,
|
||||
handle_midi_event_func_t handler,
|
||||
|
@ -110,11 +96,9 @@ FLUIDSYNTH_API void delete_fluid_midi_driver(fluid_midi_driver_t* driver);
|
|||
|
||||
|
||||
/*
|
||||
*
|
||||
* MIDI file player
|
||||
*
|
||||
* The MIDI player allows you to play MIDI files with the FLUID Synth
|
||||
*
|
||||
*/
|
||||
|
||||
FLUIDSYNTH_API fluid_player_t* new_fluid_player(fluid_synth_t* synth);
|
||||
|
|
|
@ -92,8 +92,6 @@ libfluidsynth_la_SOURCES = \
|
|||
fluid_settings.c \
|
||||
fluid_settings.h \
|
||||
fluid_sfont.h \
|
||||
fluid_strtok.c \
|
||||
fluid_strtok.h \
|
||||
fluid_synth.c \
|
||||
fluid_synth.h \
|
||||
fluidsynth_priv.h \
|
||||
|
|
|
@ -241,10 +241,20 @@ void fluid_audio_driver_settings(fluid_settings_t* settings)
|
|||
if (fluid_audio_drivers[i].settings != NULL) {
|
||||
fluid_audio_drivers[i].settings(settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
|
@ -269,6 +279,19 @@ new_fluid_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
|
@ -294,6 +317,12 @@ new_fluid_audio_driver2(fluid_settings_t* settings, fluid_audio_func_t func, voi
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
|
|
|
@ -162,9 +162,7 @@ fluid_audio_driver_t*
|
|||
new_fluid_alsa_audio_driver(fluid_settings_t* settings,
|
||||
fluid_synth_t* synth)
|
||||
{
|
||||
return new_fluid_alsa_audio_driver2(settings,
|
||||
(fluid_audio_func_t) fluid_synth_process,
|
||||
synth);
|
||||
return new_fluid_alsa_audio_driver2(settings, NULL, synth);
|
||||
}
|
||||
|
||||
fluid_audio_driver_t*
|
||||
|
@ -296,6 +294,9 @@ new_fluid_alsa_audio_driver2(fluid_settings_t* settings,
|
|||
FLUID_LOG(FLUID_ERR, "Failed to set start threshold.");
|
||||
}
|
||||
|
||||
/* FIXME - Any of these calls important? One of them was causing massive
|
||||
ALSA CPU consumption! */
|
||||
|
||||
// if (snd_pcm_sw_params_set_stop_threshold(dev->pcm, swparams, ~0u) != 0) {
|
||||
// FLUID_LOG(FLUID_ERR, "Cannot turn off stop threshold.");
|
||||
// }
|
||||
|
@ -401,6 +402,35 @@ int delete_fluid_alsa_audio_driver(fluid_audio_driver_t* p)
|
|||
return FLUID_OK;
|
||||
}
|
||||
|
||||
/* handle error after an ALSA write call */
|
||||
static int fluid_alsa_handle_write_error (snd_pcm_t *pcm, int errval)
|
||||
{
|
||||
switch (errval)
|
||||
{
|
||||
case -EAGAIN:
|
||||
snd_pcm_wait(pcm, 1);
|
||||
break;
|
||||
case -EPIPE:
|
||||
case -EBADFD:
|
||||
if (snd_pcm_prepare(pcm) != 0) {
|
||||
FLUID_LOG(FLUID_ERR, "Failed to prepare the audio device");
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
break;
|
||||
case -ESTRPIPE:
|
||||
if ((snd_pcm_resume(pcm) != 0) && (snd_pcm_prepare(pcm) != 0)) {
|
||||
FLUID_LOG(FLUID_ERR, "Failed to resume the audio device");
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
FLUID_LOG(FLUID_ERR, "The audio device error: %s", snd_strerror(errval));
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
|
||||
return FLUID_OK;
|
||||
}
|
||||
|
||||
static void* fluid_alsa_audio_run_float(void* d)
|
||||
{
|
||||
fluid_alsa_audio_driver_t* dev = (fluid_alsa_audio_driver_t*) d;
|
||||
|
@ -430,54 +460,51 @@ static void* fluid_alsa_audio_run_float(void* d)
|
|||
goto error_recovery;
|
||||
}
|
||||
|
||||
while (dev->cont) {
|
||||
/* use separate loops depending on if callback supplied or not (overkill?) */
|
||||
if (dev->callback)
|
||||
{
|
||||
while (dev->cont) {
|
||||
handle[0] = left;
|
||||
handle[1] = right;
|
||||
|
||||
handle[0] = left;
|
||||
handle[1] = right;
|
||||
(*dev->callback)(synth, buffer_size, 0, NULL, 2, handle);
|
||||
|
||||
(*dev->callback)(synth, buffer_size, 0, NULL, 2, handle);
|
||||
offset = 0;
|
||||
while (offset < buffer_size) {
|
||||
handle[0] = left + offset;
|
||||
handle[1] = right + offset;
|
||||
|
||||
offset = 0;
|
||||
n = snd_pcm_writen(dev->pcm, (void *)handle, buffer_size - offset);
|
||||
|
||||
while (offset < buffer_size) {
|
||||
|
||||
handle[0] = left + offset;
|
||||
handle[1] = right + offset;
|
||||
|
||||
n = snd_pcm_writen(dev->pcm, (void *)handle, buffer_size - offset);
|
||||
|
||||
if (n < 0) /* error occurred? */
|
||||
{
|
||||
switch (n)
|
||||
if (n < 0) /* error occurred? */
|
||||
{
|
||||
case -EAGAIN:
|
||||
snd_pcm_wait(dev->pcm, 1);
|
||||
break;
|
||||
case -EPIPE:
|
||||
case -EBADFD:
|
||||
if (snd_pcm_prepare(dev->pcm) != 0) {
|
||||
FLUID_LOG(FLUID_ERR, "Failed to prepare the audio device");
|
||||
if (!fluid_alsa_handle_write_error (dev->pcm, n))
|
||||
goto error_recovery;
|
||||
}
|
||||
break;
|
||||
case -ESTRPIPE:
|
||||
if ((snd_pcm_resume(dev->pcm) != 0)
|
||||
&& (snd_pcm_prepare(dev->pcm) != 0)) {
|
||||
FLUID_LOG(FLUID_ERR, "Failed to resume the audio device");
|
||||
goto error_recovery;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
FLUID_LOG(FLUID_ERR, "The audio device error: %s", snd_strerror(n));
|
||||
goto error_recovery;
|
||||
break;
|
||||
}
|
||||
} else { /* no error occurred */
|
||||
offset += n;
|
||||
}
|
||||
}
|
||||
} else offset += n; /* no error occurred */
|
||||
} /* while (offset < buffer_size) */
|
||||
} /* while (dev->cont) */
|
||||
}
|
||||
|
||||
else /* no user audio callback (faster) */
|
||||
{
|
||||
while (dev->cont) {
|
||||
fluid_synth_write_float(dev->data, buffer_size, left, 0, 1, right, 0, 1);
|
||||
|
||||
offset = 0;
|
||||
while (offset < buffer_size) {
|
||||
handle[0] = left + offset;
|
||||
handle[1] = right + offset;
|
||||
|
||||
n = snd_pcm_writen(dev->pcm, (void *)handle, buffer_size - offset);
|
||||
|
||||
if (n < 0) /* error occurred? */
|
||||
{
|
||||
if (!fluid_alsa_handle_write_error (dev->pcm, n))
|
||||
goto error_recovery;
|
||||
} else offset += n; /* no error occurred */
|
||||
} /* while (offset < buffer_size) */
|
||||
} /* while (dev->cont) */
|
||||
}
|
||||
|
||||
error_recovery:
|
||||
|
||||
FLUID_FREE(left);
|
||||
|
@ -521,52 +548,43 @@ static void* fluid_alsa_audio_run_s16(void* d)
|
|||
goto error_recovery;
|
||||
}
|
||||
|
||||
while (dev->cont) {
|
||||
/* use separate loops depending on if callback supplied or not (overkill?) */
|
||||
if (dev->callback)
|
||||
{
|
||||
while (dev->cont) {
|
||||
(*dev->callback)(synth, buffer_size, 0, NULL, 2, handle);
|
||||
|
||||
handle[0] = left;
|
||||
handle[1] = right;
|
||||
/* convert floating point data to 16 bit (with dithering) */
|
||||
fluid_synth_dither_s16 (synth, buffer_size, left, right, buf, 0, 2, buf, 1, 2);
|
||||
|
||||
(*dev->callback)(synth, buffer_size, 0, NULL, 2, handle);
|
||||
offset = 0;
|
||||
while (offset < buffer_size) {
|
||||
n = snd_pcm_writei(dev->pcm, (void*) (buf + 2 * offset), buffer_size - offset);
|
||||
|
||||
/* convert floating point data to 16 bit (with dithering) */
|
||||
fluid_synth_dither_s16 (synth, buffer_size, left, right, buf, 0, 2, buf, 1, 2);
|
||||
|
||||
offset = 0;
|
||||
|
||||
while (offset < buffer_size) {
|
||||
|
||||
n = snd_pcm_writei(dev->pcm, (void*) (buf + 2 * offset), buffer_size - offset);
|
||||
|
||||
if (n < 0) /* error occurred? */
|
||||
{
|
||||
switch (n)
|
||||
if (n < 0) /* error occurred? */
|
||||
{
|
||||
case -EAGAIN:
|
||||
snd_pcm_wait(dev->pcm, 1);
|
||||
break;
|
||||
case -EPIPE:
|
||||
case -EBADFD:
|
||||
if (snd_pcm_prepare(dev->pcm) != 0) {
|
||||
FLUID_LOG(FLUID_ERR, "Failed to prepare the audio device");
|
||||
if (!fluid_alsa_handle_write_error (dev->pcm, n))
|
||||
goto error_recovery;
|
||||
}
|
||||
break;
|
||||
case -ESTRPIPE:
|
||||
if ((snd_pcm_resume(dev->pcm) != 0)
|
||||
&& (snd_pcm_prepare(dev->pcm) != 0)) {
|
||||
FLUID_LOG(FLUID_ERR, "Failed to resume the audio device");
|
||||
} else offset += n; /* no error occurred */
|
||||
} /* while (offset < buffer_size) */
|
||||
} /* while (dev->cont) */
|
||||
}
|
||||
else /* no user audio callback (faster) */
|
||||
{
|
||||
while (dev->cont) {
|
||||
fluid_synth_write_s16(dev->data, buffer_size, buf, 0, 2, buf, 1, 2);
|
||||
|
||||
offset = 0;
|
||||
while (offset < buffer_size) {
|
||||
n = snd_pcm_writei(dev->pcm, (void*) (buf + 2 * offset), buffer_size - offset);
|
||||
|
||||
if (n < 0) /* error occurred? */
|
||||
{
|
||||
if (!fluid_alsa_handle_write_error (dev->pcm, n))
|
||||
goto error_recovery;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
FLUID_LOG(FLUID_ERR, "The audio device error: %s", snd_strerror(n));
|
||||
goto error_recovery;
|
||||
break;
|
||||
}
|
||||
} else { /* no error occurred */
|
||||
offset += n;
|
||||
}
|
||||
}
|
||||
} else offset += n; /* no error occurred */
|
||||
} /* while (offset < buffer_size) */
|
||||
} /* while (dev->cont) */
|
||||
}
|
||||
|
||||
error_recovery:
|
||||
|
@ -1086,7 +1104,6 @@ fluid_alsa_seq_run(void* d)
|
|||
if (n < 0) {
|
||||
perror("poll");
|
||||
} else if (n > 0) { /* check for pending events */
|
||||
// while (snd_seq_event_input_pending (dev->seq_handle, 0))
|
||||
do
|
||||
{
|
||||
ev = snd_seq_event_input(dev->seq_handle, &seq_ev); /* read the events */
|
||||
|
|
|
@ -157,43 +157,26 @@ int delete_fluid_file_audio_driver(fluid_audio_driver_t* p)
|
|||
static int fluid_file_audio_run_s16(void* d, unsigned int clock_time)
|
||||
{
|
||||
fluid_file_audio_driver_t* dev = (fluid_file_audio_driver_t*) d;
|
||||
float* handle[2];
|
||||
int i, k, n, offset;
|
||||
float s;
|
||||
int n, offset;
|
||||
unsigned int sample_time;
|
||||
|
||||
handle[0] = dev->left;
|
||||
handle[1] = dev->right;
|
||||
|
||||
|
||||
sample_time = (unsigned int) (dev->samples / dev->sample_rate * 1000.0);
|
||||
if (sample_time > clock_time) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
(*dev->callback)(dev->data, dev->period_size, 0, NULL, 2, handle);
|
||||
|
||||
for (i = 0, k = 0; i < dev->period_size; i++, k += 2) {
|
||||
s = 32768.0f * dev->left[i];
|
||||
fluid_clip(s, -32768.0f, 32767.0f);
|
||||
dev->buf[k] = (short) s;
|
||||
}
|
||||
|
||||
for (i = 0, k = 1; i < dev->period_size; i++, k += 2) {
|
||||
s = 32768.0f * dev->right[i];
|
||||
fluid_clip(s, -32768.0f, 32767.0f);
|
||||
dev->buf[k] = (short) s;
|
||||
}
|
||||
|
||||
fluid_synth_write_s16(dev->data, dev->period_size, dev->buf, 0, 2, dev->buf, 1, 2);
|
||||
|
||||
for (offset = 0; offset < dev->buf_size; offset += n) {
|
||||
|
||||
n = fwrite((char*) dev->buf + offset, 1, dev->buf_size - offset, dev->file);
|
||||
if (n < 0) {
|
||||
FLUID_LOG(FLUID_ERR, "Audio file error");
|
||||
return 0;
|
||||
}
|
||||
FLUID_LOG(FLUID_ERR, "Audio output file write error: %s",
|
||||
strerror (errno));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dev->samples += dev->period_size;
|
||||
|
||||
return 1;
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include "fluidsynth_priv.h"
|
||||
#include "fluid_cmd.h"
|
||||
#include "fluid_synth.h"
|
||||
#include "fluid_strtok.h"
|
||||
#include "fluid_settings.h"
|
||||
#include "fluid_io.h"
|
||||
#include "fluid_hash.h"
|
||||
|
@ -36,6 +35,7 @@
|
|||
#endif
|
||||
|
||||
#define MAX_TOKENS 100 /* LADSPA plugins need lots of parameters */
|
||||
#define MAX_COMMAND_LEN 1024 /* max command length accepted by fluid_command() */
|
||||
#define FLUID_WORKLINELENGTH 1024 /* LADSPA plugins use long command lines */
|
||||
|
||||
void fluid_shell_settings(fluid_settings_t* settings)
|
||||
|
@ -157,44 +157,43 @@ fluid_cmd_t fluid_commands[] = {
|
|||
{ NULL, NULL, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
int fluid_command2(fluid_strtok_t* strtok, fluid_cmd_handler_t* handler,
|
||||
char* cmd, fluid_ostream_t out);
|
||||
|
||||
/**
|
||||
* Process a string command.
|
||||
* NOTE: FluidSynth 1.0.8+ no longer modifies the 'cmd' string.
|
||||
* @param handle FluidSynth command handler
|
||||
* @param cmd Command string (NOTE: Gets modified by FluidSynth prior to 1.0.8)
|
||||
* @param out Output stream to display command response to
|
||||
* @return Integer value corresponding to: -1 on command error, 0 on success,
|
||||
* 1 if 'cmd' is a comment or is empty and -2 if quit was issued
|
||||
*/
|
||||
int
|
||||
fluid_command(fluid_cmd_handler_t* handler, char* cmd, fluid_ostream_t out)
|
||||
{
|
||||
int ret;
|
||||
|
||||
fluid_strtok_t* st = new_fluid_strtok(cmd, " \t\n\r");
|
||||
if (st == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = fluid_command2(st, handler, cmd, out);
|
||||
delete_fluid_strtok(st);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
fluid_command2(fluid_strtok_t* st, fluid_cmd_handler_t* handler, char* cmd, fluid_ostream_t out)
|
||||
{
|
||||
char* token[MAX_TOKENS];
|
||||
char buf[MAX_COMMAND_LEN+1];
|
||||
char *strtok, *tok;
|
||||
int num_tokens = 0;
|
||||
|
||||
if (cmd[0] == '#') {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* tokenize the input line */
|
||||
fluid_strtok_set(st, cmd, " \t\n\r");
|
||||
while (fluid_strtok_has_more(st)) {
|
||||
token[num_tokens++] = fluid_strtok_next_token(st);
|
||||
}
|
||||
|
||||
if (num_tokens == 0) {
|
||||
return 1;
|
||||
if (strlen (cmd) > MAX_COMMAND_LEN)
|
||||
{
|
||||
fluid_ostream_printf(out, "Command exceeded max length of %d chars\n",
|
||||
MAX_COMMAND_LEN);
|
||||
return -1;
|
||||
}
|
||||
|
||||
FLUID_STRCPY(buf, cmd); /* copy - since fluid_strtok thrashes it */
|
||||
strtok = buf;
|
||||
|
||||
/* tokenize the input line */
|
||||
while ((tok = fluid_strtok (&strtok, " \t\n\r")))
|
||||
token[num_tokens++] = tok;
|
||||
|
||||
if (num_tokens == 0) return 1;
|
||||
|
||||
/* handle the command */
|
||||
return fluid_cmd_handler_handle(handler, num_tokens, &token[0], out);
|
||||
}
|
||||
|
@ -203,7 +202,6 @@ struct _fluid_shell_t {
|
|||
fluid_settings_t* settings;
|
||||
fluid_cmd_handler_t* handler;
|
||||
fluid_thread_t* thread;
|
||||
fluid_strtok_t* st;
|
||||
fluid_istream_t in;
|
||||
fluid_ostream_t out;
|
||||
};
|
||||
|
@ -247,7 +245,6 @@ void fluid_shell_init(fluid_shell_t* shell,
|
|||
{
|
||||
shell->settings = settings;
|
||||
shell->handler = handler;
|
||||
shell->st = new_fluid_strtok(NULL, NULL);
|
||||
shell->in = in;
|
||||
shell->out = out;
|
||||
}
|
||||
|
@ -258,8 +255,6 @@ void delete_fluid_shell(fluid_shell_t* shell)
|
|||
delete_fluid_thread(shell->thread);
|
||||
}
|
||||
|
||||
if (shell->st) delete_fluid_strtok (shell->st);
|
||||
|
||||
FLUID_FREE(shell);
|
||||
}
|
||||
|
||||
|
@ -292,7 +287,7 @@ int fluid_shell_run(fluid_shell_t* shell)
|
|||
#endif
|
||||
|
||||
/* handle the command */
|
||||
switch (fluid_command2(shell->st, shell->handler, workline, shell->out)) {
|
||||
switch (fluid_command(shell->handler, workline, shell->out)) {
|
||||
|
||||
case 1: /* empty line or comment */
|
||||
break;
|
||||
|
|
|
@ -215,36 +215,23 @@ fluid_core_audio_callback(AudioDeviceID id,
|
|||
{
|
||||
int i, k;
|
||||
fluid_core_audio_driver_t* dev = (fluid_core_audio_driver_t*) data;
|
||||
/* int len = out->mBuffers[0].mDataByteSize / dev->format.mBytesPerFrame; */
|
||||
int len = dev->buffer_size / dev->format.mBytesPerFrame;
|
||||
float* buffer = out->mBuffers[0].mData;
|
||||
float* left = dev->buffers[0];
|
||||
float* right = dev->buffers[1];
|
||||
|
||||
#if 0
|
||||
double incr = 220.0 * 2. * 3.14159265359 / dev->format.mSampleRate;
|
||||
if (dev->callback)
|
||||
{
|
||||
float* left = dev->buffers[0];
|
||||
float* right = dev->buffers[1];
|
||||
|
||||
for (i = 0, k = 0; i < len; i++) {
|
||||
float s = 0.2 * sin(dev->phase);
|
||||
dev->phase += incr;
|
||||
buffer[k++] = s;
|
||||
buffer[k++] = s;
|
||||
(*dev->callback)(dev->data, len, 0, NULL, 2, dev->buffers);
|
||||
|
||||
for (i = 0, k = 0; i < len; i++) {
|
||||
buffer[k++] = left[i];
|
||||
buffer[k++] = right[i];
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#if 0
|
||||
(*dev->callback)(dev->data, len, 0, NULL, 2, dev->buffers);
|
||||
#else
|
||||
fluid_synth_write_float((fluid_synth_t*) dev->data, len, dev->buffers[0], 0, 1, dev->buffers[1], 0, 1);
|
||||
#endif
|
||||
|
||||
for (i = 0, k = 0; i < len; i++) {
|
||||
buffer[k++] = left[i];
|
||||
buffer[k++] = right[i];
|
||||
}
|
||||
#endif
|
||||
|
||||
else fluid_synth_write_float((fluid_synth_t*) dev->data, len, buffer, 0, 2,
|
||||
buffer, 1, 2);
|
||||
return noErr;
|
||||
}
|
||||
|
||||
|
|
|
@ -301,21 +301,20 @@ int fluid_defsfont_load(fluid_defsfont_t* sfont, const char* file)
|
|||
sfont->samplesize = sfdata->samplesize;
|
||||
|
||||
/* load sample data in one block */
|
||||
if (fluid_defsfont_load_sampledata(sfont) != FLUID_OK) {
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
if (fluid_defsfont_load_sampledata(sfont) != FLUID_OK)
|
||||
goto err_exit;
|
||||
|
||||
/* Create all the sample headers */
|
||||
p = sfdata->sample;
|
||||
while (p != NULL) {
|
||||
sfsample = (SFSample *) p->data;
|
||||
|
||||
sample = new_fluid_sample();
|
||||
if (sample == NULL) {
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
if (fluid_sample_import_sfont(sample, sfsample, sfont) != FLUID_OK) {
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
if (sample == NULL) goto err_exit;
|
||||
|
||||
if (fluid_sample_import_sfont(sample, sfsample, sfont) != FLUID_OK)
|
||||
goto err_exit;
|
||||
|
||||
fluid_defsfont_add_sample(sfont, sample);
|
||||
fluid_voice_optimize_sample(sample);
|
||||
p = fluid_list_next(p);
|
||||
|
@ -326,18 +325,21 @@ int fluid_defsfont_load(fluid_defsfont_t* sfont, const char* file)
|
|||
while (p != NULL) {
|
||||
sfpreset = (SFPreset *) p->data;
|
||||
preset = new_fluid_defpreset(sfont);
|
||||
if (preset == NULL) {
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
if (fluid_defpreset_import_sfont(preset, sfpreset, sfont) != FLUID_OK) {
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
if (preset == NULL) goto err_exit;
|
||||
|
||||
if (fluid_defpreset_import_sfont(preset, sfpreset, sfont) != FLUID_OK)
|
||||
goto err_exit;
|
||||
|
||||
fluid_defsfont_add_preset(sfont, preset);
|
||||
p = fluid_list_next(p);
|
||||
}
|
||||
sfont_free_data(sfdata);
|
||||
sfont_close (sfdata);
|
||||
|
||||
return FLUID_OK;
|
||||
|
||||
err_exit:
|
||||
sfont_close (sfdata);
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
|
||||
/* fluid_defsfont_add_sample
|
||||
|
@ -3009,21 +3011,15 @@ unsigned short badpgen[] = { Gen_StartAddrOfs, Gen_EndAddrOfs, Gen_StartLoopAddr
|
|||
Gen_OverrideRootKey, 0
|
||||
};
|
||||
|
||||
/* close SoundFont file and delete a SoundFont structure */
|
||||
void
|
||||
sfont_close (SFData * sf)
|
||||
{
|
||||
fluid_list_t *p, *p2;
|
||||
|
||||
if (sf->sffd)
|
||||
fclose (sf->sffd);
|
||||
|
||||
sfont_free_data (sf);
|
||||
}
|
||||
|
||||
/* delete a sound font structure */
|
||||
void
|
||||
sfont_free_data (SFData * sf)
|
||||
{
|
||||
fluid_list_t *p, *p2;
|
||||
|
||||
if (sf->fname)
|
||||
free (sf->fname);
|
||||
|
||||
|
|
|
@ -218,7 +218,6 @@ extern unsigned short badpgen[]; /* list of bad preset generators */
|
|||
void sfont_init_chunks (void);
|
||||
|
||||
void sfont_close (SFData * sf);
|
||||
void sfont_free_data (SFData * sf);
|
||||
void sfont_free_zone (SFZone * zone);
|
||||
int sfont_preset_compare_func (void* a, void* b);
|
||||
|
||||
|
|
|
@ -38,6 +38,10 @@
|
|||
|
||||
/* Event alloc/free */
|
||||
|
||||
/**
|
||||
* Create a new sequencer event structure.
|
||||
* @return New sequencer event structure or NULL if out of memory
|
||||
*/
|
||||
fluid_event_t*
|
||||
new_fluid_event()
|
||||
{
|
||||
|
@ -52,13 +56,17 @@ new_fluid_event()
|
|||
FLUID_MEMSET(evt, 0, sizeof(fluid_event_t));
|
||||
|
||||
// by default, no type
|
||||
evt->dest = -1;
|
||||
evt->src = -1;
|
||||
evt->type = -1;
|
||||
|
||||
return(evt);
|
||||
evt->dest = -1;
|
||||
evt->src = -1;
|
||||
evt->type = -1;
|
||||
|
||||
return(evt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a sequencer event structure.
|
||||
* @param evt Sequencer event structure created by new_fluid_event().
|
||||
*/
|
||||
void
|
||||
delete_fluid_event(fluid_event_t* evt)
|
||||
{
|
||||
|
@ -70,26 +78,45 @@ delete_fluid_event(fluid_event_t* 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
|
||||
fluid_event_set_time(fluid_event_t* evt, unsigned int time)
|
||||
{
|
||||
evt->time = time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set source of a sequencer event (DOCME).
|
||||
* @param evt Sequencer event structure
|
||||
* @param src DOCME
|
||||
*/
|
||||
void
|
||||
fluid_event_set_source(fluid_event_t* evt, short src)
|
||||
{
|
||||
evt->src = src;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set destination of a sequencer event (DOCME).
|
||||
* @param evt Sequencer event structure
|
||||
* @param dest DOCME
|
||||
*/
|
||||
void
|
||||
fluid_event_set_dest(fluid_event_t* evt, short dest)
|
||||
{
|
||||
evt->dest = dest;
|
||||
}
|
||||
|
||||
/* Timer events */
|
||||
/**
|
||||
* Set a sequencer event to be a timer event.
|
||||
* @param evt Sequencer event structure
|
||||
* @param data DOCME
|
||||
*/
|
||||
void
|
||||
fluid_event_timer(fluid_event_t* evt, void* data)
|
||||
{
|
||||
|
@ -97,8 +124,13 @@ fluid_event_timer(fluid_event_t* evt, void* data)
|
|||
evt->data = data;
|
||||
}
|
||||
|
||||
|
||||
/* Note events */
|
||||
/**
|
||||
* Set a sequencer event to be a note on event.
|
||||
* @param evt Sequencer event structure
|
||||
* @param channel MIDI channel number
|
||||
* @param key MIDI note number (0-127)
|
||||
* @param vel MIDI velocity value (0-127)
|
||||
*/
|
||||
void
|
||||
fluid_event_noteon(fluid_event_t* evt, int channel, short key, short vel)
|
||||
{
|
||||
|
@ -108,6 +140,12 @@ fluid_event_noteon(fluid_event_t* evt, int channel, short key, short vel)
|
|||
evt->vel = vel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a sequencer event to be a note off event.
|
||||
* @param evt Sequencer event structure
|
||||
* @param channel MIDI channel number
|
||||
* @param key MIDI note number (0-127)
|
||||
*/
|
||||
void
|
||||
fluid_event_noteoff(fluid_event_t* evt, int channel, short key)
|
||||
{
|
||||
|
@ -116,6 +154,14 @@ fluid_event_noteoff(fluid_event_t* evt, int channel, short key)
|
|||
evt->key = key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a sequencer event to be a note duration event.
|
||||
* @param evt Sequencer event structure
|
||||
* @param channel MIDI channel number
|
||||
* @param key MIDI note number (0-127)
|
||||
* @param vel MIDI velocity value (0-127)
|
||||
* @param duration Duration of note (DOCME units?)
|
||||
*/
|
||||
void
|
||||
fluid_event_note(fluid_event_t* evt, int channel, short key, short vel, unsigned int duration)
|
||||
{
|
||||
|
@ -126,6 +172,11 @@ fluid_event_note(fluid_event_t* evt, int channel, short key, short vel, unsigned
|
|||
evt->duration = duration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a sequencer event to be an all sounds off event.
|
||||
* @param evt Sequencer event structure
|
||||
* @param channel MIDI channel number
|
||||
*/
|
||||
void
|
||||
fluid_event_all_sounds_off(fluid_event_t* evt, int channel)
|
||||
{
|
||||
|
@ -133,6 +184,11 @@ fluid_event_all_sounds_off(fluid_event_t* evt, int channel)
|
|||
evt->channel = channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a sequencer event to be a all notes off event.
|
||||
* @param evt Sequencer event structure
|
||||
* @param channel MIDI channel number
|
||||
*/
|
||||
void
|
||||
fluid_event_all_notes_off(fluid_event_t* evt, int channel)
|
||||
{
|
||||
|
@ -140,6 +196,12 @@ fluid_event_all_notes_off(fluid_event_t* evt, int channel)
|
|||
evt->channel = channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a sequencer event to be a bank select event.
|
||||
* @param evt Sequencer event structure
|
||||
* @param channel MIDI channel number
|
||||
* @param bank_num MIDI bank number (0-16383)
|
||||
*/
|
||||
void
|
||||
fluid_event_bank_select(fluid_event_t* evt, int channel, short bank_num)
|
||||
{
|
||||
|
@ -148,6 +210,12 @@ fluid_event_bank_select(fluid_event_t* evt, int channel, short bank_num)
|
|||
evt->control = bank_num;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a sequencer event to be a program change event.
|
||||
* @param evt Sequencer event structure
|
||||
* @param channel MIDI channel number
|
||||
* @param val MIDI program number (0-127)
|
||||
*/
|
||||
void
|
||||
fluid_event_program_change(fluid_event_t* evt, int channel, short val)
|
||||
{
|
||||
|
@ -156,6 +224,14 @@ fluid_event_program_change(fluid_event_t* evt, int channel, short val)
|
|||
evt->value = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a sequencer event to be a program select event.
|
||||
* @param evt Sequencer event structure
|
||||
* @param channel MIDI channel number
|
||||
* @param sfont_id SoundFont ID number
|
||||
* @param bank_num MIDI bank number (0-16383)
|
||||
* @param preset_num MIDI preset number (0-127)
|
||||
*/
|
||||
void
|
||||
fluid_event_program_select(fluid_event_t* evt, int channel,
|
||||
unsigned int sfont_id, short bank_num, short preset_num)
|
||||
|
@ -167,6 +243,12 @@ fluid_event_program_select(fluid_event_t* evt, int channel,
|
|||
evt->control = bank_num;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a sequencer event to be an any control change event.
|
||||
* @param evt Sequencer event structure
|
||||
* @param channel MIDI channel number
|
||||
* DOCME
|
||||
*/
|
||||
void
|
||||
fluid_event_any_control_change(fluid_event_t* evt, int channel)
|
||||
{
|
||||
|
@ -174,6 +256,12 @@ fluid_event_any_control_change(fluid_event_t* evt, int channel)
|
|||
evt->channel = channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a sequencer event to be a pitch bend event.
|
||||
* @param evt Sequencer event structure
|
||||
* @param channel MIDI channel number
|
||||
* @param pitch MIDI pitch bend value (0-16383, 8192 = no bend)
|
||||
*/
|
||||
void
|
||||
fluid_event_pitch_bend(fluid_event_t* evt, int channel, int pitch)
|
||||
{
|
||||
|
@ -184,6 +272,12 @@ fluid_event_pitch_bend(fluid_event_t* evt, int channel, int pitch)
|
|||
evt->pitch = pitch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a sequencer event to be a pitch wheel sensitivity event.
|
||||
* @param evt Sequencer event structure
|
||||
* @param channel MIDI channel number
|
||||
* @param value MIDI pitch wheel sensitivity value (DOCME units?)
|
||||
*/
|
||||
void
|
||||
fluid_event_pitch_wheelsens(fluid_event_t* evt, int channel, short value)
|
||||
{
|
||||
|
@ -192,6 +286,12 @@ fluid_event_pitch_wheelsens(fluid_event_t* evt, int channel, short value)
|
|||
evt->value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a sequencer event to be a modulation event.
|
||||
* @param evt Sequencer event structure
|
||||
* @param channel MIDI channel number
|
||||
* @param val MIDI modulation value (0-127)
|
||||
*/
|
||||
void
|
||||
fluid_event_modulation(fluid_event_t* evt, int channel, short val)
|
||||
{
|
||||
|
@ -202,6 +302,12 @@ fluid_event_modulation(fluid_event_t* evt, int channel, short val)
|
|||
evt->value = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a sequencer event to be a MIDI sustain event.
|
||||
* @param evt Sequencer event structure
|
||||
* @param channel MIDI channel number
|
||||
* @param val MIDI sustain value (0-127)
|
||||
*/
|
||||
void
|
||||
fluid_event_sustain(fluid_event_t* evt, int channel, short val)
|
||||
{
|
||||
|
@ -212,6 +318,13 @@ fluid_event_sustain(fluid_event_t* evt, int channel, short val)
|
|||
evt->value = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a sequencer event to be a MIDI control change event.
|
||||
* @param evt Sequencer event structure
|
||||
* @param channel MIDI channel number
|
||||
* @param control MIDI control number (0-127)
|
||||
* @param val MIDI control value (0-16383 DOCME is that true?)
|
||||
*/
|
||||
void
|
||||
fluid_event_control_change(fluid_event_t* evt, int channel, short control, short val)
|
||||
{
|
||||
|
@ -221,6 +334,12 @@ fluid_event_control_change(fluid_event_t* evt, int channel, short control, short
|
|||
evt->value = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a sequencer event to be a stereo pan event.
|
||||
* @param evt Sequencer event structure
|
||||
* @param channel MIDI channel number
|
||||
* @param val MIDI panning value (0-127, 0=left, 64 = middle, 127 = right)
|
||||
*/
|
||||
void
|
||||
fluid_event_pan(fluid_event_t* evt, int channel, short val)
|
||||
{
|
||||
|
@ -231,6 +350,12 @@ fluid_event_pan(fluid_event_t* evt, int channel, short val)
|
|||
evt->value = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a sequencer event to be a volume event.
|
||||
* @param evt Sequencer event structure
|
||||
* @param channel MIDI channel number
|
||||
* @param val Volume value (0-127)
|
||||
*/
|
||||
void
|
||||
fluid_event_volume(fluid_event_t* evt, int channel, short val)
|
||||
{
|
||||
|
@ -241,6 +366,12 @@ fluid_event_volume(fluid_event_t* evt, int channel, short val)
|
|||
evt->value = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a sequencer event to be a reverb send event.
|
||||
* @param evt Sequencer event structure
|
||||
* @param channel MIDI channel number
|
||||
* @param val Reverb amount (0-127)
|
||||
*/
|
||||
void
|
||||
fluid_event_reverb_send(fluid_event_t* evt, int channel, short val)
|
||||
{
|
||||
|
@ -251,6 +382,12 @@ fluid_event_reverb_send(fluid_event_t* evt, int channel, short val)
|
|||
evt->value = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a sequencer event to be a chorus send event.
|
||||
* @param evt Sequencer event structure
|
||||
* @param channel MIDI channel number
|
||||
* @param val Chorus amount (0-127)
|
||||
*/
|
||||
void
|
||||
fluid_event_chorus_send(fluid_event_t* evt, int channel, short val)
|
||||
{
|
||||
|
@ -261,75 +398,178 @@ fluid_event_chorus_send(fluid_event_t* evt, int channel, short val)
|
|||
evt->value = val;
|
||||
}
|
||||
|
||||
/* Accessing event data */
|
||||
|
||||
/*
|
||||
* Accessing event data
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get the event type (#fluid_seq_event_type) field from a sequencer event structure.
|
||||
* @param evt Sequencer event structure
|
||||
* @return Event type (#fluid_seq_event_type).
|
||||
*/
|
||||
int fluid_event_get_type(fluid_event_t* evt)
|
||||
{
|
||||
return evt->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the time field from a sequencer event structure.
|
||||
* @param evt Sequencer event structure
|
||||
* @return Time value (DOCME units?)
|
||||
*/
|
||||
unsigned int fluid_event_get_time(fluid_event_t* evt)
|
||||
{
|
||||
return evt->time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the source field from a sequencer event structure.
|
||||
* @param evt Sequencer event structure
|
||||
* @return DOCME
|
||||
*/
|
||||
short fluid_event_get_source(fluid_event_t* evt)
|
||||
{
|
||||
return evt->src;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the dest field from a sequencer event structure.
|
||||
* @param evt Sequencer event structure
|
||||
* @return DOCME
|
||||
*/
|
||||
short fluid_event_get_dest(fluid_event_t* evt)
|
||||
{
|
||||
return evt->dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the MIDI channel field from a sequencer event structure.
|
||||
* @param evt Sequencer event structure
|
||||
* @return MIDI channel number (DOCME 0-15 or more?)
|
||||
*/
|
||||
int fluid_event_get_channel(fluid_event_t* evt)
|
||||
{
|
||||
return evt->channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the MIDI note field from a sequencer event structure.
|
||||
* @param evt Sequencer event structure
|
||||
* @return MIDI note number (0-127)
|
||||
*/
|
||||
short fluid_event_get_key(fluid_event_t* evt)
|
||||
{
|
||||
return evt->key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the MIDI velocity field from a sequencer event structure.
|
||||
* @param evt Sequencer event structure
|
||||
* @return MIDI velocity value (0-127)
|
||||
*/
|
||||
short fluid_event_get_velocity(fluid_event_t* evt)
|
||||
|
||||
{
|
||||
return evt->vel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the MIDI control number field from a sequencer event structure.
|
||||
* @param evt Sequencer event structure
|
||||
* @return MIDI control number (0-127)
|
||||
*/
|
||||
short fluid_event_get_control(fluid_event_t* evt)
|
||||
{
|
||||
return evt->control;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value field from a sequencer event structure.
|
||||
* @param evt Sequencer event structure
|
||||
* @return Value field of event.
|
||||
*
|
||||
* The Value field is used by the following event types:
|
||||
* #FLUID_SEQ_PROGRAMCHANGE, #FLUID_SEQ_PROGRAMSELECT (preset_num),
|
||||
* #FLUID_SEQ_PITCHWHHELSENS, #FLUID_SEQ_MODULATION, #FLUID_SEQ_SUSTAIN,
|
||||
* #FLUID_SEQ_CONTROLCHANGE, #FLUID_SEQ_PAN, #FLUID_SEQ_VOLUME,
|
||||
* #FLUID_SEQ_REVERBSEND, #FLUID_SEQ_CHORUSSEND.
|
||||
*/
|
||||
short fluid_event_get_value(fluid_event_t* evt)
|
||||
{
|
||||
return evt->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data field from a sequencer event structure.
|
||||
* @param evt Sequencer event structure
|
||||
* @return Data field of event.
|
||||
*
|
||||
* Used by the #FLUID_SEQ_TIMER event type.
|
||||
*/
|
||||
void* fluid_event_get_data(fluid_event_t* evt)
|
||||
{
|
||||
return evt->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the duration field from a sequencer event structure.
|
||||
* @param evt Sequencer event structure
|
||||
* @return Note duration value (DOCME units?)
|
||||
*
|
||||
* Used by the #FLUID_SEQ_NOTE event type.
|
||||
*/
|
||||
unsigned int fluid_event_get_duration(fluid_event_t* evt)
|
||||
{
|
||||
return evt->duration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the MIDI bank field from a sequencer event structure.
|
||||
* @param evt Sequencer event structure
|
||||
* @return MIDI bank number (0-16383)
|
||||
*
|
||||
* Used by the #FLUID_SEQ_BANKSELECT and #FLUID_SEQ_PROGRAMSELECT
|
||||
* event types.
|
||||
*/
|
||||
short fluid_event_get_bank(fluid_event_t* evt)
|
||||
{
|
||||
return evt->control;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the pitch field from a sequencer event structure.
|
||||
* @param evt Sequencer event structure
|
||||
* @return MIDI pitch bend pitch value (0-16383, 8192 = no bend)
|
||||
*
|
||||
* Used by the #FLUID_SEQ_PITCHBEND event type.
|
||||
*/
|
||||
int fluid_event_get_pitch(fluid_event_t* evt)
|
||||
{
|
||||
return evt->pitch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the MIDI program field from a sequencer event structure.
|
||||
* @param evt Sequencer event structure
|
||||
* @return MIDI program number (0-127)
|
||||
*
|
||||
* Used by the #FLUID_SEQ_PROGRAMCHANGE and #FLUID_SEQ_PROGRAMSELECT
|
||||
* event types.
|
||||
*/
|
||||
short
|
||||
fluid_event_get_program(fluid_event_t* evt)
|
||||
{
|
||||
return evt->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
|
|
|
@ -89,9 +89,10 @@ fluid_gen_info_t fluid_gen_info[] = {
|
|||
};
|
||||
|
||||
|
||||
/* fluid_gen_set_default_values
|
||||
*
|
||||
* Set an array of generators to their initial value
|
||||
/**
|
||||
* Set an array of generators to their default values.
|
||||
* @param gen Array of generators (should be #GEN_LAST in size).
|
||||
* @return Always returns 0
|
||||
*/
|
||||
int
|
||||
fluid_gen_set_default_values(fluid_gen_t* gen)
|
||||
|
|
|
@ -151,7 +151,14 @@ void fluid_midi_driver_settings(fluid_settings_t* settings)
|
|||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a new MIDI driver instance.
|
||||
* @param settings Settings used to configure new MIDI driver.
|
||||
* @param handler MIDI handler callback (for example: fluid_midi_router_handle_midi_event()
|
||||
* for MIDI router)
|
||||
* @param event_handler_data Caller defined data to pass to 'handler'
|
||||
* @return New MIDI driver instance or NULL on error
|
||||
*/
|
||||
fluid_midi_driver_t* new_fluid_midi_driver(fluid_settings_t* settings, handle_midi_event_func_t handler, void* event_handler_data)
|
||||
{
|
||||
int i;
|
||||
|
@ -171,6 +178,10 @@ fluid_midi_driver_t* new_fluid_midi_driver(fluid_settings_t* settings, handle_mi
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a MIDI driver instance.
|
||||
* @param driver MIDI driver to delete
|
||||
*/
|
||||
void delete_fluid_midi_driver(fluid_midi_driver_t* driver)
|
||||
{
|
||||
int i;
|
||||
|
|
|
@ -55,8 +55,12 @@ static int remains_80e0[] = {
|
|||
*
|
||||
* MIDIFILE
|
||||
*/
|
||||
/*
|
||||
* new_fluid_midi_file
|
||||
|
||||
/**
|
||||
* Open a MIDI file and return a new MIDI file handle.
|
||||
* @internal
|
||||
* @param filename Path of file to open.
|
||||
* @return New MIDI file handle or NULL on error.
|
||||
*/
|
||||
fluid_midi_file* new_fluid_midi_file(char* filename)
|
||||
{
|
||||
|
@ -86,8 +90,10 @@ fluid_midi_file* new_fluid_midi_file(char* filename)
|
|||
return mf;
|
||||
}
|
||||
|
||||
/*
|
||||
* delete_fluid_midi_file
|
||||
/**
|
||||
* Delete a MIDI file handle.
|
||||
* @internal
|
||||
* @param mf MIDI file handle to close and free.
|
||||
*/
|
||||
void delete_fluid_midi_file(fluid_midi_file* mf)
|
||||
{
|
||||
|
@ -102,7 +108,7 @@ void delete_fluid_midi_file(fluid_midi_file* mf)
|
|||
}
|
||||
|
||||
/*
|
||||
* fluid_midi_file_getc
|
||||
* Get the next byte in a MIDI file.
|
||||
*/
|
||||
int fluid_midi_file_getc(fluid_midi_file* mf)
|
||||
{
|
||||
|
@ -660,8 +666,9 @@ int fluid_midi_file_get_division(fluid_midi_file* midifile)
|
|||
* fluid_track_t
|
||||
*/
|
||||
|
||||
/*
|
||||
* new_fluid_midi_event
|
||||
/**
|
||||
* Create a MIDI event structure.
|
||||
* @return New MIDI event structure or NULL when out of memory.
|
||||
*/
|
||||
fluid_midi_event_t* new_fluid_midi_event()
|
||||
{
|
||||
|
@ -680,8 +687,10 @@ fluid_midi_event_t* new_fluid_midi_event()
|
|||
return evt;
|
||||
}
|
||||
|
||||
/*
|
||||
* delete_fluid_midi_event
|
||||
/**
|
||||
* Delete MIDI event structure.
|
||||
* @param evt MIDI event structure
|
||||
* @return Always returns 0
|
||||
*/
|
||||
int delete_fluid_midi_event(fluid_midi_event_t* evt)
|
||||
{
|
||||
|
@ -696,16 +705,23 @@ int delete_fluid_midi_event(fluid_midi_event_t* evt)
|
|||
return FLUID_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* fluid_midi_event_get_type
|
||||
/**
|
||||
* Get the event type field of a MIDI event structure.
|
||||
* DOCME - Event type enum appears to be internal (fluid_midi.h)
|
||||
* @param evt MIDI event structure
|
||||
* @return Event type field
|
||||
*/
|
||||
int fluid_midi_event_get_type(fluid_midi_event_t* evt)
|
||||
{
|
||||
return evt->type;
|
||||
}
|
||||
|
||||
/*
|
||||
* fluid_midi_event_set_type
|
||||
/**
|
||||
* Set the event type field of a MIDI event structure.
|
||||
* DOCME - Event type enum appears to be internal (fluid_midi.h)
|
||||
* @param evt MIDI event structure
|
||||
* @param type Event type field
|
||||
* @return Always returns 0
|
||||
*/
|
||||
int fluid_midi_event_set_type(fluid_midi_event_t* evt, int type)
|
||||
{
|
||||
|
@ -713,16 +729,21 @@ int fluid_midi_event_set_type(fluid_midi_event_t* evt, int type)
|
|||
return FLUID_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* fluid_midi_event_get_channel
|
||||
/**
|
||||
* Get the channel field of a MIDI event structure.
|
||||
* @param evt MIDI event structure
|
||||
* @return Channel field
|
||||
*/
|
||||
int fluid_midi_event_get_channel(fluid_midi_event_t* evt)
|
||||
{
|
||||
return evt->channel;
|
||||
}
|
||||
|
||||
/*
|
||||
* fluid_midi_event_set_channel
|
||||
/**
|
||||
* Set the channel field of a MIDI event structure.
|
||||
* @param evt MIDI event structure
|
||||
* @param chan MIDI channel field
|
||||
* @return Always returns 0
|
||||
*/
|
||||
int fluid_midi_event_set_channel(fluid_midi_event_t* evt, int chan)
|
||||
{
|
||||
|
@ -730,16 +751,21 @@ int fluid_midi_event_set_channel(fluid_midi_event_t* evt, int chan)
|
|||
return FLUID_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* fluid_midi_event_get_key
|
||||
/**
|
||||
* Get the key field of a MIDI event structure.
|
||||
* @param evt MIDI event structure
|
||||
* @return MIDI note number (0-127)
|
||||
*/
|
||||
int fluid_midi_event_get_key(fluid_midi_event_t* evt)
|
||||
{
|
||||
return evt->param1;
|
||||
}
|
||||
|
||||
/*
|
||||
* fluid_midi_event_set_key
|
||||
/**
|
||||
* Set the key field of a MIDI event structure.
|
||||
* @param evt MIDI event structure
|
||||
* @param v MIDI note number (0-127)
|
||||
* @return Always returns 0
|
||||
*/
|
||||
int fluid_midi_event_set_key(fluid_midi_event_t* evt, int v)
|
||||
{
|
||||
|
@ -747,16 +773,21 @@ int fluid_midi_event_set_key(fluid_midi_event_t* evt, int v)
|
|||
return FLUID_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* fluid_midi_event_get_velocity
|
||||
/**
|
||||
* Get the velocity field of a MIDI event structure.
|
||||
* @param evt MIDI event structure
|
||||
* @return MIDI velocity number (0-127)
|
||||
*/
|
||||
int fluid_midi_event_get_velocity(fluid_midi_event_t* evt)
|
||||
{
|
||||
return evt->param2;
|
||||
}
|
||||
|
||||
/*
|
||||
* fluid_midi_event_set_velocity
|
||||
/**
|
||||
* Set the velocity field of a MIDI event structure.
|
||||
* @param evt MIDI event structure
|
||||
* @param v MIDI velocity value
|
||||
* @return Always returns 0
|
||||
*/
|
||||
int fluid_midi_event_set_velocity(fluid_midi_event_t* evt, int v)
|
||||
{
|
||||
|
@ -764,16 +795,21 @@ int fluid_midi_event_set_velocity(fluid_midi_event_t* evt, int v)
|
|||
return FLUID_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* fluid_midi_event_get_control
|
||||
/**
|
||||
* Get the control number of a MIDI event structure.
|
||||
* @param evt MIDI event structure
|
||||
* @return MIDI control number
|
||||
*/
|
||||
int fluid_midi_event_get_control(fluid_midi_event_t* evt)
|
||||
{
|
||||
return evt->param1;
|
||||
}
|
||||
|
||||
/*
|
||||
* fluid_midi_event_set_control
|
||||
/**
|
||||
* Set the control field of a MIDI event structure.
|
||||
* @param evt MIDI event structure
|
||||
* @param v MIDI control number
|
||||
* @return Always returns 0
|
||||
*/
|
||||
int fluid_midi_event_set_control(fluid_midi_event_t* evt, int v)
|
||||
{
|
||||
|
@ -781,16 +817,21 @@ int fluid_midi_event_set_control(fluid_midi_event_t* evt, int v)
|
|||
return FLUID_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* fluid_midi_event_get_value
|
||||
/**
|
||||
* Get the value field from a MIDI event structure.
|
||||
* @param evt MIDI event structure
|
||||
* @return Value field
|
||||
*/
|
||||
int fluid_midi_event_get_value(fluid_midi_event_t* evt)
|
||||
{
|
||||
return evt->param2;
|
||||
}
|
||||
|
||||
/*
|
||||
* fluid_midi_event_set_value
|
||||
/**
|
||||
* Set the value field of a MIDI event structure.
|
||||
* @param evt MIDI event structure
|
||||
* @param v Value to assign
|
||||
* @return Always returns 0
|
||||
*/
|
||||
int fluid_midi_event_set_value(fluid_midi_event_t* evt, int v)
|
||||
{
|
||||
|
@ -798,22 +839,44 @@ int fluid_midi_event_set_value(fluid_midi_event_t* evt, int v)
|
|||
return FLUID_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the program field of a MIDI event structure.
|
||||
* @param evt MIDI event structure
|
||||
* @return MIDI program number (0-127)
|
||||
*/
|
||||
int fluid_midi_event_get_program(fluid_midi_event_t* evt)
|
||||
{
|
||||
return evt->param1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the program field of a MIDI event structure.
|
||||
* @param evt MIDI event structure
|
||||
* @param val MIDI program number (0-127)
|
||||
* @return Always returns 0
|
||||
*/
|
||||
int fluid_midi_event_set_program(fluid_midi_event_t* evt, int val)
|
||||
{
|
||||
evt->param1 = val;
|
||||
return FLUID_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the pitch field of a MIDI event structure.
|
||||
* @param evt MIDI event structure
|
||||
* @return Pitch value (DOCME units?)
|
||||
*/
|
||||
int fluid_midi_event_get_pitch(fluid_midi_event_t* evt)
|
||||
{
|
||||
return evt->param1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the pitch field of a MIDI event structure.
|
||||
* @param evt MIDI event structure
|
||||
* @param val Pitch value (DOCME units?)
|
||||
* @return Always returns 0
|
||||
*/
|
||||
int fluid_midi_event_set_pitch(fluid_midi_event_t* evt, int val)
|
||||
{
|
||||
evt->param1 = val;
|
||||
|
@ -1046,8 +1109,11 @@ fluid_track_send_events(fluid_track_t* track,
|
|||
*
|
||||
* fluid_player
|
||||
*/
|
||||
/*
|
||||
* new_fluid_player
|
||||
|
||||
/**
|
||||
* Create a new MIDI player.
|
||||
* @param synth Fluid synthesizer instance to create player for
|
||||
* @return New MIDI player instance or NULL on error (out of memory)
|
||||
*/
|
||||
fluid_player_t* new_fluid_player(fluid_synth_t* synth)
|
||||
{
|
||||
|
@ -1075,8 +1141,10 @@ fluid_player_t* new_fluid_player(fluid_synth_t* synth)
|
|||
return player;
|
||||
}
|
||||
|
||||
/*
|
||||
* delete_fluid_player
|
||||
/**
|
||||
* Delete a MIDI player instance.
|
||||
* @param player MIDI player instance
|
||||
* @return Always returns 0
|
||||
*/
|
||||
int delete_fluid_player(fluid_player_t* player)
|
||||
{
|
||||
|
@ -1240,8 +1308,10 @@ int fluid_player_callback(void* data, unsigned int msec)
|
|||
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)
|
||||
{
|
||||
|
@ -1263,8 +1333,10 @@ int fluid_player_play(fluid_player_t* player)
|
|||
return FLUID_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* fluid_player_stop
|
||||
/**
|
||||
* Stops a MIDI player.
|
||||
* @param player MIDI player instance
|
||||
* @return Always returns 0
|
||||
*/
|
||||
int fluid_player_stop(fluid_player_t* player)
|
||||
{
|
||||
|
@ -1276,8 +1348,13 @@ int fluid_player_stop(fluid_player_t* player)
|
|||
return FLUID_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* fluid_player_set_loop
|
||||
/* FIXME - Looping seems to not actually be implemented? */
|
||||
|
||||
/**
|
||||
* Enable looping of a MIDI player (DOCME - Does this actually work?)
|
||||
* @param player MIDI player instance
|
||||
* @param loop Value for looping (DOCME - What would this value be, boolean/time index?)
|
||||
* @return Always returns 0
|
||||
*/
|
||||
int fluid_player_set_loop(fluid_player_t* player, int loop)
|
||||
{
|
||||
|
@ -1285,8 +1362,12 @@ int fluid_player_set_loop(fluid_player_t* player, int loop)
|
|||
return FLUID_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* fluid_player_set_midi_tempo
|
||||
/**
|
||||
* Set the tempo of a MIDI player.
|
||||
* @param player MIDI player instance
|
||||
* @param tempo Tempo to set playback speed to (DOCME - Units?)
|
||||
* @return Always returns 0
|
||||
*
|
||||
*/
|
||||
int fluid_player_set_midi_tempo(fluid_player_t* player, int tempo)
|
||||
{
|
||||
|
@ -1301,16 +1382,22 @@ int fluid_player_set_midi_tempo(fluid_player_t* player, int tempo)
|
|||
return FLUID_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* fluid_player_set_bpm
|
||||
/**
|
||||
* Set the tempo of a MIDI player in beats per minute.
|
||||
* @param player MIDI player instance
|
||||
* @param bpm Tempo in beats per minute
|
||||
* @return Always returns 0
|
||||
*/
|
||||
int fluid_player_set_bpm(fluid_player_t* player, int bpm)
|
||||
{
|
||||
return fluid_player_set_midi_tempo(player, (int)((double) 60 * 1e6 / bpm));
|
||||
}
|
||||
|
||||
/*
|
||||
* fluid_player_join
|
||||
/**
|
||||
* Wait for a MIDI player to terminate (when done playing).
|
||||
* @param player MIDI player instance
|
||||
* @return 0 on success, -1 otherwise
|
||||
*
|
||||
*/
|
||||
int fluid_player_join(fluid_player_t* player)
|
||||
{
|
||||
|
@ -1525,5 +1612,3 @@ int fluid_midi_send_event(fluid_synth_t* synth, fluid_player_t* player, fluid_mi
|
|||
}
|
||||
return FLUID_OK;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -26,14 +26,22 @@
|
|||
#include "fluid_synth.h"
|
||||
#include "fluid_io.h"
|
||||
|
||||
/*
|
||||
* new_fluid_midi_router
|
||||
/**
|
||||
* Create a new midi router.
|
||||
* @param settings Settings used to configure MIDI router
|
||||
* @param handler MIDI event callback
|
||||
* @param event_handler_data Caller defined data pointer which gets passed to 'handler'
|
||||
* @return New MIDI router instance or NULL on error
|
||||
*
|
||||
* A midi handler connects to a midi input
|
||||
* device and forwards incoming midi events to the synthesizer.
|
||||
*/
|
||||
fluid_midi_router_t*
|
||||
new_fluid_midi_router(fluid_settings_t* settings, handle_midi_event_func_t handler, void* event_handler_data)
|
||||
{
|
||||
fluid_midi_router_t* router=NULL;
|
||||
fluid_midi_router_rule_t* rule=NULL;;
|
||||
fluid_midi_router_rule_t* rule=NULL;
|
||||
|
||||
/* create the router */
|
||||
router = FLUID_NEW(fluid_midi_router_t); if (router == NULL){
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
|
@ -68,8 +76,10 @@ new_fluid_midi_router(fluid_settings_t* settings, handle_midi_event_func_t handl
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* delete_fluid_midi_router
|
||||
/**
|
||||
* Delete a MIDI router instance.
|
||||
* @param router MIDI router to delete
|
||||
* @return Always returns 0
|
||||
*/
|
||||
int
|
||||
delete_fluid_midi_router(fluid_midi_router_t* router)
|
||||
|
@ -239,8 +249,12 @@ int fluid_midi_router_end(fluid_midi_router_t* router){
|
|||
return FLUID_FAILED;
|
||||
};
|
||||
|
||||
/*
|
||||
* fluid_midi_router_send_event
|
||||
/**
|
||||
* Handle a MIDI event through a MIDI router instance.
|
||||
* @param data MIDI router instance #fluid_midi_router_t (DOCME why is it a void *?)
|
||||
* @param event MIDI event to handle
|
||||
* @return 0 on success, -1 otherwise
|
||||
*
|
||||
* Purpose: The midi router is called for each event, that is received
|
||||
* via the 'physical' midi input. Each event can trigger an arbitrary number
|
||||
* of generated events.
|
||||
|
@ -786,11 +800,15 @@ void fluid_midi_router_free_unused_rules(fluid_midi_router_t* router)
|
|||
};
|
||||
};
|
||||
|
||||
/* Purpose:
|
||||
* This function demonstrates, how to access incoming MIDI messages.
|
||||
* It prints a message to stdout (which can be used to hook up an external user interface),
|
||||
* and hands the event on to the MIDI router.
|
||||
* It is not a part of the MIDI router, but an added link in the MIDI chain.
|
||||
/**
|
||||
* MIDI event callback function to display event information to stdout
|
||||
* @param data MIDI router instance
|
||||
* @param event MIDI event data
|
||||
* @return 0 on success, -1 otherwise
|
||||
*
|
||||
* An implementation of the #handle_midi_event_func_t function type, used for
|
||||
* displaying MIDI event information between the MIDI driver and router to
|
||||
* stdout. Useful for adding into a MIDI router chain for debugging MIDI events.
|
||||
*/
|
||||
int fluid_midi_dump_prerouter(void* data, fluid_midi_event_t* event)
|
||||
{
|
||||
|
@ -798,35 +816,27 @@ int fluid_midi_dump_prerouter(void* data, fluid_midi_event_t* event)
|
|||
case NOTE_ON:
|
||||
fprintf(stdout, "event_pre_noteon %i %i %i\n",
|
||||
event->channel, event->param1, event->param2);
|
||||
fflush(stdout);
|
||||
break;
|
||||
case NOTE_OFF:
|
||||
fprintf(stdout, "event_pre_noteoff %i %i %i\n",
|
||||
event->channel, event->param1, event->param2);
|
||||
fflush(stdout);
|
||||
break;
|
||||
break;
|
||||
case CONTROL_CHANGE:
|
||||
fprintf(stdout, "event_pre_cc %i %i %i\n",
|
||||
event->channel, event->param1, event->param2);
|
||||
fflush(stdout);
|
||||
break;
|
||||
case PROGRAM_CHANGE:
|
||||
fprintf(stdout, "event_pre_prog %i %i\n", event->channel, event->param1);
|
||||
fflush(stdout);
|
||||
break;
|
||||
case PITCH_BEND:
|
||||
fprintf(stdout, "event_pre_pitch %i %i\n", event->channel, event->param1);
|
||||
fflush(stdout);
|
||||
break;
|
||||
case CHANNEL_PRESSURE:
|
||||
fprintf(stdout, "event_pre_cpress %i %i\n", event->channel, event->param1);
|
||||
fflush(stdout);
|
||||
break;
|
||||
case KEY_PRESSURE:
|
||||
fprintf(stdout, "event_pre_kpress %i %i %i\n",
|
||||
event->channel, event->param1, event->param2);
|
||||
fflush(stdout);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -834,11 +844,15 @@ int fluid_midi_dump_prerouter(void* data, fluid_midi_event_t* event)
|
|||
return fluid_midi_router_handle_midi_event((fluid_midi_router_t*) data, event);
|
||||
};
|
||||
|
||||
/* Purpose:
|
||||
* This function demonstrates, how to access MIDI messages going from the MIDI
|
||||
* router to the synth.
|
||||
* Again, it prints a message to stdout and hands the event on to the synth.
|
||||
* It is not a part of the MIDI router, but an added link in the MIDI chain.
|
||||
/**
|
||||
* MIDI event callback function to display event information to stdout
|
||||
* @param data MIDI router instance
|
||||
* @param event MIDI event data
|
||||
* @return 0 on success, -1 otherwise
|
||||
*
|
||||
* An implementation of the #handle_midi_event_func_t function type, used for
|
||||
* displaying MIDI event information between the MIDI driver and router to
|
||||
* stdout. Useful for adding into a MIDI router chain for debugging MIDI events.
|
||||
*/
|
||||
int fluid_midi_dump_postrouter(void* data, fluid_midi_event_t* event)
|
||||
{
|
||||
|
@ -846,18 +860,14 @@ int fluid_midi_dump_postrouter(void* data, fluid_midi_event_t* event)
|
|||
case NOTE_ON:
|
||||
fprintf(stdout, "event_post_noteon %i %i %i\n",
|
||||
event->channel, event->param1, event->param2);
|
||||
fflush(stdout);
|
||||
break;
|
||||
case NOTE_OFF:
|
||||
fprintf(stdout, "event_post_noteoff %i %i %i\n",
|
||||
event->channel, event->param1, event->param2);
|
||||
fflush(stdout);
|
||||
break;
|
||||
break;
|
||||
case CONTROL_CHANGE:
|
||||
fprintf(stdout, "event_post_cc %i %i %i\n",
|
||||
event->channel, event->param1, event->param2);
|
||||
fflush(stdout);
|
||||
break;
|
||||
case PROGRAM_CHANGE:
|
||||
fprintf(stdout, "event_post_prog %i %i\n", event->channel, event->param1);
|
||||
|
|
|
@ -624,12 +624,8 @@ fluid_oss_audio_run2(void* d)
|
|||
|
||||
(*dev->callback)(dev->data, buffer_size, 0, NULL, 2, dev->buffers);
|
||||
|
||||
for (i = 0, k = 0; i < buffer_size; i++) {
|
||||
/* fluid_clip(left[i], -1.0f, 1.0f); */
|
||||
/* fluid_clip(right[i], -1.0f, 1.0f); */
|
||||
buffer[k++] = (short) (left[i] * 32767.0f);
|
||||
buffer[k++] = (short) (right[i] * 32767.0f);
|
||||
}
|
||||
fluid_synth_dither_s16 (dev->data, buffer_size, left, right,
|
||||
buffer, 0, 2, buffer, 1, 2);
|
||||
|
||||
write(dev->dspfd, buffer, dev->buffer_byte_size);
|
||||
}
|
||||
|
|
|
@ -19,18 +19,21 @@
|
|||
*/
|
||||
|
||||
#include "fluidsynth_priv.h"
|
||||
#include "fluid_settings.h"
|
||||
#include "fluid_sys.h"
|
||||
#include "fluid_hash.h"
|
||||
#include "fluid_strtok.h"
|
||||
#include "fluid_synth.h"
|
||||
#include "fluid_cmd.h"
|
||||
#include "fluid_adriver.h"
|
||||
#include "fluid_mdriver.h"
|
||||
#include "fluid_settings.h"
|
||||
|
||||
/* maximum allowed components of a settings variable (separated by '.') */
|
||||
#define MAX_SETTINGS_TOKENS 8 /* currently only a max of 3 are used */
|
||||
#define MAX_SETTINGS_LABEL 256 /* max length of a settings variable label */
|
||||
|
||||
static void fluid_settings_init(fluid_settings_t* settings);
|
||||
static void fluid_settings_hash_delete(void* value, int type);
|
||||
static int fluid_settings_tokenize(char* s, char* buf, char** ptr);
|
||||
static int fluid_settings_tokenize(char* s, char *buf, char** ptr);
|
||||
|
||||
|
||||
typedef struct {
|
||||
|
@ -196,22 +199,31 @@ void fluid_settings_init(fluid_settings_t* settings)
|
|||
fluid_midi_driver_settings(settings);
|
||||
}
|
||||
|
||||
static fluid_strtok_t* fluid_settings_strtok = NULL;
|
||||
|
||||
int fluid_settings_tokenize(char* s, char* buf, char** ptr)
|
||||
static int fluid_settings_tokenize(char* s, char *buf, char** ptr)
|
||||
{
|
||||
char *tokstr, *tok;
|
||||
int n = 0;
|
||||
|
||||
FLUID_STRCPY(buf, s);
|
||||
|
||||
if (fluid_settings_strtok == NULL) {
|
||||
fluid_settings_strtok = new_fluid_strtok(buf, ".");
|
||||
} else {
|
||||
fluid_strtok_set(fluid_settings_strtok, buf, ".");
|
||||
if (strlen (s) > MAX_SETTINGS_LABEL)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Setting variable name exceeded max length of %d chars",
|
||||
MAX_SETTINGS_LABEL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (fluid_strtok_has_more(fluid_settings_strtok)) {
|
||||
ptr[n++] = fluid_strtok_next_token(fluid_settings_strtok);
|
||||
FLUID_STRCPY(buf, s); /* copy string to buffer, since it gets modified */
|
||||
tokstr = buf;
|
||||
|
||||
while ((tok = fluid_strtok (&tokstr, ".")))
|
||||
{
|
||||
if (n > MAX_SETTINGS_TOKENS)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Setting variable name exceeded max token count of %d",
|
||||
MAX_SETTINGS_TOKENS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ptr[n++] = tok;
|
||||
}
|
||||
|
||||
return n;
|
||||
|
@ -251,7 +263,6 @@ static int fluid_settings_get(fluid_settings_t* settings,
|
|||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/** returns 1 if the value has been set, zero otherwise */
|
||||
static int fluid_settings_set(fluid_settings_t* settings,
|
||||
char** name, int len,
|
||||
|
@ -288,15 +299,15 @@ static int fluid_settings_set(fluid_settings_t* settings,
|
|||
return 1;
|
||||
}
|
||||
|
||||
/** returns 1 if the value has been resgister correctly, 0
|
||||
/** returns 1 if the value has been registered correctly, 0
|
||||
otherwise */
|
||||
int fluid_settings_register_str(fluid_settings_t* settings, char* name, char* def, int hints,
|
||||
fluid_str_update_t fun, void* data)
|
||||
{
|
||||
int type;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
fluid_str_setting_t* setting;
|
||||
|
||||
|
@ -330,8 +341,8 @@ int fluid_settings_register_num(fluid_settings_t* settings, char* name, double d
|
|||
{
|
||||
int type;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
@ -370,8 +381,8 @@ int fluid_settings_register_int(fluid_settings_t* settings, char* name, int def,
|
|||
{
|
||||
int type;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
@ -402,13 +413,12 @@ int fluid_settings_register_int(fluid_settings_t* settings, char* name, int def,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
int fluid_settings_get_type(fluid_settings_t* settings, char* name)
|
||||
{
|
||||
int type;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
@ -416,13 +426,12 @@ int fluid_settings_get_type(fluid_settings_t* settings, char* name)
|
|||
return (fluid_settings_get(settings, tokens, ntokens, &value, &type))? type : FLUID_NO_TYPE;
|
||||
}
|
||||
|
||||
|
||||
int fluid_settings_get_hints(fluid_settings_t* settings, char* name)
|
||||
{
|
||||
int type;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
@ -446,8 +455,8 @@ int fluid_settings_is_realtime(fluid_settings_t* settings, char* name)
|
|||
{
|
||||
int type;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
@ -468,11 +477,10 @@ int fluid_settings_is_realtime(fluid_settings_t* settings, char* name)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
int fluid_settings_setstr(fluid_settings_t* settings, char* name, char* str)
|
||||
{
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
int type;
|
||||
void* value;
|
||||
|
@ -511,8 +519,8 @@ int fluid_settings_getstr(fluid_settings_t* settings, char* name, char** str)
|
|||
{
|
||||
int type;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
@ -527,13 +535,12 @@ int fluid_settings_getstr(fluid_settings_t* settings, char* name, char** str)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int fluid_settings_str_equal(fluid_settings_t* settings, char* name, char* s)
|
||||
{
|
||||
int type;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
@ -546,14 +553,13 @@ int fluid_settings_str_equal(fluid_settings_t* settings, char* name, char* s)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
fluid_settings_getstr_default(fluid_settings_t* settings, char* name)
|
||||
{
|
||||
int type;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
@ -571,8 +577,8 @@ int fluid_settings_add_option(fluid_settings_t* settings, char* name, char* s)
|
|||
{
|
||||
int type;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
@ -592,8 +598,8 @@ int fluid_settings_remove_option(fluid_settings_t* settings, char* name, char* s
|
|||
{
|
||||
int type;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
@ -620,14 +626,13 @@ int fluid_settings_remove_option(fluid_settings_t* settings, char* name, char* s
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
int fluid_settings_setnum(fluid_settings_t* settings, char* name, double val)
|
||||
{
|
||||
int type;
|
||||
void* value;
|
||||
fluid_num_setting_t* setting;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
@ -667,8 +672,8 @@ int fluid_settings_getnum(fluid_settings_t* settings, char* name, double* val)
|
|||
{
|
||||
int type;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
@ -687,8 +692,8 @@ void fluid_settings_getnum_range(fluid_settings_t* settings, char* name, double*
|
|||
{
|
||||
int type;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
@ -706,8 +711,8 @@ fluid_settings_getnum_default(fluid_settings_t* settings, char* name)
|
|||
{
|
||||
int type;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
@ -727,8 +732,8 @@ int fluid_settings_setint(fluid_settings_t* settings, char* name, int val)
|
|||
int type;
|
||||
void* value;
|
||||
fluid_int_setting_t* setting;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
@ -768,8 +773,8 @@ int fluid_settings_getint(fluid_settings_t* settings, char* name, int* val)
|
|||
{
|
||||
int type;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
@ -788,8 +793,8 @@ void fluid_settings_getint_range(fluid_settings_t* settings, char* name, int* mi
|
|||
{
|
||||
int type;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
@ -807,8 +812,8 @@ fluid_settings_getint_default(fluid_settings_t* settings, char* name)
|
|||
{
|
||||
int type;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
@ -830,8 +835,8 @@ void fluid_settings_foreach_option(fluid_settings_t* settings, char* name, void*
|
|||
{
|
||||
int type;
|
||||
void* value;
|
||||
char buf[1024];
|
||||
char* tokens[16];
|
||||
char* tokens[MAX_SETTINGS_TOKENS];
|
||||
char buf[MAX_SETTINGS_LABEL+1];
|
||||
int ntokens;
|
||||
|
||||
if (!func) {
|
||||
|
|
|
@ -601,6 +601,14 @@ delete_fluid_synth(fluid_synth_t* synth)
|
|||
|
||||
synth->state = FLUID_SYNTH_STOPPED;
|
||||
|
||||
/* turn off all voices, needed to unload SoundFont data */
|
||||
if (synth->voice != NULL) {
|
||||
for (i = 0; i < synth->nvoice; i++) {
|
||||
if (synth->voice[i] && fluid_voice_is_playing (synth->voice[i]))
|
||||
fluid_voice_off (synth->voice[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* delete all the SoundFonts */
|
||||
for (list = synth->sfont; list; list = fluid_list_next(list)) {
|
||||
sfont = (fluid_sfont_t*) fluid_list_get(list);
|
||||
|
|
|
@ -63,8 +63,12 @@ int fluid_debug(int level, char * fmt, ...)
|
|||
}
|
||||
#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_set_log_function(int level, fluid_log_function_t fun, void* data)
|
||||
|
@ -79,8 +83,11 @@ fluid_set_log_function(int level, fluid_log_function_t fun, void* data)
|
|||
return old;
|
||||
}
|
||||
|
||||
/*
|
||||
* fluid_default_log_function
|
||||
/**
|
||||
* Default log function which prints to the stderr.
|
||||
* @param level Log level
|
||||
* @param message Log message
|
||||
* @param data User supplied data (not used)
|
||||
*/
|
||||
void
|
||||
fluid_default_log_function(int level, char* message, void* data)
|
||||
|
@ -154,8 +161,12 @@ fluid_log_config(void)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
fluid_log(int level, char* fmt, ...)
|
||||
|
@ -176,6 +187,75 @@ fluid_log(int level, char* fmt, ...)
|
|||
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
|
||||
|
|
|
@ -43,6 +43,13 @@ void fluid_sys_config(void);
|
|||
void fluid_log_config(void);
|
||||
void fluid_time_config(void);
|
||||
|
||||
|
||||
/*
|
||||
* Utility functions
|
||||
*/
|
||||
char *fluid_strtok (char **str, char *delim);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
Additional debugging system, separate from the log system. This
|
||||
|
@ -288,4 +295,3 @@ extern fluid_profile_data_t fluid_profile_data[];
|
|||
unsigned int fluid_check_fpe_i386(char * explanation_in_case_of_fpe);
|
||||
|
||||
#endif /* _FLUID_SYS_H */
|
||||
|
||||
|
|
|
@ -1718,9 +1718,10 @@ fluid_voice_off(fluid_voice_t* voice)
|
|||
voice->status = FLUID_VOICE_OFF;
|
||||
|
||||
/* Decrement the reference count of the sample. */
|
||||
fluid_sample_decr_ref(voice->sample);
|
||||
|
||||
voice->sample = NULL;
|
||||
if (voice->sample) {
|
||||
fluid_sample_decr_ref(voice->sample);
|
||||
voice->sample = NULL;
|
||||
}
|
||||
|
||||
return FLUID_OK;
|
||||
}
|
||||
|
|
|
@ -458,13 +458,16 @@ int main(int argc, char** argv)
|
|||
fluid_source(cmd_handler, buf);
|
||||
}
|
||||
|
||||
/* load the soundfonts */
|
||||
/* load the soundfonts (check that all non options are SoundFont or MIDI files) */
|
||||
for (i = arg1; i < argc; i++) {
|
||||
if ((argv[i][0] != '-') && fluid_is_soundfont(argv[i])) {
|
||||
if (fluid_synth_sfload(synth, argv[i], 1) == -1) {
|
||||
if (fluid_is_soundfont(argv[i]))
|
||||
{
|
||||
if (fluid_synth_sfload(synth, argv[i], 1) == -1)
|
||||
fprintf(stderr, "Failed to load the SoundFont %s\n", argv[i]);
|
||||
}
|
||||
}
|
||||
else if (!fluid_is_midifile(argv[i]))
|
||||
fprintf (stderr, "Parameter '%s' not a SoundFont or MIDI file or error occurred identifying it.\n",
|
||||
argv[i]);
|
||||
}
|
||||
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
|
|
Loading…
Reference in a new issue