Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
sfx_player.c
Go to the documentation of this file.
1#include "audio.h"
2#include "audio/core.h"
3
4static void au_sfx_play_sound(SoundManager* manager, SoundPlayer* player, s8* readPos, SoundRequest* request, s32 priority, s32 exclusiveID);
5static void au_sfx_set_triggers(SoundManager* manager, u32 soundID);
6static void au_sfx_stop_by_id(SoundManager* manager, u32 soundID);
7static void au_sfx_stop_by_exlusive_id(SoundManager* manager, u32 soundID);
8static void au_sfx_set_modifiers(SoundManager* manager, SoundRequest* request);
9static void au_sfx_set_player_modifiers(SoundPlayer* player, SoundRequest* request);
10
11static void au_sfx_update_basic(SoundManager* manager, SoundPlayer* player, AuVoice* arg2, u8 arg3);
12static s16 au_sfx_get_scaled_volume(SoundManager* manager, SoundPlayer* player);
13static void au_sfx_update_sequence(SoundManager* manager, SoundPlayer* player, AuVoice* arg2, u8 arg3);
14static void au_sfx_set_voice_volume(AuVoice* voice, SoundManager* manager, SoundPlayer* player);
15static u8 au_sfx_get_random_pan(s32 arg0, s32 arg1, s32 arg2);
16static s32 au_sfx_get_random_pitch(s32 arg0, s32 arg1, s32 arg2);
17static u8 au_sfx_get_random_vol(s32 arg0, s32 arg1, s32 arg2);
18static void au_sfx_reset_players(SoundManager* manager);
19
20static void au_SEFCmd_00_SetVolume(SoundManager* manager, SoundPlayer* player);
21static void au_SEFCmd_01_SetPan(SoundManager* manager, SoundPlayer* player);
22static void au_SEFCmd_02_SetInstrument(SoundManager* manager, SoundPlayer* player);
23static void au_SEFCmd_03_SetReverb(SoundManager* manager, SoundPlayer* player);
24static void au_SEFCmd_04_SetEnvelope(SoundManager* manager, SoundPlayer* player);
25static void au_SEFCmd_05_CoarseTune(SoundManager* manager, SoundPlayer* player);
26static void au_SEFCmd_06_FineTune(SoundManager* manager, SoundPlayer* player);
27static void au_SEFCmd_07_WaitForEnd(SoundManager* manager, SoundPlayer* player);
28static void au_SEFCmd_08_PitchSweep(SoundManager* manager, SoundPlayer* player);
29static void au_SEFCmd_09_StartLoop(SoundManager* manager, SoundPlayer* player);
30static void au_SEFCmd_0A_EndLoop(SoundManager* manager, SoundPlayer* player);
31static void au_SEFCmd_0B_WaitForRelease(SoundManager* manager, SoundPlayer* player);
32static void au_SEFCmd_0C_SetCurrentVolume(SoundManager* manager, SoundPlayer* player);
33static void au_SEFCmd_0D_VolumeRamp(SoundManager* manager, SoundPlayer* player);
34static void au_SEFCmd_0E_SetAlternativeSound(SoundManager* manager, SoundPlayer* player);
35static void au_SEFCmd_0F_Stop(SoundManager* manager, SoundPlayer* player);
36static void au_SEFCmd_10_Jump(SoundManager* manager, SoundPlayer* player);
37static void au_SEFCmd_11_Restart(SoundManager* manager, SoundPlayer* player);
38static void au_SEFCmd_12_NOP(SoundManager* manager, SoundPlayer* player);
39static void au_SEFCmd_13_SetRandomPitch(SoundManager* manager, SoundPlayer* player);
40static void au_SEFCmd_14_SetRandomVelocity(SoundManager* manager, SoundPlayer* player);
41static void au_SEFCmd_15_SetRandomUnused(SoundManager* manager, SoundPlayer* player);
42static void au_SEFCmd_16_SetEnvelopePress(SoundManager* manager, SoundPlayer* player);
43static void au_SEFCmd_17_PlaySound(SoundManager* manager, SoundPlayer* player);
44static void au_SEFCmd_18_SetAlternativeVolume(SoundManager* manager, SoundPlayer* player);
45
46typedef struct MusicTriggeredSound {
47 /* 0x00 */ u16 sound;
48 /* 0x02 */ u16 prereq; // when nonzero, sound may only play if this is already playing
49 /* 0x04 */ u8 flags;
50} MusicTriggeredSound; // size = 0x5
51
52// This flag field prefixes every SEF stream: two low bits choose a mode
53// (BASIC vs SEQUENCE vs COMPACT) and extra bits lock parameters while playing.
55 // 8 bytes: flags, instrument, volume, pan, reverb, pitch, randomPitch
57 // arbitrary sequence of commands
59 // 4 bytes: flags, instrument, volume and randomPitch
61 SFX_PARAM_MODE_MASK = 0x00000003,
62 // when flags below are set, these params can't be changed from api functions like sfx_play_sound_with_params
64 SFX_PARAM_LOCK_PAN = 0x00000008,
66 SFX_PARAM_LOCK_REVERB = 0x00000020 // ignored SetReverb command
67};
68
70 0xF803, 0x0125, 0x07D0, 0xFDBC, 0xF886, 0x0355, 0x06FC, 0xFBAB,
71 0xFEDA, 0xF82D, 0x0245, 0x077D, 0xFCA9, 0xF901, 0x0456, 0x065D,
72 0xFC33, 0xFBB2, 0xFCEF, 0xFE94, 0xFFD8, 0x0080, 0x00A4, 0x007D,
73 0x090E, 0x0673, 0x02FF, 0x0053, 0xFEF2, 0xFEA7, 0xFEF9, 0xFF7B
74};
75
77 0xB1, 0x01, 0x11, 0x10, 0x00, 0xFF, 0xFE, 0x34, 0xBB, 0x90, 0xE2, 0x1E, 0x00, 0xFB, 0x10, 0xEF,
78 0xF2, 0xD1, 0x80, 0xC4, 0xB3, 0xB1, 0xD3, 0xCF, 0xD1, 0xFD, 0xFE, 0x80, 0x1D, 0x2D, 0x3D, 0x3B,
79 0x2C, 0x3B, 0xFC, 0x1D, 0x80, 0xDE, 0xF0, 0xD0, 0xD3, 0xD2, 0xB3, 0xD1, 0xF4, 0x80, 0xA2, 0x03,
80 0xD0, 0x0D, 0xA9, 0xEA, 0xCB, 0x72, 0x90, 0x41, 0x4E, 0x1D, 0x2D, 0x0C, 0x1E, 0x10, 0x2F, 0x90,
81 0xF2, 0x12, 0x03, 0xF0, 0xC2, 0xD1, 0xD4, 0xF3, 0x80, 0xB0, 0xA1, 0xBF, 0xD2, 0x1E, 0x12, 0x70,
82 0x4D, 0x80, 0x4C, 0x39, 0x2C, 0x7E, 0x30, 0x6D, 0xB9, 0xCF, 0x90, 0xE1, 0xF2, 0xF3, 0xF2, 0xE1,
83 0xE2, 0x16, 0x22, 0xC1, 0xE7, 0x28, 0xF4, 0xF0, 0x21, 0x10, 0x10, 0xFF, 0xA1, 0xED, 0x9F, 0x2F,
84 0xF5, 0x61, 0x33, 0x3C, 0xD0, 0xA1, 0xDA, 0xC2, 0xFF, 0x14, 0x41, 0x22, 0x2D, 0xEF, 0xA1, 0xFA,
85 0xE1, 0x0E, 0x23, 0x30, 0x32, 0x0E, 0xF0, 0x91, 0x9A, 0xF2, 0xCF, 0x55, 0x13, 0x61, 0xEE, 0x1C,
86 0x91, 0x9D, 0x0F, 0xD2, 0x52, 0x06, 0x4D, 0xE1, 0x09, 0x91, 0xD0, 0x1B, 0x15, 0x2E, 0x36, 0xFD,
87 0x12, 0xCB, 0x81, 0x22, 0xBC, 0x65, 0xF0, 0x73, 0xCE, 0x3F, 0xAE, 0x71, 0x4E, 0x93, 0x70, 0xF5,
88 0x6E, 0xD2, 0x1B, 0xD1, 0x61, 0x0A, 0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
89};
90
91// copy of SMALL_ROOM_PARAMS
93 /* sections length */
94 3, 11,
95 /* chorus chorus filter
96 input output fbcoef ffcoef gain rate depth coef */
97 0, 9, 9830, -9830, 0, 0, 0, 0,
98 3, 7, 3276, -3276, 0x3FFF, 0, 0, 0,
99 0, 10, 5000, 0, 0, 0, 0, 0x5000
100};
101
102// modified ECHO_PARAMS -- length and output changed
104 /* sections length */
105 1, 11,
106 /* chorus chorus filter
107 input output fbcoef ffcoef gain rate depth coef */
108 0, 10, 20000, 0, 0x7FFF, 0, 0, 0x7FFF
109};
110
111// modified ECHO_PARAMS -- length and output changed
113 /* sections length */
114 1, 13,
115 /* chorus chorus filter
116 input output fbcoef ffcoef gain rate depth coef */
117 0, 12, 20000, 0, 0x7FFF, 0, 0, 0x7FFF
118};
119
120// modified ECHO_PARAMS -- length and output changed
122 /* sections length */
123 1, 14,
124 /* chorus chorus filter
125 input output fbcoef ffcoef gain rate depth coef */
126 0, 13, 20000, 0, 0x7FFF, 0, 0, 0x7FFF
127};
128
130 {
132 .prereq = SOUND_LRAW_CHEERING,
133 .flags = 1
134 }
135};
136
137// TODO: figure out how to make struct properly
139 .count = 1,
140 .offsets = { { 0x08, 0x12 } },
141};
142
144 // press
145 ENV_TIME_290MS, 127,
146 ENV_TIME_900MS, 127,
147 ENV_TIME_1S, 95,
148 ENV_TIME_3S, 0,
149 ENV_CMD_END, 0,
150 // release
152 ENV_CMD_END, 0
153};
154
156 .count = 1,
157 .offsets = { { 0x08, 0x1A } },
158};
159
161 // press
162 ENV_TIME_290MS, 127,
163 ENV_TIME_1800MS, 127,
164 ENV_TIME_290MS, 63,
165 ENV_TIME_1100MS, 31,
166 ENV_TIME_1100MS, 15,
170 ENV_CMD_END, 0,
171 // release
173 ENV_CMD_END, 0,
174};
175
176// looks like envelope data, but it's not aligned and not used
178 0x34337F26, 0x3F1600FF, 0x343B7F3B, 0x3FFF0000
179};
180
199
201 au_SEFCmd_00_SetVolume,
202 au_SEFCmd_01_SetPan,
203 au_SEFCmd_02_SetInstrument,
204 au_SEFCmd_03_SetReverb,
205 au_SEFCmd_04_SetEnvelope,
206 au_SEFCmd_05_CoarseTune,
207 au_SEFCmd_06_FineTune,
208 au_SEFCmd_07_WaitForEnd,
209 au_SEFCmd_08_PitchSweep,
210 au_SEFCmd_09_StartLoop,
211 au_SEFCmd_0A_EndLoop,
212 au_SEFCmd_0B_WaitForRelease,
213 au_SEFCmd_0C_SetCurrentVolume,
214 au_SEFCmd_0D_VolumeRamp,
215 au_SEFCmd_0E_SetAlternativeSound,
216 au_SEFCmd_0F_Stop,
217 au_SEFCmd_10_Jump,
218 au_SEFCmd_11_Restart,
219 au_SEFCmd_12_NOP,
220 au_SEFCmd_13_SetRandomPitch,
221 au_SEFCmd_14_SetRandomVelocity,
222 au_SEFCmd_15_SetRandomUnused,
223 au_SEFCmd_16_SetEnvelopePress,
224 au_SEFCmd_17_PlaySound,
225 au_SEFCmd_18_SetAlternativeVolume
226};
227
229 0x00, 0x00, 0x00, 0x00,
230 0x00, 0x00, 0x00, 0x00,
231 0x00, 0x00, 0x00, 0x00
232};
233
234// --------------------------------------------
235// the following are only referenced in audio/bgm_player
236
271
273 2, 1, 1, 1, 4, 3, 2, 0,
274 2, 1, 1, 1, 1, 1, 1, 2,
275 3, 1, 1, 0, 2, 1, 3, 1,
276 0, 0, 0, 0, 3, 3, 3, 3
277};
278
280 48, 24, 32, 40, 48, 56, 64, 48,
281 0, 0, 0, 0, 0, 0, 0, 0
282};
283
284// --------------------------------------------
285// the following are only referenced in audio/mseq_player
286
288 0x00, 0x00, 0x00, 0x00,
289 0x00, 0x00, 0x00, 0x00,
290 0x00, 0x00, 0x00, 0x00,
291 0x00, 0x00, 0x00, 0x00
292};
293
294// --------------------------------------------
295// the following are only referenced in audio/core/engine
296
300 [VOL_LEVEL_MUTE] 0, // 0.0 %
301 [VOL_LEVEL_1] AU_MAX_BUS_VOLUME * SQ(0.125), // 1.5625 %
302 [VOL_LEVEL_2] AU_MAX_BUS_VOLUME * SQ(0.250), // 6.25 %
303 [VOL_LEVEL_3] AU_MAX_BUS_VOLUME * SQ(0.375), // 14.0625 %
304 [VOL_LEVEL_4] AU_MAX_BUS_VOLUME * SQ(0.500), // 25.0 %
305 [VOL_LEVEL_5] AU_MAX_BUS_VOLUME * SQ(0.625), // 39.0625 %
306 [VOL_LEVEL_6] AU_MAX_BUS_VOLUME * SQ(0.750), // 56.25 %
307 [VOL_LEVEL_7] AU_MAX_BUS_VOLUME * SQ(0.875), // 76.5625 %
309};
310
311// TODO: figure out how to make struct properly
313 .count = 1,
314 .offsets = { { 0x8, 0xC } }, // EnvelopePressDefault, EnvelopePressDefault
315};
316
321
326
331
332// --------------------------------------------
333// the following are only referenced in audio/bgm_player
334
336 0x5E, 0x5D, 0x5C, 0x5B, 0x5A, 0x58, 0x56, 0x53,
337 0x51, 0x4F, 0x4A, 0x45, 0x40, 0x3B, 0x37, 0x35,
338 0x33, 0x31, 0x2F, 0x2D, 0x2B, 0x29, 0x27, 0x26,
339 0x25, 0x23, 0x21, 0x20, 0x1F, 0x1E, 0x1D, 0x1C,
340 0x1B, 0x1A, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14
341};
342
343// --------------------------------------------
344// the following are only referenced in audio/core/engine
345
347 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
348 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12,
349 0x13, 0x14, 0x15, 0x16, 0x17, 0x00, 0x00, 0x00,
350 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
351};
352
353// --------------------------------------------
354// the following are only referenced in audio/voice_envelope
355
356// convert seconds to microseconds and round to number multiple to 5750
357#define SEC(x) (((s32)(x * 1000000) / AU_FRAME_USEC) * AU_FRAME_USEC)
358
360 SEC(60), SEC(55), SEC(50), SEC(45), SEC(40), SEC(35), SEC(30), SEC(27.5), SEC(25), SEC(22.5),
361 SEC(20), SEC(19), SEC(18), SEC(17), SEC(16), SEC(15), SEC(14), SEC(13), SEC(12), SEC(11),
362 SEC(10), SEC(9), SEC(8), SEC(7), SEC(6), SEC(5), SEC(4.5), SEC(4), SEC(3.5), SEC(3),
363 SEC(2.75), SEC(2.5), SEC(2.25), SEC(2), SEC(1.9), SEC(1.8), SEC(1.7), SEC(1.6), SEC(1.5), SEC(1.4),
364 SEC(1.3), SEC(1.2), SEC(1.1), SEC(1), SEC(0.95), SEC(0.9), SEC(0.85), SEC(0.8), SEC(0.75), SEC(0.7),
365 SEC(0.65), SEC(0.6), SEC(0.55), SEC(0.5), SEC(0.45), SEC(0.4), SEC(0.375), SEC(0.35), SEC(0.325), SEC(0.3),
366 SEC(0.29), SEC(0.28), SEC(0.27), SEC(0.26), SEC(0.25), SEC(0.24), SEC(0.23), SEC(0.22), SEC(0.21), SEC(0.2),
367 SEC(0.19), SEC(0.18), SEC(0.17), SEC(0.16), SEC(0.15), SEC(0.14), SEC(0.13), SEC(0.12), SEC(0.11), SEC(0.1),
370 4 * AU_FRAME_USEC, 3 * AU_FRAME_USEC, 2 * AU_FRAME_USEC, 1 * AU_FRAME_USEC, 0, 0, 0, 0, 0, 0,
371};
372
373#undef SEC
374
375// --------------------------------------------
376// the following are only referenced in audio/core/engine
377
379 // ---------------------------------------------------------
380 // TUNE_SCALING_ARR_AMPLIFY_FINE (offset 0, size 128)
381 // ---------------------------------------------------------
382 // Pitch scaling for fine positive tuning.
383 // Each increment represents a pitch increase of 1 cent (1/100 semitone).
384 //
385 // Formula: 2^((i / 100) / 12) = 2^(i / 1200)
386 // i.e., 1 semitone of amplification at i = 100 (2^(1/12) ~ 1.059463)
387 1.00000000f, 1.00057781f, 1.00115597f, 1.00173450f, 1.00231326f, 1.00289237f, 1.00347185f, 1.00405169f,
388 1.00463188f, 1.00521231f, 1.00579309f, 1.00637424f, 1.00695574f, 1.00753760f, 1.00811982f, 1.00870228f,
389 1.00928509f, 1.00986826f, 1.01045179f, 1.01103568f, 1.01161981f, 1.01220429f, 1.01278913f, 1.01337433f,
390 1.01395988f, 1.01454580f, 1.01513207f, 1.01571858f, 1.01630545f, 1.01689267f, 1.01748025f, 1.01806819f,
391 1.01865649f, 1.01924503f, 1.01983392f, 1.02042317f, 1.02101278f, 1.02160275f, 1.02219307f, 1.02278376f,
392 1.02337468f, 1.02396595f, 1.02455759f, 1.02514958f, 1.02574193f, 1.02633464f, 1.02692771f, 1.02752113f,
393 1.02811480f, 1.02870882f, 1.02930319f, 1.02989793f, 1.03049302f, 1.03108847f, 1.03168428f, 1.03228045f,
394 1.03287685f, 1.03347361f, 1.03407073f, 1.03466821f, 1.03526604f, 1.03586423f, 1.03646278f, 1.03706169f,
395 1.03766096f, 1.03826058f, 1.03886044f, 1.03946066f, 1.04006124f, 1.04066217f, 1.04126346f, 1.04186511f,
396 1.04246712f, 1.04306948f, 1.04367220f, 1.04427528f, 1.04487872f, 1.04548252f, 1.04608655f, 1.04669094f,
397 1.04729569f, 1.04790080f, 1.04850626f, 1.04911208f, 1.04971826f, 1.05032480f, 1.05093169f, 1.05153894f,
398 1.05214655f, 1.05275452f, 1.05336285f, 1.05397153f, 1.05458057f, 1.05518997f, 1.05579972f, 1.05640972f,
399 1.05702007f, 1.05763078f, 1.05824184f, 1.05885327f, 1.05946505f, 1.06007719f, 1.06068969f, 1.06130254f,
400 1.06191576f, 1.06252933f, 1.06314325f, 1.06375754f, 1.06437218f, 1.06498718f, 1.06560254f, 1.06621826f,
401 1.06683433f, 1.06745076f, 1.06806755f, 1.06868470f, 1.06930220f, 1.06992006f, 1.07053828f, 1.07115686f,
402 1.07177579f, 1.07239509f, 1.07301474f, 1.07363474f, 1.07425511f, 1.07487583f, 1.07549691f, 1.07611835f,
403 // ---------------------------------------------------------
404 // TUNE_SCALING_ARR_AMPLIFY_COARSE (offset 128, size 32)
405 // ---------------------------------------------------------
406 // Pitch scaling for coarse positive tuning.
407 // Each increment represents a pitch increase of 128 cents (1.28 semitones)
408 //
409 // Formula: 2^((128 * i / 100) / 12)
410 1.00000000f, 1.07674015f, 1.15936935f, 1.24833953f, 1.34413731f, 1.44728661f, 1.55835164f, 1.67793977f,
411 1.80670512f, 1.94535196f, 2.09463859f, 2.25538135f, 2.42845964f, 2.61482000f, 2.81548166f, 3.03154206f,
412 3.26418304f, 3.51467681f, 3.78439355f, 4.07480860f, 4.38750982f, 4.72420788f, 5.08674431f, 5.47710180f,
413 5.89741516f, 6.34998369f, 6.83728218f, 7.36197615f, 7.92693520f, 8.53524971f, 9.19024563f, 9.89550686f,
414 // ---------------------------------------------------------
415 // TUNE_SCALING_ARR_ATTENUATE_FINE (offset 160, size 128)
416 // ---------------------------------------------------------
417 // Pitch scaling for fine downward tuning.
418 // Each increment represents a pitch decrease of 1 cent (1/100 semitone).
419 //
420 // Formula: 2^(-(i / 100) / 12)
421 1.00000000f, 0.99942255f, 0.99884546f, 0.99826866f, 0.99769223f, 0.99711609f, 0.99654031f, 0.99596488f,
422 0.99538976f, 0.99481499f, 0.99424052f, 0.99366641f, 0.99309260f, 0.99251914f, 0.99194598f, 0.99137318f,
423 0.99080074f, 0.99022859f, 0.98965681f, 0.98908532f, 0.98851418f, 0.98794335f, 0.98737288f, 0.98680270f,
424 0.98623288f, 0.98566335f, 0.98509419f, 0.98452532f, 0.98395681f, 0.98338860f, 0.98282075f, 0.98225319f,
425 0.98168600f, 0.98111910f, 0.98055255f, 0.97998631f, 0.97942042f, 0.97885484f, 0.97828960f, 0.97772467f,
426 0.97716010f, 0.97659582f, 0.97603190f, 0.97546828f, 0.97490501f, 0.97434205f, 0.97377944f, 0.97321713f,
427 0.97265512f, 0.97209346f, 0.97153211f, 0.97097111f, 0.97041041f, 0.96985006f, 0.96929002f, 0.96873033f,
428 0.96817094f, 0.96761185f, 0.96705312f, 0.96649468f, 0.96593660f, 0.96537882f, 0.96482134f, 0.96426421f,
429 0.96370739f, 0.96315092f, 0.96259475f, 0.96203887f, 0.96148336f, 0.96092814f, 0.96037328f, 0.95981872f,
430 0.95926446f, 0.95871055f, 0.95815694f, 0.95760363f, 0.95705068f, 0.95649803f, 0.95594567f, 0.95539367f,
431 0.95484197f, 0.95429057f, 0.95373952f, 0.95318878f, 0.95263839f, 0.95208830f, 0.95153850f, 0.95098901f,
432 0.95043987f, 0.94989103f, 0.94934249f, 0.94879431f, 0.94824642f, 0.94769883f, 0.94715160f, 0.94660467f,
433 0.94605803f, 0.94551176f, 0.94496578f, 0.94442010f, 0.94387472f, 0.94332969f, 0.94278497f, 0.94224054f,
434 0.94169647f, 0.94115269f, 0.94060922f, 0.94006604f, 0.93952322f, 0.93898070f, 0.93843848f, 0.93789655f,
435 0.93735498f, 0.93681371f, 0.93627274f, 0.93573207f, 0.93519175f, 0.93465173f, 0.93411201f, 0.93357259f,
436 0.93303353f, 0.93249476f, 0.93195629f, 0.93141812f, 0.93088025f, 0.93034273f, 0.92980552f, 0.92926860f,
437 // ---------------------------------------------------------
438 // TUNE_SCALING_ARR_ATTENUATE_COARSE (offset 288, size 128)
439 // ---------------------------------------------------------
440 // Pitch scaling for coarse downward tuning.
441 // Each increment represents a pitch decrease of 128 cents (1.28 semitones)
442 //
443 // Formula: 2^(-(128 * i / 100) / 12)
444 1.00000000f, 0.92873198f, 0.86254311f, 0.80107135f, 0.74398059f, 0.69095856f, 0.64171529f, 0.59598154f,
445 0.55350709f, 0.51405972f, 0.47742370f, 0.44339865f, 0.41179851f, 0.38245043f, 0.35519394f, 0.32987997f,
446 0.30637008f, 0.28453568f, 0.26425737f, 0.24542427f, 0.22793336f, 0.21168900f, 0.19660234f, 0.18259089f,
447 0.16957800f, 0.15749252f, 0.14626834f, 0.13584408f, 0.12616274f, 0.11717137f, 0.10882080f, 0.10106535f,
448 0.09386262f, 0.08717322f, 0.08096056f, 0.07519066f, 0.06983197f, 0.06485518f, 0.06023308f, 0.05594039f,
449 0.05195362f, 0.04825099f, 0.04481224f, 0.04161856f, 0.03865249f, 0.03589780f, 0.03333944f, 0.03096340f,
450 0.02875670f, 0.02670727f, 0.02480390f, 0.02303617f, 0.02139443f, 0.01986969f, 0.01845361f, 0.01713846f,
451 0.01591704f, 0.01478266f, 0.01372913f, 0.01275068f, 0.01184197f, 0.01099801f, 0.01021421f, 0.00948626f,
452 0.00881019f, 0.00818231f, 0.00759917f, 0.00705759f, 0.00655461f, 0.00608748f, 0.00565364f, 0.00525071f,
453 0.00487650f, 0.00452897f, 0.00420620f, 0.00390643f, 0.00362802f, 0.00336946f, 0.00312933f, 0.00290631f,
454 0.00269918f, 0.00250681f, 0.00232816f, 0.00216224f, 0.00200814f, 0.00186502f, 0.00173211f, 0.00160866f,
455 0.00149402f, 0.00138754f, 0.00128865f, 0.00119681f, 0.00111152f, 0.00103230f, 0.00095873f, 0.00089041f,
456 0.00082695f, 0.00076801f, 0.00071328f, 0.00066244f, 0.00061523f, 0.00057139f, 0.00053067f, 0.00049285f,
457 0.00045772f, 0.00042510f, 0.00039480f, 0.00036667f, 0.00034054f, 0.00031627f, 0.00029373f, 0.00027279f,
458 0.00025335f, 0.00023530f, 0.00021853f, 0.00020295f, 0.00018849f, 0.00017506f, 0.00016258f, 0.00015099f,
459 0.00014023f, 0.00013024f, 0.00012096f, 0.00011234f, 0.00010433f, 0.00009689f, 0.00008999f, 0.00008358f
460};
461
462extern s32* AU_FX_CUSTOM_PARAMS[0]; // points to 80078290
463
465
466void au_sfx_init(SoundManager* manager, u8 priority, u8 busID, AuGlobals* globals, u8 minVoiceIdx) {
467 // odd choice of parameters, perhaps chosen for a very large LCM (67934687500)?
468 // gives a pseudo-random sfx update pattern
469 s32 c = 434782;
470 u32 i;
471
472 manager->globals = globals;
473 manager->nextUpdateStep = 312500;
474 manager->nextUpdateCounter = c;
475 manager->nextUpdateInterval = c;
476 manager->priority = priority;
477 manager->busID = busID;
478
479 if (minVoiceIdx > 16) {
480 manager->firstVoice = 16;
481 } else {
482 manager->firstVoice = minVoiceIdx;
483 }
484
485 manager->busVolume = AU_MAX_BUS_VOLUME;
486 manager->baseVolume = AU_MAX_BUS_VOLUME;
487 manager->frameCounter = 0;
488 manager->randomValue = 0;
489
490 for (i = 0; i < ARRAY_COUNT(manager->players); i++) {
491 SoundPlayer* player = &manager->players[i];
492
493 player->sefDataReadPos = nullptr;
494 player->sfxVolume = 0;
495 player->delay = 0;
496 player->playLength = 0;
497 player->coarseTune = 0;
498 player->fineTune = 0;
499 player->sfxPan = 0;
500 player->reverb = 0;
501 player->instrumentIndex = 0;
502 player->envelopePreset = 0;
503 player->playVelocity = 0;
504 player->exclusiveID = 0;
505 player->cmdListOneShot[0] = 0; // will be set to bank
506 player->cmdListOneShot[1] = 0; // will be set to patch
507 player->cmdListOneShot[2] = 0; // will be set to volume
508 player->cmdListOneShot[3] = AU_PAN_MID; // default pan
509 player->cmdListOneShot[4] = 0; // reverb
510 player->cmdListOneShot[5] = 0x80 + (DEFAULT_KEYBASE / 100); // default tune, higher bit is meaningless
511 player->cmdListOneShot[6] = 0; // random pitch
512 player->cmdListOneShot[7] = 0; // unused
513 }
514
515 for (i = 0; i < ARRAY_COUNT(manager->bgmSounds); i++) {
516 manager->bgmSounds[i].raw = 0;
517 }
518
519 for (i = 0; i < ARRAY_COUNT(manager->customCmdList); i++) {
520 manager->customCmdList[i].data[0] = 0;
521 }
522
523 manager->resetPending = false;
527 au_fade_set_volume(manager->busID, manager->fadeInfo.baseVolume >> 16, manager->busVolume);
528 manager->lastCustomEffectIdx = 0xFF;
529
530 manager->customReverbParams[0] = CUSTOM_SMALL_ROOM_PARAMS;
531 manager->customReverbParams[1] = CUSTOM_ECHO_PARAMS_1;
532 manager->customReverbParams[2] = CUSTOM_ECHO_PARAMS_2;
533 manager->customReverbParams[3] = CUSTOM_ECHO_PARAMS_3;
534 manager->customReverbParams[4] = CUSTOM_ECHO_PARAMS_3;
535 manager->customReverbParams[5] = CUSTOM_ECHO_PARAMS_3;
536 manager->customReverbParams[6] = CUSTOM_ECHO_PARAMS_3;
537 manager->customReverbParams[7] = CUSTOM_ECHO_PARAMS_3;
538
539 manager->customReverbAmounts[0] = 0x10;
540 manager->customReverbAmounts[1] = 0x20;
541 manager->customReverbAmounts[2] = 0x20;
542 manager->customReverbAmounts[3] = 0x20;
543 manager->customReverbAmounts[4] = 0x20;
544 manager->customReverbAmounts[5] = 0x30;
545 manager->customReverbAmounts[6] = 0x40;
546 manager->customReverbAmounts[7] = 0x50;
547
549}
550
552 SEFHeader* sefData = manager->globals->dataSEF;
553 s32 sections = ARRAY_COUNT(sefData->sections);
554 u32 i;
555
556 manager->sefData = (u8*)sefData;
557
558 for (i = 0; i < sections; i++) {
559 if (sefData->sections[i] != 0) {
560 manager->normalSounds[i] = AU_FILE_RELATIVE(sefData, sefData->sections[i]);
561 }
562 }
563
564 if (sefData->hasExtraSection == 1) {
565 if (sefData->section2000 != 0) {
566 manager->extraSounds = AU_FILE_RELATIVE(sefData, sefData->section2000);
567 }
568 }
569}
570
572 s32 i;
573
574 for (i = 0; i < SFX_QUEUE_SIZE; i++) {
575 manager->soundQueue[i].soundID = SOUND_NONE;
576 manager->soundQueue[i].toReplaceID = SOUND_NONE;
577 manager->soundQueue[i].volume = 0;
578 manager->soundQueue[i].pitchShift = 0;
579 manager->soundQueue[i].pan = 0;
580 }
581
582 manager->unused_165 = 0;
583 manager->sfxQueueWritePos = 0;
584 manager->sfxQueueReadPos = 0;
585 manager->unused_162 = 0;
586}
587
588// Registers a new sound effect for playback from the main/game thread.
589// The new event is dropped if the buffer is full.
590void au_sfx_enqueue_event(SoundManager* manager, u32 soundID, s16 volume, s16 pitchShift, u8 pan) {
591 // Determine the number of pending sound effects in the queue
592 s32 pending = manager->sfxQueueWritePos - manager->sfxQueueReadPos;
593 if (pending < 0) {
595 }
596
597 // Only enqueue if there's room in the buffer
598 if (pending < SFX_QUEUE_SIZE) {
599 u32 nextPos = manager->sfxQueueWritePos;
600
601 manager->soundQueue[nextPos].soundID = soundID & (SOUND_ID_LOWER | SOUND_ID_STOP | SOUND_ID_ADJUST | SOUND_ID_TRIGGER_MASK);
602 manager->soundQueue[nextPos].toReplaceID = (soundID & SOUND_ID_UPPER_MASK) >> 0x10;
603 manager->soundQueue[nextPos].volume = volume;
604 manager->soundQueue[nextPos].pitchShift = pitchShift;
605 manager->soundQueue[nextPos].pan = pan;
606
607 nextPos++;
608 if (nextPos >= SFX_QUEUE_SIZE) {
609 nextPos = 0;
610 }
611
612 manager->sfxQueueWritePos = nextPos;
613 }
614}
615
616// Called from the audio thread once per video frame.
617// Consumes and processes sound events from the queue.
621 u32 i, j, k;
622 s32 pending;
623
624 manager->frameCounter++;
625 if (manager->resetPending) {
626 au_sfx_reset_players(manager);
627 manager->resetPending = false;
628 }
629
630 // Process sound effects triggered by music via BGM_SPECIAL_TRIGGER_SOUND
631 for (i = 0; i < ARRAY_COUNT(manager->bgmSounds); i++) {
632 k = manager->bgmSounds[i].index;
633 if (k == 0) {
634 // do nothing
635 } else if (k <= ARRAY_COUNT(MusicSounds)) {
637 u16 prereq = triggered->prereq;
638 if (prereq != 0) {
639 // try playing sound ONLY IF prereq sound is already playing
640 for (j = 0; j < ARRAY_COUNT(manager->players); j++) {
641 if (manager->players[j].curSoundID == prereq) {
642 newRequest.soundID = triggered->sound;
643 newRequest.toReplaceID = SOUND_NONE;
644 newRequest.pitchShift = 0;
645 if ((triggered->flags & 1) && (manager->bgmSounds[i].volume != 0)) {
646 newRequest.volume = (manager->bgmSounds[i].volume << 8) + 0xFF;
647 } else {
648 newRequest.volume = 0;
649 }
650 newRequest.pan = 0;
652 break;
653 }
654 }
655 } else {
656 // no prereq defined, unconditionally play the sound
657 newRequest.soundID = triggered->sound;
658 newRequest.toReplaceID = SOUND_NONE;
659 newRequest.volume = 0;
660 newRequest.pitchShift = 0;
661 newRequest.pan = 0;
663 }
664 }
665 // clear the event
666 manager->bgmSounds[i].raw = 0;
667 }
668
669 // Process sound effects triggered by SEF command 17
670 for (i = 0; i < ARRAY_COUNT(manager->customCmdList); i++) {
671 if (manager->customCmdList[i].data[0] != 0) {
672 newRequest.soundID = 1;
673 newRequest.toReplaceID = SOUND_NONE;
674 newRequest.volume = 0;
675 newRequest.pitchShift = 0;
676 newRequest.pan = 0;
677 au_sfx_try_sound(manager, &newRequest, &manager->customCmdList[i]);
678 }
679 manager->customCmdList[i].data[0] = 0;
680 }
681
682 // Determine the number of pending sound effects in the queue
683 pending = manager->sfxQueueWritePos - manager->sfxQueueReadPos;
684 if (pending < 0) {
686 }
687
688 // Process each pending sound effect in the queue
689 j = manager->sfxQueueReadPos;
690 if (pending > 0 && pending < SFX_QUEUE_SIZE) {
691 for (i = 0; i < pending; i++) {
692 request = &manager->soundQueue[j];
693 if (request->soundID & SOUND_ID_LOWER) {
694 if (request->soundID & SOUND_ID_STOP) {
695 au_sfx_stop_by_id(manager, request->soundID);
696 } else if (!(request->soundID & (SOUND_ID_ADJUST | SOUND_ID_TRIGGER_MASK))) {
698 } else {
699 if (request->soundID & SOUND_ID_TRIGGER_MASK) {
700 au_sfx_set_triggers(manager, request->soundID);
701 }
702 if (request->soundID & SOUND_ID_ADJUST) {
703 au_sfx_set_modifiers(manager, request);
704 }
705 }
706 }
707 request->soundID = SOUND_NONE;
708
709 j++;
710 if (j >= SFX_QUEUE_SIZE) {
711 j = 0;
712 }
713 }
714 manager->sfxQueueReadPos = manager->sfxQueueWritePos;
715 }
716}
717
718// also affects ambience because it uses same fx bus
720 s32 customIdx = (u8) arg1;
721
722 if (customIdx != 0xF0) {
723 if (customIdx < ARRAY_COUNT(manager->customReverbParams)) {
724 if (manager->lastCustomEffectIdx != customIdx) {
725 manager->lastCustomEffectIdx = customIdx;
726 manager->globals->effectChanges[FX_BUS_SOUND].type = AU_FX_CUSTOM_0;
727 manager->globals->effectChanges[FX_BUS_SOUND].changed = true;
728 AU_FX_CUSTOM_PARAMS[0] = manager->customReverbParams[customIdx];
729 }
730 manager->defaultReverbAmt = manager->customReverbAmounts[customIdx];
731 } else {
732 manager->lastCustomEffectIdx = 0xFF;
733 manager->defaultReverbAmt = 0;
734 }
735 }
736 return manager->lastCustomEffectIdx;
737}
738
740 if (state == SND_MANAGER_STATE_ENABLED) {
741 manager->state = state;
742 } else if (state == SND_MANAGER_STATE_DISABLED) {
743 manager->state = state;
744 }
745}
746
748 SoundPlayer* player;
749 s32 playerIndex;
750 u16* cmdList;
752 s32 foundPlayer = false;
753 u32 exclusiveID;
757 s32 v1;
758 s32* normalSounds;
759
760 #define NEXT_POLY_TRACK trackCount--; if (trackCount <= 0 ) { break; } cmdList += 2;
761
762 u32 soundIndex = (request->soundID - 1) & 0xFF;
764 u16 soundID = request->soundID;
765
766 if (soundID & SOUND_ID_UNK) {
767 // sound from extra section
768 soundIndex = (request->soundID - 1) & SOUND_ID_UNK_INDEX_MASK;
769 if (soundIndex < 0x140) {
770 cmdList = (u16*)&manager->extraSounds[soundIndex];
771 if (*cmdList != 0) {
772 // check if any player is playing this sound
773 for (playerIndex = 7; playerIndex >= 0; playerIndex--) {
774 player = &manager->players[playerIndex];
775 if (player->curSoundID == soundIDLower) {
776 foundPlayer = true;
777 break;
778 }
779 }
780
781 if (!foundPlayer) {
782 //find free player
783 for (playerIndex = 7; playerIndex >= 0; playerIndex--) {
784 player = &manager->players[playerIndex];
785 if (player->sefDataReadPos == nullptr) {
786 foundPlayer = true;
787 break;
788 }
789 }
790 }
791
792 if (foundPlayer) {
793 au_sfx_play_sound(manager, player, (s8*)cmdList, request, 0, 0);
794 }
795 }
796 }
797 } else {
798 if (soundIndex >= 0xC0) {
799 if (customSEF != nullptr) {
800 cmdList = (u16*)customSEF;
801 } else {
802 sectionIndex = ((soundIDLower - 1) >> 8) + 4;
803 normalSounds = manager->normalSounds[sectionIndex];
804 v1 = soundIndex - 0xC0;
805 cmdList = (u16*)&manager->normalSounds[sectionIndex][v1];
806 }
807
808 if (*cmdList != 0) {
809 // check if any player is playing this sound
810 for (playerIndex = 7; playerIndex >= 0; playerIndex--) {
811 player = &manager->players[playerIndex];
812 if (player->curSoundID == soundIDLower) {
813 foundPlayer = true;
814 break;
815 }
816 }
817
818 if (!foundPlayer) {
819 //find free player
820 for (playerIndex = 7; playerIndex >= 0; playerIndex--) {
821 player = &manager->players[playerIndex];
822 if (player->sefDataReadPos == nullptr) {
823 foundPlayer = true;
824 break;
825 }
826 }
827 }
828
829 if (foundPlayer) {
830 au_sfx_play_sound(manager, player, (u8*)cmdList, request, 0, 0);
831 }
832 }
833 } else {
834 if (customSEF != nullptr) {
835 cmdList = (u16*)customSEF;
836 } else {
837 sectionIndex = ((soundID) >> 8) & 3;
838 cmdList = (u16*)&manager->normalSounds[sectionIndex][soundIndex];
839 }
840
841 if (*cmdList != 0) {
842 // read sound info chunk
843 soundInfo = cmdList[1];
844
845 priority = (soundInfo & 0x300) >> 8; // bits 8, 9
846 polyphonyMode = (soundInfo & 0x60) >> 5; // bits 5, 6,
848 useSpecificPlayerMode = (useSpecificPlayerMode & 0x80) >> 7; // bit 7
849
850 if (polyphonyMode == 0) {
851 if (request->toReplaceID != SOUND_NONE) {
852 for (playerIndex = 0; playerIndex < 8; playerIndex++) {
853 player = &manager->players[playerIndex];
854 if (player->curSoundID == request->toReplaceID) {
855 foundPlayer = true;
856 break;
857 }
858 }
859 }
860
861 if (useSpecificPlayerMode == 0) {
862 if (!foundPlayer) {
863 playerIndex = soundInfo & 0x7;
864 player = &manager->players[playerIndex];
865 if (player->sefDataReadPos == nullptr || priority >= player->priority) {
866 au_sfx_play_sound(manager, player, AU_FILE_RELATIVE(manager->sefData, *cmdList), request, priority, 0);
867 }
868 return;
869 }
870 }
871
872 if (!foundPlayer) {
873 // lower 4 bits of soundInfo: max playerIndex
874 // check if any player is playing this sound
875 for (playerIndex = soundInfo & 0x7; playerIndex >= 0; playerIndex--) {
876 player = &manager->players[playerIndex];
877 if (player->curSoundID == soundIDLower) {
878 foundPlayer = true;
879 break;
880 }
881 }
882 }
883
884 if (!foundPlayer) {
885 // find free player
886 for (playerIndex = soundInfo & 0x7; playerIndex >= 0; playerIndex--) {
887 player = &manager->players[playerIndex];
888 if (player->sefDataReadPos == nullptr) {
889 foundPlayer = true;
890 break;
891 }
892 }
893 }
894
895 if (!foundPlayer) {
896 // if there is no free player try stealing one with lower priority
897 for (playerIndex = soundInfo & 0x7; playerIndex >= 0; playerIndex--) {
898 player = &manager->players[playerIndex];
899 if (player->priority < priority) {
900 foundPlayer = true;
901 break;
902 }
903 }
904 }
905
906 if (!foundPlayer) {
907 playerIndex = soundInfo & 0x7;
908 player = &manager->players[playerIndex];
909 if (player->priority <= priority) {
910 foundPlayer = true;
911 }
912 }
913
914 if (foundPlayer) {
915 au_sfx_play_sound(manager, player, AU_FILE_RELATIVE(manager->sefData, *cmdList), request, priority, 0);
916 }
917 } else {
918 cmdList = AU_FILE_RELATIVE(manager->sefData, *cmdList);
919 exclusiveID = (soundInfo & 0x1800) >> 11; // bits 11, 12
920 if (exclusiveID != 0) {
921 au_sfx_stop_by_exlusive_id(manager, exclusiveID);
922 } else {
923 au_sfx_stop_by_id(manager, request->soundID);
924 }
925
926 trackCount = 2 << (polyphonyMode - 1); // 2 or 4 or 8
927
928 if (useSpecificPlayerMode != 0) {
929 for (playerIndex = 7; playerIndex >= 0; playerIndex--) {
930 if (*cmdList != 0) {
931 // first check the players that were stopped just now
932 player = &manager->players[playerIndex];
933 if (player->sefDataReadPos == BlankSEFData) {
934 au_sfx_play_sound(manager, player, AU_FILE_RELATIVE(manager->sefData, *cmdList), request, priority, exclusiveID);
936 }
937 } else {
939 }
940
941 }
942
943 if (trackCount != 0) {
944 for (playerIndex = 7; playerIndex >= 0;){
945 if (*cmdList != 0) {
946 // then check any free players
947 player = &manager->players[playerIndex];
948 if (player->sefDataReadPos == nullptr) {
949 au_sfx_play_sound(manager, player, AU_FILE_RELATIVE(manager->sefData, *cmdList), request, priority, exclusiveID);
951 }
952 playerIndex--;
953 } else {
955 }
956 }
957 }
958
959 if (trackCount != 0) {
960 for (playerIndex = 7; playerIndex >= 0; playerIndex--) {
961 if (*cmdList != 0) {
962 // then try to steal
963 player = &manager->players[playerIndex];
964 if (exclusiveID > player->exclusiveID && priority >= player->priority) {
965 au_sfx_play_sound(manager, player, AU_FILE_RELATIVE(manager->sefData, *cmdList), request, priority, exclusiveID);
967 }
968 } else {
970 }
971 }
972 }
973 } else {
974 s32 i;
975 for (i = 0; i < trackCount; i++) {
976 if (*cmdList != 0) {
977 soundInfo = cmdList[1];
978 playerIndex = soundInfo & 7;
979 player = &manager->players[playerIndex];
980 priority = (soundInfo & 0x300) >> 8; // bits 8, 9
981 if (player->sefDataReadPos == nullptr || priority >= player->priority) {
982 au_sfx_play_sound(manager, player, AU_FILE_RELATIVE(manager->sefData, *cmdList), request, priority, exclusiveID);
983 }
984 cmdList += 2;
985 }
986 }
987 }
988 }
989 }
990 }
991 }
992 #undef NEXT_POLY_TRACK
993}
994
995static void au_sfx_play_sound(SoundManager* manager, SoundPlayer* player, s8* readPos, SoundRequest* request, s32 priority, s32 exclusiveID) {
996 if (manager->state == SND_MANAGER_STATE_ENABLED) {
997 player->sefDataReadPos = readPos;
998 player->sefReadStart = readPos;
999 player->sfxInstrumentRef = manager->globals->defaultInstrument;
1000 player->sfxPan = AU_PAN_MID;
1001 player->sfxVolume = AU_MAX_VOLUME_16;
1003 player->reverb = 0;
1004 player->instrumentIndex = 0;
1005 player->envelopePreset = 0;
1006 player->playVelocity = AU_MAX_VOLUME_8;
1007 player->coarseTune = 0;
1008 player->fineTune = 0;
1009 player->loopStartPos = nullptr;
1010 player->loopIterCount = 0;
1011 player->delay = 1;
1012 player->playLength = 0;
1013 player->curSoundID = request->soundID & SOUND_ID_LOWER;
1014 player->priority = priority;
1015 player->exclusiveID = exclusiveID;
1016 player->envelopCustomPressProfile = nullptr;
1017 player->changed.all = 0;
1018 player->unused_A0 = 0;
1019 player->randomPitch = 0;
1020 player->randomVelocity = 0;
1021 player->randomUnused = 0;
1023 player->volumeLerp.time = 0;
1024 player->volumeLerp.step = 0;
1025 player->volumeLerp.goal = 0;
1026 player->tuneLerp.current = 0;
1027 player->tuneLerp.time = 0;
1028 player->tuneLerp.step = 0;
1029 player->tuneLerp.goal = 0;
1030 player->alternativeDataPos = nullptr;
1031 player->alternativeType = 0;
1032 player->triggers = 0;
1033 player->sfxParamsFlags = *player->sefDataReadPos++;
1034 switch (player->sfxParamsFlags & SFX_PARAM_MODE_MASK) {
1036 player->state = SND_PLAYER_STATE_INIT;
1037 break;
1039 player->state = SND_PLAYER_STATE_INIT;
1040 break;
1042 // change mode to SFX_PARAM_MODE_BASIC
1045 player->state = SND_PLAYER_STATE_INIT;
1046 // populate preset 8‑byte SEF stream in cmdListOneShot:
1047 player->cmdListOneShot[0] = player->sefDataReadPos[0]; // instrument bank
1048 player->cmdListOneShot[1] = player->sefDataReadPos[1]; // instrument patch
1049 // bottom 3 bits are irrelevant for volume, maps to a range 3 to 127
1050 player->cmdListOneShot[2] = (player->sefDataReadPos[2] >> 1) | 3; // volume
1051 // use bottom 3 bits for random pitch amount
1052 player->cmdListOneShot[6] = player->sefDataReadPos[2] & 7; // random pitch
1053 player->sefDataReadPos = player->cmdListOneShot;
1054 break;
1055 }
1056 au_sfx_set_player_modifiers(player, request);
1057 }
1058}
1059
1060static void au_sfx_set_triggers(SoundManager* manager, u32 soundID) {
1061 s32 triggers = (soundID & SOUND_ID_TRIGGER_MASK) >> 0xA;
1062 s32 i;
1063
1064 for (i = 0; i < ARRAY_COUNT(manager->players); i++) {
1065 SoundPlayer* player = &manager->players[i];
1066 if (player->curSoundID == (soundID & SOUND_ID_LOWER)) {
1067 player->triggers = triggers;
1068 }
1069 }
1070}
1071
1072static void au_sfx_stop_by_id(SoundManager* manager, u32 soundID) {
1073 s32 i;
1074
1075 for (i = 0; i < ARRAY_COUNT(manager->players); i++) {
1076 SoundPlayer* player = &manager->players[i];
1077 if (player->curSoundID == (soundID & SOUND_ID_LOWER)) {
1078 player->sefDataReadPos = BlankSEFData;
1079 player->alternativeDataPos = nullptr;
1082 player->delay = 1;
1083 player->priority = 0;
1084 player->exclusiveID = 0;
1085 }
1086 }
1087}
1088
1089static void au_sfx_stop_by_exlusive_id(SoundManager* manager, u32 exclusiveID) {
1090 s32 i;
1091
1092 for (i = 0; i < ARRAY_COUNT(manager->players); i++) {
1093 SoundPlayer* player = &manager->players[i];
1094 if (exclusiveID == player->exclusiveID) {
1095 player->sefDataReadPos = BlankSEFData;
1096 player->alternativeDataPos = nullptr;
1099 player->delay = 1;
1100 player->priority = 0;
1101 player->exclusiveID = 0;
1102 }
1103 }
1104}
1105
1106static void au_sfx_set_modifiers(SoundManager* manager, SoundRequest* request) {
1107 s32 soundID = request->soundID & SOUND_ID_LOWER;
1108 s32 i;
1109
1110 for (i = 0; i < ARRAY_COUNT(manager->players); i++) {
1111 SoundPlayer* player = &manager->players[i];
1112 if (player->curSoundID == soundID) {
1113 au_sfx_set_player_modifiers(player, request);
1114 }
1115 }
1116}
1117
1118static void au_sfx_set_player_modifiers(SoundPlayer* player, SoundRequest* request) {
1119 if (player->sfxParamsFlags & SFX_PARAM_LOCK_VOLUME) {
1120 player->masterVolume = 0;
1121 } else {
1122 player->masterVolume = request->volume;
1123 player->changed.volume = true;
1124 }
1125 if (player->sfxParamsFlags & SFX_PARAM_LOCK_PAN) {
1126 player->masterPan = 0;
1127 } else {
1128 player->masterPan = request->pan;
1129 player->changed.pan = true;
1130 }
1131 if (player->sfxParamsFlags & SFX_PARAM_LOCK_PITCH) {
1132 player->masterPitchShift = 0;
1133 } else {
1134 player->masterPitchShift = request->pitchShift;
1135 player->changed.tune = true;
1136 }
1137}
1138
1140 SoundPlayer* player;
1141 AuVoice* voice;
1143 u8 end;
1144 u8 i;
1145
1146 // update pseudorandom number with fast 'good enough' method
1147 manager->randomValue = (u16)manager->randomValue + (u16)manager->frameCounter;
1148
1149 startVoice = manager->firstVoice;
1150 for (i = startVoice, end = startVoice + ARRAY_COUNT(manager->players); i < end; i++) {
1151 player = &manager->players[i - manager->firstVoice];
1152 if (player->sefDataReadPos != nullptr) {
1153 voice = &manager->globals->voices[i];
1154 manager->curVoice = voice;
1155 if (voice->priority <= manager->priority) {
1156 manager->curVoiceIndex = i;
1157 switch (player->sfxParamsFlags & SFX_PARAM_MODE_MASK) {
1159 au_sfx_update_basic(manager, player, voice, i);
1160 break;
1162 au_sfx_update_sequence(manager, player, voice, i);
1163 break;
1165 break;
1166 }
1167 } else {
1168 player->sefDataReadPos = nullptr;
1169 player->curSoundID = SOUND_NONE;
1170 player->priority = 0;
1171 }
1172 }
1173 }
1174 return 0;
1175}
1176
1177static void au_sfx_update_basic(SoundManager* manager, SoundPlayer* player, AuVoice* voice, u8 voiceIdx) {
1178 s16 volume;
1179 s32 tune;
1180 s32 pan;
1181
1182 switch (player->state) {
1184 if (voice->priority != manager->priority) {
1185 player->sefDataReadPos = nullptr;
1186 player->curSoundID = SOUND_NONE;
1187 player->priority = 0;
1188 } else {
1189 if (!(player->sfxParamsFlags & SFX_PARAM_LOCK_PITCH)) {
1191 ((player->tuneLerp.current >> 0x10) - player->sfxInstrumentRef->keyBase) + player->masterPitchShift) * player->sfxInstrumentRef->pitchRatio;
1192 if (voice->pitchRatio != player->pitchRatio) {
1193 voice->syncFlags |= AU_VOICE_SYNC_FLAG_PITCH;
1194 voice->pitchRatio = player->pitchRatio;
1195 }
1196 }
1197
1198 if (!(player->sfxParamsFlags & SFX_PARAM_LOCK_PAN) && player->masterPan != 0) {
1199 pan = player->masterPan;
1200 } else {
1201 pan = player->sfxPan;
1202 }
1203 if (voice->pan != pan) {
1204 voice->pan = pan;
1205 voice->syncFlags |= AU_VOICE_SYNC_FLAG_PAN_FXMIX;
1206 }
1207
1208 volume = au_sfx_get_scaled_volume(manager, player);
1209 if (voice->clientVolume != volume) {
1210 voice->clientVolume = volume;
1211 voice->envelopeFlags |= AU_VOICE_ENV_FLAG_VOL_CHANGED;
1212 }
1213 }
1214 break;
1216 au_SEFCmd_02_SetInstrument(manager, player); // 2 bytes
1217 au_SEFCmd_00_SetVolume(manager, player); // 1 byte
1218 au_SEFCmd_01_SetPan(manager, player); // 1 byte
1219 au_SEFCmd_03_SetReverb(manager, player); // 1 byte
1220 tune = (*player->sefDataReadPos++ & 0x7F) * 100; // 1 byte
1221 player->randomPitch = (*player->sefDataReadPos & 0xF) * 8; // 1 byte
1222
1223 if (player->randomPitch != 0) {
1224 player->tuneLerp.current = au_sfx_get_random_pitch(manager->randomValue, player->randomPitch, tune) << 0x10;
1225 } else {
1226 player->tuneLerp.current = tune << 0x10;
1227 }
1228 if (player->sfxParamsFlags & SFX_PARAM_LOCK_PITCH) {
1229 tune = (player->tuneLerp.current >> 0x10) - player->sfxInstrumentRef->keyBase;
1230 } else {
1231 tune = ((player->tuneLerp.current >> 0x10) - player->sfxInstrumentRef->keyBase) + player->masterPitchShift;
1232 }
1233 player->pitchRatio = au_compute_pitch_ratio(tune) * player->sfxInstrumentRef->pitchRatio;
1234
1235 if (voice->priority <= manager->priority) {
1237 if (!(player->sfxParamsFlags & SFX_PARAM_LOCK_PAN) && player->masterPan != 0) {
1238 voice->pan = player->masterPan;
1239 } else {
1240 voice->pan = player->sfxPan;
1241 }
1242
1243 voice->reverb = player->reverb;
1244 voice->clientVolume = au_sfx_get_scaled_volume(manager, player);
1245 voice->envelope.cmdListPress = player->envelope.cmdListPress;
1246 voice->envelope.cmdListRelease = player->envelope.cmdListRelease;
1247 voice->instrument = player->sfxInstrumentRef;
1248 voice->pitchRatio = player->pitchRatio;
1249 voice->syncFlags = AU_VOICE_SYNC_FLAG_ALL;
1250 voice->priority = manager->priority;
1251 voice->clientPriority = voice->priority;
1252 voice->busID = manager->busID;
1253 }
1255 break;
1256 default:
1257 player->sefDataReadPos = nullptr;
1258 player->curSoundID = SOUND_NONE;
1259 player->priority = 0;
1260 break;
1261 }
1262}
1263
1264static s16 au_sfx_get_scaled_volume(SoundManager* manager, SoundPlayer* player) {
1265 s32 outVolume;
1266
1267 outVolume = (manager->baseVolume * player->sfxVolume) >> 15;
1268 if (!(player->sfxParamsFlags & SFX_PARAM_LOCK_VOLUME) && (player->masterVolume != 0)) {
1269 outVolume = (outVolume * player->masterVolume) >> 15;
1270 }
1271 return outVolume;
1272}
1273
1274static void au_sfx_update_sequence(SoundManager* manager, SoundPlayer* player, AuVoice* voice, u8 voiceIdx) {
1275 s32 pitchShift;
1276 u8 opcode;
1277 u32 playLength;
1280
1281 startedNewVoice = false;
1282 if (player->state == SND_PLAYER_STATE_INIT) {
1284 if (voice->priority == manager->priority) {
1286 }
1287 }
1288
1289 if (player->alternativeDataPos != nullptr) {
1290 if (player->triggers == 1) {
1291 player->sefDataReadPos = player->alternativeDataPos;
1292 player->alternativeDataPos = nullptr;
1293 player->triggers = 0;
1294 player->delay = 1;
1295 }
1296 }
1297 if (player->triggers == 2) {
1298 player->changed.volume = true;
1299 player->sfxVolume = player->alternativeVolume;
1300 }
1301 player->delay--;
1302 while (player->delay == 0) {
1304 opcode = *player->sefDataReadPos++;
1305 if (opcode < 0x80) {
1306 if (opcode == 0) {
1307 if (voice->priority == manager->priority) {
1309 }
1310 player->sefDataReadPos = nullptr;
1311 player->curSoundID = SOUND_NONE;
1312 player->priority = 0;
1313 player->exclusiveID = 0;
1314 return;
1315 }
1316 if (opcode >= 0x78) {
1317 // long delay
1318 player->delay = (u8)(*player->sefDataReadPos++) + ((opcode & 7) << 8) + 0x78;
1319 } else {
1320 // short delay
1321 player->delay = opcode;
1322 }
1323 } else if (opcode < 0xD8) {
1324 // play sound
1325 // (opcode & 0x7F) = pitch
1326 if (player->randomPitch != 0) {
1327 player->tuneLerp.current = au_sfx_get_random_pitch(manager->randomValue, player->randomPitch, (opcode & 0x7F) * 100) << 0x10;
1328 } else {
1329 player->tuneLerp.current = ((opcode & 0x7F) * 100) << 0x10;
1330 }
1331
1332 if (player->randomVelocity != 0) {
1333 player->playVelocity = au_sfx_get_random_vol(manager->randomValue, player->randomVelocity, player->sefDataReadPos[0] & 0x7F);
1334 } else {
1335 player->playVelocity = player->sefDataReadPos[0] & 0x7F;
1336 }
1337
1338 playLength = player->sefDataReadPos[1];
1339 if (playLength >= 0xC0) {
1340 playLength = player->sefDataReadPos[2] + ((playLength & 0x3F) << 8) + 0xC0;
1341 player->sefDataReadPos += 3;
1342 } else {
1343 player->sefDataReadPos += 2;
1344 }
1345 player->playLength = playLength;
1346
1347 if (voice->priority <= manager->priority) {
1349 if ((player->sfxParamsFlags & SFX_PARAM_LOCK_PAN) || (player->masterPan == 0)) {
1350 voice->pan = player->sfxPan;
1351 } else {
1352 voice->pan = player->masterPan;
1353 }
1354
1355 voice->reverb = player->reverb;
1356 au_sfx_set_voice_volume(voice, manager, player);
1357 if (player->envelopCustomPressProfile == nullptr) {
1358 voice->envelope.cmdListPress = player->envelope.cmdListPress;
1359 voice->envelope.cmdListRelease = player->envelope.cmdListRelease;
1360 } else {
1361 voice->envelope.cmdListPress = player->envelopCustomPressProfile;
1362 voice->envelope.cmdListRelease = player->envelope.cmdListRelease;
1363 }
1364
1365 voice->instrument = player->sfxInstrumentRef;
1366 voice->busID = manager->busID;
1367
1368 voice->priority = manager->priority;
1369 voice->syncFlags = AU_VOICE_SYNC_FLAG_ALL;
1370 startedNewVoice = true;
1371 voice->clientPriority = manager->priority;
1372 player->changed.tune = true;
1373 }
1374 } else {
1375 s32 index = opcode - 0xE0;
1378 }
1379 }
1380
1381 if (player->volumeLerp.time != 0) {
1382 player->volumeLerp.time--;
1383 if (player->volumeLerp.time != 0) {
1384 player->volumeLerp.current += player->volumeLerp.step;
1385 } else {
1386 player->volumeLerp.current = player->volumeLerp.goal << 0x10;
1387 }
1388 player->changed.volume = true;
1389 }
1390
1391 if (!startedNewVoice) {
1392 if (player->playLength != 0) {
1393 player->playLength--;
1394 if ((player->playLength == 0) && (voice->priority == manager->priority)) {
1395 voice->envelopeFlags |= AU_VOICE_ENV_FLAG_KEY_RELEASED;
1396 }
1397 }
1398 if (player->tuneLerp.time != 0) {
1399 player->tuneLerp.time--;
1400 if (player->tuneLerp.time != 0) {
1401 player->tuneLerp.current += player->tuneLerp.step;
1402 } else {
1403 player->tuneLerp.current = player->tuneLerp.goal << 0x10;
1404 }
1405 player->changed.tune = true;
1406 }
1407 if (player->changed.pan || player->changed.reverb) {
1408 if ((player->sfxParamsFlags & SFX_PARAM_LOCK_PAN) || (player->masterPan == 0)) {
1409 voice->pan = player->sfxPan;
1410 } else {
1411 voice->pan = player->masterPan;
1412 }
1413 voice->syncFlags |= AU_VOICE_SYNC_FLAG_PAN_FXMIX;
1414 voice->reverb = player->reverb;
1415 }
1416 }
1417 if (player->changed.volume && voice->priority == manager->priority) {
1418 au_sfx_set_voice_volume(voice, manager, player);
1419 voice->envelopeFlags |= AU_VOICE_ENV_FLAG_VOL_CHANGED;
1420 }
1421 if (player->changed.tune) {
1423 if (player->sfxParamsFlags & SFX_PARAM_LOCK_PITCH) {
1424 pitchShift = (player->coarseTune + (s16)(player->tuneLerp.current >> 0x10)) - player->sfxInstrumentRef->keyBase;
1425 adjustedPitchRatio = au_compute_pitch_ratio(pitchShift + player->fineTune) * player->sfxInstrumentRef->pitchRatio;
1427 } else {
1428 pitchShift = ((player->coarseTune + (s16)(player->tuneLerp.current >> 0x10)) - player->sfxInstrumentRef->keyBase) + player->fineTune;
1429 adjustedPitchRatio = au_compute_pitch_ratio(pitchShift + player->masterPitchShift) * player->sfxInstrumentRef->pitchRatio;
1431 }
1432 if ((voice->priority == manager->priority) && (voice->pitchRatio != adjustedPitchRatio)) {
1433 voice->syncFlags |= AU_VOICE_SYNC_FLAG_PITCH;
1434 voice->pitchRatio = player->pitchRatio;
1435 }
1436 }
1437 player->changed.all = 0;
1438}
1439
1440static void au_sfx_set_voice_volume(AuVoice* voice, SoundManager* manager, SoundPlayer* player) {
1441 s32 x = ((((manager->baseVolume
1442 * player->sfxVolume) >> 0xF)
1443 * player->playVelocity) >> 7)
1444 * (player->volumeLerp.current >> 0x10) >> 0xF;
1445
1446 if (player->sfxParamsFlags & SFX_PARAM_LOCK_VOLUME || player->masterVolume == 0) {
1447 voice->clientVolume = x;
1448 } else {
1449 voice->clientVolume = (x * player->masterVolume) >> 0xF;
1450 }
1451}
1452
1453/*
1454Uses bit masks:
14551F00 = 0001 1111 0000 0000 -> 0001 1111
1456001C = 0000 0000 0001 1100 -> 1110 0000
1457*/
1458static u8 au_sfx_get_random_pan(s32 seed, s32 pan, s32 amplitude) {
1459 s32 tap5, tap3, parity;
1460 s32 lo, hi, random;
1461 s32 retPan;
1462
1463 pan = pan & 0xFF;
1464 tap5 = seed >> 5;
1465 tap3 = seed >> 3;
1466 parity = (tap5 + tap3) & 1;
1467
1468 lo = (seed >> 8) & 0x1F; // bitmask 0x1F00
1469 hi = (seed << 3) & 0xE0; // bitmask 0x001C
1470 random = lo + hi;
1471
1472 if (parity) {
1473 retPan = pan + (((amplitude & 0xFF) * random) >> 8);
1474 } else {
1475 retPan = pan - (((amplitude & 0xFF) * random) >> 8);
1476 }
1477 if (retPan < AU_PAN_MIN) {
1479 } else if (retPan > AU_PAN_MAX) {
1481 }
1482 return retPan;
1483}
1484
1485static void au_SEFCmd_00_SetVolume(SoundManager* manager, SoundPlayer* player) {
1486 player->sfxVolume = *player->sefDataReadPos++;
1487 if (player->sfxVolume != 0) {
1488 player->sfxVolume = AU_VOL_8_TO_16(player->sfxVolume);
1489 }
1490 player->changed.volume = true;
1491}
1492
1493static void au_SEFCmd_01_SetPan(SoundManager* manager, SoundPlayer* player) {
1494 s32 sfxPan = *player->sefDataReadPos++;
1495
1496 player->changed.pan = true;
1497 player->sfxPan = sfxPan;
1498}
1499
1500static void au_SEFCmd_02_SetInstrument(SoundManager* manager, SoundPlayer* player) {
1501 AuFilePos buf = player->sefDataReadPos;
1502 BankSetIndex bank = buf[0];
1503 s32 patch = buf[1];
1504 player->sefDataReadPos += 2;
1505
1506 player->instrumentIndex = patch;
1507 player->sfxInstrumentRef = au_get_instrument(manager->globals, bank, patch, &player->envelope);
1508}
1509
1510static void au_SEFCmd_03_SetReverb(SoundManager* manager, SoundPlayer* player) {
1511 u8 reverb = *player->sefDataReadPos++;
1512
1513 if (player->sfxParamsFlags & SFX_PARAM_LOCK_REVERB) {
1514 reverb = manager->defaultReverbAmt;
1515 }
1516 player->reverb = reverb;
1517 player->changed.reverb = true;
1518}
1519
1520static void au_SEFCmd_04_SetEnvelope(SoundManager* manager, SoundPlayer* player) {
1523
1524 u8 envelope = *player->sefDataReadPos++;
1525
1526 player->envelopePreset = envelope & 0x7F;
1527 other = player->sfxInstrumentRef;
1528
1529 player->sfxInstrument.wavData = other->wavData;
1530 player->sfxInstrument.wavDataLength = other->wavDataLength;
1531 player->sfxInstrument.loopState = other->loopState;
1532 player->sfxInstrument.loopStart = other->loopStart;
1533 player->sfxInstrument.loopEnd = other->loopEnd;
1534 player->sfxInstrument.loopCount = other->loopCount;
1535 player->sfxInstrument.predictor = other->predictor;
1536 player->sfxInstrument.codebookSize = other->codebookSize;
1537 player->sfxInstrument.keyBase = other->keyBase;
1538 player->sfxInstrument.pitchRatio = other->pitchRatio;
1539 player->sfxInstrument.type = other->type;
1540 player->sfxInstrument.useDma = other->useDma;
1541
1543 player->sfxInstrumentRef = &player->sfxInstrument;
1544
1546 if (envPreset != nullptr && envPreset->count != 0) {
1547 player->envelope.cmdListPress = AU_FILE_RELATIVE(envPreset, envPreset->offsets[0].offsetPress);
1548 player->envelope.cmdListRelease = AU_FILE_RELATIVE(envPreset, envPreset->offsets[0].offsetRelease);
1549 }
1550}
1551
1552static void au_SEFCmd_05_CoarseTune(SoundManager* manager, SoundPlayer* player) {
1553 player->coarseTune = (*(s8*)player->sefDataReadPos++) * 100;
1554}
1555
1556static void au_SEFCmd_06_FineTune(SoundManager* manager, SoundPlayer* player) {
1557 player->fineTune = *player->sefDataReadPos++;
1558}
1559
1560static void au_SEFCmd_07_WaitForEnd(SoundManager* manager, SoundPlayer* player) {
1561 if (manager->curVoice->priority == manager->priority) {
1562 player->delay = 2;
1563 player->sefDataReadPos--;
1564 }
1565}
1566
1567static void au_SEFCmd_08_PitchSweep(SoundManager* manager, SoundPlayer* player) {
1568 s32 hi = player->sefDataReadPos[0];
1569 s32 lo = player->sefDataReadPos[1];
1570 s16 newValue = (player->sefDataReadPos[2] & 0x7F) * 100;
1571 s16 time = lo + (hi << 8);
1572 player->sefDataReadPos += 3;
1573
1574 if (time <= 0) {
1575 time = 1;
1576 }
1577
1578 player->tuneLerp.time = time;
1579 player->tuneLerp.goal = newValue;
1580 player->tuneLerp.step = ((newValue << 0x10) - player->tuneLerp.current) / time;
1581}
1582
1583static void au_SEFCmd_09_StartLoop(SoundManager* manager, SoundPlayer* player) {
1584 s32 loopIterCount = *player->sefDataReadPos++;
1585
1586 player->loopStartPos = player->sefDataReadPos;
1587 player->loopIterCount = loopIterCount;
1588}
1589
1590static void au_SEFCmd_0A_EndLoop(SoundManager* manager, SoundPlayer* player) {
1591 if (player->loopIterCount == 0 || --player->loopIterCount != 0) {
1592 player->sefDataReadPos = player->loopStartPos;
1593 }
1594}
1595
1596static void au_SEFCmd_0B_WaitForRelease(SoundManager* manager, SoundPlayer* player) {
1597 if (player->playLength != 0) {
1598 player->delay = 3;
1599 player->sefDataReadPos--;
1600 }
1601}
1602
1603static void au_SEFCmd_0C_SetCurrentVolume(SoundManager* manager, SoundPlayer* player) {
1604 s32 vol = *player->sefDataReadPos++;
1605
1606 if (vol != 0) {
1608 }
1609 player->volumeLerp.current = vol;
1610 player->changed.volume = true;
1611}
1612
1613static void au_SEFCmd_0D_VolumeRamp(SoundManager* manager, SoundPlayer* player) {
1614 s32 hi = player->sefDataReadPos[0];
1615 s32 lo = player->sefDataReadPos[1];
1616 s32 newValue = player->sefDataReadPos[2];
1617 s16 time = lo + (hi << 8);
1618 player->sefDataReadPos += 3;
1619
1620 if (newValue != 0) {
1622 }
1623 if (time <= 0) {
1624 time = 1;
1625 }
1626
1627 player->volumeLerp.time = time;
1628 player->volumeLerp.goal = newValue;
1629 player->volumeLerp.step = ((newValue << 0x10) - player->volumeLerp.current) / time;
1630}
1631
1632static void au_SEFCmd_0E_SetAlternativeSound(SoundManager* manager, SoundPlayer* player) {
1633 s32 hi = player->sefDataReadPos[1];
1634 s32 lo = player->sefDataReadPos[2];
1635 AuFilePos pos = AU_FILE_RELATIVE(manager->sefData, (hi << 8) + lo);
1636 u8 type = player->sefDataReadPos[0];
1637 player->sefDataReadPos += 3;
1638
1639 player->alternativeType = type;
1640 switch (type) {
1641 case 1:
1642 player->alternativeDataPos = pos;
1643 break;
1644 case 2:
1645 player->alternativeDataPos = pos;
1646 break;
1647 case 3:
1648 player->alternativeDataPos = pos;
1649 break;
1650 default:
1651 player->alternativeDataPos = nullptr;
1652 break;
1653 }
1654}
1655
1656static void au_SEFCmd_0F_Stop(SoundManager* manager, SoundPlayer* player) {
1657 AuVoice* voice = manager->curVoice;
1658 if (voice->priority == manager->priority) {
1659 au_reset_voice(voice, manager->curVoiceIndex);
1660 }
1661}
1662
1663static void au_SEFCmd_10_Jump(SoundManager* manager, SoundPlayer* player) {
1664 AuFilePos buf = player->sefDataReadPos;
1665 player->sefReadStart = &buf[2];
1666 player->sefDataReadPos = AU_FILE_RELATIVE(manager->sefData, (buf[0] << 8) + buf[1]);
1667}
1668
1669static void au_SEFCmd_11_Restart(SoundManager* manager, SoundPlayer* player) {
1670 player->sefDataReadPos = player->sefReadStart;
1671}
1672
1673static void au_SEFCmd_12_NOP(SoundManager* manager, SoundPlayer* player) {
1674}
1675
1676static void au_SEFCmd_13_SetRandomPitch(SoundManager* manager, SoundPlayer* player) {
1677 player->randomPitch = *player->sefDataReadPos++;
1678}
1679
1680static void au_SEFCmd_14_SetRandomVelocity(SoundManager* manager, SoundPlayer* player) {
1681 player->randomVelocity = *player->sefDataReadPos++;
1682}
1683
1684static void au_SEFCmd_15_SetRandomUnused(SoundManager* manager, SoundPlayer* player) {
1685 player->randomUnused = *player->sefDataReadPos++;
1686}
1687
1688static void au_SEFCmd_16_SetEnvelopePress(SoundManager* manager, SoundPlayer* player) {
1689 AuFilePos buf = player->sefDataReadPos;
1690 s32 offset = (buf[0] << 8) + buf[1];
1691
1692 if (offset != 0) {
1693 player->envelopCustomPressProfile = AU_FILE_RELATIVE(manager->sefData, offset);
1694 } else {
1695 player->envelopCustomPressProfile = nullptr;
1696 }
1697
1698 player->sefDataReadPos = &buf[2];
1699}
1700
1701static void au_SEFCmd_17_PlaySound(SoundManager* manager, SoundPlayer* player) {
1702 AuFilePos buf = player->sefDataReadPos;
1703 u32 i;
1704
1705 for (i = 0; i < ARRAY_COUNT(manager->customCmdList); i++) {
1706 if (manager->customCmdList[i].data[0] == 0) {
1707 manager->customCmdList[i].data[0] = buf[1] + (buf[0] << 8);
1708 manager->customCmdList[i].data[1] = buf[3] + (buf[2] << 8);
1709 break;
1710 }
1711 }
1712 player->sefDataReadPos = &buf[4];
1713}
1714
1715static void au_SEFCmd_18_SetAlternativeVolume(SoundManager* manager, SoundPlayer* player) {
1716 player->alternativeVolume = *player->sefDataReadPos++;
1717 if (player->alternativeVolume != 0) {
1719 }
1720}
1721
1722/*
1723Uses bit masks:
1724780 = 0111 1000 0000 -> 0000 1111
172501E = 0000 0001 1110 -> 1111 0000
1726*/
1727static s32 au_sfx_get_random_pitch(s32 seed, s32 amplitude, s32 pitch) {
1728 s32 lo = (seed >> 7) & 0xF; // bitmask 0x780
1729 s32 hi = (seed << 3) & 0xF0; // bitmask 0x01E
1730 s32 random = (lo + hi);
1731 s32 tap5 = (seed >> 5);
1732 s32 tap2 = (seed >> 2);
1733 s32 parity = (tap5 + tap2) & 1;
1734
1735 if (parity) {
1736 return pitch + ((amplitude * 5 * random) >> 8);
1737 } else {
1738 return pitch - ((amplitude * 5 * random) >> 8);
1739 }
1740}
1741
1742/*
1743Uses bit masks:
1744CC = 1100 1100 -> 0011 0011
174513 = 0001 0011 -> 0100 1100
1746*/
1747static u8 au_sfx_get_random_vol(s32 seed, s32 amplitude, s32 volume) {
1748 s32 lo = (seed & 0xCC) >> 2;
1749 s32 hi = (seed & 0x13) << 2;
1750 s32 random = lo + hi;
1751
1752 return volume * (0x8000 - (amplitude * random)) >> 0xF;
1753}
1754
1755static void au_sfx_reset_players(SoundManager* manager) {
1756 s32 i;
1757
1758 for (i = 0; i < ARRAY_COUNT(manager->players); i++) {
1759 SoundPlayer* player = &manager->players[i];
1760 player->sefDataReadPos = BlankSEFData;
1761 player->alternativeDataPos = nullptr;
1764 player->delay = 1;
1765 player->priority = 0;
1766 player->exclusiveID = 0;
1767 }
1768}
BSS s32 PopupMenu_SelectedIndex
u8 cmdListOneShot[8]
Definition audio.h:734
u8 randomVelocity
Definition audio.h:758
@ SND_MANAGER_STATE_DISABLED
Definition audio.h:365
@ SND_MANAGER_STATE_ENABLED
Definition audio.h:364
f32 pitchRatio
Definition audio.h:729
u8 * cmdListPress
Definition audio.h:658
ADPCM_STATE * loopState
Definition audio.h:677
Instrument * sfxInstrumentRef
Definition audio.h:725
u8 instrumentIndex
Definition audio.h:753
s16_16 step
Definition audio.h:703
s16 * predictor
Definition audio.h:681
u16 playLength
Definition audio.h:743
AuFilePos sefDataReadPos
Definition audio.h:721
s16_16 current
Definition audio.h:702
@ AU_FX_CUSTOM_0
Definition audio.h:161
s8 alternativeType
Definition audio.h:736
u8 * cmdListRelease
Definition audio.h:659
@ ENV_CMD_END
Definition audio.h:257
b8 useDma
Definition audio.h:689
SoundLerp volumeLerp
Definition audio.h:733
u8 randomPitch
Definition audio.h:757
s16 coarseTune
Definition audio.h:744
#define AU_PAN_MIN
Definition audio.h:65
s32 loopEnd
Definition audio.h:679
s16 masterPitchShift
unused; presumably another random parameter matching randomPitch and randomVelocity
Definition audio.h:760
u8 masterPan
Definition audio.h:762
SoundPlayChange changed
Definition audio.h:728
SoundLerp tuneLerp
Definition audio.h:732
u8 reverb
Definition audio.h:752
s16 alternativeVolume
Definition audio.h:731
AuFilePos alternativeDataPos
Definition audio.h:735
u8 envelopePreset
Definition audio.h:754
#define AU_FILE_RELATIVE(base, offset)
Definition audio.h:43
#define AU_PAN_MID
Definition audio.h:66
BankSetIndex
The bank indices used by audio assets when choosing an intrument.
Definition audio.h:385
u32 wavDataLength
Definition audio.h:676
#define AU_MAX_VOLUME_8
Definition audio.h:61
s32 loopCount
Definition audio.h:680
Instrument sfxInstrument
Definition audio.h:726
s16 masterVolume
Definition audio.h:761
@ AU_VOICE_SYNC_FLAG_PAN_FXMIX
Definition audio.h:151
@ AU_VOICE_SYNC_FLAG_PITCH
Definition audio.h:150
@ AU_VOICE_SYNC_FLAG_ALL
Definition audio.h:148
s32 loopStart
Definition audio.h:678
u8 priority
Definition audio.h:748
@ FX_BUS_SOUND
Definition audio.h:235
s16 time
Definition audio.h:704
u8 triggers
Definition audio.h:737
u8 * wavData
Definition audio.h:675
u8 exclusiveID
Definition audio.h:749
#define AU_FRAME_USEC
Definition audio.h:27
EnvelopeData envelope
Definition audio.h:723
s8 randomUnused
Definition audio.h:759
u8 sfxParamsFlags
Definition audio.h:750
#define DEFAULT_KEYBASE
Definition audio.h:59
u16 curSoundID
Definition audio.h:747
u16 sections[8]
Definition audio.h:947
#define AU_PAN_MAX
Definition audio.h:67
@ SND_PLAYER_STATE_INIT
Definition audio.h:360
@ SND_PLAYER_STATE_CONTINUE
Definition audio.h:359
EnvelopePreset * envelopes
Definition audio.h:696
u16 section2000
Definition audio.h:948
s16 sfxVolume
Definition audio.h:730
s8 fineTune
Definition audio.h:745
u16 keyBase
Definition audio.h:683
u16 codebookSize
Definition audio.h:682
u16 delay
Definition audio.h:742
s8 * loopStartPos
Definition audio.h:739
#define AU_MAX_VOLUME_32
Definition audio.h:63
u8 loopIterCount
Definition audio.h:740
s16 goal
Definition audio.h:705
u8 unused_A0
Definition audio.h:756
#define AU_MAX_VOLUME_16
Definition audio.h:62
u8 * AuFilePos
Definition audio.h:11
#define AU_MAX_BUS_VOLUME
Definition audio.h:40
@ AU_VOICE_ENV_FLAG_KEY_RELEASED
Definition audio.h:143
@ AU_VOICE_ENV_FLAG_VOL_CHANGED
Definition audio.h:144
u8 * envelopCustomPressProfile
Definition audio.h:724
@ ENV_TIME_280MS
Definition audio.h:322
@ ENV_TIME_1100MS
Definition audio.h:303
@ ENV_TIME_1800MS
Definition audio.h:296
@ ENV_TIME_2UNITS
Definition audio.h:353
@ ENV_TIME_1400MS
Definition audio.h:300
@ ENV_TIME_3S
Definition audio.h:290
@ ENV_TIME_1S
Definition audio.h:304
@ ENV_TIME_450MS
Definition audio.h:315
@ ENV_TIME_900MS
Definition audio.h:306
@ ENV_TIME_550MS
Definition audio.h:313
@ ENV_TIME_290MS
Definition audio.h:321
u8 playVelocity
Definition audio.h:755
#define AU_VOL_8_TO_16(vol)
Definition audio.h:70
AuFilePos sefReadStart
Definition audio.h:727
#define AU_VOL_8_TO_32(vol)
Definition audio.h:72
u8 type
Definition audio.h:688
#define SFX_QUEUE_SIZE
Definition audio.h:108
u8 hasExtraSection
Definition audio.h:945
u8 sfxPan
Definition audio.h:751
void au_BGMCmd_F1_TrackTremoloRate(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_F7_ReverbType(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_FF_Special(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_FD_EventTrigger(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_FC_Branch(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_FE_Detour(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_F4_SubTrackRandomPan(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_E3(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_EA_InstrumentPan(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_ED_InstrumentCoarseTune(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_EC_TrackVolume(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_E2_MasterDetune(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_E5_MasterVolumeFade(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_E0_MasterTempo(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_E8_TrackOverridePatch(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_F0_TrackTremolo(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_EE_InstrumentFineTune(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_F5_UseInstrument(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_EC_TrackDetune(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_NOP(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_F2_TrackTremoloDepth(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_E6_MasterEffect(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_EB_InstrumentReverb(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_E9_InstrumentVolume(BGMPlayer *arg0, BGMPlayerTrack *track)
void au_BGMCmd_F6_InstrumentVolumeLerp(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_E1_MasterVolume(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_F3_TrackTremoloStop(BGMPlayer *player, BGMPlayerTrack *track)
void au_BGMCmd_E4_MasterTempoFade(BGMPlayer *player, BGMPlayerTrack *track)
void au_reset_voice(AuVoice *voice, u8 voiceIdx)
Definition engine.c:397
void au_reset_nonfree_voice(AuVoice *arg0, u8 arg1)
Definition engine.c:388
f32 au_compute_pitch_ratio(s32 tuning)
Converts a linear pitch value (in cents) into a frequency ratio suitable for adjusting playback speed...
Definition engine.c:410
Instrument * au_get_instrument(AuGlobals *globals, BankSetIndex bank, s32 patch, EnvelopeData *arg3)
Note that bank is supplied as BankSetIndex and not BankSet, which means it will be used to perform a ...
Definition engine.c:506
void au_fade_init(Fade *fade, s32 time, s32 startValue, s32 endValue)
Definition engine.c:421
void au_fade_set_volume(u8 arg0, u16 arg1, s32 arg2)
Definition engine.c:457
Vec3s pos
Definition demo_api.c:17
@ VOL_LEVEL_FULL
Definition enums.h:1822
@ VOL_LEVEL_5
Definition enums.h:1819
@ VOL_LEVEL_2
Definition enums.h:1816
@ VOL_LEVEL_4
Definition enums.h:1818
@ VOL_LEVEL_MUTE
Definition enums.h:1814
@ VOL_LEVEL_6
Definition enums.h:1820
@ VOL_LEVEL_3
Definition enums.h:1817
@ VOL_LEVEL_7
Definition enums.h:1821
@ VOL_LEVEL_1
Definition enums.h:1815
@ SOUND_ID_UPPER_MASK
Definition enums.h:537
@ SOUND_ID_ADJUST
Definition enums.h:529
@ SOUND_ID_UNK_INDEX_MASK
Definition enums.h:535
@ SOUND_ID_TRIGGER_MASK
Definition enums.h:530
@ SOUND_ID_STOP
Definition enums.h:526
@ SOUND_ID_UNK
Definition enums.h:528
@ SOUND_ID_LOWER
Definition enums.h:527
@ SOUND_LRAW_CHEERING
Definition enums.h:1154
@ SOUND_NONE
Definition enums.h:550
@ SOUND_SHORT_CLAP
Definition enums.h:1155
#define ARRAY_COUNT(arr)
Definition macros.h:39
#define SQ(x)
Definition macros.h:177
s32 CUSTOM_ECHO_PARAMS_1[]
Definition sfx_player.c:103
u8 EnvelopeReleaseDefault[]
Definition sfx_player.c:322
u8 EnvelopePressDefault[]
Definition sfx_player.c:317
s32 CUSTOM_SMALL_ROOM_PARAMS[]
Definition sfx_player.c:92
void au_sfx_set_state(SoundManager *manager, s32 state)
Definition sfx_player.c:739
EnvelopePreset DummyInstrumentEnvelope
Definition sfx_player.c:312
void(* SefCmdHandlers[])(SoundManager *, SoundPlayer *)
Definition sfx_player.c:200
MusicTriggeredSound MusicSounds[]
Definition sfx_player.c:129
s32 AuEnvelopeIntervals[]
Definition sfx_player.c:359
s16 au_sfx_manager_audio_frame_update(SoundManager *manager)
u8 EnvelopeReleaseDefaultFast[]
Definition sfx_player.c:327
void au_sfx_init(SoundManager *manager, u8 priority, u8 busID, AuGlobals *globals, u8 minVoiceIdx)
Definition sfx_player.c:466
#define NEXT_POLY_TRACK
#define SEC(x)
Definition sfx_player.c:357
s16 DummyInstrumentCodebook[32]
Definition sfx_player.c:69
u8 AmbientSoundIDtoMSEQFileIndex[]
Definition sfx_player.c:346
u8 SFXEnvelopeFastData[]
Definition sfx_player.c:143
s32 CUSTOM_ECHO_PARAMS_3[]
Definition sfx_player.c:121
EnvelopePreset * SFXEnvelopePresets[]
Definition sfx_player.c:181
EnvelopePreset SFXEnvelopeFast
Definition sfx_player.c:138
s8 SeqCmdArgCounts[]
Definition sfx_player.c:272
f32 AlTuneScaling[]
Definition sfx_player.c:378
s32 * AU_FX_CUSTOM_PARAMS[0]
Definition reverb.c:106
s8 BgmCustomEnvLookup[]
Definition sfx_player.c:335
u8 SFXEnvelopeSlowData[]
Definition sfx_player.c:160
EnvelopePreset SFXEnvelopeSlow
Definition sfx_player.c:155
s32 CUSTOM_ECHO_PARAMS_2[]
Definition sfx_player.c:112
void au_sfx_enqueue_event(SoundManager *manager, u32 soundID, s16 volume, s16 pitchShift, u8 pan)
Definition sfx_player.c:590
u16 PerceptualVolumeLevels[]
Volume steps use squared values so each level represents linear power increase, matching loudness per...
Definition sfx_player.c:299
void au_sfx_try_sound(SoundManager *manager, SoundRequest *request, SoundManagerCustomCmdList *customSEF)
Definition sfx_player.c:747
u8 BlankMseqData[]
Definition sfx_player.c:287
s8 BgmTicksRates[]
Definition sfx_player.c:279
s32 D_800783B0[]
Definition sfx_player.c:177
SoundEffectParamFlags
Definition sfx_player.c:54
@ SFX_PARAM_MODE_COMPACT
Definition sfx_player.c:60
@ SFX_PARAM_MODE_SEQUENCE
Definition sfx_player.c:58
@ SFX_PARAM_LOCK_PITCH
Definition sfx_player.c:65
@ SFX_PARAM_MODE_MASK
Definition sfx_player.c:61
@ SFX_PARAM_LOCK_VOLUME
Definition sfx_player.c:63
@ SFX_PARAM_LOCK_PAN
Definition sfx_player.c:64
@ SFX_PARAM_MODE_BASIC
Definition sfx_player.c:56
@ SFX_PARAM_LOCK_REVERB
Definition sfx_player.c:66
void au_sfx_clear_queue(SoundManager *manager)
Definition sfx_player.c:571
void(* CurrentSefCmdHandler)(SoundManager *, SoundPlayer *)
Definition sfx_player.c:464
u8 DummyInstrumentWavData[190]
Definition sfx_player.c:76
s32 au_sfx_set_reverb_type(SoundManager *manager, s32 arg1)
Definition sfx_player.c:719
void(* SeqCmdHandlers[])(BGMPlayer *, BGMPlayerTrack *)
Definition sfx_player.c:237
void au_sfx_load_groups_from_SEF(SoundManager *manager)
Definition sfx_player.c:551
u8 BlankSEFData[]
Definition sfx_player.c:228
void au_sfx_begin_video_frame(SoundManager *manager)
Definition sfx_player.c:618