Merge pull request #291 from FluidSynth/file-callback

Add file callbacks to fluid_sfloader_t
This commit is contained in:
Tom M 2017-11-27 16:54:27 +01:00 committed by GitHub
commit c94f747c04
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 399 additions and 226 deletions

View file

@ -85,13 +85,13 @@ Changes in FluidSynth 2.0.0 concerning developers:
- remove fluid_synth_set_gen2(), fluid_synth_set_gen() now behaves as fluid_synth_set_gen2()
- remove struct fluid_mod_t from public API, use the getters and setters of mod.h instead
- remove struct _fluid_gen_t, fluid_gen_set_default_values() and enum fluid_gen_flags from public API
<br /><br />
- all public \c fluid_settings_* functions that return an integer which is not meant to be interpreted as bool consistently return either FLUID_OK or FLUID_FAILED
- all public delete_* functions return void and are safe when called with NULL
- the shell command handler was decoupled internally, as a consequence the param list of new_fluid_server() and new_fluid_cmd_handler() was adapted
- reverb: roomsize is now limited to an upper threshold of 1.0
- use unique device names for the "audio.portaudio.device" setting
<br /><br />
- add "synth.volenv" a setting for volume envelope processing
- add "midi.autoconnect" a setting for automatically connecting fluidsynth to available MIDI input ports
- add support for polyonic key pressure events, see fluid_event_key_pressure()
@ -99,6 +99,7 @@ Changes in FluidSynth 2.0.0 concerning developers:
- add individual reverb setters: fluid_synth_set_reverb_roomsize(), fluid_synth_set_reverb_damp(), fluid_synth_set_reverb_width(), fluid_synth_set_reverb_level()
- add individual chorus setters: fluid_synth_set_chorus_nr(), fluid_synth_set_chorus_level(), fluid_synth_set_chorus_speed(), fluid_synth_set_chorus_depth(), fluid_synth_set_chorus_type()
- introduce a separate data type for sequencer client IDs: #fluid_seq_id_t
- add file callback struct to _fluid_sfloader_t and expose new_fluid_defsfloader() to enable soundfont loading from memory ( see fluid_sfload_mem.c )
\section NewIn1_1_9 Whats new in 1.1.9?
@ -797,3 +798,8 @@ Example of an arpeggio generated using the MIDI sequencer API
\example fluidsynth_register_adriver.c
Example of how to register audio drivers using fluid_audio_driver_register() (advanced users only)
*/
/*!
\example fluidsynth_sfload_mem.c
Example of how read a soundfont from memory (advanced users only)
*/

View file

@ -1,4 +1,4 @@
/**
/*
* This is a simple C99 program that demonstrates the usage of fluid_audio_driver_register()
*
* There are 3 calls to fluid_audio_driver_register(), i.e. 3 iterations:

View file

@ -0,0 +1,95 @@
/*
* This is a C99 program that demonstrates how to load a soundfont from memory.
*
* It only gives a brief overview on how to achieve this with fluidsynth's API.
* Although it should compile, it's highly incomplete, as the details of it's
* implementation depend on the users needs.
*/
#include <stdio.h>
#include <string.h>
#include <fluidsynth.h>
void * my_open(const char * filename)
{
void* p;
if(filename[0] != '&')
{
return NULL;
}
scanf("&%p", &p);
return p;
}
int my_read(void *buf, int count, void * handle)
{
// not yet implemented
memset(buf, 0, count);
return FLUID_OK;
}
int my_seek(void * handle, long offset, int origin)
{
// NYI
return FLUID_OK;
}
int my_close(void * handle)
{
// NYI
return FLUID_OK;
}
long my_tell(void * handle)
{
// NYI
return 0;
}
fluid_file_callbacks_t my_cb =
{
.fopen = my_open,
.fread = my_read,
.fseek = my_seek,
.fclose = my_close,
.ftell = my_tell
};
int main()
{
int err = 0;
fluid_settings_t* settings = new_fluid_settings();
fluid_synth_t* synth = new_fluid_synth(settings);
fluid_sfloader_t* my_sfloader = new_fluid_defsfloader(settings);
my_sfloader->file_callbacks = &my_cb;
fluid_synth_add_sfloader(synth, my_sfloader);
char abused_filename[64];
const void* pointer_to_sf2_in_mem = 0x1234Beef; // some pointer to where the soundfont shall be loaded from
sprintf(abused_filename, "&%p", pointer_to_sf2_in_mem);
int id = fluid_synth_sfload(synth, abused_filename, 0);
/* now my_open() will be called with abused_filename and should have opened the memory region */
if(id == FLUID_FAILED)
{
puts("oops");
err = -1;
goto cleanup;
}
/*
* ~~~ Do your daily business here ~~~
*/
cleanup:
/* deleting the synth also deletes my_sfloader */
delete_fluid_synth(synth);
delete_fluid_settings(settings);
return err;
}

