Moved snd_pcm_nonblock call into new_fluid_alsa_audio_driver2() and out of audio run functions.

Removed unnecessary test of snd_pcm_state and call to snd_pcm_drop.
Removed SETCC macro in fluid_chan.c and replaced with fluid_channel_set_cc() which uses atomic op.
Removed invalid fluid_channel_set_cc() and fluid_channel_get_cc() function declarations (they were replaced with macros).
Added shadow_polyphony field to fluid_synth_t which is accessed via atomic ops by all threads, polyphony field is now only set by synthesis thread.
fluid_synth_cc() now sets cc channel field atomically and queues an update as needed.
synth_thread_id field assigned every call to fluid_synth_one_block().
fluid_synth_alloc_voice() now atomically accesses gain.
Fixed bug in fluid_timer_join() where timer->thread was set to NULL even if auto_destroy was enabled, but was at that point no longer in existence.
This commit is contained in:
Josh Green 2009-11-15 02:34:24 +00:00
parent 8f63cef0aa
commit 50c88d392a
6 changed files with 59 additions and 75 deletions

View file

@ -296,6 +296,10 @@ new_fluid_alsa_audio_driver2(fluid_settings_t* settings,
FLUID_LOG(FLUID_ERR, "Software setup failed."); FLUID_LOG(FLUID_ERR, "Software setup failed.");
} }
if (snd_pcm_nonblock(dev->pcm, 0) != 0) {
FLUID_LOG(FLUID_ERR, "Failed to set the audio device to blocking mode");
goto error_recovery;
}
/* Create the audio thread */ /* Create the audio thread */
dev->thread = new_fluid_thread (fluid_alsa_formats[i].run, dev, realtime_prio, FALSE); dev->thread = new_fluid_thread (fluid_alsa_formats[i].run, dev, realtime_prio, FALSE);
@ -326,16 +330,8 @@ int delete_fluid_alsa_audio_driver(fluid_audio_driver_t* p)
if (dev->thread) if (dev->thread)
fluid_thread_join (dev->thread); fluid_thread_join (dev->thread);
if (dev->pcm) { if (dev->pcm)
snd_pcm_state_t state = snd_pcm_state(dev->pcm);
if ((state == SND_PCM_STATE_RUNNING)
|| (state == SND_PCM_STATE_XRUN)
|| (state == SND_PCM_STATE_SUSPENDED)
|| (state == SND_PCM_STATE_PAUSED)) {
snd_pcm_drop(dev->pcm);
}
snd_pcm_close (dev->pcm); snd_pcm_close (dev->pcm);
}
FLUID_FREE(dev); FLUID_FREE(dev);
@ -390,11 +386,6 @@ static void fluid_alsa_audio_run_float (void *d)
return; return;
} }
if (snd_pcm_nonblock(dev->pcm, 0) != 0) { /* double negation */
FLUID_LOG(FLUID_ERR, "Failed to set the audio device to blocking mode");
goto error_recovery;
}
if (snd_pcm_prepare(dev->pcm) != 0) { if (snd_pcm_prepare(dev->pcm) != 0) {
FLUID_LOG(FLUID_ERR, "Failed to prepare the audio device"); FLUID_LOG(FLUID_ERR, "Failed to prepare the audio device");
goto error_recovery; goto error_recovery;
@ -474,11 +465,6 @@ static void fluid_alsa_audio_run_s16 (void *d)
handle[0] = left; handle[0] = left;
handle[1] = right; handle[1] = right;
if (snd_pcm_nonblock(dev->pcm, 0) != 0) { /* double negation */
FLUID_LOG(FLUID_ERR, "Failed to set the audio device to blocking mode");
goto error_recovery;
}
if (snd_pcm_prepare(dev->pcm) != 0) { if (snd_pcm_prepare(dev->pcm) != 0) {
FLUID_LOG(FLUID_ERR, "Failed to prepare the audio device"); FLUID_LOG(FLUID_ERR, "Failed to prepare the audio device");
goto error_recovery; goto error_recovery;

View file

@ -36,8 +36,6 @@
#define SFONT_MASKVAL 0xFFE00000 #define SFONT_MASKVAL 0xFFE00000
#define SETCC(_c,_n,_v) _c->cc[_n] = _v
static void fluid_channel_init(fluid_channel_t* chan); static void fluid_channel_init(fluid_channel_t* chan);
@ -137,26 +135,26 @@ fluid_channel_init_ctrl(fluid_channel_t* chan, int is_all_ctrl_off)
continue; continue;
} }
SETCC(chan, i, 0); fluid_channel_set_cc (chan, i, 0);
} }
} }
else { else {
for (i = 0; i < 128; i++) { for (i = 0; i < 128; i++) {
SETCC(chan, i, 0); fluid_channel_set_cc (chan, i, 0);
} }
} }
/* Set RPN controllers to NULL state */ /* Set RPN controllers to NULL state */
SETCC(chan, RPN_LSB, 127); fluid_channel_set_cc (chan, RPN_LSB, 127);
SETCC(chan, RPN_MSB, 127); fluid_channel_set_cc (chan, RPN_MSB, 127);
/* Set NRPN controllers to NULL state */ /* Set NRPN controllers to NULL state */
SETCC(chan, NRPN_LSB, 127); fluid_channel_set_cc (chan, NRPN_LSB, 127);
SETCC(chan, NRPN_MSB, 127); fluid_channel_set_cc (chan, NRPN_MSB, 127);
/* Expression (MSB & LSB) */ /* Expression (MSB & LSB) */
SETCC(chan, EXPRESSION_MSB, 127); fluid_channel_set_cc (chan, EXPRESSION_MSB, 127);
SETCC(chan, EXPRESSION_LSB, 127); fluid_channel_set_cc (chan, EXPRESSION_LSB, 127);
if (!is_all_ctrl_off) { if (!is_all_ctrl_off) {
@ -164,19 +162,19 @@ fluid_channel_init_ctrl(fluid_channel_t* chan, int is_all_ctrl_off)
/* Just like panning, a value of 64 indicates no change for sound ctrls */ /* Just like panning, a value of 64 indicates no change for sound ctrls */
for (i = SOUND_CTRL1; i <= SOUND_CTRL10; i++) { for (i = SOUND_CTRL1; i <= SOUND_CTRL10; i++) {
SETCC(chan, i, 64); fluid_channel_set_cc (chan, i, 64);
} }
/* Volume / initial attenuation (MSB & LSB) */ /* Volume / initial attenuation (MSB & LSB) */
SETCC(chan, VOLUME_MSB, 100); fluid_channel_set_cc (chan, VOLUME_MSB, 100);
SETCC(chan, VOLUME_LSB, 0); fluid_channel_set_cc (chan, VOLUME_LSB, 0);
/* Pan (MSB & LSB) */ /* Pan (MSB & LSB) */
SETCC(chan, PAN_MSB, 64); fluid_channel_set_cc (chan, PAN_MSB, 64);
SETCC(chan, PAN_LSB, 0); fluid_channel_set_cc (chan, PAN_LSB, 0);
/* Reverb */ /* Reverb */
/* SETCC(chan, EFFECTS_DEPTH1, 40); */ /* fluid_channel_set_cc (chan, EFFECTS_DEPTH1, 40); */
/* Note: although XG standard specifies the default amount of reverb to /* Note: although XG standard specifies the default amount of reverb to
be 40, most people preferred having it at zero. be 40, most people preferred having it at zero.
See http://lists.gnu.org/archive/html/fluid-dev/2009-07/msg00016.html */ See http://lists.gnu.org/archive/html/fluid-dev/2009-07/msg00016.html */

View file

@ -108,8 +108,6 @@ void fluid_channel_set_bank_lsb(fluid_channel_t* chan, int banklsb);
void fluid_channel_set_bank_msb(fluid_channel_t* chan, int bankmsb); void fluid_channel_set_bank_msb(fluid_channel_t* chan, int bankmsb);
void fluid_channel_get_sfont_bank_prog(fluid_channel_t* chan, int *sfont, void fluid_channel_get_sfont_bank_prog(fluid_channel_t* chan, int *sfont,
int *bank, int *prog); int *bank, int *prog);
void fluid_channel_set_cc(fluid_channel_t* chan, int num, int val);
int fluid_channel_get_cc(fluid_channel_t* chan, int num);
int fluid_channel_get_num(fluid_channel_t* chan); int fluid_channel_get_num(fluid_channel_t* chan);
void fluid_channel_set_interp_method(fluid_channel_t* chan, int new_method); void fluid_channel_set_interp_method(fluid_channel_t* chan, int new_method);
int fluid_channel_get_interp_method(fluid_channel_t* chan); int fluid_channel_get_interp_method(fluid_channel_t* chan);

View file

@ -56,8 +56,7 @@ static int fluid_synth_noteon_LOCAL(fluid_synth_t* synth, int chan, int key,
int vel); int vel);
static int fluid_synth_noteoff_LOCAL(fluid_synth_t* synth, int chan, int key); static int fluid_synth_noteoff_LOCAL(fluid_synth_t* synth, int chan, int key);
static int fluid_synth_damp_voices_LOCAL(fluid_synth_t* synth, int chan); static int fluid_synth_damp_voices_LOCAL(fluid_synth_t* synth, int chan);
static int fluid_synth_cc_real(fluid_synth_t* synth, int channum, int num, static int fluid_synth_cc_real(fluid_synth_t* synth, int channum, int num, int noqueue);
int value, int noqueue);
static int fluid_synth_update_device_id (fluid_synth_t *synth, char *name, static int fluid_synth_update_device_id (fluid_synth_t *synth, char *name,
int value); int value);
static int fluid_synth_sysex_midi_tuning (fluid_synth_t *synth, const char *data, static int fluid_synth_sysex_midi_tuning (fluid_synth_t *synth, const char *data,
@ -532,6 +531,7 @@ new_fluid_synth(fluid_settings_t *settings)
fluid_settings_getint(settings, "synth.dump", &synth->dump); fluid_settings_getint(settings, "synth.dump", &synth->dump);
fluid_settings_getint(settings, "synth.polyphony", &synth->polyphony); fluid_settings_getint(settings, "synth.polyphony", &synth->polyphony);
synth->shadow_polyphony = synth->polyphony;
fluid_settings_getnum(settings, "synth.sample-rate", &synth->sample_rate); fluid_settings_getnum(settings, "synth.sample-rate", &synth->sample_rate);
fluid_settings_getint(settings, "synth.midi-channels", &synth->midi_channels); fluid_settings_getint(settings, "synth.midi-channels", &synth->midi_channels);
fluid_settings_getint(settings, "synth.audio-channels", &synth->audio_channels); fluid_settings_getint(settings, "synth.audio-channels", &synth->audio_channels);
@ -1370,21 +1370,24 @@ fluid_synth_cc(fluid_synth_t* synth, int chan, int num, int val)
fluid_return_val_if_fail (num >= 0 && num <= 127, FLUID_FAILED); fluid_return_val_if_fail (num >= 0 && num <= 127, FLUID_FAILED);
fluid_return_val_if_fail (val >= 0 && val <= 127, FLUID_FAILED); fluid_return_val_if_fail (val >= 0 && val <= 127, FLUID_FAILED);
fluid_synth_cc_real (synth, chan, num, val, FALSE); if (synth->verbose)
FLUID_LOG(FLUID_INFO, "cc\t%d\t%d\t%d", chan, num, val);
fluid_channel_set_cc (synth->channel[chan], num, val);
fluid_synth_cc_real (synth, chan, num, FALSE);
return FLUID_OK; return FLUID_OK;
} }
/* Local synthesis thread variant of MIDI CC set function. /* Local synthesis thread variant of MIDI CC set function. */
* NOTE: Gets called out of synthesis context for BANK_SELECT_MSB and
* BANK_SELECT_LSB events, since they should be processed immediately. */
static int static int
fluid_synth_cc_real (fluid_synth_t* synth, int channum, int num, int value, fluid_synth_cc_real (fluid_synth_t* synth, int channum, int num, int noqueue)
int noqueue)
{ {
fluid_channel_t* chan = synth->channel[channum]; fluid_channel_t* chan = synth->channel[channum];
int nrpn_select, nrpn_active = 0; int nrpn_select, nrpn_active = 0;
int rpn_msb = 0, rpn_lsb = 0; int rpn_msb = 0, rpn_lsb = 0;
int value;
/* nrpn_active, rpn_msb and rpn_lsb may get used multiple times, read them /* nrpn_active, rpn_msb and rpn_lsb may get used multiple times, read them
* once atomically if they are needed */ * once atomically if they are needed */
@ -1405,12 +1408,9 @@ fluid_synth_cc_real (fluid_synth_t* synth, int channum, int num, int value,
&& num != BANK_SELECT_MSB && num != BANK_SELECT_LSB && num != BANK_SELECT_MSB && num != BANK_SELECT_LSB
&& !(num == DATA_ENTRY_MSB && !nrpn_active && rpn_msb == 0 && !(num == DATA_ENTRY_MSB && !nrpn_active && rpn_msb == 0
&& (rpn_lsb == RPN_TUNING_PROGRAM_CHANGE || rpn_lsb == RPN_TUNING_BANK_SELECT))) && (rpn_lsb == RPN_TUNING_PROGRAM_CHANGE || rpn_lsb == RPN_TUNING_BANK_SELECT)))
return fluid_synth_queue_midi_event (synth, CONTROL_CHANGE, channum, num, value); return fluid_synth_queue_midi_event (synth, CONTROL_CHANGE, channum, num, 0);
if (synth->verbose) value = fluid_channel_get_cc (chan, num);
FLUID_LOG(FLUID_INFO, "cc\t%d\t%d\t%d", channum, num, value);
fluid_channel_set_cc (chan, num, value);
switch (num) { switch (num) {
case SUSTAIN_SWITCH: case SUSTAIN_SWITCH:
@ -1948,8 +1948,6 @@ fluid_synth_modulate_voices_LOCAL(fluid_synth_t* synth, int chan, int is_cc, int
* Update voices on a MIDI channel after all MIDI controllers have been changed. * Update voices on a MIDI channel after all MIDI controllers have been changed.
* @param synth FluidSynth instance * @param synth FluidSynth instance
* @param chan MIDI channel number (0 to MIDI channel count - 1) * @param chan MIDI channel number (0 to MIDI channel count - 1)
* @param is_cc Boolean value indicating if ctrl is a CC controller or not
* @param ctrl MIDI controller value
* @return FLUID_OK on success, FLUID_FAILED otherwise * @return FLUID_OK on success, FLUID_FAILED otherwise
*/ */
static int static int
@ -2502,16 +2500,16 @@ fluid_synth_set_gain(fluid_synth_t* synth, float gain)
static void static void
fluid_synth_update_gain_LOCAL(fluid_synth_t* synth) fluid_synth_update_gain_LOCAL(fluid_synth_t* synth)
{ {
fluid_voice_t *voice;
float gain; float gain;
int i; int i;
gain = fluid_atomic_float_get (&synth->gain); gain = fluid_atomic_float_get (&synth->gain);
for (i = 0; i < synth->polyphony; i++) { for (i = 0; i < synth->polyphony; i++)
fluid_voice_t* voice = synth->voice[i]; {
if (_PLAYING(voice)) { voice = synth->voice[i];
fluid_voice_set_gain(voice, gain); if (_PLAYING (voice)) fluid_voice_set_gain (voice, gain);
}
} }
} }
@ -2551,7 +2549,7 @@ fluid_synth_set_polyphony(fluid_synth_t* synth, int polyphony)
fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
fluid_return_val_if_fail (polyphony >= 16 && polyphony <= synth->nvoice, FLUID_FAILED); fluid_return_val_if_fail (polyphony >= 16 && polyphony <= synth->nvoice, FLUID_FAILED);
fluid_atomic_int_set (&synth->polyphony, polyphony); fluid_atomic_int_set (&synth->shadow_polyphony, polyphony);
if (fluid_synth_should_queue (synth)) if (fluid_synth_should_queue (synth))
return fluid_synth_queue_int_event (synth, FLUID_EVENT_QUEUE_ELEM_POLYPHONY, 0); return fluid_synth_queue_int_event (synth, FLUID_EVENT_QUEUE_ELEM_POLYPHONY, 0);
@ -2562,16 +2560,16 @@ fluid_synth_set_polyphony(fluid_synth_t* synth, int polyphony)
static int static int
fluid_synth_update_polyphony_LOCAL(fluid_synth_t* synth) fluid_synth_update_polyphony_LOCAL(fluid_synth_t* synth)
{ {
int i, polyphony; fluid_voice_t *voice;
int i;
polyphony = fluid_atomic_int_get (&synth->polyphony); synth->polyphony = fluid_atomic_int_get (&synth->shadow_polyphony);
/* turn off any voices above the new limit */ /* turn off any voices above the new limit */
for (i = polyphony; i < synth->nvoice; i++) { for (i = synth->polyphony; i < synth->nvoice; i++)
fluid_voice_t* voice = synth->voice[i]; {
if (_PLAYING(voice)) { voice = synth->voice[i];
fluid_voice_off(voice); if (_PLAYING (voice)) fluid_voice_off (voice);
}
} }
return FLUID_OK; return FLUID_OK;
@ -2586,7 +2584,7 @@ fluid_synth_update_polyphony_LOCAL(fluid_synth_t* synth)
int int
fluid_synth_get_polyphony(fluid_synth_t* synth) fluid_synth_get_polyphony(fluid_synth_t* synth)
{ {
return fluid_atomic_int_get (&synth->polyphony); return fluid_atomic_int_get (&synth->shadow_polyphony);
} }
/** /**
@ -2990,8 +2988,7 @@ fluid_synth_one_block(fluid_synth_t* synth, int do_not_mix_fx_to_out)
int count; int count;
fluid_profile_ref_var (prof_ref); fluid_profile_ref_var (prof_ref);
/* Assign ID of synthesis thread, if not already set */ /* Assign ID of synthesis thread */
if (synth->synth_thread_id == FLUID_THREAD_ID_NULL)
synth->synth_thread_id = fluid_thread_get_id (); synth->synth_thread_id = fluid_thread_get_id ();
fluid_check_fpe("??? Just starting up ???"); fluid_check_fpe("??? Just starting up ???");
@ -3314,8 +3311,7 @@ fluid_synth_process_event_queue_LOCAL (fluid_synth_t *synth,
break; break;
case CONTROL_CHANGE: case CONTROL_CHANGE:
/* Pass TRUE for noqueue, since event should never get re-queued */ /* Pass TRUE for noqueue, since event should never get re-queued */
fluid_synth_cc_real (synth, event->midi.channel, event->midi.param1, fluid_synth_cc_real (synth, event->midi.channel, event->midi.param1, TRUE);
event->midi.param2, TRUE);
break; break;
case MIDI_SYSTEM_RESET: case MIDI_SYSTEM_RESET:
fluid_synth_system_reset_LOCAL (synth); fluid_synth_system_reset_LOCAL (synth);
@ -3522,8 +3518,9 @@ fluid_synth_alloc_voice(fluid_synth_t* synth, fluid_sample_t* sample, int chan,
channel = synth->channel[chan]; channel = synth->channel[chan];
} }
if (fluid_voice_init(voice, sample, channel, key, vel, if (fluid_voice_init (voice, sample, channel, key, vel,
synth->storeid, synth->ticks, synth->gain) != FLUID_OK) { synth->storeid, synth->ticks,
fluid_atomic_float_get (&synth->gain)) != FLUID_OK) {
FLUID_LOG(FLUID_WARN, "Failed to initialize voice"); FLUID_LOG(FLUID_WARN, "Failed to initialize voice");
return NULL; return NULL;
} }

View file

@ -162,7 +162,8 @@ struct _fluid_synth_t
fluid_settings_t* settings; /**< the synthesizer settings */ fluid_settings_t* settings; /**< the synthesizer settings */
int device_id; /**< Device ID used for SYSEX messages */ int device_id; /**< Device ID used for SYSEX messages */
int polyphony; /**< maximum polyphony */ int polyphony; /**< Maximum polyphony */
int shadow_polyphony; /**< Maximum polyphony shadow value (for non-synth threads) */
int with_reverb; /**< Should the synth use the built-in reverb unit? */ int with_reverb; /**< Should the synth use the built-in reverb unit? */
int with_chorus; /**< Should the synth use the built-in chorus unit? */ int with_chorus; /**< Should the synth use the built-in chorus unit? */
int verbose; /**< Turn verbose mode on? */ int verbose; /**< Turn verbose mode on? */

View file

@ -736,10 +736,14 @@ delete_fluid_timer (fluid_timer_t *timer)
int int
fluid_timer_join (fluid_timer_t *timer) fluid_timer_join (fluid_timer_t *timer)
{ {
int auto_destroy;
if (timer->thread) if (timer->thread)
{ {
auto_destroy = timer->auto_destroy;
fluid_thread_join (timer->thread); fluid_thread_join (timer->thread);
timer->thread = NULL;
if (!auto_destroy) timer->thread = NULL;
} }
return FLUID_OK; return FLUID_OK;