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 getModInput(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 getModFlags(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
getModDest(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
*4, sizeof(fluid_mod_t
[4]));
179 for(i
= j
= 0;i
< sound
->ModulatorMap
.size
;i
++)
181 ALsfmodulator
*mod
= sound
->ModulatorMap
.array
[i
].value
;
182 for(k
= 0;k
< 4;k
++,mod
++)
184 if(mod
->Dest
== AL_NONE
)
186 fluid_mod_set_source1(&self
->Mods
[j
], getModInput(mod
->Source
[0].Input
),
187 getModFlags(mod
->Source
[0].Input
, mod
->Source
[0].Type
,
188 mod
->Source
[0].Form
));
189 fluid_mod_set_source2(&self
->Mods
[j
], getModInput(mod
->Source
[1].Input
),
190 getModFlags(mod
->Source
[1].Input
, mod
->Source
[1].Type
,
191 mod
->Source
[1].Form
));
192 fluid_mod_set_amount(&self
->Mods
[j
], mod
->Amount
);
193 fluid_mod_set_dest(&self
->Mods
[j
], getModDest(mod
->Dest
));
194 self
->Mods
[j
++].next
= NULL
;
201 static void FSample_Destruct(FSample
*self
)
209 typedef struct FPreset
{
210 DERIVE_FROM_TYPE(fluid_preset_t
);
221 static char* FPreset_getName(fluid_preset_t
*preset
);
222 static int FPreset_getPreset(fluid_preset_t
*preset
);
223 static int FPreset_getBank(fluid_preset_t
*preset
);
224 static int FPreset_noteOn(fluid_preset_t
*preset
, fluid_synth_t
*synth
, int channel
, int key
, int velocity
);
226 static void FPreset_Construct(FPreset
*self
, ALsfpreset
*preset
, fluid_sfont_t
*parent
)
228 STATIC_CAST(fluid_preset_t
, self
)->data
= self
;
229 STATIC_CAST(fluid_preset_t
, self
)->sfont
= parent
;
230 STATIC_CAST(fluid_preset_t
, self
)->free
= NULL
;
231 STATIC_CAST(fluid_preset_t
, self
)->get_name
= FPreset_getName
;
232 STATIC_CAST(fluid_preset_t
, self
)->get_banknum
= FPreset_getBank
;
233 STATIC_CAST(fluid_preset_t
, self
)->get_num
= FPreset_getPreset
;
234 STATIC_CAST(fluid_preset_t
, self
)->noteon
= FPreset_noteOn
;
235 STATIC_CAST(fluid_preset_t
, self
)->notify
= NULL
;
237 memset(self
->Name
, 0, sizeof(self
->Name
));
238 self
->Preset
= preset
->Preset
;
239 self
->Bank
= preset
->Bank
;
241 self
->NumSamples
= 0;
242 self
->Samples
= calloc(1, preset
->NumSounds
* sizeof(self
->Samples
[0]));
246 self
->NumSamples
= preset
->NumSounds
;
247 for(i
= 0;i
< self
->NumSamples
;i
++)
248 FSample_Construct(&self
->Samples
[i
], preset
->Sounds
[i
]);
252 static void FPreset_Destruct(FPreset
*self
)
256 for(i
= 0;i
< self
->NumSamples
;i
++)
257 FSample_Destruct(&self
->Samples
[i
]);
259 self
->Samples
= NULL
;
260 self
->NumSamples
= 0;
263 static ALboolean
FPreset_canDelete(FPreset
*self
)
266 for(i
= 0;i
< self
->NumSamples
;i
++)
268 if(fluid_sample_refcount(STATIC_CAST(fluid_sample_t
, &self
->Samples
[i
])) != 0)
274 static char* FPreset_getName(fluid_preset_t
*preset
)
276 return ((FPreset
*)preset
->data
)->Name
;
279 static int FPreset_getPreset(fluid_preset_t
*preset
)
281 return ((FPreset
*)preset
->data
)->Preset
;
284 static int FPreset_getBank(fluid_preset_t
*preset
)
286 return ((FPreset
*)preset
->data
)->Bank
;
289 static int FPreset_noteOn(fluid_preset_t
*preset
, fluid_synth_t
*synth
, int channel
, int key
, int vel
)
291 FPreset
*self
= ((FPreset
*)preset
->data
);
294 for(i
= 0;i
< self
->NumSamples
;i
++)
296 FSample
*sample
= &self
->Samples
[i
];
297 ALfontsound
*sound
= sample
->Sound
;
298 fluid_voice_t
*voice
;
301 if(!(key
>= sound
->MinKey
&& key
<= sound
->MaxKey
&& vel
>= sound
->MinVelocity
&& vel
<= sound
->MaxVelocity
))
304 voice
= fluid_synth_alloc_voice(synth
, STATIC_CAST(fluid_sample_t
, sample
), channel
, key
, vel
);
305 if(voice
== NULL
) return FLUID_FAILED
;
307 fluid_voice_gen_set(voice
, GEN_MODLFOTOPITCH
, sound
->ModLfoToPitch
);
308 fluid_voice_gen_set(voice
, GEN_VIBLFOTOPITCH
, sound
->VibratoLfoToPitch
);
309 fluid_voice_gen_set(voice
, GEN_MODENVTOPITCH
, sound
->ModEnvToPitch
);
310 fluid_voice_gen_set(voice
, GEN_FILTERFC
, sound
->FilterCutoff
);
311 fluid_voice_gen_set(voice
, GEN_FILTERQ
, sound
->FilterQ
);
312 fluid_voice_gen_set(voice
, GEN_MODLFOTOFILTERFC
, sound
->ModLfoToFilterCutoff
);
313 fluid_voice_gen_set(voice
, GEN_MODENVTOFILTERFC
, sound
->ModEnvToFilterCutoff
);
314 fluid_voice_gen_set(voice
, GEN_MODLFOTOVOL
, sound
->ModLfoToVolume
);
315 fluid_voice_gen_set(voice
, GEN_CHORUSSEND
, sound
->ChorusSend
);
316 fluid_voice_gen_set(voice
, GEN_REVERBSEND
, sound
->ReverbSend
);
317 fluid_voice_gen_set(voice
, GEN_PAN
, sound
->Pan
);
318 fluid_voice_gen_set(voice
, GEN_MODLFODELAY
, sound
->ModLfo
.Delay
);
319 fluid_voice_gen_set(voice
, GEN_MODLFOFREQ
, sound
->ModLfo
.Frequency
);
320 fluid_voice_gen_set(voice
, GEN_VIBLFODELAY
, sound
->VibratoLfo
.Delay
);
321 fluid_voice_gen_set(voice
, GEN_VIBLFOFREQ
, sound
->VibratoLfo
.Frequency
);
322 fluid_voice_gen_set(voice
, GEN_MODENVDELAY
, sound
->ModEnv
.DelayTime
);
323 fluid_voice_gen_set(voice
, GEN_MODENVATTACK
, sound
->ModEnv
.AttackTime
);
324 fluid_voice_gen_set(voice
, GEN_MODENVHOLD
, sound
->ModEnv
.HoldTime
);
325 fluid_voice_gen_set(voice
, GEN_MODENVDECAY
, sound
->ModEnv
.DecayTime
);
326 fluid_voice_gen_set(voice
, GEN_MODENVSUSTAIN
, sound
->ModEnv
.SustainAttn
);
327 fluid_voice_gen_set(voice
, GEN_MODENVRELEASE
, sound
->ModEnv
.ReleaseTime
);
328 fluid_voice_gen_set(voice
, GEN_KEYTOMODENVHOLD
, sound
->ModEnv
.KeyToHoldTime
);
329 fluid_voice_gen_set(voice
, GEN_KEYTOMODENVDECAY
, sound
->ModEnv
.KeyToDecayTime
);
330 fluid_voice_gen_set(voice
, GEN_VOLENVDELAY
, sound
->VolEnv
.DelayTime
);
331 fluid_voice_gen_set(voice
, GEN_VOLENVATTACK
, sound
->VolEnv
.AttackTime
);
332 fluid_voice_gen_set(voice
, GEN_VOLENVHOLD
, sound
->VolEnv
.HoldTime
);
333 fluid_voice_gen_set(voice
, GEN_VOLENVDECAY
, sound
->VolEnv
.DecayTime
);
334 fluid_voice_gen_set(voice
, GEN_VOLENVSUSTAIN
, sound
->VolEnv
.SustainAttn
);
335 fluid_voice_gen_set(voice
, GEN_VOLENVRELEASE
, sound
->VolEnv
.ReleaseTime
);
336 fluid_voice_gen_set(voice
, GEN_KEYTOVOLENVHOLD
, sound
->VolEnv
.KeyToHoldTime
);
337 fluid_voice_gen_set(voice
, GEN_KEYTOVOLENVDECAY
, sound
->VolEnv
.KeyToDecayTime
);
338 fluid_voice_gen_set(voice
, GEN_ATTENUATION
, sound
->Attenuation
);
339 fluid_voice_gen_set(voice
, GEN_COARSETUNE
, sound
->CoarseTuning
);
340 fluid_voice_gen_set(voice
, GEN_FINETUNE
, sound
->FineTuning
);
341 fluid_voice_gen_set(voice
, GEN_SAMPLEMODE
, getSf2LoopMode(sound
->LoopMode
));
342 fluid_voice_gen_set(voice
, GEN_SCALETUNE
, sound
->TuningScale
);
343 fluid_voice_gen_set(voice
, GEN_EXCLUSIVECLASS
, sound
->ExclusiveClass
);
344 for(m
= 0;m
< sample
->NumMods
;m
++)
345 fluid_voice_add_mod(voice
, &sample
->Mods
[m
], FLUID_VOICE_OVERWRITE
);
347 fluid_synth_start_voice(synth
, voice
);
354 typedef struct FSfont
{
355 DERIVE_FROM_TYPE(fluid_sfont_t
);
365 static int FSfont_free(fluid_sfont_t
*sfont
);
366 static char* FSfont_getName(fluid_sfont_t
*sfont
);
367 static fluid_preset_t
* FSfont_getPreset(fluid_sfont_t
*sfont
, unsigned int bank
, unsigned int prenum
);
368 static void FSfont_iterStart(fluid_sfont_t
*sfont
);
369 static int FSfont_iterNext(fluid_sfont_t
*sfont
, fluid_preset_t
*preset
);
371 static void FSfont_Construct(FSfont
*self
, ALsoundfont
*sfont
)
373 STATIC_CAST(fluid_sfont_t
, self
)->data
= self
;
374 STATIC_CAST(fluid_sfont_t
, self
)->id
= FLUID_FAILED
;
375 STATIC_CAST(fluid_sfont_t
, self
)->free
= FSfont_free
;
376 STATIC_CAST(fluid_sfont_t
, self
)->get_name
= FSfont_getName
;
377 STATIC_CAST(fluid_sfont_t
, self
)->get_preset
= FSfont_getPreset
;
378 STATIC_CAST(fluid_sfont_t
, self
)->iteration_start
= FSfont_iterStart
;
379 STATIC_CAST(fluid_sfont_t
, self
)->iteration_next
= FSfont_iterNext
;
381 memset(self
->Name
, 0, sizeof(self
->Name
));
382 self
->CurrentPos
= 0;
383 self
->NumPresets
= 0;
384 self
->Presets
= calloc(1, sfont
->NumPresets
* sizeof(self
->Presets
[0]));
388 self
->NumPresets
= sfont
->NumPresets
;
389 for(i
= 0;i
< self
->NumPresets
;i
++)
390 FPreset_Construct(&self
->Presets
[i
], sfont
->Presets
[i
], STATIC_CAST(fluid_sfont_t
, self
));
394 static void FSfont_Destruct(FSfont
*self
)
398 for(i
= 0;i
< self
->NumPresets
;i
++)
399 FPreset_Destruct(&self
->Presets
[i
]);
401 self
->Presets
= NULL
;
402 self
->NumPresets
= 0;
403 self
->CurrentPos
= 0;
406 static int FSfont_free(fluid_sfont_t
*sfont
)
408 FSfont
*self
= STATIC_UPCAST(FSfont
, fluid_sfont_t
, sfont
);
411 for(i
= 0;i
< self
->NumPresets
;i
++)
413 if(!FPreset_canDelete(&self
->Presets
[i
]))
417 FSfont_Destruct(self
);
422 static char* FSfont_getName(fluid_sfont_t
*sfont
)
424 return STATIC_UPCAST(FSfont
, fluid_sfont_t
, sfont
)->Name
;
427 static fluid_preset_t
*FSfont_getPreset(fluid_sfont_t
*sfont
, unsigned int bank
, unsigned int prenum
)
429 FSfont
*self
= STATIC_UPCAST(FSfont
, fluid_sfont_t
, sfont
);
432 for(i
= 0;i
< self
->NumPresets
;i
++)
434 FPreset
*preset
= &self
->Presets
[i
];
435 if(preset
->Bank
== (int)bank
&& preset
->Preset
== (int)prenum
)
436 return STATIC_CAST(fluid_preset_t
, preset
);
442 static void FSfont_iterStart(fluid_sfont_t
*sfont
)
444 STATIC_UPCAST(FSfont
, fluid_sfont_t
, sfont
)->CurrentPos
= 0;
447 static int FSfont_iterNext(fluid_sfont_t
*sfont
, fluid_preset_t
*preset
)
449 FSfont
*self
= STATIC_UPCAST(FSfont
, fluid_sfont_t
, sfont
);
450 if(self
->CurrentPos
>= self
->NumPresets
)
452 *preset
= *STATIC_CAST(fluid_preset_t
, &self
->Presets
[self
->CurrentPos
++]);
458 typedef struct FSynth
{
459 DERIVE_FROM_TYPE(MidiSynth
);
460 DERIVE_FROM_TYPE(fluid_sfloader_t
);
462 fluid_settings_t
*Settings
;
463 fluid_synth_t
*Synth
;
467 ALboolean ForceGM2BankSelect
;
471 static void FSynth_Construct(FSynth
*self
, ALCdevice
*device
);
472 static void FSynth_Destruct(FSynth
*self
);
473 static ALboolean
FSynth_init(FSynth
*self
, ALCdevice
*device
);
474 static ALenum
FSynth_selectSoundfonts(FSynth
*self
, ALCcontext
*context
, ALsizei count
, const ALuint
*ids
);
475 static void FSynth_setGain(FSynth
*self
, ALfloat gain
);
476 static void FSynth_stop(FSynth
*self
);
477 static void FSynth_reset(FSynth
*self
);
478 static void FSynth_update(FSynth
*self
, ALCdevice
*device
);
479 static void FSynth_processQueue(FSynth
*self
, ALuint64 time
);
480 static void FSynth_process(FSynth
*self
, ALuint SamplesToDo
, ALfloat (*restrict DryBuffer
)[BUFFERSIZE
]);
481 DECLARE_DEFAULT_ALLOCATORS(FSynth
)
482 DEFINE_MIDISYNTH_VTABLE(FSynth
);
484 static fluid_sfont_t
*FSynth_loadSfont(fluid_sfloader_t
*loader
, const char *filename
);
487 static void FSynth_Construct(FSynth
*self
, ALCdevice
*device
)
489 MidiSynth_Construct(STATIC_CAST(MidiSynth
, self
), device
);
490 SET_VTABLE2(FSynth
, MidiSynth
, self
);
492 STATIC_CAST(fluid_sfloader_t
, self
)->data
= self
;
493 STATIC_CAST(fluid_sfloader_t
, self
)->free
= NULL
;
494 STATIC_CAST(fluid_sfloader_t
, self
)->load
= FSynth_loadSfont
;
496 self
->Settings
= NULL
;
498 self
->FontIDs
= NULL
;
499 self
->NumFontIDs
= 0;
500 self
->ForceGM2BankSelect
= AL_FALSE
;
501 self
->GainScale
= 0.2f
;
504 static void FSynth_Destruct(FSynth
*self
)
508 for(i
= 0;i
< self
->NumFontIDs
;i
++)
509 fluid_synth_sfunload(self
->Synth
, self
->FontIDs
[i
], 0);
511 self
->FontIDs
= NULL
;
512 self
->NumFontIDs
= 0;
514 if(self
->Synth
!= NULL
)
515 delete_fluid_synth(self
->Synth
);
518 if(self
->Settings
!= NULL
)
519 delete_fluid_settings(self
->Settings
);
520 self
->Settings
= NULL
;
522 MidiSynth_Destruct(STATIC_CAST(MidiSynth
, self
));
525 static ALboolean
FSynth_init(FSynth
*self
, ALCdevice
*device
)
529 if(ConfigValueFloat("midi", "volume", &vol
))
533 ERR("MIDI volume %f clamped to 0\n", vol
);
536 self
->GainScale
= powf(10.0f
, vol
/ 20.0f
);
539 self
->Settings
= new_fluid_settings();
542 ERR("Failed to create FluidSettings\n");
546 fluid_settings_setint(self
->Settings
, "synth.polyphony", 256);
547 fluid_settings_setnum(self
->Settings
, "synth.gain", self
->GainScale
);
548 fluid_settings_setnum(self
->Settings
, "synth.sample-rate", device
->Frequency
);
550 self
->Synth
= new_fluid_synth(self
->Settings
);
553 ERR("Failed to create FluidSynth\n");
557 fluid_synth_add_sfloader(self
->Synth
, STATIC_CAST(fluid_sfloader_t
, self
));
563 static fluid_sfont_t
*FSynth_loadSfont(fluid_sfloader_t
*loader
, const char *filename
)
565 FSynth
*self
= STATIC_UPCAST(FSynth
, fluid_sfloader_t
, loader
);
569 if(!filename
|| sscanf(filename
, "_al_internal %d", &idx
) != 1)
571 if(idx
< 0 || idx
>= STATIC_CAST(MidiSynth
, self
)->NumSoundfonts
)
573 ERR("Received invalid soundfont index %d (max: %d)\n", idx
, STATIC_CAST(MidiSynth
, self
)->NumSoundfonts
);
577 sfont
= calloc(1, sizeof(sfont
[0]));
578 if(!sfont
) return NULL
;
580 FSfont_Construct(sfont
, STATIC_CAST(MidiSynth
, self
)->Soundfonts
[idx
]);
581 return STATIC_CAST(fluid_sfont_t
, sfont
);
584 static ALenum
FSynth_selectSoundfonts(FSynth
*self
, ALCcontext
*context
, ALsizei count
, const ALuint
*ids
)
590 ret
= MidiSynth_selectSoundfonts(STATIC_CAST(MidiSynth
, self
), context
, count
, ids
);
591 if(ret
!= AL_NO_ERROR
) return ret
;
593 ALCdevice_Lock(context
->Device
);
594 for(i
= 0;i
< 16;i
++)
595 fluid_synth_all_sounds_off(self
->Synth
, i
);
596 ALCdevice_Unlock(context
->Device
);
598 fontid
= malloc(count
* sizeof(fontid
[0]));
601 for(i
= 0;i
< STATIC_CAST(MidiSynth
, self
)->NumSoundfonts
;i
++)
604 snprintf(name
, sizeof(name
), "_al_internal %d", i
);
606 fontid
[i
] = fluid_synth_sfload(self
->Synth
, name
, 0);
607 if(fontid
[i
] == FLUID_FAILED
)
608 ERR("Failed to load selected soundfont %d\n", i
);
611 fontid
= ExchangePtr((XchgPtr
*)&self
->FontIDs
, fontid
);
612 count
= ExchangeInt(&self
->NumFontIDs
, count
);
616 ERR("Failed to allocate space for %d font IDs!\n", count
);
617 fontid
= ExchangePtr((XchgPtr
*)&self
->FontIDs
, NULL
);
618 count
= ExchangeInt(&self
->NumFontIDs
, 0);
621 for(i
= 0;i
< count
;i
++)
622 fluid_synth_sfunload(self
->Synth
, fontid
[i
], 0);
629 static void FSynth_setGain(FSynth
*self
, ALfloat gain
)
631 fluid_settings_setnum(self
->Settings
, "synth.gain", self
->GainScale
* gain
);
632 fluid_synth_set_gain(self
->Synth
, self
->GainScale
* gain
);
633 MidiSynth_setGain(STATIC_CAST(MidiSynth
, self
), gain
);
637 static void FSynth_stop(FSynth
*self
)
639 MidiSynth
*synth
= STATIC_CAST(MidiSynth
, self
);
643 /* Make sure all pending events are processed. */
644 curtime
= MidiSynth_getTime(synth
);
645 FSynth_processQueue(self
, curtime
);
648 for(chan
= 0;chan
< 16;chan
++)
649 fluid_synth_cc(self
->Synth
, chan
, CTRL_ALLNOTESOFF
, 0);
651 MidiSynth_stop(STATIC_CAST(MidiSynth
, self
));
654 static void FSynth_reset(FSynth
*self
)
656 /* Reset to power-up status. */
657 fluid_synth_system_reset(self
->Synth
);
659 MidiSynth_reset(STATIC_CAST(MidiSynth
, self
));
663 static void FSynth_update(FSynth
*self
, ALCdevice
*device
)
665 fluid_settings_setnum(self
->Settings
, "synth.sample-rate", device
->Frequency
);
666 fluid_synth_set_sample_rate(self
->Synth
, device
->Frequency
);
667 MidiSynth_update(STATIC_CAST(MidiSynth
, self
), device
);
671 static void FSynth_processQueue(FSynth
*self
, ALuint64 time
)
673 EvtQueue
*queue
= &STATIC_CAST(MidiSynth
, self
)->EventQueue
;
675 while(queue
->pos
< queue
->size
&& queue
->events
[queue
->pos
].time
<= time
)
677 const MidiEvent
*evt
= &queue
->events
[queue
->pos
];
679 if(evt
->event
== SYSEX_EVENT
)
681 static const ALbyte gm2_on
[] = { 0x7E, 0x7F, 0x09, 0x03 };
682 static const ALbyte gm2_off
[] = { 0x7E, 0x7F, 0x09, 0x02 };
685 fluid_synth_sysex(self
->Synth
, evt
->param
.sysex
.data
, evt
->param
.sysex
.size
, NULL
, NULL
, &handled
, 0);
686 if(!handled
&& evt
->param
.sysex
.size
>= (ALsizei
)sizeof(gm2_on
))
688 if(memcmp(evt
->param
.sysex
.data
, gm2_on
, sizeof(gm2_on
)) == 0)
689 self
->ForceGM2BankSelect
= AL_TRUE
;
690 else if(memcmp(evt
->param
.sysex
.data
, gm2_off
, sizeof(gm2_off
)) == 0)
691 self
->ForceGM2BankSelect
= AL_FALSE
;
694 else switch((evt
->event
&0xF0))
696 case AL_NOTEOFF_SOFT
:
697 fluid_synth_noteoff(self
->Synth
, (evt
->event
&0x0F), evt
->param
.val
[0]);
700 fluid_synth_noteon(self
->Synth
, (evt
->event
&0x0F), evt
->param
.val
[0], evt
->param
.val
[1]);
702 case AL_KEYPRESSURE_SOFT
:
705 case AL_CONTROLLERCHANGE_SOFT
:
706 if(self
->ForceGM2BankSelect
)
708 int chan
= (evt
->event
&0x0F);
709 if(evt
->param
.val
[0] == CTRL_BANKSELECT_MSB
)
711 if(evt
->param
.val
[1] == 120 && (chan
== 9 || chan
== 10))
712 fluid_synth_set_channel_type(self
->Synth
, chan
, CHANNEL_TYPE_DRUM
);
713 else if(evt
->param
.val
[1] == 121)
714 fluid_synth_set_channel_type(self
->Synth
, chan
, CHANNEL_TYPE_MELODIC
);
717 if(evt
->param
.val
[0] == CTRL_BANKSELECT_LSB
)
719 fluid_synth_bank_select(self
->Synth
, chan
, evt
->param
.val
[1]);
723 fluid_synth_cc(self
->Synth
, (evt
->event
&0x0F), evt
->param
.val
[0], evt
->param
.val
[1]);
725 case AL_PROGRAMCHANGE_SOFT
:
726 fluid_synth_program_change(self
->Synth
, (evt
->event
&0x0F), evt
->param
.val
[0]);
729 case AL_CHANNELPRESSURE_SOFT
:
730 fluid_synth_channel_pressure(self
->Synth
, (evt
->event
&0x0F), evt
->param
.val
[0]);
733 case AL_PITCHBEND_SOFT
:
734 fluid_synth_pitch_bend(self
->Synth
, (evt
->event
&0x0F), (evt
->param
.val
[0]&0x7F) |
735 ((evt
->param
.val
[1]&0x7F)<<7));
743 static void FSynth_process(FSynth
*self
, ALuint SamplesToDo
, ALfloat (*restrict DryBuffer
)[BUFFERSIZE
])
745 MidiSynth
*synth
= STATIC_CAST(MidiSynth
, self
);
746 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 curtime
= MidiSynth_getTime(synth
);
760 while(total
< SamplesToDo
)
765 time
= MidiSynth_getNextEvtTime(synth
);
766 diff
= maxu64(time
, curtime
) - curtime
;
767 if(diff
>= MIDI_CLOCK_RES
|| time
== UINT64_MAX
)
769 /* If there's no pending event, or if it's more than 1 second
770 * away, do as many samples as we can. */
775 /* Figure out how many samples until the next event. */
776 tonext
= (ALint
)((diff
*synth
->SampleRate
+ (MIDI_CLOCK_RES
-1)) / MIDI_CLOCK_RES
);
782 ALuint todo
= minu(tonext
, SamplesToDo
-total
);
783 fluid_synth_write_float(self
->Synth
, todo
, DryBuffer
[FrontLeft
], total
, 1,
784 DryBuffer
[FrontRight
], total
, 1);
788 if(total
< SamplesToDo
&& tonext
<= 0)
789 FSynth_processQueue(self
, time
);
792 synth
->SamplesDone
+= SamplesToDo
;
793 synth
->ClockBase
+= (synth
->SamplesDone
/synth
->SampleRate
) * MIDI_CLOCK_RES
;
794 synth
->SamplesDone
%= synth
->SampleRate
;
798 MidiSynth
*FSynth_create(ALCdevice
*device
)
800 FSynth
*synth
= FSynth_New(sizeof(*synth
));
803 ERR("Failed to allocate FSynth\n");
806 memset(synth
, 0, sizeof(*synth
));
807 FSynth_Construct(synth
, device
);
809 if(FSynth_init(synth
, device
) == AL_FALSE
)
811 DELETE_OBJ(STATIC_CAST(MidiSynth
, synth
));
815 return STATIC_CAST(MidiSynth
, synth
);
820 MidiSynth
*FSynth_create(ALCdevice
* UNUSED(device
))