Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
bgm_player.c
Go to the documentation of this file.
1#include "audio.h"
2#include "audio/core.h"
3
5
7extern u8 BgmTicksRates[8];
8extern u8 BgmCustomEnvLookup[40];
9
12extern u8 SeqCmdArgCounts[];
13
14static void au_bgm_stop_player(BGMPlayer* player);
15
16static s32 au_bgm_bpm_to_tempo(BGMPlayer* player, u32 tempo);
17
18static u8 au_bgm_get_random_pan(BGMPlayer* player, u8 arg1, u8 arg2);
19static s16 au_bgm_get_random_pitch(s32 arg0, s32 arg1, u8 arg2);
20static u8 au_bgm_get_random_vol(s32 arg0, u8 volume, u8 arg2);
21static u8 au_bgm_get_random_reverb(s32 arg0, u8 arg1, u8 arg2);
22
24 BGMHeader* bgmFile;
27 u32 compID;
28 s32 compOffset;
29 u32 value;
31 u8 var_a1;
32 u8 pos;
33 u32 i;
34
35 compID = 0;
36 unkType = -1;
37 player->frameCounter++;
38
39 if (player->cmdBufPending != 0) {
40 if (player->cmdBufPending < ARRAY_COUNT(player->cmdBufData)) {
41 pos = player->cmdBufReadPos;
42 for (var_a1 = 0; var_a1 < player->cmdBufPending; var_a1++) {
43 value = player->cmdBufData[pos];
44 if (value != 0) {
45 if (value < 16) {
46 unkType = value & 3;
47 compID = value >> 2;
48 }
49 pos++;
50 if (pos >= ARRAY_COUNT(player->cmdBufData)) {
51 pos = 0;
52 }
53 }
54 }
55 consumed = player->cmdBufWritePos - player->cmdBufReadPos;
56 if (consumed < 0) {
58 }
59 player->cmdBufPending -= consumed;
60 player->cmdBufReadPos = player->cmdBufWritePos;
61 } else {
62 player->cmdBufPending = 0;
63 }
64
65 if (unkType != -1) {
66 if (unkType != 0) {
67 if (unkType != player->unk_58) {
68 player->unk_58 = unkType & 0xFF;
69 player->unk_5A = unkType & 0xFF;
72 if (unkType == 2) {
73 bgmFile = player->globals->dataBGM[1];
74 } else {
75 bgmFile = player->globals->dataBGM[0];
76 }
77 player->bgmFile = bgmFile;
78 bgmData = &bgmFile->info;
80
81 compOffset = bgmData->compositions[compID];
82 if (compOffset == 0) {
83 compOffset = bgmData->compositions[0];
84 }
85 player->compStartPos = AU_FILE_RELATIVE(bgmFile, compOffset << 2);
86 player->compReadPos = AU_FILE_RELATIVE(bgmFile, compOffset << 2);
87
88 if (bgmData->drums != 0) {
89 player->drumsInfo = AU_FILE_RELATIVE(player->bgmFile, bgmData->drums << 2);
90 player->bgmDrumCount = bgmData->drumCount;
91 for (i = 0; i < player->bgmDrumCount; i++) {
92 BGMDrumInfo* drum = &player->drumsInfo[i];
93 player->drums[i] = drum;
94 }
95 for (; i < ARRAY_COUNT(player->drums); i++) {
96 player->drums[i] = player->drums[0];
97 }
98 } else {
99 player->drumsInfo = nullptr;
100 player->bgmDrumCount = 0;
101 }
102
103 if (bgmData->instruments != 0) {
104 player->instrumentsInfo = AU_FILE_RELATIVE(player->bgmFile, bgmData->instruments << 2);
105 player->bgmInstrumentCount = bgmData->instrumentCount;
106 return;
107 }
108 player->instrumentsInfo = nullptr;
109 player->bgmInstrumentCount = 0;
110 }
111 } else {
112 if (player->unk_58 != 0) {
114 player->nextUpdateCounter = 1;
115 player->nextUpdateStep = 1;
116 } else {
117 au_bgm_stop_player(player);
118 }
119 }
120 }
121 }
122}
123
127 return gBGMPlayerB;
128 }
129 } else {
130 return gBGMPlayerA;
131 }
132 return nullptr;
133}
134
136 BGMPlayer* player;
138 s32 songName;
139 s32 variation;
140 s32 duration;
141 s32 volume0;
142 s32 volume1;
143 AuResult status;
144 u32 i;
145
146 status = AU_RESULT_OK;
147 songName = request->songName;
148 variation = request->variation;
149
150 if (songName != 0) {
151 player = au_bgm_get_player_with_song_name(songName);
152 if (player != nullptr) {
153 fileInfo = &player->bgmFile->info;
154 duration = request->duration;
155 if (duration != 0) {
156 if (duration > SND_MAX_DURATION) {
157 duration = SND_MAX_DURATION;
158 } else if (duration < SND_MIN_DURATION) {
159 duration = SND_MIN_DURATION;
160 }
161 }
162 volume0 = request->startVolume;
163 if (volume0 > AU_MAX_VOLUME_8) {
165 }
166 if (volume0 != 0) {
168 }
169 volume1 = request->finalVolume;
170 if (volume1 > AU_MAX_VOLUME_8) {
172 }
173 if (volume1 != 0) {
175 } else {
177 }
178
179 au_fade_init(&player->fadeInfo, duration, volume0, volume1);
181 player->fadeInfo.envelopeTicks = 1;
183
184 if (variation < BGM_VARIATION_0 || variation > BGM_VARIATION_3 || fileInfo->compositions[variation] == 0) {
185 variation = BGM_VARIATION_0;
186 }
187 player->curVariation = variation;
188
189 player->compStartPos = AU_FILE_RELATIVE(player->bgmFile, fileInfo->compositions[variation] << 2);
190 player->compReadPos = player->compStartPos;
191
192 if (fileInfo->drums != 0) {
193 player->drumsInfo = AU_FILE_RELATIVE(player->bgmFile, fileInfo->drums << 2);
194 player->bgmDrumCount = fileInfo->drumCount;
195
196 for (i = 0; i < player->bgmDrumCount; i++) {
197 BGMDrumInfo* drum = &player->drumsInfo[i];
198 player->drums[i] = drum;
199 }
200 for (; i < ARRAY_COUNT(player->drums); i++) {
201 player->drums[i] = player->drums[0];
202 }
203 } else {
204 player->drumsInfo = nullptr;
205 player->bgmDrumCount = 0;
206 }
207
208 if (fileInfo->instruments != 0) {
209 player->instrumentsInfo = AU_FILE_RELATIVE(player->bgmFile, fileInfo->instruments << 2);
210 player->bgmInstrumentCount = fileInfo->instrumentCount;
211 } else {
212 player->instrumentsInfo = nullptr;
213 player->bgmInstrumentCount = 0;
214 }
215
216 player->songName = songName;
218 } else {
220 }
221 } else {
223 }
224 return status;
225}
226
228 BGMPlayer* player;
229 AuResult status = AU_RESULT_OK;
230
231 if (songName != 0) {
232 player = au_bgm_get_player_with_song_name(songName);
233 if (player != nullptr) {
234 if (songName == player->songName) {
235 au_bgm_stop_player(player);
236 }
237 } else {
239 }
240 } else {
242 }
243
244 return status;
245}
246
247void au_bgm_stop_all(void) {
248 au_bgm_stop_player(gBGMPlayerA);
249 au_bgm_stop_player(gBGMPlayerB);
250}
251
252static void au_bgm_stop_player(BGMPlayer* player) {
253 if (player->masterState != BGM_PLAY_STATE_IDLE) {
255 player->nextUpdateCounter = 1;
256 player->nextUpdateStep = 1;
257 au_fade_clear(&player->fadeInfo);
258 }
259}
260
262 BGMPlayer* player;
263 AuResult result = AU_RESULT_OK;
264
265 if (songName != 0) {
266 player = au_bgm_get_player_with_song_name(songName);
267 if (player != nullptr) {
268 result = (songName == player->songName);
269 } else {
271 }
272 } else {
274 }
275
276 return result;
277}
278
280 if (player->songName != 0 && player->masterState != 0) {
281 return true;
282 } else {
283 return false;
284 }
285}
286
288 AuResult status;
289 BGMPlayer* player;
290 u32 songName = request->songName;
291 u32 duration = request->duration;
292 s16 volume = request->finalVolume;
293
294 status = AU_RESULT_OK;
295 if (songName != 0) {
296 if (duration >= SND_MIN_DURATION && duration <= SND_MAX_DURATION) {
297 player = au_bgm_get_player_with_song_name(songName);
298 if (player != nullptr) {
299 if (player->songName == songName) {
300 if (player->masterState != BGM_PLAY_STATE_IDLE) {
301 if (!player->paused) {
302 player->fadeInfo.baseTarget = volume;
303 player->fadeInfo.baseTicks = (duration * 1000) / AU_FRAME_USEC;
304 player->fadeInfo.baseStep = ((volume << 0x10) - player->fadeInfo.baseVolume) / player->fadeInfo.baseTicks;
305 player->fadeInfo.onCompleteCallback = request->doneCallback;
306 if (request->onPush == 1) {
307 player->pushSongName = songName;
308 }
309 }
310 }
311 }
312 } else {
314 }
315 } else {
317 }
318 } else {
320 }
321 return status;
322}
323
326
327 s.songName = songName;
328 s.duration = 0;
329 s.startVolume = 0;
330 s.finalVolume = 0;
332 s.pauseMode = false;
333
334 return au_bgm_process_suspend(&s, 0); // force stop
335}
336
338 AuResult status;
339 BGMPlayer* player;
341 s32 songName;
342 s32 index;
343 u32 i;
344 u32 j;
345
346 songName = request->songName;
347 index = request->index;
348 status = AU_RESULT_OK;
349
350 if (songName != 0) {
351 player = au_bgm_get_player_with_song_name(songName);
352 if (player != nullptr) {
353 if (!request->pauseMode) {
355 if (snapshot != nullptr) {
356 if (songName == player->songName) {
357 if (!skipStop) {
358 for (i = 0; i < ARRAY_COUNT(player->tracks); i++) {
359 BGMPlayerTrack* track = &player->tracks[i];
360 if (track->bgmReadPos != nullptr) {
361 for (j = track->firstVoice; j < track->lastVoice; j++) {
362 track->changed.all = 0;
363 }
364 }
365 }
366 }
367 player->globals->snapshots[index].priority = player->priority;
368 player->globals->snapshots[index].assigned = 1;
369 player->pushSongName = 0;
370 au_copy_words(player, snapshot, sizeof(*player));
371 if (!skipStop) {
372 au_bgm_stop_player(player);
373 }
374 }
375 } else {
377 }
378 } else {
379 if (songName == player->songName) {
380 if (player->masterState != BGM_PLAY_STATE_IDLE) {
381 player->paused = true;
383 }
384 }
385 }
386 } else {
388 }
389 } else {
391 }
392 return status;
393}
394
396 AuResult status;
397 BGMPlayer* player;
399 s32 index;
400 s32 songName;
401 s32 volume0;
402 s32 volume1;
403 s32 duration;
404
405 songName = request->songName;
406 index = request->index;
407 status = AU_RESULT_OK;
408
409 if (songName != 0) {
410 if (!request->pauseMode) {
412 if (snapshot != nullptr && snapshot->globals->snapshots[index].assigned == 1) {
413 player = au_get_client_by_priority(snapshot->globals->snapshots[index].priority);
414 if (player != nullptr) {
415 if (!au_bgm_player_is_active(player)) {
416 status = au_reload_song_files(snapshot->songID, snapshot->bgmFile);
417 duration = request->duration;
418 if (duration != 0) {
419 if (duration > SND_MAX_DURATION) {
420 duration = SND_MAX_DURATION;
421 } else if (duration < SND_MIN_DURATION) {
422 duration = SND_MIN_DURATION;
423 }
424 }
425 volume0 = request->startVolume;
426 if (volume0 > AU_MAX_VOLUME_8) {
428 }
429 if (volume0 != 0) {
431 }
432 volume1 = request->finalVolume;
433 if (volume1 > AU_MAX_VOLUME_8) {
435 }
436 if (volume1 != 0) {
438 } else {
440 }
441 player->globals->resumeCopyTo = player;
443 player->globals->resumeSongName = songName;
444 player->globals->resumeFadeTime = duration;
446 player->globals->resumeFadeEnd = volume1;
447 player->globals->resumeRequested = true;
448 } else {
449 status = AU_ERROR_7;
450 }
451 } else {
452 status = AU_ERROR_6;
453 }
454 } else {
456 }
457 } else {
458 player = au_bgm_get_player_with_song_name(songName);
459 if (player != nullptr) {
460 if (songName == player->songName) {
461 if (player->paused) {
462 player->paused = false;
463 }
464 }
465 }
466 }
467 } else {
469 }
470 return status;
471}
472
474 BGMPlayer* player;
476 SeqNote* note;
477 u32 i;
478 u32 j;
479 s32 k;
480
481 player = globals->resumeCopyTo;
482 au_copy_words(globals->resumeCopyFrom, globals->resumeCopyTo, sizeof(*player));
483 if (globals->resumeSongName == player->songName) {
484 for (i = 0; i < ARRAY_COUNT(player->tracks); i++) {
485 track = &player->tracks[i];
486 if (track->bgmReadPos != nullptr) {
487 for (j = track->firstVoice; j < track->lastVoice; j++) {
488 note = &player->notes[j];
489 note->length = 0;
490 }
491 }
492 }
493 for (k = 0; k < ARRAY_COUNT(player->effectIndices); k++) {
494 if (player->effectIndices[k] != 0xFF) {
495 player->seqCmdArgs.MasterEffect.index = player->effectIndices[k];
496 player->seqCmdArgs.MasterEffect.value = player->effectValues[k];
498 }
499 }
500 au_fade_init(&player->fadeInfo, globals->resumeFadeTime, globals->resumeFadeStart, globals->resumeFadeEnd);
501 }
502 globals->resumeRequested = false;
503}
504
506 BGMPlayer* player;
507 AuResult status = AU_RESULT_OK;
508
509 if (request->songName != 0) {
510 player = au_bgm_get_player_with_song_name(request->songName);
511 if (player != nullptr) {
512 au_fade_calc_envelope(&player->fadeInfo, request->duration, request->finalVolume);
513 }
514 else {
516 }
517 } else {
519 }
520 return status;
521}
522
523void au_bgm_player_init(BGMPlayer* player, s32 priority, s32 busID, AuGlobals* globals) {
524 s16 i;
525
526 player->globals = globals;
530 player->masterVolume = AU_MAX_VOLUME_8 << 24;
531 player->frameCounter = 0;
532 player->songPlayingCounter = 0;
533 player->songName = 0;
534 player->pushSongName = 0;
535 player->unk_58 = 0;
536 player->unk_5A = 0;
537 player->compReadPos = nullptr;
538 player->compStartPos = nullptr;
539 player->phraseStartPos = 0;
540 player->masterTempoTicks = 0;
541 player->masterTempoTarget = 0;
542 player->masterTempoStep = 0;
543 player->masterVolumeTicks = 0;
544 player->masterVolumeTarget = 0;
545 player->masterVolumeStep = 0;
546 player->masterPitchShift = 0;
547 player->detune = 0;
548 player->paused = false;
549 player->trackVolsConfig = nullptr;
550 player->bFadeConfigSetsVolume = false;
552 player->priority = priority;
553 player->busID = busID;
554 *(s32*)player->compLoopCounters = 0;
555 player->unused_222 = 0;
556 player->conditionalLoopFlags = 0;
557 player->playbackRate = 1.0f;
558 player->polyphonyCounts[BGM_POLYPHONY_0] = 0;
559 player->polyphonyCounts[BGM_POLYPHONY_1] = 1;
563 player->polyphonyCounts[BGM_POLYPHONY_2] = 2;
564 player->polyphonyCounts[BGM_POLYPHONY_3] = 3;
565 player->polyphonyCounts[BGM_POLYPHONY_4] = 4;
566
567 for (i = 0; i < ARRAY_COUNT(player->tracks); i++) {
568 BGMPlayerTrack* track = &player->tracks[i];
569
570 track->insVolume = 0;
571 track->delayTime = 0;
572 track->insCoarseDetune = 0;
573 track->insFineDetune = 0;
574 track->insPan = 0;
575 track->insReverb = 0;
576 track->patch = 0;
577 track->isDrumTrack = false;
578 track->volume = AU_MAX_VOLUME_8;
579 track->pressOverride = 0;
580
581 if (i < ARRAY_COUNT(player->cmdBufData)) {
582 player->cmdBufData[i] = 0;
583 }
584 }
585
586 for (i = 0; i < ARRAY_COUNT(player->notes); i++) {
587 SeqNote* note = &player->notes[i];
588
589 note->volume = 0;
590 note->detune = 0;
591 note->length = 0;
592 note->randDetune = 0;
593 note->velocity = 0;
594 note->pendingTick = false;
595 }
596
599}
600
602 s32 i;
604
605 for (i = 0; i < ARRAY_COUNT(player->effectIndices); i++) {
606 s8 idx = *list++;
607
608 if (idx < 0) {
609 break;
610 }
611 player->effectIndices[i] = idx;
612 }
613
614 remaining = ARRAY_COUNT(player->effectIndices) - i;
615 if (remaining > 0) {
616 while (remaining-- != 0) {
617 player->effectIndices[i++] = -1;
618 }
619 }
620}
621
623 player->fadeInfo.baseTicks--;
624
625 if (player->fadeInfo.baseTicks != 0) {
626 player->fadeInfo.baseVolume += player->fadeInfo.baseStep;
627 } else {
628 player->fadeInfo.baseVolume = player->fadeInfo.baseTarget << 16;
629
630 if (player->fadeInfo.onCompleteCallback != nullptr) {
632 }
633
634 // Was this fade tagged as a push?
635 if (player->pushSongName != 0) {
637 } else if (player->fadeInfo.baseVolume == 0) {
638 au_bgm_stop_player(player);
639 }
640 }
642}
643
645 u16 volume = (
646 ((u32)player->fadeInfo.baseVolume >> 16) *
647 ((u32)player->fadeInfo.envelopeVolume >> 16)
648 ) >> 15;
649 s32 i;
650
651 for (i = 0; i < ARRAY_COUNT(player->effectIndices); i++) {
652 s8 busID = player->effectIndices[i];
653
654 if (busID < 0) {
655 return;
656 }
657 au_fade_set_volume(busID, volume, player->busVolume);
658 }
659}
660
662 u16 hasMore = true;
663 s32 retVal = false;
664
665 // update pseudorandom numbers with fast 'good enough' method
666 player->randomValue1 = (player->randomValue1 & 0xFFFF) + (player->songPlayingCounter & 0xFFFF) + (player->frameCounter & 0xFFFF);
667 player->randomValue2 = (player->randomValue2 & 0xFFFF) + ((player->songPlayingCounter << 4) & 0xFFFF) + ((player->frameCounter >> 4) & 0xFFFF);
668 do {
669 switch (player->masterState) {
671 hasMore = false;
672 break;
674 if (!player->paused) {
676 if (player->masterState == BGM_PLAY_STATE_ACTIVE) {
677 hasMore = false;
678 }
679 } else {
680 hasMore = false;
681 }
682 break;
685 break;
688 hasMore = false;
689 break;
692 break;
693 default:
694 retVal = true;
695 hasMore = false;
696 break;
697 }
698 } while (hasMore);
699 return retVal;
700}
701
703 s32* buf;
704 s32 cmd;
706 s32 i;
707
708 for (i = 0; i < ARRAY_COUNT(player->tracks); i++) {
709 BGMPlayerTrack* track = &player->tracks[i];
711 track->insVolume = AU_MAX_VOLUME_16 << 16; // @bug? incorrect format for 8.24 fixed, should be (AU_MAX_VOLUME_8 << 24)
712 track->insPan = 0x40;
713 track->insReverb = 0;
714 track->patch = 0;
715 track->insCoarseDetune = 0;
716 track->insFineDetune = 0;
717 track->volume = AU_MAX_VOLUME_8;
718 track->pressOverride = 0;
719 track->proxVolume = AU_MAX_VOLUME_16 << 16;
720 track->savedPos = nullptr;
721 track->prevReadPos = nullptr;
722 track->detourLength = 0;
723 track->detune = 0;
724 track->tremoloDepth = 0;
725 track->tremoloDelay = 0;
726 track->tremoloRate = 0;
727 track->insVolumeStep = 0;
728 track->insVolumeTarget = 0;
729 track->insVolumeTicks = 0;
730 track->proxVolumeStep = 0;
731 track->proxVolumeTarget = 0;
732 track->proxVolumeTicks = 0;
733 track->proxMixSetChanged = false;
734 track->proxMixValChanged = false;
735 track->proxVol1 = 0;
736 track->proxVol2 = 0;
737 track->polyVoiceCount = 0;
738 track->polyphonicIdx = 0;
739 track->randomPanAmount = 0;
740 track->isDrumTrack = false;
741 track->linkedTrackID = 0;
742 track->muted = false;
743 track->busID = player->busID;
744 track->index = i;
745 }
746
747 for (i = 0; i < ARRAY_COUNT(player->notes); i++) {
748 SeqNote* note = &player->notes[i];
750 note->pitchRatio = 2.0f;
751 note->randDetune = 0;
752 note->velocity = 0;
753 note->length = 0;
754 note->tremoloDepth = 0;
755 }
756
758 player->playbackRate = 128.0f; // set to 1.0 later om...
761 player->unused_21E = 0x80;
762 player->masterVolume = AU_MAX_VOLUME_8 << 24;
763 player->pushSongName = 0;
764 player->tickRatePtr = nullptr;
765 player->masterTempoTarget = 0;
766 player->masterPitchShift = 0;
767 player->detune = 0;
768 player->masterVolumeTicks = 0;
769 player->masterVolumeTarget = 0;
770 player->masterVolumeStep = 0;
771 player->proxMixValue = 0;
772 player->proxMixID = 0;
773 player->proxMixVolume = 0;
774 player->compActiveLoopEndPos[3] = nullptr;
775 player->compActiveLoopEndPos[2] = nullptr;
776 player->compActiveLoopEndPos[1] = nullptr;
777 player->compActiveLoopEndPos[0] = nullptr;
778 *(s32*)player->compLoopCounters = 0;
779 player->compLoopDepth = 0;
780 player->unused_222 = 0;
781 player->conditionalLoopFlags = 0;
782 player->trackVolsConfig = nullptr;
783 player->bFadeConfigSetsVolume = false;
784 player->initLinkMute = true;
785 player->writingCustomEnvelope = 0;
786 player->playbackRate = 1.0f;
787
788 for (i = 0; i < ARRAY_COUNT(player->customEnvelopeWritePos); i++) {
790 }
791
792 for (i = 0; i < ARRAY_COUNT(player->effectValues); i++) {
793 player->effectValues[i] = 0;
794 }
795
796 player->paused = false;
797 player->songPlayingCounter = 0;
798 for (i = 0; i < ARRAY_COUNT(player->compLoopStartLabels); i++) {
799 player->compLoopStartLabels[i] = player->compReadPos;
800 }
801
802 // find labels
803 buf = player->compReadPos;
804 keepReading = true;
805 while (keepReading) {
806 cmd = *buf++;
807 if (cmd == 0) {
808 keepReading = false;
809 } else if ((cmd & 0xF0000000) == BGM_COMP_START_LOOP << 28) {
810 player->compLoopStartLabels[cmd & 0x1F] = buf;
811 }
812 }
813
815}
816
818 s32 i;
819 u16* pos = player->customPressEnvelopes[index];
820 player->customEnvelopeWritePos[index] = 0;
821
822 for (i = 0; i < 9; i++) {
823 *pos++ = 0xFF00;
824 }
825}
826
828 // compute how many audio frames before the next tick
830
831 // Clamp samples per tick to stay in a valid range
832 if (mFramesPerTick > 500000) {
833 mFramesPerTick = 500000;
834 } else if (mFramesPerTick < 80000) {
835 mFramesPerTick = 80000;
836 }
837
838 // Clamp to sample rate
841 }
842
843 // breakdown of units:
844 //
845 // tickUpdateInterval / nextUpdateStep = framesPerTick
846 //
847 // 1000 x frames beat min frames
848 // ------------- x ------ x --------------- = ------
849 // min tick 1000 x beat tick
850
854
856}
857
858// runs whenever a new composition begins playing
860 u16 continueReading = true;
861 u32 cmd;
862
863 player->masterTempoStep = 0;
864 player->masterTempoTicks = 0;
865
866 while (continueReading) {
867 cmd = *player->compReadPos++;
868 if (cmd == BGM_COMP_END) {
870 continueReading = false;
871 } else {
872 switch (cmd >> 12) {
873 case BGM_COMP_PLAY_PHRASE << 16:
874 au_bgm_load_phrase(player, cmd);
876 continueReading = false;
877 break;
878 case BGM_COMP_START_LOOP << 16:
879 break;
880 case BGM_COMP_WAIT << 16:
881 continueReading = false;
882 break;
883 case BGM_COMP_END_LOOP << 16:
885 break;
887 if (!(player->conditionalLoopFlags & 1)) {
889 }
890 break;
892 if (player->conditionalLoopFlags & 1) {
894 }
895 break;
896 default:
897 continueReading = false;
898 break;
899 }
900 }
901 }
902}
903
905 s32 labelIndex = cmd & 0x1F; // 01F (bits 0-4)
906 s32 iterCount = (cmd >> 5) & 0x7F; // FE0 (bits 5-11)
907 u32 depth;
908
909 depth = player->compLoopDepth;
910 if (player->compActiveLoopEndPos[depth] != nullptr) {
911 if (player->compActiveLoopEndPos[depth] == player->compReadPos) {
912 if (player->compLoopCounters[depth] != 0) {
913 player->compLoopCounters[depth]--;
914 if ((player->compLoopCounters[depth]) == 0) {
915 player->compActiveLoopEndPos[depth] = nullptr;
916 if (depth > 0) {
917 depth--;
918 }
919 } else {
920 player->compReadPos = player->compLoopStartLabels[labelIndex];
921 }
922 } else {
923 player->compReadPos = player->compLoopStartLabels[labelIndex];
924 }
925 } else if (depth < 4) {
926 depth++;
927 player->compActiveLoopEndPos[depth] = player->compReadPos;
928 player->compLoopCounters[depth] = iterCount;
929 player->compReadPos = player->compLoopStartLabels[labelIndex];
930 }
931 } else {
932 player->compActiveLoopEndPos[depth] = player->compReadPos;
933 player->compLoopCounters[depth] = iterCount;
934 player->compReadPos = player->compLoopStartLabels[labelIndex];
935 }
936 player->compLoopDepth = depth;
937}
938
942 s32* trackList;
944 s32 count;
945 s32 curVoice;
947 s32 i;
948
949 curVoice = 0;
950 bFoundLinkedTrack = false;
951 player->phraseStartPos = AU_FILE_RELATIVE(player->compStartPos, (cmd & 0xFFFF) << 2);
952 trackList = player->phraseStartPos;
953 for (i = 0; i < ARRAY_COUNT(player->tracks); i++) {
954 track = &player->tracks[i];
955 trackInfo = *trackList++;
956 track->bgmReadPos = (AuFilePos) (trackInfo >> 0x10);
957 if (track->bgmReadPos != nullptr) {
958 if ((trackInfo & 0x100) == 0) {
959 track->polyphonicIdx = (trackInfo & (0x7 << 0xD)) >> 0xD;
960 track->isDrumTrack = (trackInfo >> 7) & 1;
961 linkedID = (trackInfo & (0xF << 9)) >> 9;
962 track->linkedTrackID = 0;
963 if (linkedID != 0) {
964 BGMPlayerTrack* linkedTrack = &player->tracks[linkedID - 1];
965 if ((linkedID - 1) < i) {
966 track->polyVoiceCount = linkedTrack->polyVoiceCount;
967 track->firstVoice = linkedTrack->firstVoice;
968 track->lastVoice = linkedTrack->lastVoice;
969
970 track->bgmReadPos = (track->bgmReadPos + (s32)player->phraseStartPos);
971 track->delayTime = 1;
972
973 track->linkedTrackID = linkedID;
974 if (player->initLinkMute) {
975 track->muted = true;
976 }
977 bFoundLinkedTrack = true;
978 } else {
979 track->bgmReadPos = nullptr;
980 }
981 } else {
982 count = player->polyphonyCounts[track->polyphonicIdx];
983 track->polyVoiceCount = count;
984 track->firstVoice = curVoice;
985 curVoice += count;
986 track->lastVoice = curVoice;
987
988 track->bgmReadPos = (track->bgmReadPos + (s32)player->phraseStartPos);
989 track->delayTime = 1;
990 }
991 } else {
992 track->bgmReadPos = nullptr;
993 }
994 }
995 }
996 player->totalVoices = curVoice;
997 if (bFoundLinkedTrack) {
998 player->initLinkMute = false;
999 }
1000}
1001
1003 s32 i;
1004
1005 player->paused = false;
1006 player->songName = 0;
1007 player->pushSongName = 0;
1008 player->unk_58 = 0;
1009 player->unk_5A = 0;
1010 for (i = 0; i < ARRAY_COUNT(player->tracks); i++) {
1011 player->tracks[i].bgmReadPos = nullptr;
1012 }
1016}
1017
1018#define POST_BGM_READ() \
1019if (track->detourLength != 0) {\
1020 track->detourLength--;\
1021 if (track->detourLength == 0) {\
1022 track->bgmReadPos = track->savedPos;\
1023 }\
1024}
1025
1029 u8 sp1F;
1030 s16 notePitch;
1031 u8 bFinished;
1032
1033 AuVoice* voice;
1036 SeqNote* note;
1037 s32 temp;
1040 u8 opcode;
1043 u32 i;
1044 u8 voiceIdx;
1045 bVolumeFading = false;
1046 bFinished = false;
1047
1048 if (player->masterTempoTicks != 0) {
1049 player->masterTempoTicks--;
1050 if (player->masterTempoTicks == 0) {
1051 player->masterTempo = player->masterTempoTarget;
1052 player->masterTempoTarget = 0;
1053 player->masterTempoStep = 0;
1054 } else {
1055 player->masterTempo += player->masterTempoStep;
1056 }
1058 }
1059 if (player->masterVolumeTicks != 0) {
1060 player->masterVolumeTicks--;
1061 if (player->masterVolumeTicks == 0) {
1062 player->masterVolume = player->masterVolumeTarget;
1063 player->masterVolumeTarget = 0;
1064 player->masterVolumeStep = 0;
1065 } else {
1066 player->masterVolume += player->masterVolumeStep;
1067 }
1068 bVolumeFading = true;
1069 }
1070 player->volumeChanged = false;
1071 if (player->trackVolsConfig != nullptr) {
1072 if (player->bFadeConfigSetsVolume) {
1073 // setting track volumes
1074 s32 lenLimit = 16;
1075 while (lenLimit-- != 0) {
1076 i = *player->trackVolsConfig++;
1077 if (i == 0) {
1078 break;
1079 }
1080 track = &player->tracks[i - 1];
1081 player->seqCmdArgs.TrackVolumeFade.time = 48;
1082 player->seqCmdArgs.TrackVolumeFade.value = *(player->trackVolsConfig++);
1083 if (track->bgmReadPos != 0) {
1085 }
1086 }
1087 }
1088 else {
1089 // clearing track volumes
1090 s32 lenLimit = 16;
1091 while (lenLimit-- != 0) {
1092 i = *player->trackVolsConfig++;
1093 if (i == 0) {
1094 break;
1095 }
1096 track = &player->tracks[i - 1];
1097 player->seqCmdArgs.TrackVolumeFade.time = 48;
1098 player->trackVolsConfig++; // ignore arg
1099 player->seqCmdArgs.TrackVolumeFade.value = 0;
1100 if (track->bgmReadPos != 0) {
1102 }
1103 }
1104 }
1105 player->trackVolsConfig = nullptr;
1106 player->bFadeConfigSetsVolume = false;
1107 }
1108 for (i = 0; i < ARRAY_COUNT(player->tracks); i++) {
1109 track = &player->tracks[i];
1110 if (track->bgmReadPos != nullptr) {
1111 track->changed.all = 0;
1112 if (bVolumeFading || player->volumeChanged) {
1113 track->changed.volume = true;
1114 } else {
1115 track->changed.volume = false;
1116 }
1117 if (track->insVolumeTicks != 0) {
1118 track->insVolumeTicks--;
1119 if (track->insVolumeTicks == 0) {
1120 track->insVolume = track->insVolumeTarget;
1121 } else {
1122 track->insVolume += track->insVolumeStep;
1123 }
1124 track->changed.volume = true;
1125 }
1126 if (track->proxVolumeTicks != 0) {
1127 track->proxVolumeTicks--;
1128 if (track->proxVolumeTicks == 0) {
1129 track->proxVolume = track->proxVolumeTarget << 16;
1130 } else {
1131 track->proxVolume += track->proxVolumeStep;
1132 }
1133 track->changed.volume = true;
1134 }
1135 track->delayTime--;
1136 if (track->delayTime <= 0) {
1137 sp1F = track->firstVoice;
1138 while (track->delayTime == 0) {
1139 opcode = *(track->bgmReadPos++);
1140 POST_BGM_READ();
1141
1142 if (opcode < 0x80) {
1143 if (opcode == 0) {
1144 if (track->prevReadPos != 0) {
1145 track->bgmReadPos = track->prevReadPos;
1146 track->prevReadPos = 0;
1147 } else {
1148 bFinished = true;
1149 break;
1150 }
1151 } else {
1152 if (opcode >= 0x78) {
1153 // long delay
1154 track->delayTime = (((opcode & 7) << 8) + *(track->bgmReadPos++)) + 0x78;
1155 POST_BGM_READ();
1156
1157 } else {
1158 // delay
1159 track->delayTime = opcode;
1160 }
1161 }
1162 } else {
1163 // note
1164 if (opcode < 0xD4) {
1165 notePitch = (opcode & 0x7F);
1166 noteVelocity = *(track->bgmReadPos++);
1167 POST_BGM_READ();
1168 noteLength = *(track->bgmReadPos++);
1169 POST_BGM_READ();
1170 if (!(noteLength < 0xC0)) {
1171 noteLength = (((u8)noteLength & ~0xC0) << 8) + *(track->bgmReadPos++) + 0xC0;
1172 POST_BGM_READ();
1173 }
1174 bAcquiredVoiceIdx = false;
1175 if (!track->muted) {
1176 // find first free voice
1177 for (voiceIdx = sp1F; voiceIdx < track->lastVoice; voiceIdx++) {
1178 voice = &player->globals->voices[voiceIdx];
1179 sp1F++;
1180 if (voice->priority == AU_PRIORITY_FREE) {
1181 bAcquiredVoiceIdx = true;
1182 break;
1183 }
1184 }
1185
1186 if (!bAcquiredVoiceIdx) {
1187 if (track->polyphonicIdx >= BGM_POLYPHONY_2) {
1188 // try stealing a voice with lower priority
1189 for (voiceIdx = track->firstVoice; voiceIdx < track->lastVoice; voiceIdx++) {
1190 voice = &player->globals->voices[voiceIdx];
1191 if (voice->priority < player->priority) {
1193 bAcquiredVoiceIdx = true;
1194 break;
1195 }
1196 }
1197 // try stealing a voice with equal priority and zero note length
1198 if (!bAcquiredVoiceIdx) {
1199 for (voiceIdx = track->firstVoice; voiceIdx < track->lastVoice; voiceIdx++) {
1200 voice = &player->globals->voices[voiceIdx];
1201 if (voice->priority == player->priority) {
1202 note = &player->notes[voiceIdx];
1203 if (note->length == 0) {
1205 bAcquiredVoiceIdx = true;
1206 break;
1207 }
1208 }
1209 }
1210 }
1211 // try stealing a voice with equal priority and lowest note length
1212 if (!bAcquiredVoiceIdx) {
1213 s32 shortestLength = 0xFFFF;
1214 u8 voice_it;
1215 AuVoice* curVoice;
1217 for (voice_it = track->firstVoice; voice_it < track->lastVoice; voice_it++) {
1218 curVoice = &player->globals->voices[voice_it];
1219 if (curVoice->priority == player->priority) {
1220 curNote = &player->notes[voice_it];
1221 if (!curNote->pendingTick && curNote->length < shortestLength) {
1223 voice = curVoice;
1224 note = curNote;
1226 bAcquiredVoiceIdx = true;
1227 }
1228 }
1229 }
1230 if (bAcquiredVoiceIdx) {
1231 note->length = 0;
1233 }
1234 }
1235
1236 } else {
1237 voiceIdx = track->firstVoice;
1238 voice = &player->globals->voices[voiceIdx];
1239 note = &player->notes[voiceIdx];
1240 note->length = 0;
1241 if (voice->priority <= player->priority) {
1243 bAcquiredVoiceIdx = true;
1244 }
1245 }
1246 }
1247 }
1248 if (bAcquiredVoiceIdx) {
1249 note = &player->notes[voiceIdx];
1250 note->tremoloDepth = 0;
1251 if (noteVelocity > 0) {
1252 note->velocity = noteVelocity + 1;
1253 } else {
1254 note->velocity = 0;
1255 }
1256 note->length = noteLength;
1257 if (track->isDrumTrack) {
1258 if (notePitch < 72) { // = 6 * 12
1259 drumInfo = &player->globals->dataPER->drums[notePitch];
1260 } else {
1261 drumInfo = player->drums[notePitch - 72]; // = 6 * 12
1262 }
1263 note->ins = au_get_instrument(player->globals, drumInfo->bankPatch >> 8, drumInfo->bankPatch & 0xFF, &voice->envelope);
1264 if (drumInfo->randVolume != 0) {
1265 note->volume = note->velocity * au_bgm_get_random_vol(player->randomValue1, drumInfo->volume, drumInfo->randVolume);
1266 } else {
1267 note->volume = note->velocity * drumInfo->volume;
1268 }
1269 // combining formats: 7.24 * 7.24 * 15.16 * 7.0 * 15.0 --> 16.16
1270 // first step, shifting fractional factors by 21:
1271 // 7.24 * 7.24 * 15.16 --> 7.3 * 7.3 * 10.0 --> 24.6
1272 // shifting this down by 20 transforms 24.6 --> 10.0
1273 // now for the second step with whole:
1274 // 10.0 * 7.0 * 15.0 --> 32.0
1275 // and a final shift by 16 transforms 32.0 --> 16.16
1276 voice->clientVolume = ((
1277 ((player->masterVolume >> 21) // 7.24 --> 7.3
1278 * (track->insVolume >> 21) // 7.24 --> 7.3
1279 * (track->proxVolume >> 21)) >> 20) // 15.16 --> 10.0 (fractional part truncated?)
1280 * (track->volume * note->volume)) >> 16;
1281 note->detune =
1282 drumInfo->keyBase
1283 + track->insCoarseDetune
1284 + track->insFineDetune
1285 - note->ins->keyBase;
1286 temp = (note->detune + track->detune) + player->detune;
1287 if (drumInfo->randTune != 0) {
1288 note->randDetune = au_bgm_get_random_pitch(player->randomValue1, temp, drumInfo->randTune);
1289 temp = note->randDetune;
1290 }
1291 note->pitchRatio = au_compute_pitch_ratio(temp) * note->ins->pitchRatio;
1292 if (drumInfo->randPan != 0) {
1293 voice->pan = au_bgm_get_random_pan(player, drumInfo->pan, drumInfo->randPan);
1294 } else {
1295 voice->pan = drumInfo->pan;
1296 }
1297 if (drumInfo->randReverb != 0) {
1298 voice->reverb = au_bgm_get_random_reverb(player->randomValue1, drumInfo->reverb, drumInfo->randReverb);
1299 } else {
1300 voice->reverb = drumInfo->reverb;
1301 }
1302 } else {
1303 // combining formats: 7.24 * 7.24 * 15.16 * 7.0 * 15.0 --> 16.16
1304 // first step, shifting fractional factors by 21:
1305 // 7.24 * 7.24 * 15.16 --> 7.3 * 7.3 * 10.0 --> 24.6
1306 // shifting this down by 20 transforms 24.6 --> 10.0
1307 // now for the second step with whole:
1308 // 10.0 * 7.0 * 7.0 --> 24.0
1309 // and a final shift by 9 transforms 24.0 --> 15.16
1310 voice->clientVolume = note->volume = ((
1311 ((player->masterVolume >> 21) // 7.24 --> 7.3
1312 * (track->insVolume >> 21) // 7.24 --> 7.3
1313 * (track->proxVolume >> 21)) >> 20) // 15.16 --> 10.0 (fractional part truncated?)
1314 * (track->volume * note->velocity)) >> 9;
1315 note->ins = track->instrument;
1316 note->detune =
1317 (notePitch * 100)
1318 + track->insCoarseDetune
1319 + player->masterPitchShift
1320 + track->insFineDetune
1321 - note->ins->keyBase;
1322 note->pitchRatio = au_compute_pitch_ratio(
1323 note->detune
1324 + track->detune
1325 + player->detune)
1326 * track->instrument->pitchRatio;
1327
1328 if (track->randomPanAmount != 0) {
1329 voice->pan = au_bgm_get_random_pan(player, track->insPan, track->randomPanAmount);
1330 } else {
1331 voice->pan = track->insPan;
1332 }
1333 voice->reverb = track->insReverb;
1334
1335 if (track->pressOverride != 0) {
1336 voice->envelope.cmdListPress = (u8*) player->customPressEnvelopes[track->pressOverride - 1];
1337 } else {
1338 voice->envelope.cmdListPress = track->envelope.cmdListPress;
1339 }
1340 voice->envelope.cmdListRelease = track->envelope.cmdListRelease;
1341 }
1342 voice->instrument = note->ins;
1343 voice->pitchRatio = note->pitchRatio;
1344 voice->busID = track->busID;
1345 if (note->length > 1) {
1346 note->pendingTick = true;
1347 note->tremoloDepth = track->tremoloDepth;
1348 note->tremoloPhase = 0;
1349 note->tremoloDelay = track->tremoloDelay;
1350 voice->syncFlags = AU_VOICE_SYNC_FLAG_ALL;
1351 voice->priority = player->priority;
1352 voice->clientPriority = voice->priority;
1353 }
1354 }
1355 } else {
1356 //TODO variable is nargs, but reusing temp is required to match
1357 temp = SeqCmdArgCounts[opcode - 0xE0];
1358 if (temp != 0) {
1359 player->seqCmdArgs.raw[0] = *(track->bgmReadPos++);
1360 POST_BGM_READ();
1361 } else {
1362 goto bgm_args_done;
1363 }
1364 if (temp > 1) {
1365 player->seqCmdArgs.raw[1] = *(track->bgmReadPos++);
1366 POST_BGM_READ();
1367 } else {
1368 goto bgm_args_done;
1369 }
1370 if (temp > 2) {
1371 player->seqCmdArgs.raw[2] = *(track->bgmReadPos++);
1372 POST_BGM_READ();
1373 } else {
1374 goto bgm_args_done;
1375 }
1376 if (temp > 3) {
1377 player->seqCmdArgs.raw[3] = *(track->bgmReadPos++);
1378 POST_BGM_READ();
1379 }
1382 CurrentSeqCmdHandler(player, track);
1383 }
1384 }
1385 } // end while
1386 }
1387
1388 for (voiceIdx = track->firstVoice; voiceIdx < track->lastVoice; voiceIdx++) {
1389 if (!track->muted) {
1390 voice = &player->globals->voices[voiceIdx];
1391 if (voice->priority == player->priority) {
1392 note = &player->notes[voiceIdx];
1393 if (!note->pendingTick) {
1394 if (note->length > 0) {
1395 note->length--;
1396 if (note->length == 0) {
1397 voice->envelopeFlags |= AU_VOICE_ENV_FLAG_KEY_RELEASED;
1398 }
1399 }
1400 if (track->isDrumTrack) {
1401 if (track->changed.tune || (player->detune != 0)) {
1402 note->pitchRatio = au_compute_pitch_ratio(((note->detune + note->randDetune) + track->detune) + player->detune) * note->ins->pitchRatio;
1403 if (voice->pitchRatio != note->pitchRatio) {
1404 voice->pitchRatio = note->pitchRatio;
1405 voice->syncFlags |= AU_VOICE_SYNC_FLAG_PITCH;
1406 }
1407 }
1408 if (track->changed.volume) {
1409 // combining formats: 7.24 * 7.24 * 15.16 * 7.0 * 15.0 --> 16.16
1410 // first step, shifting fractional factors by 21:
1411 // 7.24 * 7.24 * 15.16 --> 7.3 * 7.3 * 10.0 --> 24.6
1412 // shifting this down by 20 transforms 24.6 --> 10.0
1413 // now for the second step with whole:
1414 // 10.0 * 7.0 * 15.0 --> 32.0
1415 // and a final shift by 16 transforms 32.0 --> 16.16
1416 voice->clientVolume = (
1417 ((((player->masterVolume >> 21) // 7.24 --> 7.3
1418 * (track->insVolume >> 21)) // 7.24 --> 7.3
1419 * (track->proxVolume >> 21)) >> 20) // 15.16 --> 10.0 (fractional part truncated?)
1420 * (track->volume * note->volume)) >> 16;
1421 voice->envelopeFlags |= AU_VOICE_ENV_FLAG_VOL_CHANGED;
1422 }
1423 } else {
1424 // Modulate pitch using a triange wave for tremolo effect
1425 if (note->tremoloDepth != 0) {
1426 if (note->tremoloDelay != 0) {
1427 note->tremoloDelay--;
1428 } else {
1429 u8 quadrant;
1430 note->tremoloPhase += track->tremoloRate;
1431 opcode = (note->tremoloPhase << 2) + 3; // +3 just to fill lower 2 bits
1432
1433 // Determine what part of the triangle wave we are in (using top 2 bits of u8)
1434 quadrant = note->tremoloPhase >> 6;
1435
1436 // Invert the triangle for quadrants 1 and 3 (ugly code required to match)
1437 /* visualized: //// --> /\/\ */
1438 if ((quadrant == 1) || (quadrant == 3)) {
1439 u8 temp2 = ~opcode;
1440 tremoloDetune = temp2 + 1;
1441 } else {
1443 }
1444
1445 // Scale by depth
1446 tremoloDetune = (tremoloDetune * track->tremoloDepth) >> 8;
1447
1448 // Invert sign for the second half of triangle wave
1449 if ((quadrant == 2) || (quadrant == 3)) {
1451 }
1452
1453 // Apply pitch detune from tremolo
1454 note->pitchRatio = au_compute_pitch_ratio(tremoloDetune + ((note->detune + track->detune) + player->detune)) * note->ins->pitchRatio;
1455 if (voice->pitchRatio != note->pitchRatio) {
1456 voice->pitchRatio = note->pitchRatio;
1457 voice->syncFlags |= AU_VOICE_SYNC_FLAG_PITCH;
1458 }
1459 }
1460 } else if (track->changed.tune || (player->detune != 0)) {
1461
1462 note->pitchRatio = au_compute_pitch_ratio((note->detune + track->detune) + player->detune) * note->ins->pitchRatio;
1463 if (voice->pitchRatio != note->pitchRatio) {
1464 voice->pitchRatio = note->pitchRatio;
1465 voice->syncFlags |= AU_VOICE_SYNC_FLAG_PITCH;
1466 }
1467 }
1468 if (track->changed.volume) {
1469 // combining formats: 7.24 * 7.24 * 15.16 * 7.0 * 15.0 --> 16.16
1470 // first step, shifting fractional factors by 21:
1471 // 7.24 * 7.24 * 15.16 --> 7.3 * 7.3 * 10.0 --> 24.6
1472 // shifting this down by 20 transforms 24.6 --> 10.0
1473 // now for the second step with whole:
1474 // 10.0 * 7.0 * 7.0 --> 24.0
1475 // and a final shift by 9 transforms 24.0 --> 15.16
1476 note->volume = ((
1477 (player->masterVolume >> 21) // 7.24 --> 7.3
1478 * (track->insVolume >> 21) // 7.24 --> 7.3
1479 * (track->proxVolume >> 21)) >> 20)
1480 * (track->volume * note->velocity) >> 9;
1481 voice->clientVolume = note->volume;
1482 voice->envelopeFlags |= AU_VOICE_ENV_FLAG_VOL_CHANGED;
1483 voice->pan = track->insPan;
1484 voice->reverb = track->insReverb;
1485 } else if (track->changed.pan || track->changed.reverb) {
1486 voice->pan = track->insPan;
1487 voice->reverb = track->insReverb;
1488 voice->syncFlags |= AU_VOICE_SYNC_FLAG_PAN_FXMIX;
1489 }
1490 }
1491 }
1492 note->pendingTick = false;
1493 }
1494 }
1495 }
1496 }
1497 }
1498
1499 if (bFinished) {
1501 }
1502}
1503
1504
1506 u32 bpm = player->seqCmdArgs.MasterTempo.value;
1507 s32 tempo;
1508
1509 player->masterTempoBPM = bpm;
1510 tempo = au_bgm_bpm_to_tempo(player, bpm);
1511 player->masterTempo = tempo;
1513 player->masterTempoTicks = 0;
1514 player->masterTempoTarget = 0;
1515 player->masterTempoStep = 0;
1516}
1517
1518static s32 au_bgm_bpm_to_tempo(BGMPlayer* player, u32 tempo) {
1519 u32 maxTempo = player->maxTempo;
1520 u32 ret = tempo;
1521
1522 ret *= player->playbackRate;
1523
1524 if (maxTempo < ret) {
1525 ret = maxTempo;
1526 } else if (ret == 0) {
1527 ret = 1;
1528 }
1529
1530 return ret * 100;
1531}
1532
1534 s8_24 volume = player->seqCmdArgs.MasterVolume.value & 0x7F;
1535
1536 if (volume != 0) {
1537 volume = volume << 24;
1538 }
1539
1540 player->masterVolume = volume;
1541 player->masterVolumeTicks = 0;
1542 player->masterVolumeTarget = 0;
1543 player->masterVolumeStep = 0;
1544 player->volumeChanged = true;
1545 track->changed.volume = true;
1546}
1547
1549 player->masterPitchShift = (s8)player->seqCmdArgs.MasterPitchShift.cent * 100;
1550}
1551
1553 player->globals->effectChanges[player->busID].type = player->seqCmdArgs.UnkCmdE3.effectType;
1554 player->globals->effectChanges[player->busID].changed = true;
1555}
1556
1558 u8 index = player->seqCmdArgs.MasterEffect.index;
1559 u32 busID = player->effectIndices[index];
1560
1561 if ((index < 4) && (busID < 0x80)) {
1562 if (player->globals->effectChanges[busID].type != player->seqCmdArgs.MasterEffect.value) {
1563 player->globals->effectChanges[busID].type = player->seqCmdArgs.MasterEffect.value;
1564 player->globals->effectChanges[busID].changed = true;
1565 }
1566 player->effectValues[index] = player->seqCmdArgs.MasterEffect.value;
1567 }
1568}
1569
1571 s32 time = player->seqCmdArgs.MasterTempoFade.time;
1572 s32 tempo = au_bgm_bpm_to_tempo(player, player->seqCmdArgs.MasterTempoFade.value);
1573
1574 if (time <= 0) {
1575 time = 1;
1576 }
1577
1578 player->masterTempoTicks = time;
1579 player->masterTempoTarget = tempo;
1580 player->masterTempoStep = (tempo - player->masterTempo) / time;
1581}
1582
1584 s32 time = player->seqCmdArgs.MasterVolumeFade.time;
1585 s8_24 volume = player->seqCmdArgs.MasterVolumeFade.value & 0x7F;
1586
1587 if (volume != 0) {
1588 volume = volume << 24;
1589 }
1590
1591 if (time <= 0) {
1592 time = 1;
1593 }
1594
1595 player->masterVolumeTicks = time;
1596 player->masterVolumeTarget = volume;
1597 player->masterVolumeStep = (volume - player->masterVolume) / time;
1598}
1599
1601 track->patch = player->seqCmdArgs.OverridePatch.patch;
1602 track->instrument = au_get_instrument(player->globals, player->seqCmdArgs.OverridePatch.bank, track->patch, &track->envelope);
1603}
1604
1606 s8_24 volume = arg0->seqCmdArgs.InstrumentVolume.value & 0x7F;
1607
1608 if (volume != 0) {
1609 volume = volume << 24;
1610 }
1611
1612 track->insVolume = volume;
1613 track->changed.volume = true;
1614}
1615
1617 s32 time = player->seqCmdArgs.TrackVolumeFade.time;
1618 s8_24 volume = player->seqCmdArgs.TrackVolumeFade.value & 0x7F;
1619
1620 if (volume != 0) {
1621 volume = volume << 24;
1622 }
1623
1624 if (volume != track->insVolume) {
1625 if (time <= 0) {
1626 time = 1;
1627 }
1628
1629 track->insVolumeTicks = time;
1630 track->insVolumeTarget = volume;
1631 track->insVolumeStep = (volume - track->insVolume) / time;
1632 }
1633}
1634
1636 track->insPan = player->seqCmdArgs.InstrumentPan.value & 0x7F;
1637 track->randomPanAmount = 0;
1638 track->changed.pan = true;
1639}
1640
1642 track->insReverb = player->seqCmdArgs.InstrumentReverb.value & 0x7F;
1643 track->changed.reverb = true;
1644}
1645
1647 track->volume = player->seqCmdArgs.TrackVolume.value & 0x7F;
1648 track->changed.volume = true;
1649}
1650
1654
1656 track->insFineDetune = player->seqCmdArgs.InstrumentFineTune.cent;
1657}
1658
1660 track->detune = player->seqCmdArgs.TrackDetune.cents;
1661 track->changed.tune = true;
1662}
1663
1665 track->tremoloDelay = player->seqCmdArgs.TrackTremolo.delay;
1666 track->tremoloRate = player->seqCmdArgs.TrackTremolo.speed;
1667 track->tremoloDepth = player->seqCmdArgs.TrackTremolo.depth;
1668}
1669
1671 track->tremoloRate = player->seqCmdArgs.TrackTremoloRate.value;
1672}
1673
1675 track->tremoloDepth = player->seqCmdArgs.TrackTremoloDepth.value;
1676}
1677
1679 track->tremoloDepth = 0;
1680}
1681
1683 track->insPan = player->seqCmdArgs.RandomPan.pan0 & 0x7F;
1684 track->randomPanAmount = player->seqCmdArgs.RandomPan.pan1 & 0x7F;
1685}
1686
1688 BGMInstrumentInfo* instrument;
1689 s32 volume;
1690 u32 insIndex;
1691 u32 patch;
1692 u32 bank;
1693
1694 insIndex = player->seqCmdArgs.UseInstrument.index;
1696 if (insIndex < player->bgmInstrumentCount) {
1697 instrument = &player->instrumentsInfo[insIndex];
1698 } else {
1699 instrument = &player->globals->defaultPRGEntry;
1700 }
1701 } else {
1703 if (insIndex < PRG_MAX_COUNT) {
1704 instrument = &player->globals->dataPRG[insIndex];
1705 } else {
1706 instrument = &player->globals->defaultPRGEntry;
1707 }
1708 }
1709 bank = instrument->bankPatch >> 8;
1710 patch = (u8)instrument->bankPatch;
1711 volume = instrument->volume & 0x7F;
1712 track->patch = patch;
1713 track->instrument = au_get_instrument(player->globals, bank, patch, &track->envelope);
1714 if (volume != 0) {
1715 volume <<= 24;
1716 }
1717 track->insVolume = volume;
1718 track->insPan = instrument->pan & 0x7F;
1719 track->insReverb = instrument->reverb & 0x7F;
1720 track->insCoarseDetune = instrument->coarseTune * AU_SEMITONE_CENTS;
1721 track->insFineDetune = instrument->fineTune;
1722 track->changed.all |= 0x10101; // volume, pan, and reverb
1723}
1724
1726 u8 index = player->seqCmdArgs.ReverbType.index;
1727 s8 busID = player->effectIndices[index];
1728
1729 if ((index < ARRAY_COUNT(player->effectIndices)) && (busID >= 0)) {
1730 track->busID = busID;
1731 } else {
1732 track->busID = player->busID;
1733 }
1734}
1735
1739
1740// jump to another part of the track and return after a specified read length
1742 AuFilePos readPos = AU_FILE_RELATIVE(player->bgmFile, player->seqCmdArgs.Detour.offset);
1743
1744 track->detourLength = player->seqCmdArgs.Detour.length;
1745 track->savedPos = track->bgmReadPos;
1746 track->bgmReadPos = readPos;
1747}
1748
1749// jump to another part of the track, selected by player->branchVar
1751 AuFilePos args;
1752 u32 i;
1753
1754 // get jump table
1755 args = AU_FILE_RELATIVE(player->bgmFile, player->seqCmdArgs.Branch.offset);
1756 if (player->proxMixID < player->seqCmdArgs.Branch.tableCount) {
1757 args += player->proxMixID * 3;
1758 }
1759 // read new position from jump table
1760 track->prevReadPos = track->bgmReadPos;
1761 track->bgmReadPos = AU_FILE_RELATIVE(player->bgmFile, (args[0] << 8) + args[1]);
1762 track->isDrumTrack = args[2];
1763
1764 if (track->proxMixSetChanged) {
1765 track->proxMixSetChanged = false;
1766 track->proxVolume = 0;
1767 for (i = track->firstVoice; i < track->lastVoice; i++) {
1768 AuVoice* voice = &player->globals->voices[i];
1769 if ((voice->priority == player->priority) && (voice->cmdPtr != nullptr)) {
1771 }
1772 }
1773 }
1774 if (track->proxMixValChanged) {
1775 track->proxMixValChanged = false;
1776 au_bgm_set_prox_mix_fade(player, track, player->proxMixVolume, 144);
1777 }
1778 // reset an odd subset of parameters
1779 track->insCoarseDetune = 0;
1780 track->insFineDetune = 0;
1781 track->pressOverride = 0;
1782 track->detune = 0;
1783 track->tremoloDepth = 0;
1784 track->insVolumeTicks = 0;
1785 track->randomPanAmount = 0;
1786 track->busID = player->busID;
1787}
1788
1790 u32 writePos;
1791 u8 delaySide;
1792 u8 delayTime;
1793 u32 i;
1794
1795 u32 type = player->seqCmdArgs.Special.type;
1796 u32 arg1 = player->seqCmdArgs.Special.arg1;
1797 u32 arg2 = player->seqCmdArgs.Special.arg2;
1798
1799 switch (type) {
1801 if ((arg1 < ARRAY_COUNT(player->effectIndices)) && ((s8)player->effectIndices[arg1] >= 0)) {
1802 player->globals->channelDelayBusID = player->effectIndices[arg1];
1803 if (arg2 != 0) {
1804 delayTime = arg2 & 0xF;
1805 delaySide = ((arg2 >> 4) & 1) + 1;
1806 if ((player->globals->channelDelayTime != delayTime) || (player->globals->channelDelaySide != delaySide)) {
1807 player->globals->channelDelayTime = delayTime;
1809 player->globals->channelDelayPending = true;
1810 }
1811 } else {
1814 player->globals->channelDelayPending = true;
1815 }
1816 }
1817 }
1818 break;
1820 if (arg1 - 1 < ARRAY_COUNT(player->customPressEnvelopes)) {
1821 player->writingCustomEnvelope = arg1;
1822 au_bgm_clear_custom_note_press(player, arg1 - 1);
1823 } else {
1824 player->writingCustomEnvelope = 0;
1825 }
1826 break;
1828 i = player->writingCustomEnvelope;
1829 if (i - 1 < ARRAY_COUNT(player->customPressEnvelopes)) {
1830 i--; // convert ID --> array index, needed to match
1831 writePos = player->customEnvelopeWritePos[i];
1832 if (writePos < ARRAY_COUNT(player->customPressEnvelopes[i]) - 1) {
1833 if (arg1 >= ARRAY_COUNT(BgmCustomEnvLookup)) {
1834 player->customPressEnvelopes[i][writePos] = (arg1 << 8) + arg2;
1835 } else {
1836 player->customPressEnvelopes[i][writePos] = (BgmCustomEnvLookup[arg1] << 8) + arg2;
1837 }
1838 player->customEnvelopeWritePos[i] = writePos + 1;
1839 }
1840 }
1841 break;
1843 if (arg1 <= ARRAY_COUNT(player->customPressEnvelopes)) {
1844 track->pressOverride = arg1;
1845 } else {
1846 track->pressOverride = 0;
1847 }
1848 break;
1850 if (player->soundManager != nullptr) {
1851 for (i = 0; i < ARRAY_COUNT(player->soundManager->bgmSounds); i++) {
1852 if ((player->soundManager->bgmSounds[i].index) == 0) {
1853 player->soundManager->bgmSounds[i].index = arg1;
1854 player->soundManager->bgmSounds[i].volume =
1855 ((s32)(
1856 ((u32)player->fadeInfo.baseVolume >> 16) *
1857 ((u32)player->fadeInfo.envelopeVolume >> 16)
1858 ) + AU_MAX_VOLUME_16) >> 0x17;
1859 break;
1860 }
1861 }
1862 }
1863 break;
1865 if (arg1 == 0) {
1866 if (track->proxMixValChanged) {
1867 track->proxMixValChanged = false;
1868 for (i = 0; i < ARRAY_COUNT(player->tracks); i++) {
1869 BGMPlayerTrack* otherTrack = &player->tracks[i];
1870 if (player->proxMixVolume == AU_MAX_VOLUME_8) {
1871 if (otherTrack->proxVol1 != 0) {
1873 au_bgm_set_prox_mix_fade(player, otherTrack, otherTrack->proxVol1, 72);
1874 }
1875 } else {
1876 if (otherTrack->proxVol2 != 0) {
1877 otherTrack->proxMixValChanged = false;
1878 au_bgm_set_prox_mix_fade(player, otherTrack, otherTrack->proxVol2, 72);
1879 }
1880 }
1881 }
1882 }
1883 } else {
1884 track->proxVol1 = arg1;
1885 track->proxVol2 = arg2;
1886 }
1887 break;
1888 }
1889}
1890
1893
1894/*
1895Uses bit masks:
18963F00 = 0011 1111 0000 0000 -> 0011 1111
1897000C = 0000 0000 0000 1100 -> 1100 0000
1898*/
1899static u8 au_bgm_get_random_pan(BGMPlayer* player, u8 pan, u8 amplitude) {
1900 s32 seed = player->randomValue1;
1901 s32 tap7 = seed >> 7;
1902 s32 tap2 = seed >> 2;
1903 s32 parity = (tap7 + tap2) & 1;
1904 s32 lo = (seed >> 8) & 0x3F; // bitmask 0x3F00
1905 s32 hi = (seed << 4) & 0xC0; // bitmask 0x000C
1906 s32 random = lo + hi;
1907 s32 base = pan;
1908 s32 retPan;
1909
1910 if (parity) {
1911 retPan = base + ((amplitude * random) >> 8);
1912 } else {
1913 retPan = base - ((amplitude * random) >> 8);
1914 }
1915 if (retPan < AU_PAN_MIN) {
1917 } else if (retPan > AU_PAN_MAX) {
1919 }
1920 return retPan;
1921}
1922
1923/*
1924Uses bit masks:
19253C0 = 0000 0011 1100 0000 -> 0001 1111
192603C = 0000 0000 0011 1100 -> 1110 0000
1927*/
1928static s16 au_bgm_get_random_pitch(s32 seed, s32 pitch, u8 amplitude) {
1929 s32 tap4 = seed >> 4;
1930 s32 tap1 = seed >> 1;
1931 s32 parity = (tap4 + tap1) & 1;
1932 s32 lo = (seed >> 6) & 0xF; // bitmask 0x3C0
1933 s32 hi = (seed << 2) & 0xF0; // bitmask 0x03C
1934 s32 random = lo + hi;
1935 s32 retVal;
1936
1937 if (parity) {
1938 retVal = pitch + ((amplitude * 5 * random) >> 8);
1939 } else {
1940 retVal = pitch - ((amplitude * 5 * random) >> 8);
1941 }
1942 return retVal;
1943}
1944
1945/*
1946Uses bit masks:
19471F00 = 0001 1111 0000 0000 -> 0001 1111
194800E0 = 0000 0000 1110 0000 -> 1110 0000
1949*/
1950static u8 au_bgm_get_random_vol(s32 seed, u8 volume, u8 amplitude) {
1951 s32 lo = (seed >> 8) & 0x1F; // bitmask 0x1F00
1952 s32 hi = seed & 0xE0;
1953 s32 random = lo + hi;
1954
1955 return volume * (0x8000 - amplitude * random);
1956}
1957
1958/*
1959Uses bit masks:
19600380 = 0000 0011 1000 0000 -> 0000 0111
1961001F = 0000 0000 0001 1111 -> 1111 1000
1962*/
1963static u8 au_bgm_get_random_reverb(s32 seed, u8 reverb, u8 amplitude) {
1964 s32 lo = (seed >> 7) & 7; // bitmask 0x380
1965 s32 hi = (seed << 3) & 0xF8; // bitmask 0x01F
1966 s32 random = lo + hi;
1967
1968 return reverb * (0x8000 - (amplitude * random));
1969}
1970
1972 BGMPlayer* player;
1974 s32 changed = false;
1975 u8 mixID = mix & 0xFF;
1976 s32 i;
1977
1978 if (songName != 0) {
1979 player = au_bgm_get_player_with_song_name(songName);
1980 if ((player != nullptr) && (player->proxMixValue != mix)) {
1981 player->proxMixValue = mix;
1982 if (player->proxMixID != mixID) {
1983 player->proxMixID = mixID;
1984 changed = true;
1985 }
1986 player->proxMixVolume = (mix >> 0x18) & 0x7F;
1987 for (i = 0; i < ARRAY_COUNT(player->tracks); i++) {
1988 track = &player->tracks[i];
1989 if (changed) {
1990 track->proxMixSetChanged = true;
1991 }
1992 track->proxMixValChanged = true;
1993 }
1994 }
1995 }
1996}
1997
1999 if (rate > 2.0) {
2000 rate = 2.0f;
2001 } else if (rate < 0.25) {
2002 rate = 0.25f;
2003 }
2004
2005 player->playbackRate = rate;
2006 player->masterTempo = au_bgm_bpm_to_tempo(player, player->masterTempoBPM);
2008 player->masterTempoTicks = 0;
2009 player->masterTempoTarget = 0;
2010 player->masterTempoStep = 0;
2011}
2012
2014 if (detune > AU_OCTAVE_CENTS) {
2015 detune = AU_OCTAVE_CENTS;
2016 } else if (detune < -2 * AU_OCTAVE_CENTS) {
2017 detune = -2 * AU_OCTAVE_CENTS;
2018 }
2019
2020 player->detune = detune;
2021}
2022
2024 BGMPlayerTrack* track = &player->tracks[trackIdx];
2025
2026 if (track->bgmReadPos != 0) {
2027 player->seqCmdArgs.TrackVolumeFade.time = time;
2028 player->seqCmdArgs.TrackVolumeFade.value = volume;
2030 }
2031}
2032
2034 player->trackVolsConfig = trackVols;
2035 player->bFadeConfigSetsVolume = mode;
2036}
2037
2039 if (target != 0) {
2041 }
2042 if (duration <= 0) {
2043 duration = 1;
2044 } else if (duration > 1000) {
2045 duration = 1000;
2046 }
2047 if (target == track->proxVolume) {
2048 track->proxVolumeTicks = 0;
2049 return;
2050 }
2051 track->proxVolumeTicks = duration;
2052 track->proxVolumeTarget = target;
2053 track->proxVolumeStep = ((target << 0x10) - track->proxVolume) / duration;
2054}
2055
2057 u8 i;
2058
2059 for (i = 0; i < ARRAY_COUNT(player->globals->voices); i++) {
2060 AuVoice* voice = &player->globals->voices[i];
2061 if (voice->priority == player->priority) {
2063 }
2064 }
2065}
2066
2068 BGMPlayer* player;
2071 AuVoice* voice;
2072 s32 trackIdx;
2073 s32 voiceIdx;
2074 s8 oldVolume;
2075
2076 s32 songName = request->songName;
2077 b32 enabled = request->enabled;
2078 AuResult status = AU_RESULT_OK;
2079
2080 if (songName != 0) {
2081 player = au_bgm_get_player_with_song_name(songName);
2082 if (player != nullptr) {
2083 for (trackIdx = 0; trackIdx < ARRAY_COUNT(player->tracks); trackIdx++) {
2084 track = &player->tracks[trackIdx];
2085 if (track->bgmReadPos != nullptr) {
2086 if (track->linkedTrackID != 0) {
2087 linkTrack = &player->tracks[track->linkedTrackID - 1];
2088 if (enabled) {
2089 if (track->muted) {
2090 track->muted = false;
2091 linkTrack->muted = true;
2092 // release all voices for linked track
2093 for (voiceIdx = linkTrack->firstVoice; voiceIdx < linkTrack->lastVoice; voiceIdx++) {
2094 voice = &player->globals->voices[voiceIdx];
2095 if (voice->priority == player->priority) {
2097 voice->envelopeFlags |= AU_VOICE_ENV_FLAG_KEY_RELEASED;
2098 }
2099 }
2100 // fade in main track
2101 oldVolume = track->insVolume >> 24;
2103 player->seqCmdArgs.raw[0] = 0;
2104 player->seqCmdArgs.TrackVolumeFade.time = 96;
2105 player->seqCmdArgs.TrackVolumeFade.value = oldVolume;
2107 }
2108 } else {
2109 if (!track->muted) {
2110 track->muted = true;
2111 linkTrack->muted = false;
2112 // release all voices for main track
2113 for (voiceIdx = track->firstVoice; voiceIdx < track->lastVoice; voiceIdx++) {
2114 voice = &player->globals->voices[voiceIdx];
2115 if (voice->priority == player->priority) {
2117 voice->envelopeFlags |= AU_VOICE_ENV_FLAG_KEY_RELEASED;
2118 }
2119 }
2120 // fade in linked track
2121 oldVolume = linkTrack->insVolume >> 24;
2123 player->seqCmdArgs.raw[0] = 0;
2124 player->seqCmdArgs.TrackVolumeFade.time = 96;
2125 player->seqCmdArgs.TrackVolumeFade.value = oldVolume;
2127 }
2128 }
2129 }
2130 }
2131 }
2132 } else {
2134 }
2135 } else {
2136 status = AU_ERROR_NULL_SONG_NAME;
2137 }
2138
2139 return status;
2140}
BSS s32 PopupMenu_SelectedIndex
s32 randomValue2
Definition audio.h:1154
u8 channelDelayPending
Definition audio.h:1041
BGMInstrumentInfo * instrumentsInfo
Definition audio.h:1166
u16 unk_5A
Definition audio.h:1156
struct BGMHeader * bgmFile
Definition audio.h:1160
#define BGM_TEMPO_TO_UPDATE_UNITS(tempo)
Definition audio.h:100
struct SeqArgs::@74 TrackTremoloDepth
SoundManagerMusicEvent bgmSounds[4]
Definition audio.h:800
struct SeqArgs::@67 InstrumentReverb
s8 volumeChanged
Current write position for each custom envelope.
Definition audio.h:1194
u8 cmdBufPending
Buffer for an unused (legacy) system for controlling the BGMPlayer from the main thread.
Definition audio.h:1213
s16_16 envelopeVolume
Definition audio.h:510
#define BGM_MFRAMES_PER_MINUTE
Definition audio.h:86
SoundManager * soundManager
Definition audio.h:1140
struct SeqArgs::@81 Detour
AuVoice voices[24]
Definition audio.h:1075
struct SeqArgs::@79 Branch
struct SeqArgs::@72 TrackTremolo
u8 * tickRatePtr
Definition audio.h:1164
BGMPlayer * gBGMPlayerB
Definition engine.c:7
u16 unk_58
Definition audio.h:1155
s32 songPlayingCounter
video frames (60 fps)
Definition audio.h:1145
u8 proxMixSetChanged
Definition audio.h:1105
SoundPlayChange changed
Definition audio.h:1097
SegData * compReadPos
Definition audio.h:1161
#define BGM_DEFAULT_TICKS_PER_BEAT
Definition audio.h:77
s16 baseTicks
Definition audio.h:508
u8 * cmdListRelease
Definition audio.h:659
EnvelopeData envelope
Definition audio.h:845
s16 customPressEnvelopes[8][9]
Definition audio.h:1185
u8 initLinkMute
Definition audio.h:1208
s32 masterVolumeTicks
Definition audio.h:1175
#define AU_SEMITONE_CENTS
Definition audio.h:111
s32 songName
Definition audio.h:1146
#define BGM_DEFAULT_TEMPO
Definition audio.h:91
u8 proxMixValChanged
Definition audio.h:1106
AuCallback onCompleteCallback
Definition audio.h:509
s32 baseStep
Definition audio.h:506
s32 frameCounter
current update counter value
Definition audio.h:1144
#define NO_INSTRUMENT
Definition audio.h:14
u8 unused_21E
Definition audio.h:1198
BGMDrumInfo * drumsInfo
Definition audio.h:1165
#define AU_PAN_MIN
Definition audio.h:65
AuGlobals * globals
Definition audio.h:1139
@ AU_DELAY_CHANNEL_NONE
Definition audio.h:241
u8 raw[4]
Definition audio.h:407
u8 proxMixID
Definition audio.h:1182
s32 randomValue1
Definition audio.h:1153
s32 masterVolumeTarget
Definition audio.h:1174
u8 bgmDrumCount
Definition audio.h:1196
s32 nextUpdateCounter
update counter threshold for a single tick
Definition audio.h:1143
u8 busID
Definition audio.h:1210
u16 masterTempoBPM
Definition audio.h:1187
s32 masterTempo
Definition audio.h:1168
s8_24 masterVolume
Definition audio.h:1172
#define AU_FILE_RELATIVE(base, offset)
Definition audio.h:43
u8 unused_222
Definition audio.h:1202
struct BGMPlayer * resumeCopyTo
Definition audio.h:1050
s8_24 insVolume
Definition audio.h:1084
SeqNote notes[24]
Definition audio.h:1218
s32 masterTempoStep
Definition audio.h:1169
struct SeqArgs::@69 InstrumentCoarseTune
BGMDrumInfo drums[12]
Definition audio.h:981
struct SeqArgs::@62 MasterVolumeFade
u8 channelDelayBusID
Definition audio.h:1042
u8 effectIndices[4]
Definition audio.h:1152
@ BGM_SPECIAL_PROX_MIX_OVERRIDE
Definition audio.h:230
@ BGM_SPECIAL_SEEK_CUSTOM_ENV
Definition audio.h:226
@ BGM_SPECIAL_USE_CUSTOM_ENV
Definition audio.h:228
@ BGM_SPECIAL_WRITE_CUSTOM_ENV
Definition audio.h:227
@ BGM_SPECIAL_TRIGGER_SOUND
Definition audio.h:229
@ BGM_SPECIAL_SET_STEREO_DELAY
Definition audio.h:225
s32 masterTempoTarget
Definition audio.h:1170
BGMInstrumentInfo * dataPRG
Definition audio.h:1046
#define AU_MAX_VOLUME_8
Definition audio.h:61
SeqArgs seqCmdArgs
Definition audio.h:1177
#define BGM_DEFAULT_BPM
Definition audio.h:89
BGMFileInfo info
Definition audio.h:884
struct BGMPlayer * resumeCopyFrom
Definition audio.h:1051
@ AU_VOICE_SYNC_FLAG_PAN_FXMIX
Definition audio.h:151
@ AU_VOICE_SYNC_FLAG_PITCH
Definition audio.h:150
@ AU_VOICE_SYNC_FLAG_ALL
Definition audio.h:148
struct SeqArgs::@59 MasterPitchShift
BGMDrumInfo * drums[12]
Definition audio.h:1167
u16 maxTempo
Definition audio.h:1188
u8 paused
Definition audio.h:1200
s32 name
Definition audio.h:882
SegData * phraseStartPos
Definition audio.h:1163
SegData * compStartPos
Definition audio.h:1162
s16 baseTarget
Definition audio.h:507
@ BGM_PLAY_STATE_IDLE
Definition audio.h:207
@ BGM_PLAY_STATE_FETCH
Definition audio.h:209
@ BGM_PLAY_STATE_STOP
Definition audio.h:211
@ BGM_PLAY_STATE_ACTIVE
Definition audio.h:208
@ BGM_PLAY_STATE_INIT
Definition audio.h:210
u8 polyVoiceCount
Definition audio.h:1109
u8 * trackVolsConfig
Dynamically customizable press envelopes.
Definition audio.h:1186
struct SeqArgs::@64 OverridePatch
s32 nextUpdateStep
Definition audio.h:1141
struct SeqArgs::@80 EventTrigger
u8 bgmInstrumentCount
Definition audio.h:1197
BGMPlayerSnapshot snapshots[1]
Definition audio.h:1049
struct SeqArgs::@75 RandomPan
s16 envelopeTarget
Definition audio.h:512
u8 effectValues[4]
No means to modify value is implemented.
Definition audio.h:1204
s16 volume
Definition audio.h:1127
u16 masterPitchShift
Definition audio.h:1189
s32 pushSongName
Definition audio.h:1147
struct SeqArgs::@63 MasterEffect
BGMPlayer * gBGMPlayerA
Definition engine.c:6
u8 customEnvelopeWritePos[8]
Currently active (for writing) custom envelope.
Definition audio.h:1193
s16 envelopeTicks
Definition audio.h:513
s32 tickUpdateInterval
update counter amount to add per audio frame
Definition audio.h:1142
#define BGM_DEFAULT_UPDATE_STEP
Definition audio.h:97
struct SeqArgs::@77 TrackVolumeFade
s32 busVolume
Definition audio.h:1151
#define SND_MIN_DURATION
Definition audio.h:102
s32 cmdBufData[8]
Definition audio.h:1212
s32 resumeFadeEnd
Definition audio.h:1056
#define PRG_MAX_COUNT
Definition audio.h:119
Fade fadeInfo
Definition audio.h:1150
u8 bFadeConfigSetsVolume
Definition audio.h:1207
struct SeqArgs::@82 Special
#define AU_FRAME_USEC
Definition audio.h:27
u8 tremoloDepth
Definition audio.h:1131
@ BGM_SNAPSHOT_0
Definition audio.h:192
@ BGM_COMP_PLAY_PHRASE
Definition audio.h:216
@ BGM_COMP_START_LOOP
Definition audio.h:217
@ BGM_COMP_END
Definition audio.h:215
@ BGM_COMP_END_COND_LOOP_FALSE
Definition audio.h:220
@ BGM_COMP_END_COND_LOOP_TRUE
Definition audio.h:221
@ BGM_COMP_WAIT
Definition audio.h:218
@ BGM_COMP_END_LOOP
Definition audio.h:219
u8 channelDelaySide
Definition audio.h:1044
u8 cmdBufWritePos
Definition audio.h:1215
struct SeqArgs::@78 ReverbType
s16_16 baseVolume
Definition audio.h:505
struct SeqArgs::@73 TrackTremoloRate
struct BGMHeader * dataBGM[2]
Definition audio.h:1047
u8 conditionalLoopFlags
Definition audio.h:1203
#define AU_PAN_MAX
Definition audio.h:67
u8 writingCustomEnvelope
Definition audio.h:1192
s32 masterTempoTicks
Definition audio.h:1171
PEREntry * dataPER
Definition audio.h:1045
u8 cmdBufReadPos
Definition audio.h:1214
#define BGM_UPDATE_SCALE
Definition audio.h:81
BGMInstrumentInfo defaultPRGEntry
Definition audio.h:1030
#define AU_OCTAVE_CENTS
Definition audio.h:114
u8 priority
Used to mute any linked tracks after the first one encountered.
Definition audio.h:1209
#define SND_MAX_DURATION
Definition audio.h:103
struct SeqArgs::@58 MasterVolume
s32 resumeFadeStart
Definition audio.h:1055
s32 resumeSongName
Definition audio.h:1052
s32 masterVolumeStep
Definition audio.h:1173
BGMPlayerTrack tracks[16]
Definition audio.h:1217
struct SeqArgs::@76 UseInstrument
AuFilePos bgmReadPos
Definition audio.h:1079
struct SeqArgs::@68 TrackVolume
@ AU_PRIORITY_FREE
Definition audio.h:133
struct SeqArgs::@57 MasterTempo
SegData * compActiveLoopEndPos[4]
Definition audio.h:1179
struct SeqArgs::@60 UnkCmdE3
SegData * compLoopStartLabels[32]
Definition audio.h:1178
struct SeqArgs::@61 MasterTempoFade
s32 resumeFadeTime
Definition audio.h:1054
AuEffectChange effectChanges[4]
copied from INIT to the audio heap, seems to exist only to find SEF, PER, and PRG
Definition audio.h:1040
#define BGM_MAX_INSTRUMNETS
Definition audio.h:75
@ BGM_POLYPHONY_UNUSED_A
Definition audio.h:198
@ BGM_POLYPHONY_4
Definition audio.h:203
@ BGM_POLYPHONY_UNUSED_C
Definition audio.h:200
@ BGM_POLYPHONY_2
Definition audio.h:201
@ BGM_POLYPHONY_1
Definition audio.h:197
@ BGM_POLYPHONY_0
Definition audio.h:196
@ BGM_POLYPHONY_UNUSED_B
Definition audio.h:199
@ BGM_POLYPHONY_3
Definition audio.h:202
u8 masterState
Definition audio.h:1201
#define AU_MAX_VOLUME_16
Definition audio.h:62
f32 playbackRate
Definition audio.h:1176
u8 * AuFilePos
Definition audio.h:11
#define AU_MAX_BUS_VOLUME
Definition audio.h:40
Instrument * ins
Definition audio.h:1125
b32 resumeRequested
Definition audio.h:1053
u8 compLoopDepth
Definition audio.h:1191
@ AU_VOICE_ENV_FLAG_KEY_RELEASED
Definition audio.h:143
@ AU_VOICE_ENV_FLAG_VOL_CHANGED
Definition audio.h:144
u8 compLoopCounters[4]
Definition audio.h:1180
s32 length
Definition audio.h:1129
#define AU_VOL_8_TO_16(vol)
Definition audio.h:70
struct SeqArgs::@71 TrackDetune
Instrument * instrument
Definition audio.h:1082
struct SeqArgs::@70 InstrumentFineTune
s32 curVariation
Definition audio.h:1159
u8 polyphonyCounts[8]
Definition audio.h:1206
u8 totalVoices
Definition audio.h:1195
u8 priority
Definition audio.h:865
s32 s8_24
Definition audio.h:8
s16 detune
Definition audio.h:1190
u8 channelDelayTime
Definition audio.h:1043
s32 proxMixValue
Definition audio.h:1181
u8 proxMixVolume
Definition audio.h:1183
struct SeqArgs::@66 InstrumentPan
void au_bgm_load_phrase(BGMPlayer *player, u32 cmd)
Definition bgm_player.c:939
s32 au_bgm_player_audio_frame_update(BGMPlayer *player)
Definition bgm_player.c:661
void au_bgm_player_update_stop(BGMPlayer *player)
void au_bgm_update_bus_volumes(BGMPlayer *player)
Definition bgm_player.c:644
void au_bgm_player_read_composition(BGMPlayer *player)
Definition bgm_player.c:859
void au_BGMCmd_F1_TrackTremoloRate(BGMPlayer *player, BGMPlayerTrack *track)
void au_bgm_set_proximity_mix(s32 songName, u32 mix)
void au_BGMCmd_F7_ReverbType(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_FF_Special(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_FD_EventTrigger(BGMPlayer *player, BGMPlayerTrack *track)
u8 BgmTicksRates[8]
Definition sfx_player.c:279
AuResult au_bgm_set_linked_tracks(SongSwapLinkedRequest *request)
BGMPlayer * au_bgm_get_player_with_song_name(s32 songString)
Definition bgm_player.c:124
AuResult au_bgm_is_song_playing(s32 songName)
Definition bgm_player.c:261
void au_BGMCmd_FC_Branch(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_FE_Detour(BGMPlayer *player, BGMPlayerTrack *track)
void au_bgm_set_prox_mix_fade(BGMPlayer *player, BGMPlayerTrack *track, s32 target, s32 duration)
AuResult au_bgm_process_suspend(SongSuspendRequest *request, b32 skipStop)
Definition bgm_player.c:337
void au_BGMCmd_F4_SubTrackRandomPan(BGMPlayer *player, BGMPlayerTrack *track)
void(* SefCmdHandlers[])(SoundManager *, SoundPlayer *)
Definition sfx_player.c:200
void au_BGMCmd_E3(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_EA_InstrumentPan(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_ED_InstrumentCoarseTune(BGMPlayer *player, BGMPlayerTrack *track)
u8 EnvelopeReleaseDefaultFast[]
Definition sfx_player.c:327
void au_BGMCmd_EC_TrackVolume(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_E2_MasterDetune(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_E5_MasterVolumeFade(BGMPlayer *player, BGMPlayerTrack *track)
void au_bgm_change_track_volume(BGMPlayer *player, s32 trackIdx, s16 time, u8 volume)
u8 SeqCmdArgCounts[]
Definition sfx_player.c:272
void au_bgm_player_update_playing(BGMPlayer *player)
play next tick
void au_bgm_set_track_volumes(BGMPlayer *player, u8 *trackVols, s32 mode)
#define POST_BGM_READ()
void au_bgm_end_composition_loop(BGMPlayer *player, u32 cmd)
Definition bgm_player.c:904
void au_bgm_restore_copied_player(AuGlobals *globals)
Definition bgm_player.c:473
u8 BgmCustomEnvLookup[40]
Definition sfx_player.c:335
void au_bgm_set_tick_resolution(BGMPlayer *player, s32 mBeatsPerMinute, u32 ticksPerBeat)
Definition bgm_player.c:827
AuResult au_bgm_process_fade_out(SongFadeOutRequest *request)
Definition bgm_player.c:287
void au_bgm_player_init(BGMPlayer *player, s32 priority, s32 busID, AuGlobals *globals)
Definition bgm_player.c:523
void au_BGMCmd_E0_MasterTempo(BGMPlayer *player, BGMPlayerTrack *track)
BSS void(* CurrentSeqCmdHandler)(BGMPlayer *, BGMPlayerTrack *)
Definition bgm_player.c:4
b32 au_bgm_player_is_active(BGMPlayer *player)
Definition bgm_player.c:279
AuResult au_bgm_process_resume(SongResumeRequest *request)
Definition bgm_player.c:395
void au_bgm_begin_video_frame(BGMPlayer *player)
Definition bgm_player.c:23
void au_bgm_set_effect_indices(BGMPlayer *player, u8 *list)
Definition bgm_player.c:601
AuResult au_bgm_stop_song(s32 songName)
Definition bgm_player.c:227
void au_bgm_update_fade(BGMPlayer *player)
Definition bgm_player.c:622
void au_BGMCmd_E8_TrackOverridePatch(BGMPlayer *player, BGMPlayerTrack *track)
void au_bgm_player_initialize(BGMPlayer *player)
Definition bgm_player.c:702
void au_BGMCmd_F0_TrackTremolo(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_EE_InstrumentFineTune(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_F5_UseInstrument(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_EC_TrackDetune(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_NOP(BGMPlayer *player, BGMPlayerTrack *track)
void au_bgm_stop_all(void)
Definition bgm_player.c:247
void au_BGMCmd_F2_TrackTremoloDepth(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_E6_MasterEffect(BGMPlayer *player, BGMPlayerTrack *track)
void au_bgm_set_playback_rate(BGMPlayer *player, f32 rate)
void(* SeqCmdHandlers[])(BGMPlayer *, BGMPlayerTrack *)
Definition sfx_player.c:237
void au_bgm_clear_custom_note_press(BGMPlayer *player, s32 index)
Definition bgm_player.c:817
AuResult au_bgm_adjust_volume(SongStartRequest *request)
Definition bgm_player.c:505
void au_bgm_reset_all_voices(BGMPlayer *player)
void au_bgm_player_set_detune(BGMPlayer *player, s32 detune)
void au_BGMCmd_EB_InstrumentReverb(BGMPlayer *player, BGMPlayerTrack *track)
AuResult au_bgm_process_init_song(SongStartRequest *request)
Definition bgm_player.c:135
void au_BGMCmd_E9_InstrumentVolume(BGMPlayer *arg0, BGMPlayerTrack *track)
void au_BGMCmd_F6_InstrumentVolumeLerp(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_E1_MasterVolume(BGMPlayer *player, BGMPlayerTrack *track)
AuResult au_bgm_complete_push(s32 songName)
Definition bgm_player.c:324
void au_BGMCmd_F3_TrackTremoloStop(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_E4_MasterTempoFade(BGMPlayer *player, BGMPlayerTrack *track)
s32 b32
void au_reset_voice(AuVoice *voice, u8 voiceIdx)
Definition engine.c:397
AuResult au_reload_song_files(s32 songID, BGMHeader *arg1)
Definition engine.c:618
void au_fade_set_envelope(Fade *fade, s16 value)
Definition engine.c:469
f32 au_compute_pitch_ratio(s32 tuning)
Converts a linear pitch value (in cents) into a frequency ratio suitable for adjusting playback speed...
Definition engine.c:410
Instrument * au_get_instrument(AuGlobals *globals, BankSetIndex bank, s32 patch, EnvelopeData *arg3)
Note that bank is supplied as BankSetIndex and not BankSet, which means it will be used to perform a ...
Definition engine.c:506
BGMPlayer * au_get_snapshot_by_index(s32 index)
Definition engine.c:656
BGMPlayer * au_get_client_by_priority(u8 arg0)
Definition engine.c:732
void au_fade_init(Fade *fade, s32 time, s32 startValue, s32 endValue)
Definition engine.c:421
void au_fade_calc_envelope(Fade *fade, u32 arg1, s32 target)
Definition engine.c:476
void au_fade_set_volume(u8 arg0, u16 arg1, s32 arg2)
Definition engine.c:457
void au_copy_words(void *src, void *dst, s32 size)
Definition engine.c:1271
void au_fade_clear(Fade *fade)
Definition engine.c:436
Vec3s pos
Definition demo_api.c:17
@ BGM_VARIATION_0
Definition enums.h:1805
@ BGM_VARIATION_3
Definition enums.h:1808
AuResult
Definition enums.h:1758
@ AU_ERROR_NULL_SONG_NAME
Definition enums.h:1766
@ AU_ERROR_7
Definition enums.h:1770
@ AU_RESULT_OK
Definition enums.h:1759
@ AU_ERROR_6
Definition enums.h:1769
@ AU_ERROR_SONG_NOT_PLAYING
Definition enums.h:1764
@ AU_ERROR_INVALID_SONG_DURATION
Definition enums.h:1768
void snd_bgm_clear_legacy_commands(BGMPlayer *player)
Part of an unused system for inter-thread communication with a BGM player using commands.
void snd_song_trigger_music_event(s32 playerID, s32 trackIndex, s32 eventInfo)
#define BSS
Definition macros.h:6
#define ARRAY_COUNT(arr)
Definition macros.h:39