fluid-dev
[Top][All Lists]
Advanced

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

Re: [fluid-dev] Patch for fast midi file rendering


From: David Henningsson
Subject: Re: [fluid-dev] Patch for fast midi file rendering
Date: Thu, 19 Mar 2009 06:27:12 +0100
User-agent: Thunderbird 2.0.0.19 (X11/20090105)

Strange, it works here (gcc (Ubuntu 4.3.2-1ubuntu12) 4.3.2).
Nevertheless, here's a patch that should build on both versions.

// David

Pedro Lopez-Cabanillas skrev:
> David Henningsson wrote:
>> Enough said - now go enjoy the new patch!
> 
> Sorry, but:
> 
> fluidsynth.c: In function ‘fast_render_loop’:
> fluidsynth.c:185: error: dereferencing pointer to incomplete type
> fluidsynth.c:186: error: dereferencing pointer to incomplete type
> make[2]: *** [fluidsynth-fluidsynth.o] Error 1
> [...]
> $ gcc --version
> gcc (GCC) 4.2.1 (SUSE Linux)
> 
> Regards,
> Pedro
> 
> 
> _______________________________________________
> fluid-dev mailing list
> address@hidden
> http://lists.nongnu.org/mailman/listinfo/fluid-dev

Index: include/fluidsynth/audio.h
===================================================================
--- include/fluidsynth/audio.h  (revision 162)
+++ include/fluidsynth/audio.h  (arbetskopia)
@@ -61,8 +61,28 @@
 
 FLUIDSYNTH_API void delete_fluid_audio_driver(fluid_audio_driver_t* driver);
 
+/**
+ * Create a new file renderer and open the file.
+ * @param synth The synth that creates audio data.
+ * @param filename Output filename 
+ * @param period_size Sample count, amount of samples to write to the file at 
+ * every call to fluid_file_renderer_process_block().
+ * @return the new object, or NULL on failure
+ */
+FLUIDSYNTH_API fluid_file_renderer_t* new_fluid_file_renderer(fluid_synth_t* 
synth, 
+                                                       char* filename, int 
period_size);
 
+/**
+ * Write period_size samples to file.
+ * @return FLUID_OK or FLUID_FAILED if an error occurred
+ */
+FLUIDSYNTH_API int fluid_file_renderer_process_block(fluid_file_renderer_t* 
dev);
 
+/**
+ * Close file and destroy the file renderer object. 
+ */
+FLUIDSYNTH_API void delete_fluid_file_renderer(fluid_file_renderer_t* dev);
+
 #ifdef __cplusplus
 }
 #endif
Index: include/fluidsynth/types.h
===================================================================
--- include/fluidsynth/types.h  (revision 162)
+++ include/fluidsynth/types.h  (arbetskopia)
@@ -42,6 +42,7 @@
 typedef struct _fluid_sample_t fluid_sample_t;
 typedef struct _fluid_mod_t fluid_mod_t;
 typedef struct _fluid_audio_driver_t fluid_audio_driver_t;
+typedef struct _fluid_file_renderer_t fluid_file_renderer_t;
 typedef struct _fluid_player_t fluid_player_t;
 typedef struct _fluid_midi_event_t fluid_midi_event_t;
 typedef struct _fluid_midi_driver_t fluid_midi_driver_t;
Index: include/fluidsynth/midi.h
===================================================================
--- include/fluidsynth/midi.h   (revision 162)
+++ include/fluidsynth/midi.h   (arbetskopia)
@@ -101,6 +101,13 @@
  *  The MIDI player allows you to play MIDI files with the FLUID Synth
  */
 
+enum fluid_player_status
+{
+  FLUID_PLAYER_READY,
+  FLUID_PLAYER_PLAYING,
+  FLUID_PLAYER_DONE
+};
+
 FLUIDSYNTH_API fluid_player_t* new_fluid_player(fluid_synth_t* synth);
 FLUIDSYNTH_API int delete_fluid_player(fluid_player_t* player);
 FLUIDSYNTH_API int fluid_player_add(fluid_player_t* player, char* midifile);
@@ -110,6 +117,7 @@
 FLUIDSYNTH_API int fluid_player_set_loop(fluid_player_t* player, int loop);
 FLUIDSYNTH_API int fluid_player_set_midi_tempo(fluid_player_t* player, int 
tempo);
 FLUIDSYNTH_API int fluid_player_set_bpm(fluid_player_t* player, int bpm);
