[Top][All Lists]
[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