[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[fluid-dev] Re: FluidSynth 1.0.9 release (was Re: Patch for bad MIDI tim
From: |
David Henningsson |
Subject: |
[fluid-dev] Re: FluidSynth 1.0.9 release (was Re: Patch for bad MIDI timing (with large buffer sizes)) |
Date: |
Mon, 16 Mar 2009 06:40:00 +0100 |
User-agent: |
Thunderbird 2.0.0.19 (X11/20090105) |
Josh Green skrev:
> A FluidSynth release is long overdue. I already let the tentative date
> of March 9th slip. I'm buried in work right now, so I've had very
> little time to put into any free software projects.
>
> This patch seems like a pretty fundamental change, though good one. Its
> tempting to try and include it in 1.0.9. If there was a build time or
> runtime option to select this new timing source, that would be ideal.
According to a later e-mail you seem to have reconsidered about this, or
maybe I misunderstood you. So here's a patch that enables "slave timers"
(I call them "sample timers" in the source) only if a new option is
enabled, "player.timing-source=sample".
The pro's of applying this patch for 1.0.9 are:
- We get the same output every time (although not faster than real-time)
- Faster-than-real-time will be possible for everyone using the library
and want to process the audio themselves.
- Risk for regressions are minimized since the option is disabled by
default (although it should be enabled by default for 1.1.0).
- And, after all, every 0.9 release should contain a sneak preview of
the upcoming 1.0 features ;-)
// David
Index: src/fluid_settings.c
===================================================================
--- src/fluid_settings.c (revision 162)
+++ src/fluid_settings.c (arbetskopia)
@@ -26,6 +26,7 @@
#include "fluid_adriver.h"
#include "fluid_mdriver.h"
#include "fluid_settings.h"
+#include "fluid_midi.h"
/* maximum allowed components of a settings variable (separated by '.') */
#define MAX_SETTINGS_TOKENS 8 /* currently only a max of 3 are used */
@@ -195,6 +196,7 @@
{
fluid_synth_settings(settings);
fluid_shell_settings(settings);
+ fluid_player_settings(settings);
fluid_audio_driver_settings(settings);
fluid_midi_driver_settings(settings);
}
Index: src/fluid_settings.h
===================================================================
--- src/fluid_settings.h (revision 162)
+++ src/fluid_settings.h (arbetskopia)
@@ -35,18 +35,18 @@
typedef int (*fluid_str_update_t)(void* data, char* name, char* value);
typedef int (*fluid_int_update_t)(void* data, char* name, int value);
-/** returns 0 if the value has been resgister correctly, non-zero
+/** returns 0 if the value has been registered correctly, non-zero
otherwise */
int fluid_settings_register_str(fluid_settings_t* settings, char* name, char*
def, int hints,
fluid_str_update_t fun, void* data);
-/** returns 0 if the value has been resgister correctly, non-zero
+/** returns 0 if the value has been registered correctly, non-zero
otherwise */
int fluid_settings_register_num(fluid_settings_t* settings, char* name, double
min, double max,
double def, int hints, fluid_num_update_t fun,
void* data);
-/** returns 0 if the value has been resgister correctly, non-zero
+/** returns 0 if the value has been registered correctly, non-zero
otherwise */
int fluid_settings_register_int(fluid_settings_t* settings, char* name, int
min, int max,
int def, int hints, fluid_int_update_t fun,
void* data);
Index: src/fluid_synth.c
===================================================================
--- src/fluid_synth.c (revision 162)
+++ src/fluid_synth.c (arbetskopia)
@@ -331,6 +331,70 @@
}
/***************************************************************
+ * FLUID SAMPLE TIMERS
+ * Timers that use written audio data as timing reference
+ */
+struct _fluid_sample_timer_t
+{
+ fluid_sample_timer_t* next; /* Single linked list of timers */
+ unsigned long starttick;
+ fluid_timer_callback_t callback;
+ void* data;
+ int isfinished;
+};
+
+/*
+ * fluid_sample_timer_process - called when synth->ticks is updated
+ */
+void fluid_sample_timer_process(fluid_synth_t* synth)
+{
+ fluid_sample_timer_t* st;
+ for (st=synth->sample_timers; st; st=st->next) {
+ if (st->isfinished) {
+ continue;
+ }
+
+ long msec = (long) (1000.0*((double) (synth->ticks -
st->starttick))/synth->sample_rate);
+ int cont = (*st->callback)(st->data, msec);
+ if (cont == 0) {
+ st->isfinished = 1;
+ }
+ }
+}
+
+fluid_sample_timer_t* new_fluid_sample_timer(fluid_synth_t* synth,
fluid_timer_callback_t callback, void* data)
+{
+ fluid_sample_timer_t* result = FLUID_NEW(fluid_sample_timer_t);
+ if (result == NULL) {
+ FLUID_LOG(FLUID_ERR, "Out of memory");
+ return NULL;
+ }
+ result->starttick = synth->ticks;
+ result->isfinished = 0;
+ result->data = data;
+ result->callback = callback;
+ result->next = synth->sample_timers;
+ synth->sample_timers = result;
+ return result;
+}
+
+int delete_fluid_sample_timer(fluid_synth_t* synth, fluid_sample_timer_t*
timer)
+{
+ fluid_sample_timer_t** ptr = &synth->sample_timers;
+ while (*ptr) {
+ if (*ptr == timer) {
+ *ptr = timer->next;
+ FLUID_FREE(timer);
+ return FLUID_OK;
+ }
+ ptr = &((*ptr)->next);
+ }
+ FLUID_LOG(FLUID_ERR,"delete_fluid_sample_timer failed, no timer found");
+ return FLUID_FAILED;
+}
+
+
+/***************************************************************
*
* FLUID SYNTH
*/
@@ -2029,6 +2093,10 @@
/* fluid_mutex_unlock(synth->busy); /\* Allow other threads to touch the
synth *\/ */
+ fluid_sample_timer_process(synth);
+
+ fluid_check_fpe("fluid_sample_timer_process");
+
return 0;
}
Index: src/fluid_synth.h
===================================================================
--- src/fluid_synth.h (revision 162)
+++ src/fluid_synth.h (arbetskopia)
@@ -81,7 +81,6 @@
int offset;
};
-
/*
* fluid_synth_t
*/
@@ -144,6 +143,8 @@
* Note: This simple scheme does -not-
provide 100 % protection against
* thread problems, for example from
MIDI thread and shell thread
*/
+ fluid_sample_timer_t* sample_timers; /* List of timers triggered after a
block has been processed */
+
#ifdef LADSPA
fluid_LADSPA_FxUnit_t* LADSPA_FxUnit; /** Effects unit for LADSPA support */
#endif
@@ -208,6 +209,10 @@
void fluid_synth_dither_s16(int *dither_index, int len, float* lin, float* rin,
void* lout, int loff, int lincr,
void* rout, int roff, int rincr);
+
+fluid_sample_timer_t* new_fluid_sample_timer(fluid_synth_t* synth,
fluid_timer_callback_t callback, void* data);
+int delete_fluid_sample_timer(fluid_synth_t* synth, fluid_sample_timer_t*
timer);
+
/*
* misc
*/
Index: src/fluidsynth_priv.h
===================================================================
--- src/fluidsynth_priv.h (revision 162)
+++ src/fluidsynth_priv.h (arbetskopia)
@@ -232,6 +232,7 @@
typedef struct _fluid_hashtable_t fluid_hashtable_t;
typedef struct _fluid_client_t fluid_client_t;
typedef struct _fluid_server_socket_t fluid_server_socket_t;
+typedef struct _fluid_sample_timer_t fluid_sample_timer_t;
/***************************************************************
*
Index: src/fluid_midi.c
===================================================================
--- src/fluid_midi.c (revision 162)
+++ src/fluid_midi.c (arbetskopia)
@@ -1120,6 +1120,7 @@
fluid_player_t* new_fluid_player(fluid_synth_t* synth)
{
int i;
+ char* timing_source;
fluid_player_t* player;
player = FLUID_NEW(fluid_player_t);
if (player == NULL) {
@@ -1133,13 +1134,22 @@
player->track[i] = NULL;
}
player->synth = synth;
- player->timer = NULL;
+ player->system_timer = NULL;
+ player->sample_timer = NULL;
player->playlist = NULL;
player->current_file = NULL;
player->division = 0;
player->send_program_change = 1;
player->miditempo = 480000;
player->deltatime = 4.0;
+
+ player->use_system_timer = 0;
+ if (fluid_settings_getstr(synth->settings, "player.timing-source",
&timing_source) != 0) {
+ if (strcmp(timing_source, "system") == 0) {
+ player->use_system_timer = 1;
+ }
+ }
+
return player;
}
@@ -1159,6 +1169,17 @@
return FLUID_OK;
}
+/**
+ * Registers settings related to the MIDI player
+ */
+void fluid_player_settings(fluid_settings_t* settings)
+{
+ /* player.timing-source can be either "system" (use system timer)
+ or "sample" (use timer based on number of written samples) */
+ fluid_settings_register_str(settings, "player.timing-source", "system",
0, NULL, NULL);
+}
+
+
int fluid_player_reset(fluid_player_t* player)
{
int i;
@@ -1327,10 +1348,20 @@
player->status = FLUID_PLAYER_PLAYING;
- player->timer = new_fluid_timer((int) player->deltatime,
fluid_player_callback,
+ if (player->use_system_timer) {
+ player->system_timer = new_fluid_timer((int) player->deltatime,
fluid_player_callback,
(void*) player, 1, 0);
- if (player->timer == NULL) {
- return FLUID_FAILED;
+ if (player->system_timer == NULL) {
+ return FLUID_FAILED;
+ }
+ } else {
+ player->sample_timer = new_fluid_sample_timer(player->synth,
fluid_player_callback,
+ (void*) player);
+
+ if (player->sample_timer == NULL) {
+ return FLUID_FAILED;
+ }
+ fluid_player_callback(player, 0); /* Process the first events
before the first block */
}
return FLUID_OK;
}
@@ -1342,14 +1373,19 @@
*/
int fluid_player_stop(fluid_player_t* player)
{
- if (player->timer != NULL) {
- delete_fluid_timer(player->timer);
+ if (player->system_timer != NULL) {
+ delete_fluid_timer(player->system_timer);
}
+ if (player->sample_timer != NULL) {
+ delete_fluid_sample_timer(player->synth, player->sample_timer);
+ }
player->status = FLUID_PLAYER_DONE;
- player->timer = NULL;
+ player->sample_timer = NULL;
+ player->system_timer = NULL;
return FLUID_OK;
}
+
/* FIXME - Looping seems to not actually be implemented? */
/**
@@ -1403,7 +1439,21 @@
*/
int fluid_player_join(fluid_player_t* player)
{
- return player->timer? fluid_timer_join(player->timer) : FLUID_OK;
+ if (player->system_timer) {
+ return fluid_timer_join(player->system_timer);
+ } else if (player->sample_timer) {
+ /* Busy-wait loop, since there's no thread to wait for... */
+ while (player->status == FLUID_PLAYER_PLAYING) {
+#if defined(WIN32)
+ Sleep(10);
+#elif defined(MACOS9)
+ /* FIXME: How do we sleep in Macos9? */
+#else
+ usleep(10000);
+#endif
+ }
+ }
+ return FLUID_OK;
}
/************************************************************************
Index: src/fluid_midi.h
===================================================================
--- src/fluid_midi.h (revision 162)
+++ src/fluid_midi.h (arbetskopia)
@@ -249,10 +249,12 @@
int ntracks;
fluid_track_t *track[MAX_NUMBER_OF_TRACKS];
fluid_synth_t* synth;
- fluid_timer_t* timer;
+ fluid_timer_t* system_timer;
+ fluid_sample_timer_t* sample_timer;
fluid_list_t* playlist;
char* current_file;
char send_program_change; /* should we ignore the program changes? */
+ char use_system_timer; /* if zero, use sample timers, otherwise use system
clock timer */
int start_ticks; /* the number of tempo ticks passed at the last
tempo change */
int cur_ticks; /* the number of tempo ticks passed */
int begin_msec; /* the time (msec) of the beginning of the file */
@@ -270,7 +272,9 @@
int fluid_player_reset(fluid_player_t* player);
int fluid_player_load(fluid_player_t* player, char *filename);
+void fluid_player_settings(fluid_settings_t* settings);
+
/*
* fluid_midi_file
*/
- Re: [fluid-dev] Patch for bad MIDI timing (with large buffer sizes), (continued)
- Re: [fluid-dev] Patch for bad MIDI timing (with large buffer sizes), Pedro Lopez-Cabanillas, 2009/03/21
- Re: [fluid-dev] Patch for bad MIDI timing (with large buffer sizes), Bernat Arlandis i Mañó, 2009/03/21
- Re: [fluid-dev] Patch for bad MIDI timing (with large buffer sizes), David Henningsson, 2009/03/16
- Re: [fluid-dev] Patch for bad MIDI timing (with large buffer sizes), Pedro Lopez-Cabanillas, 2009/03/16
- Re: [fluid-dev] Patch for bad MIDI timing (with large buffer sizes), David Henningsson, 2009/03/17
- [fluid-dev] FluidSynth 1.0.9 release (was Re: Patch for bad MIDI timing (with large buffer sizes)), Josh Green, 2009/03/14
- [fluid-dev] Re: FluidSynth 1.0.9 release (was Re: Patch for bad MIDI timing (with large buffer sizes)),
David Henningsson <=
- Re: [fluid-dev] Patch for bad MIDI timing (with large buffer sizes), Bernat Arlandis i Mañó, 2009/03/16
- Re: [fluid-dev] Patch for bad MIDI timing (with large buffer sizes), Pedro Lopez-Cabanillas, 2009/03/16
- Re: [fluid-dev] Patch for bad MIDI timing (with large buffer sizes), David Henningsson, 2009/03/14