Added public fluid_synth_get_channel_preset_info() function and fluid_preset_info_t structure.

Added shadow_preset field to fluid_channel_t which stores the last assigned preset (irrespective of queuing).
Presets now deleted under lock for shadow_preset functionality.
Marked fluid_synth_get_channel_preset() as deprecated.
This commit is contained in:
Josh Green 2009-11-16 07:43:43 +00:00
parent 50c88d392a
commit 7758f5a630
6 changed files with 100 additions and 3 deletions

View file

@ -229,6 +229,20 @@ struct _fluid_preset_t {
int (*notify)(fluid_preset_t* preset, int reason, int chan);
};
#define FLUID_PRESET_INFO_NAME_LENGTH 32 /**< Length of preset info name field (including zero terminator) */
/**
* Preset information structure.
* @since 1.1.1
*/
struct _fluid_preset_info_t
{
int assigned; /**< TRUE if a preset is assigned, FALSE otherwise */
int sfont_id; /**< ID of parent SoundFont */
int bank; /**< MIDI bank number (0-16383) */
int program; /**< MIDI program number (0-127) */
char name[FLUID_PRESET_INFO_NAME_LENGTH]; /**< Preset name */
};
/**
* Virtual SoundFont sample.

View file

@ -77,6 +77,8 @@ fluid_synth_program_select_by_sfont_name (fluid_synth_t* synth, int chan,
FLUIDSYNTH_API
int fluid_synth_get_program(fluid_synth_t* synth, int chan, unsigned int* sfont_id,
unsigned int* bank_num, unsigned int* preset_num);
FLUIDSYNTH_API int fluid_synth_get_channel_preset_info (fluid_synth_t *synth, int chan,
fluid_preset_info_t *info);
FLUIDSYNTH_API int fluid_synth_program_reset(fluid_synth_t* synth);
FLUIDSYNTH_API int fluid_synth_system_reset(fluid_synth_t* synth);

View file

@ -39,6 +39,7 @@ typedef struct _fluid_voice_t fluid_voice_t; /**< Synthesis v
typedef struct _fluid_sfloader_t fluid_sfloader_t; /**< SoundFont loader plugin */
typedef struct _fluid_sfont_t fluid_sfont_t; /**< SoundFont */
typedef struct _fluid_preset_t fluid_preset_t; /**< SoundFont preset */
typedef struct _fluid_preset_info_t fluid_preset_info_t; /**< SoundFont preset info */
typedef struct _fluid_sample_t fluid_sample_t; /**< SoundFont sample */
typedef struct _fluid_mod_t fluid_mod_t; /**< SoundFont modulator */
typedef struct _fluid_audio_driver_t fluid_audio_driver_t; /**< Audio driver instance */

View file

@ -53,6 +53,7 @@ new_fluid_channel(fluid_synth_t* synth, int num)
chan->synth = synth;
chan->channum = num;
chan->preset = NULL;
chan->shadow_preset = NULL;
chan->tuning = NULL;
fluid_channel_init(chan);

View file

@ -44,6 +44,7 @@
*
* Uses atomic operations:
* sfont_bank_prog
* shadow_preset
* key_pressure
* channel_pressure
* pitch_bend
@ -60,6 +61,7 @@ struct _fluid_channel_t
int sfont_bank_prog; /**< SoundFont ID (bit 21-31), bank (bit 7-20), program (bit 0-6) */
fluid_preset_t* preset; /**< Selected preset */
fluid_preset_t* shadow_preset; /**< Most recently assigned preset */
int key_pressure; /**< MIDI key pressure */
int channel_pressure; /**< MIDI channel pressure */

View file

