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 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 * 02111-1307, USA
19 */
20
21 #include "fluid.h"
22 #include "sfont.h"
23 #include "conv.h"
24 #include "gen.h"
25 #include "voice.h"
26
27 #include "midi/event.h"
28 #include "midi/msynthesizer.h"
29
30 #include "mscore/preferences.h"
31 #include "mscore/extension.h"
32
33 namespace FluidS {
34
35 /***************************************************************
36 *
37 * GLOBAL
38 */
39
40 bool Fluid::initialized = false;
41
42 /* better than a macro to determine inappropriate values for notes*/
validNote(const int input)43 bool validNote(const int input) {
44 return (input < 255 && input > -1);
45 }
46
47 /* default modulators
48 * SF2.01 page 52 ff:
49 *
50 * There is a set of predefined default modulators. They have to be
51 * explicitly overridden by the sound font in order to turn them off.
52 */
53
54 static const Mod defaultMod[] = {
55 { GEN_ATTENUATION, FLUID_MOD_VELOCITY, FLUID_MOD_GC | FLUID_MOD_CONCAVE | FLUID_MOD_UNIPOLAR | FLUID_MOD_NEGATIVE, 0, 0, 960.0 },
56 { GEN_FILTERFC,
57 FLUID_MOD_VELOCITY, FLUID_MOD_GC | FLUID_MOD_LINEAR | FLUID_MOD_UNIPOLAR | FLUID_MOD_NEGATIVE,
58 FLUID_MOD_VELOCITY, FLUID_MOD_GC | FLUID_MOD_SWITCH | FLUID_MOD_UNIPOLAR | FLUID_MOD_POSITIVE,
59 -2400 },
60 { GEN_VIBLFOTOPITCH, FLUID_MOD_CHANNELPRESSURE, FLUID_MOD_GC | FLUID_MOD_LINEAR | FLUID_MOD_UNIPOLAR | FLUID_MOD_POSITIVE, 0, 0, 50 },
61 { GEN_VIBLFOTOPITCH, 1, FLUID_MOD_CC | FLUID_MOD_LINEAR | FLUID_MOD_UNIPOLAR | FLUID_MOD_POSITIVE, 0, 0, 50 },
62 { GEN_ATTENUATION, 7, FLUID_MOD_CC | FLUID_MOD_CONCAVE | FLUID_MOD_UNIPOLAR | FLUID_MOD_NEGATIVE, 0, 0, 960.0 },
63 { GEN_PAN, 10, FLUID_MOD_CC | FLUID_MOD_LINEAR | FLUID_MOD_BIPOLAR | FLUID_MOD_POSITIVE, 0, 0, 500.0 },
64 { GEN_ATTENUATION, 11, FLUID_MOD_CC | FLUID_MOD_CONCAVE | FLUID_MOD_UNIPOLAR | FLUID_MOD_NEGATIVE, 0, 0, 960.0 },
65 { GEN_REVERBSEND, 91, FLUID_MOD_CC | FLUID_MOD_LINEAR | FLUID_MOD_UNIPOLAR | FLUID_MOD_POSITIVE, 0, 0, 200 },
66 { GEN_CHORUSSEND, 93, FLUID_MOD_CC | FLUID_MOD_LINEAR | FLUID_MOD_UNIPOLAR | FLUID_MOD_POSITIVE, 0, 0, 200 },
67 { GEN_PITCH,
68 FLUID_MOD_PITCHWHEEL, FLUID_MOD_GC | FLUID_MOD_LINEAR | FLUID_MOD_BIPOLAR | FLUID_MOD_POSITIVE,
69 FLUID_MOD_PITCHWHEELSENS, FLUID_MOD_GC | FLUID_MOD_LINEAR | FLUID_MOD_UNIPOLAR | FLUID_MOD_POSITIVE,
70 12700.0 },
71 };
72
73 static const Mod forcePanMod = { GEN_PAN, 10, FLUID_MOD_CC | FLUID_MOD_LINEAR | FLUID_MOD_BIPOLAR | FLUID_MOD_POSITIVE, 0, 0, 1000.0 };
74
75 //---------------------------------------------------------
76 // Fluid
77 //---------------------------------------------------------
78
Fluid()79 Fluid::Fluid()
80 : Synthesizer()
81 {
82 }
83
84 //---------------------------------------------------------
85 // init
86 // instance initialization
87 //---------------------------------------------------------
88
init(float sampleRate)89 void Fluid::init(float sampleRate)
90 {
91 if (!initialized) { // initialize all the conversion tables and other stuff
92 initialized = true;
93 fluid_conversion_config();
94 Voice::dsp_float_config();
95 }
96 Synthesizer::init(sampleRate);
97 sample_rate = sampleRate;
98 sfont_id = 0;
99
100 _state = FLUID_SYNTH_PLAYING; // as soon as the synth is created it starts playing.
101 noteid = 0;
102 for (int i = 0; i < 128; ++i)
103 _tuning[i] = i * 100.0;
104 _masterTuning = 440.0;
105
106 fromkey_portamento = Channel::INVALID_NOTE;
107 lastNote = Channel::INVALID_NOTE;
108
109 for (int i = 0; i < 512; i++)
110 freeVoices.append(new Voice(this));
111 }
112
113 //---------------------------------------------------------
114 // ~Fluid
115 //---------------------------------------------------------
116
~Fluid()117 Fluid::~Fluid()
118 {
119 _state = FLUID_SYNTH_STOPPED;
120 _globalTerminate = true;
121 while (!mutex.tryLock()) {}
122 qDeleteAll(activeVoices);
123 qDeleteAll(freeVoices);
124 qDeleteAll(sfonts);
125 qDeleteAll(channel);
126 qDeleteAll(patches);
127 }
128
129 //---------------------------------------------------------
130 // freeVoice
131 //---------------------------------------------------------
132
freeVoice(Voice * v)133 void Fluid::freeVoice(Voice* v)
134 {
135 if (activeVoices.removeOne(v))
136 freeVoices.append(v);
137 }
138
139 //---------------------------------------------------------
140 // play
141 //---------------------------------------------------------
142
play(const PlayEvent & event)143 void Fluid::play(const PlayEvent& event)
144 {
145 bool err = false;
146 int ch = event.channel();
147
148 if (ch >= channel.size()) {
149 for (int i = channel.size(); i < ch+1; i++)
150 channel.append(new Channel(this, i));
151 }
152
153 int type = event.type();
154 Channel* cp = channel[ch];
155
156 if (type == ME_NOTEON) {
157 int key = event.dataA();
158 int vel = event.dataB();
159 if (vel == 0) {
160 //
161 // process note off
162 //
163 for (Voice* v : qAsConst(activeVoices)) {
164 if (v->ON() && (v->chan == ch) && (v->key == key))
165 v->noteoff();
166 }
167 return;
168 }
169 if (cp->preset() == 0) {
170 qDebug("channel has no preset");
171 err = true;
172 }
173 else {
174 /*
175 * If the same note is hit twice on the same channel, then the older
176 * voice process is advanced to the release stage. Using a mechanical
177 * MIDI controller, the only way this can happen is when the sustain
178 * pedal is held. In this case the behaviour implemented here is
179 * natural for many instruments. Note: One noteon event can trigger
180 * several voice processes, for example a stereo sample. Don't
181 * release those...
182 */
183 for(Voice* v : qAsConst(activeVoices)) {
184 if (v->isPlaying() && (v->chan == ch) && (v->key == key) && (v->get_id() != noteid))
185 v->noteoff();
186 }
187 err = !cp->preset()->noteon(this, noteid++, ch, key, vel, event.tuning());
188 }
189 }
190 else if (type == ME_CONTROLLER) {
191 switch(event.dataA()) {
192 case CTRL_PROGRAM:
193 program_change(ch, event.dataB());
194 break;
195 case CTRL_PRESS:
196 break;
197 default:
198 cp->setcc(event.dataA(), event.dataB());
199 break;
200 }
201 }
202 else if (type == ME_PITCHBEND){
203 int midiPitch = event.dataB() * 128 + event.dataA(); // msb * 128 + lsb
204 cp->pitchBend(midiPitch);
205 }
206 /*
207 * MIDI spec.: One data byte follows the Status. It is the pressure amount, a value
208 * from 0 to 127 (where 127 is the most pressure).
209 */
210 else if (type == ME_AFTERTOUCH){
211 cp->setChannelPressure(event.dataA());
212 }
213 /*
214 * MIDI spec.: Two data bytes follow the Status. The first data is the note number.
215 * This indicates to which note the pressure is being applied. The second data byte is the
216 * pressure amount, a value from 0 to 127 (where 127 is the most pressure).
217 */
218 else if (type == ME_POLYAFTER){
219 cp->setKeyPressure(event.dataA(), event.dataB());
220 }
221
222 if (err) {
223 // TODO: distinguish between types of error code.
224 // Lack of a soundfont should not produce qDebug messages, because user could deliberately be using MIDI out only.
225 //qWarning("FluidSynth error: event 0x%2x channel %d: %s", type, ch, qPrintable(error()));
226 }
227 }
228
229 //---------------------------------------------------------
230 // damp_voices
231 //---------------------------------------------------------
232
damp_voices(int chan)233 void Fluid::damp_voices(int chan)
234 {
235 for(Voice* v : qAsConst(activeVoices)) {
236 if ((v->chan == chan) && v->SUSTAINED())
237 v->noteoff();
238 }
239 }
240
241 //---------------------------------------------------------
242 // allNotesOff
243 //---------------------------------------------------------
244
allNotesOff(int chan)245 void Fluid::allNotesOff(int chan)
246 {
247 for(Voice* v : qAsConst(activeVoices)) {
248 if (chan == -1 || v->chan == chan)
249 v->noteoff();
250 }
251 }
252
253 //---------------------------------------------------------
254 // allSoundsOff
255 // immediately stop all notes on this channel.
256 // stop all channel if chan==-1
257 //---------------------------------------------------------
258
allSoundsOff(int chan)259 void Fluid::allSoundsOff(int chan)
260 {
261 for(Voice* v : qAsConst(activeVoices)) {
262 if (chan == -1 || v->chan == chan)
263 v->off();
264 }
265 }
266
267 //---------------------------------------------------------
268 // system_reset
269 //
270 // Purpose:
271 // Respond to the MIDI command 'system reset' (0xFF, big red 'panic' button)
272 //---------------------------------------------------------
273
system_reset()274 void Fluid::system_reset()
275 {
276 for(Voice* v : qAsConst(activeVoices))
277 v->off();
278 for(Channel* c : qAsConst(channel))
279 c->reset();
280 }
281
282 /*
283 * fluid_synth_modulate_voices
284 *
285 * tell all synthesis processes on this channel to update their
286 * synthesis parameters after a control change.
287 */
modulate_voices(int chan,bool is_cc,int ctrl)288 void Fluid::modulate_voices(int chan, bool is_cc, int ctrl)
289 {
290 for(Voice* v : qAsConst(activeVoices)) {
291 if (v->chan == chan)
292 v->modulate(is_cc, ctrl);
293 }
294 }
295
296 /*
297 * fluid_synth_modulate_voices_all
298 *
299 * Tell all synthesis processes on this channel to update their
300 * synthesis parameters after an all control off message (i.e. all
301 * controller have been reset to their default value).
302 */
modulate_voices_all(int chan)303 void Fluid::modulate_voices_all(int chan)
304 {
305 for(Voice* v : qAsConst(activeVoices)) {
306 if (v->chan == chan)
307 v->modulate_all();
308 }
309 }
310
311 /*
312 * fluid_synth_get_pitch_bend
313 */
get_pitch_bend(int chan,int * ppitch_bend)314 void Fluid::get_pitch_bend(int chan, int* ppitch_bend)
315 {
316 *ppitch_bend = channel[chan]->getPitchBend();
317 }
318
319 /*
320 * Fluid_synth_pitch_wheel_sens
321 */
pitch_wheel_sens(int chan,int val)322 void Fluid::pitch_wheel_sens(int chan, int val)
323 {
324 /* set the pitch-bend value in the channel */
325 channel[chan]->pitchWheelSens(val);
326 }
327
328 /*
329 * setFromKeyPortamento
330 * requires an input for a default value, usually the TPC
331 */
setFromKeyPortamento(int chan,int defaultValue)332 void Fluid::setFromKeyPortamento(int chan, int defaultValue) {
333 int ptc = get_cc(chan, PORTAMENTO_CTRL);
334 if (validNote(ptc)) {
335 resetPortamento(chan);
336 fromkey_portamento = ptc;
337 /*
338 // Assumedly this fixed some sort of bug in FluidSynth2
339 if (!validNote(defaultValue))
340 defaultValue = ptc;*/
341 }
342 else {
343
344 /* determines and returns fromkey portamento */
345 fromkey_portamento = Channel::INVALID_NOTE;
346
347 if (portamentoTime(chan)) {
348 /* Portamento when Portamento pedal is On */
349 /* 'fromkey portamento'is determined from the portamento mode
350 and the most recent note played (prev_note)*/
351 if (validNote(defaultValue))
352 fromkey_portamento = ptc;
353 else
354 fromkey_portamento = lastNote;
355 }
356 }
357 }
358
359 /*
360 * fluid_synth_get_preset
361 */
get_preset(unsigned int sfontnum,unsigned banknum,unsigned prognum)362 Preset* Fluid::get_preset(unsigned int sfontnum, unsigned banknum, unsigned prognum)
363 {
364 SFont* sf = get_sfont_by_id(sfontnum);
365 if (sf) {
366 Preset* preset = sf->get_preset(banknum, prognum);
367 if (preset != 0)
368 return preset;
369 }
370 return 0;
371 }
372
373 //---------------------------------------------------------
374 // find_preset
375 //---------------------------------------------------------
376
find_preset(unsigned banknum,unsigned prognum)377 Preset* Fluid::find_preset(unsigned banknum, unsigned prognum)
378 {
379 for (SFont* sf : qAsConst(sfonts)) {
380 Preset* preset = sf->get_preset(banknum, prognum);
381 if (preset)
382 return preset;
383 }
384 return 0;
385 }
386
387 //---------------------------------------------------------
388 // program_change
389 //---------------------------------------------------------
390
program_change(int chan,int prognum)391 void Fluid::program_change(int chan, int prognum)
392 {
393 Channel* c = channel[chan];
394 unsigned banknum = c->getBanknum();
395 c->setPrognum(prognum);
396
397 Preset* preset = find_preset(banknum, prognum);
398 if (!preset) {
399 //Suppressing qDebug because might not have soundfont if using MIDI out only.
400 //qDebug("Fluid::program_change: preset %d %d not found", banknum, prognum);
401 preset = find_preset(0, prognum);
402 if (!preset)
403 preset = find_preset(0, 0);
404 }
405
406 unsigned sfont_idl = preset? preset->sfont->id() : 0;
407 c->setSfontnum(sfont_idl);
408 c->setPreset(preset);
409 }
410
411 /*
412 * fluid_synth_get_program
413 */
get_program(int chan,unsigned * sfont_idl,unsigned * bank_num,unsigned * preset_num)414 void Fluid::get_program(int chan, unsigned* sfont_idl, unsigned* bank_num, unsigned* preset_num)
415 {
416 Channel* c = channel[chan];
417 *sfont_idl = c->getSfontnum();
418 *bank_num = c->getBanknum();
419 *preset_num = c->getPrognum();
420 }
421
422 //---------------------------------------------------------
423 // program_select
424 //---------------------------------------------------------
425
program_select(int chan,unsigned sfont_idl,unsigned bank_num,unsigned preset_num)426 bool Fluid::program_select(int chan, unsigned sfont_idl, unsigned bank_num, unsigned preset_num)
427 {
428 Channel* c = channel[chan];
429 Preset* preset = get_preset(sfont_idl, bank_num, preset_num);
430 if (preset == 0) {
431 qDebug("There is no preset with bank number %d and preset number %d in SoundFont %d", bank_num, preset_num, sfont_idl);
432 return false;
433 }
434
435 /* inform the channel of the new bank and program number */
436 c->setSfontnum(sfont_idl);
437 c->setBanknum(bank_num);
438 c->setPrognum(preset_num);
439 c->setPreset(preset);
440 return true;
441 }
442
443 //---------------------------------------------------------
444 // update_presets
445 //---------------------------------------------------------
446
update_presets()447 void Fluid::update_presets()
448 {
449 for (Channel* c : qAsConst(channel))
450 c->setPreset(get_preset(c->getSfontnum(), c->getBanknum(), c->getPrognum()));
451 }
452
453 //---------------------------------------------------------
454 // process
455 //---------------------------------------------------------
456
process(unsigned len,float * out,float * effect1,float * effect2)457 void Fluid::process(unsigned len, float* out, float* effect1, float* effect2)
458 {
459 if (mutex.tryLock()) {
460 //we have to copy voices array for proper output sound processing in for loop
461 auto tempVoices = activeVoices;
462 for (Voice* v : tempVoices)
463 v->write(len, out, effect1, effect2);
464 mutex.unlock();
465 }
466 }
467
468 /*
469 * fluid_synth_free_voice_by_kill
470 *
471 * selects a voice for killing. the selection algorithm is a refinement
472 * of the algorithm previously in fluid_synth_alloc_voice.
473 */
474
free_voice_by_kill()475 void Fluid::free_voice_by_kill()
476 {
477 float best_prio = 999999.;
478 float this_voice_prio;
479 Voice* best_voice = 0;
480
481 for(Voice* v : qAsConst(activeVoices)) {
482 /* Determine, how 'important' a voice is.
483 * Start with an arbitrary number */
484 this_voice_prio = 10000.;
485
486 /* Is this voice on the drum channel?
487 * Then it is very important.
488 * Also, forget about the released-note condition:
489 * Typically, drum notes are triggered only very briefly, they run most
490 * of the time in release phase.
491 */
492 if (v->chan == 9) {
493 this_voice_prio += 4000;
494
495 }
496 else if (v->RELEASED()) {
497 /* The key for this voice has been released. Consider it much less important
498 * than a voice, which is still held.
499 */
500 this_voice_prio -= 2000.;
501 }
502
503 if (v->SUSTAINED()) {
504 /* The sustain pedal is held down on this channel.
505 * Consider it less important than non-sustained channels.
506 * This decision is somehow subjective. But usually the sustain pedal
507 * is used to play 'more-voices-than-fingers', so it shouldn't hurt
508 * if we kill one voice.
509 */
510 this_voice_prio -= 1000;
511 }
512
513 /* We are not enthusiastic about releasing voices, which have just been started.
514 * Otherwise hitting a chord may result in killing notes belonging to that very same
515 * chord.
516 * So subtract the age of the voice from the priority - an older voice is just a little
517 * bit less important than a younger voice.
518 * This is a number between roughly 0 and 100.*/
519
520 this_voice_prio -= (noteid - v->get_id());
521
522 /* take a rough estimate of loudness into account. Louder voices are more important. */
523 if (v->volenv_section != FLUID_VOICE_ENVATTACK) {
524 this_voice_prio += v->volenv_val * 1000.;
525 }
526
527 /* check if this voice has less priority than the previous candidate. */
528 if (this_voice_prio < best_prio) {
529 best_voice = v;
530 best_prio = this_voice_prio;
531 }
532 }
533 if (best_voice)
534 best_voice->off();
535 }
536
537 //---------------------------------------------------------
538 // alloc_voice
539 //---------------------------------------------------------
540
alloc_voice(unsigned id,Sample * sample,int chan,int key,int vel,double vt)541 Voice* Fluid::alloc_voice(unsigned id, Sample* sample, int chan, int key, int vel, double vt)
542 {
543 Channel* c = 0;
544
545 /* check if there's an available synthesis process */
546 if (freeVoices.isEmpty())
547 free_voice_by_kill();
548
549 if (freeVoices.isEmpty()) {
550 qDebug("Failed to allocate a synthesis process. (chan=%d,key=%d)", chan, key);
551 return 0;
552 }
553
554 Voice* v = freeVoices.takeLast();
555 activeVoices.append(v);
556
557 if (chan >= 0)
558 c = channel[chan];
559
560 v->init(sample, c, key, vel, id, vt);
561
562 /* add the default modulators to the synthesis process. */
563 for (unsigned i = 0; i < sizeof(defaultMod)/sizeof(*defaultMod); ++i)
564 v->add_mod(&defaultMod[i], FLUID_VOICE_DEFAULT);
565 v->add_mod(&forcePanMod, FLUID_VOICE_OVERWRITE);
566 return v;
567 }
568
569 //---------------------------------------------------------
570 // start_voice
571 //---------------------------------------------------------
572
start_voice(Voice * voice)573 void Fluid::start_voice(Voice* voice)
574 {
575 /* Find the exclusive class of this voice. If set, kill all voices
576 * that match the exclusive class and are younger than the first
577 * voice process created by this noteon event. */
578
579 /** Kill all voices on a given channel, which belong into
580 excl_class. This function is called by a SoundFont's preset in
581 response to a noteon event. If one noteon event results in
582 several voice processes (stereo samples), ignore_ID must name
583 the voice ID of the first generated voice (so that it is not
584 stopped). The first voice uses ignore_ID=-1, which will
585 terminate all voices on a channel belonging into the exclusive
586 class excl_class.
587 */
588
589 /* Check if the voice belongs to an exclusive class. In that case,
590 previous notes from the same class are released. */
591
592 int excl_class = voice->GEN(GEN_EXCLUSIVECLASS);
593 if (excl_class) {
594
595 /* Kill all notes on the same channel with the same exclusive class */
596
597 for(Voice* existing_voice : qAsConst(activeVoices)) {
598 /* Existing voice does not play? Leave it alone. */
599 if (!existing_voice->isPlaying())
600 continue;
601
602 /* An exclusive class is valid for a whole channel (or preset).
603 * Is the voice on a different channel? Leave it alone. */
604 if (existing_voice->chan != voice->chan)
605 continue;
606
607 /* Existing voice has a different (or no) exclusive class? Leave it alone. */
608 if ((int)existing_voice->GEN(GEN_EXCLUSIVECLASS) != excl_class)
609 continue;
610
611 /* Existing voice is a voice process belonging to this noteon
612 * event (for example: stereo sample)? Leave it alone. */
613 if (existing_voice->get_id() == voice->get_id())
614 continue;
615 existing_voice->kill_excl();
616 }
617 }
618 voice->voice_start();
619 }
620
621 //---------------------------------------------------------
622 // updatePatchList
623 //---------------------------------------------------------
624
updatePatchList()625 void Fluid::updatePatchList()
626 {
627 qDeleteAll(patches);
628 patches.clear();
629
630 int bankOffset = 0;
631 int sfid = 0;
632 for (SFont* sf : qAsConst(sfonts)) {
633 sf->setBankOffset(bankOffset);
634 int banks = 0;
635 for (Preset* p : sf->getPresets()) {
636 MidiPatch* patch = new MidiPatch;
637 patch->drum = (p->get_banknum() == 128);
638 patch->synti = name();
639 if (p->get_banknum() > banks)
640 banks = p->get_banknum();
641 patch->bank = p->get_banknum() + bankOffset;
642 patch->prog = p->get_num();
643 patch->name = p->get_name();
644 patch->sfid = sfid;
645 patches.append(patch);
646 }
647 sfid++;
648 bankOffset += (banks + 1);
649 }
650
651 /* try to set the correct presets */
652 int n = channel.size();
653 for (int i = 0; i < n; i++)
654 program_change(i, channel[i]->getPrognum());
655 }
656
657 //---------------------------------------------------------
658 // soundFonts
659 //---------------------------------------------------------
660
soundFonts() const661 QStringList Fluid::soundFonts() const
662 {
663 QStringList sf;
664 for (SFont* f : sfonts)
665 sf.append(QFileInfo(f->get_name()).fileName());
666 return sf;
667 }
668
669 //---------------------------------------------------------
670 // soundFontsInfo
671 //---------------------------------------------------------
672
soundFontsInfo() const673 std::vector<SoundFontInfo> Fluid::soundFontsInfo() const
674 {
675 std::vector<SoundFontInfo> sl;
676 sl.reserve(sfonts.size());
677 for (SFont* f : sfonts)
678 sl.emplace_back(QFileInfo(f->get_name()).fileName(), f->fontName());
679 return sl;
680 }
681
682 //---------------------------------------------------------
683 // loadSoundFont
684 // return false on error
685 //---------------------------------------------------------
686
loadSoundFonts(const QStringList & sl)687 bool Fluid::loadSoundFonts(const QStringList& sl)
688 {
689 QStringList ol = soundFonts();
690 if (ol == sl) {
691 qDebug("Fluid:loadSoundFonts: already loaded");
692 return true;
693 }
694 QMutexLocker locker(&mutex);
695 for(Voice* v : qAsConst(activeVoices))
696 v->off();
697 for(Channel* c : qAsConst(channel))
698 c->reset();
699 for (SFont* sf : qAsConst(sfonts))
700 sfunload(sf->id());
701 locker.unlock();
702 bool ok = true;
703
704 QFileInfoList l = sfFiles();
705 for (int i = sl.size() - 1; i >= 0; --i) {
706 QString s = sl[i];
707 if (s.isEmpty())
708 continue;
709 QString path;
710 QFileInfo fis(s);
711 QString fileName = fis.fileName();
712 for (const QFileInfo& fi : qAsConst(l)) {
713 if (fi.fileName() == fileName) {
714 path = fi.absoluteFilePath();
715 break;
716 }
717 }
718 if (path.isEmpty()) {
719 qDebug("Fluid: sf <%s> not found", qPrintable(s));
720 ok = false;
721 }
722 else {
723 locker.relock();
724 if (sfload(path) == -1) {
725 qDebug("loading sf failed: <%s>", qPrintable(path));
726 ok = false;
727 }
728 locker.unlock();
729 }
730 }
731 return ok;
732 }
733
734 //---------------------------------------------------------
735 // addSoundFont
736 // return false on error
737 //---------------------------------------------------------
738
addSoundFont(const QString & s)739 bool Fluid::addSoundFont(const QString& s)
740 {
741 QMutexLocker locker(&mutex);
742 bool rv = (sfload(s) == -1) ? false : true;
743 return rv;
744 }
745
746 //---------------------------------------------------------
747 // removeSoundFont
748 // return false on error
749 //---------------------------------------------------------
750
removeSoundFont(const QString & s)751 bool Fluid::removeSoundFont(const QString& s)
752 {
753 QMutexLocker locker(&mutex);
754 for(Voice* v : qAsConst(activeVoices))
755 v->off();
756 SFont* sf = get_sfont_by_name(s);
757 if (!sf)
758 return false;
759
760 sfunload(sf->id());
761 return true;
762 }
763
764 //---------------------------------------------------------
765 // sfload
766 //---------------------------------------------------------
767
sfload(const QString & filename)768 int Fluid::sfload(const QString& filename)
769 {
770 if (filename.isEmpty())
771 return -1;
772
773 SFont* sf = new SFont(this);
774 try {
775 if (!sf->read(filename)) {
776 delete sf;
777 sf = 0;
778 return -1;
779 }
780 }
781 catch(...) {
782 delete sf;
783 sf = 0;
784 return -1;
785 }
786
787 sf->setId(++sfont_id);
788
789 /* insert the sfont as the first one on the list */
790 sfonts.prepend(sf);
791
792 /* reset the presets for all channels */
793
794 updatePatchList();
795 return sf->id();
796 }
797
798 //---------------------------------------------------------
799 // sfunload
800 //---------------------------------------------------------
801
sfunload(int id)802 bool Fluid::sfunload(int id)
803 {
804 SFont* sf = get_sfont_by_id(id);
805
806 if (!sf) {
807 qDebug("No SoundFont with id = %d", id);
808 return false;
809 }
810
811 sfonts.removeAll(sf); // remove the SoundFont from the list
812 updatePatchList();
813
814 delete sf;
815 return true;
816 }
817
818 //---------------------------------------------------------
819 // get_sfont_by_id
820 //---------------------------------------------------------
821
get_sfont_by_id(int id)822 SFont* Fluid::get_sfont_by_id(int id)
823 {
824 for(SFont* sf : qAsConst(sfonts)) {
825 if (sf->id() == id)
826 return sf;
827 }
828 return 0;
829 }
830
831 //---------------------------------------------------------
832 // get_sfont_by_name
833 //---------------------------------------------------------
834
get_sfont_by_name(const QString & name)835 SFont* Fluid::get_sfont_by_name(const QString& name)
836 {
837 for(SFont* sf : qAsConst(sfonts)) {
838 if (QFileInfo(sf->get_name()).fileName() == name)
839 return sf;
840 }
841 return 0;
842 }
843
844 //---------------------------------------------------------
845 // set_interp_method
846 // Sets the interpolation method to use on channel chan.
847 // If chan is < 0, then set the interpolation method on all channels.
848 //---------------------------------------------------------
849
set_interp_method(int chan,int interp_method)850 void Fluid::set_interp_method(int chan, int interp_method)
851 {
852 for(Channel* c : qAsConst(channel)) {
853 if (chan < 0 || c->getNum() == chan)
854 c->setInterpMethod(interp_method);
855 }
856 }
857
858 //---------------------------------------------------------
859 // set_gen
860 //---------------------------------------------------------
861
set_gen(int chan,int param,float value)862 void Fluid::set_gen(int chan, int param, float value)
863 {
864 channel[chan]->setGen(param, value, 0);
865 for(Voice* v : qAsConst(activeVoices)) {
866 if (v->chan == chan)
867 v->set_param(param, value, 0);
868 }
869 }
870
871 /** Change the value of a generator. This function allows to control
872 all synthesis parameters in real-time. The changes are additive,
873 i.e. they add up to the existing parameter value. This function is
874 similar to sending an NRPN message to the synthesizer. The
875 function accepts a float as the value of the parameter. The
876 parameter numbers and ranges are described in the SoundFont 2.01
877 specification, paragraph 8.1.3, page 48. See also
878 'fluid_gen_type'.
879
880 Using the fluid_synth_set_gen2() function, it is possible to set
881 the absolute value of a generator. This is an extension to the
882 SoundFont standard. If 'absolute' is non-zero, the value of the
883 generator specified in the SoundFont is completely ignored and the
884 generator is fixed to the value passed as argument. To undo this
885 behavior, you must call fluid_synth_set_gen2 again, with
886 'absolute' set to 0 (and possibly 'value' set to zero).
887
888 If 'normalized' is non-zero, the value is supposed to be
889 normalized between 0 and 1. Before applying the value, it will be
890 scaled and shifted to the range defined in the SoundFont
891 specifications.
892
893 */
set_gen2(int chan,int param,float value,int absolute,int normalized)894 void Fluid::set_gen2(int chan, int param, float value, int absolute, int normalized)
895 {
896 float v = (normalized)? fluid_gen_scale(param, value) : value;
897 channel[chan]->setGen(param, v, absolute);
898
899 for(Voice* vo : qAsConst(activeVoices)) {
900 if (vo->chan == chan)
901 vo->set_param(param, v, absolute);
902 }
903 }
904
get_gen(int chan,int param)905 float Fluid::get_gen(int chan, int param)
906 {
907 if ((param < 0) || (param >= GEN_LAST)) {
908 qDebug("Parameter number out of range");
909 return 0.0;
910 }
911 return channel[chan]->getGen(param);
912 }
913
914 //---------------------------------------------------------
915 // state
916 //---------------------------------------------------------
917
state() const918 SynthesizerGroup Fluid::state() const
919 {
920 SynthesizerGroup g;
921 g.setName(name());
922
923 QStringList sfl = soundFonts();
924 for (const QString &sf : qAsConst(sfl))
925 g.push_back(IdValue(0, sf));
926
927 return g;
928 }
929
930 //---------------------------------------------------------
931 // setState
932 //---------------------------------------------------------
933
setState(const SynthesizerGroup & sp)934 bool Fluid::setState(const SynthesizerGroup& sp)
935 {
936 QStringList sfl;
937 for (const IdValue& v : sp) {
938 if (v.id == 0)
939 sfl.append(v.data);
940 else
941 qDebug("Fluid::setState: unknown id %d", v.id);
942 }
943 return loadSoundFonts(sfl);
944 }
945
946 //---------------------------------------------------------
947 // collectFiles
948 //---------------------------------------------------------
949
collectFiles(QFileInfoList * l,const QString & path)950 static void collectFiles(QFileInfoList* l, const QString& path)
951 {
952 QDir dir(path);
953 for (const QFileInfo& s : dir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot)) {
954 if (path == s.absoluteFilePath())
955 return;
956
957 if (s.isDir() && !s.isHidden())
958 collectFiles(l, s.absoluteFilePath());
959 else {
960 QString suffix = s.suffix().toLower();
961 if (suffix == "sf" || suffix == "sf2" || suffix == "sf3")
962 l->append(s);
963 }
964 }
965 }
966
967 //---------------------------------------------------------
968 // sfFiles
969 //---------------------------------------------------------
970
sfFiles()971 QFileInfoList Fluid::sfFiles()
972 {
973 QFileInfoList l;
974
975 QStringList pl = preferences.getString(PREF_APP_PATHS_MYSOUNDFONTS).split(";");
976 pl.prepend(QFileInfo(QString("%1%2").arg(mscoreGlobalShare, "sound")).absoluteFilePath());
977
978 // append extensions directory
979 QStringList extensionsDir = Ms::Extension::getDirectoriesByType(Ms::Extension::soundfontsDir);
980 pl.append(extensionsDir);
981
982 foreach (const QString& s, pl) {
983 QString ss(s);
984 if (!s.isEmpty() && s[0] == '~')
985 ss = QDir::homePath() + s.mid(1);
986 collectFiles(&l, ss);
987 }
988 return l;
989 }
990 }
991