View file

@ -75,15 +75,17 @@ enum {
* SoundFont loader structure.
*/
struct _fluid_sfloader_t {
void* data; /**< User defined data pointer */
void* data; /**< User defined data pointer used by _fluid_sfloader_t::load() */
/**
* The free method should free the memory allocated for the loader in
/** Callback structure specifying file operations used during soundfont loading to allow custom loading, such as from memory */
const fluid_file_callbacks_t* file_callbacks;
/**
* The free method should free the memory allocated for this loader instance in
* addition to any private data.
* @param loader SoundFont loader
* @return Should return 0 if no error occured, non-zero otherwise
*/
int (*free)(fluid_sfloader_t* loader);
void (*free)(fluid_sfloader_t* loader);
/**
* Method to load an instrument file (does not actually need to be a real file name,
@ -96,6 +98,46 @@ struct _fluid_sfloader_t {
};
/**
* File callback structure to enable custom soundfont loading (e.g. from memory).
*/
struct _fluid_file_callbacks_t {
/**
* Opens the file or memory indicated by \c filename in binary read mode.
* \c filename matches the one provided during the fluid_synth_sfload() call.
*
* @return returns a file handle on success, NULL otherwise
*/
void * (* fopen )(const char * filename);
/**
* Reads \c count bytes to the specified buffer \c buf.
*
* @return returns #FLUID_OK if exactly \c count bytes were successfully read, else #FLUID_FAILED
*/
int (* fread )(void *buf, int count, void * handle);
/**
* Same purpose and behaviour as fseek.
*
* @param origin either \c SEEK_SET, \c SEEK_CUR or \c SEEK_END
*
* @return returns #FLUID_OK if the seek was successfully performed while not seeking beyond a buffer or file, #FLUID_FAILED otherwise */
int (* fseek )(void * handle, long offset, int origin);
/**
* Closes the handle and frees used ressources.
*
* @return returns #FLUID_OK on success, #FLUID_FAILED on error */
int (* fclose)(void * handle);
/** @return returns current file offset or #FLUID_FAILED on error */
long (* ftell )(void * handle);
};
FLUIDSYNTH_API fluid_sfloader_t* new_fluid_defsfloader(fluid_settings_t* settings);
/*
* Virtual SoundFont instance structure.
*/
struct _fluid_sfont_t {

View file

@ -58,7 +58,7 @@ typedef struct _fluid_ramsfont_t fluid_ramsfont_t; /**< RAM SoundFo
typedef struct _fluid_rampreset_t fluid_rampreset_t; /**< RAM SoundFont preset */
typedef struct _fluid_cmd_handler_t fluid_cmd_handler_t; /**< Shell Command Handler */
typedef struct _fluid_ladspa_fx_t fluid_ladspa_fx_t; /**< LADSPA effects instance */
typedef struct _fluid_file_callbacks_t fluid_file_callbacks_t; /**< Callback struct to perform custom file loading of soundfonts */
typedef int fluid_istream_t; /**< Input stream descriptor */
typedef int fluid_ostream_t; /**< Output stream descriptor */

File diff suppressed because it is too large Load diff

View file

@ -215,7 +215,7 @@ Gen_Unit;
/* functions */
void sfont_init_chunks (void);
void sfont_close (SFData * sf);
void sfont_close (SFData * sf, const fluid_file_callbacks_t* fcbs);
void sfont_free_zone (SFZone * zone);
int sfont_preset_compare_func (void* a, void* b);
@ -291,7 +291,7 @@ typedef struct _SFShdr
SFShdr;
/* functions */
SFData *sfload_file (const char * fname);
SFData *sfload_file (const char * fname, const fluid_file_callbacks_t* fcbs);
@ -319,9 +319,6 @@ enum
#define ErrnoEnd ErrWrite
int gerr (int ev, char * fmt, ...);
int safe_fread (void *buf, int count, FILE * fd);
int safe_fwrite (void *buf, int count, FILE * fd);
int safe_fseek (FILE * fd, long ofs, int whence);
/********************************************************************************/
@ -348,8 +345,7 @@ typedef struct _fluid_inst_zone_t fluid_inst_zone_t;
*/
fluid_sfloader_t* new_fluid_defsfloader(fluid_settings_t* settings);
int delete_fluid_defsfloader(fluid_sfloader_t* loader);
void delete_fluid_defsfloader(fluid_sfloader_t* loader);
fluid_sfont_t* fluid_defsfloader_load(fluid_sfloader_t* loader, const char* filename);
@ -391,12 +387,12 @@ struct _fluid_defsfont_t
fluid_defsfont_t* new_fluid_defsfont(fluid_settings_t* settings);
int delete_fluid_defsfont(fluid_defsfont_t* sfont);
int fluid_defsfont_load(fluid_defsfont_t* sfont, const char* file);
int fluid_defsfont_load(fluid_defsfont_t* sfont, const fluid_file_callbacks_t* file_callbacks, const char* file);
const char* fluid_defsfont_get_name(fluid_defsfont_t* sfont);
fluid_defpreset_t* fluid_defsfont_get_preset(fluid_defsfont_t* sfont, unsigned int bank, unsigned int prenum);
void fluid_defsfont_iteration_start(fluid_defsfont_t* sfont);
int fluid_defsfont_iteration_next(fluid_defsfont_t* sfont, fluid_preset_t* preset);
int fluid_defsfont_load_sampledata(fluid_defsfont_t* sfont);
int fluid_defsfont_load_sampledata(fluid_defsfont_t* sfont, const fluid_file_callbacks_t* file_callbacks);
int fluid_defsfont_add_sample(fluid_defsfont_t* sfont, fluid_sample_t* sample);
int fluid_defsfont_add_preset(fluid_defsfont_t* sfont, fluid_defpreset_t* preset);

View file

@ -3365,10 +3365,10 @@ fluid_synth_start_voice(fluid_synth_t* synth, fluid_voice_t* voice)
}
/**
* Add a SoundFont loader interface.
* Add a SoundFont loader to the synth. This function takes ownership of \c loader
* and frees it automatically upon \c synth destruction.
* @param synth FluidSynth instance
* @param loader Loader API structure, used directly and should remain allocated
* as long as the synth instance is used.
* @param loader Loader API structure
*
* SoundFont loaders are used to add custom instrument loading to FluidSynth.
* The caller supplied functions for loading files, allocating presets,
@ -3397,7 +3397,7 @@ fluid_synth_add_sfloader(fluid_synth_t* synth, fluid_sfloader_t* loader)
* stack. Presets are searched starting from the SoundFont on the
* top of the stack, working the way down the stack until a preset is found.
*
* @param synth SoundFont instance
* @param synth FluidSynth instance
* @param filename File to load
* @param reset_presets TRUE to re-assign presets for all MIDI channels
* @return SoundFont ID on success, FLUID_FAILED on error
@ -3470,7 +3470,7 @@ new_fluid_sfont_info (fluid_synth_t *synth, fluid_sfont_t *sfont)
/**
* Unload a SoundFont.
* @param synth SoundFont instance
* @param synth FluidSynth instance
* @param id ID of SoundFont to unload
* @param reset_presets TRUE to re-assign presets for all MIDI channels
* @return FLUID_OK on success, FLUID_FAILED on error
@ -3559,7 +3559,7 @@ fluid_synth_sfunload_callback(void* data, unsigned int msec)
/**
* Reload a SoundFont. The SoundFont retains its ID and index on the SoundFont stack.
* @param synth SoundFont instance
* @param synth FluidSynth instance
* @param id ID of SoundFont to reload
* @return SoundFont ID on success, FLUID_FAILED on error
*/

View file

@ -231,6 +231,7 @@ typedef FILE* fluid_file;
#define FLUID_FCLOSE(_f) fclose(_f)
#define FLUID_FREAD(_p,_s,_n,_f) fread(_p,_s,_n,_f)
#define FLUID_FSEEK(_f,_n,_set) fseek(_f,_n,_set)
#define FLUID_FTELL(_f) ftell(_f)
#define FLUID_MEMCPY(_dst,_src,_n) memcpy(_dst,_src,_n)
#define FLUID_MEMSET(_s,_c,_n) memset(_s,_c,_n)
#define FLUID_STRLEN(_s) strlen(_s)