Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
MorsGames
GitHub Repository: MorsGames/sm64plus
Path: blob/master/src/audio/internal.h
7857 views
1
#ifndef AUDIO_INTERNAL_H
2
#define AUDIO_INTERNAL_H
3
4
#include <ultra64.h>
5
6
#include "types.h"
7
8
#if defined(VERSION_EU) || defined(VERSION_SH)
9
#define SEQUENCE_PLAYERS 4
10
#define SEQUENCE_CHANNELS 48
11
#define SEQUENCE_LAYERS 64
12
#else
13
#define SEQUENCE_PLAYERS 3
14
#define SEQUENCE_CHANNELS 32
15
#ifdef VERSION_JP
16
#define SEQUENCE_LAYERS 48
17
#else
18
#define SEQUENCE_LAYERS 52
19
#endif
20
#endif
21
22
#define LAYERS_MAX 4
23
#define CHANNELS_MAX 16
24
25
#define NO_LAYER ((struct SequenceChannelLayer *)(-1))
26
27
#define MUTE_BEHAVIOR_STOP_SCRIPT 0x80 // stop processing sequence/channel scripts
28
#define MUTE_BEHAVIOR_STOP_NOTES 0x40 // prevent further notes from playing
29
#define MUTE_BEHAVIOR_SOFTEN 0x20 // lower volume, by default to half
30
31
#define SEQUENCE_PLAYER_STATE_0 0
32
#define SEQUENCE_PLAYER_STATE_FADE_OUT 1
33
#define SEQUENCE_PLAYER_STATE_2 2
34
#define SEQUENCE_PLAYER_STATE_3 3
35
#define SEQUENCE_PLAYER_STATE_4 4
36
37
#define NOTE_PRIORITY_DISABLED 0
38
#define NOTE_PRIORITY_STOPPING 1
39
#define NOTE_PRIORITY_MIN 2
40
#define NOTE_PRIORITY_DEFAULT 3
41
42
#define TATUMS_PER_BEAT 48
43
44
// abi.h contains more details about the ADPCM and S8 codecs, "skip" skips codec processing
45
#define CODEC_ADPCM 0
46
#define CODEC_S8 1
47
#define CODEC_SKIP 2
48
49
#ifdef VERSION_JP
50
#define TEMPO_SCALE 1
51
#else
52
#define TEMPO_SCALE TATUMS_PER_BEAT
53
#endif
54
55
// TODO: US_FLOAT should probably be renamed to JP_DOUBLE since eu seems to use floats too
56
#ifdef VERSION_JP
57
#define US_FLOAT(x) x
58
#else
59
#define US_FLOAT(x) x ## f
60
#endif
61
62
// Convert u8 or u16 to f32. On JP, this uses a u32->f32 conversion,
63
// resulting in more bloated codegen, while on US it goes through s32.
64
// Since u8 and u16 fit losslessly in both, behavior is the same.
65
#ifdef VERSION_JP
66
#define FLOAT_CAST(x) (f32) (x)
67
#else
68
#define FLOAT_CAST(x) (f32) (s32) (x)
69
#endif
70
71
// No-op printf macro which leaves string literals in rodata in IDO. IDO
72
// doesn't support variadic macros, so instead we let the parameter list
73
// expand to a no-op comma expression. Another possibility is that it might
74
// have expanded to something with "if (0)". See also goddard/gd_main.h.
75
// On US/JP, -sopt optimizes away these except for external.c.
76
#ifdef __sgi
77
#define stubbed_printf
78
#else
79
#define stubbed_printf(...)
80
#endif
81
82
#ifdef VERSION_EU
83
#define eu_stubbed_printf_0(msg) stubbed_printf(msg)
84
#define eu_stubbed_printf_1(msg, a) stubbed_printf(msg, a)
85
#define eu_stubbed_printf_2(msg, a, b) stubbed_printf(msg, a, b)
86
#define eu_stubbed_printf_3(msg, a, b, c) stubbed_printf(msg, a, b, c)
87
#else
88
#define eu_stubbed_printf_0(msg)
89
#define eu_stubbed_printf_1(msg, a)
90
#define eu_stubbed_printf_2(msg, a, b)
91
#define eu_stubbed_printf_3(msg, a, b, c)
92
#endif
93
94
struct NotePool;
95
96
struct AudioListItem
97
{
98
// A node in a circularly linked list. Each node is either a head or an item:
99
// - Items can be either detached (prev = NULL), or attached to a list.
100
// 'value' points to something of interest.
101
// - List heads are always attached; if a list is empty, its head points
102
// to itself. 'count' contains the size of the list.
103
// If the list holds notes, 'pool' points back to the pool where it lives.
104
// Otherwise, that member is NULL.
105
struct AudioListItem *prev;
106
struct AudioListItem *next;
107
union {
108
void *value; // either Note* or SequenceChannelLayer*
109
s32 count;
110
} u;
111
struct NotePool *pool;
112
}; // size = 0x10
113
114
struct NotePool
115
{
116
struct AudioListItem disabled;
117
struct AudioListItem decaying;
118
struct AudioListItem releasing;
119
struct AudioListItem active;
120
};
121
122
struct VibratoState {
123
/*0x00, 0x00*/ struct SequenceChannel *seqChannel;
124
/*0x04, 0x04*/ u32 time;
125
#if defined(VERSION_EU) || defined(VERSION_SH)
126
/* , 0x08*/ s16 *curve;
127
/* , 0x0C*/ f32 extent;
128
/* , 0x10*/ f32 rate;
129
/* , 0x14*/ u8 active;
130
#else
131
/*0x08, */ s8 *curve;
132
/*0x0C, */ u8 active;
133
/*0x0E, */ u16 rate;
134
/*0x10, */ u16 extent;
135
#endif
136
/*0x12, 0x16*/ u16 rateChangeTimer;
137
/*0x14, 0x18*/ u16 extentChangeTimer;
138
/*0x16, 0x1A*/ u16 delay;
139
}; // size = 0x18, 0x1C on EU
140
141
// Pitch sliding by up to one octave in the positive direction. Negative
142
// direction is "supported" by setting extent to be negative. The code
143
// extrapolates exponentially in the wrong direction in that case, but that
144
// doesn't prevent seqplayer from doing it, AFAICT.
145
struct Portamento {
146
u8 mode; // bit 0x80 denotes something; the rest are an index 0-5
147
f32 cur;
148
f32 speed;
149
f32 extent;
150
}; // size = 0x10
151
152
struct AdsrEnvelope {
153
s16 delay;
154
s16 arg;
155
}; // size = 0x4
156
157
struct AdpcmLoop
158
{
159
u32 start;
160
u32 end;
161
u32 count;
162
u32 pad;
163
s16 state[16]; // only exists if count != 0. 8-byte aligned
164
};
165
166
struct AdpcmBook
167
{
168
s32 order;
169
s32 npredictors;
170
s16 book[1]; // size 8 * order * npredictors. 8-byte aligned
171
};
172
173
struct AudioBankSample
174
{
175
#ifdef VERSION_SH
176
#if !IS_BIG_ENDIAN
177
u32 size : 24;
178
#endif
179
/* 0x00 */ u32 codec : 4;
180
/* 0x00 */ u32 medium : 2;
181
/* 0x00 */ u32 bit1 : 1;
182
/* 0x00 */ u32 isPatched : 1;
183
#if IS_BIG_ENDIAN
184
/* 0x01 */ u32 size : 24;
185
#endif
186
#else
187
u8 unused;
188
u8 loaded;
189
#endif
190
u8 *sampleAddr;
191
struct AdpcmLoop *loop;
192
struct AdpcmBook *book;
193
#ifndef VERSION_SH
194
u32 sampleSize; // never read. either 0 or 1 mod 9, depending on padding
195
#endif
196
};
197
198
struct AudioBankSound
199
{
200
struct AudioBankSample *sample;
201
f32 tuning; // frequency scale factor
202
}; // size = 0x8
203
204
struct Instrument
205
{
206
/*0x00*/ u8 loaded;
207
/*0x01*/ u8 normalRangeLo;
208
/*0x02*/ u8 normalRangeHi;
209
/*0x03*/ u8 releaseRate;
210
/*0x04*/ struct AdsrEnvelope *envelope;
211
/*0x08*/ struct AudioBankSound lowNotesSound;
212
/*0x10*/ struct AudioBankSound normalNotesSound;
213
/*0x18*/ struct AudioBankSound highNotesSound;
214
}; // size = 0x20
215
216
struct Drum
217
{
218
u8 releaseRate;
219
u8 pan;
220
u8 loaded;
221
struct AudioBankSound sound;
222
struct AdsrEnvelope *envelope;
223
};
224
225
struct AudioBank
226
{
227
struct Drum **drums;
228
struct Instrument *instruments[1];
229
}; // dynamic size
230
231
struct CtlEntry
232
{
233
#ifndef VERSION_SH
234
u8 unused;
235
#endif
236
u8 numInstruments;
237
u8 numDrums;
238
#ifdef VERSION_SH
239
u8 bankId1;
240
u8 bankId2;
241
#endif
242
struct Instrument **instruments;
243
struct Drum **drums;
244
}; // size = 0xC
245
246
struct M64ScriptState {
247
u8 *pc;
248
u8 *stack[4];
249
u8 remLoopIters[4];
250
u8 depth;
251
}; // size = 0x1C
252
253
// Also known as a Group, according to debug strings.
254
struct SequencePlayer
255
{
256
/*US/JP, EU, SH */
257
#if defined(VERSION_EU) || defined(VERSION_SH)
258
/*0x000, 0x000, 0x000*/ u8 enabled : 1;
259
#else
260
/*0x000, 0x000*/ volatile u8 enabled : 1;
261
#endif
262
/*0x000, 0x000*/ u8 finished : 1; // never read
263
/*0x000, 0x000*/ u8 muted : 1;
264
/*0x000, 0x000*/ u8 seqDmaInProgress : 1;
265
/*0x000, 0x000*/ u8 bankDmaInProgress : 1;
266
#if defined(VERSION_EU) || defined(VERSION_SH)
267
/* 0x000*/ u8 recalculateVolume : 1;
268
#endif
269
#ifdef VERSION_SH
270
/* 0x000*/ u8 unkSh: 1;
271
#endif
272
#if defined(VERSION_JP) || defined(VERSION_US)
273
/*0x001 */ s8 seqVariation;
274
#endif
275
/*0x002, 0x001, 0x001*/ u8 state;
276
/*0x003, 0x002*/ u8 noteAllocPolicy;
277
/*0x004, 0x003*/ u8 muteBehavior;
278
/*0x005, 0x004*/ u8 seqId;
279
/*0x006, 0x005*/ u8 defaultBank[1]; // must be an array to get a comparison
280
// to match; other u8's might also be part of that array
281
/*0x007, 0x006*/ u8 loadingBankId;
282
#if defined(VERSION_JP) || defined(VERSION_US)
283
/*0x008, ?????*/ u8 loadingBankNumInstruments;
284
/*0x009, ?????*/ u8 loadingBankNumDrums;
285
#endif
286
#if defined(VERSION_EU) || defined(VERSION_SH)
287
/* , 0x007, 0x007*/ s8 seqVariationEu[1];
288
#endif
289
/*0x00A, 0x008*/ u16 tempo; // beats per minute in JP, tatums per minute in US/EU
290
/*0x00C, 0x00A*/ u16 tempoAcc;
291
#if defined(VERSION_JP) || defined(VERSION_US)
292
/*0x00E, 0x010*/ u16 fadeRemainingFrames;
293
#endif
294
#ifdef VERSION_SH
295
/* 0x00C*/ s16 tempoAdd;
296
#endif
297
/*0x010, 0x00C, 0x00E*/ s16 transposition;
298
/*0x012, 0x00E, 0x010*/ u16 delay;
299
#if defined(VERSION_EU) || defined(VERSION_SH)
300
/*0x00E, 0x010, 0x012*/ u16 fadeRemainingFrames;
301
/* , 0x012, 0x014*/ u16 fadeTimerUnkEu;
302
#endif
303
/*0x014, 0x014*/ u8 *seqData; // buffer of some sort
304
/*0x018, 0x018, 0x1C*/ f32 fadeVolume; // set to 1.0f
305
/*0x01C, 0x01C*/ f32 fadeVelocity; // set to 0.0f
306
/*0x020, 0x020, 0x024*/ f32 volume; // set to 0.0f
307
/*0x024, 0x024*/ f32 muteVolumeScale; // set to 0.5f
308
#if defined(VERSION_EU) || defined(VERSION_SH)
309
/* , 0x028, 0x02C*/ f32 fadeVolumeScale;
310
/* , 0x02C*/ f32 appliedFadeVolume;
311
#else
312
/* */ u8 pad2[4];
313
#endif
314
/*0x02C, 0x030, 0x034*/ struct SequenceChannel *channels[CHANNELS_MAX];
315
/*0x06C, 0x070*/ struct M64ScriptState scriptState;
316
/*0x088, 0x08C*/ u8 *shortNoteVelocityTable;
317
/*0x08C, 0x090*/ u8 *shortNoteDurationTable;
318
/*0x090, 0x094*/ struct NotePool notePool;
319
/*0x0D0, 0x0D4*/ OSMesgQueue seqDmaMesgQueue;
320
/*0x0E8, 0x0EC*/ OSMesg seqDmaMesg;
321
/*0x0EC, 0x0F0*/ OSIoMesg seqDmaIoMesg;
322
/*0x100, 0x108*/ OSMesgQueue bankDmaMesgQueue;
323
/*0x118, 0x120*/ OSMesg bankDmaMesg;
324
/*0x11C, 0x124*/ OSIoMesg bankDmaIoMesg;
325
/*0x130, 0x13C*/ u8 *bankDmaCurrMemAddr;
326
#if defined(VERSION_JP) || defined(VERSION_US)
327
/*0x134, ?????*/ struct AudioBank *loadingBank;
328
#endif
329
/*0x138, 0x140*/ uintptr_t bankDmaCurrDevAddr;
330
/*0x13C, 0x144*/ ssize_t bankDmaRemaining;
331
}; // size = 0x140, 0x148 on EU, 0x14C on SH
332
333
struct AdsrSettings
334
{
335
u8 releaseRate;
336
#if defined(VERSION_EU) || defined(VERSION_SH)
337
u8 sustain;
338
#else
339
u16 sustain; // sustain level, 2^16 = max
340
#endif
341
struct AdsrEnvelope *envelope;
342
}; // size = 0x8
343
344
struct AdsrState {
345
/*0x00, 0x00*/ u8 action;
346
/*0x01, 0x01*/ u8 state;
347
#if defined(VERSION_JP) || defined(VERSION_US)
348
/*0x02, */ s16 initial; // always 0
349
/*0x04, */ s16 target;
350
/*0x06, */ s16 current;
351
#endif
352
/*0x08, 0x02*/ s16 envIndex;
353
/*0x0A, 0x04*/ s16 delay;
354
#if defined(VERSION_EU) || defined(VERSION_SH)
355
/* , 0x08*/ f32 sustain;
356
/* , 0x0C*/ f32 velocity;
357
/* , 0x10*/ f32 fadeOutVel;
358
/* , 0x14*/ f32 current;
359
/* , 0x18*/ f32 target;
360
s32 pad1C;
361
#else
362
/*0x0C, */ s16 sustain;
363
/*0x0E, */ s16 fadeOutVel;
364
/*0x10, */ s32 velocity;
365
/*0x14, */ s32 currentHiRes;
366
/*0x18, */ s16 *volOut;
367
#endif
368
/*0x1C, 0x20*/ struct AdsrEnvelope *envelope;
369
}; // size = 0x20, 0x24 in EU
370
371
struct ReverbBitsData {
372
/* 0x00 */ u8 bit0 : 1;
373
/* 0x00 */ u8 bit1 : 1;
374
/* 0x00 */ u8 bit2 : 1;
375
/* 0x00 */ u8 usesHeadsetPanEffects : 1;
376
/* 0x00 */ u8 stereoHeadsetEffects : 2;
377
/* 0x00 */ u8 strongRight : 1;
378
/* 0x00 */ u8 strongLeft : 1;
379
};
380
381
union ReverbBits {
382
/* 0x00 */ struct ReverbBitsData s;
383
/* 0x00 */ u8 asByte;
384
};
385
struct ReverbInfo {
386
u8 reverbVol;
387
u8 synthesisVolume; // UQ4.4, although 0 <= x < 1 is rounded up to 1
388
u8 pan;
389
union ReverbBits reverbBits;
390
f32 freqScale;
391
f32 velocity;
392
s32 unused;
393
s16 *filter;
394
};
395
396
struct NoteAttributes
397
{
398
u8 reverbVol;
399
#ifdef VERSION_SH
400
u8 synthesisVolume; // UQ4.4, although 0 <= x < 1 is rounded up to 1
401
#endif
402
#if defined(VERSION_EU) || defined(VERSION_SH)
403
u8 pan;
404
#endif
405
#ifdef VERSION_SH
406
union ReverbBits reverbBits;
407
#endif
408
f32 freqScale;
409
f32 velocity;
410
#if defined(VERSION_JP) || defined(VERSION_US)
411
f32 pan;
412
#endif
413
#ifdef VERSION_SH
414
s16 *filter;
415
#endif
416
}; // size = 0x10
417
418
// Also known as a SubTrack, according to debug strings.
419
// Confusingly, a SubTrack is a container of Tracks.
420
struct SequenceChannel
421
{
422
/* U/J, EU, SH */
423
/*0x00, 0x00*/ u8 enabled : 1;
424
/*0x00, 0x00*/ u8 finished : 1;
425
/*0x00, 0x00*/ u8 stopScript : 1;
426
/*0x00, 0x00*/ u8 stopSomething2 : 1; // sets SequenceChannelLayer.stopSomething
427
/*0x00, 0x00*/ u8 hasInstrument : 1;
428
/*0x00, 0x00*/ u8 stereoHeadsetEffects : 1;
429
/*0x00, ????*/ u8 largeNotes : 1; // notes specify duration and velocity
430
/*0x00, ????*/ u8 unused : 1; // never read, set to 0
431
#if defined(VERSION_EU) || defined(VERSION_SH)
432
/* , 0x01*/ union {
433
struct {
434
u8 freqScale : 1;
435
u8 volume : 1;
436
u8 pan : 1;
437
} as_bitfields;
438
u8 as_u8;
439
} changes;
440
#endif
441
/*0x01, 0x02*/ u8 noteAllocPolicy;
442
/*0x02, 0x03, 0x03*/ u8 muteBehavior;
443
/*0x03, 0x04, 0x04*/ u8 reverbVol; // until EU: Q1.7, after EU: UQ0.8
444
/*0x04, ????*/ u8 notePriority; // 0-3
445
#ifdef VERSION_SH
446
u8 unkSH06; // some priority
447
#endif
448
/*0x05, 0x06*/ u8 bankId;
449
#if defined(VERSION_EU) || defined(VERSION_SH)
450
/* , 0x07*/ u8 reverbIndex;
451
/* , 0x08, 0x09*/ u8 bookOffset;
452
/* , 0x09*/ u8 newPan;
453
/* , 0x0A*/ u8 panChannelWeight; // proportion of pan that comes from the channel (0..128)
454
#else
455
/*0x06, */ u8 updatesPerFrameUnused;
456
#endif
457
#ifdef VERSION_SH
458
/* 0x0C*/ u8 synthesisVolume; // UQ4.4, although 0 <= x < 1 is rounded up to 1
459
#endif
460
/*0x08, 0x0C, 0x0E*/ u16 vibratoRateStart; // initially 0x800
461
/*0x0A, 0x0E, 0x10*/ u16 vibratoExtentStart;
462
/*0x0C, 0x10, 0x12*/ u16 vibratoRateTarget; // initially 0x800
463
/*0x0E, 0x12, 0x14*/ u16 vibratoExtentTarget;
464
/*0x10, 0x14, 0x16*/ u16 vibratoRateChangeDelay;
465
/*0x12, 0x16, 0x18*/ u16 vibratoExtentChangeDelay;
466
/*0x14, 0x18, 0x1A*/ u16 vibratoDelay;
467
/*0x16, 0x1A, 0x1C*/ u16 delay;
468
/*0x18, 0x1C, 0x1E*/ s16 instOrWave; // either 0 (none), instrument index + 1, or
469
// 0x80..0x83 for sawtooth/triangle/sine/square waves.
470
/*0x1A, 0x1E, 0x20*/ s16 transposition;
471
/*0x1C, 0x20, 0x24*/ f32 volumeScale;
472
/*0x20, 0x24, 0x28*/ f32 volume;
473
#if defined(VERSION_JP) || defined(VERSION_US)
474
/*0x24, */ f32 pan;
475
/*0x28, */ f32 panChannelWeight; // proportion of pan that comes from the channel (0..1)
476
#else
477
/* , 0x28*/ s32 pan;
478
/* , 0x2C*/ f32 appliedVolume;
479
#endif
480
/*0x2C, 0x30*/ f32 freqScale;
481
/*0x30, 0x34*/ u8 (*dynTable)[][2];
482
/*0x34, ????*/ struct Note *noteUnused; // never read
483
/*0x38, ????*/ struct SequenceChannelLayer *layerUnused; // never read
484
/*0x3C, 0x40*/ struct Instrument *instrument;
485
/*0x40, 0x44*/ struct SequencePlayer *seqPlayer;
486
/*0x44, 0x48*/ struct SequenceChannelLayer *layers[LAYERS_MAX];
487
#ifndef VERSION_SH
488
/*0x54, 0x58 */ s8 soundScriptIO[8]; // bridge between sound script and audio lib. For player 2,
489
// [0] contains enabled, [4] contains sound ID, [5] contains reverb adjustment
490
#endif
491
/*0x5C, 0x60*/ struct M64ScriptState scriptState;
492
/*0x78, 0x7C*/ struct AdsrSettings adsr;
493
/*0x80, 0x84*/ struct NotePool notePool;
494
#ifdef VERSION_SH
495
/* 0xC0*/ s8 soundScriptIO[8]; // bridge between sound script and audio lib. For player 2,
496
// [0] contains enabled, [4] contains sound ID, [5] contains reverb adjustment
497
/* 0xC8*/ u16 unkC8;
498
/* 0xCC*/ s16 *filter;
499
#endif
500
}; // size = 0xC0, 0xC4 in EU, 0xD0 in SH
501
502
// Also known as a Track, according to debug strings.
503
struct SequenceChannelLayer
504
{
505
/* U/J, EU, SH */
506
/*0x00, 0x00*/ u8 enabled : 1;
507
/*0x00, 0x00*/ u8 finished : 1;
508
/*0x00, 0x00*/ u8 stopSomething : 1; // ?
509
/*0x00, 0x00*/ u8 continuousNotes : 1; // keep the same note for consecutive notes with the same sound
510
#if defined(VERSION_EU) || defined(VERSION_SH)
511
/* , 0x00*/ u8 unusedEu0b8 : 1;
512
/* , 0x00*/ u8 notePropertiesNeedInit : 1;
513
/* , 0x00*/ u8 ignoreDrumPan : 1;
514
#ifdef VERSION_SH
515
/* , , 0x01 */ union ReverbBits reverbBits;
516
#endif
517
/* , 0x01, 0x02*/ u8 instOrWave;
518
#endif
519
/*0x01, 0x02, 0x03*/ u8 status; // 0x03 in SH
520
/*0x02, 0x03*/ u8 noteDuration; // set to 0x80
521
/*0x03, 0x04*/ u8 portamentoTargetNote;
522
#if defined(VERSION_EU) || defined(VERSION_SH)
523
/* , 0x05*/ u8 pan; // 0..128
524
/* , 0x06, 0x07*/ u8 notePan;
525
#endif
526
/*0x04, 0x08*/ struct Portamento portamento;
527
/*0x14, 0x18*/ struct AdsrSettings adsr;
528
/*0x1C, 0x20*/ u16 portamentoTime;
529
/*0x1E, 0x22*/ s16 transposition; // #semitones added to play commands
530
// (m64 instruction encoding only allows referring to the limited range
531
// 0..0x3f; this makes 0x40..0x7f accessible as well)
532
/*0x20, 0x24, 0x24*/ f32 freqScale;
533
#ifdef VERSION_SH
534
/* 0x28*/ f32 freqScaleMultiplier;
535
#endif
536
/*0x24, 0x28, 0x2C*/ f32 velocitySquare;
537
#if defined(VERSION_JP) || defined(VERSION_US)
538
/*0x28, */ f32 pan; // 0..1
539
#endif
540
/*0x2C, 0x2C, 0x30*/ f32 noteVelocity;
541
#if defined(VERSION_JP) || defined(VERSION_US)
542
/*0x30*/ f32 notePan;
543
#endif
544
/*0x34, 0x30, 0x34*/ f32 noteFreqScale;
545
/*0x38, 0x34*/ s16 shortNoteDefaultPlayPercentage;
546
/*0x3A, 0x36*/ s16 playPercentage; // it's not really a percentage...
547
/*0x3C, 0x38*/ s16 delay;
548
/*0x3E, 0x3A*/ s16 duration;
549
/*0x40, 0x3C*/ s16 delayUnused; // set to 'delay', never read
550
/*0x44, 0x40, 0x44*/ struct Note *note;
551
/*0x48, 0x44*/ struct Instrument *instrument;
552
/*0x4C, 0x48*/ struct AudioBankSound *sound;
553
/*0x50, 0x4C, 0x50*/ struct SequenceChannel *seqChannel;
554
/*0x54, 0x50*/ struct M64ScriptState scriptState;
555
/*0x70, 0x6C*/ struct AudioListItem listItem;
556
#if defined(VERSION_EU)
557
u8 pad2[4];
558
#endif
559
}; // size = 0x80
560
561
#if defined(VERSION_EU) || defined(VERSION_SH)
562
struct NoteSynthesisState
563
{
564
/*0x00*/ u8 restart;
565
/*0x01*/ u8 sampleDmaIndex;
566
/*0x02*/ u8 prevHeadsetPanRight;
567
/*0x03*/ u8 prevHeadsetPanLeft;
568
#ifdef VERSION_SH
569
/* 0x04*/ u8 reverbVol;
570
/* 0x05*/ u8 unk5;
571
#endif
572
/*0x04, 0x06*/ u16 samplePosFrac;
573
/*0x08*/ s32 samplePosInt;
574
/*0x0C*/ struct NoteSynthesisBuffers *synthesisBuffers;
575
/*0x10*/ s16 curVolLeft; // UQ0.16 (EU Q1.15)
576
/*0x12*/ s16 curVolRight; // UQ0.16 (EU Q1.15)
577
};
578
struct NotePlaybackState
579
{
580
/* U/J, EU, SH */
581
/*0x04, 0x00, 0x00*/ u8 priority;
582
/* 0x01, 0x01*/ u8 waveId;
583
/* 0x02, 0x02*/ u8 sampleCountIndex;
584
#ifdef VERSION_SH
585
/* 0x03*/ u8 bankId;
586
/* 0x04*/ u8 unkSH34;
587
#endif
588
/*0x08, 0x04, 0x06*/ s16 adsrVolScale;
589
/*0x18, 0x08, 0x08*/ f32 portamentoFreqScale;
590
/*0x1C, 0x0C, 0x0C*/ f32 vibratoFreqScale;
591
/*0x28, 0x10, */ struct SequenceChannelLayer *prevParentLayer;
592
/*0x2C, 0x14, 0x14*/ struct SequenceChannelLayer *parentLayer;
593
/*0x30, 0x18, 0x18*/ struct SequenceChannelLayer *wantedParentLayer;
594
/* , 0x1C, 0x1C*/ struct NoteAttributes attributes;
595
/*0x54, 0x28, 0x2C*/ struct AdsrState adsr;
596
/*0x74, 0x4C, */ struct Portamento portamento;
597
/*0x84, 0x5C, */ struct VibratoState vibratoState;
598
};
599
struct NoteSubEu
600
{
601
/*0x00*/ volatile u8 enabled : 1;
602
/*0x00*/ u8 needsInit : 1;
603
/*0x00*/ u8 finished : 1;
604
/*0x00*/ u8 envMixerNeedsInit : 1;
605
/*0x00*/ u8 stereoStrongRight : 1;
606
/*0x00*/ u8 stereoStrongLeft : 1;
607
/*0x00*/ u8 stereoHeadsetEffects : 1;
608
/*0x00*/ u8 usesHeadsetPanEffects : 1;
609
/*0x01*/ u8 reverbIndex : 3;
610
/*0x01*/ u8 bookOffset : 3;
611
/*0x01*/ u8 isSyntheticWave : 1;
612
/*0x01*/ u8 hasTwoAdpcmParts : 1;
613
#ifdef VERSION_EU
614
/*0x02*/ u8 bankId;
615
#else
616
/*0x02*/ u8 synthesisVolume; // UQ4.4, although 0 <= x < 1 is rounded up to 1
617
#endif
618
/*0x03*/ u8 headsetPanRight;
619
/*0x04*/ u8 headsetPanLeft;
620
/*0x05*/ u8 reverbVol; // UQ0.7 (EU Q1.7)
621
/*0x06*/ u16 targetVolLeft; // UQ0.12 (EU UQ0.10)
622
/*0x08*/ u16 targetVolRight; // UQ0.12 (EU UQ0.10)
623
/*0x0A*/ u16 resamplingRateFixedPoint; // stored as signed but loaded as u16
624
/*0x0C*/ union {
625
s16 *samples;
626
struct AudioBankSound *audioBankSound;
627
} sound;
628
#ifdef VERSION_SH
629
/*0x10*/ s16 *filter;
630
#endif
631
};
632
struct Note
633
{
634
/* U/J, EU, SH */
635
/*0xA4, 0x00, 0x00*/ struct AudioListItem listItem;
636
/* 0x10, 0x10*/ struct NoteSynthesisState synthesisState;
637
// The next members are actually part of a struct (NotePlaybackState), but
638
// that results in messy US/EU ifdefs. Instead we cast to a struct pointer
639
// when needed... This breaks alignment on non-N64 platforms, which we hack
640
// around by skipping the padding in that case.
641
// TODO: use macros or something instead.
642
#ifdef TARGET_N64
643
u8 pad0[12];
644
#endif
645
646
/*0x04, 0x30, 0x30*/ u8 priority;
647
/* 0x31, 0x31*/ u8 waveId;
648
/* 0x32, 0x32*/ u8 sampleCountIndex;
649
#ifdef VERSION_SH
650
/* 0x33*/ u8 bankId;
651
/* 0x34*/ u8 unkSH34;
652
#endif
653
/*0x08, 0x34, 0x36*/ s16 adsrVolScale;
654
/*0x18, 0x38, */ f32 portamentoFreqScale;
655
/*0x1C, 0x3C, */ f32 vibratoFreqScale;
656
/*0x28, 0x40, */ struct SequenceChannelLayer *prevParentLayer;
657
/*0x2C, 0x44, 0x44*/ struct SequenceChannelLayer *parentLayer;
658
/*0x30, 0x48, 0x48*/ struct SequenceChannelLayer *wantedParentLayer;
659
/* , 0x4C, 0x4C*/ struct NoteAttributes attributes;
660
/*0x54, 0x58, 0x5C*/ struct AdsrState adsr;
661
/*0x74, 0x7C*/ struct Portamento portamento;
662
/*0x84, 0x8C*/ struct VibratoState vibratoState;
663
u8 pad3[8];
664
/* , 0xB0, 0xB4*/ struct NoteSubEu noteSubEu;
665
}; // size = 0xC0, known to be 0xC8 on SH
666
#else
667
// volatile Note, needed in synthesis_process_notes
668
struct vNote
669
{
670
/* U/J, EU */
671
/*0x00*/ volatile u8 enabled : 1;
672
long long int force_structure_alignment;
673
}; // size = 0xC0
674
struct Note
675
{
676
/* U/J, EU */
677
/*0x00*/ u8 enabled : 1;
678
/*0x00*/ u8 needsInit : 1;
679
/*0x00*/ u8 restart : 1;
680
/*0x00*/ u8 finished : 1;
681
/*0x00*/ u8 envMixerNeedsInit : 1;
682
/*0x00*/ u8 stereoStrongRight : 1;
683
/*0x00*/ u8 stereoStrongLeft : 1;
684
/*0x00*/ u8 stereoHeadsetEffects : 1;
685
/*0x01*/ u8 usesHeadsetPanEffects;
686
/*0x02*/ u8 unk2;
687
/*0x03*/ u8 sampleDmaIndex;
688
/*0x04, 0x30*/ u8 priority;
689
/*0x05*/ u8 sampleCount; // 0, 8, 16, 32 or 64
690
/*0x06*/ u8 instOrWave;
691
/*0x07*/ u8 bankId; // in NoteSubEu on EU
692
/*0x08*/ s16 adsrVolScale;
693
/* */ u8 pad1[2];
694
/*0x0C, 0xB3*/ u16 headsetPanRight;
695
/*0x0E, 0xB4*/ u16 headsetPanLeft;
696
/*0x10*/ u16 prevHeadsetPanRight;
697
/*0x12*/ u16 prevHeadsetPanLeft;
698
/*0x14*/ s32 samplePosInt;
699
/*0x18, 0x38*/ f32 portamentoFreqScale;
700
/*0x1C, 0x3C*/ f32 vibratoFreqScale;
701
/*0x20*/ u16 samplePosFrac;
702
/*0x24*/ struct AudioBankSound *sound;
703
/*0x28, 0x40*/ struct SequenceChannelLayer *prevParentLayer;
704
/*0x2C, 0x44*/ struct SequenceChannelLayer *parentLayer;
705
/*0x30, 0x48*/ struct SequenceChannelLayer *wantedParentLayer;
706
/*0x34*/ struct NoteSynthesisBuffers *synthesisBuffers;
707
/*0x38*/ f32 frequency;
708
/*0x3C*/ u16 targetVolLeft; // Q1.15, but will always be non-negative
709
/*0x3E*/ u16 targetVolRight; // Q1.15, but will always be non-negative
710
/*0x40*/ u8 reverbVol; // Q1.7
711
/*0x41*/ u8 unused1; // never read, set to 0x3f
712
/*0x44*/ struct NoteAttributes attributes;
713
/*0x54, 0x58*/ struct AdsrState adsr;
714
/*0x74, 0x7C*/ struct Portamento portamento;
715
/*0x84, 0x8C*/ struct VibratoState vibratoState;
716
/*0x9C*/ s16 curVolLeft; // Q1.15, but will always be non-negative
717
/*0x9E*/ s16 curVolRight; // Q1.15, but will always be non-negative
718
/*0xA0*/ s16 reverbVolShifted; // Q1.15
719
/*0xA2*/ s16 unused2; // never read, set to 0
720
/*0xA4, 0x00*/ struct AudioListItem listItem;
721
/* */ u8 pad2[0xc];
722
}; // size = 0xC0
723
#endif
724
725
struct NoteSynthesisBuffers
726
{
727
s16 adpcmdecState[0x10];
728
s16 finalResampleState[0x10];
729
#ifdef VERSION_SH
730
s16 unk[0x10];
731
s16 filterBuffer[0x20];
732
s16 panSamplesBuffer[0x20];
733
#else
734
s16 mixEnvelopeState[0x28];
735
s16 panResampleState[0x10];
736
s16 panSamplesBuffer[0x20];
737
s16 dummyResampleState[0x10];
738
#if defined(VERSION_JP) || defined(VERSION_US)
739
s16 samples[0x40];
740
#endif
741
#endif
742
};
743
744
#ifdef VERSION_EU
745
struct ReverbSettingsEU
746
{
747
u8 downsampleRate;
748
u8 windowSize; // To be multiplied by 64
749
u16 gain;
750
};
751
#else
752
struct ReverbSettingsEU
753
{
754
u8 downsampleRate; // always 1
755
u8 windowSize; // To be multiplied by 16
756
u16 gain;
757
u16 unk4; // always zero
758
u16 unk6; // always zero
759
s8 unk8; // always -1
760
u16 unkA; // always 0x3000
761
s16 unkC; // always zero
762
s16 unkE; // always zero
763
};
764
#endif
765
766
struct AudioSessionSettingsEU
767
{
768
/* 0x00 */ u32 frequency;
769
/* 0x04 */ u8 unk1; // always 1
770
/* 0x05 */ u8 maxSimultaneousNotes;
771
/* 0x06 */ u8 numReverbs; // always 1
772
/* 0x07 */ u8 unk2; // always 0
773
/* 0x08 */ struct ReverbSettingsEU *reverbSettings;
774
/* 0x0C */ u16 volume;
775
/* 0x0E */ u16 unk3; // always 0
776
/* 0x10 */ u32 persistentSeqMem;
777
/* 0x14 */ u32 persistentBankMem;
778
#ifdef VERSION_SH
779
/* 0x18 */ u32 unk18; // always 0
780
#endif
781
/* 0x18, 0x1C */ u32 temporarySeqMem;
782
/* 0x1C, 0x20 */ u32 temporaryBankMem;
783
#ifdef VERSION_SH
784
/* 0x24 */ u32 unk24; // always 0
785
/* 0x28 */ u32 unkMem28; // always 0
786
/* 0x2C */ u32 unkMem2C; // always 0
787
#endif
788
}; // 0x30 on shindou
789
790
struct AudioSessionSettings
791
{
792
/*0x00*/ u32 frequency;
793
/*0x04*/ u8 maxSimultaneousNotes;
794
/*0x05*/ u8 reverbDownsampleRate; // always 1
795
/*0x06*/ u16 reverbWindowSize;
796
/*0x08*/ u16 reverbGain;
797
/*0x0A*/ u16 volume;
798
/*0x0C*/ u32 persistentSeqMem;
799
/*0x10*/ u32 persistentBankMem;
800
/*0x14*/ u32 temporarySeqMem;
801
/*0x18*/ u32 temporaryBankMem;
802
}; // size = 0x1C
803
804
struct AudioBufferParametersEU {
805
/*0x00*/ s16 presetUnk4; // audio frames per vsync?
806
/*0x02*/ u16 frequency;
807
/*0x04*/ u16 aiFrequency; // ?16
808
/*0x06*/ s16 samplesPerFrameTarget;
809
/*0x08*/ s16 maxAiBufferLength;
810
/*0x0A*/ s16 minAiBufferLength;
811
/*0x0C*/ s16 updatesPerFrame;
812
/*0x0E*/ s16 samplesPerUpdate;
813
/*0x10*/ s16 samplesPerUpdateMax;
814
/*0x12*/ s16 samplesPerUpdateMin;
815
/*0x14*/ f32 resampleRate; // contains 32000.0f / frequency
816
/*0x18*/ f32 updatesPerFrameInv; // 1.0f / updatesPerFrame
817
/*0x1C*/ f32 unkUpdatesPerFrameScaled; // 3.0f / (1280.0f * updatesPerFrame)
818
};
819
820
struct EuAudioCmd {
821
union {
822
#if IS_BIG_ENDIAN
823
struct {
824
u8 op;
825
u8 arg1;
826
u8 arg2;
827
u8 arg3;
828
} s;
829
#else
830
struct {
831
u8 arg3;
832
u8 arg2;
833
u8 arg1;
834
u8 op;
835
} s;
836
#endif
837
s32 first;
838
} u;
839
union {
840
s32 as_s32;
841
u32 as_u32;
842
f32 as_f32;
843
#if IS_BIG_ENDIAN
844
u8 as_u8;
845
s8 as_s8;
846
#else
847
struct {
848
u8 pad0[3];
849
u8 as_u8;
850
};
851
struct {
852
u8 pad1[3];
853
s8 as_s8;
854
};
855
#endif
856
} u2;
857
};
858
859
#ifdef VERSION_SH
860
struct PendingDmaSample {
861
u8 medium;
862
u8 bankId;
863
u8 idx;
864
uintptr_t devAddr;
865
void *vAddr;
866
u8 *resultSampleAddr;
867
s32 state;
868
s32 remaining;
869
s8 *io;
870
/*0x1C*/ struct AudioBankSample sample;
871
/*0x2C*/ OSMesgQueue queue;
872
/*0x44*/ OSMesg mesgs[1];
873
/*0x48*/ OSIoMesg ioMesg;
874
};
875
876
struct UnkStruct80343D00 {
877
u32 someIndex; // array into one of the two slots below
878
struct PendingDmaSample arr[2];
879
};
880
881
// in external.c
882
extern s32 D_SH_80343CF0;
883
extern struct UnkStruct80343D00 D_SH_80343D00;
884
#endif
885
886
#endif // AUDIO_INTERNAL_H
887
888