summaryrefslogtreecommitdiff
path: root/src/audio/internal.h
diff options
context:
space:
mode:
authorTyler McGavran <tyler.taggerung@gmail.com>2022-11-06 10:24:24 -0500
committerGitHub <noreply@github.com>2022-11-06 08:24:24 -0700
commite9415164bb5786f0f5052f92d59843d6549b79e4 (patch)
tree2ca31c2211890441d74afdd19ef7a2d6eb5d7ca3 /src/audio/internal.h
parent4e5946257d8049f421c4247d6039de94d3db83d5 (diff)
Lots and lots of audio code copied from SM64 (#270)
* Lots of audio decomp * effects and playback are 100% matched * Took some notes from the SM64 Makefile to get the right compiler options for a couple files * Added the audio files to rename_symbol utility Signed-off-by: Taggerung <tyler.taggerung@gmail.com>
Diffstat (limited to 'src/audio/internal.h')
-rw-r--r--src/audio/internal.h494
1 files changed, 484 insertions, 10 deletions
diff --git a/src/audio/internal.h b/src/audio/internal.h
index f9bbc5593..a9aaa4628 100644
--- a/src/audio/internal.h
+++ b/src/audio/internal.h
@@ -1,8 +1,51 @@
#ifndef AUDIO_INTERNAL_H
#define AUDIO_INTERNAL_H
-#include <PR/ultratypes.h>
+#include <ultra64.h>
+#include "types.h"
+
+#define SEQUENCE_PLAYERS 4
+#define SEQUENCE_CHANNELS 48
+#define SEQUENCE_LAYERS 64
+
+#define LAYERS_MAX 4
+#define CHANNELS_MAX 16
+
+#define NO_LAYER ((struct SequenceChannelLayer *)(-1))
+
+#define MUTE_BEHAVIOR_STOP_SCRIPT 0x80 // stop processing sequence/channel scripts
+#define MUTE_BEHAVIOR_STOP_NOTES 0x40 // prevent further notes from playing
+#define MUTE_BEHAVIOR_SOFTEN 0x20 // lower volume, by default to half
+
+#define SEQUENCE_PLAYER_STATE_0 0
+#define SEQUENCE_PLAYER_STATE_FADE_OUT 1
+#define SEQUENCE_PLAYER_STATE_2 2
+#define SEQUENCE_PLAYER_STATE_3 3
+#define SEQUENCE_PLAYER_STATE_4 4
+
+#define NOTE_PRIORITY_DISABLED 0
+#define NOTE_PRIORITY_STOPPING 1
+#define NOTE_PRIORITY_MIN 2
+#define NOTE_PRIORITY_DEFAULT 3
+
+#define TATUMS_PER_BEAT 48
+
+// abi.h contains more details about the ADPCM and S8 codecs, "skip" skips codec processing
+#define CODEC_ADPCM 0
+#define CODEC_S8 1
+#define CODEC_SKIP 2
+
+#define TEMPO_SCALE TATUMS_PER_BEAT
+
+// TODO: US_FLOAT should probably be renamed to JP_DOUBLE since eu seems to use floats too
+#define US_FLOAT(x) x ## f
+#define US_FLOAT2(x) x
+
+// Convert u8 or u16 to f32. On JP, this uses a u32->f32 conversion,
+// resulting in more bloated codegen, while on US it goes through s32.
+// Since u8 and u16 fit losslessly in both, behavior is the same.
+#define FLOAT_CAST(x) (f32) (s32) (x)
// No-op printf macro which leaves string literals in rodata in IDO. IDO
// doesn't support variadic macros, so instead we let the parameter list
@@ -15,11 +58,59 @@
#define stubbed_printf(...)
#endif
-#define stubbed_printf_0(msg) stubbed_printf(msg)
-#define stubbed_printf_1(msg, a) stubbed_printf(msg, a)
-#define stubbed_printf_2(msg, a, b) stubbed_printf(msg, a, b)
-#define stubbed_printf_3(msg, a, b, c) stubbed_printf(msg, a, b, c)
+#define eu_stubbed_printf_0(msg) stubbed_printf(msg)
+#define eu_stubbed_printf_1(msg, a) stubbed_printf(msg, a)
+#define eu_stubbed_printf_2(msg, a, b) stubbed_printf(msg, a, b)
+#define eu_stubbed_printf_3(msg, a, b, c) stubbed_printf(msg, a, b, c)
+
+struct NotePool;
+
+struct AudioListItem {
+ // A node in a circularly linked list. Each node is either a head or an item:
+ // - Items can be either detached (prev = NULL), or attached to a list.
+ // 'value' points to something of interest.
+ // - List heads are always attached; if a list is empty, its head points
+ // to itself. 'count' contains the size of the list.
+ // If the list holds notes, 'pool' points back to the pool where it lives.
+ // Otherwise, that member is NULL.
+ struct AudioListItem *prev;
+ struct AudioListItem *next;
+ union {
+ void *value; // either Note* or SequenceChannelLayer*
+ s32 count;
+ } u;
+ struct NotePool *pool;
+}; // size = 0x10
+
+struct NotePool {
+ struct AudioListItem disabled;
+ struct AudioListItem decaying;
+ struct AudioListItem releasing;
+ struct AudioListItem active;
+};
+
+struct VibratoState {
+ /*0x00, 0x00*/ struct SequenceChannel *seqChannel;
+ /*0x04, 0x04*/ u32 time;
+ /* , 0x08*/ s16 *curve;
+ /* , 0x0C*/ f32 extent;
+ /* , 0x10*/ f32 rate;
+ /* , 0x14*/ u8 active;
+ /*0x12, 0x16*/ u16 rateChangeTimer;
+ /*0x14, 0x18*/ u16 extentChangeTimer;
+ /*0x16, 0x1A*/ u16 delay;
+}; // size = 0x18, 0x1C on EU
+// Pitch sliding by up to one octave in the positive direction. Negative
+// direction is "supported" by setting extent to be negative. The code
+// extrapolates exponentially in the wrong direction in that case, but that
+// doesn't prevent seqplayer from doing it, AFAICT.
+struct Portamento {
+ u8 mode; // bit 0x80 denotes something; the rest are an index 0-5
+ f32 cur;
+ f32 speed;
+ f32 extent;
+}; // size = 0x10
struct AdsrEnvelope {
s16 delay;
@@ -54,8 +145,269 @@ struct AudioBankSound {
f32 tuning; // frequency scale factor
}; // size = 0x8
-struct NoteSub
-{
+struct Instrument {
+ /*0x00*/ u8 loaded;
+ /*0x01*/ u8 normalRangeLo;
+ /*0x02*/ u8 normalRangeHi;
+ /*0x03*/ u8 releaseRate;
+ /*0x04*/ struct AdsrEnvelope *envelope;
+ /*0x08*/ struct AudioBankSound lowNotesSound;
+ /*0x10*/ struct AudioBankSound normalNotesSound;
+ /*0x18*/ struct AudioBankSound highNotesSound;
+}; // size = 0x20
+
+struct Drum {
+ u8 releaseRate;
+ u8 pan;
+ u8 loaded;
+ struct AudioBankSound sound;
+ struct AdsrEnvelope *envelope;
+};
+
+struct AudioBank {
+ struct Drum **drums;
+ struct Instrument *instruments[1];
+}; // dynamic size
+
+struct CtlEntry {
+ u8 unused;
+ u8 numInstruments;
+ u8 numDrums;
+ struct Instrument **instruments;
+ struct Drum **drums;
+}; // size = 0xC
+
+struct M64ScriptState {
+ u8 *pc;
+ u8 *stack[4];
+ u8 remLoopIters[4];
+ u8 depth;
+}; // size = 0x1C
+
+// Also known as a Group, according to debug strings.
+struct SequencePlayer {
+ /*US/JP, EU, SH */
+ /*0x000, 0x000, 0x000*/ u8 enabled : 1;
+ /*0x000, 0x000*/ u8 finished : 1; // never read
+ /*0x000, 0x000*/ u8 muted : 1;
+ /*0x000, 0x000*/ u8 seqDmaInProgress : 1;
+ /*0x000, 0x000*/ u8 bankDmaInProgress : 1;
+ /* 0x000*/ u8 recalculateVolume : 1;
+ /*0x002, 0x001, 0x001*/ u8 state;
+ /*0x003, 0x002*/ u8 noteAllocPolicy;
+ /*0x004, 0x003*/ u8 muteBehavior;
+ /*0x005, 0x004*/ u8 seqId;
+ /*0x006, 0x005*/ u8 defaultBank[1]; // must be an array to get a comparison
+ // to match; other u8's might also be part of that array
+ /*0x007, 0x006*/ u8 loadingBankId;
+ /* , 0x007, 0x007*/ s8 seqVariationEu[1];
+ /*0x00A, 0x008*/ u16 tempo; // beats per minute in JP, tatums per minute in US/EU
+ /*0x00C, 0x00A*/ u16 tempoAcc;
+ /*0x010, 0x00C, 0x00E*/ s16 transposition;
+ /*0x012, 0x00E, 0x010*/ u16 delay;
+ /*0x00E, 0x010, 0x012*/ u16 fadeRemainingFrames;
+ /* , 0x012, 0x014*/ u16 fadeTimerUnkEu;
+ /*0x014, 0x014*/ u8 *seqData; // buffer of some sort
+ /*0x018, 0x018, 0x1C*/ f32 fadeVolume; // set to 1.0f
+ /*0x01C, 0x01C*/ f32 fadeVelocity; // set to 0.0f
+ /*0x020, 0x020, 0x024*/ f32 volume; // set to 0.0f
+ /*0x024, 0x024*/ f32 muteVolumeScale; // set to 0.5f
+ /* , 0x028, 0x02C*/ f32 fadeVolumeScale;
+ /* , 0x02C*/ f32 appliedFadeVolume;
+ /*0x02C, 0x030, 0x034*/ struct SequenceChannel *channels[CHANNELS_MAX];
+ /*0x06C, 0x070*/ struct M64ScriptState scriptState;
+ /*0x088, 0x08C*/ u8 *shortNoteVelocityTable;
+ /*0x08C, 0x090*/ u8 *shortNoteDurationTable;
+ /*0x090, 0x094*/ struct NotePool notePool;
+ /*0x0D0, 0x0D4*/ OSMesgQueue seqDmaMesgQueue;
+ /*0x0E8, 0x0EC*/ OSMesg seqDmaMesg;
+ /*0x0EC, 0x0F0*/ OSIoMesg seqDmaIoMesg;
+ /*0x100, 0x108*/ OSMesgQueue bankDmaMesgQueue;
+ /*0x118, 0x120*/ OSMesg bankDmaMesg;
+ /*0x11C, 0x124*/ OSIoMesg bankDmaIoMesg;
+ /*0x130, 0x13C*/ u8 *bankDmaCurrMemAddr;
+ /*0x138, 0x140*/ uintptr_t bankDmaCurrDevAddr;
+ /*0x13C, 0x144*/ ssize_t bankDmaRemaining;
+}; // size = 0x140, 0x148 on EU, 0x14C on SH
+
+struct AdsrSettings {
+ u8 releaseRate;
+ u8 sustain;
+ struct AdsrEnvelope *envelope;
+}; // size = 0x8
+
+struct AdsrState {
+ /*0x00, 0x00*/ u8 action;
+ /*0x01, 0x01*/ u8 state;
+ /*0x08, 0x02*/ s16 envIndex;
+ /*0x0A, 0x04*/ s16 delay;
+ /* , 0x08*/ f32 sustain;
+ /* , 0x0C*/ f32 velocity;
+ /* , 0x10*/ f32 fadeOutVel;
+ /* , 0x14*/ f32 current;
+ /* , 0x18*/ f32 target;
+ s32 pad1C;
+ /*0x1C, 0x20*/ struct AdsrEnvelope *envelope;
+}; // size = 0x20, 0x24 in EU
+
+struct ReverbBitsData {
+ /* 0x00 */ u8 bit0 : 1;
+ /* 0x00 */ u8 bit1 : 1;
+ /* 0x00 */ u8 bit2 : 1;
+ /* 0x00 */ u8 usesHeadsetPanEffects : 1;
+ /* 0x00 */ u8 stereoHeadsetEffects : 2;
+ /* 0x00 */ u8 strongRight : 1;
+ /* 0x00 */ u8 strongLeft : 1;
+};
+
+union ReverbBits {
+ /* 0x00 */ struct ReverbBitsData s;
+ /* 0x00 */ u8 asByte;
+};
+struct ReverbInfo {
+ u8 reverbVol;
+ u8 synthesisVolume; // UQ4.4, although 0 <= x < 1 is rounded up to 1
+ u8 pan;
+ union ReverbBits reverbBits;
+ f32 freqScale;
+ f32 velocity;
+ s32 unused;
+ s16 *filter;
+};
+
+struct NoteAttributes {
+ u8 reverbVol;
+ u8 pan;
+ f32 freqScale;
+ f32 velocity;
+}; // size = 0x10
+
+// Also known as a SubTrack, according to debug strings.
+// Confusingly, a SubTrack is a container of Tracks.
+struct SequenceChannel {
+ /* U/J, EU, SH */
+ /*0x00, 0x00*/ u8 enabled : 1;
+ /*0x00, 0x00*/ u8 finished : 1;
+ /*0x00, 0x00*/ u8 stopScript : 1;
+ /*0x00, 0x00*/ u8 stopSomething2 : 1; // sets SequenceChannelLayer.stopSomething
+ /*0x00, 0x00*/ u8 hasInstrument : 1;
+ /*0x00, 0x00*/ u8 stereoHeadsetEffects : 1;
+ /*0x00, ????*/ u8 largeNotes : 1; // notes specify duration and velocity
+ /*0x00, ????*/ u8 unused : 1; // never read, set to 0
+ /* , 0x01*/ union {
+ struct {
+ u8 freqScale : 1;
+ u8 volume : 1;
+ u8 pan : 1;
+ } as_bitfields;
+ u8 as_u8;
+ } changes;
+ /*0x01, 0x02*/ u8 noteAllocPolicy;
+ /*0x02, 0x03, 0x03*/ u8 muteBehavior;
+ /*0x03, 0x04, 0x04*/ u8 reverbVol; // until EU: Q1.7, after EU: UQ0.8
+ /*0x04, ????*/ u8 notePriority; // 0-3
+ /*0x05, 0x06*/ u8 bankId;
+ /* , 0x07*/ u8 reverbIndex;
+ /* , 0x08, 0x09*/ u8 bookOffset;
+ /* , 0x09*/ u8 newPan;
+ /* , 0x0A*/ u8 panChannelWeight; // proportion of pan that comes from the channel (0..128)
+ /*0x08, 0x0C, 0x0E*/ u16 vibratoRateStart; // initially 0x800
+ /*0x0A, 0x0E, 0x10*/ u16 vibratoExtentStart;
+ /*0x0C, 0x10, 0x12*/ u16 vibratoRateTarget; // initially 0x800
+ /*0x0E, 0x12, 0x14*/ u16 vibratoExtentTarget;
+ /*0x10, 0x14, 0x16*/ u16 vibratoRateChangeDelay;
+ /*0x12, 0x16, 0x18*/ u16 vibratoExtentChangeDelay;
+ /*0x14, 0x18, 0x1A*/ u16 vibratoDelay;
+ /*0x16, 0x1A, 0x1C*/ u16 delay;
+ /*0x18, 0x1C, 0x1E*/ s16 instOrWave; // either 0 (none), instrument index + 1, or
+ // 0x80..0x83 for sawtooth/triangle/sine/square waves.
+ /*0x1A, 0x1E, 0x20*/ s16 transposition;
+ /*0x1C, 0x20, 0x24*/ f32 volumeScale;
+ /*0x20, 0x24, 0x28*/ f32 volume;
+ /* , 0x28*/ s32 pan;
+ /* , 0x2C*/ f32 appliedVolume;
+ /*0x2C, 0x30*/ f32 freqScale;
+ /*0x30, 0x34*/ u8 (*dynTable)[][2];
+ /*0x34, ????*/ struct Note *noteUnused; // never read
+ /*0x38, ????*/ struct SequenceChannelLayer *layerUnused; // never read
+ /*0x3C, 0x40*/ struct Instrument *instrument;
+ /*0x40, 0x44*/ struct SequencePlayer *seqPlayer;
+ /*0x44, 0x48*/ struct SequenceChannelLayer *layers[LAYERS_MAX];
+ /*0x54, 0x58 */ s8 soundScriptIO[8]; // bridge between sound script and audio lib. For player 2,
+ // [0] contains enabled, [4] contains sound ID, [5] contains reverb adjustment
+ /*0x5C, 0x60*/ struct M64ScriptState scriptState;
+ /*0x78, 0x7C*/ struct AdsrSettings adsr;
+ /*0x80, 0x84*/ struct NotePool notePool;
+}; // size = 0xC0, 0xC4 in EU, 0xD0 in SH
+
+// Also known as a Track, according to debug strings.
+struct SequenceChannelLayer {
+ /* U/J, EU, SH */
+ /*0x00, 0x00*/ u8 enabled : 1;
+ /*0x00, 0x00*/ u8 finished : 1;
+ /*0x00, 0x00*/ u8 stopSomething : 1; // ?
+ /*0x00, 0x00*/ u8 continuousNotes : 1; // keep the same note for consecutive notes with the same sound
+ /* , 0x00*/ u8 unusedEu0b8 : 1;
+ /* , 0x00*/ u8 notePropertiesNeedInit : 1;
+ /* , 0x00*/ u8 ignoreDrumPan : 1;
+ /* , 0x01, 0x02*/ u8 instOrWave;
+ /*0x01, 0x02, 0x03*/ u8 status; // 0x03 in SH
+ /*0x02, 0x03*/ u8 noteDuration; // set to 0x80
+ /*0x03, 0x04*/ u8 portamentoTargetNote;
+ /* , 0x05*/ u8 pan; // 0..128
+ /* , 0x06, 0x07*/ u8 notePan;
+ /*0x04, 0x08*/ struct Portamento portamento;
+ /*0x14, 0x18*/ struct AdsrSettings adsr;
+ /*0x1C, 0x20*/ u16 portamentoTime;
+ /*0x1E, 0x22*/ s16 transposition; // #semitones added to play commands
+ // (m64 instruction encoding only allows referring to the limited range
+ // 0..0x3f; this makes 0x40..0x7f accessible as well)
+ /*0x20, 0x24, 0x24*/ f32 freqScale;
+ /*0x24, 0x28, 0x2C*/ f32 velocitySquare;
+ /*0x2C, 0x2C, 0x30*/ f32 noteVelocity;
+ /*0x34, 0x30, 0x34*/ f32 noteFreqScale;
+ /*0x38, 0x34*/ s16 shortNoteDefaultPlayPercentage;
+ /*0x3A, 0x36*/ s16 playPercentage; // it's not really a percentage...
+ /*0x3C, 0x38*/ s16 delay;
+ /*0x3E, 0x3A*/ s16 duration;
+ /*0x40, 0x3C*/ s16 delayUnused; // set to 'delay', never read
+ /*0x44, 0x40, 0x44*/ struct Note *note;
+ /*0x48, 0x44*/ struct Instrument *instrument;
+ /*0x4C, 0x48*/ struct AudioBankSound *sound;
+ /*0x50, 0x4C, 0x50*/ struct SequenceChannel *seqChannel;
+ /*0x54, 0x50*/ struct M64ScriptState scriptState;
+ /*0x70, 0x6C*/ struct AudioListItem listItem;
+ u8 pad2[4];
+}; // size = 0x80
+
+struct NoteSynthesisState {
+ /*0x00*/ u8 restart;
+ /*0x01*/ u8 sampleDmaIndex;
+ /*0x02*/ u8 prevHeadsetPanRight;
+ /*0x03*/ u8 prevHeadsetPanLeft;
+ /*0x04, 0x06*/ u16 samplePosFrac;
+ /*0x08*/ s32 samplePosInt;
+ /*0x0C*/ struct NoteSynthesisBuffers *synthesisBuffers;
+ /*0x10*/ s16 curVolLeft; // UQ0.16 (EU Q1.15)
+ /*0x12*/ s16 curVolRight; // UQ0.16 (EU Q1.15)
+};
+struct NotePlaybackState {
+ /* U/J, EU, SH */
+ /*0x04, 0x00, 0x00*/ u8 priority;
+ /* 0x01, 0x01*/ u8 waveId;
+ /* 0x02, 0x02*/ u8 sampleCountIndex;
+ /*0x08, 0x04, 0x06*/ s16 adsrVolScale;
+ /*0x18, 0x08, 0x08*/ f32 portamentoFreqScale;
+ /*0x1C, 0x0C, 0x0C*/ f32 vibratoFreqScale;
+ /*0x28, 0x10, */ struct SequenceChannelLayer *prevParentLayer;
+ /*0x2C, 0x14, 0x14*/ struct SequenceChannelLayer *parentLayer;
+ /*0x30, 0x18, 0x18*/ struct SequenceChannelLayer *wantedParentLayer;
+ /* , 0x1C, 0x1C*/ struct NoteAttributes attributes;
+ /*0x54, 0x28, 0x2C*/ struct AdsrState adsr;
+ /*0x74, 0x4C, */ struct Portamento portamento;
+ /*0x84, 0x5C, */ struct VibratoState vibratoState;
+};
+struct NoteSubEu {
/*0x00*/ volatile u8 enabled : 1;
/*0x00*/ u8 needsInit : 1;
/*0x00*/ u8 finished : 1;
@@ -71,15 +423,98 @@ struct NoteSub
/*0x02*/ u8 bankId;
/*0x03*/ u8 headsetPanRight;
/*0x04*/ u8 headsetPanLeft;
- /*0x05*/ u8 reverbVol;
- /*0x06*/ u16 targetVolLeft;
- /*0x08*/ u16 targetVolRight;
+ /*0x05*/ u8 reverbVol; // UQ0.7 (EU Q1.7)
+ /*0x06*/ u16 targetVolLeft; // UQ0.12 (EU UQ0.10)
+ /*0x08*/ u16 targetVolRight; // UQ0.12 (EU UQ0.10)
/*0x0A*/ u16 resamplingRateFixedPoint; // stored as signed but loaded as u16
/*0x0C*/ union {
s16 *samples;
struct AudioBankSound *audioBankSound;
} sound;
};
+struct Note {
+ /* U/J, EU, SH */
+ /*0xA4, 0x00, 0x00*/ struct AudioListItem listItem;
+ /* 0x10, 0x10*/ struct NoteSynthesisState synthesisState;
+ // The next members are actually part of a struct (NotePlaybackState), but
+ // that results in messy US/EU ifdefs. Instead we cast to a struct pointer
+ // when needed... This breaks alignment on non-N64 platforms, which we hack
+ // around by skipping the padding in that case.
+ // TODO: use macros or something instead.
+#ifdef TARGET_N64
+ u8 pad0[12];
+#endif
+
+ /*0x04, 0x30, 0x30*/ u8 priority;
+ /* 0x31, 0x31*/ u8 waveId;
+ /* 0x32, 0x32*/ u8 sampleCountIndex;
+ /*0x08, 0x34, 0x36*/ s16 adsrVolScale;
+ /*0x18, 0x38, */ f32 portamentoFreqScale;
+ /*0x1C, 0x3C, */ f32 vibratoFreqScale;
+ /*0x28, 0x40, */ struct SequenceChannelLayer *prevParentLayer;
+ /*0x2C, 0x44, 0x44*/ struct SequenceChannelLayer *parentLayer;
+ /*0x30, 0x48, 0x48*/ struct SequenceChannelLayer *wantedParentLayer;
+ /* , 0x4C, 0x4C*/ struct NoteAttributes attributes;
+ /*0x54, 0x58, 0x5C*/ struct AdsrState adsr;
+ /*0x74, 0x7C*/ struct Portamento portamento;
+ /*0x84, 0x8C*/ struct VibratoState vibratoState;
+ u8 pad3[8];
+ /* , 0xB0, 0xB4*/ struct NoteSubEu noteSubEu;
+}; // size = 0xC0, known to be 0xC8 on SH
+
+// While this struct needs to be size 0xA0, its not clear
+// what innards are necessary. All the possible options from
+// SM64 are sized incorrectly so we're probably looking at some
+// MK64 weirdness
+struct NoteSynthesisBuffers {
+ s16 adpcmdecState[0x10];
+ s16 finalResampleState[0x10];
+ s16 panResampleState[0x10];
+ s16 panSamplesBuffer[0x20];
+}; // size = 0xA0
+
+/*
+SM64 NoteSynthesisBuffers, kept here because I'm not sure our current
+version is correct
+struct NoteSynthesisBuffers {
+ s16 adpcmdecState[0x10];
+ s16 finalResampleState[0x10];
+#ifdef VERSION_SH
+ s16 unk[0x10];
+ s16 filterBuffer[0x20];
+ s16 panSamplesBuffer[0x20];
+#else
+ s16 mixEnvelopeState[0x28];
+ s16 panResampleState[0x10];
+ s16 panSamplesBuffer[0x20];
+ s16 dummyResampleState[0x10];
+#if defined(VERSION_JP) || defined(VERSION_US)
+ s16 samples[0x40];
+#endif
+#endif
+};
+*/
+
+struct ReverbSettingsEU {
+ u8 downsampleRate;
+ u8 windowSize; // To be multiplied by 64
+ u16 gain;
+};
+
+struct AudioSessionSettingsEU {
+ /* 0x00 */ u32 frequency;
+ /* 0x04 */ u8 unk1; // always 1
+ /* 0x05 */ u8 maxSimultaneousNotes;
+ /* 0x06 */ u8 numReverbs; // always 1
+ /* 0x07 */ u8 unk2; // always 0
+ /* 0x08 */ struct ReverbSettingsEU *reverbSettings;
+ /* 0x0C */ u16 volume;
+ /* 0x0E */ u16 unk3; // always 0
+ /* 0x10 */ u32 persistentSeqMem;
+ /* 0x14 */ u32 persistentBankMem;
+ /* 0x18, 0x1C */ u32 temporarySeqMem;
+ /* 0x1C, 0x20 */ u32 temporaryBankMem;
+}; // 0x30 on shindou
struct AudioSessionSettings {
/*0x00*/ u32 frequency;
@@ -110,4 +545,43 @@ struct AudioBufferParametersEU {
/*0x1C*/ f32 unkUpdatesPerFrameScaled; // 3.0f / (1280.0f * updatesPerFrame)
};
+struct EuAudioCmd {
+ union {
+#if IS_BIG_ENDIAN
+ struct {
+ u8 op;
+ u8 arg1;
+ u8 arg2;
+ u8 arg3;
+ } s;
+#else
+ struct {
+ u8 arg3;
+ u8 arg2;
+ u8 arg1;
+ u8 op;
+ } s;
+#endif
+ s32 first;
+ } u;
+ union {
+ s32 as_s32;
+ u32 as_u32;
+ f32 as_f32;
+#if IS_BIG_ENDIAN
+ u8 as_u8;
+ s8 as_s8;
+#else
+ struct {
+ u8 pad0[3];
+ u8 as_u8;
+ };
+ struct {
+ u8 pad1[3];
+ s8 as_s8;
+ };
#endif
+ } u2;
+};
+
+#endif // AUDIO_INTERNAL_H