18 #ifdef HAVE_FLUIDSYNTH
20 #include <fluidsynth.h>
24 #define FLUID_FUNCS(MAGIC) \
25 MAGIC(new_fluid_synth); \
26 MAGIC(delete_fluid_synth); \
27 MAGIC(new_fluid_settings); \
28 MAGIC(delete_fluid_settings); \
29 MAGIC(fluid_settings_setint); \
30 MAGIC(fluid_settings_setnum); \
31 MAGIC(fluid_synth_noteon); \
32 MAGIC(fluid_synth_noteoff); \
33 MAGIC(fluid_synth_program_change); \
34 MAGIC(fluid_synth_pitch_bend); \
35 MAGIC(fluid_synth_channel_pressure); \
36 MAGIC(fluid_synth_cc); \
37 MAGIC(fluid_synth_sysex); \
38 MAGIC(fluid_synth_bank_select); \
39 MAGIC(fluid_synth_set_channel_type); \
40 MAGIC(fluid_synth_all_sounds_off); \
41 MAGIC(fluid_synth_system_reset); \
42 MAGIC(fluid_synth_set_gain); \
43 MAGIC(fluid_synth_set_sample_rate); \
44 MAGIC(fluid_synth_write_float); \
45 MAGIC(fluid_synth_add_sfloader); \
46 MAGIC(fluid_synth_sfload); \
47 MAGIC(fluid_synth_sfunload); \
48 MAGIC(fluid_synth_alloc_voice); \
49 MAGIC(fluid_synth_start_voice); \
50 MAGIC(fluid_voice_gen_set); \
51 MAGIC(fluid_voice_add_mod); \
52 MAGIC(fluid_mod_set_source1); \
53 MAGIC(fluid_mod_set_source2); \
54 MAGIC(fluid_mod_set_amount); \
55 MAGIC(fluid_mod_set_dest);
57 void *fsynth_handle
= NULL
;
58 #define DECL_FUNC(x) __typeof(x) *p##x
59 FLUID_FUNCS(DECL_FUNC
)
62 #define new_fluid_synth pnew_fluid_synth
63 #define delete_fluid_synth pdelete_fluid_synth
64 #define new_fluid_settings pnew_fluid_settings
65 #define delete_fluid_settings pdelete_fluid_settings
66 #define fluid_settings_setint pfluid_settings_setint
67 #define fluid_settings_setnum pfluid_settings_setnum
68 #define fluid_synth_noteon pfluid_synth_noteon
69 #define fluid_synth_noteoff pfluid_synth_noteoff
70 #define fluid_synth_program_change pfluid_synth_program_change
71 #define fluid_synth_pitch_bend pfluid_synth_pitch_bend
72 #define fluid_synth_channel_pressure pfluid_synth_channel_pressure
73 #define fluid_synth_cc pfluid_synth_cc
74 #define fluid_synth_sysex pfluid_synth_sysex
75 #define fluid_synth_bank_select pfluid_synth_bank_select
76 #define fluid_synth_set_channel_type pfluid_synth_set_channel_type
77 #define fluid_synth_all_sounds_off pfluid_synth_all_sounds_off
78 #define fluid_synth_system_reset pfluid_synth_system_reset
79 #define fluid_synth_set_gain pfluid_synth_set_gain
80 #define fluid_synth_set_sample_rate pfluid_synth_set_sample_rate
81 #define fluid_synth_write_float pfluid_synth_write_float
82 #define fluid_synth_add_sfloader pfluid_synth_add_sfloader
83 #define fluid_synth_sfload pfluid_synth_sfload
84 #define fluid_synth_sfunload pfluid_synth_sfunload
85 #define fluid_synth_alloc_voice pfluid_synth_alloc_voice
86 #define fluid_synth_start_voice pfluid_synth_start_voice
87 #define fluid_voice_gen_set pfluid_voice_gen_set
88 #define fluid_voice_add_mod pfluid_voice_add_mod
89 #define fluid_mod_set_source1 pfluid_mod_set_source1
90 #define fluid_mod_set_source2 pfluid_mod_set_source2
91 #define fluid_mod_set_amount pfluid_mod_set_amount
92 #define fluid_mod_set_dest pfluid_mod_set_dest
94 static ALboolean
LoadFSynth(void)
96 ALboolean ret
= AL_TRUE
;
99 fsynth_handle
= LoadLib("libfluidsynth.so.1");
100 if(!fsynth_handle
) return AL_FALSE
;
102 #define LOAD_FUNC(x) do { \
103 p##x = GetSymbol(fsynth_handle, #x); \
104 if(!p##x) ret = AL_FALSE; \
106 FLUID_FUNCS(LOAD_FUNC
)
111 CloseLib(fsynth_handle
);
112 fsynth_handle
= NULL
;
118 static inline ALboolean
LoadFSynth(void) { return AL_TRUE
; }
123 #define SYSEX_EVENT (0xF0)
125 /* MIDI controllers */
126 #define CTRL_BANKSELECT_MSB (0)
127 #define CTRL_BANKSELECT_LSB (32)
128 #define CTRL_ALLNOTESOFF (123)
131 static int getModInput(ALenum input
)
135 case AL_ONE_SOFT
: return FLUID_MOD_NONE
;
136 case AL_NOTEON_VELOCITY_SOFT
: return FLUID_MOD_VELOCITY
;
137 case AL_NOTEON_KEY_SOFT
: return FLUID_MOD_KEY
;
138 case AL_KEYPRESSURE_SOFT
: return FLUID_MOD_KEYPRESSURE
;
139 case AL_CHANNELPRESSURE_SOFT
: return FLUID_MOD_CHANNELPRESSURE
;
140 case AL_PITCHBEND_SOFT
: return FLUID_MOD_PITCHWHEEL
;
141 case AL_PITCHBEND_SENSITIVITY_SOFT
: return FLUID_MOD_PITCHWHEELSENS
;
146 static int getModFlags(ALenum input
, ALenum type
, ALenum form
)
152 case AL_UNORM_SOFT
: ret
|= FLUID_MOD_UNIPOLAR
| FLUID_MOD_POSITIVE
; break;
153 case AL_UNORM_REV_SOFT
: ret
|= FLUID_MOD_UNIPOLAR
| FLUID_MOD_NEGATIVE
; break;
154 case AL_SNORM_SOFT
: ret
|= FLUID_MOD_BIPOLAR
| FLUID_MOD_POSITIVE
; break;
155 case AL_SNORM_REV_SOFT
: ret
|= FLUID_MOD_BIPOLAR
| FLUID_MOD_NEGATIVE
; break;
159 case AL_LINEAR_SOFT
: ret
|= FLUID_MOD_LINEAR
; break;
160 case AL_CONCAVE_SOFT
: ret
|= FLUID_MOD_CONCAVE
; break;
161 case AL_CONVEX_SOFT
: ret
|= FLUID_MOD_CONVEX
; break;
162 case AL_SWITCH_SOFT
: ret
|= FLUID_MOD_SWITCH
; break;
164 /* Source input values less than 128 correspond to a MIDI continuous
165 * controller. Otherwise, it's a general controller. */
166 if(input
< 128) ret
|= FLUID_MOD_CC
;
167 else ret
|= FLUID_MOD_GC
;
172 static enum fluid_gen_type
getModDest(ALenum gen
)
176 case AL_MOD_LFO_TO_PITCH_SOFT
: return GEN_MODLFOTOPITCH
;
177 case AL_VIBRATO_LFO_TO_PITCH_SOFT
: return GEN_VIBLFOTOPITCH
;
178 case AL_MOD_ENV_TO_PITCH_SOFT
: return GEN_MODENVTOPITCH
;
179 case AL_FILTER_CUTOFF_SOFT
: return GEN_FILTERFC
;
180 case AL_FILTER_RESONANCE_SOFT
: return GEN_FILTERQ
;
181 case AL_MOD_LFO_TO_FILTER_CUTOFF_SOFT
: return GEN_MODLFOTOFILTERFC
;
182 case AL_MOD_ENV_TO_FILTER_CUTOFF_SOFT
: return GEN_MODENVTOFILTERFC
;
183 case AL_MOD_LFO_TO_VOLUME_SOFT
: return GEN_MODLFOTOVOL
;
184 case AL_CHORUS_SEND_SOFT
: return GEN_CHORUSSEND
;
185 case AL_REVERB_SEND_SOFT
: return GEN_REVERBSEND
;
186 case AL_PAN_SOFT
: return GEN_PAN
;
187 case AL_MOD_LFO_DELAY_SOFT
: return GEN_MODLFODELAY
;
188 case AL_MOD_LFO_FREQUENCY_SOFT
: return GEN_MODLFOFREQ
;
189 case AL_VIBRATO_LFO_DELAY_SOFT
: return GEN_VIBLFODELAY
;
190 case AL_VIBRATO_LFO_FREQUENCY_SOFT
: return GEN_VIBLFOFREQ
;
191 case AL_MOD_ENV_DELAYTIME_SOFT
: return GEN_MODENVDELAY
;
192 case AL_MOD_ENV_ATTACKTIME_SOFT
: return GEN_MODENVATTACK
;
193 case AL_MOD_ENV_HOLDTIME_SOFT
: return GEN_MODENVHOLD
;
194 case AL_MOD_ENV_DECAYTIME_SOFT
: return GEN_MODENVDECAY
;
195 case AL_MOD_ENV_SUSTAINVOLUME_SOFT
: return GEN_MODENVSUSTAIN
;
196 case AL_MOD_ENV_RELEASETIME_SOFT
: return GEN_MODENVRELEASE
;
197 case AL_MOD_ENV_KEY_TO_HOLDTIME_SOFT
: return GEN_KEYTOMODENVHOLD
;
198 case AL_MOD_ENV_KEY_TO_DECAYTIME_SOFT
: return GEN_KEYTOMODENVDECAY
;
199 case AL_VOLUME_ENV_DELAYTIME_SOFT
: return GEN_VOLENVDELAY
;
200 case AL_VOLUME_ENV_ATTACKTIME_SOFT
: return GEN_VOLENVATTACK
;
201 case AL_VOLUME_ENV_HOLDTIME_SOFT
: return GEN_VOLENVHOLD
;
202 case AL_VOLUME_ENV_DECAYTIME_SOFT
: return GEN_VOLENVDECAY
;
203 case AL_VOLUME_ENV_SUSTAINVOLUME_SOFT
: return GEN_VOLENVSUSTAIN
;
204 case AL_VOLUME_ENV_RELEASETIME_SOFT
: return GEN_VOLENVRELEASE
;
205 case AL_VOLUME_ENV_KEY_TO_HOLDTIME_SOFT
: return GEN_KEYTOVOLENVHOLD
;
206 case AL_VOLUME_ENV_KEY_TO_DECAYTIME_SOFT
: return GEN_KEYTOVOLENVDECAY
;
207 case AL_ATTENUATION_SOFT
: return GEN_ATTENUATION
;
208 case AL_TUNING_COARSE_SOFT
: return GEN_COARSETUNE
;
209 case AL_TUNING_FINE_SOFT
: return GEN_FINETUNE
;
210 case AL_TUNING_SCALE_SOFT
: return GEN_SCALETUNE
;
212 ERR("Unhandled generator: 0x%04x\n", gen
);
216 static int getSf2LoopMode(ALenum mode
)
220 case AL_NONE
: return 0;
221 case AL_LOOP_CONTINUOUS_SOFT
: return 1;
222 case AL_LOOP_UNTIL_RELEASE_SOFT
: return 3;
227 static int getSampleType(ALenum type
)
231 case AL_MONO_SOFT
: return FLUID_SAMPLETYPE_MONO
;
232 case AL_RIGHT_SOFT
: return FLUID_SAMPLETYPE_RIGHT
;
233 case AL_LEFT_SOFT
: return FLUID_SAMPLETYPE_LEFT
;
235 return FLUID_SAMPLETYPE_MONO
;
238 typedef struct FSample
{
239 DERIVE_FROM_TYPE(fluid_sample_t
);
247 static void FSample_Construct(FSample
*self
, ALfontsound
*sound
)
249 fluid_sample_t
*sample
= STATIC_CAST(fluid_sample_t
, self
);
250 ALbuffer
*buffer
= ATOMIC_LOAD(&sound
->Buffer
);
252 memset(sample
->name
, 0, sizeof(sample
->name
));
253 sample
->start
= sound
->Start
;
254 sample
->end
= sound
->End
;
255 sample
->loopstart
= sound
->LoopStart
;
256 sample
->loopend
= sound
->LoopEnd
;
257 sample
->samplerate
= sound
->SampleRate
;
258 sample
->origpitch
= sound
->PitchKey
;
259 sample
->pitchadj
= sound
->PitchCorrection
;
260 sample
->sampletype
= getSampleType(sound
->SampleType
);
261 sample
->valid
= !!buffer
;
262 sample
->data
= buffer
? buffer
->data
: NULL
;
264 sample
->amplitude_that_reaches_noise_floor_is_valid
= 0;
265 sample
->amplitude_that_reaches_noise_floor
= 0.0;
267 sample
->refcount
= 0;
269 sample
->notify
= NULL
;
271 sample
->userdata
= self
;
276 self
->Mods
= calloc(sound
->ModulatorMap
.size
*4, sizeof(fluid_mod_t
[4]));
281 for(i
= j
= 0;i
< sound
->ModulatorMap
.size
;i
++)
283 ALsfmodulator
*mod
= sound
->ModulatorMap
.array
[i
].value
;
284 for(k
= 0;k
< 4;k
++,mod
++)
286 if(mod
->Dest
== AL_NONE
)
288 fluid_mod_set_source1(&self
->Mods
[j
], getModInput(mod
->Source
[0].Input
),
289 getModFlags(mod
->Source
[0].Input
, mod
->Source
[0].Type
,
290 mod
->Source
[0].Form
));
291 fluid_mod_set_source2(&self
->Mods
[j
], getModInput(mod
->Source
[1].Input
),
292 getModFlags(mod
->Source
[1].Input
, mod
->Source
[1].Type
,
293 mod
->Source
[1].Form
));
294 fluid_mod_set_amount(&self
->Mods
[j
], mod
->Amount
);
295 fluid_mod_set_dest(&self
->Mods
[j
], getModDest(mod
->Dest
));
296 self
->Mods
[j
++].next
= NULL
;
303 static void FSample_Destruct(FSample
*self
)
311 typedef struct FPreset
{
312 DERIVE_FROM_TYPE(fluid_preset_t
);
323 static char* FPreset_getName(fluid_preset_t
*preset
);
324 static int FPreset_getPreset(fluid_preset_t
*preset
);
325 static int FPreset_getBank(fluid_preset_t
*preset
);
326 static int FPreset_noteOn(fluid_preset_t
*preset
, fluid_synth_t
*synth
, int channel
, int key
, int velocity
);
328 static void FPreset_Construct(FPreset
*self
, ALsfpreset
*preset
, fluid_sfont_t
*parent
)
330 STATIC_CAST(fluid_preset_t
, self
)->data
= self
;
331 STATIC_CAST(fluid_preset_t
, self
)->sfont
= parent
;
332 STATIC_CAST(fluid_preset_t
, self
)->free
= NULL
;
333 STATIC_CAST(fluid_preset_t
, self
)->get_name
= FPreset_getName
;
334 STATIC_CAST(fluid_preset_t
, self
)->get_banknum
= FPreset_getBank
;
335 STATIC_CAST(fluid_preset_t
, self
)->get_num
= FPreset_getPreset
;
336 STATIC_CAST(fluid_preset_t
, self
)->noteon
= FPreset_noteOn
;
337 STATIC_CAST(fluid_preset_t
, self
)->notify
= NULL
;
339 memset(self
->Name
, 0, sizeof(self
->Name
));
340 self
->Preset
= preset
->Preset
;
341 self
->Bank
= preset
->Bank
;
343 self
->NumSamples
= 0;
344 self
->Samples
= calloc(1, preset
->NumSounds
* sizeof(self
->Samples
[0]));
348 self
->NumSamples
= preset
->NumSounds
;
349 for(i
= 0;i
< self
->NumSamples
;i
++)
350 FSample_Construct(&self
->Samples
[i
], preset
->Sounds
[i
]);
354 static void FPreset_Destruct(FPreset
*self
)
358 for(i
= 0;i
< self
->NumSamples
;i
++)
359 FSample_Destruct(&self
->Samples
[i
]);
361 self
->Samples
= NULL
;
362 self
->NumSamples
= 0;
365 static ALboolean
FPreset_canDelete(FPreset
*self
)
368 for(i
= 0;i
< self
->NumSamples
;i
++)
370 if(fluid_sample_refcount(STATIC_CAST(fluid_sample_t
, &self
->Samples
[i
])) != 0)
376 static char* FPreset_getName(fluid_preset_t
*preset
)
378 return ((FPreset
*)preset
->data
)->Name
;
381 static int FPreset_getPreset(fluid_preset_t
*preset
)
383 return ((FPreset
*)preset
->data
)->Preset
;
386 static int FPreset_getBank(fluid_preset_t
*preset
)
388 return ((FPreset
*)preset
->data
)->Bank
;
391 static int FPreset_noteOn(fluid_preset_t
*preset
, fluid_synth_t
*synth
, int channel
, int key
, int vel
)
393 FPreset
*self
= ((FPreset
*)preset
->data
);
396 for(i
= 0;i
< self
->NumSamples
;i
++)
398 FSample
*sample
= &self
->Samples
[i
];
399 ALfontsound
*sound
= sample
->Sound
;
400 fluid_voice_t
*voice
;
403 if(!(key
>= sound
->MinKey
&& key
<= sound
->MaxKey
&& vel
>= sound
->MinVelocity
&& vel
<= sound
->MaxVelocity
))
406 voice
= fluid_synth_alloc_voice(synth
, STATIC_CAST(fluid_sample_t
, sample
), channel
, key
, vel
);
407 if(voice
== NULL
) return FLUID_FAILED
;
409 fluid_voice_gen_set(voice
, GEN_MODLFOTOPITCH
, sound
->ModLfoToPitch
);
410 fluid_voice_gen_set(voice
, GEN_VIBLFOTOPITCH
, sound
->VibratoLfoToPitch
);
411 fluid_voice_gen_set(voice
, GEN_MODENVTOPITCH
, sound
->ModEnvToPitch
);
412 fluid_voice_gen_set(voice
, GEN_FILTERFC
, sound
->FilterCutoff
);
413 fluid_voice_gen_set(voice
, GEN_FILTERQ
, sound
->FilterQ
);
414 fluid_voice_gen_set(voice
, GEN_MODLFOTOFILTERFC
, sound
->ModLfoToFilterCutoff
);
415 fluid_voice_gen_set(voice
, GEN_MODENVTOFILTERFC
, sound
->ModEnvToFilterCutoff
);
416 fluid_voice_gen_set(voice
, GEN_MODLFOTOVOL
, sound
->ModLfoToVolume
);
417 fluid_voice_gen_set(voice
, GEN_CHORUSSEND
, sound
->ChorusSend
);
418 fluid_voice_gen_set(voice
, GEN_REVERBSEND
, sound
->ReverbSend
);
419 fluid_voice_gen_set(voice
, GEN_PAN
, sound
->Pan
);
420 fluid_voice_gen_set(voice
, GEN_MODLFODELAY
, sound
->ModLfo
.Delay
);
421 fluid_voice_gen_set(voice
, GEN_MODLFOFREQ
, sound
->ModLfo
.Frequency
);
422 fluid_voice_gen_set(voice
, GEN_VIBLFODELAY
, sound
->VibratoLfo
.Delay
);
423 fluid_voice_gen_set(voice
, GEN_VIBLFOFREQ
, sound
->VibratoLfo
.Frequency
);
424 fluid_voice_gen_set(voice
, GEN_MODENVDELAY
, sound
->ModEnv
.DelayTime
);
425 fluid_voice_gen_set(voice
, GEN_MODENVATTACK
, sound
->ModEnv
.AttackTime
);
426 fluid_voice_gen_set(voice
, GEN_MODENVHOLD
, sound
->ModEnv
.HoldTime
);
427 fluid_voice_gen_set(voice
, GEN_MODENVDECAY
, sound
->ModEnv
.DecayTime
);
428 fluid_voice_gen_set(voice
, GEN_MODENVSUSTAIN
, sound
->ModEnv
.SustainAttn
);
429 fluid_voice_gen_set(voice
, GEN_MODENVRELEASE
, sound
->ModEnv
.ReleaseTime
);
430 fluid_voice_gen_set(voice
, GEN_KEYTOMODENVHOLD
, sound
->ModEnv
.KeyToHoldTime
);
431 fluid_voice_gen_set(voice
, GEN_KEYTOMODENVDECAY
, sound
->ModEnv
.KeyToDecayTime
);
432 fluid_voice_gen_set(voice
, GEN_VOLENVDELAY
, sound
->VolEnv
.DelayTime
);
433 fluid_voice_gen_set(voice
, GEN_VOLENVATTACK
, sound
->VolEnv
.AttackTime
);
434 fluid_voice_gen_set(voice
, GEN_VOLENVHOLD
, sound
->VolEnv
.HoldTime
);
435 fluid_voice_gen_set(voice
, GEN_VOLENVDECAY
, sound
->VolEnv
.DecayTime
);
436 fluid_voice_gen_set(voice
, GEN_VOLENVSUSTAIN
, sound
->VolEnv
.SustainAttn
);
437 fluid_voice_gen_set(voice
, GEN_VOLENVRELEASE
, sound
->VolEnv
.ReleaseTime
);
438 fluid_voice_gen_set(voice
, GEN_KEYTOVOLENVHOLD
, sound
->VolEnv
.KeyToHoldTime
);
439 fluid_voice_gen_set(voice
, GEN_KEYTOVOLENVDECAY
, sound
->VolEnv
.KeyToDecayTime
);
440 fluid_voice_gen_set(voice
, GEN_ATTENUATION
, sound
->Attenuation
);
441 fluid_voice_gen_set(voice
, GEN_COARSETUNE
, sound
->CoarseTuning
);
442 fluid_voice_gen_set(voice
, GEN_FINETUNE
, sound
->FineTuning
);
443 fluid_voice_gen_set(voice
, GEN_SAMPLEMODE
, getSf2LoopMode(sound
->LoopMode
));
444 fluid_voice_gen_set(voice
, GEN_SCALETUNE
, sound
->TuningScale
);
445 fluid_voice_gen_set(voice
, GEN_EXCLUSIVECLASS
, sound
->ExclusiveClass
);
446 for(m
= 0;m
< sample
->NumMods
;m
++)
447 fluid_voice_add_mod(voice
, &sample
->Mods
[m
], FLUID_VOICE_OVERWRITE
);
449 fluid_synth_start_voice(synth
, voice
);
456 typedef struct FSfont
{
457 DERIVE_FROM_TYPE(fluid_sfont_t
);
467 static int FSfont_free(fluid_sfont_t
*sfont
);
468 static char* FSfont_getName(fluid_sfont_t
*sfont
);
469 static fluid_preset_t
* FSfont_getPreset(fluid_sfont_t
*sfont
, unsigned int bank
, unsigned int prenum
);
470 static void FSfont_iterStart(fluid_sfont_t
*sfont
);
471 static int FSfont_iterNext(fluid_sfont_t
*sfont
, fluid_preset_t
*preset
);
473 static void FSfont_Construct(FSfont
*self
, ALsoundfont
*sfont
)
475 STATIC_CAST(fluid_sfont_t
, self
)->data
= self
;
476 STATIC_CAST(fluid_sfont_t
, self
)->id
= FLUID_FAILED
;
477 STATIC_CAST(fluid_sfont_t
, self
)->free
= FSfont_free
;
478 STATIC_CAST(fluid_sfont_t
, self
)->get_name
= FSfont_getName
;
479 STATIC_CAST(fluid_sfont_t
, self
)->get_preset
= FSfont_getPreset
;
480 STATIC_CAST(fluid_sfont_t
, self
)->iteration_start
= FSfont_iterStart
;
481 STATIC_CAST(fluid_sfont_t
, self
)->iteration_next
= FSfont_iterNext
;
483 memset(self
->Name
, 0, sizeof(self
->Name
));
484 self
->CurrentPos
= 0;
485 self
->NumPresets
= 0;
486 self
->Presets
= calloc(1, sfont
->NumPresets
* sizeof(self
->Presets
[0]));
490 self
->NumPresets
= sfont
->NumPresets
;
491 for(i
= 0;i
< self
->NumPresets
;i
++)
492 FPreset_Construct(&self
->Presets
[i
], sfont
->Presets
[i
], STATIC_CAST(fluid_sfont_t
, self
));
496 static void FSfont_Destruct(FSfont
*self
)
500 for(i
= 0;i
< self
->NumPresets
;i
++)
501 FPreset_Destruct(&self
->Presets
[i
]);
503 self
->Presets
= NULL
;
504 self
->NumPresets
= 0;
505 self
->CurrentPos
= 0;
508 static int FSfont_free(fluid_sfont_t
*sfont
)
510 FSfont
*self
= STATIC_UPCAST(FSfont
, fluid_sfont_t
, sfont
);
513 for(i
= 0;i
< self
->NumPresets
;i
++)
515 if(!FPreset_canDelete(&self
->Presets
[i
]))
519 FSfont_Destruct(self
);
524 static char* FSfont_getName(fluid_sfont_t
*sfont
)
526 return STATIC_UPCAST(FSfont
, fluid_sfont_t
, sfont
)->Name
;
529 static fluid_preset_t
*FSfont_getPreset(fluid_sfont_t
*sfont
, unsigned int bank
, unsigned int prenum
)
531 FSfont
*self
= STATIC_UPCAST(FSfont
, fluid_sfont_t
, sfont
);
534 for(i
= 0;i
< self
->NumPresets
;i
++)
536 FPreset
*preset
= &self
->Presets
[i
];
537 if(preset
->Bank
== (int)bank
&& preset
->Preset
== (int)prenum
)
538 return STATIC_CAST(fluid_preset_t
, preset
);
544 static void FSfont_iterStart(fluid_sfont_t
*sfont
)
546 STATIC_UPCAST(FSfont
, fluid_sfont_t
, sfont
)->CurrentPos
= 0;
549 static int FSfont_iterNext(fluid_sfont_t
*sfont
, fluid_preset_t
*preset
)
551 FSfont
*self
= STATIC_UPCAST(FSfont
, fluid_sfont_t
, sfont
);
552 if(self
->CurrentPos
>= self
->NumPresets
)
554 *preset
= *STATIC_CAST(fluid_preset_t
, &self
->Presets
[self
->CurrentPos
++]);
560 typedef struct FSynth
{
561 DERIVE_FROM_TYPE(MidiSynth
);
562 DERIVE_FROM_TYPE(fluid_sfloader_t
);
564 fluid_settings_t
*Settings
;
565 fluid_synth_t
*Synth
;
569 ALboolean ForceGM2BankSelect
;
573 static void FSynth_Construct(FSynth
*self
, ALCdevice
*device
);
574 static void FSynth_Destruct(FSynth
*self
);
575 static ALboolean
FSynth_init(FSynth
*self
, ALCdevice
*device
);
576 static ALenum
FSynth_selectSoundfonts(FSynth
*self
, ALCcontext
*context
, ALsizei count
, const ALuint
*ids
);
577 static void FSynth_setGain(FSynth
*self
, ALfloat gain
);
578 static void FSynth_stop(FSynth
*self
);
579 static void FSynth_reset(FSynth
*self
);
580 static void FSynth_update(FSynth
*self
, ALCdevice
*device
);
581 static void FSynth_processQueue(FSynth
*self
, ALuint64 time
);
582 static void FSynth_process(FSynth
*self
, ALuint SamplesToDo
, ALfloat (*restrict DryBuffer
)[BUFFERSIZE
]);
583 DECLARE_DEFAULT_ALLOCATORS(FSynth
)
584 DEFINE_MIDISYNTH_VTABLE(FSynth
);
586 static fluid_sfont_t
*FSynth_loadSfont(fluid_sfloader_t
*loader
, const char *filename
);
589 static void FSynth_Construct(FSynth
*self
, ALCdevice
*device
)
591 MidiSynth_Construct(STATIC_CAST(MidiSynth
, self
), device
);
592 SET_VTABLE2(FSynth
, MidiSynth
, self
);
594 STATIC_CAST(fluid_sfloader_t
, self
)->data
= self
;
595 STATIC_CAST(fluid_sfloader_t
, self
)->free
= NULL
;
596 STATIC_CAST(fluid_sfloader_t
, self
)->load
= FSynth_loadSfont
;
598 self
->Settings
= NULL
;
600 self
->FontIDs
= NULL
;
601 self
->NumFontIDs
= 0;
602 self
->ForceGM2BankSelect
= AL_FALSE
;
603 self
->GainScale
= 0.2f
;
606 static void FSynth_Destruct(FSynth
*self
)
610 for(i
= 0;i
< self
->NumFontIDs
;i
++)
611 fluid_synth_sfunload(self
->Synth
, self
->FontIDs
[i
], 0);
613 self
->FontIDs
= NULL
;
614 self
->NumFontIDs
= 0;
616 if(self
->Synth
!= NULL
)
617 delete_fluid_synth(self
->Synth
);
620 if(self
->Settings
!= NULL
)
621 delete_fluid_settings(self
->Settings
);
622 self
->Settings
= NULL
;
624 MidiSynth_Destruct(STATIC_CAST(MidiSynth
, self
));
627 static ALboolean
FSynth_init(FSynth
*self
, ALCdevice
*device
)
631 if(ConfigValueFloat("midi", "volume", &vol
))
635 ERR("MIDI volume %f clamped to 0\n", vol
);
638 self
->GainScale
= powf(10.0f
, vol
/ 20.0f
);
641 self
->Settings
= new_fluid_settings();
644 ERR("Failed to create FluidSettings\n");
648 fluid_settings_setint(self
->Settings
, "synth.polyphony", 256);
649 fluid_settings_setnum(self
->Settings
, "synth.gain", self
->GainScale
);
650 fluid_settings_setnum(self
->Settings
, "synth.sample-rate", device
->Frequency
);
652 self
->Synth
= new_fluid_synth(self
->Settings
);
655 ERR("Failed to create FluidSynth\n");
659 fluid_synth_add_sfloader(self
->Synth
, STATIC_CAST(fluid_sfloader_t
, self
));
665 static fluid_sfont_t
*FSynth_loadSfont(fluid_sfloader_t
*loader
, const char *filename
)
667 FSynth
*self
= STATIC_UPCAST(FSynth
, fluid_sfloader_t
, loader
);
671 if(!filename
|| sscanf(filename
, "_al_internal %d", &idx
) != 1)
673 if(idx
< 0 || idx
>= STATIC_CAST(MidiSynth
, self
)->NumSoundfonts
)
675 ERR("Received invalid soundfont index %d (max: %d)\n", idx
, STATIC_CAST(MidiSynth
, self
)->NumSoundfonts
);
679 sfont
= calloc(1, sizeof(sfont
[0]));
680 if(!sfont
) return NULL
;
682 FSfont_Construct(sfont
, STATIC_CAST(MidiSynth
, self
)->Soundfonts
[idx
]);
683 return STATIC_CAST(fluid_sfont_t
, sfont
);
686 static ALenum
FSynth_selectSoundfonts(FSynth
*self
, ALCcontext
*context
, ALsizei count
, const ALuint
*ids
)
692 ret
= MidiSynth_selectSoundfonts(STATIC_CAST(MidiSynth
, self
), context
, count
, ids
);
693 if(ret
!= AL_NO_ERROR
) return ret
;
695 ALCdevice_Lock(context
->Device
);
696 for(i
= 0;i
< 16;i
++)
697 fluid_synth_all_sounds_off(self
->Synth
, i
);
698 ALCdevice_Unlock(context
->Device
);
700 fontid
= malloc(count
* sizeof(fontid
[0]));
703 for(i
= 0;i
< STATIC_CAST(MidiSynth
, self
)->NumSoundfonts
;i
++)
706 snprintf(name
, sizeof(name
), "_al_internal %d", i
);
708 fontid
[i
] = fluid_synth_sfload(self
->Synth
, name
, 0);
709 if(fontid
[i
] == FLUID_FAILED
)
710 ERR("Failed to load selected soundfont %d\n", i
);
713 fontid
= ExchangePtr((XchgPtr
*)&self
->FontIDs
, fontid
);
714 count
= ExchangeInt(&self
->NumFontIDs
, count
);
718 ERR("Failed to allocate space for %d font IDs!\n", count
);
719 fontid
= ExchangePtr((XchgPtr
*)&self
->FontIDs
, NULL
);
720 count
= ExchangeInt(&self
->NumFontIDs
, 0);
723 for(i
= 0;i
< count
;i
++)
724 fluid_synth_sfunload(self
->Synth
, fontid
[i
], 0);
731 static void FSynth_setGain(FSynth
*self
, ALfloat gain
)
733 fluid_settings_setnum(self
->Settings
, "synth.gain", self
->GainScale
* gain
);
734 fluid_synth_set_gain(self
->Synth
, self
->GainScale
* gain
);
735 MidiSynth_setGain(STATIC_CAST(MidiSynth
, self
), gain
);
739 static void FSynth_stop(FSynth
*self
)
741 MidiSynth
*synth
= STATIC_CAST(MidiSynth
, self
);
745 /* Make sure all pending events are processed. */
746 curtime
= MidiSynth_getTime(synth
);
747 FSynth_processQueue(self
, curtime
);
750 for(chan
= 0;chan
< 16;chan
++)
751 fluid_synth_cc(self
->Synth
, chan
, CTRL_ALLNOTESOFF
, 0);
753 MidiSynth_stop(STATIC_CAST(MidiSynth
, self
));
756 static void FSynth_reset(FSynth
*self
)
758 /* Reset to power-up status. */
759 fluid_synth_system_reset(self
->Synth
);
761 MidiSynth_reset(STATIC_CAST(MidiSynth
, self
));
765 static void FSynth_update(FSynth
*self
, ALCdevice
*device
)
767 fluid_settings_setnum(self
->Settings
, "synth.sample-rate", device
->Frequency
);
768 fluid_synth_set_sample_rate(self
->Synth
, device
->Frequency
);
769 MidiSynth_update(STATIC_CAST(MidiSynth
, self
), device
);
773 static void FSynth_processQueue(FSynth
*self
, ALuint64 time
)
775 EvtQueue
*queue
= &STATIC_CAST(MidiSynth
, self
)->EventQueue
;
777 while(queue
->pos
< queue
->size
&& queue
->events
[queue
->pos
].time
<= time
)
779 const MidiEvent
*evt
= &queue
->events
[queue
->pos
];
781 if(evt
->event
== SYSEX_EVENT
)
783 static const ALbyte gm2_on
[] = { 0x7E, 0x7F, 0x09, 0x03 };
784 static const ALbyte gm2_off
[] = { 0x7E, 0x7F, 0x09, 0x02 };
787 fluid_synth_sysex(self
->Synth
, evt
->param
.sysex
.data
, evt
->param
.sysex
.size
, NULL
, NULL
, &handled
, 0);
788 if(!handled
&& evt
->param
.sysex
.size
>= (ALsizei
)sizeof(gm2_on
))
790 if(memcmp(evt
->param
.sysex
.data
, gm2_on
, sizeof(gm2_on
)) == 0)
791 self
->ForceGM2BankSelect
= AL_TRUE
;
792 else if(memcmp(evt
->param
.sysex
.data
, gm2_off
, sizeof(gm2_off
)) == 0)
793 self
->ForceGM2BankSelect
= AL_FALSE
;
796 else switch((evt
->event
&0xF0))
798 case AL_NOTEOFF_SOFT
:
799 fluid_synth_noteoff(self
->Synth
, (evt
->event
&0x0F), evt
->param
.val
[0]);
802 fluid_synth_noteon(self
->Synth
, (evt
->event
&0x0F), evt
->param
.val
[0], evt
->param
.val
[1]);
804 case AL_KEYPRESSURE_SOFT
:
807 case AL_CONTROLLERCHANGE_SOFT
:
808 if(self
->ForceGM2BankSelect
)
810 int chan
= (evt
->event
&0x0F);
811 if(evt
->param
.val
[0] == CTRL_BANKSELECT_MSB
)
813 if(evt
->param
.val
[1] == 120 && (chan
== 9 || chan
== 10))
814 fluid_synth_set_channel_type(self
->Synth
, chan
, CHANNEL_TYPE_DRUM
);
815 else if(evt
->param
.val
[1] == 121)
816 fluid_synth_set_channel_type(self
->Synth
, chan
, CHANNEL_TYPE_MELODIC
);
819 if(evt
->param
.val
[0] == CTRL_BANKSELECT_LSB
)
821 fluid_synth_bank_select(self
->Synth
, chan
, evt
->param
.val
[1]);
825 fluid_synth_cc(self
->Synth
, (evt
->event
&0x0F), evt
->param
.val
[0], evt
->param
.val
[1]);
827 case AL_PROGRAMCHANGE_SOFT
:
828 fluid_synth_program_change(self
->Synth
, (evt
->event
&0x0F), evt
->param
.val
[0]);
831 case AL_CHANNELPRESSURE_SOFT
:
832 fluid_synth_channel_pressure(self
->Synth
, (evt
->event
&0x0F), evt
->param
.val
[0]);
835 case AL_PITCHBEND_SOFT
:
836 fluid_synth_pitch_bend(self
->Synth
, (evt
->event
&0x0F), (evt
->param
.val
[0]&0x7F) |
837 ((evt
->param
.val
[1]&0x7F)<<7));
845 static void FSynth_process(FSynth
*self
, ALuint SamplesToDo
, ALfloat (*restrict DryBuffer
)[BUFFERSIZE
])
847 MidiSynth
*synth
= STATIC_CAST(MidiSynth
, self
);
848 ALenum state
= synth
->State
;
852 if(state
== AL_INITIAL
)
854 if(state
!= AL_PLAYING
)
856 fluid_synth_write_float(self
->Synth
, SamplesToDo
, DryBuffer
[FrontLeft
], 0, 1,
857 DryBuffer
[FrontRight
], 0, 1);
861 curtime
= MidiSynth_getTime(synth
);
862 while(total
< SamplesToDo
)
867 time
= MidiSynth_getNextEvtTime(synth
);
868 diff
= maxu64(time
, curtime
) - curtime
;
869 if(diff
>= MIDI_CLOCK_RES
|| time
== UINT64_MAX
)
871 /* If there's no pending event, or if it's more than 1 second
872 * away, do as many samples as we can. */
877 /* Figure out how many samples until the next event. */
878 tonext
= (ALint
)((diff
*synth
->SampleRate
+ (MIDI_CLOCK_RES
-1)) / MIDI_CLOCK_RES
);
884 ALuint todo
= minu(tonext
, SamplesToDo
-total
);
885 fluid_synth_write_float(self
->Synth
, todo
, DryBuffer
[FrontLeft
], total
, 1,
886 DryBuffer
[FrontRight
], total
, 1);
890 if(total
< SamplesToDo
&& tonext
<= 0)
891 FSynth_processQueue(self
, time
);
894 synth
->SamplesDone
+= SamplesToDo
;
895 synth
->ClockBase
+= (synth
->SamplesDone
/synth
->SampleRate
) * MIDI_CLOCK_RES
;
896 synth
->SamplesDone
%= synth
->SampleRate
;
900 MidiSynth
*FSynth_create(ALCdevice
*device
)
907 synth
= FSynth_New(sizeof(*synth
));
910 ERR("Failed to allocate FSynth\n");
913 memset(synth
, 0, sizeof(*synth
));
914 FSynth_Construct(synth
, device
);
916 if(FSynth_init(synth
, device
) == AL_FALSE
)
918 DELETE_OBJ(STATIC_CAST(MidiSynth
, synth
));
922 return STATIC_CAST(MidiSynth
, synth
);
927 MidiSynth
*FSynth_create(ALCdevice
* UNUSED(device
))