12 #include "midi/base.h"
15 static ALuint
read_le32(Reader
*stream
)
18 if(READ(stream
, buf
, 4) != 4)
23 return (buf
[3]<<24) | (buf
[2]<<16) | (buf
[1]<<8) | buf
[0];
25 static ALushort
read_le16(Reader
*stream
)
28 if(READ(stream
, buf
, 2) != 2)
33 return (buf
[1]<<8) | buf
[0];
35 static ALubyte
read_8(Reader
*stream
)
38 if(READ(stream
, buf
, 1) != 1)
45 static void skip(Reader
*stream
, ALuint amt
)
47 while(amt
> 0 && !READERR(stream
))
52 got
= READ(stream
, buf
, minu(sizeof(buf
), amt
));
53 if(got
== 0 || got
> amt
)
60 typedef struct Generator
{
64 static void Generator_read(Generator
*self
, Reader
*stream
)
66 self
->mGenerator
= read_le16(stream
);
67 self
->mAmount
= read_le16(stream
);
70 static const ALint DefaultGenValue
[60] = {
71 0, /* 0 - startAddrOffset */
72 0, /* 1 - endAddrOffset */
73 0, /* 2 - startloopAddrOffset */
74 0, /* 3 - endloopAddrOffset */
75 0, /* 4 - startAddrCoarseOffset */
76 0, /* 5 - modLfoToPitch */
77 0, /* 6 - vibLfoToPitch */
78 0, /* 7 - modEnvToPitch */
79 13500, /* 8 - initialFilterFc */
80 0, /* 9 - initialFilterQ */
81 0, /* 10 - modLfoToFilterFc */
82 0, /* 11 - modEnvToFilterFc */
83 0, /* 12 - endAddrCoarseOffset */
84 0, /* 13 - modLfoToVolume */
86 0, /* 15 - chorusEffectsSend */
87 0, /* 16 - reverbEffectsSend */
92 -12000, /* 21 - delayModLFO */
93 0, /* 22 - freqModLFO */
94 -12000, /* 23 - delayVibLFO */
95 0, /* 24 - freqVibLFO */
96 -12000, /* 25 - delayModEnv */
97 -12000, /* 26 - attackModEnv */
98 -12000, /* 27 - holdModEnv */
99 -12000, /* 28 - decayModEnv */
100 0, /* 29 - sustainModEnv */
101 -12000, /* 30 - releaseModEnv */
102 0, /* 31 - keynumToModEnvHold */
103 0, /* 32 - keynumToModEnvDecay */
104 -12000, /* 33 - delayVolEnv */
105 -12000, /* 34 - attackVolEnv */
106 -12000, /* 35 - holdVolEnv */
107 -12000, /* 36 - decayVolEnv */
108 0, /* 37 - sustainVolEnv */
109 -12000, /* 38 - releaseVolEnv */
110 0, /* 39 - keynumToVolEnvHold */
111 0, /* 40 - keynumToVolEnvDecay */
114 0, /* 43 - keyRange */
115 0, /* 44 - velRange */
116 0, /* 45 - startloopAddrCoarseOffset */
118 0, /* 47 - velocity */
119 0, /* 48 - initialAttenuation */
121 0, /* 50 - endloopAddrCoarseOffset */
122 0, /* 51 - corseTune */
123 0, /* 52 - fineTune */
125 0, /* 54 - sampleModes */
127 100, /* 56 - scaleTuning */
128 0, /* 57 - exclusiveClass */
129 0, /* 58 - overridingRootKey */
133 typedef struct Modulator
{
140 static void Modulator_read(Modulator
*self
, Reader
*stream
)
142 self
->mSrcOp
= read_le16(stream
);
143 self
->mDstOp
= read_le16(stream
);
144 self
->mAmount
= read_le16(stream
);
145 self
->mAmtSrcOp
= read_le16(stream
);
146 self
->mTransOp
= read_le16(stream
);
149 typedef struct Zone
{
153 static void Zone_read(Zone
*self
, Reader
*stream
)
155 self
->mGenIdx
= read_le16(stream
);
156 self
->mModIdx
= read_le16(stream
);
159 typedef struct PresetHeader
{
161 ALushort mPreset
; /* MIDI program number */
168 static void PresetHeader_read(PresetHeader
*self
, Reader
*stream
)
170 if(READ(stream
, self
->mName
, sizeof(self
->mName
)) != sizeof(self
->mName
))
172 self
->mPreset
= read_le16(stream
);
173 self
->mBank
= read_le16(stream
);
174 self
->mZoneIdx
= read_le16(stream
);
175 self
->mLibrary
= read_le32(stream
);
176 self
->mGenre
= read_le32(stream
);
177 self
->mMorphology
= read_le32(stream
);
180 typedef struct InstrumentHeader
{
184 static void InstrumentHeader_read(InstrumentHeader
*self
, Reader
*stream
)
186 if(READ(stream
, self
->mName
, sizeof(self
->mName
)) != sizeof(self
->mName
))
188 self
->mZoneIdx
= read_le16(stream
);
191 typedef struct SampleHeader
{
192 ALchar mName
[20]; // 20 bytes
198 ALubyte mOriginalKey
;
200 ALushort mSampleLink
;
201 ALushort mSampleType
;
203 static void SampleHeader_read(SampleHeader
*self
, Reader
*stream
)
205 if(READ(stream
, self
->mName
, sizeof(self
->mName
)) != sizeof(self
->mName
))
207 self
->mStart
= read_le32(stream
);
208 self
->mEnd
= read_le32(stream
);
209 self
->mStartloop
= read_le32(stream
);
210 self
->mEndloop
= read_le32(stream
);
211 self
->mSampleRate
= read_le32(stream
);
212 self
->mOriginalKey
= read_8(stream
);
213 self
->mCorrection
= read_8(stream
);
214 self
->mSampleLink
= read_le16(stream
);
215 self
->mSampleType
= read_le16(stream
);
219 typedef struct Soundfont
{
233 InstrumentHeader
*inst
;
247 static void Soundfont_Construct(Soundfont
*self
)
276 static void Soundfont_Destruct(Soundfont
*self
)
315 #define FOURCC(a,b,c,d) (((d)<<24) | ((c)<<16) | ((b)<<8) | (a))
316 #define FOURCCARGS(x) (char)((x)&0xff), (char)(((x)>>8)&0xff), (char)(((x)>>16)&0xff), (char)(((x)>>24)&0xff)
317 typedef struct RiffHdr
{
321 static void RiffHdr_read(RiffHdr
*self
, Reader
*stream
)
323 self
->mCode
= read_le32(stream
);
324 self
->mSize
= read_le32(stream
);
328 DECL_VECTOR(Generator
)
329 DECL_VECTOR(Modulator
)
331 typedef struct GenModList
{
332 vector_Generator gens
;
333 vector_Modulator mods
;
336 static void GenModList_Construct(GenModList
*self
)
338 VECTOR_INIT(self
->gens
);
339 VECTOR_INIT(self
->mods
);
342 static void GenModList_Destruct(GenModList
*self
)
344 VECTOR_DEINIT(self
->mods
);
345 VECTOR_DEINIT(self
->gens
);
348 static GenModList
GenModList_clone(const GenModList
*self
)
352 GenModList_Construct(&ret
);
354 VECTOR_INSERT(ret
.gens
, VECTOR_ITER_END(ret
.gens
),
355 VECTOR_ITER_BEGIN(self
->gens
), VECTOR_ITER_END(self
->gens
)
357 VECTOR_INSERT(ret
.mods
, VECTOR_ITER_END(ret
.mods
),
358 VECTOR_ITER_BEGIN(self
->mods
), VECTOR_ITER_END(self
->mods
)
364 static void GenModList_insertGen(GenModList
*self
, const Generator
*gen
, ALboolean ispreset
)
366 Generator
*i
= VECTOR_ITER_BEGIN(self
->gens
);
367 Generator
*end
= VECTOR_ITER_END(self
->gens
);
370 if(i
->mGenerator
== gen
->mGenerator
)
372 i
->mAmount
= gen
->mAmount
;
378 (gen
->mGenerator
== 0 || gen
->mGenerator
== 1 || gen
->mGenerator
== 2 ||
379 gen
->mGenerator
== 3 || gen
->mGenerator
== 4 || gen
->mGenerator
== 12 ||
380 gen
->mGenerator
== 45 || gen
->mGenerator
== 46 || gen
->mGenerator
== 47 ||
381 gen
->mGenerator
== 50 || gen
->mGenerator
== 54 || gen
->mGenerator
== 57 ||
382 gen
->mGenerator
== 58))
385 if(VECTOR_PUSH_BACK(self
->gens
, *gen
) == AL_FALSE
)
387 ERR("Failed to insert generator (from %d elements)\n", VECTOR_SIZE(self
->gens
));
391 static void GenModList_accumGen(GenModList
*self
, const Generator
*gen
)
393 Generator
*i
= VECTOR_ITER_BEGIN(self
->gens
);
394 Generator
*end
= VECTOR_ITER_END(self
->gens
);
397 if(i
->mGenerator
== gen
->mGenerator
)
399 if(gen
->mGenerator
== 43 || gen
->mGenerator
== 44)
401 /* Range generators accumulate by taking the intersection of
404 ALushort low
= maxu(i
->mAmount
&0x00ff, gen
->mAmount
&0x00ff);
405 ALushort high
= minu(i
->mAmount
&0xff00, gen
->mAmount
&0xff00);
406 i
->mAmount
= low
| high
;
409 i
->mAmount
+= gen
->mAmount
;
414 if(VECTOR_PUSH_BACK(self
->gens
, *gen
) == AL_FALSE
)
416 ERR("Failed to insert generator (from %d elements)\n", VECTOR_SIZE(self
->gens
));
419 if(gen
->mGenerator
< 60)
420 VECTOR_BACK(self
->gens
).mAmount
+= DefaultGenValue
[gen
->mGenerator
];
423 static void GenModList_insertMod(GenModList
*self
, const Modulator
*mod
)
425 Modulator
*i
= VECTOR_ITER_BEGIN(self
->mods
);
426 Modulator
*end
= VECTOR_ITER_END(self
->mods
);
429 if(i
->mDstOp
== mod
->mDstOp
&& i
->mSrcOp
== mod
->mSrcOp
&&
430 i
->mAmtSrcOp
== mod
->mAmtSrcOp
&& i
->mTransOp
== mod
->mTransOp
)
432 i
->mAmount
= mod
->mAmount
;
437 if(VECTOR_PUSH_BACK(self
->mods
, *mod
) == AL_FALSE
)
439 ERR("Failed to insert modulator (from %d elements)\n", VECTOR_SIZE(self
->mods
));
443 static void GenModList_accumMod(GenModList
*self
, const Modulator
*mod
)
445 Modulator
*i
= VECTOR_ITER_BEGIN(self
->mods
);
446 Modulator
*end
= VECTOR_ITER_END(self
->mods
);
449 if(i
->mDstOp
== mod
->mDstOp
&& i
->mSrcOp
== mod
->mSrcOp
&&
450 i
->mAmtSrcOp
== mod
->mAmtSrcOp
&& i
->mTransOp
== mod
->mTransOp
)
452 i
->mAmount
+= mod
->mAmount
;
457 if(VECTOR_PUSH_BACK(self
->mods
, *mod
) == AL_FALSE
)
459 ERR("Failed to insert modulator (from %d elements)\n", VECTOR_SIZE(self
->mods
));
463 if(mod
->mSrcOp
== 0x0502 && mod
->mDstOp
== 48 && mod
->mAmtSrcOp
== 0 && mod
->mTransOp
== 0)
464 VECTOR_BACK(self
->mods
).mAmount
+= 960;
465 else if(mod
->mSrcOp
== 0x0102 && mod
->mDstOp
== 8 && mod
->mAmtSrcOp
== 0 && mod
->mTransOp
== 0)
466 VECTOR_BACK(self
->mods
).mAmount
+= -2400;
467 else if(mod
->mSrcOp
== 0x000D && mod
->mDstOp
== 6 && mod
->mAmtSrcOp
== 0 && mod
->mTransOp
== 0)
468 VECTOR_BACK(self
->mods
).mAmount
+= 50;
469 else if(mod
->mSrcOp
== 0x0081 && mod
->mDstOp
== 6 && mod
->mAmtSrcOp
== 0 && mod
->mTransOp
== 0)
470 VECTOR_BACK(self
->mods
).mAmount
+= 50;
471 else if(mod
->mSrcOp
== 0x0582 && mod
->mDstOp
== 48 && mod
->mAmtSrcOp
== 0 && mod
->mTransOp
== 0)
472 VECTOR_BACK(self
->mods
).mAmount
+= 960;
473 else if(mod
->mSrcOp
== 0x028A && mod
->mDstOp
== 17 && mod
->mAmtSrcOp
== 0 && mod
->mTransOp
== 0)
474 VECTOR_BACK(self
->mods
).mAmount
+= 1000;
475 else if(mod
->mSrcOp
== 0x058B && mod
->mDstOp
== 48 && mod
->mAmtSrcOp
== 0 && mod
->mTransOp
== 0)
476 VECTOR_BACK(self
->mods
).mAmount
+= 960;
477 else if(mod
->mSrcOp
== 0x00DB && mod
->mDstOp
== 16 && mod
->mAmtSrcOp
== 0 && mod
->mTransOp
== 0)
478 VECTOR_BACK(self
->mods
).mAmount
+= 200;
479 else if(mod
->mSrcOp
== 0x00DD && mod
->mDstOp
== 15 && mod
->mAmtSrcOp
== 0 && mod
->mTransOp
== 0)
480 VECTOR_BACK(self
->mods
).mAmount
+= 200;
481 /*else if(mod->mSrcOp == 0x020E && mod->mDstOp == ?initialpitch? && mod->mAmtSrcOp == 0x0010 && mod->mTransOp == 0)
482 VECTOR_BACK(self->mods).mAmount += 12700;*/
486 #define ERROR_GOTO(lbl_, ...) do { \
491 static ALboolean
ensureFontSanity(const Soundfont
*sfont
)
495 for(i
= 0;i
< sfont
->phdr_size
-1;i
++)
497 if(sfont
->phdr
[i
].mZoneIdx
>= sfont
->pbag_size
)
499 WARN("Preset %d has invalid zone index %d (max: %d)\n", i
,
500 sfont
->phdr
[i
].mZoneIdx
, sfont
->pbag_size
);
503 if(sfont
->phdr
[i
+1].mZoneIdx
< sfont
->phdr
[i
].mZoneIdx
)
505 WARN("Preset %d has invalid zone index (%d does not follow %d)\n", i
+1,
506 sfont
->phdr
[i
+1].mZoneIdx
, sfont
->phdr
[i
].mZoneIdx
);
510 if(sfont
->phdr
[i
].mZoneIdx
>= sfont
->pbag_size
)
512 WARN("Preset %d has invalid zone index %d (max: %d)\n", i
,
513 sfont
->phdr
[i
].mZoneIdx
, sfont
->pbag_size
);
517 for(i
= 0;i
< sfont
->pbag_size
-1;i
++)
519 if(sfont
->pbag
[i
].mGenIdx
>= sfont
->pgen_size
)
521 WARN("Preset zone %d has invalid generator index %d (max: %d)\n", i
,
522 sfont
->pbag
[i
].mGenIdx
, sfont
->pgen_size
);
525 if(sfont
->pbag
[i
+1].mGenIdx
< sfont
->pbag
[i
].mGenIdx
)
527 WARN("Preset zone %d has invalid generator index (%d does not follow %d)\n", i
+1,
528 sfont
->pbag
[i
+1].mGenIdx
, sfont
->pbag
[i
].mGenIdx
);
531 if(sfont
->pbag
[i
].mModIdx
>= sfont
->pmod_size
)
533 WARN("Preset zone %d has invalid modulator index %d (max: %d)\n", i
,
534 sfont
->pbag
[i
].mModIdx
, sfont
->pmod_size
);
537 if(sfont
->pbag
[i
+1].mModIdx
< sfont
->pbag
[i
].mModIdx
)
539 WARN("Preset zone %d has invalid modulator index (%d does not follow %d)\n", i
+1,
540 sfont
->pbag
[i
+1].mModIdx
, sfont
->pbag
[i
].mModIdx
);
544 if(sfont
->pbag
[i
].mGenIdx
>= sfont
->pgen_size
)
546 WARN("Preset zone %d has invalid generator index %d (max: %d)\n", i
,
547 sfont
->pbag
[i
].mGenIdx
, sfont
->pgen_size
);
550 if(sfont
->pbag
[i
].mModIdx
>= sfont
->pmod_size
)
552 WARN("Preset zone %d has invalid modulator index %d (max: %d)\n", i
,
553 sfont
->pbag
[i
].mModIdx
, sfont
->pmod_size
);
558 for(i
= 0;i
< sfont
->inst_size
-1;i
++)
560 if(sfont
->inst
[i
].mZoneIdx
>= sfont
->ibag_size
)
562 WARN("Instrument %d has invalid zone index %d (max: %d)\n", i
,
563 sfont
->inst
[i
].mZoneIdx
, sfont
->ibag_size
);
566 if(sfont
->inst
[i
+1].mZoneIdx
< sfont
->inst
[i
].mZoneIdx
)
568 WARN("Instrument %d has invalid zone index (%d does not follow %d)\n", i
+1,
569 sfont
->inst
[i
+1].mZoneIdx
, sfont
->inst
[i
].mZoneIdx
);
573 if(sfont
->inst
[i
].mZoneIdx
>= sfont
->ibag_size
)
575 WARN("Instrument %d has invalid zone index %d (max: %d)\n", i
,
576 sfont
->inst
[i
].mZoneIdx
, sfont
->ibag_size
);
580 for(i
= 0;i
< sfont
->ibag_size
-1;i
++)
582 if(sfont
->ibag
[i
].mGenIdx
>= sfont
->igen_size
)
584 WARN("Instrument zone %d has invalid generator index %d (max: %d)\n", i
,
585 sfont
->ibag
[i
].mGenIdx
, sfont
->igen_size
);
588 if(sfont
->ibag
[i
+1].mGenIdx
< sfont
->ibag
[i
].mGenIdx
)
590 WARN("Instrument zone %d has invalid generator index (%d does not follow %d)\n", i
+1,
591 sfont
->ibag
[i
+1].mGenIdx
, sfont
->ibag
[i
].mGenIdx
);
594 if(sfont
->ibag
[i
].mModIdx
>= sfont
->imod_size
)
596 WARN("Instrument zone %d has invalid modulator index %d (max: %d)\n", i
,
597 sfont
->ibag
[i
].mModIdx
, sfont
->imod_size
);
600 if(sfont
->ibag
[i
+1].mModIdx
< sfont
->ibag
[i
].mModIdx
)
602 WARN("Instrument zone %d has invalid modulator index (%d does not follow %d)\n", i
+1,
603 sfont
->ibag
[i
+1].mModIdx
, sfont
->ibag
[i
].mModIdx
);
607 if(sfont
->ibag
[i
].mGenIdx
>= sfont
->igen_size
)
609 WARN("Instrument zone %d has invalid generator index %d (max: %d)\n", i
,
610 sfont
->ibag
[i
].mGenIdx
, sfont
->igen_size
);
613 if(sfont
->ibag
[i
].mModIdx
>= sfont
->imod_size
)
615 WARN("Instrument zone %d has invalid modulator index %d (max: %d)\n", i
,
616 sfont
->ibag
[i
].mModIdx
, sfont
->imod_size
);
621 for(i
= 0;i
< sfont
->shdr_size
-1;i
++)
623 if((sfont
->shdr
[i
].mSampleType
&0x8000) && sfont
->irom
== NULL
)
625 WARN("Sample header %d has ROM sample type without an irom sub-chunk\n", i
);
634 static ALboolean
checkZone(const GenModList
*zone
, const PresetHeader
*preset
, const InstrumentHeader
*inst
, const SampleHeader
*samp
)
636 Generator
*gen
= VECTOR_ITER_BEGIN(zone
->gens
);
637 Generator
*gen_end
= VECTOR_ITER_END(zone
->gens
);
638 for(;gen
!= gen_end
;gen
++)
640 if(gen
->mGenerator
== 43 || gen
->mGenerator
== 44)
642 int high
= gen
->mAmount
>>8;
643 int low
= gen
->mAmount
&0xff;
645 if(!(low
>= 0 && high
<= 127 && high
>= low
))
647 TRACE("Preset \"%s\", inst \"%s\", sample \"%s\": invalid %s range %d...%d\n",
648 preset
->mName
, inst
->mName
, samp
->mName
,
649 (gen
->mGenerator
== 43) ? "key" :
650 (gen
->mGenerator
== 44) ? "velocity" : "(unknown)",
660 static ALenum
getModSrcInput(int input
)
662 if(input
== 0) return AL_ONE_SOFT
;
663 if(input
== 2) return AL_NOTEON_VELOCITY_SOFT
;
664 if(input
== 3) return AL_NOTEON_KEY_SOFT
;
665 if(input
== 10) return AL_KEYPRESSURE_SOFT
;
666 if(input
== 13) return AL_CHANNELPRESSURE_SOFT
;
667 if(input
== 14) return AL_PITCHBEND_SOFT
;
668 if(input
== 16) return AL_PITCHBEND_SENSITIVITY_SOFT
;
672 if(input
> 0 && input
< 120 && !(input
== 6 || (input
>= 32 && input
<= 63) ||
673 (input
>= 98 && input
<= 101)))
677 ERR("Unhandled modulator source input: 0x%02x\n", input
);
681 static ALenum
getModSrcType(int type
)
683 if(type
== 0x0000) return AL_UNORM_SOFT
;
684 if(type
== 0x0100) return AL_UNORM_REV_SOFT
;
685 if(type
== 0x0200) return AL_SNORM_SOFT
;
686 if(type
== 0x0300) return AL_SNORM_REV_SOFT
;
687 ERR("Unhandled modulator source type: 0x%04x\n", type
);
691 static ALenum
getModSrcForm(int form
)
693 if(form
== 0x0000) return AL_LINEAR_SOFT
;
694 if(form
== 0x0400) return AL_CONCAVE_SOFT
;
695 if(form
== 0x0800) return AL_CONVEX_SOFT
;
696 if(form
== 0x0C00) return AL_SWITCH_SOFT
;
697 ERR("Unhandled modulator source form: 0x%04x\n", form
);
701 static ALenum
getModTransOp(int op
)
703 if(op
== 0) return AL_LINEAR_SOFT
;
704 if(op
== 2) return AL_ABSOLUTE_SOFT
;
705 ERR("Unhandled modulator transform op: 0x%04x\n", op
);
709 static ALenum
getLoopMode(int mode
)
711 if(mode
== 0) return AL_NONE
;
712 if(mode
== 1) return AL_LOOP_CONTINUOUS_SOFT
;
713 if(mode
== 3) return AL_LOOP_UNTIL_RELEASE_SOFT
;
714 ERR("Unhandled loop mode: %d\n", mode
);
718 static ALenum
getSampleType(int type
)
720 if(type
== 1) return AL_MONO_SOFT
;
721 if(type
== 2) return AL_RIGHT_SOFT
;
722 if(type
== 4) return AL_LEFT_SOFT
;
725 WARN("Sample type \"linked\" ignored; pretending mono\n");
728 ERR("Unhandled sample type: 0x%04x\n", type
);
732 static void fillZone(ALfontsound
*sound
, ALCcontext
*context
, const GenModList
*zone
)
734 static const ALenum Gen2Param
[60] = {
735 0, /* 0 - startAddrOffset */
736 0, /* 1 - endAddrOffset */
737 0, /* 2 - startloopAddrOffset */
738 0, /* 3 - endloopAddrOffset */
739 0, /* 4 - startAddrCoarseOffset */
740 AL_MOD_LFO_TO_PITCH_SOFT
, /* 5 - modLfoToPitch */
741 AL_VIBRATO_LFO_TO_PITCH_SOFT
, /* 6 - vibLfoToPitch */
742 AL_MOD_ENV_TO_PITCH_SOFT
, /* 7 - modEnvToPitch */
743 AL_FILTER_CUTOFF_SOFT
, /* 8 - initialFilterFc */
744 AL_FILTER_RESONANCE_SOFT
, /* 9 - initialFilterQ */
745 AL_MOD_LFO_TO_FILTER_CUTOFF_SOFT
, /* 10 - modLfoToFilterFc */
746 AL_MOD_ENV_TO_FILTER_CUTOFF_SOFT
, /* 11 - modEnvToFilterFc */
747 0, /* 12 - endAddrCoarseOffset */
748 AL_MOD_LFO_TO_VOLUME_SOFT
, /* 13 - modLfoToVolume */
750 AL_CHORUS_SEND_SOFT
, /* 15 - chorusEffectsSend */
751 AL_REVERB_SEND_SOFT
, /* 16 - reverbEffectsSend */
752 AL_PAN_SOFT
, /* 17 - pan */
756 AL_MOD_LFO_DELAY_SOFT
, /* 21 - delayModLFO */
757 AL_MOD_LFO_FREQUENCY_SOFT
, /* 22 - freqModLFO */
758 AL_VIBRATO_LFO_DELAY_SOFT
, /* 23 - delayVibLFO */
759 AL_VIBRATO_LFO_FREQUENCY_SOFT
, /* 24 - freqVibLFO */
760 AL_MOD_ENV_DELAYTIME_SOFT
, /* 25 - delayModEnv */
761 AL_MOD_ENV_ATTACKTIME_SOFT
, /* 26 - attackModEnv */
762 AL_MOD_ENV_HOLDTIME_SOFT
, /* 27 - holdModEnv */
763 AL_MOD_ENV_DECAYTIME_SOFT
, /* 28 - decayModEnv */
764 AL_MOD_ENV_SUSTAINVOLUME_SOFT
, /* 29 - sustainModEnv */
765 AL_MOD_ENV_RELEASETIME_SOFT
, /* 30 - releaseModEnv */
766 AL_MOD_ENV_KEY_TO_HOLDTIME_SOFT
, /* 31 - keynumToModEnvHold */
767 AL_MOD_ENV_KEY_TO_DECAYTIME_SOFT
, /* 32 - keynumToModEnvDecay */
768 AL_VOLUME_ENV_DELAYTIME_SOFT
, /* 33 - delayVolEnv */
769 AL_VOLUME_ENV_ATTACKTIME_SOFT
, /* 34 - attackVolEnv */
770 AL_VOLUME_ENV_HOLDTIME_SOFT
, /* 35 - holdVolEnv */
771 AL_VOLUME_ENV_DECAYTIME_SOFT
, /* 36 - decayVolEnv */
772 AL_VOLUME_ENV_SUSTAINVOLUME_SOFT
, /* 37 - sustainVolEnv */
773 AL_VOLUME_ENV_RELEASETIME_SOFT
, /* 38 - releaseVolEnv */
774 AL_VOLUME_ENV_KEY_TO_HOLDTIME_SOFT
, /* 39 - keynumToVolEnvHold */
775 AL_VOLUME_ENV_KEY_TO_DECAYTIME_SOFT
, /* 40 - keynumToVolEnvDecay */
778 AL_KEY_RANGE_SOFT
, /* 43 - keyRange */
779 AL_VELOCITY_RANGE_SOFT
, /* 44 - velRange */
780 0, /* 45 - startloopAddrCoarseOffset */
782 0, /* 47 - velocity */
783 AL_ATTENUATION_SOFT
, /* 48 - initialAttenuation */
785 0, /* 50 - endloopAddrCoarseOffset */
786 AL_TUNING_COARSE_SOFT
, /* 51 - corseTune */
787 AL_TUNING_FINE_SOFT
, /* 52 - fineTune */
789 AL_LOOP_MODE_SOFT
, /* 54 - sampleModes */
791 AL_TUNING_SCALE_SOFT
, /* 56 - scaleTuning */
792 AL_EXCLUSIVE_CLASS_SOFT
, /* 57 - exclusiveClass */
793 AL_BASE_KEY_SOFT
, /* 58 - overridingRootKey */
796 const Generator
*gen
, *gen_end
;
797 const Modulator
*mod
, *mod_end
;
799 mod
= VECTOR_ITER_BEGIN(zone
->mods
);
800 mod_end
= VECTOR_ITER_END(zone
->mods
);
801 for(;mod
!= mod_end
;mod
++)
803 ALenum src0in
= getModSrcInput(mod
->mSrcOp
&0xFF);
804 ALenum src0type
= getModSrcType(mod
->mSrcOp
&0x0300);
805 ALenum src0form
= getModSrcForm(mod
->mSrcOp
&0xFC00);
806 ALenum src1in
= getModSrcInput(mod
->mAmtSrcOp
&0xFF);
807 ALenum src1type
= getModSrcType(mod
->mAmtSrcOp
&0x0300);
808 ALenum src1form
= getModSrcForm(mod
->mAmtSrcOp
&0xFC00);
809 ALenum trans
= getModTransOp(mod
->mTransOp
);
810 ALenum dst
= (mod
->mDstOp
< 60) ? Gen2Param
[mod
->mDstOp
] : 0;
811 if(!dst
|| dst
== AL_KEY_RANGE_SOFT
|| dst
== AL_VELOCITY_RANGE_SOFT
||
812 dst
== AL_LOOP_MODE_SOFT
|| dst
== AL_EXCLUSIVE_CLASS_SOFT
||
813 dst
== AL_BASE_KEY_SOFT
)
814 ERR("Unhandled modulator destination: %d\n", mod
->mDstOp
);
815 else if(src0in
!= AL_INVALID
&& src0form
!= AL_INVALID
&& src0type
!= AL_INVALID
&&
816 src1in
!= AL_INVALID
&& src1form
!= AL_INVALID
&& src0type
!= AL_INVALID
&&
819 ALsizei idx
= (ALsizei
)(mod
- VECTOR_ITER_BEGIN(zone
->mods
));
820 ALfontsound_setModStagei(sound
, context
, idx
, AL_SOURCE0_INPUT_SOFT
, src0in
);
821 ALfontsound_setModStagei(sound
, context
, idx
, AL_SOURCE0_TYPE_SOFT
, src0type
);
822 ALfontsound_setModStagei(sound
, context
, idx
, AL_SOURCE0_FORM_SOFT
, src0form
);
823 ALfontsound_setModStagei(sound
, context
, idx
, AL_SOURCE1_INPUT_SOFT
, src1in
);
824 ALfontsound_setModStagei(sound
, context
, idx
, AL_SOURCE1_TYPE_SOFT
, src1type
);
825 ALfontsound_setModStagei(sound
, context
, idx
, AL_SOURCE1_FORM_SOFT
, src1form
);
826 ALfontsound_setModStagei(sound
, context
, idx
, AL_AMOUNT_SOFT
, mod
->mAmount
);
827 ALfontsound_setModStagei(sound
, context
, idx
, AL_TRANSFORM_OP_SOFT
, trans
);
828 ALfontsound_setModStagei(sound
, context
, idx
, AL_DESTINATION_SOFT
, dst
);
832 gen
= VECTOR_ITER_BEGIN(zone
->gens
);
833 gen_end
= VECTOR_ITER_END(zone
->gens
);
834 for(;gen
!= gen_end
;gen
++)
836 ALint value
= (ALshort
)gen
->mAmount
;
837 if(gen
->mGenerator
== 0)
838 sound
->Start
+= value
;
839 else if(gen
->mGenerator
== 1)
841 else if(gen
->mGenerator
== 2)
842 sound
->LoopStart
+= value
;
843 else if(gen
->mGenerator
== 3)
844 sound
->LoopEnd
+= value
;
845 else if(gen
->mGenerator
== 4)
846 sound
->Start
+= value
<<15;
847 else if(gen
->mGenerator
== 12)
848 sound
->End
+= value
<<15;
849 else if(gen
->mGenerator
== 45)
850 sound
->LoopStart
+= value
<<15;
851 else if(gen
->mGenerator
== 50)
852 sound
->LoopEnd
+= value
<<15;
853 else if(gen
->mGenerator
== 43)
855 sound
->MinKey
= mini((value
&0xff), 127);
856 sound
->MaxKey
= mini(((value
>>8)&0xff), 127);
858 else if(gen
->mGenerator
== 44)
860 sound
->MinVelocity
= mini((value
&0xff), 127);
861 sound
->MaxVelocity
= mini(((value
>>8)&0xff), 127);
866 if(gen
->mGenerator
< 60)
867 param
= Gen2Param
[gen
->mGenerator
];
870 if(param
== AL_BASE_KEY_SOFT
)
872 if(!(value
>= 0 && value
<= 127))
875 WARN("Invalid overridingRootKey generator value %d\n", value
);
879 if(param
== AL_FILTER_RESONANCE_SOFT
|| param
== AL_ATTENUATION_SOFT
)
880 value
= maxi(0, value
);
881 else if(param
== AL_CHORUS_SEND_SOFT
|| param
== AL_REVERB_SEND_SOFT
)
882 value
= clampi(value
, 0, 1000);
883 else if(param
== AL_LOOP_MODE_SOFT
)
884 value
= getLoopMode(value
);
885 ALfontsound_setPropi(sound
, context
, param
, value
);
887 else if(gen
->mGenerator
< 256)
889 static ALboolean warned
[256];
890 if(!warned
[gen
->mGenerator
])
892 warned
[gen
->mGenerator
] = AL_TRUE
;
893 ERR("Unhandled generator %d\n", gen
->mGenerator
);
900 static void processInstrument(ALfontsound
***sounds
, ALsizei
*sounds_size
, ALCcontext
*context
, ALbuffer
*buffer
, InstrumentHeader
*inst
, const PresetHeader
*preset
, const Soundfont
*sfont
, const GenModList
*pzone
)
902 const Generator
*gen
, *gen_end
;
903 const Modulator
*mod
, *mod_end
;
904 const Zone
*zone
, *zone_end
;
908 if((inst
+1)->mZoneIdx
== inst
->mZoneIdx
)
909 ERR("Instrument with no zones!");
911 GenModList_Construct(&gzone
);
912 zone
= sfont
->ibag
+ inst
->mZoneIdx
;
913 zone_end
= sfont
->ibag
+ (inst
+1)->mZoneIdx
;
914 if(zone_end
-zone
> 1)
916 gen
= sfont
->igen
+ zone
->mGenIdx
;
917 gen_end
= sfont
->igen
+ (zone
+1)->mGenIdx
;
919 // If no generators, or last generator is not a sample, this is a global zone
920 for(;gen
!= gen_end
;gen
++)
922 if(gen
->mGenerator
== 53)
928 gen
= sfont
->igen
+ zone
->mGenIdx
;
929 gen_end
= sfont
->igen
+ (zone
+1)->mGenIdx
;
930 for(;gen
!= gen_end
;gen
++)
931 GenModList_insertGen(&gzone
, gen
, AL_FALSE
);
933 mod
= sfont
->imod
+ zone
->mModIdx
;
934 mod_end
= sfont
->imod
+ (zone
+1)->mModIdx
;
935 for(;mod
!= mod_end
;mod
++)
936 GenModList_insertMod(&gzone
, mod
);
942 temp
= realloc(*sounds
, (zone_end
-zone
+ *sounds_size
)*sizeof((*sounds
)[0]));
945 ERR("Failed reallocating fontsound storage to %d elements (from %d)\n",
946 (ALsizei
)(zone_end
-zone
) + *sounds_size
, *sounds_size
);
950 for(;zone
!= zone_end
;zone
++)
952 GenModList lzone
= GenModList_clone(&gzone
);
953 mod
= sfont
->imod
+ zone
->mModIdx
;
954 mod_end
= sfont
->imod
+ (zone
+1)->mModIdx
;
955 for(;mod
!= mod_end
;mod
++)
956 GenModList_insertMod(&lzone
, mod
);
958 gen
= sfont
->igen
+ zone
->mGenIdx
;
959 gen_end
= sfont
->igen
+ (zone
+1)->mGenIdx
;
960 for(;gen
!= gen_end
;gen
++)
962 if(gen
->mGenerator
== 53)
964 const SampleHeader
*samp
;
967 if(gen
->mAmount
>= sfont
->shdr_size
-1)
969 ERR("Generator %ld has invalid sample ID (%d of %d)\n",
970 (long)(gen
-sfont
->igen
), gen
->mAmount
, sfont
->shdr_size
-1);
973 samp
= &sfont
->shdr
[gen
->mAmount
];
975 gen
= VECTOR_ITER_BEGIN(pzone
->gens
);
976 gen_end
= VECTOR_ITER_END(pzone
->gens
);
977 for(;gen
!= gen_end
;gen
++)
978 GenModList_accumGen(&lzone
, gen
);
980 mod
= VECTOR_ITER_BEGIN(pzone
->mods
);
981 mod_end
= VECTOR_ITER_END(pzone
->mods
);
982 for(;mod
!= mod_end
;mod
++)
983 GenModList_accumMod(&lzone
, mod
);
985 if(!checkZone(&lzone
, preset
, inst
, samp
))
987 /* Ignore ROM samples for now. */
988 if((samp
->mSampleType
&0x8000))
991 sound
= NewFontsound(context
);
992 (*sounds
)[(*sounds_size
)++] = sound
;
993 ALfontsound_setPropi(sound
, context
, AL_BUFFER
, buffer
->id
);
994 ALfontsound_setPropi(sound
, context
, AL_SAMPLE_START_SOFT
, samp
->mStart
);
995 ALfontsound_setPropi(sound
, context
, AL_SAMPLE_END_SOFT
, samp
->mEnd
);
996 ALfontsound_setPropi(sound
, context
, AL_SAMPLE_LOOP_START_SOFT
, samp
->mStartloop
);
997 ALfontsound_setPropi(sound
, context
, AL_SAMPLE_LOOP_END_SOFT
, samp
->mEndloop
);
998 ALfontsound_setPropi(sound
, context
, AL_SAMPLE_RATE_SOFT
, samp
->mSampleRate
);
999 ALfontsound_setPropi(sound
, context
, AL_BASE_KEY_SOFT
, (samp
->mOriginalKey
<= 127) ? samp
->mOriginalKey
: 60);
1000 ALfontsound_setPropi(sound
, context
, AL_KEY_CORRECTION_SOFT
, samp
->mCorrection
);
1001 ALfontsound_setPropi(sound
, context
, AL_SAMPLE_TYPE_SOFT
, getSampleType(samp
->mSampleType
&0x7fff));
1002 fillZone(sound
, context
, &lzone
);
1006 GenModList_insertGen(&lzone
, gen
, AL_FALSE
);
1009 GenModList_Destruct(&lzone
);
1012 GenModList_Destruct(&gzone
);
1015 ALboolean
loadSf2(Reader
*stream
, ALsoundfont
*soundfont
, ALCcontext
*context
)
1017 ALsfpreset
**presets
= NULL
;
1018 ALsizei presets_size
= 0;
1019 ALbuffer
*buffer
= NULL
;
1026 Soundfont_Construct(&sfont
);
1028 RiffHdr_read(&riff
, stream
);
1029 if(riff
.mCode
!= FOURCC('R','I','F','F'))
1030 ERROR_GOTO(error
, "Invalid Format, expected RIFF got '%c%c%c%c'\n", FOURCCARGS(riff
.mCode
));
1031 if((ltype
=read_le32(stream
)) != FOURCC('s','f','b','k'))
1032 ERROR_GOTO(error
, "Invalid Format, expected sfbk got '%c%c%c%c'\n", FOURCCARGS(ltype
));
1034 if(READERR(stream
) != 0)
1035 ERROR_GOTO(error
, "Error reading file header\n");
1037 RiffHdr_read(&list
, stream
);
1038 if(list
.mCode
!= FOURCC('L','I','S','T'))
1039 ERROR_GOTO(error
, "Invalid Format, expected LIST (INFO) got '%c%c%c%c'\n", FOURCCARGS(list
.mCode
));
1040 if((ltype
=read_le32(stream
)) != FOURCC('I','N','F','O'))
1041 ERROR_GOTO(error
, "Invalid Format, expected INFO got '%c%c%c%c'\n", FOURCCARGS(ltype
));
1043 while(list
.mSize
> 0 && !READERR(stream
))
1047 RiffHdr_read(&info
, stream
);
1049 if(info
.mCode
== FOURCC('i','f','i','l'))
1052 ERR("Invalid ifil chunk size: %d\n", info
.mSize
);
1055 ALushort major
= read_le16(stream
);
1056 ALushort minor
= read_le16(stream
);
1062 ERROR_GOTO(error
, "Unsupported SF2 format version: %d.%02d\n", major
, minor
);
1063 TRACE("SF2 format version: %d.%02d\n", major
, minor
);
1065 sfont
.ifil
= (major
<<16) | minor
;
1068 else if(info
.mCode
== FOURCC('i','r','o','m'))
1070 if(info
.mSize
== 0 || (info
.mSize
&1))
1071 ERR("Invalid irom size: %d\n", info
.mSize
);
1075 sfont
.irom
= calloc(1, info
.mSize
+1);
1076 READ(stream
, sfont
.irom
, info
.mSize
);
1078 list
.mSize
-= info
.mSize
;
1079 info
.mSize
-= info
.mSize
;
1081 TRACE("SF2 ROM ID: %s\n", sfont
.irom
);
1085 TRACE("Skipping INFO sub-chunk '%c%c%c%c' (%u bytes)\n", FOURCCARGS(info
.mCode
), info
.mSize
);
1086 list
.mSize
-= info
.mSize
;
1087 skip(stream
, info
.mSize
);
1090 if(READERR(stream
) != 0)
1091 ERROR_GOTO(error
, "Error reading INFO chunk\n");
1093 ERROR_GOTO(error
, "Missing ifil sub-chunk\n");
1095 RiffHdr_read(&list
, stream
);
1096 if(list
.mCode
!= FOURCC('L','I','S','T'))
1097 ERROR_GOTO(error
, "Invalid Format, expected LIST (sdta) got '%c%c%c%c'\n", FOURCCARGS(list
.mCode
));
1098 if((ltype
=read_le32(stream
)) != FOURCC('s','d','t','a'))
1099 ERROR_GOTO(error
, "Invalid Format, expected sdta got '%c%c%c%c'\n", FOURCCARGS(ltype
));
1106 RiffHdr_read(&smpl
, stream
);
1107 if(smpl
.mCode
!= FOURCC('s','m','p','l'))
1108 ERROR_GOTO(error
, "Invalid Format, expected smpl got '%c%c%c%c'\n", FOURCCARGS(smpl
.mCode
));
1111 if(smpl
.mSize
> list
.mSize
)
1112 ERROR_GOTO(error
, "Invalid Format, sample chunk size mismatch\n");
1114 buffer
= NewBuffer(context
);
1116 SET_ERROR_AND_GOTO(context
, AL_OUT_OF_MEMORY
, error
);
1117 /* Sample rate it unimportant, the individual fontsounds will specify it. */
1118 if((err
=LoadData(buffer
, 22050, AL_MONO16_SOFT
, smpl
.mSize
/2, UserFmtMono
, UserFmtShort
, NULL
, 1, AL_FALSE
)) != AL_NO_ERROR
)
1119 SET_ERROR_AND_GOTO(context
, err
, error
);
1122 if(IS_LITTLE_ENDIAN
)
1123 READ(stream
, ptr
, smpl
.mSize
);
1127 while(total
< smpl
.mSize
)
1130 ALuint todo
= minu(smpl
.mSize
-total
, sizeof(buf
));
1133 READ(stream
, buf
, todo
);
1134 for(i
= 0;i
< todo
;i
++)
1135 ptr
[total
+i
] = buf
[i
^1];
1140 list
.mSize
-= smpl
.mSize
;
1142 skip(stream
, list
.mSize
);
1145 if(READERR(stream
) != 0)
1146 ERROR_GOTO(error
, "Error reading sdta chunk\n");
1148 RiffHdr_read(&list
, stream
);
1149 if(list
.mCode
!= FOURCC('L','I','S','T'))
1150 ERROR_GOTO(error
, "Invalid Format, expected LIST (pdta) got '%c%c%c%c'\n", FOURCCARGS(list
.mCode
));
1151 if((ltype
=read_le32(stream
)) != FOURCC('p','d','t','a'))
1152 ERROR_GOTO(error
, "Invalid Format, expected pdta got '%c%c%c%c'\n", FOURCCARGS(ltype
));
1155 RiffHdr_read(&list
, stream
);
1156 if(list
.mCode
!= FOURCC('p','h','d','r'))
1157 ERROR_GOTO(error
, "Invalid Format, expected phdr got '%c%c%c%c'\n", FOURCCARGS(list
.mCode
));
1158 if((list
.mSize
%38) != 0 || list
.mSize
== 0)
1159 ERROR_GOTO(error
, "Invalid Format, bad phdr size: %u\n", list
.mSize
);
1160 sfont
.phdr_size
= list
.mSize
/38;
1161 sfont
.phdr
= calloc(sfont
.phdr_size
, sizeof(sfont
.phdr
[0]));
1162 for(i
= 0;i
< sfont
.phdr_size
;i
++)
1163 PresetHeader_read(&sfont
.phdr
[i
], stream
);
1165 RiffHdr_read(&list
, stream
);
1166 if(list
.mCode
!= FOURCC('p','b','a','g'))
1167 ERROR_GOTO(error
, "Invalid Format, expected pbag got '%c%c%c%c'\n", FOURCCARGS(list
.mCode
));
1168 if((list
.mSize
%4) != 0 || list
.mSize
== 0)
1169 ERROR_GOTO(error
, "Invalid Format, bad pbag size: %u\n", list
.mSize
);
1170 sfont
.pbag_size
= list
.mSize
/4;
1171 sfont
.pbag
= calloc(sfont
.pbag_size
, sizeof(sfont
.pbag
[0]));
1172 for(i
= 0;i
< sfont
.pbag_size
;i
++)
1173 Zone_read(&sfont
.pbag
[i
], stream
);
1175 RiffHdr_read(&list
, stream
);
1176 if(list
.mCode
!= FOURCC('p','m','o','d'))
1177 ERROR_GOTO(error
, "Invalid Format, expected pmod got '%c%c%c%c'\n", FOURCCARGS(list
.mCode
));
1178 if((list
.mSize
%10) != 0 || list
.mSize
== 0)
1179 ERROR_GOTO(error
, "Invalid Format, bad pmod size: %u\n", list
.mSize
);
1180 sfont
.pmod_size
= list
.mSize
/10;
1181 sfont
.pmod
= calloc(sfont
.pmod_size
, sizeof(sfont
.pmod
[0]));
1182 for(i
= 0;i
< sfont
.pmod_size
;i
++)
1183 Modulator_read(&sfont
.pmod
[i
], stream
);
1185 RiffHdr_read(&list
, stream
);
1186 if(list
.mCode
!= FOURCC('p','g','e','n'))
1187 ERROR_GOTO(error
, "Invalid Format, expected pgen got '%c%c%c%c'\n", FOURCCARGS(list
.mCode
));
1188 if((list
.mSize
%4) != 0 || list
.mSize
== 0)
1189 ERROR_GOTO(error
, "Invalid Format, bad pgen size: %u\n", list
.mSize
);
1190 sfont
.pgen_size
= list
.mSize
/4;
1191 sfont
.pgen
= calloc(sfont
.pgen_size
, sizeof(sfont
.pgen
[0]));
1192 for(i
= 0;i
< sfont
.pgen_size
;i
++)
1193 Generator_read(&sfont
.pgen
[i
], stream
);
1196 RiffHdr_read(&list
, stream
);
1197 if(list
.mCode
!= FOURCC('i','n','s','t'))
1198 ERROR_GOTO(error
, "Invalid Format, expected inst got '%c%c%c%c'\n", FOURCCARGS(list
.mCode
));
1199 if((list
.mSize
%22) != 0 || list
.mSize
== 0)
1200 ERROR_GOTO(error
, "Invalid Format, bad inst size: %u\n", list
.mSize
);
1201 sfont
.inst_size
= list
.mSize
/22;
1202 sfont
.inst
= calloc(sfont
.inst_size
, sizeof(sfont
.inst
[0]));
1203 for(i
= 0;i
< sfont
.inst_size
;i
++)
1204 InstrumentHeader_read(&sfont
.inst
[i
], stream
);
1206 RiffHdr_read(&list
, stream
);
1207 if(list
.mCode
!= FOURCC('i','b','a','g'))
1208 ERROR_GOTO(error
, "Invalid Format, expected ibag got '%c%c%c%c'\n", FOURCCARGS(list
.mCode
));
1209 if((list
.mSize
%4) != 0 || list
.mSize
== 0)
1210 ERROR_GOTO(error
, "Invalid Format, bad ibag size: %u\n", list
.mSize
);
1211 sfont
.ibag_size
= list
.mSize
/4;
1212 sfont
.ibag
= calloc(sfont
.ibag_size
, sizeof(sfont
.ibag
[0]));
1213 for(i
= 0;i
< sfont
.ibag_size
;i
++)
1214 Zone_read(&sfont
.ibag
[i
], stream
);
1216 RiffHdr_read(&list
, stream
);
1217 if(list
.mCode
!= FOURCC('i','m','o','d'))
1218 ERROR_GOTO(error
, "Invalid Format, expected imod got '%c%c%c%c'\n", FOURCCARGS(list
.mCode
));
1219 if((list
.mSize
%10) != 0 || list
.mSize
== 0)
1220 ERROR_GOTO(error
, "Invalid Format, bad imod size: %u\n", list
.mSize
);
1221 sfont
.imod_size
= list
.mSize
/10;
1222 sfont
.imod
= calloc(sfont
.imod_size
, sizeof(sfont
.imod
[0]));
1223 for(i
= 0;i
< sfont
.imod_size
;i
++)
1224 Modulator_read(&sfont
.imod
[i
], stream
);
1226 RiffHdr_read(&list
, stream
);
1227 if(list
.mCode
!= FOURCC('i','g','e','n'))
1228 ERROR_GOTO(error
, "Invalid Format, expected igen got '%c%c%c%c'\n", FOURCCARGS(list
.mCode
));
1229 if((list
.mSize
%4) != 0 || list
.mSize
== 0)
1230 ERROR_GOTO(error
, "Invalid Format, bad igen size: %u\n", list
.mSize
);
1231 sfont
.igen_size
= list
.mSize
/4;
1232 sfont
.igen
= calloc(sfont
.igen_size
, sizeof(sfont
.igen
[0]));
1233 for(i
= 0;i
< sfont
.igen_size
;i
++)
1234 Generator_read(&sfont
.igen
[i
], stream
);
1237 RiffHdr_read(&list
, stream
);
1238 if(list
.mCode
!= FOURCC('s','h','d','r'))
1239 ERROR_GOTO(error
, "Invalid Format, expected shdr got '%c%c%c%c'\n", FOURCCARGS(list
.mCode
));
1240 if((list
.mSize
%46) != 0 || list
.mSize
== 0)
1241 ERROR_GOTO(error
, "Invalid Format, bad shdr size: %u\n", list
.mSize
);
1242 sfont
.shdr_size
= list
.mSize
/46;
1243 sfont
.shdr
= calloc(sfont
.shdr_size
, sizeof(sfont
.shdr
[0]));
1244 for(i
= 0;i
< sfont
.shdr_size
;i
++)
1245 SampleHeader_read(&sfont
.shdr
[i
], stream
);
1247 if(READERR(stream
) != 0)
1248 ERROR_GOTO(error
, "Error reading pdta chunk\n");
1250 if(!ensureFontSanity(&sfont
))
1253 presets
= calloc(1, (sfont
.phdr_size
-1)*sizeof(presets
[0]));
1255 ERROR_GOTO(error
, "Error allocating presets\n");
1257 for(i
= 0;i
< sfont
.phdr_size
-1;i
++)
1259 const Generator
*gen
, *gen_end
;
1260 const Modulator
*mod
, *mod_end
;
1261 const Zone
*zone
, *zone_end
;
1262 ALfontsound
**sounds
= NULL
;
1263 ALsizei sounds_size
= 0;
1266 if(sfont
.phdr
[i
+1].mZoneIdx
== sfont
.phdr
[i
].mZoneIdx
)
1269 GenModList_Construct(&gzone
);
1270 zone
= sfont
.pbag
+ sfont
.phdr
[i
].mZoneIdx
;
1271 zone_end
= sfont
.pbag
+ sfont
.phdr
[i
+1].mZoneIdx
;
1272 if(zone_end
-zone
> 1)
1274 gen
= sfont
.pgen
+ zone
->mGenIdx
;
1275 gen_end
= sfont
.pgen
+ (zone
+1)->mGenIdx
;
1277 // If no generators, or last generator is not an instrument, this is a global zone
1278 for(;gen
!= gen_end
;gen
++)
1280 if(gen
->mGenerator
== 41)
1286 gen
= sfont
.pgen
+ zone
->mGenIdx
;
1287 gen_end
= sfont
.pgen
+ (zone
+1)->mGenIdx
;
1288 for(;gen
!= gen_end
;gen
++)
1289 GenModList_insertGen(&gzone
, gen
, AL_TRUE
);
1291 mod
= sfont
.pmod
+ zone
->mModIdx
;
1292 mod_end
= sfont
.pmod
+ (zone
+1)->mModIdx
;
1293 for(;mod
!= mod_end
;mod
++)
1294 GenModList_insertMod(&gzone
, mod
);
1300 for(;zone
!= zone_end
;zone
++)
1302 GenModList lzone
= GenModList_clone(&gzone
);
1304 mod
= sfont
.pmod
+ zone
->mModIdx
;
1305 mod_end
= sfont
.pmod
+ (zone
+1)->mModIdx
;
1306 for(;mod
!= mod_end
;mod
++)
1307 GenModList_insertMod(&lzone
, mod
);
1309 gen
= sfont
.pgen
+ zone
->mGenIdx
;
1310 gen_end
= sfont
.pgen
+ (zone
+1)->mGenIdx
;
1311 for(;gen
!= gen_end
;gen
++)
1313 if(gen
->mGenerator
== 41)
1315 if(gen
->mAmount
>= sfont
.inst_size
-1)
1316 ERR("Generator %ld has invalid instrument ID (%d of %d)\n",
1317 (long)(gen
-sfont
.pgen
), gen
->mAmount
, sfont
.inst_size
-1);
1320 &sounds
, &sounds_size
, context
, buffer
, &sfont
.inst
[gen
->mAmount
],
1321 &sfont
.phdr
[i
], &sfont
, &lzone
1325 GenModList_insertGen(&lzone
, gen
, AL_TRUE
);
1327 GenModList_Destruct(&lzone
);
1334 presets
[presets_size
] = NewPreset(context
);
1335 presets
[presets_size
]->Preset
= sfont
.phdr
[i
].mPreset
;
1336 presets
[presets_size
]->Bank
= sfont
.phdr
[i
].mBank
;
1338 for(j
= 0;j
< sounds_size
;j
++)
1339 IncrementRef(&sounds
[j
]->ref
);
1340 sounds
= ExchangePtr((XchgPtr
*)&presets
[presets_size
]->Sounds
, sounds
);
1341 ExchangeInt(&presets
[presets_size
]->NumSounds
, sounds_size
);
1346 GenModList_Destruct(&gzone
);
1349 for(i
= 0;i
< presets_size
;i
++)
1350 IncrementRef(&presets
[i
]->ref
);
1351 presets
= ExchangePtr((XchgPtr
*)&soundfont
->Presets
, presets
);
1352 ExchangeInt(&soundfont
->NumPresets
, presets_size
);
1356 Soundfont_Destruct(&sfont
);
1357 /* If the buffer ends up unused, delete it. */
1358 if(ReadRef(&buffer
->ref
) == 0)
1359 DeleteBuffer(context
->Device
, buffer
->id
);
1366 ALCdevice
*device
= context
->Device
;
1367 for(i
= 0;i
< presets_size
;i
++)
1368 DeletePreset(presets
[i
], device
);
1372 Soundfont_Destruct(&sfont
);
1374 DeleteBuffer(context
->Device
, buffer
->id
);