1 /* FluidSynth - A Software Synthesizer
2 *
3 * Copyright (C) 2003 Peter Hanappe and others.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public License
7 * as published by the Free Software Foundation; either version 2 of
8 * the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the Free
17 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 */
20
21
22
23 /*
24 2002 : API design by Peter Hanappe and Antoine Schmitt
25 August 2002 : Implementation by Antoine Schmitt as@gratin.org
26 as part of the infiniteCD author project
27 http://www.infiniteCD.org/
28 */
29
30 #include "fluidsynth_priv.h"
31 #include "fluid_synth.h"
32 #include "fluid_midi.h"
33 #include "fluid_event_priv.h"
34
35 /***************************************************************
36 *
37 * SEQUENCER BINDING
38 */
39
40 struct _fluid_seqbind_t {
41 fluid_synth_t* synth;
42 fluid_sequencer_t* seq;
43 fluid_sample_timer_t* sample_timer;
44 short client_id;
45 };
46 typedef struct _fluid_seqbind_t fluid_seqbind_t;
47
48
49 int fluid_seqbind_timer_callback(void* data, unsigned int msec);
50 void fluid_seq_fluidsynth_callback(unsigned int time, fluid_event_t* event, fluid_sequencer_t* seq, void* data);
51
52 /* Proper cleanup of the seqbind struct. */
53 void
delete_fluid_seqbind(fluid_seqbind_t * seqbind)54 delete_fluid_seqbind(fluid_seqbind_t* seqbind)
55 {
56 if (seqbind == NULL) {
57 return;
58 }
59
60 if ((seqbind->client_id != -1) && (seqbind->seq != NULL)) {
61 fluid_sequencer_unregister_client(seqbind->seq, seqbind->client_id);
62 seqbind->client_id = -1;
63 }
64
65 if ((seqbind->sample_timer != NULL) && (seqbind->synth != NULL)) {
66 delete_fluid_sample_timer(seqbind->synth, seqbind->sample_timer);
67 seqbind->sample_timer = NULL;
68 }
69
70 FLUID_FREE(seqbind);
71 }
72
73 /**
74 * Registers a synthesizer as a destination client of the given sequencer.
75 * The \a synth is registered with the name "fluidsynth".
76 * @param seq Sequencer instance
77 * @param synth Synthesizer instance
78 * @returns Sequencer client ID, or #FLUID_FAILED on error.
79 */
80 short
fluid_sequencer_register_fluidsynth(fluid_sequencer_t * seq,fluid_synth_t * synth)81 fluid_sequencer_register_fluidsynth (fluid_sequencer_t* seq, fluid_synth_t* synth)
82 {
83 fluid_seqbind_t* seqbind;
84
85 seqbind = FLUID_NEW(fluid_seqbind_t);
86 if (seqbind == NULL) {
87 fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
88 return FLUID_FAILED;
89 }
90
91 seqbind->synth = synth;
92 seqbind->seq = seq;
93 seqbind->sample_timer = NULL;
94 seqbind->client_id = -1;
95
96 /* set up the sample timer */
97 if (!fluid_sequencer_get_use_system_timer(seq)) {
98 seqbind->sample_timer =
99 new_fluid_sample_timer(synth, fluid_seqbind_timer_callback, (void *) seqbind);
100 if (seqbind->sample_timer == NULL) {
101 fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
102 delete_fluid_seqbind(seqbind);
103 return FLUID_FAILED;
104 }
105 }
106
107 /* register fluidsynth itself */
108 seqbind->client_id =
109 fluid_sequencer_register_client(seq, "fluidsynth", fluid_seq_fluidsynth_callback, (void *)seqbind);
110 if (seqbind->client_id == -1) {
111 delete_fluid_seqbind(seqbind);
112 return FLUID_FAILED;
113 }
114
115 return seqbind->client_id;
116 }
117
118 /* Callback for sample timer */
119 int
fluid_seqbind_timer_callback(void * data,unsigned int msec)120 fluid_seqbind_timer_callback(void* data, unsigned int msec)
121 {
122 fluid_seqbind_t* seqbind = (fluid_seqbind_t *) data;
123 fluid_sequencer_process(seqbind->seq, msec);
124 return 1;
125 }
126
127 /* Callback for midi events */
128 void
fluid_seq_fluidsynth_callback(unsigned int time,fluid_event_t * evt,fluid_sequencer_t * seq,void * data)129 fluid_seq_fluidsynth_callback(unsigned int time, fluid_event_t* evt, fluid_sequencer_t* seq, void* data)
130 {
131 fluid_synth_t* synth;
132 fluid_seqbind_t* seqbind = (fluid_seqbind_t *) data;
133 synth = seqbind->synth;
134
135 switch (fluid_event_get_type(evt)) {
136
137 case FLUID_SEQ_NOTEON:
138 fluid_synth_noteon(synth, fluid_event_get_channel(evt), fluid_event_get_key(evt), fluid_event_get_velocity(evt));
139 break;
140
141 case FLUID_SEQ_NOTEOFF:
142 fluid_synth_noteoff(synth, fluid_event_get_channel(evt), fluid_event_get_key(evt));
143 break;
144
145 case FLUID_SEQ_NOTE:
146 {
147 unsigned int dur;
148 fluid_synth_noteon(synth, fluid_event_get_channel(evt), fluid_event_get_key(evt), fluid_event_get_velocity(evt));
149 dur = fluid_event_get_duration(evt);
150 fluid_event_noteoff(evt, fluid_event_get_channel(evt), fluid_event_get_key(evt));
151 fluid_sequencer_send_at(seq, evt, dur, 0);
152 }
153 break;
154
155 case FLUID_SEQ_ALLSOUNDSOFF:
156 /* NYI */
157 break;
158
159 case FLUID_SEQ_ALLNOTESOFF:
160 fluid_synth_cc(synth, fluid_event_get_channel(evt), 0x7B, 0);
161 break;
162
163 case FLUID_SEQ_BANKSELECT:
164 fluid_synth_bank_select(synth, fluid_event_get_channel(evt), fluid_event_get_bank(evt));
165 break;
166
167 case FLUID_SEQ_PROGRAMCHANGE:
168 fluid_synth_program_change(synth, fluid_event_get_channel(evt), fluid_event_get_program(evt));
169 break;
170
171 case FLUID_SEQ_PROGRAMSELECT:
172 fluid_synth_program_select(synth, fluid_event_get_channel(evt), fluid_event_get_sfont_id(evt),
173 fluid_event_get_bank(evt), fluid_event_get_program(evt));
174 break;
175
176 case FLUID_SEQ_ANYCONTROLCHANGE:
177 /* nothing = only used by remove_events */
178 break;
179
180 case FLUID_SEQ_PITCHBEND:
181 fluid_synth_pitch_bend(synth, fluid_event_get_channel(evt), fluid_event_get_pitch(evt));
182 break;
183
184 case FLUID_SEQ_PITCHWHHELSENS:
185 fluid_synth_pitch_wheel_sens(synth, fluid_event_get_channel(evt), fluid_event_get_value(evt));
186 break;
187
188 case FLUID_SEQ_CONTROLCHANGE:
189 fluid_synth_cc(synth, fluid_event_get_channel(evt), fluid_event_get_control(evt), fluid_event_get_value(evt));
190 break;
191
192 case FLUID_SEQ_MODULATION:
193 {
194 short ctrl = 0x01; // MODULATION_MSB
195 fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
196 }
197 break;
198
199 case FLUID_SEQ_SUSTAIN:
200 {
201 short ctrl = 0x40; // SUSTAIN_SWITCH
202 fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
203 }
204 break;
205
206 case FLUID_SEQ_PAN:
207 {
208 short ctrl = 0x0A; // PAN_MSB
209 fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
210 }
211 break;
212
213 case FLUID_SEQ_VOLUME:
214 {
215 short ctrl = 0x07; // VOLUME_MSB
216 fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
217 }
218 break;
219
220 case FLUID_SEQ_REVERBSEND:
221 {
222 short ctrl = 0x5B; // EFFECTS_DEPTH1
223 fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
224 }
225 break;
226
227 case FLUID_SEQ_CHORUSSEND:
228 {
229 short ctrl = 0x5D; // EFFECTS_DEPTH3
230 fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt));
231 }
232 break;
233
234 case FLUID_SEQ_CHANNELPRESSURE:
235 {
236 fluid_synth_channel_pressure(synth, fluid_event_get_channel(evt), fluid_event_get_value(evt));
237 }
238 break;
239
240 case FLUID_SEQ_SYSTEMRESET:
241 {
242 fluid_synth_system_reset(synth);
243 }
244 break;
245
246 case FLUID_SEQ_UNREGISTERING: /* free ourselves */
247 {
248 seqbind->client_id = -1; /* avoid recursive call to fluid_sequencer_unregister_client */
249 delete_fluid_seqbind(seqbind);
250 }
251 break;
252
253 case FLUID_SEQ_TIMER:
254 /* nothing in fluidsynth */
255 break;
256
257 default:
258 break;
259 }
260 }
261
get_fluidsynth_dest(fluid_sequencer_t * seq)262 static int get_fluidsynth_dest(fluid_sequencer_t* seq)
263 {
264 int i, id;
265 char* name;
266 int j = fluid_sequencer_count_clients(seq);
267 for (i = 0; i < j; i++) {
268 id = fluid_sequencer_get_client_id(seq, i);
269 name = fluid_sequencer_get_client_name(seq, id);
270 if (strcmp(name, "fluidsynth") == 0) {
271 return id;
272 }
273 }
274 return -1;
275 }
276
277 /**
278 * Transforms an incoming midi event (from a midi driver or midi router) to a
279 * sequencer event and adds it to the sequencer queue for sending as soon as possible.
280 * @param data The sequencer, must be a valid #fluid_sequencer_t
281 * @param event MIDI event
282 * @return #FLUID_OK or #FLUID_FAILED
283 * @since 1.1.0
284 */
285 int
fluid_sequencer_add_midi_event_to_buffer(void * data,fluid_midi_event_t * event)286 fluid_sequencer_add_midi_event_to_buffer(void* data, fluid_midi_event_t* event)
287 {
288 fluid_event_t evt;
289 fluid_sequencer_t* seq = (fluid_sequencer_t*) data;
290 int chan = fluid_midi_event_get_channel(event);
291
292 fluid_event_clear(&evt);
293 fluid_event_set_time(&evt, fluid_sequencer_get_tick(seq));
294 fluid_event_set_dest(&evt, get_fluidsynth_dest(seq));
295
296 switch (fluid_midi_event_get_type(event)) {
297 case NOTE_OFF:
298 fluid_event_noteoff(&evt, chan, fluid_midi_event_get_key(event));
299 break;
300 case NOTE_ON:
301 fluid_event_noteon(&evt, fluid_midi_event_get_channel(event),
302 fluid_midi_event_get_key(event), fluid_midi_event_get_velocity(event));
303 break;
304 case CONTROL_CHANGE:
305 fluid_event_control_change(&evt, chan, fluid_midi_event_get_control(event),
306 fluid_midi_event_get_value(event));
307 break;
308 case PROGRAM_CHANGE:
309 fluid_event_program_change(&evt, chan, fluid_midi_event_get_program(event));
310 break;
311 case PITCH_BEND:
312 fluid_event_pitch_bend(&evt, chan, fluid_midi_event_get_pitch(event));
313 break;
314 case CHANNEL_PRESSURE:
315 fluid_event_channel_pressure(&evt, chan, fluid_midi_event_get_program(event));
316 break;
317 case MIDI_SYSTEM_RESET:
318 fluid_event_system_reset(&evt);
319 break;
320 default: /* Not yet implemented */
321 return FLUID_FAILED;
322 }
323
324 /* Schedule for sending at next call to fluid_sequencer_process */
325 return fluid_sequencer_send_at(seq, &evt, 0, 0);
326 }
327
328
329