fluid-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [fluid-dev] invalid instrument/drum selection problem


From: Bernhard Schelling
Subject: Re: [fluid-dev] invalid instrument/drum selection problem
Date: Tue, 08 Jan 2008 00:40:21 +0100
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8.1.9) Gecko/20071030 SeaMonkey/1.1.6

Hi guys

Sorry I'm late to the party and I'm not even sure if I can be helpful :-)

We, too, are using FluidSynth's MIDI file reading and playing capabilities so 
we naturally stumbled on the same issues over development/testing.
Here are two patches which show all our fixes concerning these features.

I may add, that I don't know much about the MIDI standards and my fixes were 
made 'on-the-fly' during testing with many different MIDIs from all over the 
web.

I actually wanted to post all my changes a few months ago but then I thought to wait until our project is actually in a more finished/releasable state. Then we somehow got stuck and had to devote ourself to other (commercial, eww) work, so the project is kinda on hold at the moment. Other changes include external use of FluidSynth's MIDI reading/parsing functionality and a 'hacked' implementation of a sound font format with ogg vorbis compressed sample data (including a vorbis compressing soundfont converter implemented/hacked directly into FluidSynth's code).

The first one is my solution to the drumset (and other instruments actually, 
too) selection problem.
The second one fixes a few things with starting and stopping voices when playing MIDI files. I had test midis which actually played the same channel/key note again without releasing the first one before (and with two note offs later). I solved this by storing the exact start time of the noteon in the voice and only releasing the newest voices (reversing the for loop in fluid_synth_noteoff) which were started at the same time.


Index: src/fluid_synth.c
===================================================================
--- src/fluid_synth.c   (Revision 124)
+++ src/fluid_synth.c   (Arbeitskopie)
@@ -1193,13 +1193,32 @@
       /* try to search the drum instrument first */
       preset = fluid_synth_find_preset(synth, banknum | DRUM_INST_MASK, 
prognum);

+      /* then try to search the basic (0) drum instrument */
+      if (preset == NULL) preset = fluid_synth_find_preset(synth, banknum | 
DRUM_INST_MASK, 0);
+
+      /* try to search the drum instrument first */
+      if (preset == NULL) preset = fluid_synth_find_preset(synth, banknum | 
128, prognum);
+
+      /* then try to search the basic (0) drum instrument */
+      if (preset == NULL) preset = fluid_synth_find_preset(synth, banknum | 
128, 0);
+
+      /* try to search the drum instrument first */
+      if (preset == NULL) preset = fluid_synth_find_preset(synth, 128, 
prognum);
+
+      /* then try to search the basic (0) drum instrument */
+      if (preset == NULL) preset = fluid_synth_find_preset(synth, 128, 0);
+
       /* if that fails try to search the melodic instrument */
       if (preset == NULL) {
        preset = fluid_synth_find_preset(synth, banknum, prognum);
       }

     } else {
+      /* try to search the melodic instrument in the selected bank first */
       preset = fluid_synth_find_preset(synth, banknum, prognum);
+
+      /* if that fails try to search the melodic instrument in the base bank */
+      if (preset == NULL) preset = fluid_synth_find_preset(synth, 0, prognum);
     }

     sfont_id = preset? fluid_sfont_get_id(preset->sfont) : 0;




===============================================================================================================
===============================================================================================================
===============================================================================================================
===============================================================================================================




Index: include/fluidsynth/synth.h
===================================================================
--- include/fluidsynth/synth.h  (Revision 124)
+++ include/fluidsynth/synth.h  (Arbeitskopie)
@@ -669,7 +671,7 @@
       Note: A single noteon event may create any number of voices, when the 
preset is layered.
       Typically 1 (mono) or 2 (stereo).*/
 FLUIDSYNTH_API fluid_voice_t* fluid_synth_alloc_voice(fluid_synth_t* synth, 
fluid_sample_t* sample,
-                                                  int channum, int key, int 
vel);
+                                                  int channum, int key, int 
vel, int start_time);

   /** Start a synthesis voice. This function is called by a
       soundfont's preset in response to a noteon event after the voice
Index: src/fluid_ramsfont.c
===================================================================
--- src/fluid_ramsfont.c        (Revision 124)
+++ src/fluid_ramsfont.c        (Arbeitskopie)
@@ -798,7 +799,8 @@
   fluid_mod_t * mod_list[FLUID_NUM_MOD]; /* list for 'sorting' preset 
modulators */
   int mod_list_count;
   int i;
