fluid-dev
[Top][All Lists]
Advanced

[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
  */


reply via email to

[Prev in Thread] Current Thread [Next in Thread]