Hi all,

I'm still having problems (with CVS HEAD) with memory not being freed.  This 
seems to have been caused by still-active voices maintaining their lock on 
the sfont's refcount (see start of delete_fluid_defsfont() in 
src/fluid_defsfont.c).

The solution I've attached is to explicitly call fluid_voice_off() before 
trying to delete the sfont(s).  This should be OK, right?  For neatness, I've 
also updated fluid_voice.c so neither fluid_voice_off( NULL)  nor calling 
fluid_voice_off() twice with the same voice crashes fluidsynth.

I found a couple of other minor memory leaks: the string tokenizer usage in 
fluid_settings.c and a leaked FILE pointer in fluid_defsfont.c.  Both should 
be fixed in the patch.

With these changes, I'm now only seeing a leak of around 10kB or so.  This all 
seems to come from libasound and libc, and (from what I can see) isn't  
fluidsynth's fault.

I've tested the code against my simple test-case and it seems to work OK.  
But, I'm new to fluidsynth code; perhaps some more familiar with the 
code-base should review this patch.

Cheers,

Paul.
Index: src/fluid_defsfont.c
===================================================================
RCS file: /sources/fluid/fluidsynth/src/fluid_defsfont.c,v
retrieving revision 1.11
diff -u -r1.11 fluid_defsfont.c
--- src/fluid_defsfont.c	23 Nov 2006 18:49:36 -0000	1.11
+++ src/fluid_defsfont.c	28 Nov 2006 19:30:15 -0000
@@ -311,10 +311,10 @@
     sfsample = (SFSample *) p->data;
     sample = new_fluid_sample();
     if (sample == NULL) {
-      return FLUID_FAILED;
+      goto err_exit;
     }
     if (fluid_sample_import_sfont(sample, sfsample, sfont) != FLUID_OK) {
-      return FLUID_FAILED;
+      goto err_exit;
     }
     fluid_defsfont_add_sample(sfont, sample);
     fluid_voice_optimize_sample(sample);
@@ -327,10 +327,10 @@
     sfpreset = (SFPreset *) p->data;
     preset = new_fluid_defpreset(sfont);
     if (preset == NULL) {
-      return FLUID_FAILED;
+      goto err_exit;
     }
     if (fluid_defpreset_import_sfont(preset, sfpreset, sfont) != FLUID_OK) {
-      return FLUID_FAILED;
+      goto err_exit;
     }
     fluid_defsfont_add_preset(sfont, preset);
     p = fluid_list_next(p);
@@ -338,6 +338,10 @@
   sfont_free_data(sfdata);
 
   return FLUID_OK;
+
+ err_exit:
+  sfont_free_data( sfdata);
+  return FLUID_FAILED;
 }
 
 /* fluid_defsfont_add_sample
@@ -3027,6 +3031,9 @@
   if (sf->fname)
     free (sf->fname);
 
+  if( sf->sffd)
+    fclose( sf->sffd);
+
   p = sf->info;
   while (p)
     {
Index: src/fluid_settings.c
===================================================================
RCS file: /sources/fluid/fluidsynth/src/fluid_settings.c,v
retrieving revision 1.2
diff -u -r1.2 fluid_settings.c
--- src/fluid_settings.c	23 Nov 2006 18:49:36 -0000	1.2
+++ src/fluid_settings.c	28 Nov 2006 19:30:15 -0000
@@ -32,6 +32,8 @@
 static void fluid_settings_hash_delete(void* value, int type);
 static int fluid_settings_tokenize(char* s, char* buf, char** ptr);
 
+static fluid_strtok_t* fluid_settings_strtok = NULL;
+
 
 typedef struct {
   char* value;
@@ -167,6 +169,11 @@
 
 void delete_fluid_settings(fluid_settings_t* settings)
 {
+  if( fluid_settings_strtok) {
+    delete_fluid_strtok( fluid_settings_strtok);
+    fluid_settings_strtok = NULL;
+  }
+
   delete_fluid_hashtable(settings);
 }
 
@@ -196,8 +203,6 @@
   fluid_midi_driver_settings(settings);
 }
 
-static fluid_strtok_t* fluid_settings_strtok = NULL;
-
 int fluid_settings_tokenize(char* s, char* buf, char** ptr)
 {
   int n = 0;
@@ -214,6 +219,7 @@
     ptr[n++] = fluid_strtok_next_token(fluid_settings_strtok);
   }
 
+
   return n;
 }
 
Index: src/fluid_synth.c
===================================================================
RCS file: /sources/fluid/fluidsynth/src/fluid_synth.c,v
retrieving revision 1.17
diff -u -r1.17 fluid_synth.c
--- src/fluid_synth.c	23 Nov 2006 18:49:36 -0000	1.17
+++ src/fluid_synth.c	28 Nov 2006 19:30:15 -0000
@@ -601,6 +601,18 @@
 
   synth->state = FLUID_SYNTH_STOPPED;
 
+  /* turn off all voices, needed to unload SoundFonts */
+  if (synth->voice != NULL) {
+    for (i = 0; i < synth->nvoice; i++) {
+      
+      if( !synth->voice[i] ||!fluid_voice_is_playing( synth->voice[i]))
+	continue;
+      
+      fluid_voice_off(synth->voice[i]);
+    }
+  }
+  
+
   /* delete all the SoundFonts */
   for (list = synth->sfont; list; list = fluid_list_next(list)) {
     sfont = (fluid_sfont_t*) fluid_list_get(list);
@@ -639,9 +651,7 @@
 
   if (synth->voice != NULL) {
     for (i = 0; i < synth->nvoice; i++) {
-      if (synth->voice[i] != NULL) {
-	delete_fluid_voice(synth->voice[i]);
-      }
+      delete_fluid_voice(synth->voice[i]);
     }
     FLUID_FREE(synth->voice);
   }
Index: src/fluid_voice.c
===================================================================
RCS file: /sources/fluid/fluidsynth/src/fluid_voice.c,v
retrieving revision 1.16
diff -u -r1.16 fluid_voice.c
--- src/fluid_voice.c	18 Feb 2006 23:46:34 -0000	1.16
+++ src/fluid_voice.c	28 Nov 2006 19:30:15 -0000
@@ -1708,6 +1708,10 @@
 int 
 fluid_voice_off(fluid_voice_t* voice)
 {
+  if( voice == NULL) {
+    return FLUID_OK;
+  }
+
   fluid_profile(FLUID_PROF_VOICE_RELEASE, voice->ref);
 
   voice->chan = NO_CHANNEL;
@@ -1718,9 +1722,10 @@
   voice->status = FLUID_VOICE_OFF;
 
   /* Decrement the reference count of the sample. */
-  fluid_sample_decr_ref(voice->sample);
-
-  voice->sample = NULL;
+  if( voice->sample) {
+    fluid_sample_decr_ref(voice->sample);
+    voice->sample = NULL;
+  }
 
   return FLUID_OK;
 }

Attachment: pgpdh6GAbrrIV.pgp
Description: PGP signature

_______________________________________________
fluid-dev mailing list
[email protected]
http://lists.nongnu.org/mailman/listinfo/fluid-dev

Reply via email to