@ -791,6 +791,7 @@ fluid_synth_return_event_process_callback (void* data, unsigned int msec)
fluid_synth_t *synth = data;
fluid_event_queue_elem_t *event;
fluid_preset_t *preset;
fluid_sfont_t *sfont;
while ((event = fluid_event_queue_get_outptr (synth->return_queue)))
{
@ -827,8 +828,14 @@ fluid_synth_return_event_process_callback (void* data, unsigned int msec)
break;
case FLUID_EVENT_QUEUE_ELEM_FREE_PRESET: /* Preset free event */
preset = (fluid_preset_t *)(event->pval);
fluid_synth_sfont_unref (synth, preset->sfont); /* -- unref preset's SoundFont */
sfont = preset->sfont;
/* Delete presets under mutex lock, to protect chan->shadow_preset */
fluid_rec_mutex_lock (synth->mutex);
delete_fluid_preset (preset);
fluid_rec_mutex_unlock (synth->mutex);
fluid_synth_sfont_unref (synth, sfont); /* -- unref preset's SoundFont */
break;
}
@ -2109,6 +2116,7 @@ fluid_synth_set_preset (fluid_synth_t *synth, int chan, fluid_preset_t *preset)
{
fluid_event_queue_t *queue;
fluid_event_queue_elem_t *event;
fluid_channel_t *channel;
fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
fluid_return_val_if_fail (chan >= 0 && chan < synth->midi_channels, FLUID_FAILED);
@ -2118,6 +2126,9 @@ fluid_synth_set_preset (fluid_synth_t *synth, int chan, fluid_preset_t *preset)
event = fluid_synth_get_event_elem (synth, &queue);
if (!event) return FLUID_FAILED;
channel = synth->channel[chan];
fluid_atomic_pointer_set (&channel->shadow_preset, preset);
event->type = FLUID_EVENT_QUEUE_ELEM_PRESET;
event->preset.channel = chan;
event->preset.preset = preset;
@ -2135,7 +2146,9 @@ fluid_synth_set_preset_LOCAL (fluid_synth_t *synth, int chan,
{
fluid_channel_t *channel;
/* Set shadow preset again, so it contains the actual latest assigned value */
channel = synth->channel[chan];
fluid_atomic_pointer_set (&channel->shadow_preset, preset);
fluid_channel_set_preset (channel, preset);
return FLUID_OK;
}
@ -4055,17 +4068,81 @@ fluid_synth_get_sfont_by_name(fluid_synth_t* synth, const char *name)
* @param synth FluidSynth instance
* @param chan MIDI channel number (0 to MIDI channel count - 1)
* @return Preset or NULL if no preset active on channel
* @deprecated
*
* NOTE: Should only be called from within synthesis thread, which includes
* SoundFont loader preset noteon methods.
* SoundFont loader preset noteon methods. Not thread safe otherwise.
*/
fluid_preset_t *
fluid_synth_get_channel_preset(fluid_synth_t* synth, int chan)
{
fluid_channel_t *channel;
fluid_return_val_if_fail (synth != NULL, NULL);
fluid_return_val_if_fail (chan >= 0 && chan < synth->midi_channels, NULL);
return fluid_channel_get_preset(synth->channel[chan]);
channel = synth->channel[chan];
return fluid_atomic_pointer_get (&channel->shadow_preset);
}
/**
* Get preset information for the currently selected preset on a MIDI channel.
* @param synth FluidSynth instance
* @param chan MIDI channel number (0 to MIDI channel count - 1)
* @param info Caller supplied structure to fill with preset information
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
* @since 1.1.1
*/
int
fluid_synth_get_channel_preset_info (fluid_synth_t *synth, int chan,
fluid_preset_info_t *info)
{
fluid_channel_t *channel;
fluid_preset_t *preset;
char *name;
if (info)
{
info->assigned = FALSE;
info->name[0] = '\0';
}
fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
fluid_return_val_if_fail (chan >= 0 && chan < synth->midi_channels, FLUID_FAILED);
fluid_return_val_if_fail (info != NULL, FLUID_FAILED);
/* Lock mutex to ensure preset doesn't get deleted, while working on it */
fluid_rec_mutex_lock (synth->mutex);
channel = synth->channel[chan];
preset = fluid_atomic_pointer_get (&channel->shadow_preset);
if (preset)
{
info->assigned = TRUE;
name = fluid_preset_get_name (preset);
if (name)
{
strncpy (info->name, name, FLUID_PRESET_INFO_NAME_LENGTH);
info->name[FLUID_PRESET_INFO_NAME_LENGTH - 1] = '\0';
}
else info->name[0] = '\0';
info->sfont_id = preset->sfont->id;
info->bank = fluid_preset_get_banknum (preset);
info->program = fluid_preset_get_num (preset);
}
else
{
info->assigned = FALSE;
fluid_channel_get_sfont_bank_prog (channel, &info->sfont_id, &info->bank, &info->program);
info->name[0] = '\0';
}
fluid_rec_mutex_unlock (synth->mutex);
return FLUID_OK;
}
/**