Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
MorsGames
GitHub Repository: MorsGames/sm64plus
Path: blob/master/src/audio/heap.c
7857 views
1
#include <ultra64.h>
2
3
#include "heap.h"
4
#include "data.h"
5
#include "load.h"
6
#include "synthesis.h"
7
#include "seqplayer.h"
8
#include "effects.h"
9
10
#define ALIGN16(val) (((val) + 0xF) & ~0xF)
11
12
struct PoolSplit {
13
u32 wantSeq;
14
u32 wantBank;
15
u32 wantUnused;
16
u32 wantCustom;
17
}; // size = 0x10
18
19
struct PoolSplit2 {
20
u32 wantPersistent;
21
u32 wantTemporary;
22
}; // size = 0x8
23
24
#if defined(VERSION_JP) || defined(VERSION_US)
25
s16 gVolume;
26
s8 gReverbDownsampleRate;
27
u8 sReverbDownsampleRateLog; // never read
28
#endif
29
30
struct SoundAllocPool gAudioSessionPool;
31
struct SoundAllocPool gAudioInitPool;
32
struct SoundAllocPool gNotesAndBuffersPool;
33
u8 sAudioHeapPad[0x20]; // probably two unused pools
34
struct SoundAllocPool gSeqAndBankPool;
35
struct SoundAllocPool gPersistentCommonPool;
36
struct SoundAllocPool gTemporaryCommonPool;
37
38
struct SoundMultiPool gSeqLoadedPool;
39
struct SoundMultiPool gBankLoadedPool;
40
struct SoundMultiPool gUnusedLoadedPool;
41
42
#ifdef VERSION_SH
43
struct Unk1Pool gUnkPool1;
44
struct UnkPool gUnkPool2;
45
struct UnkPool gUnkPool3;
46
#endif
47
48
struct PoolSplit sSessionPoolSplit;
49
struct PoolSplit2 sSeqAndBankPoolSplit;
50
struct PoolSplit sPersistentCommonPoolSplit;
51
struct PoolSplit sTemporaryCommonPoolSplit;
52
53
#ifdef VERSION_SH
54
u8 gUnkLoadStatus[0x40];
55
#endif
56
u8 gBankLoadStatus[0x40];
57
u8 gSeqLoadStatus[0x100];
58
59
#if defined(VERSION_EU) || defined(VERSION_SH)
60
volatile u8 gAudioResetStatus;
61
u8 gAudioResetPresetIdToLoad;
62
s32 gAudioResetFadeOutFramesLeft;
63
#endif
64
65
u8 gAudioUnusedBuffer[0x1000];
66
67
extern s32 gMaxAudioCmds;
68
69
#ifdef VERSION_SH
70
void *get_bank_or_seq_inner(s32 poolIdx, s32 arg1, s32 bankId);
71
struct UnkEntry *func_sh_802f1ec4(u32 size);
72
void func_sh_802f2158(struct UnkEntry *entry);
73
struct UnkEntry *unk_pool2_alloc(u32 size);
74
void func_sh_802F2320(struct UnkEntry *entry, struct AudioBankSample *sample);
75
void func_sh_802f23ec(void);
76
77
void unk_pools_init(u32 size1, u32 size2);
78
#endif
79
80
#if defined(VERSION_EU)
81
/**
82
* Assuming 'k' in [9, 24],
83
* Computes a newton's method step for f(x) = x^k - d
84
*/
85
f64 root_newton_step(f64 x, s32 k, f64 d)
86
{
87
f64 deg2 = x * x;
88
f64 deg4 = deg2 * deg2;
89
f64 deg8 = deg4 * deg4;
90
s32 degree = k - 9;
91
f64 fx;
92
93
f64 deriv = deg8;
94
if (degree & 1) {
95
deriv *= x;
96
}
97
if (degree & 2) {
98
deriv *= deg2;
99
}
100
if (degree & 4) {
101
deriv *= deg4;
102
}
103
if (degree & 8) {
104
deriv *= deg8;
105
}
106
fx = deriv * x - d;
107
deriv = k * deriv;
108
return x - fx / deriv;
109
}
110
111
/**
112
* Assuming 'k' in [9, 24],
113
* Computes d ^ (1/k)
114
*
115
* @return the root, or 1.0 if d is 0
116
*/
117
f64 kth_root(f64 d, s32 k) {
118
f64 root = 1.5;
119
f64 next;
120
f64 diff;
121
s32 i;
122
if (d == 0.0) {
123
root = 1.0;
124
} else {
125
for (i = 0; i < 64; i++) {
126
if (1) {
127
}
128
next = root_newton_step(root, k, d);
129
diff = next - root;
130
131
if (diff < 0) {
132
diff = -diff;
133
}
134
135
if (diff < 1e-07) {
136
root = next;
137
break;
138
} else {
139
root = next;
140
}
141
}
142
}
143
144
return root;
145
}
146
147
void build_vol_rampings_table(s32 UNUSED unused, s32 len) {
148
s32 i;
149
s32 step;
150
s32 d;
151
s32 k = len / 8;
152
153
for (step = 0, i = 0; i < 0x400; step += 32, i++) {
154
d = step;
155
if (step == 0) {
156
d = 1;
157
}
158
159
gLeftVolRampings[0][i] = kth_root( d, k - 1);
160
gRightVolRampings[0][i] = kth_root(1.0 / d, k - 1) * 65536.0;
161
gLeftVolRampings[1][i] = kth_root( d, k);
162
gRightVolRampings[1][i] = kth_root(1.0 / d, k) * 65536.0;
163
gLeftVolRampings[2][i] = kth_root( d, k + 1);
164
gRightVolRampings[2][i] = kth_root(1.0 / d, k + 1) * 65536.0;
165
}
166
}
167
#endif
168
169
void reset_bank_and_seq_load_status(void) {
170
s32 i;
171
172
#ifdef VERSION_SH
173
for (i = 0; i < 64; i++) {
174
if (gBankLoadStatus[i] != SOUND_LOAD_STATUS_5) {
175
gBankLoadStatus[i] = SOUND_LOAD_STATUS_NOT_LOADED;
176
}
177
}
178
179
for (i = 0; i < 64; i++) {
180
if (gUnkLoadStatus[i] != SOUND_LOAD_STATUS_5) {
181
gUnkLoadStatus[i] = SOUND_LOAD_STATUS_NOT_LOADED;
182
}
183
}
184
185
for (i = 0; i < 256; i++) {
186
if (gSeqLoadStatus[i] != SOUND_LOAD_STATUS_5) {
187
gSeqLoadStatus[i] = SOUND_LOAD_STATUS_NOT_LOADED;
188
}
189
}
190
#else
191
for (i = 0; i < 64; i++) {
192
gBankLoadStatus[i] = SOUND_LOAD_STATUS_NOT_LOADED;
193
}
194
195
for (i = 0; i < 256; i++) {
196
gSeqLoadStatus[i] = SOUND_LOAD_STATUS_NOT_LOADED;
197
}
198
#endif
199
}
200
201
void discard_bank(s32 bankId) {
202
s32 i;
203
204
for (i = 0; i < gMaxSimultaneousNotes; i++) {
205
struct Note *note = &gNotes[i];
206
207
#if defined(VERSION_EU)
208
if (note->noteSubEu.bankId == bankId) {
209
#else
210
if (note->bankId == bankId) {
211
#endif
212
// (These prints are unclear. Arguments are picked semi-randomly.)
213
eu_stubbed_printf_1("Warning:Kill Note %x \n", i);
214
#ifdef VERSION_SH
215
if (note->unkSH34 == NOTE_PRIORITY_DISABLED && note->priority) {
216
#else
217
if (note->priority >= NOTE_PRIORITY_MIN) {
218
#endif
219
eu_stubbed_printf_3("Kill Voice %d (ID %d) %d\n", note->waveId,
220
bankId, note->priority);
221
eu_stubbed_printf_0("Warning: Running Sequence's data disappear!\n");
222
note->parentLayer->enabled = FALSE; // is 0x48, should be 0x44
223
note->parentLayer->finished = TRUE;
224
}
225
note_disable(note);
226
audio_list_remove(&note->listItem);
227
audio_list_push_back(&gNoteFreeLists.disabled, &note->listItem);
228
}
229
}
230
}
231
232
void discard_sequence(s32 seqId) {
233
s32 i;
234
235
for (i = 0; i < SEQUENCE_PLAYERS; i++) {
236
if (gSequencePlayers[i].enabled && gSequencePlayers[i].seqId == seqId) {
237
#if defined(VERSION_EU) || defined(VERSION_SH)
238
sequence_player_disable(&gSequencePlayers[i]);
239
#else
240
sequence_player_disable(gSequencePlayers + i);
241
#endif
242
}
243
}
244
}
245
246
void *soundAlloc(struct SoundAllocPool *pool, u32 size) {
247
#if defined(VERSION_EU) || defined(VERSION_SH)
248
u8 *start;
249
u8 *pos;
250
u32 alignedSize = ALIGN16(size);
251
252
start = pool->cur;
253
if (start + alignedSize <= pool->start + pool->size) {
254
pool->cur += alignedSize;
255
for (pos = start; pos < pool->cur; pos++) {
256
*pos = 0;
257
}
258
} else {
259
eu_stubbed_printf_1("Heap OverFlow : Not Allocate %d!\n", size);
260
return NULL;
261
}
262
#ifdef VERSION_SH
263
pool->numAllocatedEntries++;
264
#endif
265
return start;
266
#else
267
u8 *start;
268
s32 last;
269
s32 i;
270
271
if ((pool->cur + ALIGN16(size) <= pool->size + pool->start)) {
272
start = pool->cur;
273
pool->cur += ALIGN16(size);
274
last = pool->cur - start - 1;
275
for (i = 0; i <= last; i++) {
276
start[i] = 0;
277
}
278
} else {
279
return NULL;
280
}
281
return start;
282
#endif
283
}
284
285
#ifdef VERSION_SH
286
void *sound_alloc_uninitialized(struct SoundAllocPool *pool, u32 size) {
287
u8 *start;
288
u32 alignedSize = ALIGN16(size);
289
290
start = pool->cur;
291
if (start + alignedSize <= pool->start + pool->size) {
292
pool->cur += alignedSize;
293
} else {
294
return NULL;
295
}
296
297
pool->numAllocatedEntries++;
298
return start;
299
}
300
#endif
301
302
void sound_alloc_pool_init(struct SoundAllocPool *pool, void *memAddr, u32 size) {
303
pool->cur = pool->start = (u8 *) ALIGN16((uintptr_t) memAddr);
304
#ifdef VERSION_SH
305
pool->size = size - ((uintptr_t) memAddr & 0xf);
306
#else
307
pool->size = size;
308
#endif
309
pool->numAllocatedEntries = 0;
310
}
311
312
void persistent_pool_clear(struct PersistentPool *persistent) {
313
persistent->pool.numAllocatedEntries = 0;
314
persistent->pool.cur = persistent->pool.start;
315
persistent->numEntries = 0;
316
}
317
318
void temporary_pool_clear(struct TemporaryPool *temporary) {
319
temporary->pool.numAllocatedEntries = 0;
320
temporary->pool.cur = temporary->pool.start;
321
temporary->nextSide = 0;
322
temporary->entries[0].ptr = temporary->pool.start;
323
#if defined(VERSION_EU) || defined(VERSION_SH)
324
temporary->entries[1].ptr = temporary->pool.start + temporary->pool.size;
325
#else
326
temporary->entries[1].ptr = temporary->pool.size + temporary->pool.start;
327
#endif
328
temporary->entries[0].id = -1; // should be at 1e not 1c
329
temporary->entries[1].id = -1;
330
}
331
332
void unused_803160F8(struct SoundAllocPool *pool) {
333
pool->numAllocatedEntries = 0;
334
pool->cur = pool->start;
335
}
336
337
extern s32 D_SH_80315EE8;
338
void sound_init_main_pools(s32 sizeForAudioInitPool) {
339
sound_alloc_pool_init(&gAudioInitPool, gAudioHeap, sizeForAudioInitPool);
340
sound_alloc_pool_init(&gAudioSessionPool, gAudioHeap + sizeForAudioInitPool, gAudioHeapSize - sizeForAudioInitPool);
341
}
342
343
#ifdef VERSION_SH
344
#define SOUND_ALLOC_FUNC sound_alloc_uninitialized
345
#else
346
#define SOUND_ALLOC_FUNC soundAlloc
347
#endif
348
349
void session_pools_init(struct PoolSplit *a) {
350
gAudioSessionPool.cur = gAudioSessionPool.start;
351
sound_alloc_pool_init(&gNotesAndBuffersPool, SOUND_ALLOC_FUNC(&gAudioSessionPool, a->wantSeq), a->wantSeq);
352
sound_alloc_pool_init(&gSeqAndBankPool, SOUND_ALLOC_FUNC(&gAudioSessionPool, a->wantCustom), a->wantCustom);
353
}
354
355
void seq_and_bank_pool_init(struct PoolSplit2 *a) {
356
gSeqAndBankPool.cur = gSeqAndBankPool.start;
357
sound_alloc_pool_init(&gPersistentCommonPool, SOUND_ALLOC_FUNC(&gSeqAndBankPool, a->wantPersistent), a->wantPersistent);
358
sound_alloc_pool_init(&gTemporaryCommonPool, SOUND_ALLOC_FUNC(&gSeqAndBankPool, a->wantTemporary), a->wantTemporary);
359
}
360
361
void persistent_pools_init(struct PoolSplit *a) {
362
gPersistentCommonPool.cur = gPersistentCommonPool.start;
363
sound_alloc_pool_init(&gSeqLoadedPool.persistent.pool, SOUND_ALLOC_FUNC(&gPersistentCommonPool, a->wantSeq), a->wantSeq);
364
sound_alloc_pool_init(&gBankLoadedPool.persistent.pool, SOUND_ALLOC_FUNC(&gPersistentCommonPool, a->wantBank), a->wantBank);
365
sound_alloc_pool_init(&gUnusedLoadedPool.persistent.pool, SOUND_ALLOC_FUNC(&gPersistentCommonPool, a->wantUnused),
366
a->wantUnused);
367
persistent_pool_clear(&gSeqLoadedPool.persistent);
368
persistent_pool_clear(&gBankLoadedPool.persistent);
369
persistent_pool_clear(&gUnusedLoadedPool.persistent);
370
}
371
372
void temporary_pools_init(struct PoolSplit *a) {
373
gTemporaryCommonPool.cur = gTemporaryCommonPool.start;
374
sound_alloc_pool_init(&gSeqLoadedPool.temporary.pool, SOUND_ALLOC_FUNC(&gTemporaryCommonPool, a->wantSeq), a->wantSeq);
375
sound_alloc_pool_init(&gBankLoadedPool.temporary.pool, SOUND_ALLOC_FUNC(&gTemporaryCommonPool, a->wantBank), a->wantBank);
376
sound_alloc_pool_init(&gUnusedLoadedPool.temporary.pool, SOUND_ALLOC_FUNC(&gTemporaryCommonPool, a->wantUnused),
377
a->wantUnused);
378
temporary_pool_clear(&gSeqLoadedPool.temporary);
379
temporary_pool_clear(&gBankLoadedPool.temporary);
380
temporary_pool_clear(&gUnusedLoadedPool.temporary);
381
}
382
#undef SOUND_ALLOC_FUNC
383
384
#if defined(VERSION_JP) || defined(VERSION_US)
385
UNUSED static void unused_803163D4(void) {
386
}
387
#endif
388
389
#ifdef VERSION_SH
390
void *alloc_bank_or_seq(s32 poolIdx, s32 size, s32 arg3, s32 id) {
391
#else
392
void *alloc_bank_or_seq(struct SoundMultiPool *arg0, s32 arg1, s32 size, s32 arg3, s32 id) {
393
#endif
394
// arg3 = 0, 1 or 2?
395
396
#ifdef VERSION_SH
397
struct SoundMultiPool *arg0;
398
#define isSound poolIdx
399
#endif
400
struct TemporaryPool *tp;
401
struct SoundAllocPool *pool;
402
void *ret;
403
#if defined(VERSION_JP) || defined(VERSION_US)
404
u16 UNUSED _firstVal;
405
u16 UNUSED _secondVal;
406
#else
407
u16 firstVal;
408
u16 secondVal;
409
#endif
410
u32 nullID = -1;
411
UNUSED s32 i;
412
u8 *table;
413
#ifndef VERSION_SH
414
u8 isSound;
415
#endif
416
#if defined(VERSION_JP) || defined(VERSION_US)
417
u16 firstVal;
418
u16 secondVal;
419
u32 bothDiscardable;
420
u32 leftDiscardable, rightDiscardable;
421
u32 leftNotLoaded, rightNotLoaded;
422
u32 leftAvail, rightAvail;
423
#endif
424
425
#ifdef VERSION_SH
426
switch (poolIdx) {
427
case 0:
428
arg0 = &gSeqLoadedPool;
429
table = gSeqLoadStatus;
430
break;
431
432
case 1:
433
arg0 = &gBankLoadedPool;
434
table = gBankLoadStatus;
435
break;
436
437
case 2:
438
arg0 = &gUnusedLoadedPool;
439
table = gUnkLoadStatus;
440
break;
441
}
442
#endif
443
444
if (arg3 == 0) {
445
tp = &arg0->temporary;
446
#ifndef VERSION_SH
447
if (arg0 == &gSeqLoadedPool) {
448
table = gSeqLoadStatus;
449
isSound = FALSE;
450
} else if (arg0 == &gBankLoadedPool) {
451
table = gBankLoadStatus;
452
isSound = TRUE;
453
}
454
#endif
455
456
#ifdef VERSION_SH
457
if (tp->entries[0].id == (s8)nullID) {
458
firstVal = SOUND_LOAD_STATUS_NOT_LOADED;
459
} else {
460
firstVal = table[tp->entries[0].id];
461
}
462
if (tp->entries[1].id == (s8)nullID) {
463
secondVal = SOUND_LOAD_STATUS_NOT_LOADED;
464
} else {
465
secondVal = table[tp->entries[1].id];
466
}
467
#else
468
firstVal = (tp->entries[0].id == (s8)nullID ? SOUND_LOAD_STATUS_NOT_LOADED : table[tp->entries[0].id]);
469
secondVal = (tp->entries[1].id == (s8)nullID ? SOUND_LOAD_STATUS_NOT_LOADED : table[tp->entries[1].id]);
470
#endif
471
472
#if defined(VERSION_JP) || defined(VERSION_US)
473
leftNotLoaded = (firstVal == SOUND_LOAD_STATUS_NOT_LOADED);
474
leftDiscardable = (firstVal == SOUND_LOAD_STATUS_DISCARDABLE);
475
leftAvail = (firstVal != SOUND_LOAD_STATUS_IN_PROGRESS);
476
rightNotLoaded = (secondVal == SOUND_LOAD_STATUS_NOT_LOADED);
477
rightDiscardable = (secondVal == SOUND_LOAD_STATUS_DISCARDABLE);
478
rightAvail = (secondVal != SOUND_LOAD_STATUS_IN_PROGRESS);
479
bothDiscardable = (leftDiscardable && rightDiscardable);
480
481
if (leftNotLoaded) {
482
tp->nextSide = 0;
483
} else if (rightNotLoaded) {
484
tp->nextSide = 1;
485
} else if (bothDiscardable) {
486
// Use the opposite side from last time.
487
} else if (firstVal == SOUND_LOAD_STATUS_DISCARDABLE) { // ??! (I blame copt)
488
tp->nextSide = 0;
489
} else if (rightDiscardable) {
490
tp->nextSide = 1;
491
} else if (leftAvail) {
492
tp->nextSide = 0;
493
} else if (rightAvail) {
494
tp->nextSide = 1;
495
} else {
496
// Both left and right sides are being loaded into.
497
return NULL;
498
}
499
#else
500
#ifdef VERSION_EU
501
if (0) {
502
// It's unclear where these string literals go.
503
eu_stubbed_printf_0("DataHeap Not Allocate \n");
504
eu_stubbed_printf_1("StayHeap Not Allocate %d\n", 0);
505
eu_stubbed_printf_1("AutoHeap Not Allocate %d\n", 0);
506
}
507
#endif
508
509
#ifdef VERSION_SH
510
if (poolIdx == 1) {
511
if (firstVal == SOUND_LOAD_STATUS_4) {
512
for (i = 0; i < gMaxSimultaneousNotes; i++) {
513
if (gNotes[i].bankId == tp->entries[0].id && gNotes[i].noteSubEu.enabled) {
514
break;
515
}
516
}
517
if (i == gMaxSimultaneousNotes) {
518
if (gBankLoadStatus[tp->entries[0].id] != SOUND_LOAD_STATUS_5) {
519
gBankLoadStatus[tp->entries[0].id] = SOUND_LOAD_STATUS_DISCARDABLE;
520
}
521
firstVal = SOUND_LOAD_STATUS_DISCARDABLE;
522
}
523
}
524
if (secondVal == SOUND_LOAD_STATUS_4) {
525
for (i = 0; i < gMaxSimultaneousNotes; i++) {
526
if (gNotes[i].bankId == tp->entries[1].id && gNotes[i].noteSubEu.enabled) {
527
break;
528
}
529
}
530
if (i == gMaxSimultaneousNotes) {
531
if (gBankLoadStatus[tp->entries[1].id] != SOUND_LOAD_STATUS_5) {
532
gBankLoadStatus[tp->entries[1].id] = SOUND_LOAD_STATUS_DISCARDABLE;
533
}
534
secondVal = SOUND_LOAD_STATUS_DISCARDABLE;
535
}
536
}
537
}
538
#endif
539
540
if (firstVal == SOUND_LOAD_STATUS_NOT_LOADED) {
541
tp->nextSide = 0;
542
} else if (secondVal == SOUND_LOAD_STATUS_NOT_LOADED) {
543
tp->nextSide = 1;
544
} else {
545
eu_stubbed_printf_0("WARNING: NO FREE AUTOSEQ AREA.\n");
546
if ((firstVal == SOUND_LOAD_STATUS_DISCARDABLE) && (secondVal == SOUND_LOAD_STATUS_DISCARDABLE)) {
547
// Use the opposite side from last time.
548
} else if (firstVal == SOUND_LOAD_STATUS_DISCARDABLE) {
549
tp->nextSide = 0;
550
} else if (secondVal == SOUND_LOAD_STATUS_DISCARDABLE) {
551
tp->nextSide = 1;
552
} else {
553
#ifdef VERSION_EU
554
eu_stubbed_printf_0("WARNING: NO STOP AUTO AREA.\n");
555
eu_stubbed_printf_0(" AND TRY FORCE TO STOP SIDE \n");
556
if (firstVal != SOUND_LOAD_STATUS_IN_PROGRESS) {
557
tp->nextSide = 0;
558
} else if (secondVal != SOUND_LOAD_STATUS_IN_PROGRESS) {
559
tp->nextSide = 1;
560
} else {
561
// Both left and right sides are being loaded into.
562
eu_stubbed_printf_0("TWO SIDES ARE LOADING... ALLOC CANCELED.\n");
563
return NULL;
564
}
565
#else
566
if (poolIdx == 0) {
567
if (firstVal == SOUND_LOAD_STATUS_COMPLETE) {
568
for (i = 0; i < SEQUENCE_PLAYERS; i++) {
569
if (gSequencePlayers[i].enabled && gSequencePlayers[i].seqId == tp->entries[0].id) {
570
break;
571
}
572
}
573
if (i == SEQUENCE_PLAYERS) {
574
tp->nextSide = 0;
575
goto out;
576
}
577
}
578
if (secondVal == SOUND_LOAD_STATUS_COMPLETE) {
579
for (i = 0; i < SEQUENCE_PLAYERS; i++) {
580
if (gSequencePlayers[i].enabled && gSequencePlayers[i].seqId == tp->entries[1].id) {
581
break;
582
}
583
}
584
if (i == SEQUENCE_PLAYERS) {
585
tp->nextSide = 1;
586
goto out;
587
}
588
}
589
} else if (poolIdx == 1) {
590
if (firstVal == SOUND_LOAD_STATUS_COMPLETE) {
591
for (i = 0; i < gMaxSimultaneousNotes; i++) {
592
if (gNotes[i].bankId == tp->entries[0].id && gNotes[i].noteSubEu.enabled) {
593
break;
594
}
595
}
596
if (i == gMaxSimultaneousNotes) {
597
tp->nextSide = 0;
598
goto out;
599
}
600
}
601
if (secondVal == SOUND_LOAD_STATUS_COMPLETE) {
602
for (i = 0; i < gMaxSimultaneousNotes; i++) {
603
if (gNotes[i].bankId == tp->entries[1].id && gNotes[i].noteSubEu.enabled) {
604
break;
605
}
606
}
607
if (i == gMaxSimultaneousNotes) {
608
tp->nextSide = 1;
609
goto out;
610
}
611
}
612
}
613
if (tp->nextSide == 0) {
614
if (firstVal == SOUND_LOAD_STATUS_IN_PROGRESS) {
615
if (secondVal != SOUND_LOAD_STATUS_IN_PROGRESS) {
616
tp->nextSide = 1;
617
goto out;
618
}
619
} else {
620
goto out;
621
}
622
} else {
623
if (secondVal == SOUND_LOAD_STATUS_IN_PROGRESS) {
624
if (firstVal != SOUND_LOAD_STATUS_IN_PROGRESS) {
625
tp->nextSide = 0;
626
goto out;
627
}
628
} else {
629
goto out;
630
}
631
}
632
return NULL;
633
out:;
634
#endif
635
}
636
}
637
#endif
638
639
pool = &arg0->temporary.pool;
640
if (tp->entries[tp->nextSide].id != (s8)nullID) {
641
table[tp->entries[tp->nextSide].id] = SOUND_LOAD_STATUS_NOT_LOADED;
642
if (isSound == TRUE) {
643
discard_bank(tp->entries[tp->nextSide].id);
644
}
645
}
646
647
switch (tp->nextSide) {
648
case 0:
649
tp->entries[0].ptr = pool->start;
650
tp->entries[0].id = id;
651
tp->entries[0].size = size;
652
653
pool->cur = pool->start + size;
654
655
#ifdef VERSION_SH
656
if (tp->entries[1].id != (s32)nullID)
657
#endif
658
if (tp->entries[1].ptr < pool->cur) {
659
eu_stubbed_printf_0("WARNING: Before Area Overlaid After.");
660
661
// Throw out the entry on the other side if it doesn't fit.
662
// (possible @bug: what if it's currently being loaded?)
663
table[tp->entries[1].id] = SOUND_LOAD_STATUS_NOT_LOADED;
664
665
switch (isSound) {
666
case FALSE:
667
discard_sequence(tp->entries[1].id);
668
break;
669
case TRUE:
670
discard_bank(tp->entries[1].id);
671
break;
672
}
673
674
tp->entries[1].id = (s32)nullID;
675
#if defined(VERSION_EU) || defined(VERSION_SH)
676
tp->entries[1].ptr = pool->start + pool->size;
677
#else
678
tp->entries[1].ptr = pool->size + pool->start;
679
#endif
680
}
681
682
ret = tp->entries[0].ptr;
683
break;
684
685
case 1:
686
#if defined(VERSION_SH)
687
tp->entries[1].ptr = (u8 *) ((uintptr_t) (pool->start + pool->size - size) & ~0x0f);
688
#elif defined(VERSION_EU)
689
tp->entries[1].ptr = pool->start + pool->size - size - 0x10;
690
#else
691
tp->entries[1].ptr = pool->size + pool->start - size - 0x10;
692
#endif
693
tp->entries[1].id = id;
694
tp->entries[1].size = size;
695
696
#ifdef VERSION_SH
697
if (tp->entries[0].id != (s32)nullID)
698
#endif
699
if (tp->entries[1].ptr < pool->cur) {
700
eu_stubbed_printf_0("WARNING: After Area Overlaid Before.");
701
702
table[tp->entries[0].id] = SOUND_LOAD_STATUS_NOT_LOADED;
703
704
switch (isSound) {
705
case FALSE:
706
discard_sequence(tp->entries[0].id);
707
break;
708
case TRUE:
709
discard_bank(tp->entries[0].id);
710
break;
711
}
712
713
tp->entries[0].id = (s32)nullID;
714
pool->cur = pool->start;
715
}
716
717
ret = tp->entries[1].ptr;
718
break;
719
720
default:
721
eu_stubbed_printf_1("MEMORY:SzHeapAlloc ERROR: sza->side %d\n", tp->nextSide);
722
return NULL;
723
}
724
725
// Switch sides for next time in case both entries are
726
// SOUND_LOAD_STATUS_DISCARDABLE.
727
tp->nextSide ^= 1;
728
729
return ret;
730
}
731
732
#if defined(VERSION_EU) || defined(VERSION_SH)
733
#ifdef VERSION_SH
734
ret = sound_alloc_uninitialized(&arg0->persistent.pool, size);
735
#else
736
ret = soundAlloc(&arg0->persistent.pool, arg1 * size);
737
#endif
738
arg0->persistent.entries[arg0->persistent.numEntries].ptr = ret;
739
740
if (ret == NULL)
741
#else
742
arg0->persistent.entries[arg0->persistent.numEntries].ptr = soundAlloc(&arg0->persistent.pool, arg1 * size);
743
744
if (arg0->persistent.entries[arg0->persistent.numEntries].ptr == NULL)
745
#endif
746
{
747
switch (arg3) {
748
case 2:
749
#if defined(VERSION_EU)
750
eu_stubbed_printf_0("MEMORY:StayHeap OVERFLOW.");
751
return alloc_bank_or_seq(arg0, arg1, size, 0, id);
752
#elif defined(VERSION_SH)
753
return alloc_bank_or_seq(poolIdx, size, 0, id);
754
#else
755
// Prevent tail call optimization.
756
ret = alloc_bank_or_seq(arg0, arg1, size, 0, id);
757
return ret;
758
#endif
759
case 1:
760
#ifdef VERSION_SH
761
case 0:
762
#endif
763
eu_stubbed_printf_1("MEMORY:StayHeap OVERFLOW (REQ:%d)", arg1 * size);
764
return NULL;
765
}
766
}
767
768
// TODO: why is this guaranteed to write <= 32 entries...?
769
// Because the buffer is small enough that more don't fit?
770
arg0->persistent.entries[arg0->persistent.numEntries].id = id;
771
arg0->persistent.entries[arg0->persistent.numEntries].size = size;
772
#if defined(VERSION_EU) || defined(VERSION_SH)
773
return arg0->persistent.entries[arg0->persistent.numEntries++].ptr;
774
#else
775
arg0->persistent.numEntries++; return arg0->persistent.entries[arg0->persistent.numEntries - 1].ptr;
776
#endif
777
#ifdef VERSION_SH
778
#undef isSound
779
#endif
780
}
781
782
#ifdef VERSION_SH
783
void *get_bank_or_seq(s32 poolIdx, s32 arg1, s32 id) {
784
void *ret;
785
786
ret = unk_pool1_lookup(poolIdx, id);
787
if (ret != NULL) {
788
return ret;
789
}
790
if (arg1 == 3) {
791
return NULL;
792
}
793
return get_bank_or_seq_inner(poolIdx, arg1, id);
794
}
795
void *get_bank_or_seq_inner(s32 poolIdx, s32 arg1, s32 bankId) {
796
u32 i;
797
struct SoundMultiPool* loadedPool;
798
struct TemporaryPool* temporary;
799
struct PersistentPool* persistent;
800
801
switch (poolIdx) {
802
case 0:
803
loadedPool = &gSeqLoadedPool;
804
break;
805
case 1:
806
loadedPool = &gBankLoadedPool;
807
break;
808
case 2:
809
loadedPool = &gUnusedLoadedPool;
810
break;
811
}
812
813
temporary = &loadedPool->temporary;
814
if (arg1 == 0) {
815
if (temporary->entries[0].id == bankId) {
816
temporary->nextSide = 1;
817
return temporary->entries[0].ptr;
818
} else if (temporary->entries[1].id == bankId) {
819
temporary->nextSide = 0;
820
return temporary->entries[1].ptr;
821
} else {
822
return NULL;
823
}
824
}
825
826
persistent = &loadedPool->persistent;
827
for (i = 0; i < persistent->numEntries; i++) {
828
if (persistent->entries[i].id == bankId) {
829
return persistent->entries[i].ptr;
830
}
831
}
832
833
if (arg1 == 2) {
834
return get_bank_or_seq(poolIdx, 0, bankId);
835
}
836
return NULL;
837
}
838
#endif
839
#ifndef VERSION_SH
840
void *get_bank_or_seq(struct SoundMultiPool *arg0, s32 arg1, s32 id) {
841
u32 i;
842
UNUSED void *ret;
843
struct TemporaryPool *temporary = &arg0->temporary;
844
845
if (arg1 == 0) {
846
// Try not to overwrite sound that we have just accessed, by setting nextSide appropriately.
847
if (temporary->entries[0].id == id) {
848
temporary->nextSide = 1;
849
return temporary->entries[0].ptr;
850
} else if (temporary->entries[1].id == id) {
851
temporary->nextSide = 0;
852
return temporary->entries[1].ptr;
853
}
854
eu_stubbed_printf_1("Auto Heap Unhit for ID %d\n", id);
855
return NULL;
856
} else {
857
struct PersistentPool *persistent = &arg0->persistent;
858
for (i = 0; i < persistent->numEntries; i++) {
859
if (id == persistent->entries[i].id) {
860
eu_stubbed_printf_2("Cache hit %d at stay %d\n", id, i);
861
return persistent->entries[i].ptr;
862
}
863
}
864
865
if (arg1 == 2) {
866
#if defined(VERSION_EU) || defined(VERSION_SH)
867
return get_bank_or_seq(arg0, 0, id);
868
#else
869
// Prevent tail call optimization by using a temporary.
870
// Either copt or -Wo,-notail.
871
ret = get_bank_or_seq(arg0, 0, id);
872
return ret;
873
#endif
874
}
875
return NULL;
876
}
877
}
878
#endif
879
880
#if defined(VERSION_EU) || defined(VERSION_SH)
881
void func_eu_802e27e4_unused(f32 arg0, f32 arg1, u16 *arg2) {
882
s32 i;
883
f32 tmp[16];
884
885
tmp[0] = (f32) (arg1 * 262159.0f);
886
tmp[8] = (f32) (arg0 * 262159.0f);
887
tmp[1] = (f32) ((arg1 * arg0) * 262159.0f);
888
tmp[9] = (f32) (((arg0 * arg0) + arg1) * 262159.0f);
889
890
for (i = 2; i < 8; i++) {
891
//! @bug they probably meant to store the value to tmp[i] and tmp[8 + i]
892
arg2[i] = arg1 * tmp[i - 2] + arg0 * tmp[i - 1];
893
arg2[8 + i] = arg1 * tmp[6 + i] + arg0 * tmp[7 + i];
894
}
895
896
for (i = 0; i < 16; i++) {
897
arg2[i] = tmp[i];
898
}
899
900
#ifdef VERSION_EU
901
for (i = 0; i < 8; i++) {
902
eu_stubbed_printf_1("%d ", arg2[i]);
903
}
904
eu_stubbed_printf_0("\n");
905
906
for (i = 8; i < 16; i++) {
907
eu_stubbed_printf_1("%d ", arg2[i]);
908
}
909
eu_stubbed_printf_0("\n");
910
#endif
911
}
912
#endif
913
914
#ifdef VERSION_SH
915
void fill_zero_filter(s16 filter[]) {
916
s32 i;
917
for (i = 0; i < 8; i++) {
918
filter[i] = 0;
919
}
920
}
921
922
extern s16 unk_sh_data_3[15 * 8];
923
extern s16 unk_sh_data_4[15 * 8];
924
void func_sh_802F0DE8(s16 filter[8], s32 arg1) {
925
s32 i;
926
s16 *ptr = &unk_sh_data_3[8 * (arg1 - 1)];
927
for (i = 0; i < 8; i++) {
928
filter[i] = ptr[i];
929
}
930
}
931
932
void func_sh_802F0E40(s16 filter[8], s32 arg1) { // Unused
933
s32 i;
934
s16 *ptr = &unk_sh_data_4[8 * (arg1 - 1)];
935
for (i = 0; i < 8; i++) {
936
filter[i] = ptr[i];
937
}
938
}
939
940
void fill_filter(s16 filter[8], s32 arg1, s32 arg2) {
941
s32 i;
942
s16 *ptr;
943
if (arg1 != 0) {
944
func_sh_802F0DE8(filter, arg1);
945
} else {
946
fill_zero_filter(filter);
947
}
948
if (arg2 != 0) {
949
ptr = &unk_sh_data_4[8 * (arg2 - 1)];
950
for (i = 0; i < 8; i++) {
951
filter[i] += ptr[i];
952
}
953
}
954
}
955
#endif
956
957
void decrease_reverb_gain(void) {
958
#if defined(VERSION_EU)
959
s32 i;
960
for (i = 0; i < gNumSynthesisReverbs; i++) {
961
gSynthesisReverbs[i].reverbGain -= gSynthesisReverbs[i].reverbGain / 8;
962
}
963
#elif defined(VERSION_JP) || defined(VERSION_US)
964
gSynthesisReverb.reverbGain -= gSynthesisReverb.reverbGain / 4;
965
#else
966
s32 i, j;
967
s32 v0 = gAudioBufferParameters.presetUnk4 == 2 ? 2 : 1;
968
for (i = 0; i < gNumSynthesisReverbs; i++) {
969
for (j = 0; j < v0; j++) {
970
gSynthesisReverbs[i].reverbGain -= gSynthesisReverbs[i].reverbGain / 3;
971
}
972
}
973
#endif
974
}
975
976
#if defined(VERSION_SH)
977
void clear_curr_ai_buffer(void) {
978
s32 currIndex = gCurrAiBufferIndex;
979
s32 i;
980
gAiBufferLengths[currIndex] = gAudioBufferParameters.minAiBufferLength;
981
for (i = 0; i < (s32) (AIBUFFER_LEN / sizeof(s16)); i++) {
982
gAiBuffers[currIndex][i] = 0;
983
}
984
}
985
#endif
986
987
988
#if defined(VERSION_EU) || defined(VERSION_SH)
989
s32 audio_shut_down_and_reset_step(void) {
990
s32 i;
991
s32 j;
992
#ifdef VERSION_SH
993
s32 num = gAudioBufferParameters.presetUnk4 == 2 ? 2 : 1;
994
#endif
995
996
switch (gAudioResetStatus) {
997
case 5:
998
for (i = 0; i < SEQUENCE_PLAYERS; i++) {
999
sequence_player_disable(&gSequencePlayers[i]);
1000
}
1001
#ifdef VERSION_SH
1002
gAudioResetFadeOutFramesLeft = 4 / num;
1003
#else
1004
gAudioResetFadeOutFramesLeft = 4;
1005
#endif
1006
gAudioResetStatus--;
1007
break;
1008
case 4:
1009
if (gAudioResetFadeOutFramesLeft != 0) {
1010
gAudioResetFadeOutFramesLeft--;
1011
decrease_reverb_gain();
1012
} else {
1013
for (i = 0; i < gMaxSimultaneousNotes; i++) {
1014
if (gNotes[i].noteSubEu.enabled && gNotes[i].adsr.state != ADSR_STATE_DISABLED) {
1015
gNotes[i].adsr.fadeOutVel = gAudioBufferParameters.updatesPerFrameInv;
1016
gNotes[i].adsr.action |= ADSR_ACTION_RELEASE;
1017
}
1018
}
1019
#ifdef VERSION_SH
1020
gAudioResetFadeOutFramesLeft = 16 / num;
1021
#else
1022
gAudioResetFadeOutFramesLeft = 16;
1023
#endif
1024
gAudioResetStatus--;
1025
}
1026
break;
1027
case 3:
1028
if (gAudioResetFadeOutFramesLeft != 0) {
1029
gAudioResetFadeOutFramesLeft--;
1030
#ifdef VERSION_SH
1031
if (1) {
1032
}
1033
#endif
1034
decrease_reverb_gain();
1035
} else {
1036
for (i = 0; i < NUMAIBUFFERS; i++) {
1037
for (j = 0; j < (s32) (AIBUFFER_LEN / sizeof(s16)); j++) {
1038
gAiBuffers[i][j] = 0;
1039
}
1040
}
1041
#ifdef VERSION_SH
1042
gAudioResetFadeOutFramesLeft = 4 / num;
1043
#else
1044
gAudioResetFadeOutFramesLeft = 4;
1045
#endif
1046
gAudioResetStatus--;
1047
}
1048
break;
1049
case 2:
1050
#ifdef VERSION_SH
1051
clear_curr_ai_buffer();
1052
#endif
1053
if (gAudioResetFadeOutFramesLeft != 0) {
1054
gAudioResetFadeOutFramesLeft--;
1055
} else {
1056
gAudioResetStatus--;
1057
#ifdef VERSION_SH
1058
func_sh_802f23ec();
1059
#endif
1060
}
1061
break;
1062
case 1:
1063
audio_reset_session();
1064
gAudioResetStatus = 0;
1065
#ifdef VERSION_SH
1066
for (i = 0; i < NUMAIBUFFERS; i++) {
1067
gAiBufferLengths[i] = gAudioBufferParameters.maxAiBufferLength;
1068
for (j = 0; j < (s32) (AIBUFFER_LEN / sizeof(s16)); j++) {
1069
gAiBuffers[i][j] = 0;
1070
}
1071
}
1072
#endif
1073
}
1074
#ifdef VERSION_SH
1075
if (gAudioResetFadeOutFramesLeft) {
1076
}
1077
#endif
1078
if (gAudioResetStatus < 3) {
1079
return 0;
1080
}
1081
return 1;
1082
}
1083
#else
1084
/**
1085
* Waits until a specified number of audio frames have been created
1086
*/
1087
void wait_for_audio_frames(UNUSED s32 frames) {
1088
gAudioFrameCount = 0;
1089
#ifdef TARGET_N64
1090
// Sound thread will update gAudioFrameCount
1091
while (gAudioFrameCount < frames) {
1092
// spin
1093
}
1094
#endif
1095
}
1096
#endif
1097
1098
#if defined(VERSION_JP) || defined(VERSION_US)
1099
void audio_reset_session(struct AudioSessionSettings *preset) {
1100
#else
1101
void audio_reset_session(void) {
1102
struct AudioSessionSettingsEU *preset = &gAudioSessionPresets[gAudioResetPresetIdToLoad];
1103
struct ReverbSettingsEU *reverbSettings;
1104
#endif
1105
s16 *mem;
1106
#if defined(VERSION_JP) || defined(VERSION_US)
1107
s8 updatesPerFrame;
1108
s32 reverbWindowSize;
1109
s32 k;
1110
#endif
1111
s32 i;
1112
s32 j;
1113
s32 persistentMem;
1114
s32 temporaryMem;
1115
s32 totalMem;
1116
s32 wantMisc;
1117
#if defined(VERSION_JP) || defined(VERSION_US)
1118
s32 frames;
1119
s32 remainingDmas;
1120
#else
1121
struct SynthesisReverb *reverb;
1122
#endif
1123
eu_stubbed_printf_1("Heap Reconstruct Start %x\n", gAudioResetPresetIdToLoad);
1124
1125
#if defined(VERSION_JP) || defined(VERSION_US)
1126
if (gAudioLoadLock != AUDIO_LOCK_UNINITIALIZED) {
1127
decrease_reverb_gain();
1128
for (i = 0; i < gMaxSimultaneousNotes; i++) {
1129
if (gNotes[i].enabled && gNotes[i].adsr.state != ADSR_STATE_DISABLED) {
1130
gNotes[i].adsr.fadeOutVel = 0x8000 / gAudioUpdatesPerFrame;
1131
gNotes[i].adsr.action |= ADSR_ACTION_RELEASE;
1132
}
1133
}
1134
1135
// Wait for all notes to stop playing
1136
frames = 0;
1137
for (;;) {
1138
wait_for_audio_frames(1);
1139
frames++;
1140
if (frames > 4 * 60) {
1141
// Break after 4 seconds
1142
break;
1143
}
1144
1145
for (i = 0; i < gMaxSimultaneousNotes; i++) {
1146
if (gNotes[i].enabled)
1147
break;
1148
}
1149
1150
if (i == gMaxSimultaneousNotes) {
1151
// All zero, break early
1152
break;
1153
}
1154
}
1155
1156
// Wait for the reverb to finish as well
1157
decrease_reverb_gain();
1158
wait_for_audio_frames(3);
1159
1160
// The audio interface is double buffered; thus, we have to take the
1161
// load lock for 2 frames for the buffers to free up before we can
1162
// repurpose memory. Make that 3 frames, just in case.
1163
gAudioLoadLock = AUDIO_LOCK_LOADING;
1164
wait_for_audio_frames(3);
1165
1166
remainingDmas = gCurrAudioFrameDmaCount;
1167
while (remainingDmas > 0) {
1168
for (i = 0; i < gCurrAudioFrameDmaCount; i++) {
1169
if (osRecvMesg(&gCurrAudioFrameDmaQueue, NULL, OS_MESG_NOBLOCK) == 0)
1170
remainingDmas--;
1171
}
1172
}
1173
gCurrAudioFrameDmaCount = 0;
1174
1175
for (j = 0; j < NUMAIBUFFERS; j++) {
1176
for (k = 0; k < (s32) (AIBUFFER_LEN / sizeof(s16)); k++) {
1177
gAiBuffers[j][k] = 0;
1178
}
1179
}
1180
}
1181
#endif
1182
1183
gSampleDmaNumListItems = 0;
1184
#if defined(VERSION_EU) || defined(VERSION_SH)
1185
gAudioBufferParameters.frequency = preset->frequency;
1186
gAudioBufferParameters.aiFrequency = osAiSetFrequency(gAudioBufferParameters.frequency);
1187
gAudioBufferParameters.samplesPerFrameTarget = ALIGN16(gAudioBufferParameters.frequency / gRefreshRate);
1188
gAudioBufferParameters.minAiBufferLength = gAudioBufferParameters.samplesPerFrameTarget - 0x10;
1189
gAudioBufferParameters.maxAiBufferLength = gAudioBufferParameters.samplesPerFrameTarget + 0x10;
1190
#ifdef VERSION_SH
1191
gAudioBufferParameters.updatesPerFrame = (gAudioBufferParameters.samplesPerFrameTarget + 0x10) / 192 + 1;
1192
gAudioBufferParameters.samplesPerUpdate = (gAudioBufferParameters.samplesPerFrameTarget / gAudioBufferParameters.updatesPerFrame) & -8;
1193
#else
1194
gAudioBufferParameters.updatesPerFrame = (gAudioBufferParameters.samplesPerFrameTarget + 0x10) / 160 + 1;
1195
gAudioBufferParameters.samplesPerUpdate = (gAudioBufferParameters.samplesPerFrameTarget / gAudioBufferParameters.updatesPerFrame) & 0xfff8;
1196
#endif
1197
gAudioBufferParameters.samplesPerUpdateMax = gAudioBufferParameters.samplesPerUpdate + 8;
1198
gAudioBufferParameters.samplesPerUpdateMin = gAudioBufferParameters.samplesPerUpdate - 8;
1199
gAudioBufferParameters.resampleRate = 32000.0f / FLOAT_CAST(gAudioBufferParameters.frequency);
1200
#ifdef VERSION_SH
1201
gAudioBufferParameters.unkUpdatesPerFrameScaled = (1.0f / 256.0f) / gAudioBufferParameters.updatesPerFrame;
1202
#else
1203
gAudioBufferParameters.unkUpdatesPerFrameScaled = (3.0f / 1280.0f) / gAudioBufferParameters.updatesPerFrame;
1204
#endif
1205
gAudioBufferParameters.updatesPerFrameInv = 1.0f / gAudioBufferParameters.updatesPerFrame;
1206
1207
gMaxSimultaneousNotes = preset->maxSimultaneousNotes;
1208
gVolume = preset->volume;
1209
gTempoInternalToExternal = (u32) (gAudioBufferParameters.updatesPerFrame * 2880000.0f / gTatumsPerBeat / D_EU_802298D0);
1210
1211
gAudioBufferParameters.presetUnk4 = preset->unk1;
1212
gAudioBufferParameters.samplesPerFrameTarget *= gAudioBufferParameters.presetUnk4;
1213
gAudioBufferParameters.maxAiBufferLength *= gAudioBufferParameters.presetUnk4;
1214
gAudioBufferParameters.minAiBufferLength *= gAudioBufferParameters.presetUnk4;
1215
gAudioBufferParameters.updatesPerFrame *= gAudioBufferParameters.presetUnk4;
1216
1217
#ifdef VERSION_SH
1218
if (gAudioBufferParameters.presetUnk4 >= 2) {
1219
gAudioBufferParameters.maxAiBufferLength -= 0x10;
1220
}
1221
gMaxAudioCmds = gMaxSimultaneousNotes * 0x14 * gAudioBufferParameters.updatesPerFrame + preset->numReverbs * 0x20 + 0x1E0;
1222
#else
1223
gMaxAudioCmds = gMaxSimultaneousNotes * 0x10 * gAudioBufferParameters.updatesPerFrame + preset->numReverbs * 0x20 + 0x300;
1224
#endif
1225
#else
1226
reverbWindowSize = preset->reverbWindowSize;
1227
gAiFrequency = osAiSetFrequency(preset->frequency);
1228
gMaxSimultaneousNotes = preset->maxSimultaneousNotes;
1229
gSamplesPerFrameTarget = ALIGN16(gAiFrequency / 60);
1230
gReverbDownsampleRate = preset->reverbDownsampleRate;
1231
1232
switch (gReverbDownsampleRate) {
1233
case 1:
1234
sReverbDownsampleRateLog = 0;
1235
break;
1236
case 2:
1237
sReverbDownsampleRateLog = 1;
1238
break;
1239
case 4:
1240
sReverbDownsampleRateLog = 2;
1241
break;
1242
case 8:
1243
sReverbDownsampleRateLog = 3;
1244
break;
1245
case 16:
1246
sReverbDownsampleRateLog = 4;
1247
break;
1248
default:
1249
sReverbDownsampleRateLog = 0;
1250
}
1251
1252
gReverbDownsampleRate = preset->reverbDownsampleRate;
1253
gVolume = preset->volume;
1254
gMinAiBufferLength = gSamplesPerFrameTarget - 0x10;
1255
updatesPerFrame = gSamplesPerFrameTarget / 160 + 1;
1256
gAudioUpdatesPerFrame = gSamplesPerFrameTarget / 160 + 1;
1257
1258
// Compute conversion ratio from the internal unit tatums/tick to the
1259
// external beats/minute (JP) or tatums/minute (US). In practice this is
1260
// 300 on JP and 14360 on US.
1261
#ifdef VERSION_JP
1262
gTempoInternalToExternal = updatesPerFrame * 3600 / gTatumsPerBeat;
1263
#else
1264
gTempoInternalToExternal = (u32)(updatesPerFrame * 2880000.0f / gTatumsPerBeat / 16.713f);
1265
#endif
1266
gMaxAudioCmds = gMaxSimultaneousNotes * 20 * updatesPerFrame + 320;
1267
#endif
1268
1269
#if defined(VERSION_SH)
1270
persistentMem = DOUBLE_SIZE_ON_64_BIT(preset->persistentSeqMem + preset->persistentBankMem + preset->unk18 + preset->unkMem28 + 0x10);
1271
temporaryMem = DOUBLE_SIZE_ON_64_BIT(preset->temporarySeqMem + preset->temporaryBankMem + preset->unk24 + preset->unkMem2C + 0x10);
1272
#elif defined(VERSION_EU)
1273
persistentMem = DOUBLE_SIZE_ON_64_BIT(preset->persistentSeqMem + preset->persistentBankMem);
1274
temporaryMem = DOUBLE_SIZE_ON_64_BIT(preset->temporarySeqMem + preset->temporaryBankMem);
1275
#else
1276
persistentMem = DOUBLE_SIZE_ON_64_BIT(preset->persistentBankMem + preset->persistentSeqMem);
1277
temporaryMem = DOUBLE_SIZE_ON_64_BIT(preset->temporaryBankMem + preset->temporarySeqMem);
1278
#endif
1279
totalMem = persistentMem + temporaryMem;
1280
wantMisc = gAudioSessionPool.size - totalMem - 0x100;
1281
sSessionPoolSplit.wantSeq = wantMisc;
1282
sSessionPoolSplit.wantCustom = totalMem;
1283
session_pools_init(&sSessionPoolSplit);
1284
sSeqAndBankPoolSplit.wantPersistent = persistentMem;
1285
sSeqAndBankPoolSplit.wantTemporary = temporaryMem;
1286
seq_and_bank_pool_init(&sSeqAndBankPoolSplit);
1287
sPersistentCommonPoolSplit.wantSeq = DOUBLE_SIZE_ON_64_BIT(preset->persistentSeqMem);
1288
sPersistentCommonPoolSplit.wantBank = DOUBLE_SIZE_ON_64_BIT(preset->persistentBankMem);
1289
#ifdef VERSION_SH
1290
sPersistentCommonPoolSplit.wantUnused = preset->unk18;
1291
#else
1292
sPersistentCommonPoolSplit.wantUnused = 0;
1293
#endif
1294
persistent_pools_init(&sPersistentCommonPoolSplit);
1295
sTemporaryCommonPoolSplit.wantSeq = DOUBLE_SIZE_ON_64_BIT(preset->temporarySeqMem);
1296
sTemporaryCommonPoolSplit.wantBank = DOUBLE_SIZE_ON_64_BIT(preset->temporaryBankMem);
1297
#ifdef VERSION_SH
1298
sTemporaryCommonPoolSplit.wantUnused = preset->unk24;
1299
#else
1300
sTemporaryCommonPoolSplit.wantUnused = 0;
1301
#endif
1302
temporary_pools_init(&sTemporaryCommonPoolSplit);
1303
#ifdef VERSION_SH
1304
unk_pools_init(preset->unkMem28, preset->unkMem2C);
1305
#endif
1306
reset_bank_and_seq_load_status();
1307
1308
#if defined(VERSION_JP) || defined(VERSION_US)
1309
for (j = 0; j < 2; j++) {
1310
gAudioCmdBuffers[j] = soundAlloc(&gNotesAndBuffersPool, gMaxAudioCmds * sizeof(u64));
1311
}
1312
#endif
1313
1314
gNotes = soundAlloc(&gNotesAndBuffersPool, gMaxSimultaneousNotes * sizeof(struct Note));
1315
note_init_all();
1316
init_note_free_list();
1317
1318
#if defined(VERSION_EU) || defined(VERSION_SH)
1319
gNoteSubsEu = soundAlloc(&gNotesAndBuffersPool, (gAudioBufferParameters.updatesPerFrame * gMaxSimultaneousNotes) * sizeof(struct NoteSubEu));
1320
1321
for (j = 0; j != 2; j++) {
1322
gAudioCmdBuffers[j] = soundAlloc(&gNotesAndBuffersPool, gMaxAudioCmds * sizeof(u64));
1323
}
1324
1325
for (j = 0; j < 4; j++) {
1326
gSynthesisReverbs[j].useReverb = 0;
1327
}
1328
gNumSynthesisReverbs = preset->numReverbs;
1329
for (j = 0; j < gNumSynthesisReverbs; j++) {
1330
reverb = &gSynthesisReverbs[j];
1331
reverbSettings = &preset->reverbSettings[j];
1332
#ifdef VERSION_SH
1333
reverb->downsampleRate = reverbSettings->downsampleRate;
1334
reverb->windowSize = reverbSettings->windowSize * 64;
1335
reverb->windowSize /= reverb->downsampleRate;
1336
#else
1337
reverb->windowSize = reverbSettings->windowSize * 64;
1338
reverb->downsampleRate = reverbSettings->downsampleRate;
1339
#endif
1340
reverb->reverbGain = reverbSettings->gain;
1341
#ifdef VERSION_SH
1342
reverb->panRight = reverbSettings->unk4;
1343
reverb->panLeft = reverbSettings->unk6;
1344
reverb->unk5 = reverbSettings->unk8;
1345
reverb->unk08 = reverbSettings->unkA;
1346
#endif
1347
reverb->useReverb = 8;
1348
reverb->ringBuffer.left = soundAlloc(&gNotesAndBuffersPool, reverb->windowSize * 2);
1349
reverb->ringBuffer.right = soundAlloc(&gNotesAndBuffersPool, reverb->windowSize * 2);
1350
reverb->nextRingBufferPos = 0;
1351
reverb->unkC = 0;
1352
reverb->curFrame = 0;
1353
reverb->bufSizePerChannel = reverb->windowSize;
1354
reverb->framesLeftToIgnore = 2;
1355
#ifdef VERSION_SH
1356
reverb->resampleFlags = A_INIT;
1357
#endif
1358
if (reverb->downsampleRate != 1) {
1359
#ifndef VERSION_SH
1360
reverb->resampleFlags = A_INIT;
1361
#endif
1362
reverb->resampleRate = 0x8000 / reverb->downsampleRate;
1363
reverb->resampleStateLeft = soundAlloc(&gNotesAndBuffersPool, 16 * sizeof(s16));
1364
reverb->resampleStateRight = soundAlloc(&gNotesAndBuffersPool, 16 * sizeof(s16));
1365
reverb->unk24 = soundAlloc(&gNotesAndBuffersPool, 16 * sizeof(s16));
1366
reverb->unk28 = soundAlloc(&gNotesAndBuffersPool, 16 * sizeof(s16));
1367
for (i = 0; i < gAudioBufferParameters.updatesPerFrame; i++) {
1368
mem = soundAlloc(&gNotesAndBuffersPool, DEFAULT_LEN_2CH);
1369
reverb->items[0][i].toDownsampleLeft = mem;
1370
reverb->items[0][i].toDownsampleRight = mem + DEFAULT_LEN_1CH / sizeof(s16);
1371
mem = soundAlloc(&gNotesAndBuffersPool, DEFAULT_LEN_2CH);
1372
reverb->items[1][i].toDownsampleLeft = mem;
1373
reverb->items[1][i].toDownsampleRight = mem + DEFAULT_LEN_1CH / sizeof(s16);
1374
}
1375
}
1376
#ifdef VERSION_SH
1377
if (reverbSettings->unkC != 0) {
1378
reverb->unk108 = sound_alloc_uninitialized(&gNotesAndBuffersPool, 16 * sizeof(s16));
1379
reverb->unk100 = sound_alloc_uninitialized(&gNotesAndBuffersPool, 8 * sizeof(s16));
1380
func_sh_802F0DE8(reverb->unk100, reverbSettings->unkC);
1381
} else {
1382
reverb->unk100 = NULL;
1383
}
1384
if (reverbSettings->unkE != 0) {
1385
reverb->unk10C = sound_alloc_uninitialized(&gNotesAndBuffersPool, 16 * sizeof(s16));
1386
reverb->unk104 = sound_alloc_uninitialized(&gNotesAndBuffersPool, 8 * sizeof(s16));
1387
func_sh_802F0DE8(reverb->unk104, reverbSettings->unkE);
1388
} else {
1389
reverb->unk104 = NULL;
1390
}
1391
#endif
1392
}
1393
1394
#else
1395
if (reverbWindowSize == 0) {
1396
gSynthesisReverb.useReverb = 0;
1397
} else {
1398
gSynthesisReverb.useReverb = 8;
1399
gSynthesisReverb.ringBuffer.left = soundAlloc(&gNotesAndBuffersPool, reverbWindowSize * 2);
1400
gSynthesisReverb.ringBuffer.right = soundAlloc(&gNotesAndBuffersPool, reverbWindowSize * 2);
1401
gSynthesisReverb.nextRingBufferPos = 0;
1402
gSynthesisReverb.unkC = 0;
1403
gSynthesisReverb.curFrame = 0;
1404
gSynthesisReverb.bufSizePerChannel = reverbWindowSize;
1405
gSynthesisReverb.reverbGain = preset->reverbGain;
1406
gSynthesisReverb.framesLeftToIgnore = 2;
1407
if (gReverbDownsampleRate != 1) {
1408
gSynthesisReverb.resampleFlags = A_INIT;
1409
gSynthesisReverb.resampleRate = 0x8000 / gReverbDownsampleRate;
1410
gSynthesisReverb.resampleStateLeft = soundAlloc(&gNotesAndBuffersPool, 16 * sizeof(s16));
1411
gSynthesisReverb.resampleStateRight = soundAlloc(&gNotesAndBuffersPool, 16 * sizeof(s16));
1412
gSynthesisReverb.unk24 = soundAlloc(&gNotesAndBuffersPool, 16 * sizeof(s16));
1413
gSynthesisReverb.unk28 = soundAlloc(&gNotesAndBuffersPool, 16 * sizeof(s16));
1414
for (i = 0; i < gAudioUpdatesPerFrame; i++) {
1415
mem = soundAlloc(&gNotesAndBuffersPool, DEFAULT_LEN_2CH);
1416
gSynthesisReverb.items[0][i].toDownsampleLeft = mem;
1417
gSynthesisReverb.items[0][i].toDownsampleRight = mem + DEFAULT_LEN_1CH / sizeof(s16);
1418
mem = soundAlloc(&gNotesAndBuffersPool, DEFAULT_LEN_2CH);
1419
gSynthesisReverb.items[1][i].toDownsampleLeft = mem;
1420
gSynthesisReverb.items[1][i].toDownsampleRight = mem + DEFAULT_LEN_1CH / sizeof(s16);
1421
}
1422
}
1423
}
1424
#endif
1425
1426
init_sample_dma_buffers(gMaxSimultaneousNotes);
1427
1428
#if defined(VERSION_EU)
1429
build_vol_rampings_table(0, gAudioBufferParameters.samplesPerUpdate);
1430
#endif
1431
1432
#ifdef VERSION_SH
1433
D_SH_8034F68C = 0;
1434
D_SH_803479B4 = 4096;
1435
#endif
1436
1437
osWritebackDCacheAll();
1438
1439
#if defined(VERSION_JP) || defined(VERSION_US)
1440
if (gAudioLoadLock != AUDIO_LOCK_UNINITIALIZED) {
1441
gAudioLoadLock = AUDIO_LOCK_NOT_LOADING;
1442
}
1443
#endif
1444
}
1445
1446
#ifdef VERSION_SH
1447
void *unk_pool1_lookup(s32 poolIdx, s32 id) {
1448
s32 i;
1449
1450
for (i = 0; i < gUnkPool1.pool.numAllocatedEntries; i++) {
1451
if (gUnkPool1.entries[i].poolIndex == poolIdx && gUnkPool1.entries[i].id == id) {
1452
return gUnkPool1.entries[i].ptr;
1453
}
1454
}
1455
return NULL;
1456
}
1457
1458
void *unk_pool1_alloc(s32 poolIndex, s32 arg1, u32 size) {
1459
void *ret;
1460
s32 pos;
1461
1462
pos = gUnkPool1.pool.numAllocatedEntries;
1463
ret = sound_alloc_uninitialized(&gUnkPool1.pool, size);
1464
gUnkPool1.entries[pos].ptr = ret;
1465
if (ret == NULL) {
1466
return NULL;
1467
}
1468
gUnkPool1.entries[pos].poolIndex = poolIndex;
1469
gUnkPool1.entries[pos].id = arg1;
1470
gUnkPool1.entries[pos].size = size;
1471
1472
#ifdef AVOID_UB
1473
//! @bug UB: missing return. "ret" is in v0 at this point, but doing an
1474
// explicit return uses an additional register.
1475
return ret;
1476
#endif
1477
}
1478
1479
u8 *func_sh_802f1d40(u32 size, s32 bank, u8 *arg2, s8 medium) {
1480
struct UnkEntry *ret;
1481
1482
ret = func_sh_802f1ec4(size);
1483
if (ret != NULL) {
1484
ret->bankId = bank;
1485
ret->dstAddr = arg2;
1486
ret->medium = medium;
1487
return ret->srcAddr;
1488
}
1489
return NULL;
1490
}
1491
u8 *func_sh_802f1d90(u32 size, s32 bank, u8 *arg2, s8 medium) {
1492
struct UnkEntry *ret;
1493
1494
ret = unk_pool2_alloc(size);
1495
if (ret != NULL) {
1496
ret->bankId = bank;
1497
ret->dstAddr = arg2;
1498
ret->medium = medium;
1499
return ret->srcAddr;
1500
}
1501
return NULL;
1502
}
1503
u8 *func_sh_802f1de0(u32 size, s32 bank, u8 *arg2, s8 medium) { // duplicated function?
1504
struct UnkEntry *ret;
1505
1506
ret = unk_pool2_alloc(size);
1507
if (ret != NULL) {
1508
ret->bankId = bank;
1509
ret->dstAddr = arg2;
1510
ret->medium = medium;
1511
return ret->srcAddr;
1512
}
1513
return NULL;
1514
}
1515
void unk_pools_init(u32 size1, u32 size2) {
1516
void *mem;
1517
1518
mem = sound_alloc_uninitialized(&gPersistentCommonPool, size1);
1519
if (mem == NULL) {
1520
gUnkPool2.pool.size = 0;
1521
} else {
1522
sound_alloc_pool_init(&gUnkPool2.pool, mem, size1);
1523
}
1524
mem = sound_alloc_uninitialized(&gTemporaryCommonPool, size2);
1525
1526
if (mem == NULL) {
1527
gUnkPool3.pool.size = 0;
1528
} else {
1529
sound_alloc_pool_init(&gUnkPool3.pool, mem, size2);
1530
}
1531
1532
gUnkPool2.numEntries = 0;
1533
gUnkPool3.numEntries = 0;
1534
}
1535
1536
struct UnkEntry *func_sh_802f1ec4(u32 size) {
1537
u8 *temp_s2;
1538
u8 *phi_s3;
1539
u8 *memLocation;
1540
u8 *cur;
1541
1542
s32 i;
1543
s32 chosenIndex;
1544
1545
struct UnkStructSH8034EC88 *unkStruct;
1546
struct UnkPool *pool = &gUnkPool3;
1547
1548
u8 *itemStart;
1549
u8 *itemEnd;
1550
1551
phi_s3 = pool->pool.cur;
1552
memLocation = sound_alloc_uninitialized(&pool->pool, size);
1553
if (memLocation == NULL) {
1554
cur = pool->pool.cur;
1555
pool->pool.cur = pool->pool.start;
1556
memLocation = sound_alloc_uninitialized(&pool->pool, size);
1557
if (memLocation == NULL) {
1558
pool->pool.cur = cur;
1559
return NULL;
1560
}
1561
phi_s3 = pool->pool.start;
1562
}
1563
temp_s2 = pool->pool.cur;
1564
1565
chosenIndex = -1;
1566
for (i = 0; i < D_SH_8034F68C; i++) {
1567
unkStruct = &D_SH_8034EC88[i];
1568
if (unkStruct->isFree == FALSE) {
1569
itemStart = unkStruct->ramAddr;
1570
itemEnd = unkStruct->ramAddr + unkStruct->sample->size - 1;
1571
if (itemEnd < phi_s3 && itemStart < phi_s3) {
1572
continue;
1573
1574
}
1575
if (itemEnd >= temp_s2 && itemStart >= temp_s2) {
1576
continue;
1577
1578
}
1579
1580
unkStruct->isFree = TRUE;
1581
}
1582
}
1583
1584
for (i = 0; i < pool->numEntries; i++) {
1585
if (pool->entries[i].used == FALSE) {
1586
continue;
1587
}
1588
itemStart = pool->entries[i].srcAddr;
1589
itemEnd = itemStart + pool->entries[i].size - 1;
1590
1591
if (itemEnd < phi_s3 && itemStart < phi_s3) {
1592
continue;
1593
}
1594
1595
if (itemEnd >= temp_s2 && itemStart >= temp_s2) {
1596
continue;
1597
}
1598
1599
func_sh_802f2158(&pool->entries[i]);
1600
if (chosenIndex == -1) {
1601
chosenIndex = i;
1602
}
1603
}
1604
1605
if (chosenIndex == -1) {
1606
chosenIndex = pool->numEntries++;
1607
}
1608
pool->entries[chosenIndex].used = TRUE;
1609
pool->entries[chosenIndex].srcAddr = memLocation;
1610
pool->entries[chosenIndex].size = size;
1611
1612
return &pool->entries[chosenIndex];
1613
}
1614
1615
void func_sh_802f2158(struct UnkEntry *entry) {
1616
s32 idx;
1617
s32 seqCount;
1618
s32 bankId1;
1619
s32 bankId2;
1620
s32 instId;
1621
s32 drumId;
1622
struct Drum *drum;
1623
struct Instrument *inst;
1624
1625
seqCount = gAlCtlHeader->seqCount;
1626
for (idx = 0; idx < seqCount; idx++) {
1627
bankId1 = gCtlEntries[idx].bankId1;
1628
bankId2 = gCtlEntries[idx].bankId2;
1629
if ((bankId1 != 0xff && entry->bankId == bankId1) || (bankId2 != 0xff && entry->bankId == bankId2) || entry->bankId == 0) {
1630
if (get_bank_or_seq(1, 2, idx) != NULL) {
1631
if (IS_BANK_LOAD_COMPLETE(idx) != FALSE) {
1632
for (instId = 0; instId < gCtlEntries[idx].numInstruments; instId++) {
1633
inst = get_instrument_inner(idx, instId);
1634
if (inst != NULL) {
1635
if (inst->normalRangeLo != 0) {
1636
func_sh_802F2320(entry, inst->lowNotesSound.sample);
1637
}
1638
if (inst->normalRangeHi != 127) {
1639
func_sh_802F2320(entry, inst->highNotesSound.sample);
1640
}
1641
func_sh_802F2320(entry, inst->normalNotesSound.sample);
1642
}
1643
}
1644
for (drumId = 0; drumId < gCtlEntries[idx].numDrums; drumId++) {
1645
drum = get_drum(idx, drumId);
1646
if (drum != NULL) {
1647
func_sh_802F2320(entry, drum->sound.sample);
1648
}
1649
}
1650
}
1651
}
1652
}
1653
}
1654
}
1655
1656
void func_sh_802F2320(struct UnkEntry *entry, struct AudioBankSample *sample) {
1657
if (sample != NULL && sample->sampleAddr == entry->srcAddr) {
1658
sample->sampleAddr = entry->dstAddr;
1659
sample->medium = entry->medium;
1660
}
1661
}
1662
1663
struct UnkEntry *unk_pool2_alloc(u32 size) {
1664
void *data;
1665
struct UnkEntry *ret;
1666
s32 *numEntries = &gUnkPool2.numEntries;
1667
1668
data = sound_alloc_uninitialized(&gUnkPool2.pool, size);
1669
if (data == NULL) {
1670
return NULL;
1671
}
1672
ret = &gUnkPool2.entries[*numEntries];
1673
ret->used = TRUE;
1674
ret->srcAddr = data;
1675
ret->size = size;
1676
(*numEntries)++;
1677
return ret;
1678
}
1679
1680
void func_sh_802f23ec(void) {
1681
s32 i;
1682
s32 idx;
1683
s32 seqCount;
1684
s32 bankId1;
1685
s32 bankId2;
1686
s32 instId;
1687
s32 drumId;
1688
struct Drum *drum;
1689
struct Instrument *inst;
1690
UNUSED s32 pad;
1691
struct UnkEntry *entry; //! @bug: not initialized but nevertheless used
1692
1693
seqCount = gAlCtlHeader->seqCount;
1694
for (idx = 0; idx < seqCount; idx++) {
1695
bankId1 = gCtlEntries[idx].bankId1;
1696
bankId2 = gCtlEntries[idx].bankId2;
1697
if ((bankId1 != 0xffu && entry->bankId == bankId1) || (bankId2 != 0xff && entry->bankId == bankId2) || entry->bankId == 0) {
1698
if (get_bank_or_seq(1, 3, idx) != NULL) {
1699
if (IS_BANK_LOAD_COMPLETE(idx) != FALSE) {
1700
for (i = 0; i < gUnkPool2.numEntries; i++) {
1701
entry = &gUnkPool2.entries[i];
1702
for (instId = 0; instId < gCtlEntries[idx].numInstruments; instId++) {
1703
inst = get_instrument_inner(idx, instId);
1704
if (inst != NULL) {
1705
if (inst->normalRangeLo != 0) {
1706
func_sh_802F2320(entry, inst->lowNotesSound.sample);
1707
}
1708
if (inst->normalRangeHi != 127) {
1709
func_sh_802F2320(entry, inst->highNotesSound.sample);
1710
}
1711
func_sh_802F2320(entry, inst->normalNotesSound.sample);
1712
}
1713
}
1714
for (drumId = 0; drumId < gCtlEntries[idx].numDrums; drumId++) {
1715
drum = get_drum(idx, drumId);
1716
if (drum != NULL) {
1717
func_sh_802F2320(entry, drum->sound.sample);
1718
}
1719
}
1720
}
1721
}
1722
}
1723
}
1724
}
1725
}
1726
#endif
1727
1728
#ifdef VERSION_EU
1729
u8 audioString22[] = "SFrame Sample %d %d %d\n";
1730
u8 audioString23[] = "AHPBASE %x\n";
1731
u8 audioString24[] = "AHPCUR %x\n";
1732
u8 audioString25[] = "HeapTop %x\n";
1733
u8 audioString26[] = "SynoutRate %d / %d \n";
1734
u8 audioString27[] = "FXSIZE %d\n";
1735
u8 audioString28[] = "FXCOMP %d\n";
1736
u8 audioString29[] = "FXDOWN %d\n";
1737
u8 audioString30[] = "WaveCacheLen: %d\n";
1738
u8 audioString31[] = "SpecChange Finished\n";
1739
#endif
1740
1741