sm64

A Super Mario 64 decompilation
Log | Files | Refs | README | LICENSE

internal.h (28206B)


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