On Thursday 14 June 2012, Raja Mukherji wrote: > I'm not sure if I'm doing something wrong but it seems as though > fluid_sequencer_send_at is ignoring the time parameter. > > I'm trying to use fluid_synth_write_float to render music to a buffer > that I can then encode and stream to a browser. Hence realtime > rendering is not important, rather rendering as fast as possible is > desired. > I've created a sequencer using new_fluid_sequencer2(0) so it's not > using the system timer. I'm trying to render in 3 second blocks > (arbitrary for now, I've tried smaller and longer blocks). For each > block, I create and send all the events for that block. Then I call > fluid_synth_write_float. It seems that the tick value of the sequencer > does not change in a manner consistent with the call to > fluid_synth_write_float so I am adjusting the times for all events in > a block by the value returned by fluid_sequencer_get_tick and using > relative times (so the last parameter to fluid_sequencer_send_at is > false). I have tried using absolute times too, with no difference.
I can't reproduce your problem. Attached is a slightly version of our fluidsynth_metronome program that is distributed in the doc/ folder of FluidSynth: http://fluidsynth.sourceforge.net/api/fluidsynth__metronome.c-example.html Instead of using an audio driver, this modified program renders 10 bars of the metronome pattern to a wav disk file. It uses absolute tick times, like the original sample program. The result has all beats where they should be. Regards, Pedro
/* FluidSynth Metronome - Sequencer API example * * This code is in the public domain. * * To compile: * gcc -o rendermetronome -lfluidsynth rendermetronome.c * * To run: * rendermetronome soundfont [beats [tempo]] * * [Pedro Lopez-Cabanillas <p...@users.sf.net>] */ #include <stdlib.h> #include <stdio.h> #include <fluidsynth.h> fluid_synth_t *synth; fluid_audio_driver_t *audiodriver; fluid_sequencer_t *sequencer; short synth_destination, client_destination; unsigned int time_marker; /* default tempo, beats per minute */ #define TEMPO 120 unsigned int note_duration = 60000 / TEMPO; /* metronome click/bell */ unsigned int weak_note = 33; unsigned int strong_note = 34; /* number of notes in one pattern */ unsigned int pattern_size = 4; /* total sequence length in bars */ unsigned int pending_bars = 10; /* prototype */ void sequencer_callback (unsigned int time, fluid_event_t *event, fluid_sequencer_t *seq, void *data); /* schedule a note on message */ void schedule_noteon (int chan, short key, unsigned int ticks) { fluid_event_t *ev = new_fluid_event (); fluid_event_set_source (ev, -1); fluid_event_set_dest (ev, synth_destination); fluid_event_noteon (ev, chan, key, 127); fluid_sequencer_send_at (sequencer, ev, ticks, 1); delete_fluid_event (ev); } /* schedule a timer event (shall trigger the callback) */ void schedule_timer_event () { fluid_event_t *ev = new_fluid_event (); fluid_event_set_source (ev, -1); fluid_event_set_dest (ev, client_destination); fluid_event_timer (ev, NULL); fluid_sequencer_send_at (sequencer, ev, time_marker, 1); delete_fluid_event (ev); } /* schedule the metronome pattern */ void schedule_pattern () { int i, note_time; note_time = time_marker; for (i = 0; i < pattern_size; ++i) { schedule_noteon (9, i ? weak_note : strong_note, note_time); note_time += note_duration; } time_marker = note_time; } void sequencer_callback (unsigned int time, fluid_event_t *event, fluid_sequencer_t *seq, void *data) { schedule_timer_event (); schedule_pattern (); pending_bars--; } void fast_render_loop(fluid_synth_t* synth) { fluid_file_renderer_t* renderer; renderer = new_fluid_file_renderer (synth); if (!renderer) return; while (pending_bars > 0) { if (fluid_file_renderer_process_block(renderer) != FLUID_OK) { break; } } delete_fluid_file_renderer(renderer); } void usage (char* prog_name) { printf ("Usage: %s soundfont.sf2 [beats [tempo]]\n", prog_name); printf ("\t(optional) beats: number of pattern beats, default %d\n", pattern_size); printf ("\t(optional) tempo: BPM (Beats Per Minute), default %d\n", TEMPO); } int main (int argc, char *argv[]) { int n; fluid_settings_t *settings; settings = new_fluid_settings (); fluid_settings_setstr(settings, "audio.file.name", "rendermetronome.wav"); fluid_settings_setnum(settings, "synth.gain", 2.0); if (argc < 2) { usage (argv[0]); } else { /* create the synth and sequencer instances */ synth = new_fluid_synth (settings); sequencer = new_fluid_sequencer2 (0); /* register the synth with the sequencer */ synth_destination = fluid_sequencer_register_fluidsynth (sequencer, synth); /* register the client name and callback */ client_destination = fluid_sequencer_register_client (sequencer, "metronome", sequencer_callback, NULL); /* load a SoundFont */ n = fluid_synth_sfload (synth, argv[1], 1); if (n != -1) { if (argc > 2) { n = atoi (argv[2]); if (n > 0) pattern_size = n; } if (argc > 3) { n = atoi (argv[3]); if (n > 0) note_duration = 60000 / n; } /* get the current time in ticks */ time_marker = fluid_sequencer_get_tick (sequencer); /* schedule patterns */ schedule_pattern (); schedule_timer_event (); schedule_pattern (); /* render output */ fast_render_loop(synth); } /* clean and exit */ delete_fluid_sequencer (sequencer); delete_fluid_synth (synth); } delete_fluid_settings (settings); return 0; }
_______________________________________________ fluid-dev mailing list fluid-dev@nongnu.org https://lists.nongnu.org/mailman/listinfo/fluid-dev