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

Reply via email to