+FLUIDSYNTH_API int fluid_player_get_status(fluid_player_t* player);
 
 #ifdef __cplusplus
 }
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_aufile.c
===================================================================
--- src/fluid_aufile.c  (revision 162)
+++ src/fluid_aufile.c  (arbetskopia)
@@ -39,14 +39,10 @@
        fluid_audio_driver_t driver;
        fluid_audio_func_t callback;
        void* data;
+       fluid_file_renderer_t* renderer;
        int period_size;
        double sample_rate;
-       FILE* file;
        fluid_timer_t* timer;
-       float* left;
-       float* right;
-       short* buf;
-       int buf_size;
        unsigned int samples;
 } fluid_file_audio_driver_t;
 
@@ -61,7 +57,7 @@
 /**************************************************************
  *
  *        'file' audio driver
- *
+ * 
  */
 
 void fluid_file_audio_driver_settings(fluid_settings_t* settings)
@@ -92,22 +88,18 @@
        dev->data = synth;
        dev->callback = (fluid_audio_func_t) fluid_synth_process;
        dev->samples = 0;
-       dev->left = FLUID_ARRAY(float, dev->period_size);
-       dev->right = FLUID_ARRAY(float, dev->period_size);
-       dev->buf = FLUID_ARRAY(short, 2 * dev->period_size);
-       dev->buf_size = 2 * dev->period_size * sizeof(short);
 
        if (fluid_settings_getstr(settings, "audio.file.name", &filename) == 0) 
{
                FLUID_LOG(FLUID_ERR, "No file name specified");
                goto error_recovery;
        }
 
