2019-08-25 00:46:40 -04:00
|
|
|
#ifndef _AUDIO_INTERNAL_H
|
|
|
|
#define _AUDIO_INTERNAL_H
|
|
|
|
|
|
|
|
#include <ultra64.h>
|
|
|
|
|
|
|
|
#include "types.h"
|
|
|
|
|
|
|
|
#define SEQUENCE_PLAYERS 3
|
|
|
|
#define CHANNELS_MAX 16
|
|
|
|
|
|
|
|
#define NO_LAYER ((struct SequenceChannelLayer *)(-1))
|
|
|
|
|
|
|
|
#define MUTE_BEHAVIOR_80 0x80
|
|
|
|
#define MUTE_BEHAVIOR_40 0x40
|
|
|
|
#define MUTE_BEHAVIOR_20 0x20
|
|
|
|
|
|
|
|
#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
|
|
|
|
|
|
|
|
#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 {
|
|
|
|
struct SequenceChannel *seqChannel;
|
|
|
|
u32 time;
|
|
|
|
s8 *curve;
|
|
|
|
u8 active;
|
|
|
|
u16 rate;
|
|
|
|
u16 extent;
|
|
|
|
u16 rateChangeTimer;
|
|
|
|
u16 extentChangeTimer;
|
|
|
|
u16 delay;
|
|
|
|
}; // size = 0x18
|
|
|
|
|
|
|
|
// Pitch sliding by up to one octave in the positive direction. Negative
|
|
|
|
// direction is "supported" by setting extent to be negative. The code
|
|
|
|
// exterpolates 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 unk1;
|
|
|
|
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
|
|
|
|
{
|
|
|
|
/*0x000*/ volatile u8 enabled : 1;
|
|
|
|
/*0x000*/ u8 finished : 1; // never read
|
|
|
|
/*0x000*/ u8 muted : 1;
|
|
|
|
/*0x000*/ u8 seqDmaInProgress : 1;
|
|
|
|
/*0x000*/ u8 bankDmaInProgress : 1;
|
|
|
|
/*0x001*/ s8 seqVariation;
|
|
|
|
/*0x002*/ u8 state;
|
|
|
|
/*0x003*/ u8 noteAllocPolicy;
|
|
|
|
/*0x004*/ u8 muteBehavior;
|
|
|
|
/*0x005*/ u8 seqId;
|
|
|
|
/*0x006*/ u8 anyBank[1]; // must be an array to get a comparison
|
|
|
|
// to match; other u8's might also be part of that array
|
|
|
|
/*0x007*/ u8 loadingBankId;
|
|
|
|
/*0x008*/ u8 loadingBankNumInstruments;
|
|
|
|
/*0x009*/ u8 loadingBankNumDrums;
|
|
|
|
/*0x00A*/ u16 tempo; // beats per minute in JP, tatums per minute in US
|
|
|
|
/*0x00C*/ u16 tempoAcc;
|
|
|
|
/*0x00E*/ u16 fadeTimer;
|
|
|
|
/*0x010*/ s16 transposition;
|
|
|
|
/*0x012*/ u16 delay;
|
|
|
|
/*0x014*/ u8 *seqData; // buffer of some sort
|
|
|
|
/*0x018*/ f32 fadeVolume; // set to 1.0f
|
|
|
|
/*0x01C*/ f32 fadeVelocity; // set to 0.0f
|
|
|
|
/*0x020*/ f32 volume; // set to 0.0f
|
|
|
|
/*0x024*/ f32 muteVolumeScale; // set to 0.5f
|
|
|
|
/* */ u8 pad1[4];
|
|
|
|
/*0x02C*/ struct SequenceChannel *channels[CHANNELS_MAX];
|
|
|
|
/*0x06C*/ struct M64ScriptState scriptState;
|
|
|
|
/*0x088*/ u8 *shortNoteVelocityTable;
|
|
|
|
/*0x08C*/ u8 *shortNoteDurationTable;
|
|
|
|
/*0x090*/ struct NotePool notePool;
|
|
|
|
/*0x0D0*/ OSMesgQueue seqDmaMesgQueue;
|
|
|
|
/*0x0E8*/ OSMesg seqDmaMesg;
|
|
|
|
/*0x0EC*/ OSIoMesg seqDmaIoMesg;
|
|
|
|
/*0x100*/ OSMesgQueue bankDmaMesgQueue;
|
|
|
|
/*0x118*/ OSMesg bankDmaMesg;
|
|
|
|
/*0x11C*/ OSIoMesg bankDmaIoMesg;
|
|
|
|
/*0x130*/ u8 *bankDmaCurrMemAddr;
|
|
|
|
/*0x134*/ struct AudioBank *loadingBank;
|
2019-10-05 15:08:05 -04:00
|
|
|
/*0x138*/ uintptr_t bankDmaCurrDevAddr;
|
|
|
|
/*0x13C*/ ssize_t bankDmaRemaining;
|
2019-08-25 00:46:40 -04:00
|
|
|
}; // size = 0x140
|
|
|
|
|
|
|
|
struct AdsrSettings
|
|
|
|
{
|
|
|
|
u8 releaseRate;
|
|
|
|
u16 sustain; // sustain level, 2^16 = max
|
|
|
|
struct AdsrEnvelope *envelope;
|
|
|
|
}; // size = 0x8
|
|
|
|
|
|
|
|
struct AdsrState {
|
|
|
|
u8 action;
|
|
|
|
u8 state;
|
|
|
|
s16 initial; // always 0
|
|
|
|
s16 target;
|
|
|
|
s16 current;
|
|
|
|
s16 envIndex;
|
|
|
|
s16 delay;
|
|
|
|
s16 sustain;
|
|
|
|
s16 fadeOutVel;
|
|
|
|
s32 velocity;
|
|
|
|
s32 currentHiRes;
|
|
|
|
s16 *volOut;
|
|
|
|
struct AdsrEnvelope *envelope;
|
|
|
|
}; // size = 0x20
|
|
|
|
|
|
|
|
struct NoteAttributes
|
|
|
|
{
|
|
|
|
s8 reverb;
|
|
|
|
f32 freqScale;
|
|
|
|
f32 velocity;
|
|
|
|
f32 pan;
|
|
|
|
}; // size = 0x10
|
|
|
|
|
|
|
|
struct SequenceChannel
|
|
|
|
{
|
|
|
|
/*0x00*/ u8 enabled : 1;
|
|
|
|
/*0x00*/ u8 finished : 1;
|
|
|
|
/*0x00*/ u8 stopScript : 1;
|
|
|
|
/*0x00*/ u8 unk0b10 : 1;
|
|
|
|
/*0x00*/ u8 hasInstrument : 1;
|
|
|
|
/*0x00*/ u8 stereoHeadsetEffects : 1;
|
|
|
|
/*0x00*/ u8 largeNotes : 1; // notes specify duration and velocity
|
|
|
|
/*0x00*/ u8 unused : 1; // never read, set to 0
|
|
|
|
/*0x01*/ u8 noteAllocPolicy;
|
|
|
|
/*0x02*/ u8 muteBehavior;
|
|
|
|
/*0x03*/ u8 reverb; // or dry/wet mix
|
|
|
|
/*0x04*/ u8 notePriority; // 0-3
|
|
|
|
/*0x05*/ u8 bankId;
|
|
|
|
/*0x06*/ u8 updatesPerFrameUnused; // never read
|
|
|
|
/*0x08*/ u16 vibratoRateStart; // initially 0x800
|
|
|
|
/*0x0A*/ u16 vibratoExtentStart;
|
|
|
|
/*0x0C*/ u16 vibratoRateTarget; // initially 0x800
|
|
|
|
/*0x0E*/ u16 vibratoExtentTarget;
|
|
|
|
/*0x10*/ u16 vibratoRateChangeDelay;
|
|
|
|
/*0x12*/ u16 vibratoExtentChangeDelay;
|
|
|
|
/*0x14*/ u16 vibratoDelay;
|
|
|
|
/*0x16*/ u16 delay;
|
|
|
|
/*0x18*/ s16 instOrWave; // either 0 (none), instrument index + 1, or
|
|
|
|
// 0x80..0x83 for sawtooth/triangle/sine/square waves.
|
|
|
|
/*0x1A*/ s16 transposition;
|
|
|
|
/*0x1C*/ f32 volumeScale;
|
|
|
|
/*0x20*/ f32 volume;
|
|
|
|
/*0x24*/ f32 pan;
|
|
|
|
/*0x28*/ f32 panChannelWeight; // proportion of pan that comes from the channel (0..1)
|
|
|
|
/*0x2C*/ f32 freqScale;
|
|
|
|
/*0x30*/ u8 (*dynTable)[][2];
|
|
|
|
/*0x34*/ struct Note *noteUnused; // never read
|
|
|
|
/*0x38*/ struct SequenceChannelLayer *layerUnused; // never read
|
|
|
|
/*0x3C*/ struct Instrument *instrument;
|
|
|
|
/*0x40*/ struct SequencePlayer *seqPlayer;
|
|
|
|
/*0x44*/ struct SequenceChannelLayer *layers[4];
|
|
|
|
/*0x54*/ 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*/ struct M64ScriptState scriptState;
|
|
|
|
/*0x78*/ struct AdsrSettings adsr;
|
|
|
|
/*0x80*/ struct NotePool notePool;
|
|
|
|
}; // size = 0xC0
|
|
|
|
|
|
|
|
struct SequenceChannelLayer // Maybe SequenceTrack?
|
|
|
|
{
|
|
|
|
/*0x00*/ u8 enabled : 1;
|
|
|
|
/*0x00*/ u8 finished : 1;
|
|
|
|
/*0x00*/ u8 unk0b20 : 1;
|
|
|
|
/*0x00*/ u8 unk0b10 : 1;
|
|
|
|
/*0x01*/ u8 unk1;
|
|
|
|
/*0x02*/ u8 noteDuration; // set to 0x80
|
|
|
|
/*0x03*/ u8 portamentoTargetNote;
|
|
|
|
/*0x04*/ struct Portamento portamento;
|
|
|
|
/*0x14*/ struct AdsrSettings adsr;
|
|
|
|
/*0x1C*/ u16 portamentoTime;
|
|
|
|
/*0x1E*/ 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*/ f32 freqScale;
|
|
|
|
/*0x24*/ f32 velocitySquare;
|
|
|
|
/*0x28*/ f32 pan;
|
|
|
|
/*0x2C*/ f32 noteVelocity;
|
|
|
|
/*0x30*/ f32 notePan;
|
|
|
|
/*0x34*/ f32 noteFreqScale;
|
|
|
|
/*0x38*/ s16 shortNoteDefaultPlayPercentage;
|
|
|
|
/*0x3A*/ s16 playPercentage; // it's not really a percentage...
|
|
|
|
/*0x3C*/ s16 delay;
|
|
|
|
/*0x3E*/ s16 duration;
|
|
|
|
/*0x40*/ s16 delayUnused; // set to 'delay', never read
|
|
|
|
/*0x44*/ struct Note *note;
|
|
|
|
/*0x48*/ struct Instrument *instrument;
|
|
|
|
/*0x4C*/ struct AudioBankSound *sound;
|
|
|
|
/*0x50*/ struct SequenceChannel *seqChannel;
|
|
|
|
/*0x54*/ struct M64ScriptState scriptState;
|
|
|
|
/*0x70*/ struct AudioListItem listItem;
|
|
|
|
}; // size = 0x80
|
|
|
|
|
|
|
|
struct Note
|
|
|
|
{
|
|
|
|
/*0x00*/ u8 enabled : 1;
|
2019-11-03 14:36:27 -05:00
|
|
|
/*0x00*/ u8 needsInit : 1;
|
|
|
|
/*0x00*/ u8 restart : 1;
|
|
|
|
/*0x00*/ u8 finished : 1;
|
|
|
|
/*0x00*/ u8 envMixerNeedsInit : 1;
|
2019-08-25 00:46:40 -04:00
|
|
|
/*0x00*/ u8 stereoStrongRight : 1;
|
|
|
|
/*0x00*/ u8 stereoStrongLeft : 1;
|
|
|
|
/*0x00*/ u8 stereoHeadsetEffects : 1;
|
2019-11-03 14:36:27 -05:00
|
|
|
/*0x01*/ u8 usesHeadsetPanEffects;
|
2019-08-25 00:46:40 -04:00
|
|
|
/*0x02*/ u8 unk2;
|
|
|
|
/*0x03*/ u8 sampleDmaIndex;
|
|
|
|
/*0x04*/ u8 priority;
|
|
|
|
/*0x05*/ u8 sampleCount; // 0, 8, 16, 32 or 64
|
|
|
|
/*0x06*/ u8 instOrWave;
|
|
|
|
/*0x07*/ u8 bankId;
|
|
|
|
/*0x08*/ s16 adsrVolScale;
|
|
|
|
/* */ u8 pad1[2];
|
|
|
|
/*0x0C*/ u16 headsetPanRight;
|
|
|
|
/*0x0E*/ u16 headsetPanLeft;
|
|
|
|
/*0x10*/ u16 prevHeadsetPanRight;
|
|
|
|
/*0x12*/ u16 prevHeadsetPanLeft;
|
2019-11-03 14:36:27 -05:00
|
|
|
/*0x14*/ s32 samplePosInt;
|
2019-08-25 00:46:40 -04:00
|
|
|
/*0x18*/ f32 portamentoFreqScale;
|
|
|
|
/*0x1C*/ f32 vibratoFreqScale;
|
2019-11-03 14:36:27 -05:00
|
|
|
/*0x20*/ u16 samplePosFrac;
|
2019-08-25 00:46:40 -04:00
|
|
|
/*0x24*/ struct AudioBankSound *sound;
|
|
|
|
/*0x28*/ struct SequenceChannelLayer *prevParentLayer;
|
|
|
|
/*0x2C*/ struct SequenceChannelLayer *parentLayer;
|
|
|
|
/*0x30*/ struct SequenceChannelLayer *wantedParentLayer;
|
2019-11-03 14:36:27 -05:00
|
|
|
/*0x34*/ struct NoteSynthesisBuffers *synthesisBuffers;
|
2019-08-25 00:46:40 -04:00
|
|
|
/*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*/ struct AdsrState adsr;
|
|
|
|
/*0x74*/ struct Portamento portamento;
|
|
|
|
/*0x84*/ struct VibratoState vibratoState;
|
|
|
|
/*0x9C*/ s16 curVolLeft;
|
|
|
|
/*0x9E*/ s16 curVolRight;
|
|
|
|
/*0xA0*/ s16 reverbVol;
|
|
|
|
/*0xA2*/ s16 unused2; // never read, set to 0
|
|
|
|
/*0xA4*/ struct AudioListItem listItem;
|
|
|
|
/* */ u8 pad2[0xc];
|
|
|
|
}; // size = 0xC0
|
|
|
|
|
2019-11-03 14:36:27 -05:00
|
|
|
struct NoteSynthesisBuffers
|
2019-08-25 00:46:40 -04:00
|
|
|
{
|
2019-11-03 14:36:27 -05:00
|
|
|
s16 adpcmdecState[0x10];
|
|
|
|
s16 finalResampleState[0x10];
|
|
|
|
s16 mixEnvelopeState[0x28];
|
|
|
|
s16 panResampleState[0x10];
|
|
|
|
s16 panSamplesBuffer[0x20];
|
|
|
|
s16 dummyResampleState[0x10];
|
2019-08-25 00:46:40 -04:00
|
|
|
s16 samples[0x40];
|
|
|
|
};
|
|
|
|
|
2019-11-03 14:36:27 -05:00
|
|
|
struct AudioSessionSettings
|
2019-08-25 00:46:40 -04:00
|
|
|
{
|
|
|
|
/*0x00*/ u32 frequency;
|
|
|
|
/*0x04*/ u8 maxSimultaneousNotes;
|
2019-11-03 14:36:27 -05:00
|
|
|
/*0x05*/ u8 reverbDownsampleRate; // always 1
|
|
|
|
/*0x06*/ u16 reverbWindowSize;
|
|
|
|
/*0x08*/ u16 reverbGain;
|
2019-08-25 00:46:40 -04:00
|
|
|
/*0x0A*/ u16 volume;
|
|
|
|
/*0x0C*/ u32 persistentSeqMem;
|
|
|
|
/*0x10*/ u32 persistentBankMem;
|
|
|
|
/*0x14*/ u32 temporarySeqMem;
|
|
|
|
/*0x18*/ u32 temporaryBankMem;
|
|
|
|
}; // size = 0x1C
|
|
|
|
|
|
|
|
#endif /* _AUDIO_INTERNAL_H */
|