1 /* FluidSynth Arpeggio - Sequencer API example
2 *
3 * This code is in the public domain.
4 *
5 * To compile:
6 * gcc -o fluidsynth_arpeggio -lfluidsynth fluidsynth_arpeggio.c
7 *
8 * To run:
9 * fluidsynth_arpeggio soundfont [steps [duration]]
10 *
11 * [Pedro Lopez-Cabanillas <plcl@users.sf.net>]
12 */
13
14 #include <stdlib.h>
15 #include <stdio.h>
16 #include <fluidsynth.h>
17
18 fluid_synth_t *synth;
19 fluid_audio_driver_t *audiodriver;
20 fluid_sequencer_t *sequencer;
21 short synth_destination, client_destination;
22 unsigned int time_marker;
23 /* duration of the pattern in ticks. */
24 unsigned int duration = 1440;
25 /* notes of the arpeggio */
26 unsigned int notes[] = { 60, 64, 67, 72, 76, 79, 84, 79, 76, 72, 67, 64 };
27 /* number of notes in one pattern */
28 unsigned int pattern_size;
29 /* prototype */
30 void
31 sequencer_callback(unsigned int time, fluid_event_t *event,
32 fluid_sequencer_t *seq, void *data);
33
34 /* schedule a note on message */
35 void
schedule_noteon(int chan,short key,unsigned int ticks)36 schedule_noteon(int chan, short key, unsigned int ticks)
37 {
38 fluid_event_t *ev = new_fluid_event();
39 fluid_event_set_source(ev, -1);
40 fluid_event_set_dest(ev, synth_destination);
41 fluid_event_noteon(ev, chan, key, 127);
42 fluid_sequencer_send_at(sequencer, ev, ticks, 1);
43 delete_fluid_event(ev);
44 }
45
46 /* schedule a note off message */
47 void
schedule_noteoff(int chan,short key,unsigned int ticks)48 schedule_noteoff(int chan, short key, unsigned int ticks)
49 {
50 fluid_event_t *ev = new_fluid_event();
51 fluid_event_set_source(ev, -1);
52 fluid_event_set_dest(ev, synth_destination);
53 fluid_event_noteoff(ev, chan, key);
54 fluid_sequencer_send_at(sequencer, ev, ticks, 1);
55 delete_fluid_event(ev);
56 }
57
58 /* schedule a timer event (shall trigger the callback) */
59 void
schedule_timer_event(void)60 schedule_timer_event(void)
61 {
62 fluid_event_t *ev = new_fluid_event();
63 fluid_event_set_source(ev, -1);
64 fluid_event_set_dest(ev, client_destination);
65 fluid_event_timer(ev, NULL);
66 fluid_sequencer_send_at(sequencer, ev, time_marker, 1);
67 delete_fluid_event(ev);
68 }
69
70 /* schedule the arpeggio's notes */
71 void
schedule_pattern(void)72 schedule_pattern(void)
73 {
74 unsigned int i;
75 int note_time, note_duration;
76 note_time = time_marker;
77 note_duration = duration / pattern_size;
78
79 for(i = 0; i < pattern_size; ++i)
80 {
81 schedule_noteon(0, notes[i], note_time);
82 note_time += note_duration;
83 schedule_noteoff(0, notes[i], note_time);
84 }
85
86 time_marker += duration;
87 }
88
89 void
sequencer_callback(unsigned int time,fluid_event_t * event,fluid_sequencer_t * seq,void * data)90 sequencer_callback(unsigned int time, fluid_event_t *event,
91 fluid_sequencer_t *seq, void *data)
92 {
93 schedule_timer_event();
94 schedule_pattern();
95 }
96
97 void
usage(char * prog_name)98 usage(char *prog_name)
99 {
100 printf("Usage: %s soundfont.sf2 [steps [duration]]\n", prog_name);
101 printf("\t(optional) steps: number of pattern notes, from 2 to %d\n",
102 pattern_size);
103 printf("\t(optional) duration: of the pattern in ticks, default %d\n",
104 duration);
105 }
106
107 int
main(int argc,char * argv[])108 main(int argc, char *argv[])
109 {
110 int n;
111 fluid_settings_t *settings;
112 settings = new_fluid_settings();
113 pattern_size = sizeof(notes) / sizeof(int);
114
115 if(argc < 2)
116 {
117 usage(argv[0]);
118 }
119 else
120 {
121 /* create the synth, driver and sequencer instances */
122 synth = new_fluid_synth(settings);
123 /* load a SoundFont */
124 n = fluid_synth_sfload(synth, argv[1], 1);
125
126 if(n != -1)
127 {
128 sequencer = new_fluid_sequencer2(0);
129 /* register the synth with the sequencer */
130 synth_destination = fluid_sequencer_register_fluidsynth(sequencer,
131 synth);
132 /* register the client name and callback */
133 client_destination = fluid_sequencer_register_client(sequencer,
134 "arpeggio", sequencer_callback, NULL);
135 if(argc > 2)
136 {
137 n = atoi(argv[2]);
138
139 if((n > 1) && (n <= (int)pattern_size))
140 {
141 pattern_size = n;
142 }
143 }
144
145 if(argc > 3)
146 {
147 n = atoi(argv[3]);
148
149 if(n > 0)
150 {
151 duration = n;
152 }
153 }
154
155 audiodriver = new_fluid_audio_driver(settings, synth);
156
157 /* get the current time in ticks */
158 time_marker = fluid_sequencer_get_tick(sequencer);
159 /* schedule patterns */
160 schedule_pattern();
161 schedule_timer_event();
162 schedule_pattern();
163 /* wait for user input */
164 printf("press <Enter> to stop\n");
165 n = getchar();
166 }
167
168 /* clean and exit */
169 delete_fluid_audio_driver(audiodriver);
170 delete_fluid_sequencer(sequencer);
171 delete_fluid_synth(synth);
172 }
173
174 delete_fluid_settings(settings);
175 return 0;
176 }
177