-       dev->file = fopen(filename, "wb");
-       if (dev->file == NULL) {
-               FLUID_LOG(FLUID_ERR, "Failed to open the file '%s'", filename);
+       dev->renderer = new_fluid_file_renderer(synth, filename, 
dev->period_size);
+       if (dev->renderer == NULL) {
                goto error_recovery;
        }
 
+
        msec = (int) (0.5 + dev->period_size / dev->sample_rate * 1000.0);
        dev->timer = new_fluid_timer(msec, fluid_file_audio_run_s16, (void*) 
dev, 1, 0);
        if (dev->timer == NULL) {
@@ -133,23 +125,11 @@
        if (dev->timer != NULL) {
                delete_fluid_timer(dev->timer);
        }
-
-       if (dev->file != NULL) {
-               fclose(dev->file);
+       
+       if (dev->renderer != NULL) {
+               delete_fluid_file_renderer(dev->renderer);
        }
 
-       if (dev->left != NULL) {
-               FLUID_FREE(dev->left);
-       }
-
-       if (dev->right != NULL) {
-               FLUID_FREE(dev->right);
-       }
-
-       if (dev->buf != NULL) {
-               FLUID_FREE(dev->buf);
-       }
-
        FLUID_FREE(dev);
        return FLUID_OK;
 }
@@ -157,7 +137,6 @@
 static int fluid_file_audio_run_s16(void* d, unsigned int clock_time)
 {
        fluid_file_audio_driver_t* dev = (fluid_file_audio_driver_t*) d;
-       int n, offset;
        unsigned int sample_time;
 
        sample_time = (unsigned int) (dev->samples / dev->sample_rate * 1000.0);
@@ -165,19 +144,7 @@
                return 1;
        }
 
-       fluid_synth_write_s16(dev->data, dev->period_size, dev->buf, 0, 2, 
dev->buf, 1, 2);
-
-       for (offset = 0; offset < dev->buf_size; offset += n) {
-
-               n = fwrite((char*) dev->buf + offset, 1, dev->buf_size - 
offset, dev->file);
-               if (n < 0) {
-                       FLUID_LOG(FLUID_ERR, "Audio output file write error: 
%s",
-                                 strerror (errno));
-                       return 0;
-               }
-       }
-
        dev->samples += dev->period_size;
 
-       return 1;
+       return fluid_file_renderer_process_block(dev->renderer) == FLUID_OK ? 1 
: 0;
 }
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_filerenderer.c
===================================================================
--- src/fluid_filerenderer.c    (revision 0)
+++ src/fluid_filerenderer.c    (revision 0)
@@ -0,0 +1,119 @@
+/* FluidSynth - A Software Synthesizer
+ *
+ * Copyright (C) 2003  Peter Hanappe and others.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307, USA
+ */
+
+ /* 
+  * Low-level routines for file output.
+  */
+
+#include <stdio.h>
+#include "fluidsynth_priv.h"
+
+struct _fluid_file_renderer_t {
+       FILE* file;
+       fluid_synth_t* synth;
+       short* buf;
+       int period_size;
+       int buf_size;
+};
+
+void delete_fluid_file_renderer(fluid_file_renderer_t* dev)
+{
+       if (dev == NULL) {
+               return;
+       }
+
+       if (dev->file != NULL) {
+               fclose(dev->file);
+       }
+
+       if (dev->buf != NULL) {
+               FLUID_FREE(dev->buf);
+       }
+
+       FLUID_FREE(dev);
+       return;
+}
+
+
+/* 
+ * Create a new file renderer object and open the file. 
+ */ 
+
+fluid_file_renderer_t* new_fluid_file_renderer(fluid_synth_t* synth, char* 
filename, int period_size)
+{
+       fluid_file_renderer_t* dev;
+
+       dev = FLUID_NEW(fluid_file_renderer_t);
+       if (dev == NULL) {
+               FLUID_LOG(FLUID_ERR, "Out of memory");
+               return NULL;
+       }
+       FLUID_MEMSET(dev, 0, sizeof(fluid_file_renderer_t));
+
+       dev->synth = synth;
+       dev->period_size = period_size;
+       dev->buf_size = 2 * dev->period_size * sizeof(short);
+
+       dev->buf = FLUID_ARRAY(short, 2 * dev->period_size);
+       if (dev->buf == NULL) {
+               FLUID_LOG(FLUID_ERR, "Out of memory");
+               goto error_recovery;
+       }
+
+       if (filename == NULL) {
+               FLUID_LOG(FLUID_ERR, "No file name specified");
+               goto error_recovery;
+       }
+
+       dev->file = fopen(filename, "wb");
+       if (dev->file == NULL) {
+               FLUID_LOG(FLUID_ERR, "Failed to open the file '%s'", filename);
+               goto error_recovery;
+       }
+
+       return dev;
+
+ error_recovery:
+       delete_fluid_file_renderer(dev);
+       return NULL;
+       
+}
+
+/*
+ * Write period_size samples to file.
+ */
+int fluid_file_renderer_process_block(fluid_file_renderer_t* dev)
+{
+       int n, offset;
+
+       fluid_synth_write_s16(dev->synth, dev->period_size, dev->buf, 0, 2, 
dev->buf, 1, 2);
+
+       for (offset = 0; offset < dev->buf_size; offset += n) {
+
+               n = fwrite((char*) dev->buf + offset, 1, dev->buf_size - 
offset, dev->file);
+               if (n < 0) {
+                       FLUID_LOG(FLUID_ERR, "Audio output file write error: 
%s",
+                                 strerror (errno));
+                       return FLUID_FAILED;
+               }
+       }
+       return FLUID_OK;
+}
+
Index: src/fluidsynth.c
===================================================================
--- src/fluidsynth.c    (revision 162)
+++ src/fluidsynth.c    (arbetskopia)
@@ -176,7 +176,32 @@
   }
 }
 
+void fast_render_loop(fluid_settings_t* settings, fluid_synth_t* synth, 
fluid_player_t* player)
+{
+  fluid_file_renderer_t* renderer;
+  char* filename = NULL;
+  int period_size = 0;
 
+  fluid_settings_getint(settings, "audio.period-size", &period_size);
+  fluid_settings_getstr(settings, "audio.file.name", &filename);
+
+  if (filename == NULL || period_size <= 0) {
+    fprintf(stderr, "Failed to fetch parameters for file renderer\n");
+  }
+
+  renderer = new_fluid_file_renderer(synth, filename, period_size);
+  if (!renderer) {
+  return;
+  }
+
+  while (fluid_player_get_status(player) == FLUID_PLAYER_PLAYING) {
+    if (fluid_file_renderer_process_block(renderer) != FLUID_OK) {
+      break;
+    }
+  }
+  delete_fluid_file_renderer(renderer);
+}
+
 #ifdef HAVE_SIGNAL_H
 /*
  * handle_signal
@@ -212,8 +237,9 @@
   int audio_channels = 0;
   int with_server = 0;
   int dump = 0;
+  int fast_render = 0;
   int connect_lash = 1;
-  char *optchars = "a:C:c:df:G:g:hijK:L:lm:no:p:R:r:sVvz:";
+  char *optchars = "a:C:c:df:F:G:g:hijK:L:lm:no:p:R:r:sVvz:";
 #ifdef LASH_ENABLED
   int enabled_lash = 0;                /* set to TRUE if lash gets enabled */
   fluid_lash_args_t *lash_args;
