Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
2BF90.c
Go to the documentation of this file.
1#include "audio.h"
2
3extern u8 BlankMseqData[];
4
5#define TRACK_ID_DRUM 9
6
13
19
25
38
39void au_amb_manager_init(AmbienceManager* manager, s8 priority, s8 busId, AuGlobals* globals) {
40 AmbiencePlayer* player;
41 s32 i;
42
43 au_memset(manager, sizeof(*manager), 0);
44
45 for (i = 0; i < ARRAY_COUNT(manager->players); i++) {
46 player = &manager->players[i];
47 player->id.playerIndex = i;
48 player->delay = 1;
49 player->fadeVolume = 0x7F000000;
50 }
51
52 manager->globals = globals;
53 manager->nextUpdateStep = 1;
54 manager->nextUpdateCounter = 2;
55 manager->nextUpdateInterval = 2;
56 manager->priority = priority;
57 manager->busId = busId;
58}
59
63 } else {
64 return AU_RESULT_OK;
65 }
66}
67
68void au_amb_load_tracks_fade(s32 arg0, s32 arg1) {
70}
71
72void au_amb_set_disabled(s32 index, s32 disable) {
74 AmbiencePlayer* ambPlayer = &manager->players[index];
75
76 if (!disable) {
77 ambPlayer->playState = AMB_PLAYER_PLAYING;
78 } else {
79 ambPlayer->playState = AMB_PLAYER_STOPPING;
80 }
81}
82
83AuResult au_amb_start(s32 index, s32 time) {
84 AmbiencePlayer* player = &gAuAmbienceManager->players[index];
86 AuResult status = AU_RESULT_OK;
87
88 if (mseq != NULL) {
89 if (player->mseqName == 0) {
91 if (time != 0) {
92 player->fadeSettingsTime = time;
93 player->fadeSettingsInitial = 0;
94 player->fadeSettingsGoal = 127;
96 au_amb_fade_setup(player);
97 }
98 } else {
99 status = AU_AMBIENCE_ERROR_1;
100 }
101 } else {
102 status = AU_AMBIENCE_ERROR_2;
103 }
104 return status;
105}
106
108 u16 time = player->fadeSettingsTime;
109
110 if (player->fadeSettingsInitial == 255) {
111 player->fadeSettingsInitial = player->fadeVolume >> 0x18;
112 }
113
114 if (time >= SND_MIN_DURATION && time <= SND_MAX_DURATION) {
115 player->fadeVolume = player->fadeSettingsInitial << 0x18;
116 player->fadeGoal = player->fadeSettingsGoal;
117 player->fadeTime = (u32)(time * 10) / 115; // TODO figure out why is the ratio like this
118 player->fadeStep = ((player->fadeSettingsGoal - player->fadeSettingsInitial) << 0x18) / ((s16)player->fadeTime & 0xFFFF);
119 }
120
121 player->fadeSettingsTime = 0;
122 player->fadeSettingsInitial = 0;
123 player->fadeSettingsGoal = 0;
124}
125
126void au_amb_pause(s32 index, s32 time) {
127 AmbiencePlayer* player = &gAuAmbienceManager->players[index];
128
129 if (player->mseqReadStart != NULL && player->mseqReadPos != NULL) {
130 if (time != 0) {
131 player->fadeSettingsInitial = 255;
132 player->fadeSettingsTime = time;
133 player->fadeSettingsGoal = 0;
135 return;
136 }
137 player->mode = AMB_MODE_PAUSING;
138 }
139}
140
141void au_amb_resume(s32 index, s32 time) {
142 AmbiencePlayer* player = &gAuAmbienceManager->players[index];
143
144 if (player->mseqReadStart != NULL && player->mseqReadPos != NULL) {
145 player->mode = AMB_MODE_RESUMING;
146 if (time != 0) {
147 player->fadeSettingsTime = time;
148 } else {
150 }
151 player->fadeSettingsInitial = 0;
154 }
155}
156
157void au_amb_stop_quick(s32 index) {
158 AmbiencePlayer* player = &gAuAmbienceManager->players[index];
159
160 if (player->mseqReadStart != NULL && player->mseqReadPos != NULL) {
161 if (player->mode != AMB_MODE_NORMAL) {
162 player->mseqReadPos = NULL;
163 player->mseqName = 0;
164 player->mode = AMB_MODE_NORMAL;
165 return;
166 }
167 player->mseqReadPos = BlankMseqData;
168 player->delay = 1;
169 }
170}
171
172void au_amb_stop_slow(s32 index, s32 time) {
173 AmbiencePlayer* player = &gAuAmbienceManager->players[index];
174
175 if (player->mseqReadStart != NULL && player->mseqReadPos != NULL) {
176 if (time != 0) {
177 player->fadeSettingsTime = time;
178 } else {
180 }
181 player->fadeSettingsInitial = 255;
182 player->fadeSettingsGoal = 0;
184 }
185}
186
187void au_amb_set_volume(s32 index, s32 time, s32 volume) {
188 AmbiencePlayer* player = &gAuAmbienceManager->players[index];
189 if ((player->mseqReadStart != 0) && (player->mseqReadPos != 0)) {
190 if (volume <= 0) {
191 volume = 1;
192 } else if (volume > SND_MAX_VOLUME_8) {
193 volume = SND_MAX_VOLUME_8;
194 }
195 if (time != 0) {
196 player->fadeSettingsTime = time;
197 } else {
199 }
200 player->fadeSettingsInitial = 255;
201 player->fadeSettingsGoal = volume;
203 }
204}
205
207 AmbiencePlayer* player = &gAuAmbienceManager->players[index];
208 AuResult status = AU_RESULT_OK;
209
210 if (player->mseqReadStart != NULL && player->mseqReadPos != NULL) {
211 status = AU_AMBIENCE_ERROR_1;
212 if (player->mode != AMB_MODE_NORMAL) {
213 status = AU_AMBIENCE_ERROR_2;
214 }
215 }
216 return status;
217}
218
219void au_amb_play_sequence(AmbienceManager* manager, MSEQHeader* mseqFile, s32 index) {
220 AmbiencePlayer* player;
221 AmbienceTrack* track;
222 AuFilePos readPos;
223 s32 i;
224
225 player = &manager->players[index];
226 au_memset(player, sizeof(*player), 0);
227
228 player->mseqFile = mseqFile;
229 readPos = AU_FILE_RELATIVE(mseqFile->dataStart, mseqFile);
230 player->id.playerIndex = index;
231 player->mseqReadPos = readPos;
232 player->loopStartPos[1] = readPos;
233 player->loopStartPos[0] = readPos;
234 player->mseqReadStart = readPos;
235
236 player->delay = 1;
237 player->fadeVolume = 0x7F000000;
238 player->fadeGoal = 0x7F;
239
240 player->mseqName = player->mseqFile->name;
241 player->firstVoiceIdx = player->mseqFile->firstVoiceIdx;
242 player->lastVoiceIdx = player->firstVoiceIdx + 16;
243 if (player->lastVoiceIdx > 24) {
244 player->lastVoiceIdx = 24;
245 }
246 for (i = 0; i < ARRAY_COUNT(player->tracks); i++) {
247 track = &player->tracks[i];
248 track->instrument = manager->globals->defaultInstrument;
249 track->volumeLerp.current = 0x7FFFFFFF;
250 track->pan = 64;
251 }
252 player->resetRequired = TRUE;
253}
254
256 u32 i;
257 s32 j;
258
259 for (i = 0; i < ARRAY_COUNT(manager->voiceStates); i++) {
260 AmbienceVoiceState* voiceState = &manager->voiceStates[i];
261
262 if (voiceState->info.released == TRUE && manager->globals->voices[i].priority != manager->priority) {
263 voiceState->info.all = 0;
264 }
265 }
266
267 for (j = 0; j < ARRAY_COUNT(manager->players); j++) {
268 AmbiencePlayer* player = &manager->players[j];
269 s32 mode;
270
271 if (player->mseqReadPos != NULL) {
272 if (manager->loadTracksFadeInfo) {
273 au_amb_load_track_fade_info(manager, player);
274 }
275
276 mode = player->mode;
277 if (mode != AMB_MODE_NORMAL) {
278 if (mode == AMB_MODE_PAUSING) {
279 player->mode = AMB_MODE_STOPPED;
280 au_amb_save_voices(manager, player);
281 au_amb_player_stop(manager, player);
282 } else if (player->mode == AMB_MODE_RESUMING) {
283 player->mode = AMB_MODE_NORMAL;
284 if (player->fadeSettingsTime != 0) {
285 au_amb_fade_setup(player);
286 }
287 au_amb_restore_voices(manager, player);
288 }
289 } else {
290 // case AMB_MODE_NORMAL
291 if (player->fadeSettingsTime != 0) {
292 au_amb_fade_setup(player);
293 }
294 if (player->playState == AMB_PLAYER_STOPPING) {
295 au_amb_player_stop(manager, player);
297 }
298 au_amb_player_update(manager, player);
299 }
300 }
301 }
302
303 manager->loadTracksFadeInfo = FALSE;
304}
305
307 MSEQHeader* mseqFile;
308 MSEQTrackData* trackData;
309 AmbienceTrack* track;
310 s32 offset;
311 s32 count;
312
313 mseqFile = player->mseqFile;
314 count = mseqFile->trackSettingsCount;
315 if (count != 0 && mseqFile->trackSettingsOffset != 0) {
316 trackData = AU_FILE_RELATIVE(mseqFile->trackSettingsOffset, mseqFile);
317 while (count--) {
318 track = &player->tracks[trackData->trackIndex];
319 if (trackData->type == 0) {
320 track->tuneLerp.time = trackData->time;
321 track->tuneLerp.step = (trackData->delta << 0x10) / trackData->time;
322 track->tuneLerp.goal = trackData->goal;
323 } else if (trackData->type == 1) {
324 track->volumeLerp.time = trackData->time;
325 track->volumeLerp.step = (trackData->delta << 0x10) / trackData->time;
326 track->volumeLerp.goal = trackData->goal;
327 }
328 trackData++;
329 }
330 }
331}
332
334 u8 isVolumeChanged[16];
335 u8 isPitchChanged[16];
336 AuGlobals* globals;
337 u8 fadeVolChanged;
338 AmbienceVoiceState* voiceState;
339 AuVoice* voice;
340 BGMDrumInfo* drum;
341 u32 trackIdx;
342 s32 temp;
343 s32 i;
344 u16 bankPatch;
345 u32 count;
346 s32 loopId;
347 u8 op, arg1, arg2;
348 AmbienceTrack* track;
349
350 globals = manager->globals;
351 fadeVolChanged = FALSE;
352 for (i = 0; i < 16U; i++) { // required to use unsigned literal
353 isVolumeChanged[i] = FALSE;
354 isPitchChanged[i] = FALSE;
355 }
356
357 if (player->resetRequired == TRUE) {
358 au_amb_player_stop(manager, player);
359 player->resetRequired = FALSE;
360 }
361
362 if (player->fadeTime != 0) {
363 player->fadeVolume += player->fadeStep;
364 player->fadeTime--;
365 if (player->fadeTime == 0) {
366 player->fadeVolume = player->fadeGoal << 0x18;
367 if (player->fadeSettingsType == AMB_FADE_IN) {
368 // do nothing
369 } else if (player->fadeSettingsType == AMB_FADE_OUT) {
370 player->mseqReadPos = BlankMseqData;
371 player->delay = 1;
372 } else if (player->fadeSettingsType == AMB_FADE_OUT_PAUSING) {
373 player->mode = AMB_MODE_PAUSING;
374 }
375 }
376 fadeVolChanged = TRUE;
377 }
378
379 // update pitch
380 for (trackIdx = 0; trackIdx < ARRAY_COUNT(player->tracks); trackIdx++) {
381 track = &player->tracks[trackIdx];
382 if (track->tuneLerp.time != 0) {
383 track->tuneLerp.time--;
384 if (track->tuneLerp.time != 0) {
385 track->tuneLerp.current += track->tuneLerp.step;
386 } else {
387 track->tuneLerp.current = track->tuneLerp.goal << 0x10;
388 }
389
390 temp = player->id.all + (trackIdx << 0x10);
391 for (i = player->firstVoiceIdx; i < player->lastVoiceIdx; i++) {
392 voiceState = &manager->voiceStates[i - player->firstVoiceIdx];
393 // update all voices belonging to current track
394 if ((voiceState->info.all & 0xFFFF0000) == temp) {
395 voice = &globals->voices[i];
396 if (voice->priority == manager->priority && trackIdx != TRACK_ID_DRUM) {
397 voice->pitchRatio = au_compute_pitch_ratio(voiceState->pitch + (track->tuneLerp.current >> 0x10)) * track->instrument->pitchRatio;
399 isPitchChanged[i - player->firstVoiceIdx] = TRUE;
400 }
401 }
402 }
403 }
404 }
405
406 // update volume
407 for (trackIdx = 0; trackIdx < ARRAY_COUNT(player->tracks); trackIdx++) {
408 track = &player->tracks[trackIdx];
409 if (track->volumeLerp.time != 0) {
410 track->volumeLerp.time--;
411 if (track->volumeLerp.time != 0) {
412 track->volumeLerp.current += track->volumeLerp.step;
413 } else {
414 track->volumeLerp.current = track->volumeLerp.goal << 0x10;
415 }
416
417 temp = player->id.all + (trackIdx << 0x10);
418 for (i = player->firstVoiceIdx; i < player->lastVoiceIdx; i++) {
419 voiceState = &manager->voiceStates[i - player->firstVoiceIdx];
420 // update all voices belonging to current track
421 if ((voiceState->info.all & 0xFFFF0000) == temp) {
422 voice = &globals->voices[i];
423 if (voice->priority == manager->priority) {
424 track = &player->tracks[voiceState->info.trackIndex];
425 voice->clientVolume = ((player->fadeVolume >> 0x18) * (track->volumeLerp.current >> 0x10) * voiceState->volume) >> 0xE;
427 }
428 }
429 }
430 }
431 }
432
433 player->delay--;
434 if (player->delay <= 0) {
435 while (player->delay == 0) {
436 op = au_amb_read_next(player);
437 if ((s8)op >= 0) {
438 if (op == 0) {
439 // stop
440 player->mseqReadPos = NULL;
441 player->mseqName = 0;
442 au_amb_player_stop(manager, player);
443 break;
444 }
445 if (op >= 0x78) {
446 // long delay
447 player->delay = ((op & 7) << 8) + au_amb_read_next(player) + 0x78;
448 } else {
449 //short delay
450 player->delay = op;
451 }
452 continue;
453 }
454
455 // op >= 0x80
456 // op & 0xF0 : command
457 // op & 0xF : track index
458
459 arg1 = au_amb_read_next(player);
460 trackIdx = op & 0xF;
461 track = &player->tracks[trackIdx];
462
463 switch (op & 0xF0) {
465 // arg1: sound index
466 if (player->playState == AMB_PLAYER_PLAYING) {
467 temp = player->id.all + (trackIdx << 0x10) + (arg1 << 8);
468 for (i = player->firstVoiceIdx; i < player->lastVoiceIdx; i++) {
469 if (manager->voiceStates[i - player->firstVoiceIdx].info.all == temp) {
470 manager->voiceStates[i - player->firstVoiceIdx].info.released = 1;
471 voice = &globals->voices[i];
472 if (voice->priority == manager->priority) {
474 }
475 }
476 }
477 }
478 break;
480 // arg1: pitch or drum sound id
481 // arg2: volume
482 arg2 = au_amb_read_next(player);
483 if (player->playState == AMB_PLAYER_PLAYING) {
484 // find free voice
485 for (i = player->firstVoiceIdx; i < player->lastVoiceIdx; i++) {
486 voice = &globals->voices[i];
487 if (voice->priority == AU_PRIORITY_FREE) {
488 break;
489 }
490 }
491 if (i >= player->lastVoiceIdx) {
492 // use another ambience voice
493 for (i = player->firstVoiceIdx; i < player->lastVoiceIdx; i++) {
494 voice = &globals->voices[i];
495 if (voice->priority == manager->priority) {
496 au_reset_voice(voice, i);
497 break;
498 }
499 }
500 }
501 if (i >= player->lastVoiceIdx) {
502 // try stealing voice with lower priority
503 for (i = player->firstVoiceIdx; i < player->lastVoiceIdx; i++) {
504 voice = &globals->voices[i];
505 if (voice->priority < manager->priority) {
506 au_reset_voice(voice, i);
507 break;
508 }
509 }
510 }
511 if (i < player->lastVoiceIdx) {
512 isVolumeChanged[i - player->firstVoiceIdx] = TRUE;
513 isPitchChanged[i - player->firstVoiceIdx] = TRUE;
514 voiceState = &manager->voiceStates[i - player->firstVoiceIdx];
515 // set playerIndex, trackIndex and tune
516 voiceState->info.all = player->id.all + (trackIdx << 0x10) + (arg1 << 8);
517 if (track->flags & 1) {
518 voiceState->isResumable = TRUE;
519 } else {
520 voiceState->isResumable = FALSE;
521 }
522 if (trackIdx != TRACK_ID_DRUM) {
523 if (track->flags & 1) {
524 voiceState->isResumable = TRUE;
525 } else {
526 voiceState->isResumable = FALSE;
527 }
528
529 voiceState->pitch = (arg1 & 0x7F) * 100 - track->instrument->keyBase;
530 voiceState->volume = arg2 & 0x7F;
531 voice->clientVolume = ((player->fadeVolume >> 0x18) * (track->volumeLerp.current >> 0x10) * voiceState->volume) >> 0xE;
532 voice->pitchRatio = au_compute_pitch_ratio(voiceState->pitch + (track->tuneLerp.current >> 0x10)) * track->instrument->pitchRatio;
533 voice->pan = track->pan;
534 voice->reverb = track->reverb;
535 voice->instrument = track->instrument;
536 voice->busId = manager->busId;
539 } else {
540 voiceState->isResumable = FALSE;
541 drum = &manager->globals->dataPER->drums[arg1 & 0x7F];
542 bankPatch = drum->bankPatch;
543 voice->instrument = au_get_instrument(manager->globals, bankPatch >> 8, bankPatch & 0xFF, &voice->envelope);
544 voiceState->pitch = drum->keyBase - voice->instrument->keyBase;
545 voiceState->volume = ((arg2 & 0x7F) * drum->volume) >> 7;
546 voice->clientVolume = ((player->fadeVolume >> 0x18) * (track->volumeLerp.current >> 0x10) * voiceState->volume) >> 0xE;
547 voice->pitchRatio = au_compute_pitch_ratio(voiceState->pitch) * voice->instrument->pitchRatio;
548 voice->pan = drum->pan;
549 voice->reverb = drum->reverb;
550 voice->busId = manager->busId;
551 }
553 voice->priority = manager->priority;
554 voice->clientPriority = voice->priority;
555 }
556 }
557 break;
559 // higher bit: set pan (1) or volume (0)
560 // lower 7 bits: value
561 if (arg1 & 0x80) {
562 track->pan = arg1 & 0x7F;
563 temp = player->id.all + (trackIdx << 0x10);
564 for (i = player->firstVoiceIdx; i < player->lastVoiceIdx; i++) {
565 voiceState = &manager->voiceStates[i - player->firstVoiceIdx];
566 if ((voiceState->info.all & 0xFFFF0000) == temp) {
567 voice = &globals->voices[i];
568 if (voice->priority == manager->priority && trackIdx != TRACK_ID_DRUM) {
569 voice->pan = track->pan;
571 }
572 }
573 }
574 } else {
575 track->volumeLerp.current = arg1 << 0x18;
576 if (track->volumeLerp.current != 0) {
577 track->volumeLerp.current |= 0xFFFFFF;
578 }
579 temp = player->id.all + (trackIdx << 0x10);
580 for (i = player->firstVoiceIdx; i < player->lastVoiceIdx; i++) {
581 voiceState = &manager->voiceStates[i - player->firstVoiceIdx];
582 if ((voiceState->info.all & 0xFFFF0000) == temp) {
583 voice = &globals->voices[i];
584 if (voice->priority == manager->priority) {
585 voice->clientVolume = ((player->fadeVolume >> 0x18) * (track->volumeLerp.current >> 0x10) * voiceState->volume) >> 0xE;
586 if (!isVolumeChanged[i - player->firstVoiceIdx]) {
588 isVolumeChanged[i - player->firstVoiceIdx] = TRUE;
589 }
590 }
591 }
592 }
593 }
594 break;
596 // arg1: sub command
597 // arg2: depends on sub command
598 arg2 = au_amb_read_next(player);
599 switch (arg1) {
601 // arg2: loop id
602 player->loopStartPos[arg2 & 1] = player->mseqReadPos;
603 break;
605 // arg2 lower bit: loop id
606 // (arg2 & 0x7C) >> 2: loop count
607 loopId = arg2 & 1;
608 count = (arg2 & 0x7C) >> 2;
609 if (count != 0) {
610 if (player->loopCount[loopId] != 0) {
611 player->loopCount[loopId]--;
612 // if it's the last iteration then don't jump to the loop start
613 if (player->loopCount[loopId] != 0) {
614 player->mseqReadPos = player->loopStartPos[loopId];
615 }
616 } else {
617 // first iteration, set loop counter
618 player->mseqReadPos = player->loopStartPos[loopId];
619 player->loopCount[loopId] = count;
620 }
621 } else {
622 // infinite loop
623 player->mseqReadPos = player->loopStartPos[loopId];
624 player->loopCount[loopId] = 0;
625 }
626 break;
628 track->reverb = arg2;
629 break;
631 if (arg2 == 1) {
632 track->flags |= 1;
633 }
634 break;
635 }
636 break;
638 // arg1: bank
639 // arg2: patch
640 arg2 = au_amb_read_next(player);
641 if (trackIdx != TRACK_ID_DRUM) {
642 track->instrument = au_get_instrument(manager->globals, arg1, arg2, &track->envelope);
643 }
644 break;
646 // arg1: coarse tune
647 // arg2: fine tune
648 track->tuneLerp.current = (arg1 << 0x18) + (au_amb_read_next(player) << 0x10);
649 temp = player->id.all + (trackIdx << 0x10);
650 for (i = player->firstVoiceIdx; i < player->lastVoiceIdx; i++) {
651 voiceState = &manager->voiceStates[i - player->firstVoiceIdx];
652 if ((voiceState->info.all & 0xFFFF0000) == temp) {
653 voice = &globals->voices[i];
654 if (voice->priority == manager->priority && trackIdx != TRACK_ID_DRUM) {
655 voice->pitchRatio = au_compute_pitch_ratio(voiceState->pitch + (track->tuneLerp.current >> 0x10)) * track->instrument->pitchRatio;
657 isPitchChanged[i - player->firstVoiceIdx] = 1;
658 }
659 }
660 }
661 break;
662 case 0xF0: // required to match
663 break;
664 }
665 }
666 }
667 if (fadeVolChanged) {
668 for (i = player->firstVoiceIdx; i < player->lastVoiceIdx; i++) {
669 voiceState = &manager->voiceStates[i - player->firstVoiceIdx];
670 // update all voices belonging to this player
671 if ((voiceState->info.all & 0xFF000000) == player->id.all) {
672 voice = &globals->voices[i];
673 if (voice->priority == manager->priority && !isVolumeChanged[i - player->firstVoiceIdx]) {
674 track = &player->tracks[voiceState->info.trackIndex];
675 voice->clientVolume = ((player->fadeVolume >> 0x18) * (track->volumeLerp.current >> 0x10) * voiceState->volume) >> 0xE;
677 }
678 }
679 }
680 }
681}
682
684 u8 value = *state->mseqReadPos++;
685 return value;
686}
687
689 AuVoice* voice;
690 AmbienceVoiceState* voiceState;
691 s32 i;
692
693 for (i = player->firstVoiceIdx; i < player->lastVoiceIdx; i++) {
694 voiceState = &manager->voiceStates[i - player->firstVoiceIdx];
695 if (voiceState->info.playerIndex == player->id.playerIndex) {
696 voice = &manager->globals->voices[i];
697 if (voice->priority == manager->priority) {
698 au_reset_voice(voice, i);
699 }
700 voiceState->info.all = 0;
701 }
702 }
703}
704
706 AmbienceSavedVoice* savedVoice = player->savedVoices;
707 u32 numSaved = 0;
708 s32 i;
709
710 for (i = player->firstVoiceIdx; i < player->lastVoiceIdx; i++) {
711 AmbienceVoiceState* voiceState = &arg0->voiceStates[i - player->firstVoiceIdx];
712
713 if (!voiceState->isResumable) {
714 continue;
715 }
716
717 savedVoice->trackIndex = voiceState->info.trackIndex;
718 savedVoice->tune = voiceState->info.tune;
719 savedVoice->volume = voiceState->volume;
720
721 savedVoice++;
722 numSaved++;
723 if (numSaved >= ARRAY_COUNT(player->savedVoices)) {
724 break;
725 }
726 }
727}
728
730 AuGlobals* globals;
731 AuVoice* voice;
732 AmbienceSavedVoice* savedVoice;
733 AmbienceVoiceState* voiceState;
734 AmbienceTrack* track;
735 u32 i, j;
736
737 globals = manager->globals;
738 if (player->playState == AMB_PLAYER_PLAYING) {
739 for (i = 0; i < ARRAY_COUNT(player->savedVoices); i++) {
740 savedVoice = &player->savedVoices[i];
741 if (savedVoice->tune != 0) {
742 track = &player->tracks[savedVoice->trackIndex];
743
744 // find first free voice
745 for (j = player->firstVoiceIdx; j < player->lastVoiceIdx; j++) {
746 voice = &globals->voices[j];
747 if (voice->priority == AU_PRIORITY_FREE) {
748 break;
749 }
750 }
751
752 // try stealing a voice with lower priority
753 if (j >= player->lastVoiceIdx) {
754 for (j = player->firstVoiceIdx; j < player->lastVoiceIdx; j++) {
755 voice = &globals->voices[j];
756 if (voice->priority < manager->priority) {
757 au_reset_voice(voice, j);
758 break;
759 }
760 }
761 }
762
763 if (j < player->lastVoiceIdx) {
764 voiceState = &manager->voiceStates[j - player->firstVoiceIdx];
765 voiceState->info.all = player->id.all + (savedVoice->trackIndex << 0x10) + (savedVoice->tune << 8);
766 voiceState->pitch = (savedVoice->tune & 0x7F) * 100 - track->instrument->keyBase;
767 voiceState->volume = savedVoice->volume & 0x7F;
768 voice->clientVolume = ((player->fadeVolume >> 0x18) * (track->volumeLerp.current >> 0x10) * voiceState->volume) >> 0xE;
769 voice->pitchRatio = au_compute_pitch_ratio(voiceState->pitch + (track->tuneLerp.current >> 0x10)) * track->instrument->pitchRatio;
770 voice->pan = track->pan;
771 voice->reverb = track->reverb;
772 voice->instrument = track->instrument;
773 voice->busId = manager->busId;
777 voice->priority = manager->priority;
778 voice->clientPriority = voice->priority;
779 }
780 }
781 savedVoice->trackIndex = 0;
782 savedVoice->tune = 0;
783 savedVoice->volume = 0;
784 }
785 }
786}
void au_amb_manager_update(AmbienceManager *manager)
Definition 2BF90.c:255
void au_amb_player_stop(AmbienceManager *manager, AmbiencePlayer *player)
Definition 2BF90.c:688
void au_amb_set_disabled(s32 index, s32 disable)
Definition 2BF90.c:72
void au_amb_player_update(AmbienceManager *manager, AmbiencePlayer *player)
Definition 2BF90.c:333
void au_amb_restore_voices(AmbienceManager *manager, AmbiencePlayer *player)
Definition 2BF90.c:729
u8 au_amb_read_next(AmbiencePlayer *state)
Definition 2BF90.c:683
void au_amb_stop_quick(s32 index)
Definition 2BF90.c:157
#define TRACK_ID_DRUM
Definition 2BF90.c:5
AmbientFadeState
Definition 2BF90.c:14
@ AMB_FADE_OUT_PAUSING
Definition 2BF90.c:17
@ AMB_FADE_OUT
Definition 2BF90.c:16
@ AMB_FADE_IN
Definition 2BF90.c:15
AuResult au_amb_check_player_index(u32 index)
Definition 2BF90.c:60
void au_amb_load_track_fade_info(AmbienceManager *manager, AmbiencePlayer *player)
Definition 2BF90.c:306
MSEQCommand
Definition 2BF90.c:26
@ MSEQ_CMD_C0_SET_INSTRUMENT
Definition 2BF90.c:31
@ MSEQ_CMD_SUB_68_SET_REVERB
Definition 2BF90.c:35
@ MSEQ_CMD_SUB_67_END_LOOP
Definition 2BF90.c:34
@ MSEQ_CMD_SUB_69_SET_RESUMABLE
Definition 2BF90.c:36
@ MSEQ_CMD_90_PLAY_SOUND
Definition 2BF90.c:28
@ MSEQ_CMD_B0_MULTI
Definition 2BF90.c:30
@ MSEQ_CMD_SUB_66_START_LOOP
Definition 2BF90.c:33
@ MSEQ_CMD_A0_SET_VOLUME_PAN
Definition 2BF90.c:29
@ MSEQ_CMD_80_STOP_SOUND
Definition 2BF90.c:27
@ MSEQ_CMD_E0_TUNING
Definition 2BF90.c:32
void au_amb_save_voices(AmbienceManager *arg0, AmbiencePlayer *player)
Definition 2BF90.c:705
void au_amb_manager_init(AmbienceManager *manager, s8 priority, s8 busId, AuGlobals *globals)
Definition 2BF90.c:39
AmbientMode
Definition 2BF90.c:7
@ AMB_MODE_STOPPED
Definition 2BF90.c:10
@ AMB_MODE_PAUSING
Definition 2BF90.c:11
@ AMB_MODE_NORMAL
Definition 2BF90.c:8
@ AMB_MODE_RESUMING
Definition 2BF90.c:9
AuResult au_amb_is_stopped(s32 index)
Definition 2BF90.c:206
void au_amb_load_tracks_fade(s32 arg0, s32 arg1)
Definition 2BF90.c:68
void au_amb_fade_setup(AmbiencePlayer *player)
Definition 2BF90.c:107
void au_amb_resume(s32 index, s32 time)
Definition 2BF90.c:141
void au_amb_set_volume(s32 index, s32 time, s32 volume)
Definition 2BF90.c:187
void au_amb_play_sequence(AmbienceManager *manager, MSEQHeader *mseqFile, s32 index)
Definition 2BF90.c:219
void au_amb_stop_slow(s32 index, s32 time)
Definition 2BF90.c:172
void au_amb_pause(s32 index, s32 time)
Definition 2BF90.c:126
u8 BlankMseqData[]
Definition sfx_player.c:279
AuResult au_amb_start(s32 index, s32 time)
Definition 2BF90.c:83
AmbientPlayState
Definition 2BF90.c:20
@ AMB_PLAYER_STOPPED
Definition 2BF90.c:22
@ AMB_PLAYER_PLAYING
Definition 2BF90.c:21
@ AMB_PLAYER_STOPPING
Definition 2BF90.c:23
void au_reset_voice(AuVoice *voice, u8 voiceIdx)
Instrument * au_get_instrument(AuGlobals *globals, u32 bank, u32 patch, EnvelopeData *envData)
f32 au_compute_pitch_ratio(s32 pitch)
void au_memset(void *dst, s32 size, u8 value)
MSEQHeader * mseqFiles[4]
Definition audio.h:1164
u8 * cmdListPress
Definition audio.h:533
u32 firstVoiceIdx
Definition audio.h:1146
AmbVoiceStateInfo info
Definition audio.h:1122
MSEQHeader * mseqFile
Definition audio.h:1129
u8 fadeSettingsType
Definition audio.h:1139
u8 trackSettingsCount
Definition audio.h:1098
AuVoice voices[24]
Definition audio.h:938
AuFilePos mseqReadPos
Definition audio.h:1131
u8 fadeSettingsGoal
Definition audio.h:1143
s32 nextUpdateInterval
Definition audio.h:1162
u8 * cmdListRelease
Definition audio.h:534
EnvelopeData envelope
Definition audio.h:721
Instrument * defaultInstrument
Definition audio.h:891
Instrument * instrument
Definition audio.h:1104
s16 keyBase
Definition audio.h:765
u16 fadeSettingsTime
Definition audio.h:1141
u16 dataStart
Definition audio.h:1100
s32 step
Definition audio.h:578
AmbienceTrack tracks[10]
Definition audio.h:1153
s32 nextUpdateStep
Definition audio.h:1161
s32 current
Definition audio.h:577
u8 loopCount[2]
Definition audio.h:1144
#define AU_FILE_RELATIVE(base, offset)
Definition audio.h:40
SoundLerp tuneLerp
Definition audio.h:1106
AmbVoiceStateInfo id
Definition audio.h:1133
BGMDrumInfo drums[12]
Definition audio.h:831
f32 pitchRatio
Definition audio.h:714
u8 numActivePlayers
Definition audio.h:1165
AuFilePos mseqReadStart
Definition audio.h:1130
SoundLerp volumeLerp
Definition audio.h:1107
u8 loadTracksFadeInfo
Definition audio.h:1166
@ AU_VOICE_SYNC_FLAG_PAN_FXMIX
Definition audio.h:83
@ AU_VOICE_SYNC_FLAG_PITCH
Definition audio.h:82
@ AU_VOICE_SYNC_FLAG_ALL
Definition audio.h:80
s16 bankPatch
Definition audio.h:764
s8 clientPriority
Definition audio.h:740
s16 clientVolume
Definition audio.h:737
s32 name
Definition audio.h:1096
AmbienceVoiceState voiceStates[16]
Definition audio.h:1170
u8 pan
Definition audio.h:717
s16 time
Definition audio.h:579
u16 trackSettingsOffset
Definition audio.h:1099
u8 volume
Definition audio.h:766
u8 syncFlags
Definition audio.h:739
#define SND_MIN_DURATION
Definition audio.h:55
s32 nextUpdateCounter
Definition audio.h:1163
AmbienceSavedVoice savedVoices[4]
Definition audio.h:1154
AuFilePos loopStartPos[2]
Definition audio.h:1132
AmbiencePlayer players[4]
Definition audio.h:1169
Instrument * instrument
Definition audio.h:713
PEREntry * dataPER
Definition audio.h:908
u8 envelopeFlags
Definition audio.h:734
s8 reverb
Definition audio.h:768
#define SND_MAX_DURATION
Definition audio.h:56
u8 reverb
Definition audio.h:718
u8 firstVoiceIdx
Definition audio.h:1097
u8 fadeSettingsInitial
Definition audio.h:1142
u16 keyBase
Definition audio.h:558
@ AU_PRIORITY_FREE
Definition audio.h:65
s16 goal
Definition audio.h:580
EnvelopeData envelope
Definition audio.h:1105
AuGlobals * globals
Definition audio.h:1160
u32 lastVoiceIdx
Definition audio.h:1147
u8 * AuFilePos
Definition audio.h:14
u8 busId
Definition audio.h:719
@ AU_VOICE_ENV_FLAG_KEY_RELEASED
Definition audio.h:75
@ AU_VOICE_ENV_FLAG_VOL_CHANGED
Definition audio.h:76
#define SND_MAX_VOLUME_8
Definition audio.h:49
u8 priority
Definition audio.h:741
AmbienceManager * gAuAmbienceManager
AuResult
Definition enums.h:1755
@ AU_AMBIENCE_ERROR_2
Definition enums.h:1760
@ AU_RESULT_OK
Definition enums.h:1756
@ AU_AMBIENCE_ERROR_3
Definition enums.h:1762
@ AU_AMBIENCE_ERROR_1
Definition enums.h:1758
#define ARRAY_COUNT(arr)
Definition macros.h:40