mirror of
https://github.com/ZDoom/fluidsynth.git
synced 2025-01-19 07:50:49 +00:00
Now setting shadow_preset parameter directly in fluid_channel_set_preset() which fixes crash bug where MIDI system reset event would cause shadow_preset and preset to get out of sync.
Reverted return queuing of program changes. Program changes are once again real-time unsafe. Added public function fluid_synth_unset_program(). Renamed fluid_synth_get_channel_preset_info() to fluid_synth_get_channel_info(). Changed fluid_preset_info_t to fluid_synth_channel_info_t and moved to synth.h header. Shell 'channels' command now uses thread safe fluid_synth_get_channel_info(). Removed fluid_synth_set_preset_LOCAL(), now just using fluid_channel_set_preset(). Added New In 1.1.1 section to developer docs.
This commit is contained in:
parent
836a6b45d8
commit
2ee782a6cc
8 changed files with 83 additions and 83 deletions
|
@ -5,7 +5,7 @@
|
|||
#---------------------------------------------------------------------------
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = libfluidsynth
|
||||
PROJECT_NUMBER = 1.1.0
|
||||
PROJECT_NUMBER = 1.1.1
|
||||
OUTPUT_DIRECTORY = api
|
||||
CREATE_SUBDIRS = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
\author Pedro López-Cabanillas
|
||||
\author Josh Green
|
||||
\author Copyright © 2003-2009 Peter Hanappe, Conrad Berhörster, Antoine Schmitt, Pedro López-Cabanillas, Josh Green
|
||||
\version Revision 1.1.0
|
||||
\version Revision 1.1.1
|
||||
\date 2009-10-20
|
||||
|
||||
All the source code examples in this document are in the public domain; you can use them as you please. This document is licensed under the Creative Commons Attribution-Share Alike 3.0 Unported License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/3.0/ . The FluidSynth library is distributed under the GNU Library General Public License. A copy of the GNU Library General Public License is contained in the FluidSynth package; if not, visit http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt or write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
@ -19,6 +19,7 @@ All the source code examples in this document are in the public domain; you can
|
|||
|
||||
- \ref Disclaimer
|
||||
- \ref Introduction
|
||||
- \ref NewIn1_1_1
|
||||
- \ref NewIn1_1_0
|
||||
- \ref CreatingSettings
|
||||
- \ref CreatingSynth
|
||||
|
@ -55,6 +56,14 @@ What is FluidSynth?
|
|||
|
||||
- FluidSynth is open source, in active development. For more details, take a look at http://www.fluidsynth.org
|
||||
|
||||
\section NewIn1_1_1 Whats new in 1.1.1?
|
||||
|
||||
Changes in FluidSynth 1.1.1 concerning developers:
|
||||
|
||||
- fluid_synth_get_channel_preset() marked as deprecated. New function
|
||||
fluid_synth_get_channel_info() added which is thread safe and should replace
|
||||
most uses of the older function.
|
||||
- Added fluid_synth_unset_program() to unset the active preset on a channel.
|
||||
|
||||
\section NewIn1_1_0 Whats new in 1.1.0?
|
||||
|
||||
|
|
|
@ -229,21 +229,6 @@ 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.
|
||||
*/
|
||||
|
|
|
@ -45,6 +45,22 @@ extern "C" {
|
|||
* fluid_synth_noteon(), fluid_synth_noteoff(), ...
|
||||
*/
|
||||
|
||||
#define FLUID_SYNTH_CHANNEL_INFO_NAME_SIZE 32 /**< Length of channel info name field (including zero terminator) */
|
||||
|
||||
/**
|
||||
* Channel information structure for fluid_synth_get_channel_info().
|
||||
* @since 1.1.1
|
||||
*/
|
||||
struct _fluid_synth_channel_info_t
|
||||
{
|
||||
int assigned : 1; /**< TRUE if a preset is assigned, FALSE otherwise */
|
||||
/* Reserved flag bits (at the least 31) */
|
||||
int sfont_id; /**< ID of parent SoundFont */
|
||||
int bank; /**< MIDI bank number (0-16383) */
|
||||
int program; /**< MIDI program number (0-127) */
|
||||
char name[FLUID_SYNTH_CHANNEL_INFO_NAME_SIZE]; /**< Channel preset name */
|
||||
char reserved[32]; /**< Reserved data for future expansion */
|
||||
};
|
||||
|
||||
FLUIDSYNTH_API fluid_synth_t* new_fluid_synth(fluid_settings_t* settings);
|
||||
FLUIDSYNTH_API int delete_fluid_synth(fluid_synth_t* synth);
|
||||
|
@ -77,8 +93,9 @@ 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_unset_program (fluid_synth_t *synth, int chan);
|
||||
FLUIDSYNTH_API int fluid_synth_get_channel_info (fluid_synth_t *synth, int chan,
|
||||
fluid_synth_channel_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);
|
||||
|
||||
|
|
|
@ -35,11 +35,11 @@ extern "C" {
|
|||
|
||||
typedef struct _fluid_hashtable_t fluid_settings_t; /**< Configuration settings instance */
|
||||
typedef struct _fluid_synth_t fluid_synth_t; /**< Synthesizer instance */
|
||||
typedef struct _fluid_synth_channel_info_t fluid_synth_channel_info_t; /**< SoundFont channel info */
|
||||
typedef struct _fluid_voice_t fluid_voice_t; /**< Synthesis voice instance */
|
||||
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 */
|
||||
|
|
|
@ -75,6 +75,7 @@ fluid_channel_init(fluid_channel_t* chan)
|
|||
chan->sfont_bank_prog = 0 << SFONT_SHIFTVAL | banknum << BANK_SHIFTVAL
|
||||
| prognum << PROG_SHIFTVAL;
|
||||
|
||||
/* FIXME - fluid_synth_find_preset not real-time safe */
|
||||
newpreset = fluid_synth_find_preset(chan->synth, banknum, prognum);
|
||||
fluid_channel_set_preset(chan, newpreset);
|
||||
|
||||
|
@ -191,6 +192,7 @@ delete_fluid_channel(fluid_channel_t* chan)
|
|||
return FLUID_OK;
|
||||
}
|
||||
|
||||
/* FIXME - Calls fluid_channel_init() potentially in synthesis context */
|
||||
void
|
||||
fluid_channel_reset(fluid_channel_t* chan)
|
||||
{
|
||||
|
@ -206,6 +208,9 @@ fluid_channel_set_preset(fluid_channel_t* chan, fluid_preset_t* preset)
|
|||
|
||||
fluid_preset_notify (chan->preset, FLUID_PRESET_UNSELECTED, chan->channum);
|
||||
|
||||
/* Set shadow preset again, so it contains the actual latest assigned value */
|
||||
fluid_atomic_pointer_set (&chan->shadow_preset, preset);
|
||||
|
||||
if (chan->preset) /* Queue preset free (shouldn't free() in synth context) */
|
||||
{
|
||||
event = fluid_event_queue_get_inptr (chan->synth->return_queue);
|
||||
|
|
|
@ -543,22 +543,25 @@ fluid_handle_inst(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out)
|
|||
int
|
||||
fluid_handle_channels(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out)
|
||||
{
|
||||
int i;
|
||||
fluid_preset_t* preset;
|
||||
fluid_synth_channel_info_t info;
|
||||
int verbose = 0;
|
||||
int i;
|
||||
|
||||
if (ac > 0 && strcmp( av[0], "-verbose") == 0) verbose = 1;
|
||||
|
||||
for (i = 0; i < fluid_synth_count_midi_channels(synth); i++) {
|
||||
preset = fluid_synth_get_channel_preset(synth, i);
|
||||
if (preset == NULL) fluid_ostream_printf(out, "chan %d, no preset\n", i);
|
||||
else if (!verbose) fluid_ostream_printf(out, "chan %d, %s\n", i, fluid_preset_get_name(preset));
|
||||
else fluid_ostream_printf(out, "chan %d, sfont %d, bank %d, preset %d, %s\n", i,
|
||||
fluid_sfont_get_id( preset->sfont),
|
||||
fluid_preset_get_banknum(preset),
|
||||
fluid_preset_get_num(preset),
|
||||
fluid_preset_get_name(preset));
|
||||
for (i = 0; i < fluid_synth_count_midi_channels (synth); i++)
|
||||
{
|
||||
fluid_synth_get_channel_info (synth, i, &info);
|
||||
|
||||
if (!verbose)
|
||||
fluid_ostream_printf (out, "chan %d, %s\n", i,
|
||||
info.assigned ? info.name : "no preset");
|
||||
else
|
||||
fluid_ostream_printf (out, "chan %d, sfont %d, bank %d, preset %d, %s\n", i,
|
||||
info.sfont_id, info.bank, info.program,
|
||||
info.assigned ? info.name : "no preset");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -76,8 +76,6 @@ static int fluid_synth_update_pitch_bend_LOCAL(fluid_synth_t* synth, int chan);
|
|||
static int fluid_synth_update_pitch_wheel_sens_LOCAL(fluid_synth_t* synth, int chan);
|
||||
static int fluid_synth_set_preset (fluid_synth_t *synth, int chan,
|
||||
fluid_preset_t *preset);
|
||||
static int fluid_synth_set_preset_LOCAL (fluid_synth_t *synth, int chan,
|
||||
fluid_preset_t *preset);
|
||||
static fluid_preset_t*
|
||||
fluid_synth_get_preset(fluid_synth_t* synth, unsigned int sfontnum,
|
||||
unsigned int banknum, unsigned int prognum);
|
||||
|
@ -859,10 +857,6 @@ fluid_synth_return_event_process_thread (void* data)
|
|||
|
||||
fluid_synth_sfont_unref (synth, sfont); /* -- unref preset's SoundFont */
|
||||
break;
|
||||
case FLUID_EVENT_QUEUE_ELEM_MIDI:
|
||||
if (event->midi.type == PROGRAM_CHANGE)
|
||||
fluid_synth_program_change (synth, event->midi.channel, event->midi.param1);
|
||||
break;
|
||||
}
|
||||
|
||||
fluid_event_queue_next_outptr (synth->return_queue);
|
||||
|
@ -2166,12 +2160,13 @@ fluid_synth_set_preset (fluid_synth_t *synth, int chan, fluid_preset_t *preset)
|
|||
fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
|
||||
fluid_return_val_if_fail (chan >= 0 && chan < synth->midi_channels, FLUID_FAILED);
|
||||
|
||||
channel = synth->channel[chan];
|
||||
|
||||
if (fluid_synth_should_queue (synth))
|
||||
{
|
||||
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;
|
||||
|
@ -2181,21 +2176,7 @@ fluid_synth_set_preset (fluid_synth_t *synth, int chan, fluid_preset_t *preset)
|
|||
fluid_event_queue_next_inptr (queue);
|
||||
return FLUID_OK;
|
||||
}
|
||||
else return fluid_synth_set_preset_LOCAL (synth, chan, preset);
|
||||
}
|
||||
|
||||
/* Local synthesis thread variant of set channel preset */
|
||||
static int
|
||||
fluid_synth_set_preset_LOCAL (fluid_synth_t *synth, int chan,
|
||||
fluid_preset_t *preset)
|
||||
{
|
||||
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;
|
||||
else return fluid_channel_set_preset (channel, preset);
|
||||
}
|
||||
|
||||
/* Get a preset by SoundFont, bank and program numbers.
|
||||
|
@ -2303,39 +2284,19 @@ fluid_synth_find_preset(fluid_synth_t* synth, unsigned int banknum,
|
|||
* @param prognum MIDI program number (0-127)
|
||||
* @return FLUID_OK on success, FLUID_FAILED otherwise
|
||||
*/
|
||||
/* FIXME - Currently not real-time safe, due to preset allocation and mutex lock,
|
||||
* and may be called from within synthesis context. */
|
||||
int
|
||||
fluid_synth_program_change(fluid_synth_t* synth, int chan, int prognum)
|
||||
{
|
||||
fluid_preset_t* preset = NULL;
|
||||
fluid_channel_t* channel;
|
||||
fluid_event_queue_elem_t *event;
|
||||
int subst_bank, subst_prog, banknum;
|
||||
|
||||
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 (prognum >= 0 && prognum <= FLUID_NUM_PROGRAMS, FLUID_FAILED);
|
||||
|
||||
/* If this is the synthesis thread, send program change via return queue, to
|
||||
* avoid mutex locks and other realtime naughties */
|
||||
if (fluid_synth_is_synth_thread (synth))
|
||||
{
|
||||
event = fluid_event_queue_get_inptr (synth->return_queue);
|
||||
if (!event)
|
||||
{
|
||||
FLUID_LOG (FLUID_ERR, "Synth return event queue full");
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
|
||||
event->type = FLUID_EVENT_QUEUE_ELEM_MIDI;
|
||||
event->midi.type = PROGRAM_CHANGE;
|
||||
event->midi.param1 = prognum;
|
||||
event->midi.channel = chan;
|
||||
|
||||
fluid_event_queue_next_inptr (synth->return_queue);
|
||||
|
||||
return FLUID_OK;
|
||||
}
|
||||
|
||||
channel = synth->channel[chan];
|
||||
fluid_channel_get_sfont_bank_prog(channel, NULL, &banknum, NULL);
|
||||
|
||||
|
@ -2447,6 +2408,26 @@ fluid_synth_sfont_select_LOCAL (fluid_synth_t *synth, int chan, unsigned int sfo
|
|||
fluid_channel_set_sfont_bank_prog(synth->channel[chan], sfont_id, -1, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the preset of a MIDI channel to an unassigned state.
|
||||
* @param synth FluidSynth instance
|
||||
* @param chan MIDI channel number (0 to MIDI channel count - 1)
|
||||
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
|
||||
* @since 1.1.1
|
||||
*
|
||||
* Note: Channel retains its SoundFont ID, bank and program numbers. Certain
|
||||
* operations, such as fluid_synth_reset() or MIDI program changes may
|
||||
* re-assign the preset, if one matches.
|
||||
*/
|
||||
int
|
||||
fluid_synth_unset_program (fluid_synth_t *synth, int chan)
|
||||
{
|
||||
fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
|
||||
fluid_return_val_if_fail (chan >= 0 && chan < synth->midi_channels, FLUID_FAILED);
|
||||
|
||||
return fluid_synth_set_preset (synth, chan, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current SoundFont ID, bank number and program number for a MIDI channel.
|
||||
* @param synth FluidSynth instance
|
||||
|
@ -3435,8 +3416,8 @@ fluid_synth_process_event_queue_LOCAL (fluid_synth_t *synth,
|
|||
event->gen.value, event->gen.absolute);
|
||||
break;
|
||||
case FLUID_EVENT_QUEUE_ELEM_PRESET:
|
||||
fluid_synth_set_preset_LOCAL (synth, event->preset.channel,
|
||||
event->preset.preset);
|
||||
fluid_channel_set_preset (synth->channel[event->preset.channel],
|
||||
event->preset.preset);
|
||||
break;
|
||||
case FLUID_EVENT_QUEUE_ELEM_STOP_VOICES:
|
||||
fluid_synth_stop_LOCAL (synth, event->ival);
|
||||
|
@ -4155,7 +4136,7 @@ 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
|
||||
* @deprecated fluid_synth_get_channel_info() should replace most use cases.
|
||||
*
|
||||
* NOTE: Should only be called from within synthesis thread, which includes
|
||||
* SoundFont loader preset noteon methods. Not thread safe otherwise.
|
||||
|
@ -4173,7 +4154,7 @@ fluid_synth_get_channel_preset(fluid_synth_t* synth, int chan)
|
|||
}
|
||||
|
||||
/**
|
||||
* Get preset information for the currently selected preset on a MIDI channel.
|
||||
* Get information on 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
|
||||
|
@ -4181,8 +4162,8 @@ fluid_synth_get_channel_preset(fluid_synth_t* synth, int chan)
|
|||
* @since 1.1.1
|
||||
*/
|
||||
int
|
||||
fluid_synth_get_channel_preset_info (fluid_synth_t *synth, int chan,
|
||||
fluid_preset_info_t *info)
|
||||
fluid_synth_get_channel_info (fluid_synth_t *synth, int chan,
|
||||
fluid_synth_channel_info_t *info)
|
||||
{
|
||||
fluid_channel_t *channel;
|
||||
fluid_preset_t *preset;
|
||||
|
@ -4211,8 +4192,8 @@ fluid_synth_get_channel_preset_info (fluid_synth_t *synth, int chan,
|
|||
|
||||
if (name)
|
||||
{
|
||||
strncpy (info->name, name, FLUID_PRESET_INFO_NAME_LENGTH);
|
||||
info->name[FLUID_PRESET_INFO_NAME_LENGTH - 1] = '\0';
|
||||
strncpy (info->name, name, FLUID_SYNTH_CHANNEL_INFO_NAME_SIZE);
|
||||
info->name[FLUID_SYNTH_CHANNEL_INFO_NAME_SIZE - 1] = '\0';
|
||||
}
|
||||
else info->name[0] = '\0';
|
||||
|
||||
|
|
Loading…
Reference in a new issue