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_AFTERTOUCH_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
, ALsoundfont
*sfont
)
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
);
160 sample
->data
= sfont
->Samples
;
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
, ALsoundfont
*sfont
)
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
], sfont
);
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
), sfont
);
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
;
467 static void FSynth_Construct(FSynth
*self
, ALCdevice
*device
);
468 static void FSynth_Destruct(FSynth
*self
);
469 static ALboolean
FSynth_init(FSynth
*self
, ALCdevice
*device
);
470 static ALenum
FSynth_selectSoundfonts(FSynth
*self
, ALCcontext
*context
, ALsizei count
, const ALuint
*ids
);
471 static void FSynth_setGain(FSynth
*self
, ALfloat gain
);
472 static void FSynth_setState(FSynth
*self
, ALenum state
);
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 static void FSynth_Delete(FSynth
*self
);
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
;
500 static void FSynth_Destruct(FSynth
*self
)
504 for(i
= 0;i
< self
->NumFontIDs
;i
++)
505 fluid_synth_sfunload(self
->Synth
, self
->FontIDs
[i
], 0);
507 self
->FontIDs
= NULL
;
508 self
->NumFontIDs
= 0;
510 if(self
->Synth
!= NULL
)
511 delete_fluid_synth(self
->Synth
);
514 if(self
->Settings
!= NULL
)
515 delete_fluid_settings(self
->Settings
);
516 self
->Settings
= NULL
;
518 MidiSynth_Destruct(STATIC_CAST(MidiSynth
, self
));
521 static ALboolean
FSynth_init(FSynth
*self
, ALCdevice
*device
)
523 self
->Settings
= new_fluid_settings();
526 ERR("Failed to create FluidSettings\n");
530 fluid_settings_setint(self
->Settings
, "synth.polyphony", 256);
531 fluid_settings_setnum(self
->Settings
, "synth.sample-rate", device
->Frequency
);
533 self
->Synth
= new_fluid_synth(self
->Settings
);
536 ERR("Failed to create FluidSynth\n");
540 fluid_synth_add_sfloader(self
->Synth
, STATIC_CAST(fluid_sfloader_t
, self
));
546 static fluid_sfont_t
*FSynth_loadSfont(fluid_sfloader_t
*loader
, const char *filename
)
548 FSynth
*self
= STATIC_UPCAST(FSynth
, fluid_sfloader_t
, loader
);
552 if(!filename
|| sscanf(filename
, "_al_internal %d", &idx
) != 1)
554 if(idx
< 0 || idx
>= STATIC_CAST(MidiSynth
, self
)->NumSoundfonts
)
556 ERR("Received invalid soundfont index %d (max: %d)\n", idx
, STATIC_CAST(MidiSynth
, self
)->NumSoundfonts
);
560 sfont
= calloc(1, sizeof(sfont
[0]));
561 if(!sfont
) return NULL
;
563 FSfont_Construct(sfont
, STATIC_CAST(MidiSynth
, self
)->Soundfonts
[idx
]);
564 return STATIC_CAST(fluid_sfont_t
, sfont
);
567 static ALenum
FSynth_selectSoundfonts(FSynth
*self
, ALCcontext
*context
, ALsizei count
, const ALuint
*ids
)
573 ret
= MidiSynth_selectSoundfonts(STATIC_CAST(MidiSynth
, self
), context
, count
, ids
);
574 if(ret
!= AL_NO_ERROR
) return ret
;
576 ALCdevice_Lock(context
->Device
);
577 for(i
= 0;i
< 16;i
++)
578 fluid_synth_all_sounds_off(self
->Synth
, i
);
579 ALCdevice_Unlock(context
->Device
);
581 fontid
= malloc(count
* sizeof(fontid
[0]));
584 for(i
= 0;i
< STATIC_CAST(MidiSynth
, self
)->NumSoundfonts
;i
++)
587 snprintf(name
, sizeof(name
), "_al_internal %d", i
);
589 fontid
[i
] = fluid_synth_sfload(self
->Synth
, name
, 0);
590 if(fontid
[i
] == FLUID_FAILED
)
591 ERR("Failed to load selected soundfont %d\n", i
);
594 fontid
= ExchangePtr((XchgPtr
*)&self
->FontIDs
, fontid
);
595 count
= ExchangeInt(&self
->NumFontIDs
, count
);
599 ERR("Failed to allocate space for %d font IDs!\n", count
);
600 fontid
= ExchangePtr((XchgPtr
*)&self
->FontIDs
, NULL
);
601 count
= ExchangeInt(&self
->NumFontIDs
, 0);
604 for(i
= 0;i
< count
;i
++)
605 fluid_synth_sfunload(self
->Synth
, fontid
[i
], 0);
612 static void FSynth_setGain(FSynth
*self
, ALfloat gain
)
614 /* Scale gain by an additional 0.2 (-14dB), to help keep the mix from clipping. */
615 fluid_settings_setnum(self
->Settings
, "synth.gain", 0.2 * gain
);
616 fluid_synth_set_gain(self
->Synth
, 0.2f
* gain
);
617 MidiSynth_setGain(STATIC_CAST(MidiSynth
, self
), gain
);
621 static void FSynth_setState(FSynth
*self
, ALenum state
)
623 MidiSynth_setState(STATIC_CAST(MidiSynth
, self
), state
);
626 static void FSynth_stop(FSynth
*self
)
628 MidiSynth
*synth
= STATIC_CAST(MidiSynth
, self
);
631 /* Make sure all pending events are processed. */
632 while(!(synth
->SamplesToNext
>= 1.0))
634 ALuint64 time
= synth
->NextEvtTime
;
635 if(time
== UINT64_MAX
)
638 synth
->SamplesSinceLast
-= (time
- synth
->LastEvtTime
) * synth
->SamplesPerTick
;
639 synth
->SamplesSinceLast
= maxd(synth
->SamplesSinceLast
, 0.0);
640 synth
->LastEvtTime
= time
;
641 FSynth_processQueue(self
, time
);
643 synth
->NextEvtTime
= MidiSynth_getNextEvtTime(synth
);
644 if(synth
->NextEvtTime
!= UINT64_MAX
)
645 synth
->SamplesToNext
+= (synth
->NextEvtTime
- synth
->LastEvtTime
) * synth
->SamplesPerTick
;
649 for(chan
= 0;chan
< 16;chan
++)
650 fluid_synth_cc(self
->Synth
, chan
, CTRL_ALLNOTESOFF
, 0);
652 MidiSynth_stop(STATIC_CAST(MidiSynth
, self
));
655 static void FSynth_reset(FSynth
*self
)
657 /* Reset to power-up status. */
658 fluid_synth_system_reset(self
->Synth
);
660 MidiSynth_reset(STATIC_CAST(MidiSynth
, self
));
664 static void FSynth_update(FSynth
*self
, ALCdevice
*device
)
666 fluid_settings_setnum(self
->Settings
, "synth.sample-rate", device
->Frequency
);
667 fluid_synth_set_sample_rate(self
->Synth
, device
->Frequency
);
668 MidiSynth_update(STATIC_CAST(MidiSynth
, self
), device
);
672 static void FSynth_processQueue(FSynth
*self
, ALuint64 time
)
674 EvtQueue
*queue
= &STATIC_CAST(MidiSynth
, self
)->EventQueue
;
676 while(queue
->pos
< queue
->size
&& queue
->events
[queue
->pos
].time
<= time
)
678 const MidiEvent
*evt
= &queue
->events
[queue
->pos
];
680 if(evt
->event
== SYSEX_EVENT
)
682 static const ALbyte gm2_on
[] = { 0x7E, 0x7F, 0x09, 0x03 };
683 static const ALbyte gm2_off
[] = { 0x7E, 0x7F, 0x09, 0x02 };
686 fluid_synth_sysex(self
->Synth
, evt
->param
.sysex
.data
, evt
->param
.sysex
.size
, NULL
, NULL
, &handled
, 0);
687 if(!handled
&& evt
->param
.sysex
.size
>= (ALsizei
)sizeof(gm2_on
))
689 if(memcmp(evt
->param
.sysex
.data
, gm2_on
, sizeof(gm2_on
)) == 0)
690 self
->ForceGM2BankSelect
= AL_TRUE
;
691 else if(memcmp(evt
->param
.sysex
.data
, gm2_off
, sizeof(gm2_off
)) == 0)
692 self
->ForceGM2BankSelect
= AL_FALSE
;
695 else switch((evt
->event
&0xF0))
697 case AL_NOTEOFF_SOFT
:
698 fluid_synth_noteoff(self
->Synth
, (evt
->event
&0x0F), evt
->param
.val
[0]);
701 fluid_synth_noteon(self
->Synth
, (evt
->event
&0x0F), evt
->param
.val
[0], evt
->param
.val
[1]);
703 case AL_AFTERTOUCH_SOFT
:
706 case AL_CONTROLLERCHANGE_SOFT
:
707 if(self
->ForceGM2BankSelect
)
709 int chan
= (evt
->event
&0x0F);
710 if(evt
->param
.val
[0] == CTRL_BANKSELECT_MSB
)
712 if(evt
->param
.val
[1] == 120 && (chan
== 9 || chan
== 10))
713 fluid_synth_set_channel_type(self
->Synth
, chan
, CHANNEL_TYPE_DRUM
);
714 else if(evt
->param
.val
[1] == 121)
715 fluid_synth_set_channel_type(self
->Synth
, chan
, CHANNEL_TYPE_MELODIC
);
718 if(evt
->param
.val
[0] == CTRL_BANKSELECT_LSB
)
720 fluid_synth_bank_select(self
->Synth
, chan
, evt
->param
.val
[1]);
724 fluid_synth_cc(self
->Synth
, (evt
->event
&0x0F), evt
->param
.val
[0], evt
->param
.val
[1]);
726 case AL_PROGRAMCHANGE_SOFT
:
727 fluid_synth_program_change(self
->Synth
, (evt
->event
&0x0F), evt
->param
.val
[0]);
730 case AL_CHANNELPRESSURE_SOFT
:
731 fluid_synth_channel_pressure(self
->Synth
, (evt
->event
&0x0F), evt
->param
.val
[0]);
734 case AL_PITCHBEND_SOFT
:
735 fluid_synth_pitch_bend(self
->Synth
, (evt
->event
&0x0F), (evt
->param
.val
[0]&0x7F) |
736 ((evt
->param
.val
[1]&0x7F)<<7));
744 static void FSynth_process(FSynth
*self
, ALuint SamplesToDo
, ALfloat (*restrict DryBuffer
)[BUFFERSIZE
])
746 MidiSynth
*synth
= STATIC_CAST(MidiSynth
, self
);
747 ALenum state
= synth
->State
;
750 if(state
== AL_INITIAL
)
752 if(state
!= AL_PLAYING
)
754 fluid_synth_write_float(self
->Synth
, SamplesToDo
, DryBuffer
[FrontLeft
], 0, 1,
755 DryBuffer
[FrontRight
], 0, 1);
759 while(total
< SamplesToDo
)
761 if(synth
->SamplesToNext
>= 1.0)
763 ALuint todo
= minu(SamplesToDo
- total
, fastf2u(synth
->SamplesToNext
));
765 fluid_synth_write_float(self
->Synth
, todo
,
766 &DryBuffer
[FrontLeft
][total
], 0, 1,
767 &DryBuffer
[FrontRight
][total
], 0, 1);
769 synth
->SamplesSinceLast
+= todo
;
770 synth
->SamplesToNext
-= todo
;
774 ALuint64 time
= synth
->NextEvtTime
;
775 if(time
== UINT64_MAX
)
777 synth
->SamplesSinceLast
+= SamplesToDo
-total
;
778 fluid_synth_write_float(self
->Synth
, SamplesToDo
-total
,
779 &DryBuffer
[FrontLeft
][total
], 0, 1,
780 &DryBuffer
[FrontRight
][total
], 0, 1);
784 synth
->SamplesSinceLast
-= (time
- synth
->LastEvtTime
) * synth
->SamplesPerTick
;
785 synth
->SamplesSinceLast
= maxd(synth
->SamplesSinceLast
, 0.0);
786 synth
->LastEvtTime
= time
;
787 FSynth_processQueue(self
, time
);
789 synth
->NextEvtTime
= MidiSynth_getNextEvtTime(synth
);
790 if(synth
->NextEvtTime
!= UINT64_MAX
)
791 synth
->SamplesToNext
+= (synth
->NextEvtTime
- synth
->LastEvtTime
) * synth
->SamplesPerTick
;
797 static void FSynth_Delete(FSynth
*self
)
803 MidiSynth
*FSynth_create(ALCdevice
*device
)
805 FSynth
*synth
= calloc(1, sizeof(*synth
));
808 ERR("Failed to allocate FSynth\n");
811 FSynth_Construct(synth
, device
);
813 if(FSynth_init(synth
, device
) == AL_FALSE
)
815 DELETE_OBJ(STATIC_CAST(MidiSynth
, synth
));
819 return STATIC_CAST(MidiSynth
, synth
);
824 MidiSynth
*FSynth_create(ALCdevice
* UNUSED(device
))