synthesis_sh.c (38727B)
1 #if defined(VERSION_SH) || defined(VERSION_CN) 2 #include <ultra64.h> 3 4 #include "synthesis.h" 5 #include "heap.h" 6 #include "data.h" 7 #include "load.h" 8 #include "seqplayer.h" 9 #include "internal.h" 10 #include "external.h" 11 12 13 #define DMEM_ADDR_TEMP 0x450 14 #define DMEM_ADDR_RESAMPLED 0x470 15 #define DMEM_ADDR_RESAMPLED2 0x5f0 16 #define DMEM_ADDR_UNCOMPRESSED_NOTE 0x5f0 17 #define DMEM_ADDR_NOTE_PAN_TEMP 0x650 18 #define DMEM_ADDR_COMPRESSED_ADPCM_DATA 0x990 19 #define DMEM_ADDR_LEFT_CH 0x990 20 #define DMEM_ADDR_RIGHT_CH 0xb10 21 #define DMEM_ADDR_WET_LEFT_CH 0xc90 22 #define DMEM_ADDR_WET_RIGHT_CH 0xe10 23 24 #define aSetLoadBufferPair(pkt, c, off) \ 25 aSetBuffer(pkt, 0, c + DMEM_ADDR_WET_LEFT_CH, 0, DEFAULT_LEN_1CH - c); \ 26 aLoadBuffer(pkt, VIRTUAL_TO_PHYSICAL2(gSynthesisReverb.ringBuffer.left + (off))); \ 27 aSetBuffer(pkt, 0, c + DMEM_ADDR_WET_RIGHT_CH, 0, DEFAULT_LEN_1CH - c); \ 28 aLoadBuffer(pkt, VIRTUAL_TO_PHYSICAL2(gSynthesisReverb.ringBuffer.right + (off))) 29 30 #define aSetSaveBufferPair(pkt, c, d, off) \ 31 aSetBuffer(pkt, 0, 0, c + DMEM_ADDR_WET_LEFT_CH, d); \ 32 aSaveBuffer(pkt, VIRTUAL_TO_PHYSICAL2(gSynthesisReverb.ringBuffer.left + (off))); \ 33 aSetBuffer(pkt, 0, 0, c + DMEM_ADDR_WET_RIGHT_CH, d); \ 34 aSaveBuffer(pkt, VIRTUAL_TO_PHYSICAL2(gSynthesisReverb.ringBuffer.right + (off))); 35 36 #define ALIGN(val, amnt) (((val) + (1 << amnt) - 1) & ~((1 << amnt) - 1)) 37 38 struct VolumeChange { 39 u16 sourceLeft; 40 u16 sourceRight; 41 u16 targetLeft; 42 u16 targetRight; 43 }; 44 45 u64 *synthesis_do_one_audio_update(s16 *aiBuf, s32 bufLen, u64 *cmd, s32 updateIndex); 46 u64 *synthesis_process_note(s32 noteIndex, struct NoteSubEu *noteSubEu, struct NoteSynthesisState *synthesisState, s16 *aiBuf, s32 bufLen, u64 *cmd, s32 updateIndex); 47 u64 *load_wave_samples(u64 *cmd, struct NoteSubEu *noteSubEu, struct NoteSynthesisState *synthesisState, s32 nSamplesToLoad); 48 u64 *final_resample(u64 *cmd, struct NoteSynthesisState *synthesisState, s32 count, u16 pitch, u16 dmemIn, u32 flags); 49 u64 *process_envelope(u64 *cmd, struct NoteSubEu *noteSubEu, struct NoteSynthesisState *synthesisState, s32 nSamples, u16 inBuf, s32 headsetPanSettings, u32 flags); 50 u64 *note_apply_headset_pan_effects(u64 *cmd, struct NoteSubEu *noteSubEu, struct NoteSynthesisState *note, s32 bufLen, s32 flags, s32 leftRight); 51 52 struct SynthesisReverb gSynthesisReverbs[4]; 53 u8 sAudioSynthesisPad[0x10]; 54 55 s16 gVolume; 56 s8 gUseReverb; 57 s8 gNumSynthesisReverbs; 58 s16 D_SH_803479B4; // contains 4096 59 struct NoteSubEu *gNoteSubsEu; 60 61 // Equivalent functionality as the US/JP version, 62 // just that the reverb structure is chosen from an array with index 63 // Identical in EU. 64 void prepare_reverb_ring_buffer(s32 chunkLen, u32 updateIndex, s32 reverbIndex) { 65 struct ReverbRingBufferItem *item; 66 struct SynthesisReverb *reverb = &gSynthesisReverbs[reverbIndex]; 67 s32 srcPos; 68 s32 dstPos; 69 s32 nSamples; 70 s32 excessiveSamples; 71 s32 UNUSED pad[3]; 72 if (reverb->downsampleRate != 1) { 73 if (reverb->framesLeftToIgnore == 0) { 74 // Now that the RSP has finished, downsample the samples produced two frames ago by skipping 75 // samples. 76 item = &reverb->items[reverb->curFrame][updateIndex]; 77 78 // Touches both left and right since they are adjacent in memory 79 osInvalDCache(item->toDownsampleLeft, DEFAULT_LEN_2CH); 80 81 for (srcPos = 0, dstPos = 0; dstPos < item->lengthA / 2; 82 srcPos += reverb->downsampleRate, dstPos++) { 83 reverb->ringBuffer.left[item->startPos + dstPos] = 84 item->toDownsampleLeft[srcPos]; 85 reverb->ringBuffer.right[item->startPos + dstPos] = 86 item->toDownsampleRight[srcPos]; 87 } 88 for (dstPos = 0; dstPos < item->lengthB / 2; srcPos += reverb->downsampleRate, dstPos++) { 89 reverb->ringBuffer.left[dstPos] = item->toDownsampleLeft[srcPos]; 90 reverb->ringBuffer.right[dstPos] = item->toDownsampleRight[srcPos]; 91 } 92 } 93 } 94 95 item = &reverb->items[reverb->curFrame][updateIndex]; 96 nSamples = chunkLen / reverb->downsampleRate; 97 excessiveSamples = (nSamples + reverb->nextRingBufferPos) - reverb->bufSizePerChannel; 98 if (excessiveSamples < 0) { 99 // There is space in the ring buffer before it wraps around 100 item->lengthA = nSamples * 2; 101 item->lengthB = 0; 102 item->startPos = (s32) reverb->nextRingBufferPos; 103 reverb->nextRingBufferPos += nSamples; 104 } else { 105 // Ring buffer wrapped around 106 item->lengthA = (nSamples - excessiveSamples) * 2; 107 item->lengthB = excessiveSamples * 2; 108 item->startPos = reverb->nextRingBufferPos; 109 reverb->nextRingBufferPos = excessiveSamples; 110 } 111 // These fields are never read later 112 item->numSamplesAfterDownsampling = nSamples; 113 item->chunkLen = chunkLen; 114 } 115 116 u64 *synthesis_load_reverb_ring_buffer(u64 *cmd, u16 addr, u16 srcOffset, s32 len, s32 reverbIndex) { 117 aLoadBuffer(cmd++, VIRTUAL_TO_PHYSICAL2(&gSynthesisReverbs[reverbIndex].ringBuffer.left[srcOffset]), 118 addr, len); 119 aLoadBuffer(cmd++, VIRTUAL_TO_PHYSICAL2(&gSynthesisReverbs[reverbIndex].ringBuffer.right[srcOffset]), 120 addr + DEFAULT_LEN_1CH, len); 121 return cmd; 122 } 123 124 u64 *synthesis_save_reverb_ring_buffer(u64 *cmd, u16 addr, u16 destOffset, s32 len, s32 reverbIndex) { 125 aSaveBuffer(cmd++, addr, 126 VIRTUAL_TO_PHYSICAL2(&gSynthesisReverbs[reverbIndex].ringBuffer.left[destOffset]), len); 127 aSaveBuffer(cmd++, addr + DEFAULT_LEN_1CH, 128 VIRTUAL_TO_PHYSICAL2(&gSynthesisReverbs[reverbIndex].ringBuffer.right[destOffset]), len); 129 return cmd; 130 } 131 132 void func_sh_802ed644(s32 updateIndexStart, s32 noteIndex) { 133 s32 i; 134 135 for (i = updateIndexStart + 1; i < gAudioBufferParameters.updatesPerFrame; i++) { 136 if (!gNoteSubsEu[gMaxSimultaneousNotes * i + noteIndex].needsInit) { 137 gNoteSubsEu[gMaxSimultaneousNotes * i + noteIndex].enabled = FALSE; 138 } else { 139 break; 140 } 141 } 142 } 143 144 void synthesis_load_note_subs_eu(s32 updateIndex) { 145 struct NoteSubEu *src; 146 struct NoteSubEu *dest; 147 s32 i; 148 149 for (i = 0; i < gMaxSimultaneousNotes; i++) { 150 src = &gNotes[i].noteSubEu; 151 dest = &gNoteSubsEu[gMaxSimultaneousNotes * updateIndex + i]; 152 if (src->enabled) { 153 *dest = *src; 154 src->needsInit = FALSE; 155 } else { 156 dest->enabled = FALSE; 157 } 158 } 159 } 160 161 // TODO: (Scrub C) pointless mask and whitespace 162 u64 *synthesis_execute(u64 *cmdBuf, s32 *writtenCmds, s16 *aiBuf, s32 bufLen) { 163 s32 i, j; 164 u32 *aiBufPtr; 165 u64 *cmd = cmdBuf; 166 s32 chunkLen; 167 168 for (i = gAudioBufferParameters.updatesPerFrame; i > 0; i--) { 169 process_sequences(i - 1); 170 synthesis_load_note_subs_eu(gAudioBufferParameters.updatesPerFrame - i); 171 } 172 aiBufPtr = (u32 *) aiBuf; 173 for (i = gAudioBufferParameters.updatesPerFrame; i > 0; i--) { 174 if (i == 1) { 175 chunkLen = bufLen; 176 } else { 177 if (bufLen / i >= gAudioBufferParameters.samplesPerUpdateMax) { 178 chunkLen = gAudioBufferParameters.samplesPerUpdateMax; 179 } else if (bufLen / i <= gAudioBufferParameters.samplesPerUpdateMin) { 180 chunkLen = gAudioBufferParameters.samplesPerUpdateMin; 181 } else { 182 chunkLen = gAudioBufferParameters.samplesPerUpdate; 183 } 184 } 185 for (j = 0; j < gNumSynthesisReverbs; j++) { 186 if (gSynthesisReverbs[j].useReverb != 0) { 187 prepare_reverb_ring_buffer(chunkLen, gAudioBufferParameters.updatesPerFrame - i, j); 188 } 189 } 190 cmd = synthesis_do_one_audio_update((s16 *) aiBufPtr, chunkLen, cmd, gAudioBufferParameters.updatesPerFrame - i); 191 bufLen -= chunkLen; 192 aiBufPtr += chunkLen; 193 } 194 195 for (j = 0; j < gNumSynthesisReverbs; j++) { 196 if (gSynthesisReverbs[j].framesLeftToIgnore != 0) { 197 gSynthesisReverbs[j].framesLeftToIgnore--; 198 } 199 gSynthesisReverbs[j].curFrame ^= 1; 200 } 201 *writtenCmds = cmd - cmdBuf; 202 return cmd; 203 } 204 205 u64 *synthesis_resample_and_mix_reverb(u64 *cmd, s32 bufLen, s16 reverbIndex, s16 updateIndex) { 206 struct ReverbRingBufferItem *item; 207 s16 startPad; 208 s16 paddedLengthA; 209 210 item = &gSynthesisReverbs[reverbIndex].items[gSynthesisReverbs[reverbIndex].curFrame][updateIndex]; 211 212 if (gSynthesisReverbs[reverbIndex].downsampleRate == 1) { 213 cmd = synthesis_load_reverb_ring_buffer(cmd, DMEM_ADDR_WET_LEFT_CH, item->startPos, item->lengthA, reverbIndex); 214 if (item->lengthB != 0) { 215 cmd = synthesis_load_reverb_ring_buffer(cmd, DMEM_ADDR_WET_LEFT_CH + item->lengthA, 0, item->lengthB, reverbIndex); 216 } 217 aAddMixer(cmd++, DMEM_ADDR_WET_LEFT_CH, DMEM_ADDR_LEFT_CH, DEFAULT_LEN_2CH); 218 aMix(cmd++, 0x8000 + gSynthesisReverbs[reverbIndex].reverbGain, DMEM_ADDR_WET_LEFT_CH, DMEM_ADDR_WET_LEFT_CH, DEFAULT_LEN_2CH); 219 } else { 220 startPad = (item->startPos % 8u) * 2; 221 paddedLengthA = ALIGN(startPad + item->lengthA, 4); 222 223 cmd = synthesis_load_reverb_ring_buffer(cmd, DMEM_ADDR_RESAMPLED, (item->startPos - startPad / 2), DEFAULT_LEN_1CH, reverbIndex); 224 if (item->lengthB != 0) { 225 cmd = synthesis_load_reverb_ring_buffer(cmd, DMEM_ADDR_RESAMPLED + paddedLengthA, 0, DEFAULT_LEN_1CH - paddedLengthA, reverbIndex); 226 } 227 228 aSetBuffer(cmd++, 0, DMEM_ADDR_RESAMPLED + startPad, DMEM_ADDR_WET_LEFT_CH, bufLen * 2); 229 aResample(cmd++, gSynthesisReverbs[reverbIndex].resampleFlags, gSynthesisReverbs[reverbIndex].resampleRate, VIRTUAL_TO_PHYSICAL2(gSynthesisReverbs[reverbIndex].resampleStateLeft)); 230 231 aSetBuffer(cmd++, 0, DMEM_ADDR_RESAMPLED2 + startPad, DMEM_ADDR_WET_RIGHT_CH, bufLen * 2); 232 aResample(cmd++, gSynthesisReverbs[reverbIndex].resampleFlags, gSynthesisReverbs[reverbIndex].resampleRate, VIRTUAL_TO_PHYSICAL2(gSynthesisReverbs[reverbIndex].resampleStateRight)); 233 234 aAddMixer(cmd++, DMEM_ADDR_WET_LEFT_CH, DMEM_ADDR_LEFT_CH, DEFAULT_LEN_2CH); 235 aMix(cmd++, 0x8000 + gSynthesisReverbs[reverbIndex].reverbGain, DMEM_ADDR_WET_LEFT_CH, DMEM_ADDR_WET_LEFT_CH, DEFAULT_LEN_2CH); 236 } 237 if (gSynthesisReverbs[reverbIndex].panRight != 0 || gSynthesisReverbs[reverbIndex].panLeft != 0) { 238 // Leak some audio from the left reverb channel into the right reverb channel and vice versa (pan) 239 aDMEMMove(cmd++, DMEM_ADDR_WET_LEFT_CH, DMEM_ADDR_RESAMPLED, DEFAULT_LEN_1CH); 240 aMix(cmd++, gSynthesisReverbs[reverbIndex].panRight, DMEM_ADDR_WET_RIGHT_CH, DMEM_ADDR_WET_LEFT_CH, DEFAULT_LEN_1CH); 241 aMix(cmd++, gSynthesisReverbs[reverbIndex].panLeft, DMEM_ADDR_RESAMPLED, DMEM_ADDR_WET_RIGHT_CH, DEFAULT_LEN_1CH); 242 } 243 return cmd; 244 } 245 246 u64 *synthesis_load_reverb_samples(u64 *cmd, s16 reverbIndex, s16 updateIndex) { 247 struct ReverbRingBufferItem *item; 248 struct SynthesisReverb *reverb; 249 250 reverb = &gSynthesisReverbs[reverbIndex]; 251 item = &reverb->items[reverb->curFrame][updateIndex]; 252 // Get the oldest samples in the ring buffer into the wet channels 253 cmd = synthesis_load_reverb_ring_buffer(cmd, DMEM_ADDR_RESAMPLED, item->startPos, item->lengthA, reverbIndex); 254 if (item->lengthB != 0) { 255 // Ring buffer wrapped 256 cmd = synthesis_load_reverb_ring_buffer(cmd, DMEM_ADDR_RESAMPLED + item->lengthA, 0, item->lengthB, reverbIndex); 257 } 258 return cmd; 259 } 260 261 u64 *synthesis_save_reverb_samples(u64 *cmd, s16 reverbIndex, s16 updateIndex) { 262 struct ReverbRingBufferItem *item; 263 264 item = &gSynthesisReverbs[reverbIndex].items[gSynthesisReverbs[reverbIndex].curFrame][updateIndex]; 265 switch (gSynthesisReverbs[reverbIndex].downsampleRate) { 266 case 1: 267 // Put the oldest samples in the ring buffer into the wet channels 268 cmd = synthesis_save_reverb_ring_buffer(cmd, DMEM_ADDR_WET_LEFT_CH, item->startPos, item->lengthA, reverbIndex); 269 if (item->lengthB != 0) { 270 // Ring buffer wrapped 271 cmd = synthesis_save_reverb_ring_buffer(cmd, DMEM_ADDR_WET_LEFT_CH + item->lengthA, 0, item->lengthB, reverbIndex); 272 } 273 break; 274 275 default: 276 // Downsampling is done later by CPU when RSP is done, therefore we need to have double 277 // buffering. Left and right buffers are adjacent in memory. 278 aSaveBuffer(cmd++, DMEM_ADDR_WET_LEFT_CH, 279 VIRTUAL_TO_PHYSICAL2(gSynthesisReverbs[reverbIndex].items[gSynthesisReverbs[reverbIndex].curFrame][updateIndex].toDownsampleLeft), DEFAULT_LEN_2CH); 280 break; 281 } 282 gSynthesisReverbs[reverbIndex].resampleFlags = 0; 283 return cmd; 284 } 285 286 u64 *func_sh_802EDF24(u64 *cmd, s16 reverbIndex, s16 updateIndex) { 287 struct ReverbRingBufferItem *item; 288 struct SynthesisReverb *reverb; 289 290 reverb = &gSynthesisReverbs[reverbIndex]; 291 item = &reverb->items[reverb->curFrame][updateIndex]; 292 // Put the oldest samples in the ring buffer into the wet channels 293 cmd = synthesis_save_reverb_ring_buffer(cmd, DMEM_ADDR_RESAMPLED, item->startPos, item->lengthA, reverbIndex); 294 if (item->lengthB != 0) { 295 // Ring buffer wrapped 296 cmd = synthesis_save_reverb_ring_buffer(cmd, DMEM_ADDR_RESAMPLED + item->lengthA, 0, item->lengthB, reverbIndex); 297 } 298 return cmd; 299 } 300 301 u64 *synthesis_do_one_audio_update(s16 *aiBuf, s32 bufLen, u64 *cmd, s32 updateIndex) { 302 struct NoteSubEu *noteSubEu; 303 u8 noteIndices[56]; 304 s32 temp; 305 s32 i; 306 s16 j; 307 s16 notePos = 0; 308 309 if (gNumSynthesisReverbs == 0) { 310 for (i = 0; i < gMaxSimultaneousNotes; i++) { 311 if (gNoteSubsEu[gMaxSimultaneousNotes * updateIndex + i].enabled) { 312 noteIndices[notePos++] = i; 313 } 314 } 315 } else { 316 for (j = 0; j < gNumSynthesisReverbs; j++) { 317 for (i = 0; i < gMaxSimultaneousNotes; i++) { 318 noteSubEu = &gNoteSubsEu[gMaxSimultaneousNotes * updateIndex + i]; 319 if (noteSubEu->enabled && j == noteSubEu->reverbIndex) { 320 noteIndices[notePos++] = i; 321 } 322 } 323 } 324 325 for (i = 0; i < gMaxSimultaneousNotes; i++) { 326 noteSubEu = &gNoteSubsEu[gMaxSimultaneousNotes * updateIndex + i]; 327 if (noteSubEu->enabled && noteSubEu->reverbIndex >= gNumSynthesisReverbs) { 328 noteIndices[notePos++] = i; 329 } 330 } 331 } 332 aClearBuffer(cmd++, DMEM_ADDR_LEFT_CH, DEFAULT_LEN_2CH); 333 i = 0; 334 for (j = 0; j < gNumSynthesisReverbs; j++) { 335 gUseReverb = gSynthesisReverbs[j].useReverb; 336 if (gUseReverb != 0) { 337 cmd = synthesis_resample_and_mix_reverb(cmd, bufLen, j, updateIndex); 338 } 339 for (; i < notePos; i++) { 340 temp = updateIndex * gMaxSimultaneousNotes; 341 if (j == gNoteSubsEu[temp + noteIndices[i]].reverbIndex) { 342 cmd = synthesis_process_note(noteIndices[i], 343 &gNoteSubsEu[temp + noteIndices[i]], 344 &gNotes[noteIndices[i]].synthesisState, 345 aiBuf, bufLen, cmd, updateIndex); 346 continue; 347 } else { 348 break; 349 } 350 } 351 if (gSynthesisReverbs[j].useReverb != 0) { 352 if (gSynthesisReverbs[j].unk100 != NULL) { 353 aFilter(cmd++, 0x02, bufLen * 2, gSynthesisReverbs[j].unk100); 354 aFilter(cmd++, gSynthesisReverbs[j].resampleFlags, DMEM_ADDR_WET_LEFT_CH, gSynthesisReverbs[j].unk108); 355 } 356 if (gSynthesisReverbs[j].unk104 != NULL) { 357 aFilter(cmd++, 0x02, bufLen * 2, gSynthesisReverbs[j].unk104); 358 aFilter(cmd++, gSynthesisReverbs[j].resampleFlags, DMEM_ADDR_WET_RIGHT_CH, gSynthesisReverbs[j].unk10C); 359 } 360 cmd = synthesis_save_reverb_samples(cmd, j, updateIndex); 361 if (gSynthesisReverbs[j].unk5 != -1) { 362 if (gSynthesisReverbs[gSynthesisReverbs[j].unk5].downsampleRate == 1) { 363 cmd = synthesis_load_reverb_samples(cmd, gSynthesisReverbs[j].unk5, updateIndex); 364 aMix(cmd++, gSynthesisReverbs[j].unk08, DMEM_ADDR_WET_LEFT_CH, DMEM_ADDR_RESAMPLED, DEFAULT_LEN_2CH); 365 cmd = func_sh_802EDF24(cmd++, gSynthesisReverbs[j].unk5, updateIndex); 366 } 367 } 368 } 369 } 370 for (; i < notePos; i++) { 371 struct NoteSubEu *noteSubEu2 = &gNoteSubsEu[updateIndex * gMaxSimultaneousNotes + noteIndices[i]]; 372 cmd = synthesis_process_note(noteIndices[i], 373 noteSubEu2, 374 &gNotes[noteIndices[i]].synthesisState, 375 aiBuf, bufLen, cmd, updateIndex); 376 } 377 378 temp = bufLen * 2; 379 aInterleave(cmd++, DMEM_ADDR_TEMP, DMEM_ADDR_LEFT_CH, DMEM_ADDR_RIGHT_CH, temp); 380 aSaveBuffer(cmd++, DMEM_ADDR_TEMP, VIRTUAL_TO_PHYSICAL2(aiBuf), temp * 2); 381 return cmd; 382 } 383 384 u64 *synthesis_process_note(s32 noteIndex, struct NoteSubEu *noteSubEu, struct NoteSynthesisState *synthesisState, UNUSED s16 *aiBuf, s32 bufLen, u64 *cmd, s32 updateIndex) { 385 UNUSED s32 pad0[3]; 386 struct AudioBankSample *audioBookSample; // sp164, sp138 387 struct AdpcmLoop *loopInfo; // sp160, sp134 388 s16 *curLoadedBook; // sp154, sp130 389 UNUSED u8 padEU[0x04]; 390 UNUSED u8 pad8[0x04]; 391 s32 noteFinished; // 150 t2, sp124 392 s32 restart; // 14c t3, sp120 393 s32 flags; // sp148, sp11C, t8 394 u16 resamplingRateFixedPoint; // sp5c, sp11A 395 s32 nSamplesToLoad; //s0, Ec 396 UNUSED u8 pad7[0x0c]; // sp100 397 s32 sp130; //sp128, sp104 398 UNUSED s32 tempBufLen; 399 UNUSED u32 pad9; 400 s32 t0; 401 u8 *sampleAddr; // sp120, spF4 402 s32 s6; 403 s32 samplesLenAdjusted; // 108, spEC 404 s32 nAdpcmSamplesProcessed; // signed required for US // spc0 405 s32 endPos; // sp110, spE4 406 s32 nSamplesToProcess; // sp10c/a0, spE0 407 // Might have been used to store (samplesLenFixedPoint >> 0x10), but doing so causes strange 408 // behavior with the break near the end of the loop, causing US and JP to need a goto instead 409 UNUSED s32 samplesLenInt; 410 s32 s2; 411 s32 leftRight; //s0 412 s32 s5; //s4 413 u32 samplesLenFixedPoint; // v1_1 414 s32 s3; // spA0 415 s32 nSamplesInThisIteration; // v1_2 416 u32 a3; 417 u8 *v0_2; 418 s32 unk_s6; // sp90 419 s32 s5Aligned; 420 s32 sp88; 421 s32 sp84; 422 u32 temp; 423 s32 nParts; // spE8, spBC 424 s32 curPart; // spE4, spB8 425 s32 aligned; 426 UNUSED u32 padSH1; 427 s32 resampledTempLen; // spD8, spAC, sp6c 428 u16 noteSamplesDmemAddrBeforeResampling; // spD6, spAA, sp6a -- 6C 429 UNUSED u32 padSH2; 430 UNUSED u32 padSH3; 431 UNUSED u32 padSH4; 432 struct Note *note; // sp58 433 u16 sp56; // sp56 434 u16 addr; 435 u8 synthesisVolume; 436 437 curLoadedBook = NULL; 438 note = &gNotes[noteIndex]; 439 flags = 0; 440 if (noteSubEu->needsInit == TRUE) { 441 flags = A_INIT; 442 synthesisState->restart = 0; 443 synthesisState->samplePosInt = 0; 444 synthesisState->samplePosFrac = 0; 445 synthesisState->curVolLeft = 0; 446 synthesisState->curVolRight = 0; 447 synthesisState->prevHeadsetPanRight = 0; 448 synthesisState->prevHeadsetPanLeft = 0; 449 synthesisState->reverbVol = noteSubEu->reverbVol; 450 synthesisState->unk5 = 0; 451 note->noteSubEu.finished = 0; 452 } 453 454 resamplingRateFixedPoint = noteSubEu->resamplingRateFixedPoint; 455 nParts = noteSubEu->hasTwoAdpcmParts + 1; 456 samplesLenFixedPoint = (resamplingRateFixedPoint * bufLen * 2) + synthesisState->samplePosFrac; 457 nSamplesToLoad = (samplesLenFixedPoint >> 0x10); 458 synthesisState->samplePosFrac = samplesLenFixedPoint & 0xFFFF; 459 460 if ((synthesisState->unk5 == 1) && (nParts == 2)) { 461 nSamplesToLoad += 2; 462 sp56 = 2; 463 } else if ((synthesisState->unk5 == 2) && (nParts == 1)) { 464 nSamplesToLoad -= 4; 465 sp56 = 4; 466 } else { 467 sp56 = 0; 468 } 469 470 471 synthesisState->unk5 = nParts; 472 473 if (noteSubEu->isSyntheticWave) { 474 cmd = load_wave_samples(cmd, noteSubEu, synthesisState, nSamplesToLoad); 475 noteSamplesDmemAddrBeforeResampling = (synthesisState->samplePosInt * 2) + DMEM_ADDR_UNCOMPRESSED_NOTE; 476 synthesisState->samplePosInt += nSamplesToLoad; 477 } else { 478 // ADPCM note 479 audioBookSample = noteSubEu->sound.audioBankSound->sample; 480 loopInfo = audioBookSample->loop; 481 endPos = loopInfo->end; 482 sampleAddr = audioBookSample->sampleAddr; 483 resampledTempLen = 0; 484 for (curPart = 0; curPart < nParts; curPart++) { 485 nAdpcmSamplesProcessed = 0; // s8 486 s5 = 0; // s4 487 488 if (nParts == 1) { 489 samplesLenAdjusted = nSamplesToLoad; 490 } else if (nSamplesToLoad & 1) { 491 samplesLenAdjusted = (nSamplesToLoad & ~1) + (curPart * 2); 492 } else { 493 samplesLenAdjusted = nSamplesToLoad; 494 } 495 496 if (audioBookSample->codec == CODEC_ADPCM) { 497 if (curLoadedBook != (*audioBookSample->book).book) { 498 u32 nEntries; 499 switch (noteSubEu->bookOffset) { 500 case 1: 501 curLoadedBook = euUnknownData_80301950 + 1; 502 break; 503 case 2: 504 curLoadedBook = euUnknownData_80301950 + 2; 505 break; 506 case 3: 507 default: 508 curLoadedBook = audioBookSample->book->book; 509 break; 510 } 511 nEntries = 16 * audioBookSample->book->order * audioBookSample->book->npredictors; 512 aLoadADPCM(cmd++, nEntries, VIRTUAL_TO_PHYSICAL2(curLoadedBook)); 513 } 514 } 515 516 while (nAdpcmSamplesProcessed != samplesLenAdjusted) { 517 s32 samplesRemaining; // v1 518 s32 s0; 519 520 noteFinished = FALSE; 521 restart = FALSE; 522 s2 = synthesisState->samplePosInt & 0xf; 523 samplesRemaining = endPos - synthesisState->samplePosInt; 524 nSamplesToProcess = samplesLenAdjusted - nAdpcmSamplesProcessed; 525 526 if (s2 == 0 && synthesisState->restart == FALSE) { 527 s2 = 16; 528 } 529 s6 = 16 - s2; // a1 530 if (nSamplesToProcess < samplesRemaining) { 531 t0 = (nSamplesToProcess - s6 + 0xf) / 16; 532 s0 = t0 * 16; 533 s3 = s6 + s0 - nSamplesToProcess; 534 } else { 535 s0 = samplesRemaining - s6; 536 s3 = 0; 537 if (s0 <= 0) { 538 s0 = 0; 539 s6 = samplesRemaining; 540 } 541 t0 = (s0 + 0xf) / 16; 542 if (loopInfo->count != 0) { 543 // Loop around and restart 544 restart = 1; 545 } else { 546 noteFinished = 1; 547 } 548 } 549 switch (audioBookSample->codec) { 550 case CODEC_ADPCM: 551 unk_s6 = 9; 552 sp88 = 0x10; 553 sp84 = 0; 554 break; 555 case CODEC_S8: 556 unk_s6 = 0x10; 557 sp88 = 0x10; 558 sp84 = 0; 559 break; 560 case CODEC_SKIP: goto skip; 561 } 562 if (t0 != 0) { 563 temp = (synthesisState->samplePosInt + sp88 - s2) / 16; 564 if (audioBookSample->medium == 0) { 565 v0_2 = sp84 + (temp * unk_s6) + sampleAddr; 566 } else { 567 v0_2 = dma_sample_data((uintptr_t)(sp84 + (temp * unk_s6) + sampleAddr), 568 ALIGN(t0 * unk_s6 + 16, 4), flags, &synthesisState->sampleDmaIndex, audioBookSample->medium); 569 } 570 571 a3 = ((uintptr_t)v0_2 & 0xf); 572 aligned = ALIGN(t0 * unk_s6 + 16, 4); 573 addr = (DMEM_ADDR_COMPRESSED_ADPCM_DATA - aligned) & 0xffff; 574 aLoadBuffer(cmd++, VIRTUAL_TO_PHYSICAL2(v0_2 - a3), addr, ALIGN(t0 * unk_s6 + 16, 4)); 575 } else { 576 s0 = 0; 577 a3 = 0; 578 } 579 if (synthesisState->restart != FALSE) { 580 aSetLoop(cmd++, VIRTUAL_TO_PHYSICAL2(audioBookSample->loop->state)); 581 flags = A_LOOP; // = 2 582 synthesisState->restart = FALSE; 583 } 584 nSamplesInThisIteration = s0 + s6 - s3; 585 if (nAdpcmSamplesProcessed == 0) { 586 switch (audioBookSample->codec) { 587 case CODEC_ADPCM: 588 aligned = ALIGN(t0 * unk_s6 + 16, 4); 589 addr = (DMEM_ADDR_COMPRESSED_ADPCM_DATA - aligned) & 0xffff; 590 aSetBuffer(cmd++, 0, addr + a3, DMEM_ADDR_UNCOMPRESSED_NOTE, s0 * 2); 591 aADPCMdec(cmd++, flags, VIRTUAL_TO_PHYSICAL2(synthesisState->synthesisBuffers->adpcmdecState)); 592 break; 593 case CODEC_S8: 594 aligned = ALIGN(t0 * unk_s6 + 16, 4); 595 addr = (DMEM_ADDR_COMPRESSED_ADPCM_DATA - aligned) & 0xffff; 596 aSetBuffer(cmd++, 0, addr + a3, DMEM_ADDR_UNCOMPRESSED_NOTE, s0 * 2); 597 aS8Dec(cmd++, flags, VIRTUAL_TO_PHYSICAL2(synthesisState->synthesisBuffers->adpcmdecState)); 598 break; 599 } 600 sp130 = s2 * 2; 601 } else { 602 s5Aligned = ALIGN(s5 + 16, 4); 603 switch (audioBookSample->codec) { 604 case CODEC_ADPCM: 605 aligned = ALIGN(t0 * unk_s6 + 16, 4); 606 addr = (DMEM_ADDR_COMPRESSED_ADPCM_DATA - aligned) & 0xffff; 607 aSetBuffer(cmd++, 0, addr + a3, DMEM_ADDR_UNCOMPRESSED_NOTE + s5Aligned, s0 * 2); 608 aADPCMdec(cmd++, flags, VIRTUAL_TO_PHYSICAL2(synthesisState->synthesisBuffers->adpcmdecState)); 609 break; 610 case CODEC_S8: 611 aligned = ALIGN(t0 * unk_s6 + 16, 4); 612 addr = (DMEM_ADDR_COMPRESSED_ADPCM_DATA - aligned) & 0xffff; 613 aSetBuffer(cmd++, 0, addr + a3, DMEM_ADDR_UNCOMPRESSED_NOTE + s5Aligned, s0 * 2); 614 aS8Dec(cmd++, flags, VIRTUAL_TO_PHYSICAL2(synthesisState->synthesisBuffers->adpcmdecState)); 615 break; 616 } 617 aDMEMMove(cmd++, DMEM_ADDR_UNCOMPRESSED_NOTE + s5Aligned + (s2 * 2), DMEM_ADDR_UNCOMPRESSED_NOTE + s5, (nSamplesInThisIteration) * 2); 618 } 619 nAdpcmSamplesProcessed += nSamplesInThisIteration; 620 switch (flags) { 621 case A_INIT: // = 1 622 sp130 = 0x20; 623 s5 = (s0 + 0x10) * 2; 624 break; 625 case A_LOOP: // = 2 626 s5 = (nSamplesInThisIteration) * 2 + s5; 627 break; 628 default: 629 if (s5 != 0) { 630 s5 = (nSamplesInThisIteration) * 2 + s5; 631 } else { 632 s5 = (s2 + (nSamplesInThisIteration)) * 2; 633 } 634 break; 635 } 636 flags = 0; 637 skip: 638 if (noteFinished) { 639 aClearBuffer(cmd++, DMEM_ADDR_UNCOMPRESSED_NOTE + s5, 640 (samplesLenAdjusted - nAdpcmSamplesProcessed) * 2); 641 noteSubEu->finished = 1; 642 note->noteSubEu.finished = 1; 643 func_sh_802ed644(updateIndex, noteIndex); 644 break; 645 } 646 if (restart != 0) { 647 synthesisState->restart = TRUE; 648 synthesisState->samplePosInt = loopInfo->start; 649 } else { 650 synthesisState->samplePosInt += nSamplesToProcess; 651 } 652 } 653 654 switch (nParts) { 655 case 1: 656 noteSamplesDmemAddrBeforeResampling = DMEM_ADDR_UNCOMPRESSED_NOTE + sp130; 657 break; 658 case 2: 659 switch (curPart) { 660 case 0: 661 aDownsampleHalf(cmd++, ALIGN(samplesLenAdjusted / 2, 3), DMEM_ADDR_UNCOMPRESSED_NOTE + sp130, DMEM_ADDR_RESAMPLED); 662 resampledTempLen = samplesLenAdjusted; 663 noteSamplesDmemAddrBeforeResampling = DMEM_ADDR_RESAMPLED; 664 if (noteSubEu->finished != FALSE) { 665 aClearBuffer(cmd++, noteSamplesDmemAddrBeforeResampling + resampledTempLen, samplesLenAdjusted + 0x10); 666 } 667 break; 668 case 1: 669 aDownsampleHalf(cmd++, ALIGN(samplesLenAdjusted / 2, 3), DMEM_ADDR_UNCOMPRESSED_NOTE + sp130, resampledTempLen + DMEM_ADDR_RESAMPLED); 670 break; 671 } 672 } 673 if (noteSubEu->finished != FALSE) { 674 break; 675 } 676 } 677 } 678 flags = 0; 679 if (noteSubEu->needsInit == TRUE) { 680 flags = A_INIT; 681 noteSubEu->needsInit = FALSE; 682 } 683 flags = flags | sp56; 684 cmd = final_resample(cmd, synthesisState, bufLen * 2, resamplingRateFixedPoint, 685 noteSamplesDmemAddrBeforeResampling, flags); 686 if ((flags & 1) != 0) { 687 flags = 1; 688 } 689 690 if (noteSubEu->filter) { 691 aFilter(cmd++, 0x02, bufLen * 2, noteSubEu->filter); 692 aFilter(cmd++, flags, DMEM_ADDR_TEMP, synthesisState->synthesisBuffers->filterBuffer); 693 694 } 695 696 if (noteSubEu->bookOffset == 3) { 697 aUnknown25(cmd++, 0, bufLen * 2, DMEM_ADDR_TEMP, DMEM_ADDR_TEMP); 698 } 699 700 synthesisVolume = noteSubEu->synthesisVolume; 701 if (synthesisVolume != 0) { 702 if (synthesisVolume < 0x10) { 703 synthesisVolume = 0x10; 704 } 705 706 aHiLoGain(cmd++, synthesisVolume, (bufLen + 0x10) * 2, DMEM_ADDR_TEMP); 707 } 708 709 if (noteSubEu->headsetPanRight != 0 || synthesisState->prevHeadsetPanRight != 0) { 710 leftRight = 1; 711 } else if (noteSubEu->headsetPanLeft != 0 || synthesisState->prevHeadsetPanLeft != 0) { 712 leftRight = 2; 713 } else { 714 leftRight = 0; 715 } 716 cmd = process_envelope(cmd, noteSubEu, synthesisState, bufLen, DMEM_ADDR_TEMP, leftRight, flags); 717 if (noteSubEu->usesHeadsetPanEffects) { 718 if ((flags & 1) == 0) { 719 flags = 0; 720 } 721 cmd = note_apply_headset_pan_effects(cmd, noteSubEu, synthesisState, bufLen * 2, flags, leftRight); 722 } 723 724 return cmd; 725 } 726 727 u64 *load_wave_samples(u64 *cmd, struct NoteSubEu *noteSubEu, struct NoteSynthesisState *synthesisState, s32 nSamplesToLoad) { 728 s32 a3; 729 s32 repeats; 730 aLoadBuffer(cmd++, VIRTUAL_TO_PHYSICAL2(noteSubEu->sound.samples), 731 DMEM_ADDR_UNCOMPRESSED_NOTE, 128); 732 733 synthesisState->samplePosInt &= 0x3f; 734 a3 = 64 - synthesisState->samplePosInt; 735 if (a3 < nSamplesToLoad) { 736 repeats = (nSamplesToLoad - a3 + 63) / 64; 737 if (repeats != 0) { 738 aDuplicate(cmd++, 739 /*dmemin*/ DMEM_ADDR_UNCOMPRESSED_NOTE, 740 /*dmemout*/ DMEM_ADDR_UNCOMPRESSED_NOTE + 128, 741 /*copies*/ repeats); 742 } 743 } 744 return cmd; 745 } 746 747 u64 *final_resample(u64 *cmd, struct NoteSynthesisState *synthesisState, s32 count, u16 pitch, u16 dmemIn, u32 flags) { 748 if (pitch == 0) { 749 aClearBuffer(cmd++, DMEM_ADDR_TEMP, count); 750 } else { 751 aSetBuffer(cmd++, /*flags*/ 0, dmemIn, /*dmemout*/ DMEM_ADDR_TEMP, count); 752 aResample(cmd++, flags, pitch, VIRTUAL_TO_PHYSICAL2(synthesisState->synthesisBuffers->finalResampleState)); 753 } 754 return cmd; 755 } 756 757 u64 *process_envelope(u64 *cmd, struct NoteSubEu *note, struct NoteSynthesisState *synthesisState, s32 nSamples, u16 inBuf, s32 headsetPanSettings, UNUSED u32 flags) { 758 u16 sourceRight; 759 u16 sourceLeft; 760 u16 targetLeft; 761 u16 targetRight; 762 s16 rampLeft; 763 s16 rampRight; 764 s32 sourceReverbVol; 765 s16 rampReverb; 766 s32 reverbVolDiff = 0; 767 768 sourceLeft = synthesisState->curVolLeft; 769 sourceRight = synthesisState->curVolRight; 770 targetLeft = note->targetVolLeft; 771 targetRight = note->targetVolRight; 772 targetLeft <<= 4; 773 targetRight <<= 4; 774 775 if (targetLeft != sourceLeft) { 776 rampLeft = (targetLeft - sourceLeft) / (nSamples >> 3); 777 } else { 778 rampLeft = 0; 779 } 780 if (targetRight != sourceRight) { 781 rampRight = (targetRight - sourceRight) / (nSamples >> 3); 782 } else { 783 rampRight = 0; 784 } 785 786 sourceReverbVol = synthesisState->reverbVol; 787 if (note->reverbVol != sourceReverbVol) { 788 reverbVolDiff = ((note->reverbVol & 0x7f) - (sourceReverbVol & 0x7f)) << 9; 789 rampReverb = reverbVolDiff / (nSamples >> 3); 790 synthesisState->reverbVol = note->reverbVol; 791 } else { 792 rampReverb = 0; 793 } 794 synthesisState->curVolLeft = sourceLeft + rampLeft * (nSamples >> 3); 795 synthesisState->curVolRight = sourceRight + rampRight * (nSamples >> 3); 796 797 if (note->usesHeadsetPanEffects) { 798 aClearBuffer(cmd++, DMEM_ADDR_NOTE_PAN_TEMP, DEFAULT_LEN_1CH); 799 aEnvSetup1(cmd++, (sourceReverbVol & 0x7f) * 2, rampReverb, rampLeft, rampRight); 800 aEnvSetup2(cmd++, sourceLeft, sourceRight); 801 802 switch (headsetPanSettings) { 803 case 1: 804 aEnvMixer(cmd++, 805 inBuf, nSamples, 806 (sourceReverbVol & 0x80) >> 7, 807 note->stereoStrongRight, note->stereoStrongLeft, 808 DMEM_ADDR_NOTE_PAN_TEMP, 809 DMEM_ADDR_RIGHT_CH, 810 DMEM_ADDR_WET_LEFT_CH, 811 DMEM_ADDR_WET_RIGHT_CH); 812 break; 813 case 2: 814 aEnvMixer(cmd++, 815 inBuf, nSamples, 816 (sourceReverbVol & 0x80) >> 7, 817 note->stereoStrongRight, note->stereoStrongLeft, 818 DMEM_ADDR_LEFT_CH, 819 DMEM_ADDR_NOTE_PAN_TEMP, 820 DMEM_ADDR_WET_LEFT_CH, 821 DMEM_ADDR_WET_RIGHT_CH); 822 break; 823 default: 824 aEnvMixer(cmd++, 825 inBuf, nSamples, 826 (sourceReverbVol & 0x80) >> 7, 827 note->stereoStrongRight, note->stereoStrongLeft, 828 DMEM_ADDR_LEFT_CH, 829 DMEM_ADDR_RIGHT_CH, 830 DMEM_ADDR_WET_LEFT_CH, 831 DMEM_ADDR_WET_RIGHT_CH); 832 break; 833 } 834 } else { 835 aEnvSetup1(cmd++, (sourceReverbVol & 0x7f) * 2, rampReverb, rampLeft, rampRight); 836 aEnvSetup2(cmd++, sourceLeft, sourceRight); 837 aEnvMixer(cmd++, 838 inBuf, nSamples, 839 (sourceReverbVol & 0x80) >> 7, 840 note->stereoStrongRight, note->stereoStrongLeft, 841 DMEM_ADDR_LEFT_CH, 842 DMEM_ADDR_RIGHT_CH, 843 DMEM_ADDR_WET_LEFT_CH, 844 DMEM_ADDR_WET_RIGHT_CH); 845 } 846 return cmd; 847 } 848 849 u64 *note_apply_headset_pan_effects(u64 *cmd, struct NoteSubEu *noteSubEu, struct NoteSynthesisState *note, s32 bufLen, s32 flags, s32 leftRight) { 850 u16 dest; 851 u16 pitch; 852 u8 prevPanShift; 853 u8 panShift; 854 UNUSED u8 unkDebug; 855 856 switch (leftRight) { 857 case 1: 858 dest = DMEM_ADDR_LEFT_CH; 859 panShift = noteSubEu->headsetPanRight; 860 note->prevHeadsetPanLeft = 0; 861 prevPanShift = note->prevHeadsetPanRight; 862 note->prevHeadsetPanRight = panShift; 863 break; 864 case 2: 865 dest = DMEM_ADDR_RIGHT_CH; 866 panShift = noteSubEu->headsetPanLeft; 867 note->prevHeadsetPanRight = 0; 868 869 prevPanShift = note->prevHeadsetPanLeft; 870 note->prevHeadsetPanLeft = panShift; 871 break; 872 default: 873 return cmd; 874 } 875 876 if (flags != 1) { // A_INIT? 877 // Slightly adjust the sample rate in order to fit a change in pan shift 878 if (panShift != prevPanShift) { 879 pitch = (((bufLen << 0xf) / 2) - 1) / ((bufLen + panShift - prevPanShift - 2) / 2); 880 aSetBuffer(cmd++, 0, DMEM_ADDR_NOTE_PAN_TEMP, DMEM_ADDR_TEMP, (bufLen + panShift) - prevPanShift); 881 aResampleZoh(cmd++, pitch, 0); 882 } else { 883 aDMEMMove(cmd++, DMEM_ADDR_NOTE_PAN_TEMP, DMEM_ADDR_TEMP, bufLen); 884 } 885 886 if (prevPanShift != 0) { 887 aLoadBuffer(cmd++, VIRTUAL_TO_PHYSICAL2(note->synthesisBuffers->panSamplesBuffer), 888 DMEM_ADDR_NOTE_PAN_TEMP, ALIGN(prevPanShift, 4)); 889 aDMEMMove(cmd++, DMEM_ADDR_TEMP, DMEM_ADDR_NOTE_PAN_TEMP + prevPanShift, bufLen + panShift - prevPanShift); 890 } else { 891 aDMEMMove(cmd++, DMEM_ADDR_TEMP, DMEM_ADDR_NOTE_PAN_TEMP, bufLen + panShift); 892 } 893 } else { 894 // Just shift right 895 aDMEMMove(cmd++, DMEM_ADDR_NOTE_PAN_TEMP, DMEM_ADDR_TEMP, bufLen); 896 aClearBuffer(cmd++, DMEM_ADDR_NOTE_PAN_TEMP, panShift); 897 aDMEMMove(cmd++, DMEM_ADDR_TEMP, DMEM_ADDR_NOTE_PAN_TEMP + panShift, bufLen); 898 } 899 900 if (panShift) { 901 // Save excessive samples for next iteration 902 aSaveBuffer(cmd++, DMEM_ADDR_NOTE_PAN_TEMP + bufLen, 903 VIRTUAL_TO_PHYSICAL2(note->synthesisBuffers->panSamplesBuffer), ALIGN(panShift, 4)); 904 } 905 906 aAddMixer(cmd++, DMEM_ADDR_NOTE_PAN_TEMP, dest, (bufLen + 0x3f) & 0xffc0); 907 908 return cmd; 909 } 910 #endif