Reverted bank and SoundFont ID queuing, now executed immediately using atomic instructions as previously.

Program number now uses 8 bits in the SoundFont ID/bank/program integer, where a value of 128 indicates an unset preset.
fluid_synth_unset_program() now causes preset to be unassigned until a program change occurs.
Updated units in documentation for fluid_player_set_midi_tempo().
This commit is contained in:
Josh Green 2009-12-14 03:57:25 +00:00
parent b1f76f8b0c
commit 8aa1027115
5 changed files with 36 additions and 80 deletions

View File

@ -25,15 +25,15 @@
/* Field shift amounts for sfont_bank_prog bit field integer */ /* Field shift amounts for sfont_bank_prog bit field integer */
#define PROG_SHIFTVAL 0 #define PROG_SHIFTVAL 0
#define BANK_SHIFTVAL 7 #define BANK_SHIFTVAL 8
#define SFONT_SHIFTVAL 21 #define SFONT_SHIFTVAL 22
/* Field mask values for sfont_bank_prog bit field integer */ /* Field mask values for sfont_bank_prog bit field integer */
#define PROG_MASKVAL 0x0000007F #define PROG_MASKVAL 0x000000FF /* Bit 7 is used to indicate unset state */
#define BANK_MASKVAL 0x001FFF80 #define BANK_MASKVAL 0x003FFF00
#define BANKLSB_MASKVAL 0x00003F80 #define BANKLSB_MASKVAL 0x00007F00
#define BANKMSB_MASKVAL 0x001FC000 #define BANKMSB_MASKVAL 0x003F8000
#define SFONT_MASKVAL 0xFFE00000 #define SFONT_MASKVAL 0xFFC00000
static void fluid_channel_init(fluid_channel_t* chan); static void fluid_channel_init(fluid_channel_t* chan);

View File

@ -40,9 +40,7 @@ enum fluid_event_queue_elem
FLUID_EVENT_QUEUE_ELEM_FREE_PRESET, /**< Free preset return event. Uses pval field of event value */ FLUID_EVENT_QUEUE_ELEM_FREE_PRESET, /**< Free preset return event. Uses pval field of event value */
FLUID_EVENT_QUEUE_ELEM_SET_TUNING, /**< Set tuning event. Uses set_tuning field of event value */ FLUID_EVENT_QUEUE_ELEM_SET_TUNING, /**< Set tuning event. Uses set_tuning field of event value */
FLUID_EVENT_QUEUE_ELEM_REPL_TUNING, /**< Replace tuning event. Uses repl_tuning field of event value */ FLUID_EVENT_QUEUE_ELEM_REPL_TUNING, /**< Replace tuning event. Uses repl_tuning field of event value */
FLUID_EVENT_QUEUE_ELEM_UNREF_TUNING, /**< Unref tuning return event. Uses unref_tuning field of event value */ FLUID_EVENT_QUEUE_ELEM_UNREF_TUNING /**< Unref tuning return event. Uses unref_tuning field of event value */
FLUID_EVENT_QUEUE_ELEM_BANK_SELECT, /**< MIDI bank select on a channel. Uses chan_int field. */
FLUID_EVENT_QUEUE_ELEM_SFONT_ID /**< SoundFont ID select on a channel. Uses chan_int field. */
}; };
/** /**
@ -145,7 +143,6 @@ typedef struct
fluid_event_set_tuning_t set_tuning; /**< If type == FLUID_EVENT_QUEUE_ELEM_SET_TUNING */ fluid_event_set_tuning_t set_tuning; /**< If type == FLUID_EVENT_QUEUE_ELEM_SET_TUNING */
fluid_event_repl_tuning_t repl_tuning; /**< If type == FLUID_EVENT_QUEUE_ELEM_REPL_TUNING */ fluid_event_repl_tuning_t repl_tuning; /**< If type == FLUID_EVENT_QUEUE_ELEM_REPL_TUNING */
fluid_event_unref_tuning_t unref_tuning; /**< If type == FLUID_EVENT_QUEUE_ELEM_UNREF_TUNING */ fluid_event_unref_tuning_t unref_tuning; /**< If type == FLUID_EVENT_QUEUE_ELEM_UNREF_TUNING */
fluid_event_channel_int_t chan_int; /**< If type == FLUID_EVENT_QUEUE_ELEM_BANK_SELECT || type == FLUID_EVENT_QUEUE_ELEM_SFONT_ID */
double dval; /**< A floating point payload value */ double dval; /**< A floating point payload value */
int ival; /**< An integer payload value */ int ival; /**< An integer payload value */
void *pval; /**< A pointer payload value */ void *pval; /**< A pointer payload value */

