Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
MorsGames
GitHub Repository: MorsGames/sm64plus
Path: blob/master/src/audio/external.c
7857 views
1
#include <ultra64.h>
2
#include "sm64.h"
3
#include "heap.h"
4
#include "load.h"
5
#include "data.h"
6
#include "seqplayer.h"
7
#include "external.h"
8
#include "playback.h"
9
#include "synthesis.h"
10
#include "game/level_update.h"
11
#include "game/object_list_processor.h"
12
#include "game/camera.h"
13
#include "seq_ids.h"
14
#include "dialog_ids.h"
15
16
#if defined(VERSION_EU) || defined(VERSION_SH)
17
#define EU_FLOAT(x) x##f
18
#else
19
#define EU_FLOAT(x) x
20
#endif
21
22
// N.B. sound banks are different from the audio banks referred to in other
23
// files. We should really fix our naming to be less ambiguous...
24
#define MAX_BACKGROUND_MUSIC_QUEUE_SIZE 6
25
#define MAX_CHANNELS_PER_SOUND_BANK 1
26
27
#define SEQUENCE_NONE 0xFF
28
29
#define SAMPLES_TO_OVERPRODUCE 0x10
30
#define EXTRA_BUFFERED_AI_SAMPLES_TARGET 0x40
31
32
struct Sound {
33
s32 soundBits;
34
f32 *position;
35
}; // size = 0x8
36
37
struct ChannelVolumeScaleFade {
38
f32 velocity;
39
u8 target;
40
f32 current;
41
u16 remainingFrames;
42
}; // size = 0x10
43
44
struct SoundCharacteristics {
45
f32 *x;
46
f32 *y;
47
f32 *z;
48
f32 distance;
49
u32 priority;
50
u32 soundBits; // packed bits, same as first arg to play_sound
51
u8 soundStatus;
52
u8 freshness;
53
u8 prev;
54
u8 next;
55
}; // size = 0x1C
56
57
// Also the number of frames a discrete sound can be in the WAITING state before being deleted
58
#define SOUND_MAX_FRESHNESS 10
59
60
struct SequenceQueueItem {
61
u8 seqId;
62
u8 priority;
63
}; // size = 0x2
64
65
// data
66
#if defined(VERSION_EU) || defined(VERSION_SH)
67
// moved to bss in data.c
68
s32 gAudioErrorFlags2 = 0;
69
#else
70
s32 gAudioErrorFlags = 0;
71
#endif
72
s32 sGameLoopTicked = 0;
73
74
// Dialog sounds
75
// The US difference is the sound for DIALOG_037 ("I win! You lose! Ha ha ha ha!
76
// You're no slouch, but I'm a better sledder! Better luck next time!"), spoken
77
// by Koopa instead of the penguin in JP.
78
79
#define UKIKI 0
80
#define TUXIE 1
81
#define BOWS1 2 // Bowser Intro / Doors Laugh
82
#define KOOPA 3
83
#define KBOMB 4
84
#define BOO 5
85
#define BOMB 6
86
#define BOWS2 7 // Bowser Battle Laugh
87
#define GRUNT 8
88
#define WIGLR 9
89
#define YOSHI 10
90
#define _ 0xFF
91
92
#ifdef VERSION_JP
93
#define DIFF KOOPA
94
#else
95
#define DIFF TUXIE
96
#endif
97
98
u8 sDialogSpeaker[] = {
99
// 0 1 2 3 4 5 6 7 8 9
100
/* 0*/ _, BOMB, BOMB, BOMB, BOMB, KOOPA, KOOPA, KOOPA, _, KOOPA,
101
/* 1*/ _, _, _, _, _, _, _, KBOMB, _, _,
102
/* 2*/ _, BOWS1, BOWS1, BOWS1, BOWS1, BOWS1, BOWS1, BOWS1, BOWS1, BOWS1,
103
/* 3*/ _, _, _, _, _, _, _, DIFF, _, _,
104
/* 4*/ _, KOOPA, _, _, _, _, _, BOMB, _, _,
105
/* 5*/ _, _, _, _, _, TUXIE, TUXIE, TUXIE, TUXIE, TUXIE,
106
/* 6*/ _, _, _, _, _, _, _, BOWS2, _, _,
107
/* 7*/ _, _, _, _, _, _, _, _, _, UKIKI,
108
/* 8*/ UKIKI, _, _, _, _, BOO, _, _, _, _,
109
/* 9*/ BOWS2, _, BOWS2, BOWS2, _, _, _, _, BOO, BOO,
110
/*10*/ UKIKI, UKIKI, _, _, _, BOMB, BOMB, BOO, BOO, _,
111
/*11*/ _, _, _, _, GRUNT, GRUNT, KBOMB, GRUNT, GRUNT, _,
112
/*12*/ _, _, _, _, _, _, _, _, KBOMB, _,
113
/*13*/ _, _, TUXIE, _, _, _, _, _, _, _,
114
/*14*/ _, _, _, _, _, _, _, _, _, _,
115
/*15*/ WIGLR, WIGLR, WIGLR, _, _, _, _, _, _, _,
116
/*16*/ _, YOSHI, _, _, _, _, _, _, WIGLR, _,
117
/*NW*/ _, _, TUXIE, TUXIE, _, _
118
};
119
#undef _
120
STATIC_ASSERT(ARRAY_COUNT(sDialogSpeaker) == DIALOG_COUNT,
121
"change this array if you are adding dialogs");
122
123
s32 sDialogSpeakerVoice[] = {
124
SOUND_OBJ_UKIKI_CHATTER_LONG,
125
SOUND_OBJ_BIG_PENGUIN_YELL,
126
SOUND_OBJ_BOWSER_INTRO_LAUGH,
127
SOUND_OBJ_KOOPA_TALK,
128
SOUND_OBJ_KING_BOBOMB_TALK,
129
SOUND_OBJ_BOO_LAUGH_LONG,
130
SOUND_OBJ_BOBOMB_BUDDY_TALK,
131
SOUND_OBJ_BOWSER_LAUGH,
132
SOUND_OBJ2_BOSS_DIALOG_GRUNT,
133
SOUND_OBJ_WIGGLER_TALK,
134
SOUND_GENERAL_YOSHI_TALK,
135
#if defined(VERSION_JP) || defined(VERSION_US)
136
NO_SOUND,
137
NO_SOUND,
138
NO_SOUND,
139
NO_SOUND,
140
#endif
141
};
142
143
u8 sNumProcessedSoundRequests = 0;
144
u8 sSoundRequestCount = 0;
145
146
// Music dynamic tables. A dynamic describes which volumes to apply to which
147
// channels of a sequence (I think?), and different parts of a level can have
148
// different dynamics. Each table below specifies first the sequence to apply
149
// the dynamics to, then a bunch of conditions for when each dynamic applies
150
// (e.g. "only if Mario's X position is between 100 and 300"), and finally a
151
// fallback dynamic. Due to the encoding of the tables, the conditions must
152
// come in the same order as the macros.
153
// TODO: dynamic isn't a great term for this, it means other things in music...
154
155
#define MARIO_X_GE 0
156
#define MARIO_Y_GE 1
157
#define MARIO_Z_GE 2
158
#define MARIO_X_LT 3
159
#define MARIO_Y_LT 4
160
#define MARIO_Z_LT 5
161
#define MARIO_IS_IN_AREA 6
162
#define MARIO_IS_IN_ROOM 7
163
164
#define DYN1(cond1, val1, res) (s16)(1 << (15 - cond1) | res), val1
165
#define DYN2(cond1, val1, cond2, val2, res) \
166
(s16)(1 << (15 - cond1) | 1 << (15 - cond2) | res), val1, val2
167
#define DYN3(cond1, val1, cond2, val2, cond3, val3, res) \
168
(s16)(1 << (15 - cond1) | 1 << (15 - cond2) | 1 << (15 - cond3) | res), val1, val2, val3
169
170
s16 sDynBbh[] = {
171
SEQ_LEVEL_SPOOKY, DYN1(MARIO_IS_IN_ROOM, BBH_OUTSIDE_ROOM, 6),
172
DYN1(MARIO_IS_IN_ROOM, BBH_NEAR_MERRY_GO_ROUND_ROOM, 6), 5,
173
};
174
s16 sDynDdd[] = {
175
SEQ_LEVEL_WATER,
176
DYN2(MARIO_X_LT, -800, MARIO_IS_IN_AREA, AREA_DDD_WHIRLPOOL & 0xf, 0),
177
DYN3(MARIO_Y_GE, -2000, MARIO_X_LT, 470, MARIO_IS_IN_AREA, AREA_DDD_WHIRLPOOL & 0xf, 0),
178
DYN2(MARIO_Y_GE, 100, MARIO_IS_IN_AREA, AREA_DDD_SUB & 0xf, 2),
179
1,
180
};
181
s16 sDynJrb[] = {
182
SEQ_LEVEL_WATER,
183
DYN2(MARIO_Y_GE, 945, MARIO_X_LT, -5260, 0),
184
DYN1(MARIO_IS_IN_AREA, AREA_JRB_SHIP & 0xf, 0),
185
DYN1(MARIO_Y_GE, 1000, 0),
186
DYN2(MARIO_Y_GE, -3100, MARIO_Z_LT, -900, 2),
187
1,
188
5, // bogus entry, ignored (was JRB originally intended to have spooky music?)
189
};
190
s16 sDynWdw[] = {
191
SEQ_LEVEL_UNDERGROUND, DYN2(MARIO_Y_LT, -670, MARIO_IS_IN_AREA, AREA_WDW_MAIN & 0xf, 4),
192
DYN1(MARIO_IS_IN_AREA, AREA_WDW_TOWN & 0xf, 4), 3,
193
};
194
s16 sDynHmc[] = {
195
SEQ_LEVEL_UNDERGROUND, DYN2(MARIO_X_GE, 0, MARIO_Y_LT, -203, 4),
196
DYN2(MARIO_X_LT, 0, MARIO_Y_LT, -2400, 4), 3,
197
};
198
s16 sDynUnk38[] = {
199
SEQ_LEVEL_UNDERGROUND,
200
DYN1(MARIO_IS_IN_AREA, 1, 3),
201
DYN1(MARIO_IS_IN_AREA, 2, 4),
202
DYN1(MARIO_IS_IN_AREA, 3, 7),
203
0,
204
};
205
s16 sDynNone[] = { SEQ_SOUND_PLAYER, 0 };
206
207
u8 sCurrentMusicDynamic = 0xff;
208
u8 sBackgroundMusicForDynamics = SEQUENCE_NONE;
209
210
#define STUB_LEVEL(_0, _1, _2, _3, _4, _5, _6, leveldyn, _8) leveldyn,
211
#define DEFINE_LEVEL(_0, _1, _2, _3, _4, _5, _6, _7, _8, leveldyn, _10) leveldyn,
212
213
#define _ sDynNone
214
s16 *sLevelDynamics[LEVEL_COUNT] = {
215
_, // LEVEL_NONE
216
#include "levels/level_defines.h"
217
};
218
#undef _
219
#undef STUB_LEVEL
220
#undef DEFINE_LEVEL
221
222
struct MusicDynamic {
223
/*0x0*/ s16 bits1;
224
/*0x2*/ u16 volScale1;
225
/*0x4*/ s16 dur1;
226
/*0x6*/ s16 bits2;
227
/*0x8*/ u16 volScale2;
228
/*0xA*/ s16 dur2;
229
}; // size = 0xC
230
231
struct MusicDynamic sMusicDynamics[8] = {
232
{ 0x0000, 127, 100, 0x0e43, 0, 100 }, // SEQ_LEVEL_WATER
233
{ 0x0003, 127, 100, 0x0e40, 0, 100 }, // SEQ_LEVEL_WATER
234
{ 0x0e43, 127, 200, 0x0000, 0, 200 }, // SEQ_LEVEL_WATER
235
{ 0x02ff, 127, 100, 0x0100, 0, 100 }, // SEQ_LEVEL_UNDERGROUND
236
{ 0x03f7, 127, 100, 0x0008, 0, 100 }, // SEQ_LEVEL_UNDERGROUND
237
{ 0x0070, 127, 10, 0x0000, 0, 100 }, // SEQ_LEVEL_SPOOKY
238
{ 0x0000, 127, 100, 0x0070, 0, 10 }, // SEQ_LEVEL_SPOOKY
239
{ 0xffff, 127, 100, 0x0000, 0, 100 }, // any (unused)
240
};
241
242
#define STUB_LEVEL(_0, _1, _2, _3, echo1, echo2, echo3, _7, _8) { echo1, echo2, echo3 },
243
#define DEFINE_LEVEL(_0, _1, _2, _3, _4, _5, echo1, echo2, echo3, _9, _10) { echo1, echo2, echo3 },
244
245
u8 sLevelAreaReverbs[LEVEL_COUNT][3] = {
246
{ 0x00, 0x00, 0x00 }, // LEVEL_NONE
247
#include "levels/level_defines.h"
248
};
249
#undef STUB_LEVEL
250
#undef DEFINE_LEVEL
251
252
#define STUB_LEVEL(_0, _1, _2, volume, _4, _5, _6, _7, _8) volume,
253
#define DEFINE_LEVEL(_0, _1, _2, _3, _4, volume, _6, _7, _8, _9, _10) volume,
254
255
u16 sLevelAcousticReaches[LEVEL_COUNT] = {
256
20000, // LEVEL_NONE
257
#include "levels/level_defines.h"
258
};
259
260
#undef STUB_LEVEL
261
#undef DEFINE_LEVEL
262
263
#define AUDIO_MAX_DISTANCE US_FLOAT(22000.0)
264
265
#ifdef VERSION_JP
266
#define LOW_VOLUME_REVERB 48.0
267
#else
268
#define LOW_VOLUME_REVERB 40.0f
269
#endif
270
271
#ifdef VERSION_JP
272
#define VOLUME_RANGE_UNK1 0.8f
273
#define VOLUME_RANGE_UNK2 1.0f
274
#else
275
#define VOLUME_RANGE_UNK1 0.9f
276
#define VOLUME_RANGE_UNK2 0.8f
277
#endif
278
279
// Default volume for background music sequences (playing on player 0).
280
u8 sBackgroundMusicDefaultVolume[] = {
281
127, // SEQ_SOUND_PLAYER
282
80, // SEQ_EVENT_CUTSCENE_COLLECT_STAR
283
80, // SEQ_MENU_TITLE_SCREEN
284
75, // SEQ_LEVEL_GRASS
285
70, // SEQ_LEVEL_INSIDE_CASTLE
286
75, // SEQ_LEVEL_WATER
287
75, // SEQ_LEVEL_HOT
288
75, // SEQ_LEVEL_BOSS_KOOPA
289
70, // SEQ_LEVEL_SNOW
290
65, // SEQ_LEVEL_SLIDE
291
80, // SEQ_LEVEL_SPOOKY
292
65, // SEQ_EVENT_PIRANHA_PLANT
293
85, // SEQ_LEVEL_UNDERGROUND
294
75, // SEQ_MENU_STAR_SELECT
295
65, // SEQ_EVENT_POWERUP
296
70, // SEQ_EVENT_METAL_CAP
297
65, // SEQ_EVENT_KOOPA_MESSAGE
298
70, // SEQ_LEVEL_KOOPA_ROAD
299
70, // SEQ_EVENT_HIGH_SCORE
300
65, // SEQ_EVENT_MERRY_GO_ROUND
301
80, // SEQ_EVENT_RACE
302
70, // SEQ_EVENT_CUTSCENE_STAR_SPAWN
303
85, // SEQ_EVENT_BOSS
304
75, // SEQ_EVENT_CUTSCENE_COLLECT_KEY
305
75, // SEQ_EVENT_ENDLESS_STAIRS
306
85, // SEQ_LEVEL_BOSS_KOOPA_FINAL
307
70, // SEQ_EVENT_CUTSCENE_CREDITS
308
80, // SEQ_EVENT_SOLVE_PUZZLE
309
80, // SEQ_EVENT_TOAD_MESSAGE
310
70, // SEQ_EVENT_PEACH_MESSAGE
311
75, // SEQ_EVENT_CUTSCENE_INTRO
312
80, // SEQ_EVENT_CUTSCENE_VICTORY
313
70, // SEQ_EVENT_CUTSCENE_ENDING
314
65, // SEQ_MENU_FILE_SELECT
315
0, // SEQ_EVENT_CUTSCENE_LAKITU (not in JP)
316
};
317
318
STATIC_ASSERT(ARRAY_COUNT(sBackgroundMusicDefaultVolume) == SEQ_COUNT,
319
"change this array if you are adding sequences");
320
321
u8 sCurrentBackgroundMusicSeqId = SEQUENCE_NONE;
322
u8 sMusicDynamicDelay = 0;
323
u8 sSoundBankUsedListBack[SOUND_BANK_COUNT] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
324
u8 sSoundBankFreeListFront[SOUND_BANK_COUNT] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
325
u8 sNumSoundsInBank[SOUND_BANK_COUNT] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // only used for debugging
326
u8 sMaxChannelsForSoundBank[SOUND_BANK_COUNT] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
327
328
// Banks 2 and 7 both grew from 0x30 sounds to 0x40 in size in US.
329
#ifdef VERSION_JP
330
#define BANK27_SIZE 0x30
331
#else
332
#define BANK27_SIZE 0x40
333
#endif
334
u8 sNumSoundsPerBank[SOUND_BANK_COUNT] = {
335
0x70, 0x30, BANK27_SIZE, 0x80, 0x20, 0x80, 0x20, BANK27_SIZE, 0x80, 0x80,
336
};
337
#undef BANK27_SIZE
338
339
// sBackgroundMusicMaxTargetVolume and sBackgroundMusicTargetVolume use the 0x80
340
// bit to indicate that they are set, and the rest of the bits for the actual value
341
#define TARGET_VOLUME_IS_PRESENT_FLAG 0x80
342
#define TARGET_VOLUME_VALUE_MASK 0x7f
343
#define TARGET_VOLUME_UNSET 0x00
344
345
f32 gGlobalSoundSource[3] = { 0.0f, 0.0f, 0.0f };
346
f32 sUnusedSoundArgs[3] = { 1.0f, 1.0f, 1.0f };
347
u8 sSoundBankDisabled[16] = { 0 };
348
u8 D_80332108 = 0;
349
u8 sHasStartedFadeOut = FALSE;
350
u16 sSoundBanksThatLowerBackgroundMusic = 0;
351
u8 sUnused80332114 = 0; // never read, set to 0
352
u16 sUnused80332118 = 0; // never read, set to 0
353
u8 sBackgroundMusicMaxTargetVolume = TARGET_VOLUME_UNSET;
354
u8 D_80332120 = 0;
355
u8 D_80332124 = 0;
356
357
#if defined(VERSION_EU) || defined(VERSION_SH)
358
u8 D_EU_80300558 = 0;
359
#endif
360
361
u8 sBackgroundMusicQueueSize = 0;
362
363
#ifndef VERSION_JP
364
u8 sUnused8033323C = 0; // never read, set to 0
365
#endif
366
367
368
// bss
369
#if defined(VERSION_JP) || defined(VERSION_US)
370
s16 *gCurrAiBuffer;
371
#endif
372
#ifdef VERSION_SH
373
s8 D_SH_80343CD0_pad[0x20];
374
s32 D_SH_80343CF0;
375
s8 D_SH_80343CF8_pad[0x8];
376
struct UnkStruct80343D00 D_SH_80343D00;
377
s8 D_SH_8034DC8_pad[0x8];
378
OSPiHandle DriveRomHandle; // used in osDriveRomInit.c. Why here?
379
s8 D_SH_80343E48_pad[0x8];
380
#endif
381
382
struct Sound sSoundRequests[0x100];
383
// Curiously, this has size 3, despite SEQUENCE_PLAYERS == 4 on EU
384
struct ChannelVolumeScaleFade D_80360928[3][CHANNELS_MAX];
385
u8 sUsedChannelsForSoundBank[SOUND_BANK_COUNT];
386
u8 sCurrentSound[SOUND_BANK_COUNT][MAX_CHANNELS_PER_SOUND_BANK]; // index into sSoundBanks
387
388
/**
389
* For each sound bank, a pool containing the currently active sounds for that bank.
390
* The free and used slots in these pools are linked lists. The element sSoundBanks[bank][0]
391
* is used as a list header for the used list, and never holds an actual sound. See also
392
* sSoundBankUsedListBack and sSoundBankFreeListFront.
393
*/
394
struct SoundCharacteristics sSoundBanks[SOUND_BANK_COUNT][40];
395
396
u8 sSoundMovingSpeed[SOUND_BANK_COUNT];
397
u8 sBackgroundMusicTargetVolume;
398
static u8 sLowerBackgroundMusicVolume;
399
struct SequenceQueueItem sBackgroundMusicQueue[MAX_BACKGROUND_MUSIC_QUEUE_SIZE];
400
401
#if defined(VERSION_EU) || defined(VERSION_SH)
402
s32 unk_sh_8034754C;
403
#endif
404
405
#ifdef VERSION_EU
406
OSMesgQueue OSMesgQueue0;
407
OSMesgQueue OSMesgQueue1;
408
OSMesgQueue OSMesgQueue2;
409
OSMesgQueue OSMesgQueue3;
410
extern OSMesgQueue *OSMesgQueues[];
411
412
struct EuAudioCmd sAudioCmd[0x100];
413
414
OSMesg OSMesg0;
415
s32 pad1; // why is there 1 s32 here
416
OSMesg OSMesg1;
417
s32 pad2[2]; // it's not just that the struct is bigger than we think, because there are 2 here
418
OSMesg OSMesg2; // and none here. wth nintendo
419
OSMesg OSMesg3;
420
#else // VERSION_SH
421
extern OSMesgQueue *D_SH_80350F88;
422
extern OSMesgQueue *D_SH_80350FA8;
423
#endif
424
425
#ifdef VERSION_JP
426
typedef u16 FadeT;
427
#else
428
typedef s32 FadeT;
429
#endif
430
431
// some sort of main thread -> sound thread dispatchers
432
extern void func_802ad728(u32 bits, f32 arg);
433
extern void func_802ad74c(u32 bits, u32 arg);
434
extern void func_802ad770(u32 bits, s8 arg);
435
436
static void update_background_music_after_sound(u8 bank, u8 soundIndex);
437
static void update_game_sound(void);
438
static void fade_channel_volume_scale(u8 player, u8 channelId, u8 targetScale, u16 fadeTimer);
439
void process_level_music_dynamics(void);
440
static u8 begin_background_music_fade(u16 fadeDuration);
441
void func_80320ED8(void);
442
443
#ifndef VERSION_JP
444
void unused_8031E4F0(void) {
445
// This is a debug function which is almost entirely optimized away,
446
// except for loops, string literals, and a read of a volatile variable.
447
// The string literals have allowed it to be partially reconstructed.
448
s32 i;
449
450
stubbed_printf("AUTOSEQ ");
451
stubbed_printf("%2x %2x <%5x : %5x / %5x>\n", gSeqLoadedPool.temporary.entries[0].id,
452
gSeqLoadedPool.temporary.entries[1].id, gSeqLoadedPool.temporary.entries[0].size,
453
gSeqLoadedPool.temporary.entries[1].size, gSeqLoadedPool.temporary.pool.size);
454
455
stubbed_printf("AUTOBNK ");
456
stubbed_printf("%2x %3x <%5x : %5x / %5x>\n", gBankLoadedPool.temporary.entries[0].id,
457
gBankLoadedPool.temporary.entries[1].id, gBankLoadedPool.temporary.entries[0].size,
458
gBankLoadedPool.temporary.entries[1].size, gBankLoadedPool.temporary.pool.size);
459
460
stubbed_printf("STAYSEQ ");
461
stubbed_printf("[%2x] <%5x / %5x>\n", gSeqLoadedPool.persistent.numEntries,
462
gSeqLoadedPool.persistent.pool.cur - gSeqLoadedPool.persistent.pool.start,
463
gSeqLoadedPool.persistent.pool.size);
464
for (i = 0; (u32) i < gSeqLoadedPool.persistent.numEntries; i++) {
465
stubbed_printf("%2x ", gSeqLoadedPool.persistent.entries[i].id);
466
}
467
stubbed_printf("\n");
468
469
stubbed_printf("STAYBNK ");
470
stubbed_printf("[%2x] <%5x / %5x>\n", gBankLoadedPool.persistent.numEntries,
471
gBankLoadedPool.persistent.pool.cur - gBankLoadedPool.persistent.pool.start,
472
gBankLoadedPool.persistent.pool.size);
473
for (i = 0; (u32) i < gBankLoadedPool.persistent.numEntries; i++) {
474
stubbed_printf("%2x ", gBankLoadedPool.persistent.entries[i].id);
475
}
476
stubbed_printf("\n\n");
477
478
stubbed_printf(" 0123456789ABCDEF0123456789ABCDEF01234567\n");
479
stubbed_printf("--------------------------------------------\n");
480
481
// gSeqLoadStatus/gBankLoadStatus, 4 entries at a time?
482
stubbed_printf("SEQ ");
483
for (i = 0; i < 40; i++) {
484
stubbed_printf("%1x", 0);
485
}
486
stubbed_printf("\n");
487
488
stubbed_printf("BNK ");
489
for (i = 0; i < 40; i += 4) {
490
stubbed_printf("%1x", 0);
491
}
492
stubbed_printf("\n");
493
494
stubbed_printf("FIXHEAP ");
495
stubbed_printf("%4x / %4x\n", 0, 0);
496
stubbed_printf("DRVHEAP ");
497
stubbed_printf("%5x / %5x\n", 0, 0);
498
stubbed_printf("DMACACHE %4d Blocks\n", 0);
499
stubbed_printf("CHANNELS %2d / MAX %3d \n", 0, 0);
500
501
stubbed_printf("TEMPOMAX %d\n", gTempoInternalToExternal / TEMPO_SCALE);
502
stubbed_printf("TEMPO G0 %d\n", gSequencePlayers[SEQ_PLAYER_LEVEL].tempo / TEMPO_SCALE);
503
stubbed_printf("TEMPO G1 %d\n", gSequencePlayers[SEQ_PLAYER_ENV].tempo / TEMPO_SCALE);
504
stubbed_printf("TEMPO G2 %d\n", gSequencePlayers[SEQ_PLAYER_SFX].tempo / TEMPO_SCALE);
505
stubbed_printf("DEBUGFLAG %8x\n", gAudioErrorFlags);
506
}
507
508
void unused_8031E568(void) {
509
stubbed_printf("COUNT %8d\n", gAudioFrameCount);
510
}
511
#endif
512
513
#if defined(VERSION_EU) || defined(VERSION_SH)
514
const char unusedErrorStr1[] = "Error : Queue is not empty ( %x ) \n";
515
const char unusedErrorStr2[] = "specchg error\n";
516
#endif
517
518
/**
519
* Fade out a sequence player
520
* Called from threads: thread5_game_loop
521
*/
522
#if defined(VERSION_EU) || defined(VERSION_SH)
523
void audio_reset_session_eu(s32 presetId) {
524
OSMesg mesg;
525
#ifdef VERSION_SH
526
osRecvMesg(D_SH_80350FA8, &mesg, OS_MESG_NOBLOCK);
527
osSendMesg(D_SH_80350F88, (OSMesg) presetId, OS_MESG_NOBLOCK);
528
osRecvMesg(D_SH_80350FA8, &mesg, OS_MESG_BLOCK);
529
if ((s32) mesg != presetId) {
530
osRecvMesg(D_SH_80350FA8, &mesg, OS_MESG_BLOCK);
531
}
532
533
#else
534
osRecvMesg(OSMesgQueues[3], &mesg, OS_MESG_NOBLOCK);
535
osSendMesg(OSMesgQueues[2], (OSMesg) presetId, OS_MESG_NOBLOCK);
536
osRecvMesg(OSMesgQueues[3], &mesg, OS_MESG_BLOCK);
537
if ((s32) mesg != presetId) {
538
osRecvMesg(OSMesgQueues[3], &mesg, OS_MESG_BLOCK);
539
}
540
#endif
541
}
542
#endif
543
544
#if defined(VERSION_JP) || defined(VERSION_US)
545
/**
546
* Called from threads: thread3_main, thread5_game_loop
547
*/
548
static void seq_player_fade_to_zero_volume(s32 player, FadeT fadeDuration) {
549
struct SequencePlayer *seqPlayer = &gSequencePlayers[player];
550
551
#ifndef VERSION_JP
552
// fadeDuration is never 0 in practice
553
if (fadeDuration == 0) {
554
fadeDuration++;
555
}
556
#endif
557
558
seqPlayer->fadeVelocity = -(seqPlayer->fadeVolume / fadeDuration);
559
seqPlayer->state = SEQUENCE_PLAYER_STATE_FADE_OUT;
560
seqPlayer->fadeRemainingFrames = fadeDuration;
561
}
562
563
/**
564
* Called from threads: thread4_sound, thread5_game_loop
565
*/
566
static void func_8031D690(s32 player, FadeT fadeInTime) {
567
struct SequencePlayer *seqPlayer = &gSequencePlayers[player];
568
569
if (fadeInTime == 0 || seqPlayer->state == SEQUENCE_PLAYER_STATE_FADE_OUT) {
570
return;
571
}
572
573
seqPlayer->state = SEQUENCE_PLAYER_STATE_2;
574
seqPlayer->fadeRemainingFrames = fadeInTime;
575
seqPlayer->fadeVolume = 0.0f;
576
seqPlayer->fadeVelocity = 0.0f;
577
}
578
#endif
579
580
/**
581
* Called from threads: thread5_game_loop
582
*/
583
static void seq_player_fade_to_percentage_of_volume(s32 player, FadeT fadeDuration, u8 percentage) {
584
struct SequencePlayer *seqPlayer = &gSequencePlayers[player];
585
f32 targetVolume;
586
587
#if defined(VERSION_EU) || defined(VERSION_SH)
588
if (seqPlayer->state == 2) {
589
return;
590
}
591
#else
592
if (seqPlayer->state == SEQUENCE_PLAYER_STATE_FADE_OUT) {
593
return;
594
}
595
#endif
596
597
targetVolume = (FLOAT_CAST(percentage) / EU_FLOAT(100.0)) * seqPlayer->fadeVolume;
598
seqPlayer->volume = seqPlayer->fadeVolume;
599
600
seqPlayer->fadeRemainingFrames = 0;
601
if (fadeDuration == 0) {
602
seqPlayer->fadeVolume = targetVolume;
603
return;
604
}
605
seqPlayer->fadeVelocity = (targetVolume - seqPlayer->fadeVolume) / fadeDuration;
606
#if defined(VERSION_EU) || defined(VERSION_SH)
607
seqPlayer->state = 0;
608
#else
609
seqPlayer->state = SEQUENCE_PLAYER_STATE_4;
610
#endif
611
612
seqPlayer->fadeRemainingFrames = fadeDuration;
613
}
614
615
/**
616
* Called from threads: thread3_main, thread4_sound, thread5_game_loop
617
*/
618
static void seq_player_fade_to_normal_volume(s32 player, FadeT fadeDuration) {
619
struct SequencePlayer *seqPlayer = &gSequencePlayers[player];
620
621
#if defined(VERSION_EU) || defined(VERSION_SH)
622
if (seqPlayer->state == 2) {
623
return;
624
}
625
#else
626
if (seqPlayer->state == SEQUENCE_PLAYER_STATE_FADE_OUT) {
627
return;
628
}
629
#endif
630
631
seqPlayer->fadeRemainingFrames = 0;
632
if (fadeDuration == 0) {
633
seqPlayer->fadeVolume = seqPlayer->volume;
634
return;
635
}
636
seqPlayer->fadeVelocity = (seqPlayer->volume - seqPlayer->fadeVolume) / fadeDuration;
637
#if defined(VERSION_EU) || defined(VERSION_SH)
638
seqPlayer->state = 0;
639
#else
640
seqPlayer->state = SEQUENCE_PLAYER_STATE_2;
641
#endif
642
643
seqPlayer->fadeRemainingFrames = fadeDuration;
644
}
645
646
/**
647
* Called from threads: thread3_main, thread4_sound, thread5_game_loop
648
*/
649
static void seq_player_fade_to_target_volume(s32 player, FadeT fadeDuration, u8 targetVolume) {
650
struct SequencePlayer *seqPlayer = &gSequencePlayers[player];
651
652
#if defined(VERSION_JP) || defined(VERSION_US)
653
if (seqPlayer->state == SEQUENCE_PLAYER_STATE_FADE_OUT) {
654
return;
655
}
656
#endif
657
658
seqPlayer->fadeRemainingFrames = 0;
659
if (fadeDuration == 0) {
660
seqPlayer->fadeVolume = (FLOAT_CAST(targetVolume) / EU_FLOAT(127.0));
661
return;
662
}
663
664
seqPlayer->fadeVelocity =
665
(((f32)(FLOAT_CAST(targetVolume) / EU_FLOAT(127.0)) - seqPlayer->fadeVolume)
666
/ (f32) fadeDuration);
667
#if defined(VERSION_EU) || defined(VERSION_SH)
668
seqPlayer->state = 0;
669
#else
670
seqPlayer->state = SEQUENCE_PLAYER_STATE_4;
671
#endif
672
673
seqPlayer->fadeRemainingFrames = fadeDuration;
674
}
675
676
#if defined(VERSION_EU) || defined(VERSION_SH)
677
#ifdef VERSION_EU
678
extern void func_802ad7a0(void);
679
#else
680
extern void func_sh_802F64C8(void);
681
#endif
682
683
/**
684
* Called from threads: thread5_game_loop
685
*/
686
void maybe_tick_game_sound(void) {
687
if (sGameLoopTicked != 0) {
688
update_game_sound();
689
sGameLoopTicked = 0;
690
}
691
#ifdef VERSION_EU
692
func_802ad7a0();
693
#else
694
func_sh_802F64C8(); // moved in SH
695
#endif
696
}
697
698
void func_eu_802e9bec(s32 player, s32 channel, s32 arg2) {
699
// EU verson of unused_803209D8
700
// chan->stopSomething2 = arg2?
701
func_802ad770(0x08000000 | (player & 0xff) << 16 | (channel & 0xff) << 8, (s8) arg2);
702
}
703
704
#else
705
706
#ifdef TARGET_N64
707
/**
708
* Called from threads: thread4_sound
709
*/
710
struct SPTask *create_next_audio_frame_task(void) {
711
u32 samplesRemainingInAI;
712
s32 writtenCmds;
713
s32 index;
714
OSTask_t *task;
715
s32 oldDmaCount;
716
s32 flags;
717
718
gAudioFrameCount++;
719
if (gAudioLoadLock != AUDIO_LOCK_NOT_LOADING) {
720
stubbed_printf("DAC:Lost 1 Frame.\n");
721
return NULL;
722
}
723
724
gAudioTaskIndex ^= 1;
725
gCurrAiBufferIndex++;
726
gCurrAiBufferIndex %= NUMAIBUFFERS;
727
index = (gCurrAiBufferIndex - 2 + NUMAIBUFFERS) % NUMAIBUFFERS;
728
samplesRemainingInAI = osAiGetLength() / 4;
729
730
// Audio is triple buffered; the audio interface reads from two buffers
731
// while the third is being written by the RSP. More precisely, the
732
// lifecycle is:
733
// - this function computes an audio command list
734
// - wait for vblank
735
// - the command list is sent to the RSP (we could have sent it to the
736
// RSP before the vblank, but that gives the RSP less time to finish)
737
// - wait for vblank
738
// - the RSP is now expected to be finished, and we can send its output
739
// on to the AI
740
// Here we thus send to the AI the sound that was generated two frames ago.
741
if (gAiBufferLengths[index] != 0) {
742
osAiSetNextBuffer(gAiBuffers[index], gAiBufferLengths[index] * 4);
743
}
744
745
oldDmaCount = gCurrAudioFrameDmaCount;
746
// There has to be some sort of no-op if here, but it's not exactly clear
747
// how it should look... It's also very unclear why gCurrAudioFrameDmaQueue
748
// isn't read from here, despite gCurrAudioFrameDmaCount being reset.
749
if (oldDmaCount > AUDIO_FRAME_DMA_QUEUE_SIZE) {
750
stubbed_printf("DMA: Request queue over.( %d )\n", oldDmaCount);
751
}
752
gCurrAudioFrameDmaCount = 0;
753
754
gAudioTask = &gAudioTasks[gAudioTaskIndex];
755
gAudioCmd = gAudioCmdBuffers[gAudioTaskIndex];
756
757
index = gCurrAiBufferIndex;
758
gCurrAiBuffer = gAiBuffers[index];
759
gAiBufferLengths[index] =
760
((gSamplesPerFrameTarget - samplesRemainingInAI + EXTRA_BUFFERED_AI_SAMPLES_TARGET) & ~0xf)
761
+ SAMPLES_TO_OVERPRODUCE;
762
if (gAiBufferLengths[index] < gMinAiBufferLength) {
763
gAiBufferLengths[index] = gMinAiBufferLength;
764
}
765
if (gAiBufferLengths[index] > gSamplesPerFrameTarget + SAMPLES_TO_OVERPRODUCE) {
766
gAiBufferLengths[index] = gSamplesPerFrameTarget + SAMPLES_TO_OVERPRODUCE;
767
}
768
769
if (sGameLoopTicked != 0) {
770
update_game_sound();
771
sGameLoopTicked = 0;
772
}
773
774
// For the function to match we have to preserve some arbitrary variable
775
// across this function call.
776
flags = 0;
777
gAudioCmd = synthesis_execute(gAudioCmd, &writtenCmds, gCurrAiBuffer, gAiBufferLengths[index]);
778
gAudioRandom = ((gAudioRandom + gAudioFrameCount) * gAudioFrameCount);
779
780
index = gAudioTaskIndex;
781
gAudioTask->msgqueue = NULL;
782
gAudioTask->msg = NULL;
783
784
task = &gAudioTask->task.t;
785
task->type = M_AUDTASK;
786
task->flags = flags;
787
task->ucode_boot = rspF3DBootStart;
788
task->ucode_boot_size = (u8 *) rspF3DBootEnd - (u8 *) rspF3DBootStart;
789
task->ucode = rspAspMainStart;
790
task->ucode_size = 0x800; // (this size is ignored)
791
task->ucode_data = rspAspMainDataStart;
792
task->ucode_data_size = (rspAspMainDataEnd - rspAspMainDataStart) * sizeof(u64);
793
task->dram_stack = NULL;
794
task->dram_stack_size = 0;
795
task->output_buff = NULL;
796
task->output_buff_size = NULL;
797
task->data_ptr = gAudioCmdBuffers[index];
798
task->data_size = writtenCmds * sizeof(u64);
799
800
// The audio task never yields, so having a yield buffer is pointless.
801
// This wastefulness was fixed in US.
802
#ifdef VERSION_JP
803
task->yield_data_ptr = (u64 *) gAudioSPTaskYieldBuffer;
804
task->yield_data_size = OS_YIELD_AUDIO_SIZE;
805
#else
806
task->yield_data_ptr = NULL;
807
task->yield_data_size = 0;
808
#endif
809
810
decrease_sample_dma_ttls();
811
return gAudioTask;
812
}
813
#else
814
struct SPTask *create_next_audio_frame_task(void) {
815
return NULL;
816
}
817
void create_next_audio_buffer(s16 *samples, u32 num_samples) {
818
gAudioFrameCount++;
819
if (sGameLoopTicked != 0) {
820
update_game_sound();
821
sGameLoopTicked = 0;
822
}
823
s32 writtenCmds;
824
synthesis_execute(gAudioCmdBuffers[0], &writtenCmds, samples, num_samples);
825
gAudioRandom = ((gAudioRandom + gAudioFrameCount) * gAudioFrameCount);
826
decrease_sample_dma_ttls();
827
}
828
#endif
829
#endif
830
831
/**
832
* Called from threads: thread5_game_loop
833
*/
834
void play_sound(s32 soundBits, f32 *pos) {
835
sSoundRequests[sSoundRequestCount].soundBits = soundBits;
836
sSoundRequests[sSoundRequestCount].position = pos;
837
sSoundRequestCount++;
838
}
839
840
/**
841
* Called from threads: thread4_sound, thread5_game_loop (EU only)
842
*/
843
static void process_sound_request(u32 bits, f32 *pos) {
844
u8 bank;
845
u8 soundIndex;
846
u8 counter = 0;
847
u8 soundId;
848
f32 dist;
849
const f32 one = 1.0f;
850
851
bank = (bits & SOUNDARGS_MASK_BANK) >> SOUNDARGS_SHIFT_BANK;
852
soundId = (bits & SOUNDARGS_MASK_SOUNDID) >> SOUNDARGS_SHIFT_SOUNDID;
853
854
if (soundId >= sNumSoundsPerBank[bank] || sSoundBankDisabled[bank]) {
855
return;
856
}
857
858
soundIndex = sSoundBanks[bank][0].next;
859
while (soundIndex != 0xff && soundIndex != 0) {
860
// If an existing sound from the same source exists in the bank, then we should either
861
// interrupt that sound and replace it with the new sound, or we should drop the new sound.
862
if (sSoundBanks[bank][soundIndex].x == pos) {
863
// If the existing sound has lower or equal priority, then we should replace it.
864
// Otherwise the new sound will be dropped.
865
if ((sSoundBanks[bank][soundIndex].soundBits & SOUNDARGS_MASK_PRIORITY)
866
<= (bits & SOUNDARGS_MASK_PRIORITY)) {
867
868
// If the existing sound is discrete or is a different continuous sound, then
869
// interrupt it and play the new sound instead.
870
// Otherwise the new sound is continuous and equals the existing sound, so we just
871
// need to update the sound's freshness.
872
if ((sSoundBanks[bank][soundIndex].soundBits & SOUND_DISCRETE) != 0
873
|| (bits & SOUNDARGS_MASK_SOUNDID)
874
!= (sSoundBanks[bank][soundIndex].soundBits & SOUNDARGS_MASK_SOUNDID)) {
875
update_background_music_after_sound(bank, soundIndex);
876
sSoundBanks[bank][soundIndex].soundBits = bits;
877
// In practice, the starting status is always WAITING
878
sSoundBanks[bank][soundIndex].soundStatus = bits & SOUNDARGS_MASK_STATUS;
879
}
880
881
// Reset freshness:
882
// - For discrete sounds, this gives the sound SOUND_MAX_FRESHNESS frames to play
883
// before it gets deleted for being stale
884
// - For continuous sounds, this gives it another 2 frames before play_sound must
885
// be called again to keep it playing
886
sSoundBanks[bank][soundIndex].freshness = SOUND_MAX_FRESHNESS;
887
}
888
889
// Prevent allocating a new node - if the existing sound had higher piority, then the
890
// new sound will be dropped
891
soundIndex = 0;
892
} else {
893
soundIndex = sSoundBanks[bank][soundIndex].next;
894
}
895
counter++;
896
}
897
898
if (counter == 0) {
899
sSoundMovingSpeed[bank] = 32;
900
}
901
902
// If free list has more than one element remaining
903
if (sSoundBanks[bank][sSoundBankFreeListFront[bank]].next != 0xff && soundIndex != 0) {
904
// Allocate from free list
905
soundIndex = sSoundBankFreeListFront[bank];
906
907
dist = sqrtf(pos[0] * pos[0] + pos[1] * pos[1] + pos[2] * pos[2]) * one;
908
sSoundBanks[bank][soundIndex].x = &pos[0];
909
sSoundBanks[bank][soundIndex].y = &pos[1];
910
sSoundBanks[bank][soundIndex].z = &pos[2];
911
sSoundBanks[bank][soundIndex].distance = dist;
912
sSoundBanks[bank][soundIndex].soundBits = bits;
913
// In practice, the starting status is always WAITING
914
sSoundBanks[bank][soundIndex].soundStatus = bits & SOUNDARGS_MASK_STATUS;
915
sSoundBanks[bank][soundIndex].freshness = SOUND_MAX_FRESHNESS;
916
917
// Append to end of used list and pop from front of free list
918
sSoundBanks[bank][soundIndex].prev = sSoundBankUsedListBack[bank];
919
sSoundBanks[bank][sSoundBankUsedListBack[bank]].next = sSoundBankFreeListFront[bank];
920
sSoundBankUsedListBack[bank] = sSoundBankFreeListFront[bank];
921
sSoundBankFreeListFront[bank] = sSoundBanks[bank][sSoundBankFreeListFront[bank]].next;
922
sSoundBanks[bank][sSoundBankFreeListFront[bank]].prev = 0xff;
923
sSoundBanks[bank][soundIndex].next = 0xff;
924
}
925
}
926
927
/**
928
* Processes all sound requests
929
*
930
* Called from threads: thread4_sound, thread5_game_loop (EU only)
931
*/
932
static void process_all_sound_requests(void) {
933
struct Sound *sound;
934
935
while (sSoundRequestCount != sNumProcessedSoundRequests) {
936
sound = &sSoundRequests[sNumProcessedSoundRequests];
937
process_sound_request(sound->soundBits, sound->position);
938
sNumProcessedSoundRequests++;
939
}
940
}
941
942
/**
943
* Called from threads: thread4_sound, thread5_game_loop (EU only)
944
*/
945
static void delete_sound_from_bank(u8 bank, u8 soundIndex) {
946
if (sSoundBankUsedListBack[bank] == soundIndex) {
947
// Remove from end of used list
948
sSoundBankUsedListBack[bank] = sSoundBanks[bank][soundIndex].prev;
949
} else {
950
// Set sound.next.prev to sound.prev
951
sSoundBanks[bank][sSoundBanks[bank][soundIndex].next].prev = sSoundBanks[bank][soundIndex].prev;
952
}
953
954
// Set sound.prev.next to sound.next
955
sSoundBanks[bank][sSoundBanks[bank][soundIndex].prev].next = sSoundBanks[bank][soundIndex].next;
956
957
// Push to front of free list
958
sSoundBanks[bank][soundIndex].next = sSoundBankFreeListFront[bank];
959
sSoundBanks[bank][soundIndex].prev = 0xff;
960
sSoundBanks[bank][sSoundBankFreeListFront[bank]].prev = soundIndex;
961
sSoundBankFreeListFront[bank] = soundIndex;
962
}
963
964
/**
965
* Called from threads: thread3_main, thread4_sound, thread5_game_loop
966
*/
967
static void update_background_music_after_sound(u8 bank, u8 soundIndex) {
968
if (sSoundBanks[bank][soundIndex].soundBits & SOUND_LOWER_BACKGROUND_MUSIC) {
969
sSoundBanksThatLowerBackgroundMusic &= (1 << bank) ^ 0xffff;
970
begin_background_music_fade(50);
971
}
972
}
973
974
/**
975
* Called from threads: thread4_sound, thread5_game_loop (EU only)
976
*/
977
static void select_current_sounds(u8 bank) {
978
u32 isDiscreteAndStatus;
979
u8 latestSoundIndex;
980
u8 i;
981
u8 j;
982
u8 soundIndex;
983
u32 liveSoundPriorities[16] = { 0x10000000, 0x10000000, 0x10000000, 0x10000000,
984
0x10000000, 0x10000000, 0x10000000, 0x10000000,
985
0x10000000, 0x10000000, 0x10000000, 0x10000000,
986
0x10000000, 0x10000000, 0x10000000, 0x10000000 };
987
u8 liveSoundIndices[16] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
988
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
989
u8 liveSoundStatuses[16] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
990
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
991
u8 numSoundsInBank = 0;
992
u8 requestedPriority;
993
994
//
995
// Delete stale sounds and prioritize remaining sounds into the liveSound arrays
996
//
997
soundIndex = sSoundBanks[bank][0].next;
998
while (soundIndex != 0xff) {
999
latestSoundIndex = soundIndex;
1000
1001
// If a discrete sound goes 10 frames without being played (because it is too low
1002
// priority), then mark it for deletion
1003
if ((sSoundBanks[bank][soundIndex].soundBits & (SOUND_DISCRETE | SOUNDARGS_MASK_STATUS))
1004
== (SOUND_DISCRETE | SOUND_STATUS_WAITING)) {
1005
if (sSoundBanks[bank][soundIndex].freshness-- == 0) {
1006
sSoundBanks[bank][soundIndex].soundBits = NO_SOUND;
1007
}
1008
}
1009
// If a continuous sound goes 2 frames without play_sound being called, then mark it for
1010
// deletion
1011
else if ((sSoundBanks[bank][soundIndex].soundBits & SOUND_DISCRETE) == 0) {
1012
if (sSoundBanks[bank][soundIndex].freshness-- == SOUND_MAX_FRESHNESS - 2) {
1013
update_background_music_after_sound(bank, soundIndex);
1014
sSoundBanks[bank][soundIndex].soundBits = NO_SOUND;
1015
}
1016
}
1017
1018
// If a sound was marked for deletion and hasn't started playing yet, delete it now
1019
if (sSoundBanks[bank][soundIndex].soundBits == NO_SOUND
1020
&& sSoundBanks[bank][soundIndex].soundStatus == SOUND_STATUS_WAITING) {
1021
// Since the current sound will be deleted, the next iteration should process
1022
// sound.prev.next
1023
latestSoundIndex = sSoundBanks[bank][soundIndex].prev;
1024
sSoundBanks[bank][soundIndex].soundStatus = SOUND_STATUS_STOPPED;
1025
delete_sound_from_bank(bank, soundIndex);
1026
}
1027
1028
// If the current sound was not just deleted, consider it as a candidate for the currently
1029
// playing sound
1030
if (sSoundBanks[bank][soundIndex].soundStatus != SOUND_STATUS_STOPPED
1031
&& soundIndex == latestSoundIndex) {
1032
1033
// Recompute distance each frame since the sound's position may have changed
1034
sSoundBanks[bank][soundIndex].distance =
1035
sqrtf((*sSoundBanks[bank][soundIndex].x * *sSoundBanks[bank][soundIndex].x)
1036
+ (*sSoundBanks[bank][soundIndex].y * *sSoundBanks[bank][soundIndex].y)
1037
+ (*sSoundBanks[bank][soundIndex].z * *sSoundBanks[bank][soundIndex].z))
1038
* 1;
1039
1040
requestedPriority = (sSoundBanks[bank][soundIndex].soundBits & SOUNDARGS_MASK_PRIORITY)
1041
>> SOUNDARGS_SHIFT_PRIORITY;
1042
1043
// Recompute priority, possibly based on the sound's source position relative to the
1044
// camera.
1045
// (Note that the sound's priority is the opposite of requestedPriority; lower is
1046
// more important)
1047
if (sSoundBanks[bank][soundIndex].soundBits & SOUND_NO_PRIORITY_LOSS) {
1048
sSoundBanks[bank][soundIndex].priority = 0x4c * (0xff - requestedPriority);
1049
} else if (*sSoundBanks[bank][soundIndex].z > 0.0f) {
1050
sSoundBanks[bank][soundIndex].priority =
1051
(u32) sSoundBanks[bank][soundIndex].distance
1052
+ (u32)(*sSoundBanks[bank][soundIndex].z / US_FLOAT(6.0))
1053
+ 0x4c * (0xff - requestedPriority);
1054
} else {
1055
sSoundBanks[bank][soundIndex].priority =
1056
(u32) sSoundBanks[bank][soundIndex].distance + 0x4c * (0xff - requestedPriority);
1057
}
1058
1059
// Insert the sound into the liveSound arrays, keeping the arrays sorted by priority.
1060
// If more than sMaxChannelsForSoundBank[bank] sounds are live, then the
1061
// sound with lowest priority will be removed from the arrays.
1062
// In practice sMaxChannelsForSoundBank is always 1, so this code is overly general.
1063
for (i = 0; i < sMaxChannelsForSoundBank[bank]; i++) {
1064
// If the correct position is found
1065
if (liveSoundPriorities[i] >= sSoundBanks[bank][soundIndex].priority) {
1066
// Shift remaining sounds to the right
1067
for (j = sMaxChannelsForSoundBank[bank] - 1; j > i; j--) {
1068
liveSoundPriorities[j] = liveSoundPriorities[j - 1];
1069
liveSoundIndices[j] = liveSoundIndices[j - 1];
1070
liveSoundStatuses[j] = liveSoundStatuses[j - 1];
1071
}
1072
// Insert the sound at index i
1073
liveSoundPriorities[i] = sSoundBanks[bank][soundIndex].priority;
1074
liveSoundIndices[i] = soundIndex;
1075
liveSoundStatuses[i] = sSoundBanks[bank][soundIndex].soundStatus; // unused
1076
// Break
1077
i = sMaxChannelsForSoundBank[bank];
1078
}
1079
}
1080
1081
numSoundsInBank++;
1082
}
1083
1084
soundIndex = sSoundBanks[bank][latestSoundIndex].next;
1085
}
1086
1087
sNumSoundsInBank[bank] = numSoundsInBank;
1088
sUsedChannelsForSoundBank[bank] = sMaxChannelsForSoundBank[bank];
1089
1090
//
1091
// Remove any sounds from liveSoundIndices that are already playing.
1092
// Stop any currently playing sounds that are not in liveSoundIndices.
1093
//
1094
for (i = 0; i < sUsedChannelsForSoundBank[bank]; i++) {
1095
// Check if sCurrentSound[bank][i] is present in the liveSound arrays.
1096
for (soundIndex = 0; soundIndex < sUsedChannelsForSoundBank[bank]; soundIndex++) {
1097
if (liveSoundIndices[soundIndex] != 0xff
1098
&& sCurrentSound[bank][i] == liveSoundIndices[soundIndex]) {
1099
// If found, remove it from liveSoundIndices
1100
liveSoundIndices[soundIndex] = 0xff;
1101
soundIndex = 0xfe; // Break. Afterward soundIndex will be 0xff
1102
}
1103
}
1104
1105
// If it is not present in the liveSound arrays, then stop playing it
1106
if (soundIndex != 0xff) {
1107
if (sCurrentSound[bank][i] != 0xff) {
1108
// If the sound was marked for deletion and is playing, delete it
1109
if (sSoundBanks[bank][sCurrentSound[bank][i]].soundBits == NO_SOUND) {
1110
if (sSoundBanks[bank][sCurrentSound[bank][i]].soundStatus == SOUND_STATUS_PLAYING) {
1111
sSoundBanks[bank][sCurrentSound[bank][i]].soundStatus = SOUND_STATUS_STOPPED;
1112
delete_sound_from_bank(bank, sCurrentSound[bank][i]);
1113
}
1114
}
1115
1116
// If the sound is discrete and is playing, then delete it
1117
isDiscreteAndStatus = sSoundBanks[bank][sCurrentSound[bank][i]].soundBits
1118
& (SOUND_DISCRETE | SOUNDARGS_MASK_STATUS);
1119
if (isDiscreteAndStatus >= (SOUND_DISCRETE | SOUND_STATUS_PLAYING)
1120
&& sSoundBanks[bank][sCurrentSound[bank][i]].soundStatus != SOUND_STATUS_STOPPED) {
1121
//! @bug On JP, if a discrete sound that lowers the background music is
1122
// interrupted in this way, it will keep the background music low afterward.
1123
// There are only a few of these sounds, and it probably isn't possible to do
1124
// it in practice without using a time stop glitch like triple star spawn.
1125
#ifndef VERSION_JP
1126
update_background_music_after_sound(bank, sCurrentSound[bank][i]);
1127
#endif
1128
1129
sSoundBanks[bank][sCurrentSound[bank][i]].soundBits = NO_SOUND;
1130
sSoundBanks[bank][sCurrentSound[bank][i]].soundStatus = SOUND_STATUS_STOPPED;
1131
delete_sound_from_bank(bank, sCurrentSound[bank][i]);
1132
}
1133
// If the sound is continuous and is playing, then stop playing it but don't delete
1134
// it. (A continuous sound shouldn't be deleted until it stops being requested)
1135
else {
1136
if (isDiscreteAndStatus == SOUND_STATUS_PLAYING
1137
&& sSoundBanks[bank][sCurrentSound[bank][i]].soundStatus
1138
!= SOUND_STATUS_STOPPED) {
1139
sSoundBanks[bank][sCurrentSound[bank][i]].soundStatus = SOUND_STATUS_WAITING;
1140
}
1141
}
1142
}
1143
sCurrentSound[bank][i] = 0xff;
1144
}
1145
}
1146
1147
//
1148
// Start playing the remaining sounds from liveSoundIndices.
1149
//
1150
for (soundIndex = 0; soundIndex < sUsedChannelsForSoundBank[bank]; soundIndex++) {
1151
if (liveSoundIndices[soundIndex] != 0xff) {
1152
for (i = 0; i < sUsedChannelsForSoundBank[bank]; i++) {
1153
if (sCurrentSound[bank][i] == 0xff) {
1154
sCurrentSound[bank][i] = liveSoundIndices[soundIndex];
1155
1156
// Set (soundBits & status) to WAITING (soundStatus will be updated
1157
// shortly after in update_game_sound)
1158
sSoundBanks[bank][liveSoundIndices[soundIndex]].soundBits =
1159
(sSoundBanks[bank][liveSoundIndices[soundIndex]].soundBits
1160
& ~SOUNDARGS_MASK_STATUS)
1161
+ SOUND_STATUS_WAITING;
1162
1163
liveSoundIndices[i] = 0xff; // doesn't do anything
1164
i = 0xfe; // break
1165
}
1166
}
1167
}
1168
}
1169
}
1170
1171
/**
1172
* Given x and z coordinates, return the pan. This is a value nominally between
1173
* 0 and 1 that represents the audio direction.
1174
*
1175
* Pan:
1176
* 0.0 - fully left
1177
* 0.5 - center pan
1178
* 1.0 - fully right
1179
*
1180
* Called from threads: thread4_sound, thread5_game_loop (EU only)
1181
*/
1182
static f32 get_sound_pan(f32 x, f32 z) {
1183
f32 absX;
1184
f32 absZ;
1185
f32 pan;
1186
1187
absX = (x < 0 ? -x : x);
1188
if (absX > AUDIO_MAX_DISTANCE) {
1189
absX = AUDIO_MAX_DISTANCE;
1190
}
1191
1192
absZ = (z < 0 ? -z : z);
1193
if (absZ > AUDIO_MAX_DISTANCE) {
1194
absZ = AUDIO_MAX_DISTANCE;
1195
}
1196
1197
// There are 4 panning equations (12-hr clock used for angles)
1198
// 1. (0,0) fully-centered pan
1199
// 2. far right pan: between 1:30 and 4:30
1200
// 3. far left pan: between 7:30 and 10:30
1201
// 4. center pan: between 4:30 and 7:30 or between 10:30 and 1:30
1202
if (x == US_FLOAT(0.0) && z == US_FLOAT(0.0)) {
1203
// x and z being 0 results in a center pan
1204
pan = US_FLOAT(0.5);
1205
} else if (x >= US_FLOAT(0.0) && absX >= absZ) {
1206
// far right pan
1207
pan = US_FLOAT(1.0) - (2 * AUDIO_MAX_DISTANCE - absX) / (US_FLOAT(3.0) * (2 * AUDIO_MAX_DISTANCE - absZ));
1208
} else if (x < 0 && absX > absZ) {
1209
// far left pan
1210
pan = (2 * AUDIO_MAX_DISTANCE - absX) / (US_FLOAT(3.0) * (2 * AUDIO_MAX_DISTANCE - absZ));
1211
} else {
1212
// center pan
1213
//! @bug (JP PU sound glitch) If |x|, |z| > AUDIO_MAX_DISTANCE, we'll
1214
// end up in this case, and pan may be set to something outside of [0,1]
1215
// since x is not clamped. On JP, this can lead to an out-of-bounds
1216
// float read in note_set_vel_pan_reverb when x is highly negative,
1217
// causing console crashes when that float is a nan or denormal.
1218
pan = 0.5 + x / (US_FLOAT(6.0) * absZ);
1219
}
1220
1221
return pan;
1222
}
1223
1224
/**
1225
* Called from threads: thread4_sound, thread5_game_loop (EU only)
1226
*/
1227
static f32 get_sound_volume(u8 bank, u8 soundIndex, f32 volumeRange) {
1228
f32 maxSoundDistance;
1229
f32 intensity;
1230
#ifndef VERSION_JP
1231
s32 div = bank < 3 ? 2 : 3;
1232
#endif
1233
1234
if (!(sSoundBanks[bank][soundIndex].soundBits & SOUND_NO_VOLUME_LOSS)) {
1235
#ifdef VERSION_JP
1236
// Intensity linearly lowers from 1 at the camera to 0 at maxSoundDistance
1237
maxSoundDistance = sLevelAcousticReaches[gCurrLevelNum];
1238
if (maxSoundDistance < sSoundBanks[bank][soundIndex].distance) {
1239
intensity = 0.0f;
1240
} else {
1241
intensity = 1.0 - sSoundBanks[bank][soundIndex].distance / maxSoundDistance;
1242
}
1243
#else
1244
// Intensity linearly lowers from 1 at the camera to 1 - volumeRange at maxSoundDistance,
1245
// then it goes from 1 - volumeRange at maxSoundDistance to 0 at AUDIO_MAX_DISTANCE
1246
if (sSoundBanks[bank][soundIndex].distance > AUDIO_MAX_DISTANCE) {
1247
intensity = 0.0f;
1248
} else {
1249
maxSoundDistance = sLevelAcousticReaches[gCurrLevelNum] / div;
1250
if (maxSoundDistance < sSoundBanks[bank][soundIndex].distance) {
1251
intensity = ((AUDIO_MAX_DISTANCE - sSoundBanks[bank][soundIndex].distance)
1252
/ (AUDIO_MAX_DISTANCE - maxSoundDistance))
1253
* (1.0f - volumeRange);
1254
} else {
1255
intensity =
1256
1.0f - sSoundBanks[bank][soundIndex].distance / maxSoundDistance * volumeRange;
1257
}
1258
}
1259
#endif
1260
1261
if (sSoundBanks[bank][soundIndex].soundBits & SOUND_VIBRATO) {
1262
#ifdef VERSION_JP
1263
//! @bug Intensity is 0 when the sound is far away. Due to the subtraction below, it is possible to end up with a negative intensity.
1264
// When it is, objects with a volumeRange of 1 can still occasionally be lightly heard.
1265
if (intensity != 0.0)
1266
#else
1267
if (intensity >= 0.08f)
1268
#endif
1269
{
1270
intensity -= (f32)(gAudioRandom & 0xf) / US_FLOAT(192.0);
1271
}
1272
}
1273
} else {
1274
intensity = 1.0f;
1275
}
1276
1277
// Rise quadratically from 1 - volumeRange to 1
1278
return volumeRange * intensity * intensity + 1.0f - volumeRange;
1279
}
1280
1281
/**
1282
* Called from threads: thread4_sound, thread5_game_loop (EU only)
1283
*/
1284
static f32 get_sound_freq_scale(u8 bank, u8 item) {
1285
f32 amount;
1286
1287
if (!(sSoundBanks[bank][item].soundBits & SOUND_CONSTANT_FREQUENCY)) {
1288
amount = sSoundBanks[bank][item].distance / AUDIO_MAX_DISTANCE;
1289
if (sSoundBanks[bank][item].soundBits & SOUND_VIBRATO) {
1290
amount += (f32)(gAudioRandom & 0xff) / US_FLOAT(64.0);
1291
}
1292
} else {
1293
amount = 0.0f;
1294
}
1295
1296
// Goes from 1 at the camera to 1 + 1/15 at AUDIO_MAX_DISTANCE (and continues rising
1297
// farther than that)
1298
return amount / US_FLOAT(15.0) + US_FLOAT(1.0);
1299
}
1300
1301
/**
1302
* Called from threads: thread4_sound, thread5_game_loop (EU only)
1303
*/
1304
static u8 get_sound_reverb(UNUSED u8 bank, UNUSED u8 soundIndex, u8 channelIndex) {
1305
u8 area;
1306
u8 level;
1307
u8 reverb;
1308
1309
#ifndef VERSION_JP
1310
// Disable level reverb if NO_ECHO is set
1311
if (sSoundBanks[bank][soundIndex].soundBits & SOUND_NO_ECHO) {
1312
level = 0;
1313
area = 0;
1314
} else {
1315
#endif
1316
level = (gCurrLevelNum > LEVEL_MAX ? LEVEL_MAX : gCurrLevelNum);
1317
area = gCurrAreaIndex - 1;
1318
if (area > 2) {
1319
area = 2;
1320
}
1321
#ifndef VERSION_JP
1322
}
1323
#endif
1324
1325
// reverb = reverb adjustment + level reverb + a volume-dependent value
1326
// The volume-dependent value is 0 when volume is at maximum, and raises to
1327
// LOW_VOLUME_REVERB when the volume is 0
1328
reverb = (u8)((u8) gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->soundScriptIO[5]
1329
+ sLevelAreaReverbs[level][area]
1330
+ (US_FLOAT(1.0) - gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume)
1331
* LOW_VOLUME_REVERB);
1332
1333
if (reverb > 0x7f) {
1334
reverb = 0x7f;
1335
}
1336
return reverb;
1337
}
1338
1339
static void noop_8031EEC8(void) {
1340
}
1341
1342
/**
1343
* Called from the game loop thread to inform the audio thread that a new game
1344
* frame has started.
1345
*
1346
* Called from threads: thread5_game_loop
1347
*/
1348
void audio_signal_game_loop_tick(void) {
1349
sGameLoopTicked = 1;
1350
#if defined(VERSION_EU) || defined(VERSION_SH)
1351
maybe_tick_game_sound();
1352
#endif
1353
noop_8031EEC8();
1354
}
1355
1356
/**
1357
* Called from threads: thread4_sound, thread5_game_loop (EU and SH only)
1358
*/
1359
static void update_game_sound(void) {
1360
u8 soundStatus;
1361
u8 i;
1362
u8 soundId;
1363
u8 bank;
1364
u8 channelIndex = 0;
1365
u8 soundIndex;
1366
#if defined(VERSION_JP) || defined(VERSION_US)
1367
f32 value;
1368
#endif
1369
1370
process_all_sound_requests();
1371
process_level_music_dynamics();
1372
1373
if (gSequencePlayers[SEQ_PLAYER_SFX].channels[0] == &gSequenceChannelNone) {
1374
return;
1375
}
1376
1377
for (bank = 0; bank < SOUND_BANK_COUNT; bank++) {
1378
select_current_sounds(bank);
1379
1380
for (i = 0; i < MAX_CHANNELS_PER_SOUND_BANK; i++) {
1381
soundIndex = sCurrentSound[bank][i];
1382
1383
if (soundIndex < 0xff
1384
&& sSoundBanks[bank][soundIndex].soundStatus != SOUND_STATUS_STOPPED) {
1385
soundStatus = sSoundBanks[bank][soundIndex].soundBits & SOUNDARGS_MASK_STATUS;
1386
soundId = (sSoundBanks[bank][soundIndex].soundBits >> SOUNDARGS_SHIFT_SOUNDID);
1387
1388
sSoundBanks[bank][soundIndex].soundStatus = soundStatus;
1389
1390
if (soundStatus == SOUND_STATUS_WAITING) {
1391
if (sSoundBanks[bank][soundIndex].soundBits & SOUND_LOWER_BACKGROUND_MUSIC) {
1392
sSoundBanksThatLowerBackgroundMusic |= 1 << bank;
1393
begin_background_music_fade(50);
1394
}
1395
1396
// Set sound status to PLAYING
1397
sSoundBanks[bank][soundIndex].soundBits++;
1398
sSoundBanks[bank][soundIndex].soundStatus = SOUND_STATUS_PLAYING;
1399
1400
// Begin playing the sound
1401
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->soundScriptIO[4] = soundId;
1402
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->soundScriptIO[0] = 1;
1403
1404
switch (bank) {
1405
case SOUND_BANK_MOVING:
1406
if (!(sSoundBanks[bank][soundIndex].soundBits & SOUND_CONSTANT_FREQUENCY)) {
1407
if (sSoundMovingSpeed[bank] > 8) {
1408
#if defined(VERSION_EU) || defined(VERSION_SH)
1409
func_802ad728(
1410
0x02020000 | ((channelIndex & 0xff) << 8),
1411
get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1));
1412
#else
1413
value = get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1);
1414
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume =
1415
value;
1416
#endif
1417
} else {
1418
#if defined(VERSION_EU) || defined(VERSION_SH)
1419
func_802ad728(0x02020000 | ((channelIndex & 0xff) << 8),
1420
get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1)
1421
* ((sSoundMovingSpeed[bank] + 8.0f) / 16));
1422
#else
1423
value = get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1);
1424
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume =
1425
(sSoundMovingSpeed[bank] + 8.0f) / 16 * value;
1426
#endif
1427
}
1428
#if defined(VERSION_EU) || defined(VERSION_SH)
1429
func_802ad770(0x03020000 | ((channelIndex & 0xff) << 8),
1430
get_sound_pan(*sSoundBanks[bank][soundIndex].x,
1431
*sSoundBanks[bank][soundIndex].z));
1432
#else
1433
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->pan =
1434
get_sound_pan(*sSoundBanks[bank][soundIndex].x,
1435
*sSoundBanks[bank][soundIndex].z);
1436
#endif
1437
1438
if ((sSoundBanks[bank][soundIndex].soundBits & SOUNDARGS_MASK_SOUNDID)
1439
== (SOUND_MOVING_FLYING & SOUNDARGS_MASK_SOUNDID)) {
1440
#if defined(VERSION_EU) || defined(VERSION_SH)
1441
func_802ad728(
1442
0x04020000 | ((channelIndex & 0xff) << 8),
1443
get_sound_freq_scale(bank, soundIndex)
1444
+ ((f32) sSoundMovingSpeed[bank] / US_FLOAT(80.0)));
1445
#else
1446
value = get_sound_freq_scale(bank, soundIndex);
1447
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->freqScale =
1448
((f32) sSoundMovingSpeed[bank] / US_FLOAT(80.0)) + value;
1449
#endif
1450
} else {
1451
#if defined(VERSION_EU) || defined(VERSION_SH)
1452
func_802ad728(
1453
0x04020000 | ((channelIndex & 0xff) << 8),
1454
get_sound_freq_scale(bank, soundIndex)
1455
+ ((f32) sSoundMovingSpeed[bank] / US_FLOAT(400.0)));
1456
#else
1457
value = get_sound_freq_scale(bank, soundIndex);
1458
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->freqScale =
1459
((f32) sSoundMovingSpeed[bank] / US_FLOAT(400.0)) + value;
1460
#endif
1461
}
1462
#if defined(VERSION_EU) || defined(VERSION_SH)
1463
func_802ad770(0x05020000 | ((channelIndex & 0xff) << 8),
1464
get_sound_reverb(bank, soundIndex, channelIndex));
1465
#else
1466
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->reverbVol =
1467
get_sound_reverb(bank, soundIndex, channelIndex);
1468
#endif
1469
1470
break;
1471
}
1472
// fallthrough
1473
case SOUND_BANK_MENU:
1474
#if defined(VERSION_EU) || defined(VERSION_SH)
1475
func_802ad728(0x02020000 | ((channelIndex & 0xff) << 8), 1);
1476
func_802ad770(0x03020000 | ((channelIndex & 0xff) << 8), 64);
1477
func_802ad728(0x04020000 | ((channelIndex & 0xff) << 8),
1478
get_sound_freq_scale(bank, soundIndex));
1479
#else
1480
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume = 1.0f;
1481
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->pan = 0.5f;
1482
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->freqScale = 1.0f;
1483
#endif
1484
break;
1485
case SOUND_BANK_ACTION:
1486
case SOUND_BANK_VOICE:
1487
#if defined(VERSION_EU) || defined(VERSION_SH)
1488
func_802ad770(0x05020000 | ((channelIndex & 0xff) << 8),
1489
get_sound_reverb(bank, soundIndex, channelIndex));
1490
func_802ad728(0x02020000 | ((channelIndex & 0xff) << 8),
1491
get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1));
1492
func_802ad770(0x03020000 | ((channelIndex & 0xff) << 8),
1493
get_sound_pan(*sSoundBanks[bank][soundIndex].x,
1494
*sSoundBanks[bank][soundIndex].z)
1495
* 127.0f
1496
+ 0.5f);
1497
func_802ad728(0x04020000 | ((channelIndex & 0xff) << 8),
1498
get_sound_freq_scale(bank, soundIndex));
1499
#else
1500
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume =
1501
get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1);
1502
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->pan =
1503
get_sound_pan(*sSoundBanks[bank][soundIndex].x,
1504
*sSoundBanks[bank][soundIndex].z);
1505
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->freqScale =
1506
get_sound_freq_scale(bank, soundIndex);
1507
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->reverbVol =
1508
get_sound_reverb(bank, soundIndex, channelIndex);
1509
#endif
1510
break;
1511
case SOUND_BANK_GENERAL:
1512
case SOUND_BANK_ENV:
1513
case SOUND_BANK_OBJ:
1514
case SOUND_BANK_AIR:
1515
case SOUND_BANK_GENERAL2:
1516
case SOUND_BANK_OBJ2:
1517
#if defined(VERSION_EU) || defined(VERSION_SH)
1518
func_802ad770(0x05020000 | ((channelIndex & 0xff) << 8),
1519
get_sound_reverb(bank, soundIndex, channelIndex));
1520
func_802ad728(0x02020000 | ((channelIndex & 0xff) << 8),
1521
get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK2));
1522
func_802ad770(0x03020000 | ((channelIndex & 0xff) << 8),
1523
get_sound_pan(*sSoundBanks[bank][soundIndex].x,
1524
*sSoundBanks[bank][soundIndex].z)
1525
* 127.0f
1526
+ 0.5f);
1527
func_802ad728(0x04020000 | ((channelIndex & 0xff) << 8),
1528
get_sound_freq_scale(bank, soundIndex));
1529
#else
1530
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->reverbVol =
1531
get_sound_reverb(bank, soundIndex, channelIndex);
1532
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume =
1533
get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK2);
1534
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->pan =
1535
get_sound_pan(*sSoundBanks[bank][soundIndex].x,
1536
*sSoundBanks[bank][soundIndex].z);
1537
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->freqScale =
1538
get_sound_freq_scale(bank, soundIndex);
1539
#endif
1540
break;
1541
}
1542
}
1543
#ifdef VERSION_JP
1544
// If the sound was marked for deletion (bits set to NO_SOUND), then stop playing it
1545
// and delete it
1546
// @bug (JP double red coin sound) If the sound finished within the same frame as
1547
// being marked for deletion, the signal to stop playing will be interpreted as a
1548
// signal to *start* playing, as .main_loop_023589 in 00_sound_player does not check
1549
// for soundScriptIO[0] being zero. This happens most commonly for red coin sounds
1550
// whose sound spawners deactivate 30 frames after the sound starts to play, while
1551
// the sound itself runs for 1.20 seconds. With enough lag these may coincide.
1552
// Fixed on US by checking that layer0->finished is FALSE.
1553
else if (soundStatus == SOUND_STATUS_STOPPED) {
1554
update_background_music_after_sound(bank, soundIndex);
1555
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->soundScriptIO[0] = 0;
1556
delete_sound_from_bank(bank, soundIndex);
1557
}
1558
#else
1559
else if (gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->layers[0] == NULL) {
1560
update_background_music_after_sound(bank, soundIndex);
1561
sSoundBanks[bank][soundIndex].soundStatus = SOUND_STATUS_STOPPED;
1562
delete_sound_from_bank(bank, soundIndex);
1563
} else if (soundStatus == SOUND_STATUS_STOPPED
1564
&& gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]
1565
->layers[0]->finished == FALSE) {
1566
update_background_music_after_sound(bank, soundIndex);
1567
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->soundScriptIO[0] = 0;
1568
delete_sound_from_bank(bank, soundIndex);
1569
}
1570
#endif
1571
// If sound has finished playing, then delete it
1572
// @bug (JP sound glitch) On JP, ...->layers[0] has not been checked for null,
1573
// so this access can crash if an earlier layer allocation failed due to too
1574
// many sounds playing at once. This crash is comparatively common; RTA
1575
// speedrunners even have a setup for avoiding it within the SSL pyramid:
1576
// https://www.youtube.com/watch?v=QetyTgbQxcw
1577
else if (gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->layers[0]->enabled
1578
== FALSE) {
1579
update_background_music_after_sound(bank, soundIndex);
1580
sSoundBanks[bank][soundIndex].soundStatus = SOUND_STATUS_STOPPED;
1581
delete_sound_from_bank(bank, soundIndex);
1582
} else {
1583
// Exactly the same code as before. Unfortunately we can't
1584
// make a macro out of this, because then everything ends up
1585
// on the same line after preprocessing, and the compiler,
1586
// somehow caring about line numbers, makes it not match (it
1587
// computes function arguments in the wrong order).
1588
switch (bank) {
1589
case SOUND_BANK_MOVING:
1590
if (!(sSoundBanks[bank][soundIndex].soundBits & SOUND_CONSTANT_FREQUENCY)) {
1591
if (sSoundMovingSpeed[bank] > 8) {
1592
#if defined(VERSION_EU) || defined(VERSION_SH)
1593
func_802ad728(
1594
0x02020000 | ((channelIndex & 0xff) << 8),
1595
get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1));
1596
#else
1597
value = get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1);
1598
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume =
1599
value;
1600
#endif
1601
} else {
1602
#if defined(VERSION_EU) || defined(VERSION_SH)
1603
func_802ad728(0x02020000 | ((channelIndex & 0xff) << 8),
1604
get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1)
1605
* ((sSoundMovingSpeed[bank] + 8.0f) / 16));
1606
#else
1607
value = get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1);
1608
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume =
1609
(sSoundMovingSpeed[bank] + 8.0f) / 16 * value;
1610
#endif
1611
}
1612
#if defined(VERSION_EU) || defined(VERSION_SH)
1613
func_802ad770(0x03020000 | ((channelIndex & 0xff) << 8),
1614
get_sound_pan(*sSoundBanks[bank][soundIndex].x,
1615
*sSoundBanks[bank][soundIndex].z));
1616
#else
1617
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->pan =
1618
get_sound_pan(*sSoundBanks[bank][soundIndex].x,
1619
*sSoundBanks[bank][soundIndex].z);
1620
#endif
1621
1622
if ((sSoundBanks[bank][soundIndex].soundBits & SOUNDARGS_MASK_SOUNDID)
1623
== (SOUND_MOVING_FLYING & SOUNDARGS_MASK_SOUNDID)) {
1624
#if defined(VERSION_EU) || defined(VERSION_SH)
1625
func_802ad728(
1626
0x04020000 | ((channelIndex & 0xff) << 8),
1627
get_sound_freq_scale(bank, soundIndex)
1628
+ ((f32) sSoundMovingSpeed[bank] / US_FLOAT(80.0)));
1629
#else
1630
value = get_sound_freq_scale(bank, soundIndex);
1631
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->freqScale =
1632
((f32) sSoundMovingSpeed[bank] / US_FLOAT(80.0)) + value;
1633
#endif
1634
} else {
1635
#if defined(VERSION_EU) || defined(VERSION_SH)
1636
func_802ad728(
1637
0x04020000 | ((channelIndex & 0xff) << 8),
1638
get_sound_freq_scale(bank, soundIndex)
1639
+ ((f32) sSoundMovingSpeed[bank] / US_FLOAT(400.0)));
1640
#else
1641
value = get_sound_freq_scale(bank, soundIndex);
1642
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->freqScale =
1643
((f32) sSoundMovingSpeed[bank] / US_FLOAT(400.0)) + value;
1644
#endif
1645
}
1646
#if defined(VERSION_EU) || defined(VERSION_SH)
1647
func_802ad770(0x05020000 | ((channelIndex & 0xff) << 8),
1648
get_sound_reverb(bank, soundIndex, channelIndex));
1649
#else
1650
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->reverbVol =
1651
get_sound_reverb(bank, soundIndex, channelIndex);
1652
#endif
1653
1654
break;
1655
}
1656
// fallthrough
1657
case SOUND_BANK_MENU:
1658
#if defined(VERSION_EU) || defined(VERSION_SH)
1659
func_802ad728(0x02020000 | ((channelIndex & 0xff) << 8), 1);
1660
func_802ad770(0x03020000 | ((channelIndex & 0xff) << 8), 64);
1661
func_802ad728(0x04020000 | ((channelIndex & 0xff) << 8),
1662
get_sound_freq_scale(bank, soundIndex));
1663
#else
1664
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume = 1.0f;
1665
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->pan = 0.5f;
1666
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->freqScale = 1.0f;
1667
#endif
1668
break;
1669
case SOUND_BANK_ACTION:
1670
case SOUND_BANK_VOICE:
1671
#if defined(VERSION_EU) || defined(VERSION_SH)
1672
func_802ad770(0x05020000 | ((channelIndex & 0xff) << 8),
1673
get_sound_reverb(bank, soundIndex, channelIndex));
1674
func_802ad728(0x02020000 | ((channelIndex & 0xff) << 8),
1675
get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1));
1676
func_802ad770(0x03020000 | ((channelIndex & 0xff) << 8),
1677
get_sound_pan(*sSoundBanks[bank][soundIndex].x,
1678
*sSoundBanks[bank][soundIndex].z)
1679
* 127.0f
1680
+ 0.5f);
1681
func_802ad728(0x04020000 | ((channelIndex & 0xff) << 8),
1682
get_sound_freq_scale(bank, soundIndex));
1683
#else
1684
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume =
1685
get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1);
1686
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->pan =
1687
get_sound_pan(*sSoundBanks[bank][soundIndex].x,
1688
*sSoundBanks[bank][soundIndex].z);
1689
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->freqScale =
1690
get_sound_freq_scale(bank, soundIndex);
1691
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->reverbVol =
1692
get_sound_reverb(bank, soundIndex, channelIndex);
1693
#endif
1694
break;
1695
case SOUND_BANK_GENERAL:
1696
case SOUND_BANK_ENV:
1697
case SOUND_BANK_OBJ:
1698
case SOUND_BANK_AIR:
1699
case SOUND_BANK_GENERAL2:
1700
case SOUND_BANK_OBJ2:
1701
#if defined(VERSION_EU) || defined(VERSION_SH)
1702
func_802ad770(0x05020000 | ((channelIndex & 0xff) << 8),
1703
get_sound_reverb(bank, soundIndex, channelIndex));
1704
func_802ad728(0x02020000 | ((channelIndex & 0xff) << 8),
1705
get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK2));
1706
func_802ad770(0x03020000 | ((channelIndex & 0xff) << 8),
1707
get_sound_pan(*sSoundBanks[bank][soundIndex].x,
1708
*sSoundBanks[bank][soundIndex].z)
1709
* 127.0f
1710
+ 0.5f);
1711
func_802ad728(0x04020000 | ((channelIndex & 0xff) << 8),
1712
get_sound_freq_scale(bank, soundIndex));
1713
#else
1714
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->reverbVol =
1715
get_sound_reverb(bank, soundIndex, channelIndex);
1716
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume =
1717
get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK2);
1718
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->pan =
1719
get_sound_pan(*sSoundBanks[bank][soundIndex].x,
1720
*sSoundBanks[bank][soundIndex].z);
1721
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->freqScale =
1722
get_sound_freq_scale(bank, soundIndex);
1723
#endif
1724
break;
1725
}
1726
}
1727
}
1728
1729
// Increment to the next channel that this bank owns
1730
channelIndex++;
1731
}
1732
1733
// Increment to the first channel index of the next bank
1734
// (In practice sUsedChannelsForSoundBank[i] = sMaxChannelsForSoundBank[i] = 1, so this
1735
// doesn't do anything)
1736
channelIndex += sMaxChannelsForSoundBank[bank] - sUsedChannelsForSoundBank[bank];
1737
}
1738
}
1739
1740
/**
1741
* Called from threads: thread4_sound, thread5_game_loop
1742
*/
1743
static void seq_player_play_sequence(u8 player, u8 seqId, u16 arg2) {
1744
u8 targetVolume;
1745
u8 i;
1746
1747
if (player == SEQ_PLAYER_LEVEL) {
1748
sCurrentBackgroundMusicSeqId = seqId & SEQ_BASE_ID;
1749
sBackgroundMusicForDynamics = SEQUENCE_NONE;
1750
sCurrentMusicDynamic = 0xff;
1751
sMusicDynamicDelay = 2;
1752
}
1753
1754
for (i = 0; i < CHANNELS_MAX; i++) {
1755
D_80360928[player][i].remainingFrames = 0;
1756
}
1757
1758
#if defined(VERSION_EU) || defined(VERSION_SH)
1759
func_802ad770(0x46000000 | ((u8)(u32) player) << 16, seqId & SEQ_VARIATION);
1760
func_802ad74c(0x82000000 | ((u8)(u32) player) << 16 | ((u8)(seqId & SEQ_BASE_ID)) << 8, arg2);
1761
1762
if (player == SEQ_PLAYER_LEVEL) {
1763
targetVolume = begin_background_music_fade(0);
1764
if (targetVolume != 0xff) {
1765
gSequencePlayers[SEQ_PLAYER_LEVEL].fadeVolumeScale = (f32) targetVolume / US_FLOAT(127.0);
1766
}
1767
}
1768
#else
1769
1770
gSequencePlayers[player].seqVariation = seqId & SEQ_VARIATION;
1771
load_sequence(player, seqId & SEQ_BASE_ID, 0);
1772
1773
if (player == SEQ_PLAYER_LEVEL) {
1774
targetVolume = begin_background_music_fade(0);
1775
if (targetVolume != 0xff) {
1776
gSequencePlayers[SEQ_PLAYER_LEVEL].state = SEQUENCE_PLAYER_STATE_4;
1777
gSequencePlayers[SEQ_PLAYER_LEVEL].fadeVolume = (f32) targetVolume / US_FLOAT(127.0);
1778
}
1779
} else {
1780
func_8031D690(player, arg2);
1781
}
1782
#endif
1783
}
1784
1785
/**
1786
* Called from threads: thread5_game_loop
1787
*/
1788
void seq_player_fade_out(u8 player, u16 fadeDuration) {
1789
#if defined(VERSION_EU) || defined(VERSION_SH)
1790
#ifdef VERSION_EU
1791
u32 fd = fadeDuration;
1792
#else
1793
s32 fd = fadeDuration; // will also match if we change function signature func_802ad74c to use s32 as arg1
1794
#endif
1795
if (!player) {
1796
sCurrentBackgroundMusicSeqId = SEQUENCE_NONE;
1797
}
1798
func_802ad74c(0x83000000 | (player & 0xff) << 16, fd);
1799
#else
1800
if (player == SEQ_PLAYER_LEVEL) {
1801
sCurrentBackgroundMusicSeqId = SEQUENCE_NONE;
1802
}
1803
seq_player_fade_to_zero_volume(player, fadeDuration);
1804
#endif
1805
}
1806
1807
/**
1808
* Called from threads: thread5_game_loop
1809
*/
1810
void fade_volume_scale(u8 player, u8 targetScale, u16 fadeDuration) {
1811
u8 i;
1812
for (i = 0; i < CHANNELS_MAX; i++) {
1813
fade_channel_volume_scale(player, i, targetScale, fadeDuration);
1814
}
1815
}
1816
1817
/**
1818
* Called from threads: thread3_main, thread4_sound, thread5_game_loop
1819
*/
1820
static void fade_channel_volume_scale(u8 player, u8 channelIndex, u8 targetScale, u16 fadeDuration) {
1821
struct ChannelVolumeScaleFade *temp;
1822
1823
if (gSequencePlayers[player].channels[channelIndex] != &gSequenceChannelNone) {
1824
temp = &D_80360928[player][channelIndex];
1825
temp->remainingFrames = fadeDuration;
1826
temp->velocity = ((f32)(targetScale / US_FLOAT(127.0))
1827
- gSequencePlayers[player].channels[channelIndex]->volumeScale)
1828
/ fadeDuration;
1829
temp->target = targetScale;
1830
temp->current = gSequencePlayers[player].channels[channelIndex]->volumeScale;
1831
}
1832
}
1833
1834
/**
1835
* Called from threads: thread4_sound, thread5_game_loop (EU only)
1836
*/
1837
static void func_8031F96C(u8 player) {
1838
u8 i;
1839
1840
// Loop over channels
1841
for (i = 0; i < CHANNELS_MAX; i++) {
1842
if (gSequencePlayers[player].channels[i] != &gSequenceChannelNone
1843
&& D_80360928[player][i].remainingFrames != 0) {
1844
D_80360928[player][i].current += D_80360928[player][i].velocity;
1845
#if defined(VERSION_EU) || defined(VERSION_SH)
1846
func_802ad728(0x01000000 | (player & 0xff) << 16 | (i & 0xff) << 8,
1847
D_80360928[player][i].current);
1848
#else
1849
gSequencePlayers[player].channels[i]->volumeScale = D_80360928[player][i].current;
1850
#endif
1851
D_80360928[player][i].remainingFrames--;
1852
if (D_80360928[player][i].remainingFrames == 0) {
1853
#if defined(VERSION_EU)
1854
func_802ad728(0x01000000 | (player & 0xff) << 16 | (i & 0xff) << 8,
1855
FLOAT_CAST(D_80360928[player][i].target) / 127.0);
1856
#elif defined(VERSION_SH)
1857
func_802ad728(0x01000000 | (player & 0xff) << 16 | (i & 0xff) << 8,
1858
FLOAT_CAST(D_80360928[player][i].target) / 127.0f);
1859
#else
1860
gSequencePlayers[player].channels[i]->volumeScale =
1861
D_80360928[player][i].target / 127.0f;
1862
#endif
1863
}
1864
}
1865
}
1866
}
1867
1868
/**
1869
* Called from threads: thread4_sound, thread5_game_loop (EU only)
1870
*/
1871
void process_level_music_dynamics(void) {
1872
u32 conditionBits;
1873
u16 tempBits;
1874
UNUSED u16 pad;
1875
u8 musicDynIndex;
1876
u8 condIndex;
1877
u8 i;
1878
u8 j;
1879
s16 conditionValues[8];
1880
u8 conditionTypes[8];
1881
s16 dur1;
1882
s16 dur2;
1883
u16 bit;
1884
1885
func_8031F96C(0);
1886
func_8031F96C(2);
1887
func_80320ED8();
1888
if (sMusicDynamicDelay != 0) {
1889
sMusicDynamicDelay--;
1890
} else {
1891
sBackgroundMusicForDynamics = sCurrentBackgroundMusicSeqId;
1892
}
1893
1894
if (sBackgroundMusicForDynamics != sLevelDynamics[gCurrLevelNum][0]) {
1895
return;
1896
}
1897
1898
conditionBits = sLevelDynamics[gCurrLevelNum][1] & 0xff00;
1899
musicDynIndex = (u8) sLevelDynamics[gCurrLevelNum][1] & 0xff;
1900
i = 2;
1901
while (conditionBits & 0xff00) {
1902
j = 0;
1903
condIndex = 0;
1904
bit = 0x8000;
1905
while (j < 8) {
1906
if (conditionBits & bit) {
1907
conditionValues[condIndex] = sLevelDynamics[gCurrLevelNum][i++];
1908
conditionTypes[condIndex] = j;
1909
condIndex++;
1910
}
1911
1912
j++;
1913
bit = bit >> 1;
1914
}
1915
1916
for (j = 0; j < condIndex; j++) {
1917
switch (conditionTypes[j]) {
1918
case MARIO_X_GE: {
1919
if (((s16) gMarioStates[0].pos[0]) < conditionValues[j]) {
1920
j = condIndex + 1;
1921
}
1922
break;
1923
}
1924
case MARIO_Y_GE: {
1925
if (((s16) gMarioStates[0].pos[1]) < conditionValues[j]) {
1926
j = condIndex + 1;
1927
}
1928
break;
1929
}
1930
case MARIO_Z_GE: {
1931
if (((s16) gMarioStates[0].pos[2]) < conditionValues[j]) {
1932
j = condIndex + 1;
1933
}
1934
break;
1935
}
1936
case MARIO_X_LT: {
1937
if (((s16) gMarioStates[0].pos[0]) >= conditionValues[j]) {
1938
j = condIndex + 1;
1939
}
1940
break;
1941
}
1942
case MARIO_Y_LT: {
1943
if (((s16) gMarioStates[0].pos[1]) >= conditionValues[j]) {
1944
j = condIndex + 1;
1945
}
1946
break;
1947
}
1948
case MARIO_Z_LT: {
1949
if (((s16) gMarioStates[0].pos[2]) >= conditionValues[j]) {
1950
j = condIndex + 1;
1951
}
1952
break;
1953
}
1954
case MARIO_IS_IN_AREA: {
1955
if (gCurrAreaIndex != conditionValues[j]) {
1956
j = condIndex + 1;
1957
}
1958
break;
1959
}
1960
case MARIO_IS_IN_ROOM: {
1961
if (gMarioCurrentRoom != conditionValues[j]) {
1962
j = condIndex + 1;
1963
}
1964
break;
1965
}
1966
}
1967
}
1968
1969
if (j == condIndex) {
1970
// The area matches. Break out of the loop.
1971
tempBits = 0;
1972
} else {
1973
tempBits = sLevelDynamics[gCurrLevelNum][i] & 0xff00;
1974
musicDynIndex = sLevelDynamics[gCurrLevelNum][i] & 0xff;
1975
i++;
1976
}
1977
1978
conditionBits = tempBits;
1979
}
1980
1981
if (sCurrentMusicDynamic != musicDynIndex) {
1982
tempBits = 1;
1983
if (sCurrentMusicDynamic == 0xff) {
1984
dur1 = 1;
1985
dur2 = 1;
1986
} else {
1987
dur1 = sMusicDynamics[musicDynIndex].dur1;
1988
dur2 = sMusicDynamics[musicDynIndex].dur2;
1989
}
1990
1991
for (i = 0; i < CHANNELS_MAX; i++) {
1992
conditionBits = tempBits;
1993
tempBits = 0;
1994
if (sMusicDynamics[musicDynIndex].bits1 & conditionBits) {
1995
fade_channel_volume_scale(SEQ_PLAYER_LEVEL, i, sMusicDynamics[musicDynIndex].volScale1,
1996
dur1);
1997
}
1998
if (sMusicDynamics[musicDynIndex].bits2 & conditionBits) {
1999
fade_channel_volume_scale(SEQ_PLAYER_LEVEL, i, sMusicDynamics[musicDynIndex].volScale2,
2000
dur2);
2001
}
2002
tempBits = conditionBits << 1;
2003
}
2004
2005
sCurrentMusicDynamic = musicDynIndex;
2006
}
2007
}
2008
2009
void unused_8031FED0(u8 player, u32 bits, s8 arg2) {
2010
u8 i;
2011
2012
if (arg2 < 0) {
2013
arg2 = -arg2;
2014
}
2015
2016
for (i = 0; i < CHANNELS_MAX; i++) {
2017
if (gSequencePlayers[player].channels[i] != &gSequenceChannelNone) {
2018
if ((bits & 3) == 0) {
2019
gSequencePlayers[player].channels[i]->volumeScale = 1.0f;
2020
} else if ((bits & 1) != 0) {
2021
gSequencePlayers[player].channels[i]->volumeScale = (f32) arg2 / US_FLOAT(127.0);
2022
} else {
2023
gSequencePlayers[player].channels[i]->volumeScale =
2024
US_FLOAT(1.0) - (f32) arg2 / US_FLOAT(127.0);
2025
}
2026
}
2027
bits >>= 2;
2028
}
2029
}
2030
2031
/**
2032
* Lower a sequence player's volume over fadeDuration frames.
2033
* If player is SEQ_PLAYER_LEVEL (background music), the given percentage is ignored
2034
* and a max target volume of 40 is used.
2035
*
2036
* Called from threads: thread5_game_loop
2037
*/
2038
void seq_player_lower_volume(u8 player, u16 fadeDuration, u8 percentage) {
2039
if (player == SEQ_PLAYER_LEVEL) {
2040
sLowerBackgroundMusicVolume = TRUE;
2041
begin_background_music_fade(fadeDuration);
2042
} else if (gSequencePlayers[player].enabled == TRUE) {
2043
seq_player_fade_to_percentage_of_volume(player, fadeDuration, percentage);
2044
}
2045
}
2046
2047
/**
2048
* Remove the lowered volume constraint set by seq_player_lower_volume.
2049
* If player is SEQ_PLAYER_LEVEL (background music), the music won't necessarily
2050
* raise back to normal volume if other constraints have been set, e.g.
2051
* sBackgroundMusicTargetVolume.
2052
*
2053
* Called from threads: thread5_game_loop
2054
*/
2055
void seq_player_unlower_volume(u8 player, u16 fadeDuration) {
2056
sLowerBackgroundMusicVolume = FALSE;
2057
if (player == SEQ_PLAYER_LEVEL) {
2058
if (gSequencePlayers[player].state != SEQUENCE_PLAYER_STATE_FADE_OUT) {
2059
begin_background_music_fade(fadeDuration);
2060
}
2061
} else {
2062
if (gSequencePlayers[player].enabled == TRUE) {
2063
seq_player_fade_to_normal_volume(player, fadeDuration);
2064
}
2065
}
2066
}
2067
2068
/**
2069
* Begin a volume fade to adjust the background music to the correct volume.
2070
* The target volume is determined by global variables like sBackgroundMusicTargetVolume
2071
* and sLowerBackgroundMusicVolume.
2072
* If none of the relevant global variables are set, then the default background music
2073
* volume for the sequence is used.
2074
*
2075
* Called from threads: thread3_main, thread4_sound, thread5_game_loop
2076
*/
2077
static u8 begin_background_music_fade(u16 fadeDuration) {
2078
u8 targetVolume = 0xff;
2079
2080
if (sCurrentBackgroundMusicSeqId == SEQUENCE_NONE
2081
|| sCurrentBackgroundMusicSeqId == SEQ_EVENT_CUTSCENE_CREDITS) {
2082
return 0xff;
2083
}
2084
2085
if (gSequencePlayers[SEQ_PLAYER_LEVEL].volume == 0.0f && fadeDuration) {
2086
gSequencePlayers[SEQ_PLAYER_LEVEL].volume = gSequencePlayers[SEQ_PLAYER_LEVEL].fadeVolume;
2087
}
2088
2089
if (sBackgroundMusicTargetVolume != TARGET_VOLUME_UNSET) {
2090
targetVolume = (sBackgroundMusicTargetVolume & TARGET_VOLUME_VALUE_MASK);
2091
}
2092
2093
if (sBackgroundMusicMaxTargetVolume != TARGET_VOLUME_UNSET) {
2094
u8 maxTargetVolume = (sBackgroundMusicMaxTargetVolume & TARGET_VOLUME_VALUE_MASK);
2095
if (targetVolume > maxTargetVolume) {
2096
targetVolume = maxTargetVolume;
2097
}
2098
}
2099
2100
if (sLowerBackgroundMusicVolume && targetVolume > 40) {
2101
targetVolume = 40;
2102
}
2103
2104
if (sSoundBanksThatLowerBackgroundMusic != 0 && targetVolume > 20) {
2105
targetVolume = 20;
2106
}
2107
2108
if (gSequencePlayers[SEQ_PLAYER_LEVEL].enabled == TRUE) {
2109
if (targetVolume != 0xff) {
2110
seq_player_fade_to_target_volume(SEQ_PLAYER_LEVEL, fadeDuration, targetVolume);
2111
} else {
2112
#if defined(VERSION_JP) || defined(VERSION_US)
2113
gSequencePlayers[SEQ_PLAYER_LEVEL].volume =
2114
sBackgroundMusicDefaultVolume[sCurrentBackgroundMusicSeqId] / 127.0f;
2115
#endif
2116
seq_player_fade_to_normal_volume(SEQ_PLAYER_LEVEL, fadeDuration);
2117
}
2118
}
2119
2120
return targetVolume;
2121
}
2122
2123
/**
2124
* Called from threads: thread5_game_loop
2125
*/
2126
void set_audio_muted(u8 muted) {
2127
u8 i;
2128
2129
for (i = 0; i < SEQUENCE_PLAYERS; i++) {
2130
#if defined(VERSION_EU) || defined(VERSION_SH)
2131
if (muted)
2132
func_802ad74c(0xf1000000, 0);
2133
else
2134
func_802ad74c(0xf2000000, 0);
2135
#else
2136
gSequencePlayers[i].muted = muted;
2137
#endif
2138
}
2139
}
2140
2141
/**
2142
* Called from threads: thread4_sound
2143
*/
2144
void sound_init(void) {
2145
u8 i;
2146
u8 j;
2147
2148
for (i = 0; i < SOUND_BANK_COUNT; i++) {
2149
// Set each sound in the bank to STOPPED
2150
for (j = 0; j < 40; j++) {
2151
sSoundBanks[i][j].soundStatus = SOUND_STATUS_STOPPED;
2152
}
2153
2154
// Remove current sounds
2155
for (j = 0; j < MAX_CHANNELS_PER_SOUND_BANK; j++) {
2156
sCurrentSound[i][j] = 0xff;
2157
}
2158
2159
sSoundBankUsedListBack[i] = 0;
2160
sSoundBankFreeListFront[i] = 1;
2161
sNumSoundsInBank[i] = 0;
2162
}
2163
2164
for (i = 0; i < SOUND_BANK_COUNT; i++) {
2165
// Set used list to empty
2166
sSoundBanks[i][0].prev = 0xff;
2167
sSoundBanks[i][0].next = 0xff;
2168
2169
// Set free list to contain every sound slot
2170
for (j = 1; j < 40 - 1; j++) {
2171
sSoundBanks[i][j].prev = j - 1;
2172
sSoundBanks[i][j].next = j + 1;
2173
}
2174
sSoundBanks[i][j].prev = j - 1;
2175
sSoundBanks[i][j].next = 0xff;
2176
}
2177
2178
for (j = 0; j < 3; j++) {
2179
for (i = 0; i < CHANNELS_MAX; i++) {
2180
D_80360928[j][i].remainingFrames = 0;
2181
}
2182
}
2183
2184
for (i = 0; i < MAX_BACKGROUND_MUSIC_QUEUE_SIZE; i++) {
2185
sBackgroundMusicQueue[i].priority = 0;
2186
}
2187
2188
sound_banks_enable(SEQ_PLAYER_SFX, SOUND_BANKS_ALL_BITS);
2189
2190
sUnused80332118 = 0;
2191
sBackgroundMusicTargetVolume = TARGET_VOLUME_UNSET;
2192
sLowerBackgroundMusicVolume = FALSE;
2193
sSoundBanksThatLowerBackgroundMusic = 0;
2194
sUnused80332114 = 0;
2195
sCurrentBackgroundMusicSeqId = 0xff;
2196
gSoundMode = SOUND_MODE_STEREO;
2197
sBackgroundMusicQueueSize = 0;
2198
sBackgroundMusicMaxTargetVolume = TARGET_VOLUME_UNSET;
2199
D_80332120 = 0;
2200
D_80332124 = 0;
2201
sNumProcessedSoundRequests = 0;
2202
sSoundRequestCount = 0;
2203
}
2204
2205
// (unused)
2206
void get_currently_playing_sound(u8 bank, u8 *numPlayingSounds, u8 *numSoundsInBank, u8 *soundId) {
2207
u8 i;
2208
u8 count = 0;
2209
2210
for (i = 0; i < sMaxChannelsForSoundBank[bank]; i++) {
2211
if (sCurrentSound[bank][i] != 0xff) {
2212
count++;
2213
}
2214
}
2215
*numPlayingSounds = count;
2216
2217
*numSoundsInBank = sNumSoundsInBank[bank];
2218
2219
if (sCurrentSound[bank][0] != 0xff) {
2220
*soundId = (u8)(sSoundBanks[bank][sCurrentSound[bank][0]].soundBits >> SOUNDARGS_SHIFT_SOUNDID);
2221
} else {
2222
*soundId = 0xff;
2223
}
2224
}
2225
2226
/**
2227
* Called from threads: thread5_game_loop
2228
*/
2229
void stop_sound(u32 soundBits, f32 *pos) {
2230
u8 bank = (soundBits & SOUNDARGS_MASK_BANK) >> SOUNDARGS_SHIFT_BANK;
2231
u8 soundIndex = sSoundBanks[bank][0].next;
2232
2233
while (soundIndex != 0xff) {
2234
// If sound has same id and source position pointer
2235
if ((u16)(soundBits >> SOUNDARGS_SHIFT_SOUNDID)
2236
== (u16)(sSoundBanks[bank][soundIndex].soundBits >> SOUNDARGS_SHIFT_SOUNDID)
2237
&& sSoundBanks[bank][soundIndex].x == pos) {
2238
2239
// Mark sound for deletion
2240
update_background_music_after_sound(bank, soundIndex);
2241
sSoundBanks[bank][soundIndex].soundBits = NO_SOUND;
2242
soundIndex = 0xff; // break
2243
} else {
2244
soundIndex = sSoundBanks[bank][soundIndex].next;
2245
}
2246
}
2247
}
2248
2249
/**
2250
* Called from threads: thread5_game_loop
2251
*/
2252
void stop_sounds_from_source(f32 *pos) {
2253
u8 bank;
2254
u8 soundIndex;
2255
2256
for (bank = 0; bank < SOUND_BANK_COUNT; bank++) {
2257
soundIndex = sSoundBanks[bank][0].next;
2258
while (soundIndex != 0xff) {
2259
if (sSoundBanks[bank][soundIndex].x == pos) {
2260
update_background_music_after_sound(bank, soundIndex);
2261
sSoundBanks[bank][soundIndex].soundBits = NO_SOUND;
2262
}
2263
soundIndex = sSoundBanks[bank][soundIndex].next;
2264
}
2265
}
2266
}
2267
2268
/**
2269
* Called from threads: thread3_main, thread5_game_loop
2270
*/
2271
static void stop_sounds_in_bank(u8 bank) {
2272
u8 soundIndex = sSoundBanks[bank][0].next;
2273
2274
while (soundIndex != 0xff) {
2275
update_background_music_after_sound(bank, soundIndex);
2276
sSoundBanks[bank][soundIndex].soundBits = NO_SOUND;
2277
soundIndex = sSoundBanks[bank][soundIndex].next;
2278
}
2279
}
2280
2281
/**
2282
* Stops sounds in all of the sound banks that predominantly consist of continuous
2283
* sounds. Misses some specific continuous sounds in other banks like bird chirping
2284
* and the ticking sound after pressing a switch.
2285
*
2286
* Called from threads: thread3_main, thread5_game_loop
2287
*/
2288
void stop_sounds_in_continuous_banks(void) {
2289
stop_sounds_in_bank(SOUND_BANK_MOVING);
2290
stop_sounds_in_bank(SOUND_BANK_ENV);
2291
stop_sounds_in_bank(SOUND_BANK_AIR);
2292
}
2293
2294
/**
2295
* Called from threads: thread3_main, thread5_game_loop
2296
*/
2297
void sound_banks_disable(UNUSED u8 player, u16 bankMask) {
2298
u8 i;
2299
2300
for (i = 0; i < SOUND_BANK_COUNT; i++) {
2301
if (bankMask & 1) {
2302
sSoundBankDisabled[i] = TRUE;
2303
}
2304
bankMask = bankMask >> 1;
2305
}
2306
}
2307
2308
/**
2309
* Called from threads: thread5_game_loop
2310
*/
2311
static void disable_all_sequence_players(void) {
2312
u8 i;
2313
2314
for (i = 0; i < SEQUENCE_PLAYERS; i++) {
2315
sequence_player_disable(&gSequencePlayers[i]);
2316
}
2317
}
2318
2319
/**
2320
* Called from threads: thread5_game_loop
2321
*/
2322
void sound_banks_enable(UNUSED u8 player, u16 bankMask) {
2323
u8 i;
2324
2325
for (i = 0; i < SOUND_BANK_COUNT; i++) {
2326
if (bankMask & 1) {
2327
sSoundBankDisabled[i] = FALSE;
2328
}
2329
bankMask = bankMask >> 1;
2330
}
2331
}
2332
2333
u8 unused_803209D8(u8 player, u8 channelIndex, u8 arg2) {
2334
u8 ret = 0;
2335
if (gSequencePlayers[player].channels[channelIndex] != &gSequenceChannelNone) {
2336
gSequencePlayers[player].channels[channelIndex]->stopSomething2 = arg2;
2337
ret = arg2;
2338
}
2339
return ret;
2340
}
2341
2342
/**
2343
* Set the moving speed for a sound bank, which may affect the volume and pitch
2344
* of the sound.
2345
*
2346
* Called from threads: thread5_game_loop
2347
*/
2348
void set_sound_moving_speed(u8 bank, u8 speed) {
2349
sSoundMovingSpeed[bank] = speed;
2350
}
2351
2352
/**
2353
* Called from threads: thread5_game_loop
2354
*/
2355
void play_dialog_sound(u8 dialogID) {
2356
u8 speaker;
2357
2358
if (dialogID >= DIALOG_COUNT) {
2359
dialogID = 0;
2360
}
2361
2362
speaker = sDialogSpeaker[dialogID];
2363
if (speaker != 0xff) {
2364
play_sound(sDialogSpeakerVoice[speaker], gGlobalSoundSource);
2365
2366
// Play music during bowser message that appears when first entering the
2367
// castle or when trying to enter a door without enough stars
2368
if (speaker == BOWS1) {
2369
seq_player_play_sequence(SEQ_PLAYER_ENV, SEQ_EVENT_KOOPA_MESSAGE, 0);
2370
}
2371
}
2372
2373
#ifndef VERSION_JP
2374
// "You've stepped on the (Wing|Metal|Vanish) Cap Switch"
2375
if (dialogID == DIALOG_010 || dialogID == DIALOG_011 || dialogID == DIALOG_012) {
2376
play_puzzle_jingle();
2377
}
2378
#endif
2379
}
2380
2381
/**
2382
* Called from threads: thread5_game_loop
2383
*/
2384
void play_music(u8 player, u16 seqArgs, u16 fadeTimer) {
2385
u8 seqId = seqArgs & 0xff;
2386
u8 priority = seqArgs >> 8;
2387
u8 i;
2388
u8 foundIndex = 0;
2389
2390
// Except for the background music player, we don't support queued
2391
// sequences. Just play them immediately, stopping any old sequence.
2392
if (player != SEQ_PLAYER_LEVEL) {
2393
seq_player_play_sequence(player, seqId, fadeTimer);
2394
return;
2395
}
2396
2397
// Abort if the queue is already full.
2398
if (sBackgroundMusicQueueSize == MAX_BACKGROUND_MUSIC_QUEUE_SIZE) {
2399
return;
2400
}
2401
2402
// If already in the queue, abort, after first restarting the sequence if
2403
// it is first, and handling disabled music somehow.
2404
// (That handling probably ought to occur even when the queue is full...)
2405
for (i = 0; i < sBackgroundMusicQueueSize; i++) {
2406
if (sBackgroundMusicQueue[i].seqId == seqId) {
2407
if (i == 0) {
2408
seq_player_play_sequence(SEQ_PLAYER_LEVEL, seqId, fadeTimer);
2409
} else if (!gSequencePlayers[SEQ_PLAYER_LEVEL].enabled) {
2410
stop_background_music(sBackgroundMusicQueue[0].seqId);
2411
}
2412
return;
2413
}
2414
}
2415
2416
// Find the next sequence slot by priority.
2417
for (i = 0; i < sBackgroundMusicQueueSize; i++) {
2418
if (sBackgroundMusicQueue[i].priority <= priority) {
2419
foundIndex = i;
2420
i = sBackgroundMusicQueueSize; // break
2421
}
2422
}
2423
2424
// If the sequence ends up first in the queue, start it, and make space for
2425
// one more entry in the queue.
2426
if (foundIndex == 0) {
2427
seq_player_play_sequence(SEQ_PLAYER_LEVEL, seqId, fadeTimer);
2428
sBackgroundMusicQueueSize++;
2429
}
2430
2431
// Move all items up in queue, throwing away the last one if we didn't put
2432
// the new sequence first.
2433
for (i = sBackgroundMusicQueueSize - 1; i > foundIndex; i--) {
2434
sBackgroundMusicQueue[i].priority = sBackgroundMusicQueue[i - 1].priority;
2435
sBackgroundMusicQueue[i].seqId = sBackgroundMusicQueue[i - 1].seqId;
2436
}
2437
2438
// Insert item into queue.
2439
sBackgroundMusicQueue[foundIndex].priority = priority;
2440
sBackgroundMusicQueue[foundIndex].seqId = seqId;
2441
}
2442
2443
/**
2444
* Called from threads: thread5_game_loop
2445
*/
2446
void stop_background_music(u16 seqId) {
2447
u8 foundIndex;
2448
u8 i;
2449
2450
if (sBackgroundMusicQueueSize == 0) {
2451
return;
2452
}
2453
2454
// If sequence is not found, remove an empty queue item (the next empty
2455
// queue slot).
2456
foundIndex = sBackgroundMusicQueueSize;
2457
2458
// Search for the sequence.
2459
for (i = 0; i < sBackgroundMusicQueueSize; i++) {
2460
if (sBackgroundMusicQueue[i].seqId == (u8)(seqId & 0xff)) {
2461
// Remove sequence from queue. If it was first, play the next one,
2462
// or fade out the music.
2463
sBackgroundMusicQueueSize--;
2464
if (i == 0) {
2465
if (sBackgroundMusicQueueSize != 0) {
2466
seq_player_play_sequence(SEQ_PLAYER_LEVEL, sBackgroundMusicQueue[1].seqId, 0);
2467
} else {
2468
seq_player_fade_out(SEQ_PLAYER_LEVEL, 20);
2469
}
2470
}
2471
foundIndex = i;
2472
i = sBackgroundMusicQueueSize; // "break;"
2473
}
2474
}
2475
2476
// Move later slots down.
2477
for (i = foundIndex; i < sBackgroundMusicQueueSize; i++) {
2478
sBackgroundMusicQueue[i].priority = sBackgroundMusicQueue[i + 1].priority;
2479
sBackgroundMusicQueue[i].seqId = sBackgroundMusicQueue[i + 1].seqId;
2480
}
2481
2482
// @bug? If the sequence queue is full and we attempt to stop a sequence
2483
// that isn't in the queue, this writes out of bounds. Can that happen?
2484
sBackgroundMusicQueue[i].priority = 0;
2485
}
2486
2487
/**
2488
* Called from threads: thread5_game_loop
2489
*/
2490
void fadeout_background_music(u16 seqId, u16 fadeOut) {
2491
if (sBackgroundMusicQueueSize != 0 && sBackgroundMusicQueue[0].seqId == (u8)(seqId & 0xff)) {
2492
seq_player_fade_out(SEQ_PLAYER_LEVEL, fadeOut);
2493
}
2494
}
2495
2496
/**
2497
* Called from threads: thread5_game_loop
2498
*/
2499
void drop_queued_background_music(void) {
2500
if (sBackgroundMusicQueueSize != 0) {
2501
sBackgroundMusicQueueSize = 1;
2502
}
2503
}
2504
2505
/**
2506
* Called from threads: thread5_game_loop
2507
*/
2508
u16 get_current_background_music(void) {
2509
if (sBackgroundMusicQueueSize != 0) {
2510
return (sBackgroundMusicQueue[0].priority << 8) + sBackgroundMusicQueue[0].seqId;
2511
}
2512
return -1;
2513
}
2514
2515
/**
2516
* Called from threads: thread4_sound, thread5_game_loop (EU only)
2517
*/
2518
void func_80320ED8(void) {
2519
#if defined(VERSION_EU) || defined(VERSION_SH)
2520
if (D_EU_80300558 != 0) {
2521
D_EU_80300558--;
2522
}
2523
2524
if (gSequencePlayers[SEQ_PLAYER_ENV].enabled
2525
|| sBackgroundMusicMaxTargetVolume == TARGET_VOLUME_UNSET || D_EU_80300558 != 0) {
2526
#else
2527
if (gSequencePlayers[SEQ_PLAYER_ENV].enabled
2528
|| sBackgroundMusicMaxTargetVolume == TARGET_VOLUME_UNSET) {
2529
#endif
2530
return;
2531
}
2532
2533
sBackgroundMusicMaxTargetVolume = TARGET_VOLUME_UNSET;
2534
begin_background_music_fade(50);
2535
2536
if (sBackgroundMusicTargetVolume != TARGET_VOLUME_UNSET
2537
&& (D_80332120 == SEQ_EVENT_MERRY_GO_ROUND || D_80332120 == SEQ_EVENT_PIRANHA_PLANT)) {
2538
seq_player_play_sequence(SEQ_PLAYER_ENV, D_80332120, 1);
2539
if (D_80332124 != 0xff) {
2540
seq_player_fade_to_target_volume(SEQ_PLAYER_ENV, 1, D_80332124);
2541
}
2542
}
2543
}
2544
2545
/**
2546
* Called from threads: thread5_game_loop
2547
*/
2548
void play_secondary_music(u8 seqId, u8 bgMusicVolume, u8 volume, u16 fadeTimer) {
2549
UNUSED u32 dummy;
2550
2551
sUnused80332118 = 0;
2552
if (sCurrentBackgroundMusicSeqId == 0xff || sCurrentBackgroundMusicSeqId == SEQ_MENU_TITLE_SCREEN) {
2553
return;
2554
}
2555
2556
if (sBackgroundMusicTargetVolume == TARGET_VOLUME_UNSET) {
2557
sBackgroundMusicTargetVolume = bgMusicVolume + TARGET_VOLUME_IS_PRESENT_FLAG;
2558
begin_background_music_fade(fadeTimer);
2559
seq_player_play_sequence(SEQ_PLAYER_ENV, seqId, fadeTimer >> 1);
2560
if (volume < 0x80) {
2561
seq_player_fade_to_target_volume(SEQ_PLAYER_ENV, fadeTimer, volume);
2562
}
2563
D_80332124 = volume;
2564
D_80332120 = seqId;
2565
} else if (volume != 0xff) {
2566
sBackgroundMusicTargetVolume = bgMusicVolume + TARGET_VOLUME_IS_PRESENT_FLAG;
2567
begin_background_music_fade(fadeTimer);
2568
seq_player_fade_to_target_volume(SEQ_PLAYER_ENV, fadeTimer, volume);
2569
D_80332124 = volume;
2570
}
2571
}
2572
2573
/**
2574
* Called from threads: thread5_game_loop
2575
*/
2576
void func_80321080(u16 fadeTimer) {
2577
if (sBackgroundMusicTargetVolume != TARGET_VOLUME_UNSET) {
2578
sBackgroundMusicTargetVolume = TARGET_VOLUME_UNSET;
2579
D_80332120 = 0;
2580
D_80332124 = 0;
2581
begin_background_music_fade(fadeTimer);
2582
seq_player_fade_out(SEQ_PLAYER_ENV, fadeTimer);
2583
}
2584
}
2585
2586
/**
2587
* Called from threads: thread3_main, thread5_game_loop
2588
*/
2589
void func_803210D4(u16 fadeDuration) {
2590
u8 i;
2591
2592
if (sHasStartedFadeOut) {
2593
return;
2594
}
2595
2596
if (gSequencePlayers[SEQ_PLAYER_LEVEL].enabled == TRUE) {
2597
#if defined(VERSION_EU) || defined(VERSION_SH)
2598
func_802ad74c(0x83000000, fadeDuration);
2599
#else
2600
seq_player_fade_to_zero_volume(SEQ_PLAYER_LEVEL, fadeDuration);
2601
#endif
2602
}
2603
2604
if (gSequencePlayers[SEQ_PLAYER_ENV].enabled == TRUE) {
2605
#if defined(VERSION_EU) || defined(VERSION_SH)
2606
func_802ad74c(0x83010000, fadeDuration);
2607
#else
2608
seq_player_fade_to_zero_volume(SEQ_PLAYER_ENV, fadeDuration);
2609
#endif
2610
}
2611
2612
for (i = 0; i < SOUND_BANK_COUNT; i++) {
2613
if (i != SOUND_BANK_MENU) {
2614
fade_channel_volume_scale(SEQ_PLAYER_SFX, i, 0, fadeDuration / 16);
2615
}
2616
}
2617
2618
sHasStartedFadeOut = TRUE;
2619
}
2620
2621
/**
2622
* Called from threads: thread5_game_loop
2623
*/
2624
void play_course_clear(void) {
2625
seq_player_play_sequence(SEQ_PLAYER_ENV, SEQ_EVENT_CUTSCENE_COLLECT_STAR, 0);
2626
sBackgroundMusicMaxTargetVolume = TARGET_VOLUME_IS_PRESENT_FLAG | 0;
2627
#if defined(VERSION_EU) || defined(VERSION_SH)
2628
D_EU_80300558 = 2;
2629
#endif
2630
begin_background_music_fade(50);
2631
}
2632
2633
/**
2634
* Called from threads: thread5_game_loop
2635
*/
2636
void play_peachs_jingle(void) {
2637
seq_player_play_sequence(SEQ_PLAYER_ENV, SEQ_EVENT_PEACH_MESSAGE, 0);
2638
sBackgroundMusicMaxTargetVolume = TARGET_VOLUME_IS_PRESENT_FLAG | 0;
2639
#if defined(VERSION_EU) || defined(VERSION_SH)
2640
D_EU_80300558 = 2;
2641
#endif
2642
begin_background_music_fade(50);
2643
}
2644
2645
/**
2646
* Plays the puzzle jingle. Plays the dadada dadada *dadada* jingle
2647
* that usually plays when you solve a "puzzle", like chests, talking to
2648
* yoshi, releasing chain chomp, opening the pyramid top, etc.
2649
*
2650
* Called from threads: thread5_game_loop
2651
*/
2652
void play_puzzle_jingle(void) {
2653
seq_player_play_sequence(SEQ_PLAYER_ENV, SEQ_EVENT_SOLVE_PUZZLE, 0);
2654
sBackgroundMusicMaxTargetVolume = TARGET_VOLUME_IS_PRESENT_FLAG | 20;
2655
#if defined(VERSION_EU) || defined(VERSION_SH)
2656
D_EU_80300558 = 2;
2657
#endif
2658
begin_background_music_fade(50);
2659
}
2660
2661
/**
2662
* Called from threads: thread5_game_loop
2663
*/
2664
void play_star_fanfare(void) {
2665
seq_player_play_sequence(SEQ_PLAYER_ENV, SEQ_EVENT_HIGH_SCORE, 0);
2666
sBackgroundMusicMaxTargetVolume = TARGET_VOLUME_IS_PRESENT_FLAG | 20;
2667
#if defined(VERSION_EU) || defined(VERSION_SH)
2668
D_EU_80300558 = 2;
2669
#endif
2670
begin_background_music_fade(50);
2671
}
2672
2673
/**
2674
* Called from threads: thread5_game_loop
2675
*/
2676
void play_power_star_jingle(u8 arg0) {
2677
if (!arg0) {
2678
sBackgroundMusicTargetVolume = 0;
2679
}
2680
seq_player_play_sequence(SEQ_PLAYER_ENV, SEQ_EVENT_CUTSCENE_STAR_SPAWN, 0);
2681
sBackgroundMusicMaxTargetVolume = TARGET_VOLUME_IS_PRESENT_FLAG | 20;
2682
#if defined(VERSION_EU) || defined(VERSION_SH)
2683
D_EU_80300558 = 2;
2684
#endif
2685
begin_background_music_fade(50);
2686
}
2687
2688
/**
2689
* Called from threads: thread5_game_loop
2690
*/
2691
void play_race_fanfare(void) {
2692
seq_player_play_sequence(SEQ_PLAYER_ENV, SEQ_EVENT_RACE, 0);
2693
sBackgroundMusicMaxTargetVolume = TARGET_VOLUME_IS_PRESENT_FLAG | 20;
2694
#if defined(VERSION_EU) || defined(VERSION_SH)
2695
D_EU_80300558 = 2;
2696
#endif
2697
begin_background_music_fade(50);
2698
}
2699
2700
/**
2701
* Called from threads: thread5_game_loop
2702
*/
2703
void play_toads_jingle(void) {
2704
seq_player_play_sequence(SEQ_PLAYER_ENV, SEQ_EVENT_TOAD_MESSAGE, 0);
2705
sBackgroundMusicMaxTargetVolume = TARGET_VOLUME_IS_PRESENT_FLAG | 20;
2706
#if defined(VERSION_EU) || defined(VERSION_SH)
2707
D_EU_80300558 = 2;
2708
#endif
2709
begin_background_music_fade(50);
2710
}
2711
2712
/**
2713
* Called from threads: thread5_game_loop
2714
*/
2715
void sound_reset(u8 presetId) {
2716
#ifndef VERSION_JP
2717
if (presetId >= 8) {
2718
presetId = 0;
2719
sUnused8033323C = 0;
2720
}
2721
#endif
2722
sGameLoopTicked = 0;
2723
disable_all_sequence_players();
2724
sound_init();
2725
#ifdef VERSION_SH
2726
func_802ad74c(0xF2000000, 0);
2727
#endif
2728
#if defined(VERSION_JP) || defined(VERSION_US)
2729
audio_reset_session(&gAudioSessionPresets[presetId]);
2730
#else
2731
audio_reset_session_eu(presetId);
2732
#endif
2733
osWritebackDCacheAll();
2734
if (presetId != 7) {
2735
preload_sequence(SEQ_EVENT_SOLVE_PUZZLE, PRELOAD_BANKS | PRELOAD_SEQUENCE);
2736
preload_sequence(SEQ_EVENT_PEACH_MESSAGE, PRELOAD_BANKS | PRELOAD_SEQUENCE);
2737
preload_sequence(SEQ_EVENT_CUTSCENE_STAR_SPAWN, PRELOAD_BANKS | PRELOAD_SEQUENCE);
2738
}
2739
seq_player_play_sequence(SEQ_PLAYER_SFX, SEQ_SOUND_PLAYER, 0);
2740
D_80332108 = (D_80332108 & 0xf0) + presetId;
2741
gSoundMode = D_80332108 >> 4;
2742
sHasStartedFadeOut = FALSE;
2743
}
2744
2745
/**
2746
* Called from threads: thread5_game_loop
2747
*/
2748
void audio_set_sound_mode(u8 soundMode) {
2749
D_80332108 = (D_80332108 & 0xf) + (soundMode << 4);
2750
gSoundMode = soundMode;
2751
}
2752
2753
#if defined(VERSION_JP) || defined(VERSION_US)
2754
void unused_80321460(UNUSED s32 arg0, UNUSED s32 arg1, UNUSED s32 arg2, UNUSED s32 arg3) {
2755
}
2756
2757
void unused_80321474(UNUSED s32 arg0) {
2758
}
2759
#endif
2760