17 #ifdef HAVE_FLUIDSYNTH
19 #include <fluidsynth.h>
23 #define SYSEX_EVENT (0xF0)
25 /* MIDI controllers */
26 #define CTRL_BANKSELECT_MSB (0)
27 #define CTRL_BANKSELECT_LSB (32)
28 #define CTRL_ALLNOTESOFF (123)
31 static int getGenInput(ALenum input
)
35 case AL_ONE_SOFT
: return FLUID_MOD_NONE
;
36 case AL_NOTEON_VELOCITY_SOFT
: return FLUID_MOD_VELOCITY
;
37 case AL_NOTEON_KEY_SOFT
: return FLUID_MOD_KEY
;
38 case AL_KEYPRESSURE_SOFT
: return FLUID_MOD_KEYPRESSURE
;
39 case AL_CHANNELPRESSURE_SOFT
: return FLUID_MOD_CHANNELPRESSURE
;
40 case AL_PITCHBEND_SOFT
: return FLUID_MOD_PITCHWHEEL
;
41 case AL_PITCHBEND_SENSITIVITY_SOFT
: return FLUID_MOD_PITCHWHEELSENS
;
46 static int getGenFlags(ALenum input
, ALenum type
, ALenum form
)
52 case AL_UNORM_SOFT
: ret
|= FLUID_MOD_UNIPOLAR
| FLUID_MOD_POSITIVE
; break;
53 case AL_UNORM_REV_SOFT
: ret
|= FLUID_MOD_UNIPOLAR
| FLUID_MOD_NEGATIVE
; break;
54 case AL_SNORM_SOFT
: ret
|= FLUID_MOD_BIPOLAR
| FLUID_MOD_POSITIVE
; break;
55 case AL_SNORM_REV_SOFT
: ret
|= FLUID_MOD_BIPOLAR
| FLUID_MOD_NEGATIVE
; break;
59 case AL_LINEAR_SOFT
: ret
|= FLUID_MOD_LINEAR
; break;
60 case AL_CONCAVE_SOFT
: ret
|= FLUID_MOD_CONCAVE
; break;
61 case AL_CONVEX_SOFT
: ret
|= FLUID_MOD_CONVEX
; break;
62 case AL_SWITCH_SOFT
: ret
|= FLUID_MOD_SWITCH
; break;
64 /* Source input values less than 128 correspond to a MIDI continuous
65 * controller. Otherwise, it's a general controller. */
66 if(input
< 128) ret
|= FLUID_MOD_CC
;
67 else ret
|= FLUID_MOD_GC
;
72 static enum fluid_gen_type
getSf2Gen(ALenum gen
)
76 case AL_MOD_LFO_TO_PITCH_SOFT
: return GEN_MODLFOTOPITCH
;
77 case AL_VIBRATO_LFO_TO_PITCH_SOFT
: return GEN_VIBLFOTOPITCH
;
78 case AL_MOD_ENV_TO_PITCH_SOFT
: return GEN_MODENVTOPITCH
;
79 case AL_FILTER_CUTOFF_SOFT
: return GEN_FILTERFC
;
80 case AL_FILTER_RESONANCE_SOFT
: return GEN_FILTERQ
;
81 case AL_MOD_LFO_TO_FILTER_CUTOFF_SOFT
: return GEN_MODLFOTOFILTERFC
;
82 case AL_MOD_ENV_TO_FILTER_CUTOFF_SOFT
: return GEN_MODENVTOFILTERFC
;
83 case AL_MOD_LFO_TO_VOLUME_SOFT
: return GEN_MODLFOTOVOL
;
84 case AL_CHORUS_SEND_SOFT
: return GEN_CHORUSSEND
;
85 case AL_REVERB_SEND_SOFT
: return GEN_REVERBSEND
;
86 case AL_PAN_SOFT
: return GEN_PAN
;
87 case AL_MOD_LFO_DELAY_SOFT
: return GEN_MODLFODELAY
;
88 case AL_MOD_LFO_FREQUENCY_SOFT
: return GEN_MODLFOFREQ
;
89 case AL_VIBRATO_LFO_DELAY_SOFT
: return GEN_VIBLFODELAY
;
90 case AL_VIBRATO_LFO_FREQUENCY_SOFT
: return GEN_VIBLFOFREQ
;
91 case AL_MOD_ENV_DELAYTIME_SOFT
: return GEN_MODENVDELAY
;
92 case AL_MOD_ENV_ATTACKTIME_SOFT
: return GEN_MODENVATTACK
;
93 case AL_MOD_ENV_HOLDTIME_SOFT
: return GEN_MODENVHOLD
;
94 case AL_MOD_ENV_DECAYTIME_SOFT
: return GEN_MODENVDECAY
;
95 case AL_MOD_ENV_SUSTAINVOLUME_SOFT
: return GEN_MODENVSUSTAIN
;
96 case AL_MOD_ENV_RELEASETIME_SOFT
: return GEN_MODENVRELEASE
;
97 case AL_MOD_ENV_KEY_TO_HOLDTIME_SOFT
: return GEN_KEYTOMODENVHOLD
;
98 case AL_MOD_ENV_KEY_TO_DECAYTIME_SOFT
: return GEN_KEYTOMODENVDECAY
;
99 case AL_VOLUME_ENV_DELAYTIME_SOFT
: return GEN_VOLENVDELAY
;
100 case AL_VOLUME_ENV_ATTACKTIME_SOFT
: return GEN_VOLENVATTACK
;
101 case AL_VOLUME_ENV_HOLDTIME_SOFT
: return GEN_VOLENVHOLD
;
102 case AL_VOLUME_ENV_DECAYTIME_SOFT
: return GEN_VOLENVDECAY
;
103 case AL_VOLUME_ENV_SUSTAINVOLUME_SOFT
: return GEN_VOLENVSUSTAIN
;
104 case AL_VOLUME_ENV_RELEASETIME_SOFT
: return GEN_VOLENVRELEASE
;
105 case AL_VOLUME_ENV_KEY_TO_HOLDTIME_SOFT
: return GEN_KEYTOVOLENVHOLD
;
106 case AL_VOLUME_ENV_KEY_TO_DECAYTIME_SOFT
: return GEN_KEYTOVOLENVDECAY
;
107 case AL_ATTENUATION_SOFT
: return GEN_ATTENUATION
;
108 case AL_TUNING_COARSE_SOFT
: return GEN_COARSETUNE
;
109 case AL_TUNING_FINE_SOFT
: return GEN_FINETUNE
;
110 case AL_TUNING_SCALE_SOFT
: return GEN_SCALETUNE
;
112 ERR("Unhandled generator: 0x%04x\n", gen
);
116 static int getSf2LoopMode(ALenum mode
)
120 case AL_NONE
: return 0;
121 case AL_LOOP_CONTINUOUS_SOFT
: return 1;
122 case AL_LOOP_UNTIL_RELEASE_SOFT
: return 3;
127 static int getSampleType(ALenum type
)
131 case AL_MONO_SOFT
: return FLUID_SAMPLETYPE_MONO
;
132 case AL_RIGHT_SOFT
: return FLUID_SAMPLETYPE_RIGHT
;
133 case AL_LEFT_SOFT
: return FLUID_SAMPLETYPE_LEFT
;
135 return FLUID_SAMPLETYPE_MONO
;
138 typedef struct FSample
{
139 DERIVE_FROM_TYPE(fluid_sample_t
);
147 static void FSample_Construct(FSample
*self
, ALfontsound
*sound
)
149 fluid_sample_t
*sample
= STATIC_CAST(fluid_sample_t
, self
);
150 memset(sample
->name
, 0, sizeof(sample
->name
));
151 sample
->start
= sound
->Start
;
152 sample
->end
= sound
->End
;
153 sample
->loopstart
= sound
->LoopStart
;
154 sample
->loopend
= sound
->LoopEnd
;
155 sample
->samplerate
= sound
->SampleRate
;
156 sample
->origpitch
= sound
->PitchKey
;
157 sample
->pitchadj
= sound
->PitchCorrection
;
158 sample
->sampletype
= getSampleType(sound
->SampleType
);
159 sample
->valid
= !!sound
->Buffer
;
160 sample
->data
= sound
->Buffer
? sound
->Buffer
->data
: NULL
;
162 sample
->amplitude_that_reaches_noise_floor_is_valid
= 0;
163 sample
->amplitude_that_reaches_noise_floor
= 0.0;
165 sample
->refcount
= 0;
167 sample
->notify
= NULL
;
169 sample
->userdata
= self
;
174 self
->Mods
= calloc(sound
->ModulatorMap
.size
, sizeof(self
->Mods
[0]));
179 self
->NumMods
= sound
->ModulatorMap
.size
;
180 for(i
= 0;i
< self
->NumMods
;i
++)
182 ALsfmodulator
*mod
= sound
->ModulatorMap
.array
[i
].value
;
183 fluid_mod_set_source1(&self
->Mods
[i
], getGenInput(mod
->Source
[0].Input
),
184 getGenFlags(mod
->Source
[0].Input
, mod
->Source
[0].Type
,
185 mod
->Source
[0].Form
));
186 fluid_mod_set_source2(&self
->Mods
[i
], getGenInput(mod
->Source
[1].Input
),
187 getGenFlags(mod
->Source
[1].Input
, mod
->Source
[1].Type
,
188 mod
->Source
[1].Form
));
189 fluid_mod_set_amount(&self
->Mods
[i
], mod
->Amount
);
190 fluid_mod_set_dest(&self
->Mods
[i
], getSf2Gen(mod
->Dest
));
191 self
->Mods
[i
].next
= NULL
;
196 static void FSample_Destruct(FSample
*self
)
204 typedef struct FPreset
{
205 DERIVE_FROM_TYPE(fluid_preset_t
);
216 static char* FPreset_getName(fluid_preset_t
*preset
);
217 static int FPreset_getPreset(fluid_preset_t
*preset
);
218 static int FPreset_getBank(fluid_preset_t
*preset
);
219 static int FPreset_noteOn(fluid_preset_t
*preset
, fluid_synth_t
*synth
, int channel
, int key
, int velocity
);
221 static void FPreset_Construct(FPreset
*self
, ALsfpreset
*preset
, fluid_sfont_t
*parent
)
223 STATIC_CAST(fluid_preset_t
, self
)->data
= self
;
224 STATIC_CAST(fluid_preset_t
, self
)->sfont
= parent
;
225 STATIC_CAST(fluid_preset_t
, self
)->free
= NULL
;
226 STATIC_CAST(fluid_preset_t
, self
)->get_name
= FPreset_getName
;
227 STATIC_CAST(fluid_preset_t
, self
)->get_banknum
= FPreset_getBank
;
228 STATIC_CAST(fluid_preset_t
, self
)->get_num
= FPreset_getPreset
;
229 STATIC_CAST(fluid_preset_t
, self
)->noteon
= FPreset_noteOn
;
230 STATIC_CAST(fluid_preset_t
, self
)->notify
= NULL
;
232 memset(self
->Name
, 0, sizeof(self
->Name
));
233 self
->Preset
= preset
->Preset
;
234 self
->Bank
= preset
->Bank
;
236 self
->NumSamples
= 0;
237 self
->Samples
= calloc(1, preset
->NumSounds
* sizeof(self
->Samples
[0]));
241 self
->NumSamples
= preset
->NumSounds
;
242 for(i
= 0;i
< self
->NumSamples
;i
++)
243 FSample_Construct(&self
->Samples
[i
], preset
->Sounds
[i
]);
247 static void FPreset_Destruct(FPreset
*self
)
251 for(i
= 0;i
< self
->NumSamples
;i
++)
252 FSample_Destruct(&self
->Samples
[i
]);
254 self
->Samples
= NULL
;
255 self
->NumSamples
= 0;
258 static ALboolean
FPreset_canDelete(FPreset
*self
)
262 for(i
= 0;i
< self
->NumSamples
;i
++)
264 if(fluid_sample_refcount(STATIC_CAST(fluid_sample_t
, &self
->Samples
[i
])) != 0)
270 static char* FPreset_getName(fluid_preset_t
*preset
)
272 return ((FPreset
*)preset
->data
)->Name
;
275 static int FPreset_getPreset(fluid_preset_t
*preset
)
277 return ((FPreset
*)preset
->data
)->Preset
;
280 static int FPreset_getBank(fluid_preset_t
*preset
)
282 return ((FPreset
*)preset
->data
)->Bank
;
285 static int FPreset_noteOn(fluid_preset_t
*preset
, fluid_synth_t
*synth
, int channel
, int key
, int vel
)
287 FPreset
*self
= ((FPreset
*)preset
->data
);
290 for(i
= 0;i
< self
->NumSamples
;i
++)
292 FSample
*sample
= &self
->Samples
[i
];
293 ALfontsound
*sound
= sample
->Sound
;
294 fluid_voice_t
*voice
;
297 if(!(key
>= sound
->MinKey
&& key
<= sound
->MaxKey
&& vel
>= sound
->MinVelocity
&& vel
<= sound
->MaxVelocity
))
300 voice
= fluid_synth_alloc_voice(synth
, STATIC_CAST(fluid_sample_t
, sample
), channel
, key
, vel
);
304 fluid_voice_gen_set(voice
, GEN_MODLFOTOPITCH
, sound
->ModLfoToPitch
);
305 fluid_voice_gen_set(voice
, GEN_VIBLFOTOPITCH
, sound
->VibratoLfoToPitch
);
306 fluid_voice_gen_set(voice
, GEN_MODENVTOPITCH
, sound
->ModEnvToPitch
);
307 fluid_voice_gen_set(voice
, GEN_FILTERFC
, sound
->FilterCutoff
);
308 fluid_voice_gen_set(voice
, GEN_FILTERQ
, sound
->FilterQ
);
309 fluid_voice_gen_set(voice
, GEN_MODLFOTOFILTERFC
, sound
->ModLfoToFilterCutoff
);
310 fluid_voice_gen_set(voice
, GEN_MODENVTOFILTERFC
, sound
->ModEnvToFilterCutoff
);
311 fluid_voice_gen_set(voice
, GEN_MODLFOTOVOL
, sound
->ModLfoToVolume
);
312 fluid_voice_gen_set(voice
, GEN_CHORUSSEND
, sound
->ChorusSend
);
313 fluid_voice_gen_set(voice
, GEN_REVERBSEND
, sound
->ReverbSend
);
314 fluid_voice_gen_set(voice
, GEN_PAN
, sound
->Pan
);
315 fluid_voice_gen_set(voice
, GEN_MODLFODELAY
, sound
->ModLfo
.Delay
);
316 fluid_voice_gen_set(voice
, GEN_MODLFOFREQ
, sound
->ModLfo
.Frequency
);
317 fluid_voice_gen_set(voice
, GEN_VIBLFODELAY
, sound
->VibratoLfo
.Delay
);
318 fluid_voice_gen_set(voice
, GEN_VIBLFOFREQ
, sound
->VibratoLfo
.Frequency
);
319 fluid_voice_gen_set(voice
, GEN_MODENVDELAY
, sound
->ModEnv
.DelayTime
);
320 fluid_voice_gen_set(voice
, GEN_MODENVATTACK
, sound
->ModEnv
.AttackTime
);
321 fluid_voice_gen_set(voice
, GEN_MODENVHOLD
, sound
->ModEnv
.HoldTime
);
322 fluid_voice_gen_set(voice
, GEN_MODENVDECAY
, sound
->ModEnv
.DecayTime
);
323 fluid_voice_gen_set(voice
, GEN_MODENVSUSTAIN
, sound
->ModEnv
.SustainAttn
);
324 fluid_voice_gen_set(voice
, GEN_MODENVRELEASE
, sound
->ModEnv
.ReleaseTime
);
325 fluid_voice_gen_set(voice
, GEN_KEYTOMODENVHOLD
, sound
->ModEnv
.KeyToHoldTime
);
326 fluid_voice_gen_set(voice
, GEN_KEYTOMODENVDECAY
, sound
->ModEnv
.KeyToDecayTime
);
327 fluid_voice_gen_set(voice
, GEN_VOLENVDELAY
, sound
->VolEnv
.DelayTime
);
328 fluid_voice_gen_set(voice
, GEN_VOLENVATTACK
, sound
->VolEnv
.AttackTime
);
329 fluid_voice_gen_set(voice
, GEN_VOLENVHOLD
, sound
->VolEnv
.HoldTime
);
330 fluid_voice_gen_set(voice
, GEN_VOLENVDECAY
, sound
->VolEnv
.DecayTime
);
331 fluid_voice_gen_set(voice
, GEN_VOLENVSUSTAIN
, sound
->VolEnv
.SustainAttn
);
332 fluid_voice_gen_set(voice
, GEN_VOLENVRELEASE
, sound
->VolEnv
.ReleaseTime
);
333 fluid_voice_gen_set(voice
, GEN_KEYTOVOLENVHOLD
, sound
->VolEnv
.KeyToHoldTime
);
334 fluid_voice_gen_set(voice
, GEN_KEYTOVOLENVDECAY
, sound
->VolEnv
.KeyToDecayTime
);
335 fluid_voice_gen_set(voice
, GEN_ATTENUATION
, sound
->Attenuation
);
336 fluid_voice_gen_set(voice
, GEN_COARSETUNE
, sound
->CoarseTuning
);
337 fluid_voice_gen_set(voice
, GEN_FINETUNE
, sound
->FineTuning
);
338 fluid_voice_gen_set(voice
, GEN_SAMPLEMODE
, getSf2LoopMode(sound
->LoopMode
));
339 fluid_voice_gen_set(voice
, GEN_SCALETUNE
, sound
->TuningScale
);
340 fluid_voice_gen_set(voice
, GEN_EXCLUSIVECLASS
, sound
->ExclusiveClass
);
341 for(m
= 0;m
< sample
->NumMods
;m
++)
342 fluid_voice_add_mod(voice
, &sample
->Mods
[m
], FLUID_VOICE_OVERWRITE
);
344 fluid_synth_start_voice(synth
, voice
);
351 typedef struct FSfont
{
352 DERIVE_FROM_TYPE(fluid_sfont_t
);
362 static int FSfont_free(fluid_sfont_t
*sfont
);
363 static char* FSfont_getName(fluid_sfont_t
*sfont
);
364 static fluid_preset_t
* FSfont_getPreset(fluid_sfont_t
*sfont
, unsigned int bank
, unsigned int prenum
);
365 static void FSfont_iterStart(fluid_sfont_t
*sfont
);
366 static int FSfont_iterNext(fluid_sfont_t
*sfont
, fluid_preset_t
*preset
);
368 static void FSfont_Construct(FSfont
*self
, ALsoundfont
*sfont
)
370 STATIC_CAST(fluid_sfont_t
, self
)->data
= self
;
371 STATIC_CAST(fluid_sfont_t
, self
)->id
= FLUID_FAILED
;
372 STATIC_CAST(fluid_sfont_t
, self
)->free
= FSfont_free
;
373 STATIC_CAST(fluid_sfont_t
, self
)->get_name
= FSfont_getName
;
374 STATIC_CAST(fluid_sfont_t
, self
)->get_preset
= FSfont_getPreset
;
375 STATIC_CAST(fluid_sfont_t
, self
)->iteration_start
= FSfont_iterStart
;
376 STATIC_CAST(fluid_sfont_t
, self
)->iteration_next
= FSfont_iterNext
;
378 memset(self
->Name
, 0, sizeof(self
->Name
));
379 self
->CurrentPos
= 0;
380 self
->NumPresets
= 0;
381 self
->Presets
= calloc(1, sfont
->NumPresets
* sizeof(self
->Presets
[0]));
385 self
->NumPresets
= sfont
->NumPresets
;
386 for(i
= 0;i
< self
->NumPresets
;i
++)
387 FPreset_Construct(&self
->Presets
[i
], sfont
->Presets
[i
], STATIC_CAST(fluid_sfont_t
, self
));
391 static void FSfont_Destruct(FSfont
*self
)
395 for(i
= 0;i
< self
->NumPresets
;i
++)
396 FPreset_Destruct(&self
->Presets
[i
]);
398 self
->Presets
= NULL
;
399 self
->NumPresets
= 0;
400 self
->CurrentPos
= 0;
403 static int FSfont_free(fluid_sfont_t
*sfont
)
405 FSfont
*self
= STATIC_UPCAST(FSfont
, fluid_sfont_t
, sfont
);
408 for(i
= 0;i
< self
->NumPresets
;i
++)
410 if(!FPreset_canDelete(&self
->Presets
[i
]))
414 FSfont_Destruct(self
);
419 static char* FSfont_getName(fluid_sfont_t
*sfont
)
421 return STATIC_UPCAST(FSfont
, fluid_sfont_t
, sfont
)->Name
;
424 static fluid_preset_t
*FSfont_getPreset(fluid_sfont_t
*sfont
, unsigned int bank
, unsigned int prenum
)
426 FSfont
*self
= STATIC_UPCAST(FSfont
, fluid_sfont_t
, sfont
);
429 for(i
= 0;i
< self
->NumPresets
;i
++)
431 FPreset
*preset
= &self
->Presets
[i
];
432 if(preset
->Bank
== (int)bank
&& preset
->Preset
== (int)prenum
)
433 return STATIC_CAST(fluid_preset_t
, preset
);
439 static void FSfont_iterStart(fluid_sfont_t
*sfont
)
441 STATIC_UPCAST(FSfont
, fluid_sfont_t
, sfont
)->CurrentPos
= 0;
444 static int FSfont_iterNext(fluid_sfont_t
*sfont
, fluid_preset_t
*preset
)
446 FSfont
*self
= STATIC_UPCAST(FSfont
, fluid_sfont_t
, sfont
);
447 if(self
->CurrentPos
>= self
->NumPresets
)
449 *preset
= *STATIC_CAST(fluid_preset_t
, &self
->Presets
[self
->CurrentPos
++]);
455 typedef struct FSynth
{
456 DERIVE_FROM_TYPE(MidiSynth
);
457 DERIVE_FROM_TYPE(fluid_sfloader_t
);
459 fluid_settings_t
*Settings
;
460 fluid_synth_t
*Synth
;
464 ALboolean ForceGM2BankSelect
;
468 static void FSynth_Construct(FSynth
*self
, ALCdevice
*device
);
469 static void FSynth_Destruct(FSynth
*self
);
470 static ALboolean
FSynth_init(FSynth
*self
, ALCdevice
*device
);
471 static ALenum
FSynth_selectSoundfonts(FSynth
*self
, ALCcontext
*context
, ALsizei count
, const ALuint
*ids
);
472 static void FSynth_setGain(FSynth
*self
, ALfloat gain
);
473 static void FSynth_stop(FSynth
*self
);
474 static void FSynth_reset(FSynth
*self
);
475 static void FSynth_update(FSynth
*self
, ALCdevice
*device
);
476 static void FSynth_processQueue(FSynth
*self
, ALuint64 time
);
477 static void FSynth_process(FSynth
*self
, ALuint SamplesToDo
, ALfloat (*restrict DryBuffer
)[BUFFERSIZE
]);
478 DECLARE_DEFAULT_ALLOCATORS(FSynth
)
479 DEFINE_MIDISYNTH_VTABLE(FSynth
);
481 static fluid_sfont_t
*FSynth_loadSfont(fluid_sfloader_t
*loader
, const char *filename
);
484 static void FSynth_Construct(FSynth
*self
, ALCdevice
*device
)
486 MidiSynth_Construct(STATIC_CAST(MidiSynth
, self
), device
);
487 SET_VTABLE2(FSynth
, MidiSynth
, self
);
489 STATIC_CAST(fluid_sfloader_t
, self
)->data
= self
;
490 STATIC_CAST(fluid_sfloader_t
, self
)->free
= NULL
;
491 STATIC_CAST(fluid_sfloader_t
, self
)->load
= FSynth_loadSfont
;
493 self
->Settings
= NULL
;
495 self
->FontIDs
= NULL
;
496 self
->NumFontIDs
= 0;
497 self
->ForceGM2BankSelect
= AL_FALSE
;
498 self
->GainScale
= 0.2f
;
501 static void FSynth_Destruct(FSynth
*self
)
505 for(i
= 0;i
< self
->NumFontIDs
;i
++)
506 fluid_synth_sfunload(self
->Synth
, self
->FontIDs
[i
], 0);
508 self
->FontIDs
= NULL
;
509 self
->NumFontIDs
= 0;
511 if(self
->Synth
!= NULL
)
512 delete_fluid_synth(self
->Synth
);
515 if(self
->Settings
!= NULL
)
516 delete_fluid_settings(self
->Settings
);
517 self
->Settings
= NULL
;
519 MidiSynth_Destruct(STATIC_CAST(MidiSynth
, self
));
522 static ALboolean
FSynth_init(FSynth
*self
, ALCdevice
*device
)
526 if(ConfigValueFloat("midi", "volume", &vol
))
530 ERR("MIDI volume %f clamped to 0\n", vol
);
533 self
->GainScale
= powf(10.0f
, vol
/ 20.0f
);
536 self
->Settings
= new_fluid_settings();
539 ERR("Failed to create FluidSettings\n");
543 fluid_settings_setint(self
->Settings
, "synth.polyphony", 256);
544 fluid_settings_setnum(self
->Settings
, "synth.gain", self
->GainScale
);
545 fluid_settings_setnum(self
->Settings
, "synth.sample-rate", device
->Frequency
);
547 self
->Synth
= new_fluid_synth(self
->Settings
);
550 ERR("Failed to create FluidSynth\n");
554 fluid_synth_add_sfloader(self
->Synth
, STATIC_CAST(fluid_sfloader_t
, self
));
560 static fluid_sfont_t
*FSynth_loadSfont(fluid_sfloader_t
*loader
, const char *filename
)
562 FSynth
*self
= STATIC_UPCAST(FSynth
, fluid_sfloader_t
, loader
);
566 if(!filename
|| sscanf(filename
, "_al_internal %d", &idx
) != 1)
568 if(idx
< 0 || idx
>= STATIC_CAST(MidiSynth
, self
)->NumSoundfonts
)
570 ERR("Received invalid soundfont index %d (max: %d)\n", idx
, STATIC_CAST(MidiSynth
, self
)->NumSoundfonts
);
574 sfont
= calloc(1, sizeof(sfont
[0]));
575 if(!sfont
) return NULL
;
577 FSfont_Construct(sfont
, STATIC_CAST(MidiSynth
, self
)->Soundfonts
[idx
]);
578 return STATIC_CAST(fluid_sfont_t
, sfont
);
581 static ALenum
FSynth_selectSoundfonts(FSynth
*self
, ALCcontext
*context
, ALsizei count
, const ALuint
*ids
)
587 ret
= MidiSynth_selectSoundfonts(STATIC_CAST(MidiSynth
, self
), context
, count
, ids
);
588 if(ret
!= AL_NO_ERROR
) return ret
;
590 ALCdevice_Lock(context
->Device
);
591 for(i
= 0;i
< 16;i
++)
592 fluid_synth_all_sounds_off(self
->Synth
, i
);
593 ALCdevice_Unlock(context
->Device
);
595 fontid
= malloc(count
* sizeof(fontid
[0]));
598 for(i
= 0;i
< STATIC_CAST(MidiSynth
, self
)->NumSoundfonts
;i
++)
601 snprintf(name
, sizeof(name
), "_al_internal %d", i
);
603 fontid
[i
] = fluid_synth_sfload(self
->Synth
, name
, 0);
604 if(fontid
[i
] == FLUID_FAILED
)
605 ERR("Failed to load selected soundfont %d\n", i
);
608 fontid
= ExchangePtr((XchgPtr
*)&self
->FontIDs
, fontid
);
609 count
= ExchangeInt(&self
->NumFontIDs
, count
);
613 ERR("Failed to allocate space for %d font IDs!\n", count
);
614 fontid
= ExchangePtr((XchgPtr
*)&self
->FontIDs
, NULL
);
615 count
= ExchangeInt(&self
->NumFontIDs
, 0);
618 for(i
= 0;i
< count
;i
++)
619 fluid_synth_sfunload(self
->Synth
, fontid
[i
], 0);
626 static void FSynth_setGain(FSynth
*self
, ALfloat gain
)
628 fluid_settings_setnum(self
->Settings
, "synth.gain", self
->GainScale
* gain
);
629 fluid_synth_set_gain(self
->Synth
, self
->GainScale
* gain
);
630 MidiSynth_setGain(STATIC_CAST(MidiSynth
, self
), gain
);
634 static void FSynth_stop(FSynth
*self
)
636 MidiSynth
*synth
= STATIC_CAST(MidiSynth
, self
);
640 /* Make sure all pending events are processed. */
641 curtime
= MidiSynth_getTime(synth
);
642 FSynth_processQueue(self
, curtime
);
645 for(chan
= 0;chan
< 16;chan
++)
646 fluid_synth_cc(self
->Synth
, chan
, CTRL_ALLNOTESOFF
, 0);
648 MidiSynth_stop(STATIC_CAST(MidiSynth
, self
));
651 static void FSynth_reset(FSynth
*self
)
653 /* Reset to power-up status. */
654 fluid_synth_system_reset(self
->Synth
);
656 MidiSynth_reset(STATIC_CAST(MidiSynth
, self
));
660 static void FSynth_update(FSynth
*self
, ALCdevice
*device
)
662 fluid_settings_setnum(self
->Settings
, "synth.sample-rate", device
->Frequency
);
663 fluid_synth_set_sample_rate(self
->Synth
, device
->Frequency
);
664 MidiSynth_update(STATIC_CAST(MidiSynth
, self
), device
);
668 static void FSynth_processQueue(FSynth
*self
, ALuint64 time
)
670 EvtQueue
*queue
= &STATIC_CAST(MidiSynth
, self
)->EventQueue
;
672 while(queue
->pos
< queue
->size
&& queue
->events
[queue
->pos
].time
<= time
)
674 const MidiEvent
*evt
= &queue
->events
[queue
->pos
];
676 if(evt
->event
== SYSEX_EVENT
)
678 static const ALbyte gm2_on
[] = { 0x7E, 0x7F, 0x09, 0x03 };
679 static const ALbyte gm2_off
[] = { 0x7E, 0x7F, 0x09, 0x02 };
682 fluid_synth_sysex(self
->Synth
, evt
->param
.sysex
.data
, evt
->param
.sysex
.size
, NULL
, NULL
, &handled
, 0);
683 if(!handled
&& evt
->param
.sysex
.size
>= (ALsizei
)sizeof(gm2_on
))
685 if(memcmp(evt
->param
.sysex
.data
, gm2_on
, sizeof(gm2_on
)) == 0)
686 self
->ForceGM2BankSelect
= AL_TRUE
;
687 else if(memcmp(evt
->param
.sysex
.data
, gm2_off
, sizeof(gm2_off
)) == 0)
688 self
->ForceGM2BankSelect
= AL_FALSE
;
691 else switch((evt
->event
&0xF0))
693 case AL_NOTEOFF_SOFT
:
694 fluid_synth_noteoff(self
->Synth
, (evt
->event
&0x0F), evt
->param
.val
[0]);
697 fluid_synth_noteon(self
->Synth
, (evt
->event
&0x0F), evt
->param
.val
[0], evt
->param
.val
[1]);
699 case AL_KEYPRESSURE_SOFT
:
702 case AL_CONTROLLERCHANGE_SOFT
:
703 if(self
->ForceGM2BankSelect
)
705 int chan
= (evt
->event
&0x0F);
706 if(evt
->param
.val
[0] == CTRL_BANKSELECT_MSB
)
708 if(evt
->param
.val
[1] == 120 && (chan
== 9 || chan
== 10))
709 fluid_synth_set_channel_type(self
->Synth
, chan
, CHANNEL_TYPE_DRUM
);
710 else if(evt
->param
.val
[1] == 121)
711 fluid_synth_set_channel_type(self
->Synth
, chan
, CHANNEL_TYPE_MELODIC
);
714 if(evt
->param
.val
[0] == CTRL_BANKSELECT_LSB
)
716 fluid_synth_bank_select(self
->Synth
, chan
, evt
->param
.val
[1]);
720 fluid_synth_cc(self
->Synth
, (evt
->event
&0x0F), evt
->param
.val
[0], evt
->param
.val
[1]);
722 case AL_PROGRAMCHANGE_SOFT
:
723 fluid_synth_program_change(self
->Synth
, (evt
->event
&0x0F), evt
->param
.val
[0]);
726 case AL_CHANNELPRESSURE_SOFT
:
727 fluid_synth_channel_pressure(self
->Synth
, (evt
->event
&0x0F), evt
->param
.val
[0]);
730 case AL_PITCHBEND_SOFT
:
731 fluid_synth_pitch_bend(self
->Synth
, (evt
->event
&0x0F), (evt
->param
.val
[0]&0x7F) |
732 ((evt
->param
.val
[1]&0x7F)<<7));
740 static void FSynth_process(FSynth
*self
, ALuint SamplesToDo
, ALfloat (*restrict DryBuffer
)[BUFFERSIZE
])
742 MidiSynth
*synth
= STATIC_CAST(MidiSynth
, self
);
743 ALenum state
= synth
->State
;
747 if(state
== AL_INITIAL
)
749 if(state
!= AL_PLAYING
)
751 fluid_synth_write_float(self
->Synth
, SamplesToDo
, DryBuffer
[FrontLeft
], 0, 1,
752 DryBuffer
[FrontRight
], 0, 1);
756 curtime
= MidiSynth_getTime(synth
);
757 while(total
< SamplesToDo
)
762 time
= MidiSynth_getNextEvtTime(synth
);
763 diff
= maxu64(time
, curtime
) - curtime
;
764 if(diff
>= MIDI_CLOCK_RES
|| time
== UINT64_MAX
)
766 /* If there's no pending event, or if it's more than 1 second
767 * away, do as many samples as we can. */
772 /* Figure out how many samples until the next event. */
773 tonext
= (ALint
)((diff
*synth
->SampleRate
+ (MIDI_CLOCK_RES
-1)) / MIDI_CLOCK_RES
);
779 ALuint todo
= mini(tonext
, SamplesToDo
-total
);
780 fluid_synth_write_float(self
->Synth
, todo
, DryBuffer
[FrontLeft
], total
, 1,
781 DryBuffer
[FrontRight
], total
, 1);
785 if(total
< SamplesToDo
&& tonext
== 0)
786 FSynth_processQueue(self
, time
);
789 synth
->SamplesDone
+= SamplesToDo
;
790 synth
->ClockBase
+= (synth
->SamplesDone
/synth
->SampleRate
) * MIDI_CLOCK_RES
;
791 synth
->SamplesDone
%= synth
->SampleRate
;
795 MidiSynth
*FSynth_create(ALCdevice
*device
)
797 FSynth
*synth
= FSynth_New(sizeof(*synth
));
800 ERR("Failed to allocate FSynth\n");
803 memset(synth
, 0, sizeof(*synth
));
804 FSynth_Construct(synth
, device
);
806 if(FSynth_init(synth
, device
) == AL_FALSE
)
808 DELETE_OBJ(STATIC_CAST(MidiSynth
, synth
));
812 return STATIC_CAST(MidiSynth
, synth
);
817 MidiSynth
*FSynth_create(ALCdevice
* UNUSED(device
))