4 * Copyright (C) 2001-2007 Krzysztof Foltman
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General
17 * Public License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
21 #include <calf/giface.h>
22 #include <calf/modules_dev.h>
23 #include <calf/utils.h>
26 #if ENABLE_EXPERIMENTAL
29 using namespace calf_plugins
;
32 fluidsynth_audio_module::fluidsynth_audio_module()
37 std::fill(set_presets
, set_presets
+ 16, -1);
38 std::fill(last_selected_presets
, last_selected_presets
+ 16, -1);
41 void fluidsynth_audio_module::post_instantiate(uint32_t sr
)
44 settings
= new_fluid_settings();
45 synth
= create_synth(sfid
);
46 soundfont_loaded
= sfid
!= -1;
49 void fluidsynth_audio_module::activate()
53 void fluidsynth_audio_module::deactivate()
57 fluid_synth_t
*fluidsynth_audio_module::create_synth(int &new_sfid
)
59 std::fill(set_presets
, set_presets
+ 16, -1);
60 fluid_settings_t
*new_settings
= new_fluid_settings();
61 fluid_settings_setnum(new_settings
, "synth.sample-rate", srate
);
62 fluid_synth_t
*s
= new_fluid_synth(new_settings
);
63 if (!soundfont
.empty())
65 int sid
= fluid_synth_sfload(s
, soundfont
.c_str(), 1);
68 delete_fluid_synth(s
);
72 printf("sid=%d\n", sid
);
73 fluid_synth_sfont_select(s
, 0, sid
);
76 fluid_sfont_t
* sfont
= fluid_synth_get_sfont(s
, 0);
77 soundfont_name
= (*sfont
->get_name
)(sfont
);
79 sfont
->iteration_start(sfont
);
83 int first_preset
= -1;
84 while(sfont
->iteration_next(sfont
, &tmp
))
86 string pname
= tmp
.get_name(&tmp
);
87 int bank
= tmp
.get_banknum(&tmp
);
88 int num
= tmp
.get_num(&tmp
);
89 int id
= num
+ 128 * bank
;
90 sf_preset_names
[id
] = pname
;
91 preset_list
+= calf_utils::i2s(id
) + "\t" + pname
+ "\n";
92 if (first_preset
== -1)
95 if (first_preset
!= -1)
97 fluid_synth_bank_select(s
, 0, first_preset
>> 7);
98 fluid_synth_program_change(s
, 0, first_preset
& 127);
100 soundfont_preset_list
= preset_list
;
107 void fluidsynth_audio_module::note_on(int channel
, int note
, int vel
)
109 fluid_synth_noteon(synth
, channel
, note
, vel
);
112 void fluidsynth_audio_module::note_off(int channel
, int note
, int vel
)
114 fluid_synth_noteoff(synth
, channel
, note
);
117 void fluidsynth_audio_module::control_change(int channel
, int controller
, int value
)
119 fluid_synth_cc(synth
, channel
, controller
, value
);
121 if (controller
== 0 || controller
== 32)
122 update_preset_num(channel
);
125 void fluidsynth_audio_module::program_change(int channel
, int program
)
127 fluid_synth_program_change(synth
, channel
, program
);
129 update_preset_num(channel
);
133 void fluidsynth_audio_module::update_preset_num(int channel
)
135 fluid_preset_t
*p
= fluid_synth_get_channel_preset(synth
, channel
);
137 last_selected_presets
[channel
] = p
->get_num(p
) + 128 * p
->get_banknum(p
);
139 last_selected_presets
[channel
] = -1;
143 void fluidsynth_audio_module::select_preset_in_channel(int channel
, int new_preset
)
145 fluid_synth_bank_select(synth
, channel
, new_preset
>> 7);
146 fluid_synth_program_change(synth
, channel
, new_preset
& 127);
147 last_selected_presets
[channel
] = new_preset
;
150 uint32_t fluidsynth_audio_module::process(uint32_t offset
, uint32_t nsamples
, uint32_t inputs_mask
, uint32_t outputs_mask
)
152 static const int interp_lens
[] = { 0, 1, 4, 7 };
153 for (int i
= 0; i
< 16; ++i
)
155 int new_preset
= set_presets
[i
];
156 if (new_preset
!= -1 && soundfont_loaded
)
158 // XXXKF yeah there's a tiny chance of race here, have to live with it until I write some utility classes for lock-free data passing
160 select_preset_in_channel(i
, new_preset
);
163 if (!soundfont_loaded
)
165 // Reset selected presets array to 'no preset'
166 std::fill(last_selected_presets
, last_selected_presets
+ 16, -1);
168 fluid_synth_set_interp_method(synth
, -1, interp_lens
[dsp::clip
<int>(fastf2i_drm(*params
[par_interpolation
]), 0, 3)]);
169 fluid_synth_set_reverb_on(synth
, *params
[par_reverb
] > 0);
170 fluid_synth_set_chorus_on(synth
, *params
[par_chorus
] > 0);
171 fluid_synth_set_gain(synth
, *params
[par_master
]);
172 fluid_synth_write_float(synth
, nsamples
, outs
[0], offset
, 1, outs
[1], offset
, 1);
176 char *fluidsynth_audio_module::configure(const char *key
, const char *value
)
178 if (!strncmp(key
, "preset_key_set", 14))
180 int ch
= atoi(key
+ 14);
183 if (ch
>= 0 && ch
<= 15)
184 set_presets
[ch
] = value
? atoi(value
) : 0;
187 if (!strcmp(key
, "soundfont"))
191 printf("Loading %s\n", value
);
196 printf("Creating a blank synth\n");
199 // First synth not yet created - defer creation up to post_instantiate
203 fluid_synth_t
*new_synth
= create_synth(newsfid
);
204 soundfont_loaded
= newsfid
!= -1;
212 for (int i
= 0; i
< 16; ++i
)
213 update_preset_num(i
);
216 return strdup("Cannot load a soundfont");
222 void fluidsynth_audio_module::send_configures(send_configure_iface
*sci
)
224 sci
->send_configure("soundfont", soundfont
.c_str());
225 sci
->send_configure("preset_key_set", calf_utils::i2s(last_selected_presets
[0]).c_str());
226 for (int i
= 1; i
< 16; ++i
)
228 string key
= "preset_key_set" + calf_utils::i2s(i
+ 1);
229 sci
->send_configure(key
.c_str(), calf_utils::i2s(last_selected_presets
[i
]).c_str());
233 int fluidsynth_audio_module::send_status_updates(send_updates_iface
*sui
, int last_serial
)
235 if (status_serial
!= last_serial
)
237 sui
->send_status("sf_name", soundfont_name
.c_str());
238 sui
->send_status("preset_list", soundfont_preset_list
.c_str());
239 sui
->send_status("preset_key", calf_utils::i2s(last_selected_presets
[0]).c_str());
240 for (int i
= 0; i
< 16; ++i
)
242 string id
= i
? calf_utils::i2s(i
+ 1) : string();
243 string key
= "preset_key" + id
;
244 sui
->send_status(key
.c_str(), calf_utils::i2s(last_selected_presets
[i
]).c_str());
245 key
= "preset_name" + id
;
246 map
<uint32_t, string
>::const_iterator it
= sf_preset_names
.find(last_selected_presets
[i
]);
247 if (it
== sf_preset_names
.end())
248 sui
->send_status(key
.c_str(), "");
250 sui
->send_status(key
.c_str(), it
->second
.c_str());
253 return status_serial
;
256 fluidsynth_audio_module::~fluidsynth_audio_module()
259 delete_fluid_synth(synth
);
263 // delete_fluid_settings(settings);