heap.c (59455B)
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 #if defined(VERSION_SH) || defined(VERSION_CN) 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 #if defined(VERSION_SH) || defined(VERSION_CN) 54 u8 gUnkLoadStatus[0x40]; 55 #endif 56 u8 gBankLoadStatus[0x40]; 57 u8 gSeqLoadStatus[0x100]; 58 59 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN) 60 volatile u8 gAudioResetStatus; 61 u8 gAudioResetPresetIdToLoad; 62 s32 gAudioResetFadeOutFramesLeft; 63 #endif 64 65 u8 gAudioUnusedBuffer[0x1000]; 66 67 extern s32 gMaxAudioCmds; 68 69 #if defined(VERSION_SH) || defined(VERSION_CN) 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 f64 deg2 = x * x; 87 f64 deg4 = deg2 * deg2; 88 f64 deg8 = deg4 * deg4; 89 s32 degree = k - 9; 90 f64 fx; 91 92 f64 deriv = deg8; 93 if (degree & 1) { 94 deriv *= x; 95 } 96 if (degree & 2) { 97 deriv *= deg2; 98 } 99 if (degree & 4) { 100 deriv *= deg4; 101 } 102 if (degree & 8) { 103 deriv *= deg8; 104 } 105 fx = deriv * x - d; 106 deriv = k * deriv; 107 return x - fx / deriv; 108 } 109 110 /** 111 * Assuming 'k' in [9, 24], 112 * Computes d ^ (1/k) 113 * 114 * @return the root, or 1.0 if d is 0 115 */ 116 f64 kth_root(f64 d, s32 k) { 117 f64 root = 1.5; 118 f64 next; 119 f64 diff; 120 s32 i; 121 if (d == 0.0) { 122 root = 1.0; 123 } else { 124 for (i = 0; i < 64; i++) { 125 if (1) { 126 } 127 next = root_newton_step(root, k, d); 128 diff = next - root; 129 130 if (diff < 0) { 131 diff = -diff; 132 } 133 134 if (diff < 1e-07) { 135 root = next; 136 break; 137 } else { 138 root = next; 139 } 140 } 141 } 142 143 return root; 144 } 145 146 void build_vol_rampings_table(s32 UNUSED unused, s32 len) { 147 s32 i; 148 s32 step; 149 s32 d; 150 s32 k = len / 8; 151 152 for (step = 0, i = 0; i < 0x400; step += 32, i++) { 153 d = step; 154 if (step == 0) { 155 d = 1; 156 } 157 158 gLeftVolRampings[0][i] = kth_root( d, k - 1); 159 gRightVolRampings[0][i] = kth_root(1.0 / d, k - 1) * 65536.0; 160 gLeftVolRampings[1][i] = kth_root( d, k); 161 gRightVolRampings[1][i] = kth_root(1.0 / d, k) * 65536.0; 162 gLeftVolRampings[2][i] = kth_root( d, k + 1); 163 gRightVolRampings[2][i] = kth_root(1.0 / d, k + 1) * 65536.0; 164 } 165 } 166 #endif 167 168 void reset_bank_and_seq_load_status(void) { 169 s32 i; 170 171 #if defined(VERSION_SH) || defined(VERSION_CN) 172 for (i = 0; i < 64; i++) { 173 if (gBankLoadStatus[i] != SOUND_LOAD_STATUS_5) { 174 gBankLoadStatus[i] = SOUND_LOAD_STATUS_NOT_LOADED; 175 } 176 } 177 178 for (i = 0; i < 64; i++) { 179 if (gUnkLoadStatus[i] != SOUND_LOAD_STATUS_5) { 180 gUnkLoadStatus[i] = SOUND_LOAD_STATUS_NOT_LOADED; 181 } 182 } 183 184 for (i = 0; i < 256; i++) { 185 if (gSeqLoadStatus[i] != SOUND_LOAD_STATUS_5) { 186 gSeqLoadStatus[i] = SOUND_LOAD_STATUS_NOT_LOADED; 187 } 188 } 189 #else 190 for (i = 0; i < 64; i++) { 191 gBankLoadStatus[i] = SOUND_LOAD_STATUS_NOT_LOADED; 192 } 193 194 for (i = 0; i < 256; i++) { 195 gSeqLoadStatus[i] = SOUND_LOAD_STATUS_NOT_LOADED; 196 } 197 #endif 198 } 199 200 void discard_bank(s32 bankId) { 201 s32 i; 202 203 for (i = 0; i < gMaxSimultaneousNotes; i++) { 204 struct Note *note = &gNotes[i]; 205 206 #if defined(VERSION_EU) 207 if (note->noteSubEu.bankId == bankId) 208 #else 209 if (note->bankId == bankId) 210 #endif 211 { 212 // (These prints are unclear. Arguments are picked semi-randomly.) 213 eu_stubbed_printf_1("Warning:Kill Note %x \n", i); 214 #if defined(VERSION_SH) || defined(VERSION_CN) 215 if (note->unkSH34 == NOTE_PRIORITY_DISABLED && note->priority) 216 #else 217 if (note->priority >= NOTE_PRIORITY_MIN) 218 #endif 219 { 220 eu_stubbed_printf_3("Kill Voice %d (ID %d) %d\n", note->waveId, 221 bankId, note->priority); 222 eu_stubbed_printf_0("Warning: Running Sequence's data disappear!\n"); 223 note->parentLayer->enabled = FALSE; // is 0x48, should be 0x44 224 note->parentLayer->finished = TRUE; 225 } 226 note_disable(note); 227 audio_list_remove(¬e->listItem); 228 audio_list_push_back(&gNoteFreeLists.disabled, ¬e->listItem); 229 } 230 } 231 } 232 233 void discard_sequence(s32 seqId) { 234 s32 i; 235 236 for (i = 0; i < SEQUENCE_PLAYERS; i++) { 237 if (gSequencePlayers[i].enabled && gSequencePlayers[i].seqId == seqId) { 238 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN) 239 sequence_player_disable(&gSequencePlayers[i]); 240 #else 241 sequence_player_disable(gSequencePlayers + i); 242 #endif 243 } 244 } 245 } 246 247 void *soundAlloc(struct SoundAllocPool *pool, u32 size) { 248 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN) 249 u8 *start; 250 u8 *pos; 251 u32 alignedSize = ALIGN16(size); 252 253 start = pool->cur; 254 if (start + alignedSize <= pool->start + pool->size) { 255 pool->cur += alignedSize; 256 for (pos = start; pos < pool->cur; pos++) { 257 *pos = 0; 258 } 259 } else { 260 eu_stubbed_printf_1("Heap OverFlow : Not Allocate %d!\n", size); 261 return NULL; 262 } 263 #if defined(VERSION_SH) || defined(VERSION_CN) 264 pool->numAllocatedEntries++; 265 #endif 266 return start; 267 #else 268 u8 *start; 269 s32 last; 270 s32 i; 271 272 if ((pool->cur + ALIGN16(size) <= pool->size + pool->start)) { 273 start = pool->cur; 274 pool->cur += ALIGN16(size); 275 last = pool->cur - start - 1; 276 for (i = 0; i <= last; i++) { 277 start[i] = 0; 278 } 279 } else { 280 return NULL; 281 } 282 return start; 283 #endif 284 } 285 286 #if defined(VERSION_SH) || defined(VERSION_CN) 287 void *sound_alloc_uninitialized(struct SoundAllocPool *pool, u32 size) { 288 u8 *start; 289 u32 alignedSize = ALIGN16(size); 290 291 start = pool->cur; 292 if (start + alignedSize <= pool->start + pool->size) { 293 pool->cur += alignedSize; 294 } else { 295 return NULL; 296 } 297 298 pool->numAllocatedEntries++; 299 return start; 300 } 301 #endif 302 303 void sound_alloc_pool_init(struct SoundAllocPool *pool, void *memAddr, u32 size) { 304 pool->cur = pool->start = (u8 *) ALIGN16((uintptr_t) memAddr); 305 #if defined(VERSION_SH) || defined(VERSION_CN) 306 pool->size = size - ((uintptr_t) memAddr & 0xf); 307 #else 308 pool->size = size; 309 #endif 310 pool->numAllocatedEntries = 0; 311 } 312 313 void persistent_pool_clear(struct PersistentPool *persistent) { 314 persistent->pool.numAllocatedEntries = 0; 315 persistent->pool.cur = persistent->pool.start; 316 persistent->numEntries = 0; 317 } 318 319 void temporary_pool_clear(struct TemporaryPool *temporary) { 320 temporary->pool.numAllocatedEntries = 0; 321 temporary->pool.cur = temporary->pool.start; 322 temporary->nextSide = 0; 323 temporary->entries[0].ptr = temporary->pool.start; 324 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN) 325 temporary->entries[1].ptr = temporary->pool.start + temporary->pool.size; 326 #else 327 temporary->entries[1].ptr = temporary->pool.size + temporary->pool.start; 328 #endif 329 temporary->entries[0].id = -1; // should be at 1e not 1c 330 temporary->entries[1].id = -1; 331 } 332 333 void unused_803160F8(struct SoundAllocPool *pool) { 334 pool->numAllocatedEntries = 0; 335 pool->cur = pool->start; 336 } 337 338 extern s32 D_SH_80315EE8; 339 void sound_init_main_pools(s32 sizeForAudioInitPool) { 340 sound_alloc_pool_init(&gAudioInitPool, gAudioHeap, sizeForAudioInitPool); 341 sound_alloc_pool_init(&gAudioSessionPool, gAudioHeap + sizeForAudioInitPool, gAudioHeapSize - sizeForAudioInitPool); 342 } 343 344 #if defined(VERSION_SH) || defined(VERSION_CN) 345 #define SOUND_ALLOC_FUNC sound_alloc_uninitialized 346 #else 347 #define SOUND_ALLOC_FUNC soundAlloc 348 #endif 349 350 void session_pools_init(struct PoolSplit *a) { 351 gAudioSessionPool.cur = gAudioSessionPool.start; 352 sound_alloc_pool_init(&gNotesAndBuffersPool, SOUND_ALLOC_FUNC(&gAudioSessionPool, a->wantSeq), a->wantSeq); 353 sound_alloc_pool_init(&gSeqAndBankPool, SOUND_ALLOC_FUNC(&gAudioSessionPool, a->wantCustom), a->wantCustom); 354 } 355 356 void seq_and_bank_pool_init(struct PoolSplit2 *a) { 357 gSeqAndBankPool.cur = gSeqAndBankPool.start; 358 sound_alloc_pool_init(&gPersistentCommonPool, SOUND_ALLOC_FUNC(&gSeqAndBankPool, a->wantPersistent), a->wantPersistent); 359 sound_alloc_pool_init(&gTemporaryCommonPool, SOUND_ALLOC_FUNC(&gSeqAndBankPool, a->wantTemporary), a->wantTemporary); 360 } 361 362 void persistent_pools_init(struct PoolSplit *a) { 363 gPersistentCommonPool.cur = gPersistentCommonPool.start; 364 sound_alloc_pool_init(&gSeqLoadedPool.persistent.pool, SOUND_ALLOC_FUNC(&gPersistentCommonPool, a->wantSeq), a->wantSeq); 365 sound_alloc_pool_init(&gBankLoadedPool.persistent.pool, SOUND_ALLOC_FUNC(&gPersistentCommonPool, a->wantBank), a->wantBank); 366 sound_alloc_pool_init(&gUnusedLoadedPool.persistent.pool, SOUND_ALLOC_FUNC(&gPersistentCommonPool, a->wantUnused), 367 a->wantUnused); 368 persistent_pool_clear(&gSeqLoadedPool.persistent); 369 persistent_pool_clear(&gBankLoadedPool.persistent); 370 persistent_pool_clear(&gUnusedLoadedPool.persistent); 371 } 372 373 void temporary_pools_init(struct PoolSplit *a) { 374 gTemporaryCommonPool.cur = gTemporaryCommonPool.start; 375 sound_alloc_pool_init(&gSeqLoadedPool.temporary.pool, SOUND_ALLOC_FUNC(&gTemporaryCommonPool, a->wantSeq), a->wantSeq); 376 sound_alloc_pool_init(&gBankLoadedPool.temporary.pool, SOUND_ALLOC_FUNC(&gTemporaryCommonPool, a->wantBank), a->wantBank); 377 sound_alloc_pool_init(&gUnusedLoadedPool.temporary.pool, SOUND_ALLOC_FUNC(&gTemporaryCommonPool, a->wantUnused), 378 a->wantUnused); 379 temporary_pool_clear(&gSeqLoadedPool.temporary); 380 temporary_pool_clear(&gBankLoadedPool.temporary); 381 temporary_pool_clear(&gUnusedLoadedPool.temporary); 382 } 383 #undef SOUND_ALLOC_FUNC 384 385 #if defined(VERSION_JP) || defined(VERSION_US) 386 UNUSED static void unused_803163D4(void) { 387 } 388 #endif 389 390 #if defined(VERSION_SH) || defined(VERSION_CN) 391 void *alloc_bank_or_seq(s32 poolIdx, s32 size, s32 arg3, s32 id) { 392 #else 393 void *alloc_bank_or_seq(struct SoundMultiPool *arg0, s32 arg1, s32 size, s32 arg3, s32 id) { 394 #endif 395 // arg3 = 0, 1 or 2? 396 397 #if defined(VERSION_SH) || defined(VERSION_CN) 398 struct SoundMultiPool *arg0; 399 #define isSound poolIdx 400 #endif 401 struct TemporaryPool *tp; 402 struct SoundAllocPool *pool; 403 void *ret; 404 #if defined(VERSION_JP) || defined(VERSION_US) 405 u16 UNUSED _firstVal; 406 u16 UNUSED _secondVal; 407 #else 408 u16 firstVal; 409 u16 secondVal; 410 #endif 411 u32 nullID = -1; 412 UNUSED s32 i; 413 u8 *table; 414 #if !defined(VERSION_SH) && !defined(VERSION_CN) 415 u8 isSound; 416 #endif 417 #if defined(VERSION_JP) || defined(VERSION_US) 418 u16 firstVal; 419 u16 secondVal; 420 u32 bothDiscardable; 421 u32 leftDiscardable, rightDiscardable; 422 u32 leftNotLoaded, rightNotLoaded; 423 u32 leftAvail, rightAvail; 424 #endif 425 426 #if defined(VERSION_SH) || defined(VERSION_CN) 427 switch (poolIdx) { 428 case 0: 429 arg0 = &gSeqLoadedPool; 430 table = gSeqLoadStatus; 431 break; 432 433 case 1: 434 arg0 = &gBankLoadedPool; 435 table = gBankLoadStatus; 436 break; 437 438 case 2: 439 arg0 = &gUnusedLoadedPool; 440 table = gUnkLoadStatus; 441 break; 442 } 443 #endif 444 445 if (arg3 == 0) { 446 tp = &arg0->temporary; 447 #if !defined(VERSION_SH) && !defined(VERSION_CN) 448 if (arg0 == &gSeqLoadedPool) { 449 table = gSeqLoadStatus; 450 isSound = FALSE; 451 } else if (arg0 == &gBankLoadedPool) { 452 table = gBankLoadStatus; 453 isSound = TRUE; 454 } 455 #endif 456 457 #if defined(VERSION_SH) || defined(VERSION_CN) 458 if (tp->entries[0].id == (s8)nullID) { 459 firstVal = SOUND_LOAD_STATUS_NOT_LOADED; 460 } else { 461 firstVal = table[tp->entries[0].id]; 462 } 463 if (tp->entries[1].id == (s8)nullID) { 464 secondVal = SOUND_LOAD_STATUS_NOT_LOADED; 465 } else { 466 secondVal = table[tp->entries[1].id]; 467 } 468 #else 469 firstVal = (tp->entries[0].id == (s8)nullID ? SOUND_LOAD_STATUS_NOT_LOADED : table[tp->entries[0].id]); 470 secondVal = (tp->entries[1].id == (s8)nullID ? SOUND_LOAD_STATUS_NOT_LOADED : table[tp->entries[1].id]); 471 #endif 472 473 #if defined(VERSION_JP) || defined(VERSION_US) 474 leftNotLoaded = (firstVal == SOUND_LOAD_STATUS_NOT_LOADED); 475 leftDiscardable = (firstVal == SOUND_LOAD_STATUS_DISCARDABLE); 476 leftAvail = (firstVal != SOUND_LOAD_STATUS_IN_PROGRESS); 477 rightNotLoaded = (secondVal == SOUND_LOAD_STATUS_NOT_LOADED); 478 rightDiscardable = (secondVal == SOUND_LOAD_STATUS_DISCARDABLE); 479 rightAvail = (secondVal != SOUND_LOAD_STATUS_IN_PROGRESS); 480 bothDiscardable = (leftDiscardable && rightDiscardable); 481 482 if (leftNotLoaded) { 483 tp->nextSide = 0; 484 } else if (rightNotLoaded) { 485 tp->nextSide = 1; 486 } else if (bothDiscardable) { 487 // Use the opposite side from last time. 488 } else if (firstVal == SOUND_LOAD_STATUS_DISCARDABLE) { // ??! (I blame copt) 489 tp->nextSide = 0; 490 } else if (rightDiscardable) { 491 tp->nextSide = 1; 492 } else if (leftAvail) { 493 tp->nextSide = 0; 494 } else if (rightAvail) { 495 tp->nextSide = 1; 496 } else { 497 // Both left and right sides are being loaded into. 498 return NULL; 499 } 500 #else 501 #ifdef VERSION_EU 502 if (0) { 503 // It's unclear where these string literals go. 504 eu_stubbed_printf_0("DataHeap Not Allocate \n"); 505 eu_stubbed_printf_1("StayHeap Not Allocate %d\n", 0); 506 eu_stubbed_printf_1("AutoHeap Not Allocate %d\n", 0); 507 } 508 #endif 509 510 #if defined(VERSION_SH) || defined(VERSION_CN) 511 if (poolIdx == 1) { 512 if (firstVal == SOUND_LOAD_STATUS_4) { 513 for (i = 0; i < gMaxSimultaneousNotes; i++) { 514 if (gNotes[i].bankId == tp->entries[0].id && gNotes[i].noteSubEu.enabled) { 515 break; 516 } 517 } 518 if (i == gMaxSimultaneousNotes) { 519 if (gBankLoadStatus[tp->entries[0].id] != SOUND_LOAD_STATUS_5) { 520 gBankLoadStatus[tp->entries[0].id] = SOUND_LOAD_STATUS_DISCARDABLE; 521 } 522 firstVal = SOUND_LOAD_STATUS_DISCARDABLE; 523 } 524 } 525 if (secondVal == SOUND_LOAD_STATUS_4) { 526 for (i = 0; i < gMaxSimultaneousNotes; i++) { 527 if (gNotes[i].bankId == tp->entries[1].id && gNotes[i].noteSubEu.enabled) { 528 break; 529 } 530 } 531 if (i == gMaxSimultaneousNotes) { 532 if (gBankLoadStatus[tp->entries[1].id] != SOUND_LOAD_STATUS_5) { 533 gBankLoadStatus[tp->entries[1].id] = SOUND_LOAD_STATUS_DISCARDABLE; 534 } 535 secondVal = SOUND_LOAD_STATUS_DISCARDABLE; 536 } 537 } 538 } 539 #endif 540 541 if (firstVal == SOUND_LOAD_STATUS_NOT_LOADED) { 542 tp->nextSide = 0; 543 } else if (secondVal == SOUND_LOAD_STATUS_NOT_LOADED) { 544 tp->nextSide = 1; 545 } else { 546 eu_stubbed_printf_0("WARNING: NO FREE AUTOSEQ AREA.\n"); 547 if ((firstVal == SOUND_LOAD_STATUS_DISCARDABLE) && (secondVal == SOUND_LOAD_STATUS_DISCARDABLE)) { 548 // Use the opposite side from last time. 549 } else if (firstVal == SOUND_LOAD_STATUS_DISCARDABLE) { 550 tp->nextSide = 0; 551 } else if (secondVal == SOUND_LOAD_STATUS_DISCARDABLE) { 552 tp->nextSide = 1; 553 } else { 554 #ifdef VERSION_EU 555 eu_stubbed_printf_0("WARNING: NO STOP AUTO AREA.\n"); 556 eu_stubbed_printf_0(" AND TRY FORCE TO STOP SIDE \n"); 557 if (firstVal != SOUND_LOAD_STATUS_IN_PROGRESS) { 558 tp->nextSide = 0; 559 } else if (secondVal != SOUND_LOAD_STATUS_IN_PROGRESS) { 560 tp->nextSide = 1; 561 } else { 562 // Both left and right sides are being loaded into. 563 eu_stubbed_printf_0("TWO SIDES ARE LOADING... ALLOC CANCELED.\n"); 564 return NULL; 565 } 566 #else 567 if (poolIdx == 0) { 568 if (firstVal == SOUND_LOAD_STATUS_COMPLETE) { 569 for (i = 0; i < SEQUENCE_PLAYERS; i++) { 570 if (gSequencePlayers[i].enabled && gSequencePlayers[i].seqId == tp->entries[0].id) { 571 break; 572 } 573 } 574 if (i == SEQUENCE_PLAYERS) { 575 tp->nextSide = 0; 576 goto out; 577 } 578 } 579 if (secondVal == SOUND_LOAD_STATUS_COMPLETE) { 580 for (i = 0; i < SEQUENCE_PLAYERS; i++) { 581 if (gSequencePlayers[i].enabled && gSequencePlayers[i].seqId == tp->entries[1].id) { 582 break; 583 } 584 } 585 if (i == SEQUENCE_PLAYERS) { 586 tp->nextSide = 1; 587 goto out; 588 } 589 } 590 } else if (poolIdx == 1) { 591 if (firstVal == SOUND_LOAD_STATUS_COMPLETE) { 592 for (i = 0; i < gMaxSimultaneousNotes; i++) { 593 if (gNotes[i].bankId == tp->entries[0].id && gNotes[i].noteSubEu.enabled) { 594 break; 595 } 596 } 597 if (i == gMaxSimultaneousNotes) { 598 tp->nextSide = 0; 599 goto out; 600 } 601 } 602 if (secondVal == SOUND_LOAD_STATUS_COMPLETE) { 603 for (i = 0; i < gMaxSimultaneousNotes; i++) { 604 if (gNotes[i].bankId == tp->entries[1].id && gNotes[i].noteSubEu.enabled) { 605 break; 606 } 607 } 608 if (i == gMaxSimultaneousNotes) { 609 tp->nextSide = 1; 610 goto out; 611 } 612 } 613 } 614 if (tp->nextSide == 0) { 615 if (firstVal == SOUND_LOAD_STATUS_IN_PROGRESS) { 616 if (secondVal != SOUND_LOAD_STATUS_IN_PROGRESS) { 617 tp->nextSide = 1; 618 goto out; 619 } 620 } else { 621 goto out; 622 } 623 } else { 624 if (secondVal == SOUND_LOAD_STATUS_IN_PROGRESS) { 625 if (firstVal != SOUND_LOAD_STATUS_IN_PROGRESS) { 626 tp->nextSide = 0; 627 goto out; 628 } 629 } else { 630 goto out; 631 } 632 } 633 return NULL; 634 out:; 635 #endif 636 } 637 } 638 #endif 639 640 pool = &arg0->temporary.pool; 641 if (tp->entries[tp->nextSide].id != (s8)nullID) { 642 table[tp->entries[tp->nextSide].id] = SOUND_LOAD_STATUS_NOT_LOADED; 643 if (isSound == TRUE) { 644 discard_bank(tp->entries[tp->nextSide].id); 645 } 646 } 647 648 switch (tp->nextSide) { 649 case 0: 650 tp->entries[0].ptr = pool->start; 651 tp->entries[0].id = id; 652 tp->entries[0].size = size; 653 654 pool->cur = pool->start + size; 655 656 #if defined(VERSION_SH) || defined(VERSION_CN) 657 if (tp->entries[1].id != (s32)nullID) 658 #endif 659 if (tp->entries[1].ptr < pool->cur) { 660 eu_stubbed_printf_0("WARNING: Before Area Overlaid After."); 661 662 // Throw out the entry on the other side if it doesn't fit. 663 // (possible @bug: what if it's currently being loaded?) 664 table[tp->entries[1].id] = SOUND_LOAD_STATUS_NOT_LOADED; 665 666 switch (isSound) { 667 case FALSE: 668 discard_sequence(tp->entries[1].id); 669 break; 670 case TRUE: 671 discard_bank(tp->entries[1].id); 672 break; 673 } 674 675 tp->entries[1].id = (s32)nullID; 676 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN) 677 tp->entries[1].ptr = pool->start + pool->size; 678 #else 679 tp->entries[1].ptr = pool->size + pool->start; 680 #endif 681 } 682 683 ret = tp->entries[0].ptr; 684 break; 685 686 case 1: 687 #if defined(VERSION_SH) || defined(VERSION_CN) 688 tp->entries[1].ptr = (u8 *) ((uintptr_t) (pool->start + pool->size - size) & ~0x0f); 689 #elif defined(VERSION_EU) 690 tp->entries[1].ptr = pool->start + pool->size - size - 0x10; 691 #else 692 tp->entries[1].ptr = pool->size + pool->start - size - 0x10; 693 #endif 694 tp->entries[1].id = id; 695 tp->entries[1].size = size; 696 697 #if defined(VERSION_SH) || defined(VERSION_CN) 698 if (tp->entries[0].id != (s32)nullID) 699 #endif 700 if (tp->entries[1].ptr < pool->cur) { 701 eu_stubbed_printf_0("WARNING: After Area Overlaid Before."); 702 703 table[tp->entries[0].id] = SOUND_LOAD_STATUS_NOT_LOADED; 704 705 switch (isSound) { 706 case FALSE: 707 discard_sequence(tp->entries[0].id); 708 break; 709 case TRUE: 710 discard_bank(tp->entries[0].id); 711 break; 712 } 713 714 tp->entries[0].id = (s32)nullID; 715 pool->cur = pool->start; 716 } 717 718 ret = tp->entries[1].ptr; 719 break; 720 721 default: 722 eu_stubbed_printf_1("MEMORY:SzHeapAlloc ERROR: sza->side %d\n", tp->nextSide); 723 return NULL; 724 } 725 726 // Switch sides for next time in case both entries are 727 // SOUND_LOAD_STATUS_DISCARDABLE. 728 tp->nextSide ^= 1; 729 730 return ret; 731 } 732 733 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN) 734 #if defined(VERSION_SH) || defined(VERSION_CN) 735 ret = sound_alloc_uninitialized(&arg0->persistent.pool, size); 736 #else 737 ret = soundAlloc(&arg0->persistent.pool, arg1 * size); 738 #endif 739 arg0->persistent.entries[arg0->persistent.numEntries].ptr = ret; 740 741 if (ret == NULL) 742 #else 743 arg0->persistent.entries[arg0->persistent.numEntries].ptr = soundAlloc(&arg0->persistent.pool, arg1 * size); 744 745 if (arg0->persistent.entries[arg0->persistent.numEntries].ptr == NULL) 746 #endif 747 { 748 switch (arg3) { 749 case 2: 750 #if defined(VERSION_EU) 751 eu_stubbed_printf_0("MEMORY:StayHeap OVERFLOW."); 752 return alloc_bank_or_seq(arg0, arg1, size, 0, id); 753 #elif defined(VERSION_SH) || defined(VERSION_CN) 754 return alloc_bank_or_seq(poolIdx, size, 0, id); 755 #else 756 // Prevent tail call optimization. 757 ret = alloc_bank_or_seq(arg0, arg1, size, 0, id); 758 return ret; 759 #endif 760 case 1: 761 #if defined(VERSION_SH) || defined(VERSION_CN) 762 case 0: 763 #endif 764 eu_stubbed_printf_1("MEMORY:StayHeap OVERFLOW (REQ:%d)", arg1 * size); 765 return NULL; 766 } 767 } 768 769 // TODO: why is this guaranteed to write <= 32 entries...? 770 // Because the buffer is small enough that more don't fit? 771 arg0->persistent.entries[arg0->persistent.numEntries].id = id; 772 arg0->persistent.entries[arg0->persistent.numEntries].size = size; 773 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN) 774 return arg0->persistent.entries[arg0->persistent.numEntries++].ptr; 775 #else 776 arg0->persistent.numEntries++; return arg0->persistent.entries[arg0->persistent.numEntries - 1].ptr; 777 #endif 778 #if defined(VERSION_SH) || defined(VERSION_CN) 779 #undef isSound 780 #endif 781 } 782 783 #if defined(VERSION_SH) || defined(VERSION_CN) 784 void *get_bank_or_seq(s32 poolIdx, s32 arg1, s32 id) { 785 void *ret; 786 787 ret = unk_pool1_lookup(poolIdx, id); 788 if (ret != NULL) { 789 return ret; 790 } 791 if (arg1 == 3) { 792 return NULL; 793 } 794 return get_bank_or_seq_inner(poolIdx, arg1, id); 795 } 796 void *get_bank_or_seq_inner(s32 poolIdx, s32 arg1, s32 bankId) { 797 u32 i; 798 struct SoundMultiPool* loadedPool; 799 struct TemporaryPool* temporary; 800 struct PersistentPool* persistent; 801 802 switch (poolIdx) { 803 case 0: 804 loadedPool = &gSeqLoadedPool; 805 break; 806 case 1: 807 loadedPool = &gBankLoadedPool; 808 break; 809 case 2: 810 loadedPool = &gUnusedLoadedPool; 811 break; 812 } 813 814 temporary = &loadedPool->temporary; 815 if (arg1 == 0) { 816 if (temporary->entries[0].id == bankId) { 817 temporary->nextSide = 1; 818 return temporary->entries[0].ptr; 819 } else if (temporary->entries[1].id == bankId) { 820 temporary->nextSide = 0; 821 return temporary->entries[1].ptr; 822 } else { 823 return NULL; 824 } 825 } 826 827 persistent = &loadedPool->persistent; 828 for (i = 0; i < persistent->numEntries; i++) { 829 if (persistent->entries[i].id == bankId) { 830 return persistent->entries[i].ptr; 831 } 832 } 833 834 if (arg1 == 2) { 835 return get_bank_or_seq(poolIdx, 0, bankId); 836 } 837 return NULL; 838 } 839 #endif 840 #if !defined(VERSION_SH) && !defined(VERSION_CN) 841 void *get_bank_or_seq(struct SoundMultiPool *arg0, s32 arg1, s32 id) { 842 u32 i; 843 UNUSED void *ret; 844 struct TemporaryPool *temporary = &arg0->temporary; 845 846 if (arg1 == 0) { 847 // Try not to overwrite sound that we have just accessed, by setting nextSide appropriately. 848 if (temporary->entries[0].id == id) { 849 temporary->nextSide = 1; 850 return temporary->entries[0].ptr; 851 } else if (temporary->entries[1].id == id) { 852 temporary->nextSide = 0; 853 return temporary->entries[1].ptr; 854 } 855 eu_stubbed_printf_1("Auto Heap Unhit for ID %d\n", id); 856 return NULL; 857 } else { 858 struct PersistentPool *persistent = &arg0->persistent; 859 for (i = 0; i < persistent->numEntries; i++) { 860 if (id == persistent->entries[i].id) { 861 eu_stubbed_printf_2("Cache hit %d at stay %d\n", id, i); 862 return persistent->entries[i].ptr; 863 } 864 } 865 866 if (arg1 == 2) { 867 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN) 868 return get_bank_or_seq(arg0, 0, id); 869 #else 870 // Prevent tail call optimization by using a temporary. 871 // Either copt or -Wo,-notail. 872 ret = get_bank_or_seq(arg0, 0, id); 873 return ret; 874 #endif 875 } 876 return NULL; 877 } 878 } 879 #endif 880 881 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN) 882 void func_eu_802e27e4_unused(f32 arg0, f32 arg1, u16 *arg2) { 883 s32 i; 884 f32 tmp[16]; 885 886 tmp[0] = (f32) (arg1 * 262159.0f); 887 tmp[8] = (f32) (arg0 * 262159.0f); 888 tmp[1] = (f32) ((arg1 * arg0) * 262159.0f); 889 tmp[9] = (f32) (((arg0 * arg0) + arg1) * 262159.0f); 890 891 for (i = 2; i < 8; i++) { 892 //! @bug they probably meant to store the value to tmp[i] and tmp[8 + i] 893 arg2[i] = arg1 * tmp[i - 2] + arg0 * tmp[i - 1]; 894 arg2[8 + i] = arg1 * tmp[6 + i] + arg0 * tmp[7 + i]; 895 } 896 897 for (i = 0; i < 16; i++) { 898 arg2[i] = tmp[i]; 899 } 900 901 #ifdef VERSION_EU 902 for (i = 0; i < 8; i++) { 903 eu_stubbed_printf_1("%d ", arg2[i]); 904 } 905 eu_stubbed_printf_0("\n"); 906 907 for (i = 8; i < 16; i++) { 908 eu_stubbed_printf_1("%d ", arg2[i]); 909 } 910 eu_stubbed_printf_0("\n"); 911 #endif 912 } 913 #endif 914 915 #if defined(VERSION_SH) || defined(VERSION_CN) 916 void fill_zero_filter(s16 filter[]) { 917 s32 i; 918 for (i = 0; i < 8; i++) { 919 filter[i] = 0; 920 } 921 } 922 923 extern s16 unk_sh_data_3[15 * 8]; 924 extern s16 unk_sh_data_4[15 * 8]; 925 void func_sh_802F0DE8(s16 filter[8], s32 arg1) { 926 s32 i; 927 s16 *ptr = &unk_sh_data_3[8 * (arg1 - 1)]; 928 for (i = 0; i < 8; i++) { 929 filter[i] = ptr[i]; 930 } 931 } 932 933 void func_sh_802F0E40(s16 filter[8], s32 arg1) { // Unused 934 s32 i; 935 s16 *ptr = &unk_sh_data_4[8 * (arg1 - 1)]; 936 for (i = 0; i < 8; i++) { 937 filter[i] = ptr[i]; 938 } 939 } 940 941 void fill_filter(s16 filter[8], s32 arg1, s32 arg2) { 942 s32 i; 943 s16 *ptr; 944 if (arg1 != 0) { 945 func_sh_802F0DE8(filter, arg1); 946 } else { 947 fill_zero_filter(filter); 948 } 949 if (arg2 != 0) { 950 ptr = &unk_sh_data_4[8 * (arg2 - 1)]; 951 for (i = 0; i < 8; i++) { 952 filter[i] += ptr[i]; 953 } 954 } 955 } 956 #endif 957 958 void decrease_reverb_gain(void) { 959 #if defined(VERSION_EU) 960 s32 i; 961 for (i = 0; i < gNumSynthesisReverbs; i++) { 962 gSynthesisReverbs[i].reverbGain -= gSynthesisReverbs[i].reverbGain / 8; 963 } 964 #elif defined(VERSION_JP) || defined(VERSION_US) 965 gSynthesisReverb.reverbGain -= gSynthesisReverb.reverbGain / 4; 966 #else 967 s32 i, j; 968 s32 v0 = gAudioBufferParameters.presetUnk4 == 2 ? 2 : 1; 969 for (i = 0; i < gNumSynthesisReverbs; i++) { 970 for (j = 0; j < v0; j++) { 971 gSynthesisReverbs[i].reverbGain -= gSynthesisReverbs[i].reverbGain / 3; 972 } 973 } 974 #endif 975 } 976 977 #if defined(VERSION_SH) || defined(VERSION_CN) 978 void clear_curr_ai_buffer(void) { 979 s32 currIndex = gCurrAiBufferIndex; 980 s32 i; 981 gAiBufferLengths[currIndex] = gAudioBufferParameters.minAiBufferLength; 982 for (i = 0; i < (s32) (AIBUFFER_LEN / sizeof(s16)); i++) { 983 gAiBuffers[currIndex][i] = 0; 984 } 985 } 986 #endif 987 988 989 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN) 990 s32 audio_shut_down_and_reset_step(void) { 991 s32 i; 992 s32 j; 993 #if defined(VERSION_SH) || defined(VERSION_CN) 994 s32 num = gAudioBufferParameters.presetUnk4 == 2 ? 2 : 1; 995 #endif 996 997 switch (gAudioResetStatus) { 998 case 5: 999 for (i = 0; i < SEQUENCE_PLAYERS; i++) { 1000 sequence_player_disable(&gSequencePlayers[i]); 1001 } 1002 #if defined(VERSION_SH) || defined(VERSION_CN) 1003 gAudioResetFadeOutFramesLeft = 4 / num; 1004 #else 1005 gAudioResetFadeOutFramesLeft = 4; 1006 #endif 1007 gAudioResetStatus--; 1008 break; 1009 case 4: 1010 if (gAudioResetFadeOutFramesLeft != 0) { 1011 gAudioResetFadeOutFramesLeft--; 1012 decrease_reverb_gain(); 1013 } else { 1014 for (i = 0; i < gMaxSimultaneousNotes; i++) { 1015 if (gNotes[i].noteSubEu.enabled && gNotes[i].adsr.state != ADSR_STATE_DISABLED) { 1016 gNotes[i].adsr.fadeOutVel = gAudioBufferParameters.updatesPerFrameInv; 1017 gNotes[i].adsr.action |= ADSR_ACTION_RELEASE; 1018 } 1019 } 1020 #if defined(VERSION_SH) || defined(VERSION_CN) 1021 gAudioResetFadeOutFramesLeft = 16 / num; 1022 #else 1023 gAudioResetFadeOutFramesLeft = 16; 1024 #endif 1025 gAudioResetStatus--; 1026 } 1027 break; 1028 case 3: 1029 if (gAudioResetFadeOutFramesLeft != 0) { 1030 gAudioResetFadeOutFramesLeft--; 1031 #if defined(VERSION_SH) || defined(VERSION_CN) 1032 if (1) { 1033 } 1034 #endif 1035 decrease_reverb_gain(); 1036 } else { 1037 for (i = 0; i < NUMAIBUFFERS; i++) { 1038 for (j = 0; j < (s32) (AIBUFFER_LEN / sizeof(s16)); j++) { 1039 gAiBuffers[i][j] = 0; 1040 } 1041 } 1042 #if defined(VERSION_SH) || defined(VERSION_CN) 1043 gAudioResetFadeOutFramesLeft = 4 / num; 1044 #else 1045 gAudioResetFadeOutFramesLeft = 4; 1046 #endif 1047 gAudioResetStatus--; 1048 } 1049 break; 1050 case 2: 1051 #if defined(VERSION_SH) || defined(VERSION_CN) 1052 clear_curr_ai_buffer(); 1053 #endif 1054 if (gAudioResetFadeOutFramesLeft != 0) { 1055 gAudioResetFadeOutFramesLeft--; 1056 } else { 1057 gAudioResetStatus--; 1058 #if defined(VERSION_SH) || defined(VERSION_CN) 1059 func_sh_802f23ec(); 1060 #endif 1061 } 1062 break; 1063 case 1: 1064 audio_reset_session(); 1065 gAudioResetStatus = 0; 1066 #if defined(VERSION_SH) || defined(VERSION_CN) 1067 for (i = 0; i < NUMAIBUFFERS; i++) { 1068 gAiBufferLengths[i] = gAudioBufferParameters.maxAiBufferLength; 1069 for (j = 0; j < (s32) (AIBUFFER_LEN / sizeof(s16)); j++) { 1070 gAiBuffers[i][j] = 0; 1071 } 1072 } 1073 #endif 1074 } 1075 #if defined(VERSION_SH) || defined(VERSION_CN) 1076 if (gAudioResetFadeOutFramesLeft) { 1077 } 1078 #endif 1079 if (gAudioResetStatus < 3) { 1080 return 0; 1081 } 1082 return 1; 1083 } 1084 #else 1085 /** 1086 * Waits until a specified number of audio frames have been created 1087 */ 1088 void wait_for_audio_frames(s32 frames) { 1089 gAudioFrameCount = 0; 1090 // Sound thread will update gAudioFrameCount 1091 while (gAudioFrameCount < frames) { 1092 // spin 1093 } 1094 } 1095 #endif 1096 1097 #if defined(VERSION_JP) || defined(VERSION_US) 1098 void audio_reset_session(struct AudioSessionSettings *preset) { 1099 #else 1100 void audio_reset_session(void) { 1101 struct AudioSessionSettingsEU *preset = &gAudioSessionPresets[gAudioResetPresetIdToLoad]; 1102 struct ReverbSettingsEU *reverbSettings; 1103 #endif 1104 s16 *mem; 1105 #if defined(VERSION_JP) || defined(VERSION_US) 1106 s8 updatesPerFrame; 1107 s32 reverbWindowSize; 1108 s32 k; 1109 #endif 1110 s32 i; 1111 s32 j; 1112 s32 persistentMem; 1113 s32 temporaryMem; 1114 s32 totalMem; 1115 s32 wantMisc; 1116 #if defined(VERSION_JP) || defined(VERSION_US) 1117 s32 frames; 1118 s32 remainingDmas; 1119 #else 1120 struct SynthesisReverb *reverb; 1121 #endif 1122 eu_stubbed_printf_1("Heap Reconstruct Start %x\n", gAudioResetPresetIdToLoad); 1123 1124 #if defined(VERSION_JP) || defined(VERSION_US) 1125 if (gAudioLoadLock != AUDIO_LOCK_UNINITIALIZED) { 1126 decrease_reverb_gain(); 1127 for (i = 0; i < gMaxSimultaneousNotes; i++) { 1128 if (gNotes[i].enabled && gNotes[i].adsr.state != ADSR_STATE_DISABLED) { 1129 gNotes[i].adsr.fadeOutVel = 0x8000 / gAudioUpdatesPerFrame; 1130 gNotes[i].adsr.action |= ADSR_ACTION_RELEASE; 1131 } 1132 } 1133 1134 // Wait for all notes to stop playing 1135 frames = 0; 1136 for (;;) { 1137 wait_for_audio_frames(1); 1138 frames++; 1139 if (frames > 4 * 60) { 1140 // Break after 4 seconds 1141 break; 1142 } 1143 1144 for (i = 0; i < gMaxSimultaneousNotes; i++) { 1145 if (gNotes[i].enabled) { 1146 break; 1147 } 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) || defined(VERSION_CN) 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 #if defined(VERSION_SH) || defined(VERSION_CN) 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 #if defined(VERSION_SH) || defined(VERSION_CN) 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 #if defined(VERSION_SH) || defined(VERSION_CN) 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) || defined(VERSION_CN) 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 #if defined(VERSION_SH) || defined(VERSION_CN) 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 #if defined(VERSION_SH) || defined(VERSION_CN) 1298 sTemporaryCommonPoolSplit.wantUnused = preset->unk24; 1299 #else 1300 sTemporaryCommonPoolSplit.wantUnused = 0; 1301 #endif 1302 temporary_pools_init(&sTemporaryCommonPoolSplit); 1303 #if defined(VERSION_SH) || defined(VERSION_CN) 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) || defined(VERSION_CN) 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 #if defined(VERSION_SH) || defined(VERSION_CN) 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 #if defined(VERSION_SH) || defined(VERSION_CN) 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 #if defined(VERSION_SH) || defined(VERSION_CN) 1356 reverb->resampleFlags = A_INIT; 1357 #endif 1358 if (reverb->downsampleRate != 1) { 1359 #if !defined(VERSION_SH) && !defined(VERSION_CN) 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 #if defined(VERSION_SH) || defined(VERSION_CN) 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 #if defined(VERSION_SH) || defined(VERSION_CN) 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 #if defined(VERSION_SH) || defined(VERSION_CN) 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