@@ -239,6 +265,7 @@
       {"connect-jack-outputs", 0, 0, 'j'},
       {"disable-lash", 0, 0, 'l'},
       {"dump", 0, 0, 'd'},
+      {"fast-render", 1, 0, 'F'},
       {"gain", 1, 0, 'g'},
       {"help", 0, 0, 'h'},
       {"load-config", 1, 0, 'f'},
@@ -322,6 +349,10 @@
     case 'f':
       config_file = optarg;
       break;
+    case 'F':
+      fluid_settings_setstr(settings, "audio.file.name", optarg);
+      fast_render = 1;
+      break;
     case 'G':
       audio_groups = atoi(optarg);
       break;
@@ -476,11 +507,20 @@
 /*   signal(SIGINT, handle_signal); */
 #endif
 
+  if (fast_render) {
+    midi_in = 0;
+    interactive = 0;
+    with_server = 0;
+    fluid_settings_setstr(settings, "player.timing-source", "sample");    
+  }
+
   /* start the synthesis thread */
-  adriver = new_fluid_audio_driver(settings, synth);
-  if (adriver == NULL) {
-    fprintf(stderr, "Failed to create the audio driver\n");
-    goto cleanup;
+  if (!fast_render) {
+    adriver = new_fluid_audio_driver(settings, synth);
+    if (adriver == NULL) {
+      fprintf(stderr, "Failed to create the audio driver\n");
+      goto cleanup;
+    }
   }
 
 
@@ -569,6 +609,10 @@
     fluid_usershell(settings, cmd_handler);
   }
 
+  if (fast_render) {
+    fast_render_loop(settings, synth, player);
+  }
+
  cleanup:
 
 #if !defined(MACINTOSH) && !defined(WIN32)
@@ -644,7 +688,7 @@
 print_welcome()
 {
   printf("FluidSynth version %s\n"
-        "Copyright (C) 2000-2006 Peter Hanappe and others.\n"
+        "Copyright (C) 2000-2009 Peter Hanappe and others.\n"
         "Distributed under the LGPL license.\n"
         "SoundFont(R) is a registered trademark of E-mu Systems, Inc.\n\n",
         FLUIDSYNTH_VERSION);
@@ -668,6 +712,8 @@
         "    Number of audio buffers\n");
   printf(" -d, --dump\n"
         "    Dump incoming and outgoing MIDI events to stdout\n");
+  printf(" -F, --fast-render=[file]\n"
+        "    Render MIDI file to raw audio data and store in [file]\n");
   printf(" -f, --load-config\n"
         "    Load command configuration file (shell commands)\n");
   printf(" -G, --audio-groups\n"
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", "sample", 
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,24 @@
  */
 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;
 }
 
+
+int fluid_player_get_status(fluid_player_t* player)
+{
+       return player->status;
+}
+
 /* FIXME - Looping seems to not actually be implemented? */
 
 /**
@@ -1403,7 +1444,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)
@@ -171,13 +171,6 @@
   MIDI_SEQUENCER_EVENT = 0x7f
 };
 
-enum fluid_player_status
-{
-  FLUID_PLAYER_READY,
-  FLUID_PLAYER_PLAYING,
-  FLUID_PLAYER_DONE
-};
-
 enum fluid_driver_status
 {
   FLUID_MIDI_READY,
@@ -249,10 +242,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 +265,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
  */
Index: src/Makefile.am
===================================================================
--- src/Makefile.am     (revision 162)
+++ src/Makefile.am     (arbetskopia)
@@ -121,6 +121,7 @@
        fluid_tuning.h \
        fluid_voice.c \
        fluid_voice.h \
+       fluid_filerenderer.c \
        fluid_aufile.c 
 
 INCLUDES = -I$(top_srcdir)/include $(LASH_CFLAGS) $(LADCCA_CFLAGS) \
Index: doc/fluidsynth.1
===================================================================
--- doc/fluidsynth.1    (revision 162)
+++ doc/fluidsynth.1    (arbetskopia)
@@ -70,6 +70,9 @@
 .B \-d, \-\-dump
 Dump incoming and outgoing MIDI events to stdout
 .TP
+.B \-F, \-\-fast\-render=[file]
+Render MIDI file to raw audio data and store in [file]
+.TP
 .B \-f, \-\-load\-config
 Load command configuration file (shell commands)
 .TP

reply via email to

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