[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[fluid-dev] Patch for bad MIDI timing (with large buffer sizes)
From: |
David Henningsson |
Subject: |
[fluid-dev] Patch for bad MIDI timing (with large buffer sizes) |
Date: |
Fri, 13 Mar 2009 14:27:52 +0100 |
User-agent: |
Thunderbird 2.0.0.19 (X11/20090105) |
Hi!
I was thinking of having libfluidsynth playing background music in a
game, and tried it out a bit. The ability to change the music while
playing was important in this case (e g change track volumes without
restarting the file), so this made libfluidsynth a better choice than
other midi engines.
However, the default buffer size of 64 meant a lot of glitches in the
audio stream, and in this case latency was less important, so a large
buffer size was a must. It didn't take long to realize what this
actually did to the MIDI timing.
So, I went ahead and fixed it. I guess this opens up for the possibility
to render MIDI files faster as well, but I haven't looked into that.
Anyway, here's the patch. I made it in debdiff format, and against the
1.0.8 source, because that was the simplest way for me, but I can
probably fix another patch format if needed.
Enjoy!
// David
diff -u fluidsynth-1.0.8/debian/changelog fluidsynth-1.0.8/debian/changelog
--- fluidsynth-1.0.8/debian/changelog
+++ fluidsynth-1.0.8/debian/changelog
@@ -1,3 +1,9 @@
+fluidsynth (1.0.8-1.1ubuntu1) intrepid; urgency=low
+
+ * Fix timing problems with playing MIDI files at large buffer sizes
+
+ -- David Henningsson <address@hidden> Fri, 13 Mar 2009 09:16:40 +0100
+
fluidsynth (1.0.8-1.1) unstable; urgency=low
* Non-maintainer upload.
only in patch2:
unchanged:
--- fluidsynth-1.0.8.orig/src/fluid_synth.c
+++ fluidsynth-1.0.8/src/fluid_synth.c
@@ -330,6 +330,70 @@
}
/***************************************************************
+ * FLUID SYNTH TIMERS
+ * Timers that use written audio data as timing reference
+ */
+struct _fluid_synth_timer_t
+{
+ fluid_synth_timer_t* next; /* Single linked list of timers */
+ unsigned long starttick;
+ fluid_timer_callback_t callback;
+ void* data;
+ int isfinished;
+};
+
+/*
+ * fluid_synth_timer_process - called when synth->ticks is updated
+ */
+void fluid_synth_timer_process(fluid_synth_t* synth)
+{
+ fluid_synth_timer_t* st;
+ for (st=synth->synth_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_synth_timer_t* new_fluid_synth_timer(fluid_synth_t* synth,
fluid_timer_callback_t callback, void* data)
+{
+ fluid_synth_timer_t* result = FLUID_NEW(fluid_synth_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->synth_timers;
+ synth->synth_timers = result;
+ return result;
+}
+
+int delete_fluid_synth_timer(fluid_synth_t* synth, fluid_synth_timer_t* timer)
+{
+ fluid_synth_timer_t** ptr = &synth->synth_timers;
+ while (*ptr) {
+ if (*ptr == timer) {
+ *ptr = timer->next;
+ FLUID_FREE(timer);
+ return FLUID_OK;
+ }
+ ptr = &((*ptr)->next);
+ }
+ FLUID_LOG(FLUID_ERR,"delete_fluid_synth_timer failed, no timer found");
+ return FLUID_FAILED;
+}
+
+
+/***************************************************************
*
* FLUID SYNTH
*/
@@ -1957,6 +2021,10 @@
/* fluid_mutex_unlock(synth->busy); /\* Allow other threads to touch the
synth *\/ */
+ fluid_synth_timer_process(synth);
+
+ fluid_check_fpe("fluid_synth_timer_process");
+
return 0;
}
only in patch2:
unchanged:
--- fluidsynth-1.0.8.orig/src/fluid_midi.h
+++ fluidsynth-1.0.8/src/fluid_midi.h
@@ -239,7 +239,7 @@
int ntracks;
fluid_track_t *track[MAX_NUMBER_OF_TRACKS];
fluid_synth_t* synth;
- fluid_timer_t* timer;
+ fluid_synth_timer_t* timer;
fluid_list_t* playlist;
char* current_file;
char send_program_change; /* should we ignore the program changes? */
only in patch2:
unchanged:
--- fluidsynth-1.0.8.orig/src/fluid_midi.c
+++ fluidsynth-1.0.8/src/fluid_midi.c
@@ -1325,8 +1325,11 @@
player->status = FLUID_PLAYER_PLAYING;
- player->timer = new_fluid_timer((int) player->deltatime,
fluid_player_callback,
- (void*) player, 1, 0);
+ player->timer = new_fluid_synth_timer(player->synth,
fluid_player_callback,
+ (void*) player);
+
+/* player->timer = new_fluid_timer((int) player->deltatime,
fluid_player_callback,
+ (void*) player, 1, 0);*/
if (player->timer == NULL) {
return FLUID_FAILED;
}
@@ -1341,7 +1344,8 @@
int fluid_player_stop(fluid_player_t* player)
{
if (player->timer != NULL) {
- delete_fluid_timer(player->timer);
+ delete_fluid_synth_timer(player->synth, player->timer);
+ /*delete_fluid_timer(player->timer);*/
}
player->status = FLUID_PLAYER_DONE;
player->timer = NULL;
@@ -1401,7 +1405,11 @@
*/
int fluid_player_join(fluid_player_t* player)
{
- return player->timer? fluid_timer_join(player->timer) : FLUID_OK;
+ if (player->timer) {
+ fluid_player_stop(player);
+ }
+ return FLUID_OK;
+/* return player->timer? fluid_timer_join(player->timer) : FLUID_OK;*/
}
/************************************************************************
only in patch2:
unchanged:
--- fluidsynth-1.0.8.orig/src/fluidsynth_priv.h
+++ fluidsynth-1.0.8/src/fluidsynth_priv.h
@@ -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_synth_timer_t fluid_synth_timer_t;
/***************************************************************
*
only in patch2:
unchanged:
--- fluidsynth-1.0.8.orig/src/fluid_synth.h
+++ fluidsynth-1.0.8/src/fluid_synth.h
@@ -144,6 +144,7 @@
* Note: This simple scheme does -not-
provide 100 % protection against
* thread problems, for example from
MIDI thread and shell thread
*/
+ fluid_synth_timer_t* synth_timers;
#ifdef LADSPA
fluid_LADSPA_FxUnit_t* LADSPA_FxUnit; /** Effects unit for LADSPA support */
#endif
@@ -208,6 +209,12 @@
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);
+/* Synth timers */
+
+fluid_synth_timer_t* new_fluid_synth_timer(fluid_synth_t* synth,
fluid_timer_callback_t callback, void* data);
+
+int delete_fluid_synth_timer(fluid_synth_t* synth, fluid_synth_timer_t* timer);
+
/*
* misc
*/
- [fluid-dev] Patch for bad MIDI timing (with large buffer sizes),
David Henningsson <=
- Re: [fluid-dev] Patch for bad MIDI timing (with large buffer sizes), David Henningsson, 2009/03/13
- Re: [fluid-dev] Patch for bad MIDI timing (with large buffer sizes), Pedro Lopez-Cabanillas, 2009/03/14
- Re: [fluid-dev] Patch for bad MIDI timing (with large buffer sizes), Bernat Arlandis i Mañó, 2009/03/14
- Re: [fluid-dev] Patch for bad MIDI timing (with large buffer sizes), Pedro Lopez-Cabanillas, 2009/03/14
- Re: [fluid-dev] Patch for bad MIDI timing (with large buffer sizes), David Henningsson, 2009/03/14
- Re: [fluid-dev] Patch for bad MIDI timing (with large buffer sizes), Pedro Lopez-Cabanillas, 2009/03/14
- Re: [fluid-dev] Patch for bad MIDI timing (with large buffer sizes), David Henningsson, 2009/03/15
- Re: [fluid-dev] Patch for bad MIDI timing (with large buffer sizes), Pedro Lopez-Cabanillas, 2009/03/15