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 = NULL;
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;
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) {
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 == NULL) {
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 != NULL) {
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) {
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 == NULL) {
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 != NULL) {
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) {
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 == NULL || 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) {
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 == NULL) {
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) {
901 break;
902 }
903 }
904 }
905
906 if (!foundPlayer) {
907 playerIndex = soundInfo & 0x7;
908 player = &manager->players[playerIndex];
909 if (player->priority <= priority) {
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 == NULL) {
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 == NULL || 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 = NULL;
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;
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 = NULL;
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 = NULL;
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 = NULL;
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 != NULL) {
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 = NULL;
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 s32 a;
1182 s32 b;
1183
1184 switch (player->state) {
1186 if (voice->priority != manager->priority) {
1187 player->sefDataReadPos = NULL;
1188 player->curSoundID = SOUND_NONE;
1189 player->priority = 0;
1190 } else {
1191 if (!(player->sfxParamsFlags & SFX_PARAM_LOCK_PITCH)) {
1193 ((player->tuneLerp.current >> 0x10) - player->sfxInstrumentRef->keyBase) + player->masterPitchShift) * player->sfxInstrumentRef->pitchRatio;
1194 if (voice->pitchRatio != player->pitchRatio) {
1195 voice->syncFlags |= AU_VOICE_SYNC_FLAG_PITCH;
1196 voice->pitchRatio = player->pitchRatio;
1197 }
1198 }
1199
1200 if (!(player->sfxParamsFlags & SFX_PARAM_LOCK_PAN) && player->masterPan != 0) {
1201 pan = player->masterPan;
1202 } else {
1203 pan = player->sfxPan;
1204 }
1205 if (voice->pan != pan) {
1206 voice->pan = pan;
1207 voice->syncFlags |= AU_VOICE_SYNC_FLAG_PAN_FXMIX;
1208 }
1209
1210 volume = au_sfx_get_scaled_volume(manager, player);
1211 if (voice->clientVolume != volume) {
1212 voice->clientVolume = volume;
1213 voice->envelopeFlags |= AU_VOICE_ENV_FLAG_VOL_CHANGED;
1214 }
1215 }
1216 break;
1218 au_SEFCmd_02_SetInstrument(manager, player); // 2 bytes
1219 au_SEFCmd_00_SetVolume(manager, player); // 1 byte
1220 au_SEFCmd_01_SetPan(manager, player); // 1 byte
1221 au_SEFCmd_03_SetReverb(manager, player); // 1 byte
1222 tune = (*player->sefDataReadPos++ & 0x7F) * 100; // 1 byte
1223 player->randomPitch = (*player->sefDataReadPos & 0xF) * 8; // 1 byte
1224
1225 if (player->randomPitch != 0) {
1226 player->tuneLerp.current = au_sfx_get_random_pitch(manager->randomValue, player->randomPitch, tune) << 0x10;
1227 } else {
1228 player->tuneLerp.current = tune << 0x10;
1229 }
1230 if (player->sfxParamsFlags & SFX_PARAM_LOCK_PITCH) {
1231 tune = (player->tuneLerp.current >> 0x10) - player->sfxInstrumentRef->keyBase;
1232 } else {
1233 tune = ((player->tuneLerp.current >> 0x10) - player->sfxInstrumentRef->keyBase) + player->masterPitchShift;
1234 }
1235 player->pitchRatio = au_compute_pitch_ratio(tune) * player->sfxInstrumentRef->pitchRatio;
1236
1237 if (voice->priority <= manager->priority) {
1239 if (!(player->sfxParamsFlags & SFX_PARAM_LOCK_PAN) && player->masterPan != 0) {
1240 voice->pan = player->masterPan;
1241 } else {
1242 voice->pan = player->sfxPan;
1243 }
1244
1245 voice->reverb = player->reverb;
1246 voice->clientVolume = au_sfx_get_scaled_volume(manager, player);
1247 voice->envelope.cmdListPress = player->envelope.cmdListPress;
1248 voice->envelope.cmdListRelease = player->envelope.cmdListRelease;
1249 voice->instrument = player->sfxInstrumentRef;
1250 voice->pitchRatio = player->pitchRatio;
1251 voice->syncFlags = AU_VOICE_SYNC_FLAG_ALL;
1252 voice->priority = manager->priority;
1253 voice->clientPriority = voice->priority;
1254 voice->busID = manager->busID;
1255 }
1257 break;
1258 default:
1259 player->sefDataReadPos = NULL;
1260 player->curSoundID = SOUND_NONE;
1261 player->priority = 0;
1262 break;
1263 }
1264}
1265
1266static s16 au_sfx_get_scaled_volume(SoundManager* manager, SoundPlayer* player) {
1267 s32 outVolume;
1268
1269 outVolume = (manager->baseVolume * player->sfxVolume) >> 15;
1270 if (!(player->sfxParamsFlags & SFX_PARAM_LOCK_VOLUME) && (player->masterVolume != 0)) {
1271 outVolume = (outVolume * player->masterVolume) >> 15;
1272 }
1273 return outVolume;
1274}
1275
1276static void au_sfx_update_sequence(SoundManager* manager, SoundPlayer* player, AuVoice* voice, u8 voiceIdx) {
1277 s32* var_v0_3;
1278 s32 pitchShift;
1279 s32 temp_a0;
1280 u8 opcode;
1281 u32 playLength;
1284
1286 if (player->state == SND_PLAYER_STATE_INIT) {
1288 if (voice->priority == manager->priority) {
1290 }
1291 }
1292
1293 if (player->alternativeDataPos != NULL) {
1294 if (player->triggers == 1) {
1295 player->sefDataReadPos = player->alternativeDataPos;
1296 player->alternativeDataPos = NULL;
1297 player->triggers = 0;
1298 player->delay = 1;
1299 }
1300 }
1301 if (player->triggers == 2) {
1302 player->changed.volume = TRUE;
1303 player->sfxVolume = player->alternativeVolume;
1304 }
1305 player->delay--;
1306 while (player->delay == 0) {
1308 opcode = *player->sefDataReadPos++;
1309 if (opcode < 0x80) {
1310 if (opcode == 0) {
1311 if (voice->priority == manager->priority) {
1313 }
1314 player->sefDataReadPos = NULL;
1315 player->curSoundID = SOUND_NONE;
1316 player->priority = 0;
1317 player->exclusiveID = 0;
1318 return;
1319 }
1320 if (opcode >= 0x78) {
1321 // long delay
1322 player->delay = (u8)(*player->sefDataReadPos++) + ((opcode & 7) << 8) + 0x78;
1323 } else {
1324 // short delay
1325 player->delay = opcode;
1326 }
1327 } else if (opcode < 0xD8) {
1328 // play sound
1329 // (opcode & 0x7F) = pitch
1330 if (player->randomPitch != 0) {
1331 player->tuneLerp.current = au_sfx_get_random_pitch(manager->randomValue, player->randomPitch, (opcode & 0x7F) * 100) << 0x10;
1332 } else {
1333 player->tuneLerp.current = ((opcode & 0x7F) * 100) << 0x10;
1334 }
1335
1336 if (player->randomVelocity != 0) {
1337 player->playVelocity = au_sfx_get_random_vol(manager->randomValue, player->randomVelocity, player->sefDataReadPos[0] & 0x7F);
1338 } else {
1339 player->playVelocity = player->sefDataReadPos[0] & 0x7F;
1340 }
1341
1342 playLength = player->sefDataReadPos[1];
1343 if (playLength >= 0xC0) {
1344 playLength = player->sefDataReadPos[2] + ((playLength & 0x3F) << 8) + 0xC0;
1345 player->sefDataReadPos += 3;
1346 } else {
1347 player->sefDataReadPos += 2;
1348 }
1349 player->playLength = playLength;
1350
1351 if (voice->priority <= manager->priority) {
1353 if ((player->sfxParamsFlags & SFX_PARAM_LOCK_PAN) || (player->masterPan == 0)) {
1354 voice->pan = player->sfxPan;
1355 } else {
1356 voice->pan = player->masterPan;
1357 }
1358
1359 voice->reverb = player->reverb;
1360 au_sfx_set_voice_volume(voice, manager, player);
1361 if (player->envelopCustomPressProfile == NULL) {
1362 voice->envelope.cmdListPress = player->envelope.cmdListPress;
1363 voice->envelope.cmdListRelease = player->envelope.cmdListRelease;
1364 } else {
1365 voice->envelope.cmdListPress = player->envelopCustomPressProfile;
1366 voice->envelope.cmdListRelease = player->envelope.cmdListRelease;
1367 }
1368
1369 voice->instrument = player->sfxInstrumentRef;
1370 voice->busID = manager->busID;
1371
1372 voice->priority = manager->priority;
1373 voice->syncFlags = AU_VOICE_SYNC_FLAG_ALL;
1375 voice->clientPriority = manager->priority;
1376 player->changed.tune = TRUE;
1377 }
1378 } else {
1379 s32 index = opcode - 0xE0;
1382 }
1383 }
1384
1385 if (player->volumeLerp.time != 0) {
1386 player->volumeLerp.time--;
1387 if (player->volumeLerp.time != 0) {
1388 player->volumeLerp.current += player->volumeLerp.step;
1389 } else {
1390 player->volumeLerp.current = player->volumeLerp.goal << 0x10;
1391 }
1392 player->changed.volume = TRUE;
1393 }
1394
1395 if (!startedNewVoice) {
1396 if (player->playLength != 0) {
1397 player->playLength--;
1398 if ((player->playLength == 0) && (voice->priority == manager->priority)) {
1399 voice->envelopeFlags |= AU_VOICE_ENV_FLAG_KEY_RELEASED;
1400 }
1401 }
1402 if (player->tuneLerp.time != 0) {
1403 player->tuneLerp.time--;
1404 if (player->tuneLerp.time != 0) {
1405 player->tuneLerp.current += player->tuneLerp.step;
1406 } else {
1407 player->tuneLerp.current = player->tuneLerp.goal << 0x10;
1408 }
1409 player->changed.tune = TRUE;
1410 }
1411 if (player->changed.pan || player->changed.reverb) {
1412 if ((player->sfxParamsFlags & SFX_PARAM_LOCK_PAN) || (player->masterPan == 0)) {
1413 voice->pan = player->sfxPan;
1414 } else {
1415 voice->pan = player->masterPan;
1416 }
1417 voice->syncFlags |= AU_VOICE_SYNC_FLAG_PAN_FXMIX;
1418 voice->reverb = player->reverb;
1419 }
1420 }
1421 if (player->changed.volume && voice->priority == manager->priority) {
1422 au_sfx_set_voice_volume(voice, manager, player);
1423 voice->envelopeFlags |= AU_VOICE_ENV_FLAG_VOL_CHANGED;
1424 }
1425 if (player->changed.tune) {
1427 if (player->sfxParamsFlags & SFX_PARAM_LOCK_PITCH) {
1428 pitchShift = (player->coarseTune + (s16)(player->tuneLerp.current >> 0x10)) - player->sfxInstrumentRef->keyBase;
1429 adjustedPitchRatio = au_compute_pitch_ratio(pitchShift + player->fineTune) * player->sfxInstrumentRef->pitchRatio;
1431 } else {
1432 pitchShift = ((player->coarseTune + (s16)(player->tuneLerp.current >> 0x10)) - player->sfxInstrumentRef->keyBase) + player->fineTune;
1433 adjustedPitchRatio = au_compute_pitch_ratio(pitchShift + player->masterPitchShift) * player->sfxInstrumentRef->pitchRatio;
1435 }
1436 if ((voice->priority == manager->priority) && (voice->pitchRatio != adjustedPitchRatio)) {
1437 voice->syncFlags |= AU_VOICE_SYNC_FLAG_PITCH;
1438 voice->pitchRatio = player->pitchRatio;
1439 }
1440 }
1441 player->changed.all = 0;
1442}
1443
1444static void au_sfx_set_voice_volume(AuVoice* voice, SoundManager* manager, SoundPlayer* player) {
1445 s32 x = ((((manager->baseVolume
1446 * player->sfxVolume) >> 0xF)
1447 * player->playVelocity) >> 7)
1448 * (player->volumeLerp.current >> 0x10) >> 0xF;
1449
1450 if (player->sfxParamsFlags & SFX_PARAM_LOCK_VOLUME || player->masterVolume == 0) {
1451 voice->clientVolume = x;
1452 } else {
1453 voice->clientVolume = (x * player->masterVolume) >> 0xF;
1454 }
1455}
1456
1457/*
1458Uses bit masks:
14591F00 = 0001 1111 0000 0000 -> 0001 1111
1460001C = 0000 0000 0001 1100 -> 1110 0000
1461*/
1462static u8 au_sfx_get_random_pan(s32 seed, s32 pan, s32 amplitude) {
1463 s32 tap5, tap3, parity;
1464 s32 lo, hi, random;
1465 s32 retPan;
1466
1467 pan = pan & 0xFF;
1468 tap5 = seed >> 5;
1469 tap3 = seed >> 3;
1470 parity = (tap5 + tap3) & 1;
1471
1472 lo = (seed >> 8) & 0x1F; // bitmask 0x1F00
1473 hi = (seed << 3) & 0xE0; // bitmask 0x001C
1474 random = lo + hi;
1475
1476 if (parity) {
1477 retPan = pan + (((amplitude & 0xFF) * random) >> 8);
1478 } else {
1479 retPan = pan - (((amplitude & 0xFF) * random) >> 8);
1480 }
1481 if (retPan < AU_PAN_MIN) {
1483 } else if (retPan > AU_PAN_MAX) {
1485 }
1486 return retPan;
1487}
1488
1489static void au_SEFCmd_00_SetVolume(SoundManager* manager, SoundPlayer* player) {
1490 player->sfxVolume = *player->sefDataReadPos++;
1491 if (player->sfxVolume != 0) {
1492 player->sfxVolume = AU_VOL_8_TO_16(player->sfxVolume);
1493 }
1494 player->changed.volume = TRUE;
1495}
1496
1497static void au_SEFCmd_01_SetPan(SoundManager* manager, SoundPlayer* player) {
1498 s32 sfxPan = *player->sefDataReadPos++;
1499
1500 player->changed.pan = TRUE;
1501 player->sfxPan = sfxPan;
1502}
1503
1504static void au_SEFCmd_02_SetInstrument(SoundManager* manager, SoundPlayer* player) {
1505 AuFilePos buf = player->sefDataReadPos;
1506 BankSetIndex bank = buf[0];
1507 s32 patch = buf[1];
1508 player->sefDataReadPos += 2;
1509
1510 player->instrumentIndex = patch;
1511 player->sfxInstrumentRef = au_get_instrument(manager->globals, bank, patch, &player->envelope);
1512}
1513
1514static void au_SEFCmd_03_SetReverb(SoundManager* manager, SoundPlayer* player) {
1515 u8 reverb = *player->sefDataReadPos++;
1516
1517 if (player->sfxParamsFlags & SFX_PARAM_LOCK_REVERB) {
1518 reverb = manager->defaultReverbAmt;
1519 }
1520 player->reverb = reverb;
1521 player->changed.reverb = TRUE;
1522}
1523
1524static void au_SEFCmd_04_SetEnvelope(SoundManager* manager, SoundPlayer* player) {
1527
1528 u8 envelope = *player->sefDataReadPos++;
1529
1530 player->envelopePreset = envelope & 0x7F;
1531 other = player->sfxInstrumentRef;
1532
1533 player->sfxInstrument.wavData = other->wavData;
1534 player->sfxInstrument.wavDataLength = other->wavDataLength;
1535 player->sfxInstrument.loopState = other->loopState;
1536 player->sfxInstrument.loopStart = other->loopStart;
1537 player->sfxInstrument.loopEnd = other->loopEnd;
1538 player->sfxInstrument.loopCount = other->loopCount;
1539 player->sfxInstrument.predictor = other->predictor;
1540 player->sfxInstrument.codebookSize = other->codebookSize;
1541 player->sfxInstrument.keyBase = other->keyBase;
1542 player->sfxInstrument.pitchRatio = other->pitchRatio;
1543 player->sfxInstrument.type = other->type;
1544 player->sfxInstrument.useDma = other->useDma;
1545
1547 player->sfxInstrumentRef = &player->sfxInstrument;
1548
1550 if (envPreset != NULL && envPreset->count != 0) {
1551 player->envelope.cmdListPress = AU_FILE_RELATIVE(envPreset, envPreset->offsets[0].offsetPress);
1552 player->envelope.cmdListRelease = AU_FILE_RELATIVE(envPreset, envPreset->offsets[0].offsetRelease);
1553 }
1554}
1555
1556static void au_SEFCmd_05_CoarseTune(SoundManager* manager, SoundPlayer* player) {
1557 player->coarseTune = (*(s8*)player->sefDataReadPos++) * 100;
1558}
1559
1560static void au_SEFCmd_06_FineTune(SoundManager* manager, SoundPlayer* player) {
1561 player->fineTune = *player->sefDataReadPos++;
1562}
1563
1564static void au_SEFCmd_07_WaitForEnd(SoundManager* manager, SoundPlayer* player) {
1565 if (manager->curVoice->priority == manager->priority) {
1566 player->delay = 2;
1567 player->sefDataReadPos--;
1568 }
1569}
1570
1571static void au_SEFCmd_08_PitchSweep(SoundManager* manager, SoundPlayer* player) {
1572 s32 hi = player->sefDataReadPos[0];
1573 s32 lo = player->sefDataReadPos[1];
1574 s16 newValue = (player->sefDataReadPos[2] & 0x7F) * 100;
1575 s16 time = lo + (hi << 8);
1576 player->sefDataReadPos += 3;
1577
1578 if (time <= 0) {
1579 time = 1;
1580 }
1581
1582 player->tuneLerp.time = time;
1583 player->tuneLerp.goal = newValue;
1584 player->tuneLerp.step = ((newValue << 0x10) - player->tuneLerp.current) / time;
1585}
1586
1587static void au_SEFCmd_09_StartLoop(SoundManager* manager, SoundPlayer* player) {
1588 s32 loopIterCount = *player->sefDataReadPos++;
1589
1590 player->loopStartPos = player->sefDataReadPos;
1591 player->loopIterCount = loopIterCount;
1592}
1593
1594static void au_SEFCmd_0A_EndLoop(SoundManager* manager, SoundPlayer* player) {
1595 if (player->loopIterCount == 0 || --player->loopIterCount != 0) {
1596 player->sefDataReadPos = player->loopStartPos;
1597 }
1598}
1599
1600static void au_SEFCmd_0B_WaitForRelease(SoundManager* manager, SoundPlayer* player) {
1601 if (player->playLength != 0) {
1602 player->delay = 3;
1603 player->sefDataReadPos--;
1604 }
1605}
1606
1607static void au_SEFCmd_0C_SetCurrentVolume(SoundManager* manager, SoundPlayer* player) {
1608 s32 vol = *player->sefDataReadPos++;
1609
1610 if (vol != 0) {
1612 }
1613 player->volumeLerp.current = vol;
1614 player->changed.volume = TRUE;
1615}
1616
1617static void au_SEFCmd_0D_VolumeRamp(SoundManager* manager, SoundPlayer* player) {
1618 s32 hi = player->sefDataReadPos[0];
1619 s32 lo = player->sefDataReadPos[1];
1620 s32 newValue = player->sefDataReadPos[2];
1621 s16 time = lo + (hi << 8);
1622 player->sefDataReadPos += 3;
1623
1624 if (newValue != 0) {
1626 }
1627 if (time <= 0) {
1628 time = 1;
1629 }
1630
1631 player->volumeLerp.time = time;
1632 player->volumeLerp.goal = newValue;
1633 player->volumeLerp.step = ((newValue << 0x10) - player->volumeLerp.current) / time;
1634}
1635
1636static void au_SEFCmd_0E_SetAlternativeSound(SoundManager* manager, SoundPlayer* player) {
1637 s32 hi = player->sefDataReadPos[1];
1638 s32 lo = player->sefDataReadPos[2];
1639 AuFilePos pos = AU_FILE_RELATIVE(manager->sefData, (hi << 8) + lo);
1640 u8 type = player->sefDataReadPos[0];
1641 player->sefDataReadPos += 3;
1642
1643 player->alternativeType = type;
1644 switch (type) {
1645 case 1:
1646 player->alternativeDataPos = pos;
1647 break;
1648 case 2:
1649 player->alternativeDataPos = pos;
1650 break;
1651 case 3:
1652 player->alternativeDataPos = pos;
1653 break;
1654 default:
1655 player->alternativeDataPos = NULL;
1656 break;
1657 }
1658}
1659
1660static void au_SEFCmd_0F_Stop(SoundManager* manager, SoundPlayer* player) {
1661 AuVoice* voice = manager->curVoice;
1662 if (voice->priority == manager->priority) {
1663 au_reset_voice(voice, manager->curVoiceIndex);
1664 }
1665}
1666
1667static void au_SEFCmd_10_Jump(SoundManager* manager, SoundPlayer* player) {
1668 AuFilePos buf = player->sefDataReadPos;
1669 player->sefReadStart = &buf[2];
1670 player->sefDataReadPos = AU_FILE_RELATIVE(manager->sefData, (buf[0] << 8) + buf[1]);
1671}
1672
1673static void au_SEFCmd_11_Restart(SoundManager* manager, SoundPlayer* player) {
1674 player->sefDataReadPos = player->sefReadStart;
1675}
1676
1677static void au_SEFCmd_12_NOP(SoundManager* manager, SoundPlayer* player) {
1678}
1679
1680static void au_SEFCmd_13_SetRandomPitch(SoundManager* manager, SoundPlayer* player) {
1681 player->randomPitch = *player->sefDataReadPos++;
1682}
1683
1684static void au_SEFCmd_14_SetRandomVelocity(SoundManager* manager, SoundPlayer* player) {
1685 player->randomVelocity = *player->sefDataReadPos++;
1686}
1687
1688static void au_SEFCmd_15_SetRandomUnused(SoundManager* manager, SoundPlayer* player) {
1689 player->randomUnused = *player->sefDataReadPos++;
1690}
1691
1692static void au_SEFCmd_16_SetEnvelopePress(SoundManager* manager, SoundPlayer* player) {
1693 AuFilePos buf = player->sefDataReadPos;
1694 s32 offset = (buf[0] << 8) + buf[1];
1695
1696 if (offset != 0) {
1697 player->envelopCustomPressProfile = AU_FILE_RELATIVE(manager->sefData, offset);
1698 } else {
1700 }
1701
1702 player->sefDataReadPos = &buf[2];
1703}
1704
1705static void au_SEFCmd_17_PlaySound(SoundManager* manager, SoundPlayer* player) {
1706 AuFilePos buf = player->sefDataReadPos;
1707 u32 i;
1708
1709 for (i = 0; i < ARRAY_COUNT(manager->customCmdList); i++) {
1710 if (manager->customCmdList[i].data[0] == 0) {
1711 manager->customCmdList[i].data[0] = buf[1] + (buf[0] << 8);
1712 manager->customCmdList[i].data[1] = buf[3] + (buf[2] << 8);
1713 break;
1714 }
1715 }
1716 player->sefDataReadPos = &buf[4];
1717}
1718
1719static void au_SEFCmd_18_SetAlternativeVolume(SoundManager* manager, SoundPlayer* player) {
1720 player->alternativeVolume = *player->sefDataReadPos++;
1721 if (player->alternativeVolume != 0) {
1723 }
1724}
1725
1726/*
1727Uses bit masks:
1728780 = 0111 1000 0000 -> 0000 1111
172901E = 0000 0001 1110 -> 1111 0000
1730*/
1731static s32 au_sfx_get_random_pitch(s32 seed, s32 amplitude, s32 pitch) {
1732 s32 lo = (seed >> 7) & 0xF; // bitmask 0x780
1733 s32 hi = (seed << 3) & 0xF0; // bitmask 0x01E
1734 s32 random = (lo + hi);
1735 s32 tap5 = (seed >> 5);
1736 s32 tap2 = (seed >> 2);
1737 s32 parity = (tap5 + tap2) & 1;
1738
1739 if (parity) {
1740 return pitch + ((amplitude * 5 * random) >> 8);
1741 } else {
1742 return pitch - ((amplitude * 5 * random) >> 8);
1743 }
1744}
1745
1746/*
1747Uses bit masks:
1748CC = 1100 1100 -> 0011 0011
174913 = 0001 0011 -> 0100 1100
1750*/
1751static u8 au_sfx_get_random_vol(s32 seed, s32 amplitude, s32 volume) {
1752 s32 lo = (seed & 0xCC) >> 2;
1753 s32 hi = (seed & 0x13) << 2;
1754 s32 random = lo + hi;
1755
1756 return volume * (0x8000 - (amplitude * random)) >> 0xF;
1757}
1758
1759static void au_sfx_reset_players(SoundManager* manager) {
1760 s32 i;
1761
1762 for (i = 0; i < ARRAY_COUNT(manager->players); i++) {
1763 SoundPlayer* player = &manager->players[i];
1764 player->sefDataReadPos = BlankSEFData;
1765 player->alternativeDataPos = NULL;
1768 player->delay = 1;
1769 player->priority = 0;
1770 player->exclusiveID = 0;
1771 }
1772}
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:393
void au_reset_nonfree_voice(AuVoice *arg0, u8 arg1)
Definition engine.c:384
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:406
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:502
void au_fade_init(Fade *fade, s32 time, s32 startValue, s32 endValue)
Definition engine.c:417
void au_fade_set_volume(u8 arg0, u16 arg1, s32 arg2)
Definition engine.c:453
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:40
#define SQ(x)
Definition macros.h:178
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