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 for(i
= j
= 0;i
< sound
->ModulatorMap
.size
;i
++)
181 ALsfmodulator
*mod
= sound
->ModulatorMap
.array
[i
].value
;
182 if(mod
->Dest
== AL_NONE
)
184 fluid_mod_set_source1(&self
->Mods
[j
], getGenInput(mod
->Source
[0].Input
),
185 getGenFlags(mod
->Source
[0].Input
, mod
->Source
[0].Type
,
186 mod
->Source
[0].Form
));
187 fluid_mod_set_source2(&self
->Mods
[j
], getGenInput(mod
->Source
[1].Input
),
188 getGenFlags(mod
->Source
[1].Input
, mod
->Source
[1].Type
,
189 mod
->Source
[1].Form
));
190 fluid_mod_set_amount(&self
->Mods
[j
], mod
->Amount
);
191 fluid_mod_set_dest(&self
->Mods
[j
], getSf2Gen(mod
->Dest
));
192 self
->Mods
[j
++].next
= NULL
;
198 static void FSample_Destruct(FSample
*self
)
206 typedef struct FPreset
{
207 DERIVE_FROM_TYPE(fluid_preset_t
);
218 static char* FPreset_getName(fluid_preset_t
*preset
);
219 static int FPreset_getPreset(fluid_preset_t
*preset
);
220 static int FPreset_getBank(fluid_preset_t
*preset
);
221 static int FPreset_noteOn(fluid_preset_t
*preset
, fluid_synth_t
*synth
, int channel
, int key
, int velocity
);
223 static void FPreset_Construct(FPreset
*self
, ALsfpreset
*preset
, fluid_sfont_t
*parent
)
225 STATIC_CAST(fluid_preset_t
, self
)->data
= self
;
226 STATIC_CAST(fluid_preset_t
, self
)->sfont
= parent
;
227 STATIC_CAST(fluid_preset_t
, self
)->free
= NULL
;
228 STATIC_CAST(fluid_preset_t
, self
)->get_name
= FPreset_getName
;
229 STATIC_CAST(fluid_preset_t
, self
)->get_banknum
= FPreset_getBank
;
230 STATIC_CAST(fluid_preset_t
, self
)->get_num
= FPreset_getPreset
;
231 STATIC_CAST(fluid_preset_t
, self
)->noteon
= FPreset_noteOn
;
232 STATIC_CAST(fluid_preset_t
, self
)->notify
= NULL
;
234 memset(self
->Name
, 0, sizeof(self
->Name
));
235 self
->Preset
= preset
->Preset
;
236 self
->Bank
= preset
->Bank
;
238 self
->NumSamples
= 0;
239 self
->Samples
= calloc(1, preset
->NumSounds
* sizeof(self
->Samples
[0]));
243 self
->NumSamples
= preset
->NumSounds
;
244 for(i
= 0;i
< self
->NumSamples
;i
++)
245 FSample_Construct(&self
->Samples
[i
], preset
->Sounds
[i
]);
249 static void FPreset_Destruct(FPreset
*self
)
253 for(i
= 0;i
< self
->NumSamples
;i
++)
254 FSample_Destruct(&self
->Samples
[i
]);
256 self
->Samples
= NULL
;
257 self
->NumSamples
= 0;
260 static ALboolean
FPreset_canDelete(FPreset
*self
)
264 for(i
= 0;i
< self
->NumSamples
;i
++)
266 if(fluid_sample_refcount(STATIC_CAST(fluid_sample_t
, &self
->Samples
[i
])) != 0)
272 static char* FPreset_getName(fluid_preset_t
*preset
)
274 return ((FPreset
*)preset
->data
)->Name
;
277 static int FPreset_getPreset(fluid_preset_t
*preset
)
279 return ((FPreset
*)preset
->data
)->Preset
;
282 static int FPreset_getBank(fluid_preset_t
*preset
)
284 return ((FPreset
*)preset
->data
)->Bank
;
287 static int FPreset_noteOn(fluid_preset_t
*preset
, fluid_synth_t
*synth
, int channel
, int key
, int vel
)
289 FPreset
*self
= ((FPreset
*)preset
->data
);
292 for(i
= 0;i
< self
->NumSamples
;i
++)
294 FSample
*sample
= &self
->Samples
[i
];
295 ALfontsound
*sound
= sample
->Sound
;
296 fluid_voice_t
*voice
;
299 if(!(key
>= sound
->MinKey
&& key
<= sound
->MaxKey
&& vel
>= sound
->MinVelocity
&& vel
<= sound
->MaxVelocity
))
302 voice
= fluid_synth_alloc_voice(synth
, STATIC_CAST(fluid_sample_t
, sample
), channel
, key
, vel
);
306 fluid_voice_gen_set(voice
, GEN_MODLFOTOPITCH
, sound
->ModLfoToPitch
);
307 fluid_voice_gen_set(voice
, GEN_VIBLFOTOPITCH
, sound
->VibratoLfoToPitch
);
308 fluid_voice_gen_set(voice
, GEN_MODENVTOPITCH
, sound
->ModEnvToPitch
);
309 fluid_voice_gen_set(voice
, GEN_FILTERFC
, sound
->FilterCutoff
);
310 fluid_voice_gen_set(voice
, GEN_FILTERQ
, sound
->FilterQ
);
311 fluid_voice_gen_set(voice
, GEN_MODLFOTOFILTERFC
, sound
->ModLfoToFilterCutoff
);
312 fluid_voice_gen_set(voice
, GEN_MODENVTOFILTERFC
, sound
->ModEnvToFilterCutoff
);
313 fluid_voice_gen_set(voice
, GEN_MODLFOTOVOL
, sound
->ModLfoToVolume
);
314 fluid_voice_gen_set(voice
, GEN_CHORUSSEND
, sound
->ChorusSend
);
315 fluid_voice_gen_set(voice
, GEN_REVERBSEND
, sound
->ReverbSend
);
316 fluid_voice_gen_set(voice
, GEN_PAN
, sound
->Pan
);
317 fluid_voice_gen_set(voice
, GEN_MODLFODELAY
, sound
->ModLfo
.Delay
);
318 fluid_voice_gen_set(voice
, GEN_MODLFOFREQ
, sound
->ModLfo
.Frequency
);
319 fluid_voice_gen_set(voice
, GEN_VIBLFODELAY
, sound
->VibratoLfo
.Delay
);
320 fluid_voice_gen_set(voice
, GEN_VIBLFOFREQ
, sound
->VibratoLfo
.Frequency
);
321 fluid_voice_gen_set(voice
, GEN_MODENVDELAY
, sound
->ModEnv
.DelayTime
);
322 fluid_voice_gen_set(voice
, GEN_MODENVATTACK
, sound
->ModEnv
.AttackTime
);
323 fluid_voice_gen_set(voice
, GEN_MODENVHOLD
, sound
->ModEnv
.HoldTime
);
324 fluid_voice_gen_set(voice
, GEN_MODENVDECAY
, sound
->ModEnv
.DecayTime
);
325 fluid_voice_gen_set(voice
, GEN_MODENVSUSTAIN
, sound
->ModEnv
.SustainAttn
);
326 fluid_voice_gen_set(voice
, GEN_MODENVRELEASE
, sound
->ModEnv
.ReleaseTime
);
327 fluid_voice_gen_set(voice
, GEN_KEYTOMODENVHOLD
, sound
->ModEnv
.KeyToHoldTime
);
328 fluid_voice_gen_set(voice
, GEN_KEYTOMODENVDECAY
, sound
->ModEnv
.KeyToDecayTime
);
329 fluid_voice_gen_set(voice
, GEN_VOLENVDELAY
, sound
->VolEnv
.DelayTime
);
330 fluid_voice_gen_set(voice
, GEN_VOLENVATTACK
, sound
->VolEnv
.AttackTime
);
331 fluid_voice_gen_set(voice
, GEN_VOLENVHOLD
, sound
->VolEnv
.HoldTime
);
332 fluid_voice_gen_set(voice
, GEN_VOLENVDECAY
, sound
->VolEnv
.DecayTime
);
333 fluid_voice_gen_set(voice
, GEN_VOLENVSUSTAIN
, sound
->VolEnv
.SustainAttn
);
334 fluid_voice_gen_set(voice
, GEN_VOLENVRELEASE
, sound
->VolEnv
.ReleaseTime
);
335 fluid_voice_gen_set(voice
, GEN_KEYTOVOLENVHOLD
, sound
->VolEnv
.KeyToHoldTime
);
336 fluid_voice_gen_set(voice
, GEN_KEYTOVOLENVDECAY
, sound
->VolEnv
.KeyToDecayTime
);
337 fluid_voice_gen_set(voice
, GEN_ATTENUATION
, sound
->Attenuation
);
338 fluid_voice_gen_set(voice
, GEN_COARSETUNE
, sound
->CoarseTuning
);
339 fluid_voice_gen_set(voice
, GEN_FINETUNE
, sound
->FineTuning
);
340 fluid_voice_gen_set(voice
, GEN_SAMPLEMODE
, getSf2LoopMode(sound
->LoopMode
));
341 fluid_voice_gen_set(voice
, GEN_SCALETUNE
, sound
->TuningScale
);
342 fluid_voice_gen_set(voice
, GEN_EXCLUSIVECLASS
, sound
->ExclusiveClass
);
343 for(m
= 0;m
< sample
->NumMods
;m
++)
344 fluid_voice_add_mod(voice
, &sample
->Mods
[m
], FLUID_VOICE_OVERWRITE
);
346 fluid_synth_start_voice(synth
, voice
);
353 typedef struct FSfont
{
354 DERIVE_FROM_TYPE(fluid_sfont_t
);
364 static int FSfont_free(fluid_sfont_t
*sfont
);
365 static char* FSfont_getName(fluid_sfont_t
*sfont
);
366 static fluid_preset_t
* FSfont_getPreset(fluid_sfont_t
*sfont
, unsigned int bank
, unsigned int prenum
);
367 static void FSfont_iterStart(fluid_sfont_t
*sfont
);
368 static int FSfont_iterNext(fluid_sfont_t
*sfont
, fluid_preset_t
*preset
);
370 static void FSfont_Construct(FSfont
*self
, ALsoundfont
*sfont
)
372 STATIC_CAST(fluid_sfont_t
, self
)->data
= self
;
373 STATIC_CAST(fluid_sfont_t
, self
)->id
= FLUID_FAILED
;
374 STATIC_CAST(fluid_sfont_t
, self
)->free
= FSfont_free
;
375 STATIC_CAST(fluid_sfont_t
, self
)->get_name
= FSfont_getName
;
376 STATIC_CAST(fluid_sfont_t
, self
)->get_preset
= FSfont_getPreset
;
377 STATIC_CAST(fluid_sfont_t
, self
)->iteration_start
= FSfont_iterStart
;
378 STATIC_CAST(fluid_sfont_t
, self
)->iteration_next
= FSfont_iterNext
;
380 memset(self
->Name
, 0, sizeof(self
->Name
));
381 self
->CurrentPos
= 0;
382 self
->NumPresets
= 0;
383 self
->Presets
= calloc(1, sfont
->NumPresets
* sizeof(self
->Presets
[0]));
387 self
->NumPresets
= sfont
->NumPresets
;
388 for(i
= 0;i
< self
->NumPresets
;i
++)
389 FPreset_Construct(&self
->Presets
[i
], sfont
->Presets
[i
], STATIC_CAST(fluid_sfont_t
, self
));
393 static void FSfont_Destruct(FSfont
*self
)
397 for(i
= 0;i
< self
->NumPresets
;i
++)
398 FPreset_Destruct(&self
->Presets
[i
]);
400 self
->Presets
= NULL
;
401 self
->NumPresets
= 0;
402 self
->CurrentPos
= 0;
405 static int FSfont_free(fluid_sfont_t
*sfont
)
407 FSfont
*self
= STATIC_UPCAST(FSfont
, fluid_sfont_t
, sfont
);
410 for(i
= 0;i
< self
->NumPresets
;i
++)
412 if(!FPreset_canDelete(&self
->Presets
[i
]))
416 FSfont_Destruct(self
);
421 static char* FSfont_getName(fluid_sfont_t
*sfont
)
423 return STATIC_UPCAST(FSfont
, fluid_sfont_t
, sfont
)->Name
;
426 static fluid_preset_t
*FSfont_getPreset(fluid_sfont_t
*sfont
, unsigned int bank
, unsigned int prenum
)
428 FSfont
*self
= STATIC_UPCAST(FSfont
, fluid_sfont_t
, sfont
);
431 for(i
= 0;i
< self
->NumPresets
;i
++)
433 FPreset
*preset
= &self
->Presets
[i
];
434 if(preset
->Bank
== (int)bank
&& preset
->Preset
== (int)prenum
)
435 return STATIC_CAST(fluid_preset_t
, preset
);
441 static void FSfont_iterStart(fluid_sfont_t
*sfont
)
443 STATIC_UPCAST(FSfont
, fluid_sfont_t
, sfont
)->CurrentPos
= 0;
446 static int FSfont_iterNext(fluid_sfont_t
*sfont
, fluid_preset_t
*preset
)
448 FSfont
*self
= STATIC_UPCAST(FSfont
, fluid_sfont_t
, sfont
);
449 if(self
->CurrentPos
>= self
->NumPresets
)
451 *preset
= *STATIC_CAST(fluid_preset_t
, &self
->Presets
[self
->CurrentPos
++]);
457 typedef struct FSynth
{
458 DERIVE_FROM_TYPE(MidiSynth
);
459 DERIVE_FROM_TYPE(fluid_sfloader_t
);
461 fluid_settings_t
*Settings
;
462 fluid_synth_t
*Synth
;
466 ALboolean ForceGM2BankSelect
;
470 static void FSynth_Construct(FSynth
*self
, ALCdevice
*device
);
471 static void FSynth_Destruct(FSynth
*self
);
472 static ALboolean
FSynth_init(FSynth
*self
, ALCdevice
*device
);
473 static ALenum
FSynth_selectSoundfonts(FSynth
*self
, ALCcontext
*context
, ALsizei count
, const ALuint
*ids
);
474 static void FSynth_setGain(FSynth
*self
, ALfloat gain
);
475 static void FSynth_stop(FSynth
*self
);
476 static void FSynth_reset(FSynth
*self
);
477 static void FSynth_update(FSynth
*self
, ALCdevice
*device
);
478 static void FSynth_processQueue(FSynth
*self
, ALuint64 time
);
479 static void FSynth_process(FSynth
*self
, ALuint SamplesToDo
, ALfloat (*restrict DryBuffer
)[BUFFERSIZE
]);
480 DECLARE_DEFAULT_ALLOCATORS(FSynth
)
481 DEFINE_MIDISYNTH_VTABLE(FSynth
);
483 static fluid_sfont_t
*FSynth_loadSfont(fluid_sfloader_t
*loader
, const char *filename
);
486 static void FSynth_Construct(FSynth
*self
, ALCdevice
*device
)
488 MidiSynth_Construct(STATIC_CAST(MidiSynth
, self
), device
);
489 SET_VTABLE2(FSynth
, MidiSynth
, self
);
491 STATIC_CAST(fluid_sfloader_t
, self
)->data
= self
;
492 STATIC_CAST(fluid_sfloader_t
, self
)->free
= NULL
;
493 STATIC_CAST(fluid_sfloader_t
, self
)->load
= FSynth_loadSfont
;
495 self
->Settings
= NULL
;
497 self
->FontIDs
= NULL
;
498 self
->NumFontIDs
= 0;
499 self
->ForceGM2BankSelect
= AL_FALSE
;
500 self
->GainScale
= 0.2f
;
503 static void FSynth_Destruct(FSynth
*self
)
507 for(i
= 0;i
< self
->NumFontIDs
;i
++)
508 fluid_synth_sfunload(self
->Synth
, self
->FontIDs
[i
], 0);
510 self
->FontIDs
= NULL
;
511 self
->NumFontIDs
= 0;
513 if(self
->Synth
!= NULL
)
514 delete_fluid_synth(self
->Synth
);
517 if(self
->Settings
!= NULL
)
518 delete_fluid_settings(self
->Settings
);
519 self
->Settings
= NULL
;
521 MidiSynth_Destruct(STATIC_CAST(MidiSynth
, self
));
524 static ALboolean
FSynth_init(FSynth
*self
, ALCdevice
*device
)
528 if(ConfigValueFloat("midi", "volume", &vol
))
532 ERR("MIDI volume %f clamped to 0\n", vol
);
535 self
->GainScale
= powf(10.0f
, vol
/ 20.0f
);
538 self
->Settings
= new_fluid_settings();
541 ERR("Failed to create FluidSettings\n");
545 fluid_settings_setint(self
->Settings
, "synth.polyphony", 256);
546 fluid_settings_setnum(self
->Settings
, "synth.gain", self
->GainScale
);
547 fluid_settings_setnum(self
->Settings
, "synth.sample-rate", device
->Frequency
);
549 self
->Synth
= new_fluid_synth(self
->Settings
);
552 ERR("Failed to create FluidSynth\n");
556 fluid_synth_add_sfloader(self
->Synth
, STATIC_CAST(fluid_sfloader_t
, self
));
562 static fluid_sfont_t
*FSynth_loadSfont(fluid_sfloader_t
*loader
, const char *filename
)
564 FSynth
*self
= STATIC_UPCAST(FSynth
, fluid_sfloader_t
, loader
);
568 if(!filename
|| sscanf(filename
, "_al_internal %d", &idx
) != 1)
570 if(idx
< 0 || idx
>= STATIC_CAST(MidiSynth
, self
)->NumSoundfonts
)
572 ERR("Received invalid soundfont index %d (max: %d)\n", idx
, STATIC_CAST(MidiSynth
, self
)->NumSoundfonts
);
576 sfont
= calloc(1, sizeof(sfont
[0]));
577 if(!sfont
) return NULL
;
579 FSfont_Construct(sfont
, STATIC_CAST(MidiSynth
, self
)->Soundfonts
[idx
]);
580 return STATIC_CAST(fluid_sfont_t
, sfont
);
583 static ALenum
FSynth_selectSoundfonts(FSynth
*self
, ALCcontext
*context
, ALsizei count
, const ALuint
*ids
)
589 ret
= MidiSynth_selectSoundfonts(STATIC_CAST(MidiSynth
, self
), context
, count
, ids
);
590 if(ret
!= AL_NO_ERROR
) return ret
;
592 ALCdevice_Lock(context
->Device
);
593 for(i
= 0;i
< 16;i
++)
594 fluid_synth_all_sounds_off(self
->Synth
, i
);
595 ALCdevice_Unlock(context
->Device
);
597 fontid
= malloc(count
* sizeof(fontid
[0]));
600 for(i
= 0;i
< STATIC_CAST(MidiSynth
, self
)->NumSoundfonts
;i
++)
603 snprintf(name
, sizeof(name
), "_al_internal %d", i
);
605 fontid
[i
] = fluid_synth_sfload(self
->Synth
, name
, 0);
606 if(fontid
[i
] == FLUID_FAILED
)
607 ERR("Failed to load selected soundfont %d\n", i
);
610 fontid
= ExchangePtr((XchgPtr
*)&self
->FontIDs
, fontid
);
611 count
= ExchangeInt(&self
->NumFontIDs
, count
);
615 ERR("Failed to allocate space for %d font IDs!\n", count
);
616 fontid
= ExchangePtr((XchgPtr
*)&self
->FontIDs
, NULL
);
617 count
= ExchangeInt(&self
->NumFontIDs
, 0);
620 for(i
= 0;i
< count
;i
++)
621 fluid_synth_sfunload(self
->Synth
, fontid
[i
], 0);
628 static void FSynth_setGain(FSynth
*self
, ALfloat gain
)
630 fluid_settings_setnum(self
->Settings
, "synth.gain", self
->GainScale
* gain
);
631 fluid_synth_set_gain(self
->Synth
, self
->GainScale
* gain
);
632 MidiSynth_setGain(STATIC_CAST(MidiSynth
, self
), gain
);
636 static void FSynth_stop(FSynth
*self
)
638 MidiSynth
*synth
= STATIC_CAST(MidiSynth
, self
);
642 /* Make sure all pending events are processed. */
643 curtime
= MidiSynth_getTime(synth
);
644 FSynth_processQueue(self
, curtime
);
647 for(chan
= 0;chan
< 16;chan
++)
648 fluid_synth_cc(self
->Synth
, chan
, CTRL_ALLNOTESOFF
, 0);
650 MidiSynth_stop(STATIC_CAST(MidiSynth
, self
));
653 static void FSynth_reset(FSynth
*self
)
655 /* Reset to power-up status. */
656 fluid_synth_system_reset(self
->Synth
);
658 MidiSynth_reset(STATIC_CAST(MidiSynth
, self
));
662 static void FSynth_update(FSynth
*self
, ALCdevice
*device
)
664 fluid_settings_setnum(self
->Settings
, "synth.sample-rate", device
->Frequency
);
665 fluid_synth_set_sample_rate(self
->Synth
, device
->Frequency
);
666 MidiSynth_update(STATIC_CAST(MidiSynth
, self
), device
);
670 static void FSynth_processQueue(FSynth
*self
, ALuint64 time
)
672 EvtQueue
*queue
= &STATIC_CAST(MidiSynth
, self
)->EventQueue
;
674 while(queue
->pos
< queue
->size
&& queue
->events
[queue
->pos
].time
<= time
)
676 const MidiEvent
*evt
= &queue
->events
[queue
->pos
];
678 if(evt
->event
== SYSEX_EVENT
)
680 static const ALbyte gm2_on
[] = { 0x7E, 0x7F, 0x09, 0x03 };
681 static const ALbyte gm2_off
[] = { 0x7E, 0x7F, 0x09, 0x02 };
684 fluid_synth_sysex(self
->Synth
, evt
->param
.sysex
.data
, evt
->param
.sysex
.size
, NULL
, NULL
, &handled
, 0);
685 if(!handled
&& evt
->param
.sysex
.size
>= (ALsizei
)sizeof(gm2_on
))
687 if(memcmp(evt
->param
.sysex
.data
, gm2_on
, sizeof(gm2_on
)) == 0)
688 self
->ForceGM2BankSelect
= AL_TRUE
;
689 else if(memcmp(evt
->param
.sysex
.data
, gm2_off
, sizeof(gm2_off
)) == 0)
690 self
->ForceGM2BankSelect
= AL_FALSE
;
693 else switch((evt
->event
&0xF0))
695 case AL_NOTEOFF_SOFT
:
696 fluid_synth_noteoff(self
->Synth
, (evt
->event
&0x0F), evt
->param
.val
[0]);
699 fluid_synth_noteon(self
->Synth
, (evt
->event
&0x0F), evt
->param
.val
[0], evt
->param
.val
[1]);
701 case AL_KEYPRESSURE_SOFT
:
704 case AL_CONTROLLERCHANGE_SOFT
:
705 if(self
->ForceGM2BankSelect
)
707 int chan
= (evt
->event
&0x0F);
708 if(evt
->param
.val
[0] == CTRL_BANKSELECT_MSB
)
710 if(evt
->param
.val
[1] == 120 && (chan
== 9 || chan
== 10))
711 fluid_synth_set_channel_type(self
->Synth
, chan
, CHANNEL_TYPE_DRUM
);
712 else if(evt
->param
.val
[1] == 121)
713 fluid_synth_set_channel_type(self
->Synth
, chan
, CHANNEL_TYPE_MELODIC
);
716 if(evt
->param
.val
[0] == CTRL_BANKSELECT_LSB
)
718 fluid_synth_bank_select(self
->Synth
, chan
, evt
->param
.val
[1]);
722 fluid_synth_cc(self
->Synth
, (evt
->event
&0x0F), evt
->param
.val
[0], evt
->param
.val
[1]);
724 case AL_PROGRAMCHANGE_SOFT
:
725 fluid_synth_program_change(self
->Synth
, (evt
->event
&0x0F), evt
->param
.val
[0]);
728 case AL_CHANNELPRESSURE_SOFT
:
729 fluid_synth_channel_pressure(self
->Synth
, (evt
->event
&0x0F), evt
->param
.val
[0]);
732 case AL_PITCHBEND_SOFT
:
733 fluid_synth_pitch_bend(self
->Synth
, (evt
->event
&0x0F), (evt
->param
.val
[0]&0x7F) |
734 ((evt
->param
.val
[1]&0x7F)<<7));
742 static void FSynth_process(FSynth
*self
, ALuint SamplesToDo
, ALfloat (*restrict DryBuffer
)[BUFFERSIZE
])
744 MidiSynth
*synth
= STATIC_CAST(MidiSynth
, self
);
745 ALenum state
= synth
->State
;
749 if(state
== AL_INITIAL
)
751 if(state
!= AL_PLAYING
)
753 fluid_synth_write_float(self
->Synth
, SamplesToDo
, DryBuffer
[FrontLeft
], 0, 1,
754 DryBuffer
[FrontRight
], 0, 1);
758 curtime
= MidiSynth_getTime(synth
);
759 while(total
< SamplesToDo
)
764 time
= MidiSynth_getNextEvtTime(synth
);
765 diff
= maxu64(time
, curtime
) - curtime
;
766 if(diff
>= MIDI_CLOCK_RES
|| time
== UINT64_MAX
)
768 /* If there's no pending event, or if it's more than 1 second
769 * away, do as many samples as we can. */
774 /* Figure out how many samples until the next event. */
775 tonext
= (ALint
)((diff
*synth
->SampleRate
+ (MIDI_CLOCK_RES
-1)) / MIDI_CLOCK_RES
);
781 ALuint todo
= minu(tonext
, SamplesToDo
-total
);
782 fluid_synth_write_float(self
->Synth
, todo
, DryBuffer
[FrontLeft
], total
, 1,
783 DryBuffer
[FrontRight
], total
, 1);
787 if(total
< SamplesToDo
&& tonext
<= 0)
788 FSynth_processQueue(self
, time
);
791 synth
->SamplesDone
+= SamplesToDo
;
792 synth
->ClockBase
+= (synth
->SamplesDone
/synth
->SampleRate
) * MIDI_CLOCK_RES
;
793 synth
->SamplesDone
%= synth
->SampleRate
;
797 MidiSynth
*FSynth_create(ALCdevice
*device
)
799 FSynth
*synth
= FSynth_New(sizeof(*synth
));
802 ERR("Failed to allocate FSynth\n");
805 memset(synth
, 0, sizeof(*synth
));
806 FSynth_Construct(synth
, device
);
808 if(FSynth_init(synth
, device
) == AL_FALSE
)
810 DELETE_OBJ(STATIC_CAST(MidiSynth
, synth
));
814 return STATIC_CAST(MidiSynth
, synth
);
819 MidiSynth
*FSynth_create(ALCdevice
* UNUSED(device
))