-
+  unsigned int start_time = synth->ticks;
+
   /* run thru all the zones of this preset */
   preset_zone = preset->zone;
   while (preset_zone != NULL) {
@@ -829,7 +831,7 @@
          /* this is a good zone. allocate a new synthesis process and
              initialize it */

-         voice = fluid_synth_alloc_voice(synth, sample, chan, key, vel);
+         voice = fluid_synth_alloc_voice(synth, sample, chan, key, vel, 
start_time);
          if (voice == NULL) {
            return FLUID_FAILED;
          }
Index: src/fluid_defsfont.c
===================================================================
--- src/fluid_defsfont.c        (Revision 124)
+++ src/fluid_defsfont.c        (Arbeitskopie)
@@ -25,7 +25,8 @@
 #include "fluid_defsfont.h"
 /* Todo: Get rid of that 'include' */
 #include "fluid_sys.h"
+#include "fluid_synth.h"

 /***************************************************************
  *
  *                           SFONT LOADER
@@ -597,7 +599,8 @@
   fluid_mod_t * mod_list[FLUID_NUM_MOD]; /* list for 'sorting' preset 
modulators */
   int mod_list_count;
   int i;
-
+  unsigned int start_time = synth->ticks;
+
   global_preset_zone = fluid_defpreset_get_global_zone(preset);

   /* run thru all the zones of this preset */
@@ -630,7 +633,7 @@
          /* this is a good zone. allocate a new synthesis process and
              initialize it */

-         voice = fluid_synth_alloc_voice(synth, sample, chan, key, vel);
+         voice = fluid_synth_alloc_voice(synth, sample, chan, key, vel, 
start_time);
          if (voice == NULL) {
            return FLUID_FAILED;
          }
Index: src/fluid_synth.c
===================================================================
--- src/fluid_synth.c   (Revision 124)
+++ src/fluid_synth.c   (Arbeitskopie)
@@ -758,9 +758,9 @@
     return FLUID_FAILED;
   }

-  /* If there is another voice process on the same channel and key,
-     advance it to the release phase. */
-  fluid_synth_release_voice_on_same_note(synth, chan, key);
+  ///* If there is another voice process on the same channel and key,
+  //   advance it to the release phase. */
+  //fluid_synth_release_voice_on_same_note(synth, chan, key);

   return fluid_synth_start(synth, synth->noteid++, channel->preset, 0, chan, 
key, vel);
 }
@@ -776,27 +776,32 @@
   int status = FLUID_FAILED;
 /*   fluid_mutex_lock(synth->busy); /\* Don't interfere with the audio thread 
*\/ */
 /*   fluid_mutex_unlock(synth->busy); */
-
-  for (i = 0; i < synth->polyphony; i++) {
+
+  //for (i = 0; i < synth->polyphony; i++) {
+  unsigned int iOffStartTime = 0;
+  for (i = synth->polyphony-1; i >= 0; i--) {
     voice = synth->voice[i];
     if (_ON(voice) && (voice->chan == chan) && (voice->key == key)) {
-      if (synth->verbose) {
-       int used_voices = 0;
-       int k;
-       for (k = 0; k < synth->polyphony; k++) {
-         if (!_AVAILABLE(synth->voice[k])) {
-           used_voices++;
+      if ((!iOffStartTime) || (voice->start_time == iOffStartTime)) {
+        if (synth->verbose) {
+         int used_voices = 0;
+         int k;
+         for (k = 0; k < synth->polyphony; k++) {
+           if (!_AVAILABLE(synth->voice[k])) {
+             used_voices++;
+           }
          }
-       }
-       FLUID_LOG(FLUID_INFO, "noteoff\t%d\t%d\t%d\t%05d\t%.3f\t%.3f\t%.3f\t%d",
-                voice->chan, voice->key, 0, voice->id,
-                (float) (voice->start_time + voice->ticks) / 44100.0f,
-                (fluid_curtime() - synth->start) / 1000.0f,
-                (float) voice->ticks / 44100.0f,
-                used_voices);
-      } /* if verbose */
-      fluid_voice_noteoff(voice);
-      status = FLUID_OK;
+      FLUID_LOG(FLUID_INFO, "noteoff\t%d\t%d\t%d\t%05d\t%.3f\t%.3f\t%.3f\t%d",
+           voice->chan, voice->key, 0, voice->id,
+           (float) (voice->start_time + voice->ticks) / 44100.0f,
+           (fluid_curtime() - synth->start) / 1000.0f,
+           (float) voice->ticks / 44100.0f,
+           used_voices);
+        } /* if verbose */
+        if (!iOffStartTime) iOffStartTime = voice->start_time;
+        fluid_voice_noteoff(voice);
+        status = FLUID_OK;
+      } /* if no offstarttime or offstarttime equals voice->starttime */
     } /* if voice on */
   } /* for all voices */
   return status;
@@ -2050,8 +2055,8 @@
 /*
  * fluid_synth_alloc_voice
  */
-fluid_voice_t*
-fluid_synth_alloc_voice(fluid_synth_t* synth, fluid_sample_t* sample, int 
chan, int key, int vel)
+fluid_voice_t*
+fluid_synth_alloc_voice(fluid_synth_t* synth, fluid_sample_t* sample, int 
chan, int key, int vel, int start_time)
 {
   int i, k;
   fluid_voice_t* voice = NULL;
@@ -2098,8 +2103,8 @@
          channel = synth->channel[chan];
   }

-  if (fluid_voice_init(voice, sample, channel, key, vel,
-                      synth->storeid, synth->ticks, synth->gain) != FLUID_OK) {
+  if (fluid_voice_init(voice, sample, channel, key, vel,
+                      synth->storeid, start_time, synth->gain) != FLUID_OK) {
     FLUID_LOG(FLUID_WARN, "Failed to initialize voice");
     return NULL;
   }











reply via email to

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