sm64coopdx/src/audio/internal.h
anzz1 d1739648e1
Added Luigi sounds (#77)
* added a new audio bank 10 for luigi sounds
* made some audio memory buffers larger to fix sound cuts
* added option to enable/disable luigi sounds in the sound options menu
* added Andrat's "90's Classic Luigi Voice Pack" as default luigi sounds

Co-authored-by: anzz1 <>
2020-10-16 11:54:59 -07:00

690 lines
20 KiB
C

#ifndef AUDIO_INTERNAL_H
#define AUDIO_INTERNAL_H
#include <ultra64.h>
#include "types.h"
#ifdef VERSION_EU
#define SEQUENCE_PLAYERS 4
#define SEQUENCE_CHANNELS 48
#define SEQUENCE_LAYERS 64
#else
#define SEQUENCE_PLAYERS 3
#define SEQUENCE_CHANNELS 32
#ifdef VERSION_JP
#define SEQUENCE_LAYERS 48
#else
#define SEQUENCE_LAYERS 52
#endif
#endif
#define LAYERS_MAX 8
#define CHANNELS_MAX 32
#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
#ifdef VERSION_JP
#define TEMPO_SCALE 1
#else
#define TEMPO_SCALE TATUMS_PER_BEAT
#endif
// TODO: US_FLOAT should probably be renamed to JP_DOUBLE since eu seems to use floats too
#ifdef VERSION_JP
#define US_FLOAT(x) x
#else
#define US_FLOAT(x) x ## f
#endif
// 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.
#ifdef VERSION_JP
#define FLOAT_CAST(x) (f32) (x)
#else
#define FLOAT_CAST(x) (f32) (s32) (x)
#endif
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;
#ifdef VERSION_EU
/* , 0x08*/ s16 *curve;
/* , 0x0C*/ f32 extent;
/* , 0x10*/ f32 rate;
/* , 0x14*/ u8 active;
#endif
#ifndef VERSION_EU
/*0x08, */ s8 *curve;
/*0x0C, */ u8 active;
/*0x0E, */ u16 rate;
/*0x10, */ u16 extent;
#endif
/*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;
s16 arg;
}; // size = 0x4
struct AdpcmLoop
{
u32 start;
u32 end;
u32 count;
u32 pad;
s16 state[16]; // only exists if count != 0. 8-byte aligned
};
struct AdpcmBook
{
s32 order;
s32 npredictors;
s16 book[1]; // size 8 * order * npredictors. 8-byte aligned
};
struct AudioBankSample
{
u8 unused;
u8 loaded;
u8 *sampleAddr;
struct AdpcmLoop *loop;
struct AdpcmBook *book;
u32 sampleSize; // never read. either 0 or 1 mod 9, depending on padding
};
struct AudioBankSound
{
struct AudioBankSample *sample;
f32 tuning; // frequency scale factor
}; // size = 0x8
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
struct SequencePlayer
{
/*US/JP, EU */
#ifdef VERSION_EU
/*0x000, 0x000*/ u8 enabled : 1;
#else
/*0x000, 0x000*/ volatile u8 enabled : 1;
#endif
/*0x000, 0x000*/ u8 finished : 1; // never read
/*0x000, 0x000*/ u8 muted : 1;
/*0x000, 0x000*/ u8 seqDmaInProgress : 1;
/*0x000, 0x000*/ u8 bankDmaInProgress : 1;
#ifdef VERSION_EU
/* 0x000*/ u8 recalculateVolume : 1;
#endif
#ifndef VERSION_EU
/*0x001 */ s8 seqVariation;
#endif
/*0x002, 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;
#ifndef VERSION_EU
/*0x008, ?????*/ u8 loadingBankNumInstruments;
/*0x009, ?????*/ u8 loadingBankNumDrums;
#endif
#ifdef VERSION_EU
/* , 0x007*/ s8 seqVariationEu[1];
#endif
/*0x00A, 0x008*/ u16 tempo; // beats per minute in JP, tatums per minute in US/EU
/*0x00C, 0x00A*/ u16 tempoAcc;
#ifndef VERSION_EU
/*0x00E, 0x010*/ u16 fadeTimer;
#endif
/*0x010, 0x00C*/ s16 transposition;
/*0x012, 0x00E*/ u16 delay;
#ifdef VERSION_EU
/*0x00E, 0x010*/ u16 fadeTimer;
/* , 0x012*/ u16 fadeTimerUnkEu;
#endif
/*0x014, 0x014*/ u8 *seqData; // buffer of some sort
/*0x018, 0x018*/ f32 fadeVolume; // set to 1.0f
/*0x01C, 0x01C*/ f32 fadeVelocity; // set to 0.0f
/*0x020, 0x020*/ f32 volume; // set to 0.0f
/*0x024, 0x024*/ f32 muteVolumeScale; // set to 0.5f
#ifdef VERSION_EU
/* , 0x028*/ f32 fadeVolumeScale;
/* , 0x02C*/ f32 appliedFadeVolume;
#else
/* */ u8 pad2[4];
#endif
/*0x02C, 0x030*/ 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;
#ifndef VERSION_EU
/*0x134, ?????*/ struct AudioBank *loadingBank;
#endif
/*0x138, 0x140*/ uintptr_t bankDmaCurrDevAddr;
/*0x13C, 0x144*/ ssize_t bankDmaRemaining;
/* ext */ f32 volumeScale;
}; // size = 0x140, 0x148 on EU
struct AdsrSettings
{
u8 releaseRate;
#ifdef VERSION_EU
u8 sustain;
#else
u16 sustain; // sustain level, 2^16 = max
#endif
struct AdsrEnvelope *envelope;
}; // size = 0x8
struct AdsrState {
/*0x00, 0x00*/ u8 action;
/*0x01, 0x01*/ u8 state;
#ifndef VERSION_EU
/*0x02, */ s16 initial; // always 0
/*0x04, */ s16 target;
/*0x06, */ s16 current;
#endif
/*0x08, 0x02*/ s16 envIndex;
/*0x0A, 0x04*/ s16 delay;
#ifdef VERSION_EU
/* , 0x08*/ f32 sustain;
/* , 0x0C*/ f32 velocity;
/* , 0x10*/ f32 fadeOutVel;
/* , 0x14*/ f32 current;
/* , 0x18*/ f32 target;
s32 pad1C;
#else
/*0x0C, */ s16 sustain;
/*0x0E, */ s16 fadeOutVel;
/*0x10, */ s32 velocity;
/*0x14, */ s32 currentHiRes;
/*0x18, */ s16 *volOut;
#endif
/*0x1C, 0x20*/ struct AdsrEnvelope *envelope;
}; // size = 0x20, 0x24 in EU
struct NoteAttributes
{
s8 reverb;
#ifdef VERSION_EU
u8 pan;
#endif
f32 freqScale;
f32 velocity;
#ifndef VERSION_EU
f32 pan;
#endif
}; // size = 0x10
struct SequenceChannel
{
/* U/J, EU */
/*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
#ifdef VERSION_EU
/* , 0x01*/ union {
struct {
u8 freqScale : 1;
u8 volume : 1;
u8 pan : 1;
} as_bitfields;
u8 as_u8;
} changes;
#endif
/*0x01, 0x02*/ u8 noteAllocPolicy;
/*0x02, 0x03*/ u8 muteBehavior;
/*0x03, 0x04*/ u8 reverb; // or dry/wet mix
/*0x04, ????*/ u8 notePriority; // 0-3
/*0x05, 0x06*/ u8 bankId;
#ifdef VERSION_EU
/* , 0x07*/ u8 reverbIndex;
/* , 0x08*/ u8 bookOffset;
/* , 0x09*/ u8 newPan;
/* , 0x0A*/ u8 panChannelWeight; // proportion of pan that comes from the channel (0..128)
#else
/*0x06, */ u8 updatesPerFrameUnused;
#endif
/*0x08, 0x0C*/ u16 vibratoRateStart; // initially 0x800
/*0x0A, 0x0E*/ u16 vibratoExtentStart;
/*0x0C, 0x10*/ u16 vibratoRateTarget; // initially 0x800
/*0x0E, 0x12*/ u16 vibratoExtentTarget;
/*0x10, 0x14*/ u16 vibratoRateChangeDelay;
/*0x12, 0x16*/ u16 vibratoExtentChangeDelay;
/*0x14, 0x18*/ u16 vibratoDelay;
/*0x16, 0x1A*/ u16 delay;
/*0x18, 0x1C*/ s16 instOrWave; // either 0 (none), instrument index + 1, or
// 0x80..0x83 for sawtooth/triangle/sine/square waves.
/*0x1A, 0x1E*/ s16 transposition;
/*0x1C, 0x20*/ f32 volumeScale;
/*0x20, 0x24*/ f32 volume;
#ifndef VERSION_EU
/*0x24, */ f32 pan;
/*0x28, */ f32 panChannelWeight; // proportion of pan that comes from the channel (0..1)
#else
/* , 0x28*/ s32 pan;
/* , 0x2C*/ f32 appliedVolume;
#endif
/*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
struct SequenceChannelLayer // Maybe SequenceTrack?
{
/* U/J, EU */
/*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
#ifdef VERSION_EU
/* , 0x00*/ u8 unusedEu0b8 : 1;
/* , 0x00*/ u8 notePropertiesNeedInit : 1;
/* , 0x00*/ u8 ignoreDrumPan : 1;
/* , 0x01*/ u8 instOrWave;
#endif
/*0x01, 0x02*/ u8 status;
/*0x02, 0x03*/ u8 noteDuration; // set to 0x80
/*0x03, 0x04*/ u8 portamentoTargetNote;
#ifdef VERSION_EU
/* , 0x05*/ u8 pan; // 0..128
/* , 0x06*/ u8 notePan;
#endif
/*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*/ f32 freqScale;
/*0x24, 0x28*/ f32 velocitySquare;
#ifndef VERSION_EU
/*0x28, */ f32 pan; // 0..1
#endif
/*0x2C, 0x2C*/ f32 noteVelocity;
#ifndef VERSION_EU
/*0x30*/ f32 notePan;
#endif
/*0x34, 0x30*/ 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*/ struct Note *note;
/*0x48, 0x44*/ struct Instrument *instrument;
/*0x4C, 0x48*/ struct AudioBankSound *sound;
/*0x50, 0x4C*/ struct SequenceChannel *seqChannel;
/*0x54, 0x50*/ struct M64ScriptState scriptState;
/*0x70, 0x6C*/ struct AudioListItem listItem;
#ifdef VERSION_EU
u8 pad2[4];
#endif
}; // size = 0x80
#ifdef VERSION_EU
struct NoteSynthesisState
{
/*0x00*/ u8 restart;
/*0x01*/ u8 sampleDmaIndex;
/*0x02*/ u8 prevHeadsetPanRight;
/*0x03*/ u8 prevHeadsetPanLeft;
/*0x04*/ u16 samplePosFrac;
/*0x08*/ s32 samplePosInt;
/*0x0C*/ struct NoteSynthesisBuffers *synthesisBuffers;
/*0x10*/ s16 curVolLeft;
/*0x12*/ s16 curVolRight;
};
struct NotePlaybackState
{
/* U/J, EU */
/*0x04, 0x00*/ u8 priority;
/* 0x01*/ u8 waveId;
/* 0x02*/ u8 sampleCountIndex;
/*0x08, 0x04*/ s16 adsrVolScale;
/*0x18, 0x08*/ f32 portamentoFreqScale;
/*0x1C, 0x0C*/ f32 vibratoFreqScale;
/*0x28, 0x10*/ struct SequenceChannelLayer *prevParentLayer;
/*0x2C, 0x14*/ struct SequenceChannelLayer *parentLayer;
/*0x30, 0x18*/ struct SequenceChannelLayer *wantedParentLayer;
/* , 0x1C*/ struct NoteAttributes attributes;
/*0x54, 0x28*/ 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;
/*0x00*/ u8 envMixerNeedsInit : 1;
/*0x00*/ u8 stereoStrongRight : 1;
/*0x00*/ u8 stereoStrongLeft : 1;
/*0x00*/ u8 stereoHeadsetEffects : 1;
/*0x00*/ u8 usesHeadsetPanEffects : 1;
/*0x01*/ u8 reverbIndex : 3;
/*0x01*/ u8 bookOffset : 3;
/*0x01*/ u8 isSyntheticWave : 1;
/*0x01*/ u8 hasTwoAdpcmParts : 1;
/*0x02*/ u8 bankId;
/*0x03*/ u8 headsetPanRight;
/*0x04*/ u8 headsetPanLeft;
/*0x05*/ u8 reverbVol;
/*0x06*/ u16 targetVolLeft;
/*0x08*/ u16 targetVolRight;
/*0x0A*/ u16 resamplingRateFixedPoint; // stored as signed but loaded as u16
/*0x0C*/ union {
s16 *samples;
struct AudioBankSound *audioBankSound;
} sound;
};
struct Note
{
/* U/J, EU */
/*0xA4, 0x00*/ struct AudioListItem listItem;
/* 0x10*/ struct NoteSynthesisState synthesisState;
/*0x04, 0x30*/ u8 priority;
/* 0x31*/ u8 waveId;
/* 0x32*/ u8 sampleCountIndex;
/*0x08, 0x34*/ s16 adsrVolScale;
/*0x18, 0x38*/ f32 portamentoFreqScale;
/*0x1C, 0x3C*/ f32 vibratoFreqScale;
/*0x28, 0x40*/ struct SequenceChannelLayer *prevParentLayer;
/*0x2C, 0x44*/ struct SequenceChannelLayer *parentLayer;
/*0x30, 0x48*/ struct SequenceChannelLayer *wantedParentLayer;
/* , 0x4C*/ struct NoteAttributes attributes;
/*0x54, 0x58*/ struct AdsrState adsr;
/*0x74, 0x7C*/ struct Portamento portamento;
/*0x84, 0x8C*/ struct VibratoState vibratoState;
u8 pad3[8];
/* , 0xB0*/ struct NoteSubEu noteSubEu;
}; // size = 0xC0
#else
struct vNote
{
/* U/J, EU */
/*0x00*/ volatile u8 enabled : 1;
long long int force_structure_alignment;
}; // size = 0xC0
struct Note
{
/* U/J, EU */
/*0x00*/ u8 enabled : 1;
/*0x00*/ u8 needsInit : 1;
/*0x00*/ u8 restart : 1;
/*0x00*/ u8 finished : 1;
/*0x00*/ u8 envMixerNeedsInit : 1;
/*0x00*/ u8 stereoStrongRight : 1;
/*0x00*/ u8 stereoStrongLeft : 1;
/*0x00*/ u8 stereoHeadsetEffects : 1;
/*0x01*/ u8 usesHeadsetPanEffects;
/*0x02*/ u8 unk2;
/*0x03*/ u8 sampleDmaIndex;
/*0x04, 0x30*/ u8 priority;
/*0x05*/ u8 sampleCount; // 0, 8, 16, 32 or 64
/*0x06*/ u8 instOrWave;
/*0x07*/ u8 bankId; // in NoteSubEu on EU
/*0x08*/ s16 adsrVolScale;
/* */ u8 pad1[2];
/*0x0C, 0xB3*/ u16 headsetPanRight;
/*0x0E, 0xB4*/ u16 headsetPanLeft;
/*0x10*/ u16 prevHeadsetPanRight;
/*0x12*/ u16 prevHeadsetPanLeft;
/*0x14*/ s32 samplePosInt;
/*0x18, 0x38*/ f32 portamentoFreqScale;
/*0x1C, 0x3C*/ f32 vibratoFreqScale;
/*0x20*/ u16 samplePosFrac;
/*0x24*/ struct AudioBankSound *sound;
/*0x28, 0x40*/ struct SequenceChannelLayer *prevParentLayer;
/*0x2C, 0x44*/ struct SequenceChannelLayer *parentLayer;
/*0x30, 0x48*/ struct SequenceChannelLayer *wantedParentLayer;
/*0x34*/ struct NoteSynthesisBuffers *synthesisBuffers;
/*0x38*/ f32 frequency;
/*0x3C*/ u16 targetVolLeft;
/*0x3E*/ u16 targetVolRight;
/*0x40*/ u8 reverb;
/*0x41*/ u8 unused1; // never read, set to 0x3f
/*0x44*/ struct NoteAttributes attributes;
/*0x54, 0x58*/ struct AdsrState adsr;
/*0x74, 0x7C*/ struct Portamento portamento;
/*0x84, 0x8C*/ struct VibratoState vibratoState;
/*0x9C*/ s16 curVolLeft;
/*0x9E*/ s16 curVolRight;
/*0xA0*/ s16 reverbVol;
/*0xA2*/ s16 unused2; // never read, set to 0
/*0xA4, 0x00*/ struct AudioListItem listItem;
/* */ u8 pad2[0xc];
}; // size = 0xC0
#endif
struct NoteSynthesisBuffers
{
s16 adpcmdecState[0x10];
s16 finalResampleState[0x10];
s16 mixEnvelopeState[0x28];
s16 panResampleState[0x10];
s16 panSamplesBuffer[0x20];
s16 dummyResampleState[0x10];
#ifndef VERSION_EU
s16 samples[0x40];
#endif
};
struct ReverbSettingsEU
{
u8 downsampleRate;
u8 windowSize; // To be multiplied by 64
u16 gain;
};
struct AudioSessionSettingsEU
{
u32 frequency;
u8 unk1; // always 1
u8 maxSimultaneousNotes;
u8 numReverbs; // always 1
u8 unk2; // always 0
struct ReverbSettingsEU *reverbSettings;
u16 volume;
u16 unk3; // always 0
u32 persistentSeqMem;
u32 persistentBankMem;
u32 temporarySeqMem;
u32 temporaryBankMem;
};
struct AudioSessionSettings
{
/*0x00*/ u32 frequency;
/*0x04*/ u8 maxSimultaneousNotes;
/*0x05*/ u8 reverbDownsampleRate; // always 1
/*0x06*/ u16 reverbWindowSize;
/*0x08*/ u16 reverbGain;
/*0x0A*/ u16 volume;
/*0x0C*/ u32 persistentSeqMem;
/*0x10*/ u32 persistentBankMem;
/*0x14*/ u32 temporarySeqMem;
/*0x18*/ u32 temporaryBankMem;
}; // size = 0x1C
struct AudioBufferParametersEU {
/*0x00*/ s16 presetUnk4; // audio frames per vsync?
/*0x02*/ u16 frequency;
/*0x04*/ u16 aiFrequency; // ?16
/*0x06*/ s16 samplesPerFrameTarget;
/*0x08*/ s16 maxAiBufferLength;
/*0x0A*/ s16 minAiBufferLength;
/*0x0C*/ s16 updatesPerFrame;
/*0x0E*/ s16 samplesPerUpdate;
/*0x10*/ s16 samplesPerUpdateMax;
/*0x12*/ s16 samplesPerUpdateMin;
/*0x14*/ f32 resampleRate; // contains 32000.0f / frequency
/*0x18*/ f32 updatesPerFrameInv; // 1.0f / updatesPerFrame
/*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