View File

@ -1451,7 +1451,7 @@ int fluid_player_set_loop(fluid_player_t* player, int loop)
/** /**
* Set the tempo of a MIDI player. * Set the tempo of a MIDI player.
* @param player MIDI player instance * @param player MIDI player instance
* @param tempo Tempo to set playback speed to (DOCME - Units?) * @param tempo Tempo to set playback speed to (in microseconds per quarter note, as per MIDI file spec)
* @return Always returns #FLUID_OK * @return Always returns #FLUID_OK
*/ */
int fluid_player_set_midi_tempo(fluid_player_t* player, int tempo) int fluid_player_set_midi_tempo(fluid_player_t* player, int tempo)

View File

@ -51,8 +51,6 @@ static int fluid_synth_queue_midi_event (fluid_synth_t* synth, int type, int cha
static int fluid_synth_queue_gen_event (fluid_synth_t* synth, int chan, static int fluid_synth_queue_gen_event (fluid_synth_t* synth, int chan,
int param, float value, int absolute); int param, float value, int absolute);
static int fluid_synth_queue_int_event (fluid_synth_t* synth, int type, int val); static int fluid_synth_queue_int_event (fluid_synth_t* synth, int type, int val);
static int fluid_synth_queue_chan_int_event (fluid_synth_t* synth, int type,
int chan, int val);
static void fluid_synth_thread_queue_destroy_notify (void *data); static void fluid_synth_thread_queue_destroy_notify (void *data);
static int fluid_synth_noteon_LOCAL(fluid_synth_t* synth, int chan, int key, static int fluid_synth_noteon_LOCAL(fluid_synth_t* synth, int chan, int key,
int vel); int vel);
@ -82,10 +80,6 @@ fluid_synth_get_preset(fluid_synth_t* synth, unsigned int sfontnum,
static fluid_preset_t* static fluid_preset_t*
fluid_synth_get_preset_by_sfont_name(fluid_synth_t* synth, const char *sfontname, fluid_synth_get_preset_by_sfont_name(fluid_synth_t* synth, const char *sfontname,
unsigned int banknum, unsigned int prognum); unsigned int banknum, unsigned int prognum);
static void fluid_synth_bank_select_LOCAL (fluid_synth_t *synth, int chan,
unsigned int bank);
static void fluid_synth_sfont_select_LOCAL (fluid_synth_t *synth, int chan,
unsigned int sfont_id);
static void fluid_synth_update_presets(fluid_synth_t* synth); static void fluid_synth_update_presets(fluid_synth_t* synth);
static int fluid_synth_update_gain(fluid_synth_t* synth, static int fluid_synth_update_gain(fluid_synth_t* synth,
@ -1257,32 +1251,6 @@ fluid_synth_queue_int_event (fluid_synth_t* synth, int type, int val)
return FLUID_OK; return FLUID_OK;
} }
/**
* Queues an event with a channel and integer value payload.
* @param synth FluidSynth instance
* @param type Event type (#fluid_event_queue_elem)
* @param chan MIDI channel
* @param val Event value
* @return FLUID_OK on success, FLUID_FAILED otherwise
*/
static int
fluid_synth_queue_chan_int_event (fluid_synth_t* synth, int type, int chan, int val)
{
fluid_event_queue_t *queue;
fluid_event_queue_elem_t *event;
event = fluid_synth_get_event_elem (synth, &queue);
if (!event) return FLUID_FAILED;
event->type = type;
event->chan_int.channel = chan;
event->chan_int.val = val;
fluid_event_queue_next_inptr (queue);
return FLUID_OK;
}
/* Gets called when a thread ends, which has been assigned a queue */ /* Gets called when a thread ends, which has been assigned a queue */
static void static void
fluid_synth_thread_queue_destroy_notify (void *data) fluid_synth_thread_queue_destroy_notify (void *data)
@ -2193,6 +2161,9 @@ fluid_synth_get_preset(fluid_synth_t* synth, unsigned int sfontnum,
fluid_sfont_info_t *sfont_info; fluid_sfont_info_t *sfont_info;
fluid_list_t *list; fluid_list_t *list;
/* 128 indicates an "unset" operation" */
if (prognum == FLUID_UNSET_PROGRAM) return NULL;
fluid_rec_mutex_lock (synth->mutex); /* ++ lock sfont list, bank offset list and sfont */ fluid_rec_mutex_lock (synth->mutex); /* ++ lock sfont list, bank offset list and sfont */
for (list = synth->sfont_info; list; list = fluid_list_next (list)) { for (list = synth->sfont_info; list; list = fluid_list_next (list)) {
@ -2286,6 +2257,9 @@ fluid_synth_find_preset(fluid_synth_t* synth, unsigned int banknum,
*/ */
/* FIXME - Currently not real-time safe, due to preset allocation and mutex lock, /* FIXME - Currently not real-time safe, due to preset allocation and mutex lock,
* and may be called from within synthesis context. */ * and may be called from within synthesis context. */
/* As of 1.1.1 prognum can be set to 128 to unset the preset. Not documented
* since fluid_synth_unset_program() should be used instead. */
int int
fluid_synth_program_change(fluid_synth_t* synth, int chan, int prognum) fluid_synth_program_change(fluid_synth_t* synth, int chan, int prognum)
{ {
@ -2295,7 +2269,7 @@ fluid_synth_program_change(fluid_synth_t* synth, int chan, int prognum)
fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); 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 (chan >= 0 && chan < synth->midi_channels, FLUID_FAILED);
fluid_return_val_if_fail (prognum >= 0 && prognum <= FLUID_NUM_PROGRAMS, FLUID_FAILED); fluid_return_val_if_fail (prognum >= 0 && prognum <= 128, FLUID_FAILED);
channel = synth->channel[chan]; channel = synth->channel[chan];
fluid_channel_get_sfont_bank_prog(channel, NULL, &banknum, NULL); fluid_channel_get_sfont_bank_prog(channel, NULL, &banknum, NULL);
@ -2310,9 +2284,13 @@ fluid_synth_program_change(fluid_synth_t* synth, int chan, int prognum)
* is a hack for MIDI files that do bank changes in GM mode. Proper way to * is a hack for MIDI files that do bank changes in GM mode. Proper way to
* handle this would probably be to ignore bank changes when in GM mode. - JG * handle this would probably be to ignore bank changes when in GM mode. - JG
*/ */
if (prognum != FLUID_UNSET_PROGRAM)
{
if (channel->channum == 9) if (channel->channum == 9)
preset = fluid_synth_find_preset(synth, DRUM_INST_BANK, prognum); preset = fluid_synth_find_preset(synth, DRUM_INST_BANK, prognum);
else preset = fluid_synth_find_preset(synth, banknum, prognum); else preset = fluid_synth_find_preset(synth, banknum, prognum);
}
else preset = NULL;
/* Fallback to another preset if not found */ /* Fallback to another preset if not found */
if (!preset) if (!preset)
@ -2364,22 +2342,13 @@ fluid_synth_bank_select(fluid_synth_t* synth, int chan, unsigned int bank)
{ {
fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); 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 (chan >= 0 && chan < synth->midi_channels, FLUID_FAILED);
fluid_return_val_if_fail (bank <= 16383, FLUID_FAILED);
if (fluid_synth_should_queue (synth)) fluid_channel_set_sfont_bank_prog (synth->channel[chan], -1, bank, -1);
return fluid_synth_queue_chan_int_event (synth, FLUID_EVENT_QUEUE_ELEM_BANK_SELECT,
chan, bank);
else fluid_synth_bank_select_LOCAL (synth, chan, bank);
return FLUID_OK; return FLUID_OK;
} }
/* Local synthesis thread variant of bank select */
static void
fluid_synth_bank_select_LOCAL (fluid_synth_t *synth, int chan, unsigned int bank)
{
fluid_channel_set_sfont_bank_prog (synth->channel[chan], -1, bank, -1);
}
/** /**
* Set SoundFont ID on a MIDI channel. * Set SoundFont ID on a MIDI channel.
* @param synth FluidSynth instance * @param synth FluidSynth instance
@ -2393,21 +2362,11 @@ fluid_synth_sfont_select(fluid_synth_t* synth, int chan, unsigned int sfont_id)
fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); 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 (chan >= 0 && chan < synth->midi_channels, FLUID_FAILED);
if (fluid_synth_should_queue (synth)) fluid_channel_set_sfont_bank_prog(synth->channel[chan], sfont_id, -1, -1);
return fluid_synth_queue_chan_int_event (synth, FLUID_EVENT_QUEUE_ELEM_SFONT_ID,
chan, sfont_id);
else fluid_synth_sfont_select_LOCAL (synth, chan, sfont_id);
return FLUID_OK; return FLUID_OK;
} }
/* Local synthesis thread variant of SoundFont ID select */
static void
fluid_synth_sfont_select_LOCAL (fluid_synth_t *synth, int chan, unsigned int sfont_id)
{
fluid_channel_set_sfont_bank_prog(synth->channel[chan], sfont_id, -1, -1);
}
/** /**
* Set the preset of a MIDI channel to an unassigned state. * Set the preset of a MIDI channel to an unassigned state.
* @param synth FluidSynth instance * @param synth FluidSynth instance
@ -2415,9 +2374,9 @@ fluid_synth_sfont_select_LOCAL (fluid_synth_t *synth, int chan, unsigned int sfo
* @return #FLUID_OK on success, #FLUID_FAILED otherwise * @return #FLUID_OK on success, #FLUID_FAILED otherwise
* @since 1.1.1 * @since 1.1.1
* *
* Note: Channel retains its SoundFont ID, bank and program numbers. Certain * Note: Channel retains its SoundFont ID and bank numbers, while the program
* operations, such as fluid_synth_reset() or MIDI program changes may * number is set to an "unset" state. MIDI program changes may re-assign a
* re-assign the preset, if one matches. * preset if one matches.
*/ */
int int
fluid_synth_unset_program (fluid_synth_t *synth, int chan) fluid_synth_unset_program (fluid_synth_t *synth, int chan)
@ -2425,7 +2384,7 @@ fluid_synth_unset_program (fluid_synth_t *synth, int chan)
fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); 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 (chan >= 0 && chan < synth->midi_channels, FLUID_FAILED);
return fluid_synth_set_preset (synth, chan, NULL); return fluid_synth_program_change (synth, chan, FLUID_UNSET_PROGRAM);
} }
/** /**
@ -2452,6 +2411,10 @@ fluid_synth_get_program(fluid_synth_t* synth, int chan, unsigned int* sfont_id,
channel = synth->channel[chan]; channel = synth->channel[chan];
fluid_channel_get_sfont_bank_prog(channel, (int *)sfont_id, (int *)bank_num, fluid_channel_get_sfont_bank_prog(channel, (int *)sfont_id, (int *)bank_num,
(int *)preset_num); (int *)preset_num);
/* 128 indicates that the preset is unset. Set to 0 to be backwards compatible. */
if (*preset_num == FLUID_UNSET_PROGRAM) *preset_num = 0;
return FLUID_OK; return FLUID_OK;
} }
@ -3441,12 +3404,6 @@ fluid_synth_process_event_queue_LOCAL (fluid_synth_t *synth,
event->repl_tuning.new_tuning, event->repl_tuning.new_tuning,
event->repl_tuning.apply, TRUE); event->repl_tuning.apply, TRUE);
break; break;
case FLUID_EVENT_QUEUE_ELEM_BANK_SELECT:
fluid_synth_bank_select_LOCAL (synth, event->chan_int.channel, event->chan_int.val);
break;
case FLUID_EVENT_QUEUE_ELEM_SFONT_ID:
fluid_synth_sfont_select_LOCAL (synth, event->chan_int.channel, event->chan_int.val);
break;
} }
fluid_event_queue_next_outptr (queue); fluid_event_queue_next_outptr (queue);

View File

@ -48,6 +48,8 @@
#define FLUID_NUM_PROGRAMS 128 #define FLUID_NUM_PROGRAMS 128
#define DRUM_INST_BANK 128 #define DRUM_INST_BANK 128
#define FLUID_UNSET_PROGRAM 128 /* Program number used to unset a preset */
#if defined(WITH_FLOAT) #if defined(WITH_FLOAT)
#define FLUID_SAMPLE_FORMAT FLUID_SAMPLE_FLOAT #define FLUID_SAMPLE_FORMAT FLUID_SAMPLE_FLOAT
#else #else