2009-05-01 17:26:42 +00:00
|
|
|
/* FluidSynth Arpeggio - Sequencer API example
|
|
|
|
*
|
|
|
|
* This code is in the public domain.
|
|
|
|
*
|
|
|
|
* To compile:
|
|
|
|
* gcc -o fluidsynth_arpeggio -lfluidsynth fluidsynth_arpeggio.c
|
|
|
|
*
|
|
|
|
* To run:
|
|
|
|
* fluidsynth_arpeggio soundfont [steps [duration]]
|
|
|
|
*
|
|
|
|
* [Pedro Lopez-Cabanillas <plcl@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;
|
|
|
|
/* duration of the pattern in ticks. */
|
|
|
|
unsigned int duration = 1440;
|
|
|
|
/* notes of the arpeggio */
|
|
|
|
unsigned int notes[] = { 60, 64, 67, 72, 76, 79, 84, 79, 76, 72, 67, 64 };
|
|
|
|
/* number of notes in one pattern */
|
|
|
|
unsigned int pattern_size;
|
|
|
|
/* prototype */
|
|
|
|
void
|
2018-06-24 11:01:31 +00:00
|
|
|
sequencer_callback(unsigned int time, fluid_event_t *event,
|
|
|
|
fluid_sequencer_t *seq, void *data);
|
2009-05-01 17:26:42 +00:00
|
|
|
|
|
|
|
/* schedule a note on message */
|
|
|
|
void
|
2018-06-24 11:01:31 +00:00
|
|
|
schedule_noteon(int chan, short key, unsigned int ticks)
|
2009-05-01 17:26:42 +00:00
|
|
|
{
|
2018-06-24 11:01:31 +00:00
|
|
|
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);
|
2009-05-01 17:26:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* schedule a note off message */
|
|
|
|
void
|
2018-06-24 11:01:31 +00:00
|
|
|
schedule_noteoff(int chan, short key, unsigned int ticks)
|
2009-05-01 17:26:42 +00:00
|
|
|
{
|
2018-06-24 11:01:31 +00:00
|
|
|
fluid_event_t *ev = new_fluid_event();
|
|
|
|
fluid_event_set_source(ev, -1);
|
|
|
|
fluid_event_set_dest(ev, synth_destination);
|
|
|
|
fluid_event_noteoff(ev, chan, key);
|
|
|
|
fluid_sequencer_send_at(sequencer, ev, ticks, 1);
|
|
|
|
delete_fluid_event(ev);
|
2009-05-01 17:26:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* schedule a timer event (shall trigger the callback) */
|
|
|
|
void
|
2018-06-24 11:01:31 +00:00
|
|
|
schedule_timer_event()
|
2009-05-01 17:26:42 +00:00
|
|
|
{
|
2018-06-24 11:01:31 +00:00
|
|
|
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);
|
2009-05-01 17:26:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* schedule the arpeggio's notes */
|
|
|
|
void
|
2018-06-24 11:01:31 +00:00
|
|
|
schedule_pattern()
|
2009-05-01 17:26:42 +00:00
|
|
|
{
|
|
|
|
int i, note_time, note_duration;
|
|
|
|
note_time = time_marker;
|
|
|
|
note_duration = duration / pattern_size;
|
2018-06-24 11:01:31 +00:00
|
|
|
|
|
|
|
for(i = 0; i < pattern_size; ++i)
|
|
|
|
{
|
|
|
|
schedule_noteon(0, notes[i], note_time);
|
2009-05-01 17:26:42 +00:00
|
|
|
note_time += note_duration;
|
2018-06-24 11:01:31 +00:00
|
|
|
schedule_noteoff(0, notes[i], note_time);
|
2009-05-01 17:26:42 +00:00
|
|
|
}
|
2018-06-24 11:01:31 +00:00
|
|
|
|
2009-05-01 17:26:42 +00:00
|
|
|
time_marker += duration;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-06-24 11:01:31 +00:00
|
|
|
sequencer_callback(unsigned int time, fluid_event_t *event,
|
|
|
|
fluid_sequencer_t *seq, void *data)
|
2009-05-01 17:26:42 +00:00
|
|
|
{
|
2018-06-24 11:01:31 +00:00
|
|
|
schedule_timer_event();
|
|
|
|
schedule_pattern();
|
2009-05-01 17:26:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-06-24 11:01:31 +00:00
|
|
|
usage(char *prog_name)
|
2009-05-01 17:26:42 +00:00
|
|
|
{
|
2018-06-24 11:01:31 +00:00
|
|
|
printf("Usage: %s soundfont.sf2 [steps [duration]]\n", prog_name);
|
|
|
|
printf("\t(optional) steps: number of pattern notes, from 2 to %d\n",
|
|
|
|
pattern_size);
|
|
|
|
printf("\t(optional) duration: of the pattern in ticks, default %d\n",
|
|
|
|
duration);
|
2009-05-01 17:26:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2018-06-24 11:01:31 +00:00
|
|
|
main(int argc, char *argv[])
|
2009-05-01 17:26:42 +00:00
|
|
|
{
|
|
|
|
int n;
|
|
|
|
fluid_settings_t *settings;
|
2018-06-24 11:01:31 +00:00
|
|
|
settings = new_fluid_settings();
|
2009-05-01 17:26:42 +00:00
|
|
|
pattern_size = sizeof(notes) / sizeof(int);
|
2018-06-24 11:01:31 +00:00
|
|
|
|
|
|
|
if(argc < 2)
|
|
|
|
{
|
|
|
|
usage(argv[0]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-05-01 17:26:42 +00:00
|
|
|
/* create the synth, driver and sequencer instances */
|
2018-06-24 11:01:31 +00:00
|
|
|
synth = new_fluid_synth(settings);
|
|
|
|
audiodriver = new_fluid_audio_driver(settings, synth);
|
|
|
|
sequencer = new_fluid_sequencer();
|
2009-05-01 17:26:42 +00:00
|
|
|
/* register the synth with the sequencer */
|
2018-06-24 11:01:31 +00:00
|
|
|
synth_destination = fluid_sequencer_register_fluidsynth(sequencer,
|
|
|
|
synth);
|
2009-05-01 17:26:42 +00:00
|
|
|
/* register the client name and callback */
|
2018-06-24 11:01:31 +00:00
|
|
|
client_destination = fluid_sequencer_register_client(sequencer,
|
|
|
|
"arpeggio", sequencer_callback, NULL);
|
2009-05-01 17:26:42 +00:00
|
|
|
/* load a SoundFont */
|
2018-06-24 11:01:31 +00:00
|
|
|
n = fluid_synth_sfload(synth, argv[1], 1);
|
|
|
|
|
|
|
|
if(n != -1)
|
|
|
|
{
|
|
|
|
if(argc > 2)
|
|
|
|
{
|
|
|
|
n = atoi(argv[2]);
|
|
|
|
|
|
|
|
if((n > 1) && (n <= pattern_size))
|
|
|
|
{
|
|
|
|
pattern_size = n;
|
|
|
|
}
|
2009-05-01 17:26:42 +00:00
|
|
|
}
|
2018-06-24 11:01:31 +00:00
|
|
|
|
|
|
|
if(argc > 3)
|
|
|
|
{
|
|
|
|
n = atoi(argv[3]);
|
|
|
|
|
|
|
|
if(n > 0)
|
|
|
|
{
|
|
|
|
duration = n;
|
|
|
|
}
|
2009-05-01 17:26:42 +00:00
|
|
|
}
|
2018-06-24 11:01:31 +00:00
|
|
|
|
2009-05-01 17:26:42 +00:00
|
|
|
/* get the current time in ticks */
|
2018-06-24 11:01:31 +00:00
|
|
|
time_marker = fluid_sequencer_get_tick(sequencer);
|
2009-05-01 17:26:42 +00:00
|
|
|
/* schedule patterns */
|
2018-06-24 11:01:31 +00:00
|
|
|
schedule_pattern();
|
|
|
|
schedule_timer_event();
|
|
|
|
schedule_pattern();
|
2009-05-01 17:26:42 +00:00
|
|
|
/* wait for user input */
|
2018-06-24 11:01:31 +00:00
|
|
|
printf("press <Enter> to stop\n");
|
|
|
|
n = getchar();
|
2009-05-01 17:26:42 +00:00
|
|
|
}
|
2018-06-24 11:01:31 +00:00
|
|
|
|
2009-05-01 17:26:42 +00:00
|
|
|
/* clean and exit */
|
2018-06-24 11:01:31 +00:00
|
|
|
delete_fluid_sequencer(sequencer);
|
|
|
|
delete_fluid_audio_driver(audiodriver);
|
|
|
|
delete_fluid_synth(synth);
|
2009-05-01 17:26:42 +00:00
|
|
|
}
|
2018-06-24 11:01:31 +00:00
|
|
|
|
|
|
|
delete_fluid_settings(settings);
|
2009-05-01 17:26:42 +00:00
|
|
|
return 0;
|
|
|
|
}
|