1#ifndef ALCHEMY_AUDIO_ENGINE_TYPES_H
2#define ALCHEMY_AUDIO_ENGINE_TYPES_H
10#define SOUND_LOCK 0x68736D53
12#define SOUND_WORK (*(struct SoundWork **)0x03007FF0)
14#define REG_NR10 (*(volatile u8 *)0x04000060)
15#define REG_NR11 (*(volatile u8 *)0x04000062)
16#define REG_NR12 (*(volatile u8 *)0x04000063)
17#define REG_NR13 (*(volatile u8 *)0x04000064)
18#define REG_NR14 (*(volatile u8 *)0x04000065)
19#define REG_NR21 (*(volatile u8 *)0x04000068)
20#define REG_NR22 (*(volatile u8 *)0x04000069)
21#define REG_NR23 (*(volatile u8 *)0x0400006c)
22#define REG_NR24 (*(volatile u8 *)0x0400006d)
23#define REG_NR30 (*(volatile u8 *)0x04000070)
24#define REG_NR31 (*(volatile u8 *)0x04000072)
25#define REG_NR32 (*(volatile u8 *)0x04000073)
26#define REG_NR33 (*(volatile u8 *)0x04000074)
27#define REG_NR34 (*(volatile u8 *)0x04000075)
28#define REG_NR41 (*(volatile u8 *)0x04000078)
29#define REG_NR42 (*(volatile u8 *)0x04000079)
30#define REG_NR43 (*(volatile u8 *)0x0400007c)
31#define REG_NR44 (*(volatile u8 *)0x0400007d)
32#define REG_NR51 (*(volatile u8 *)0x04000081)
34#define REG_NR50 (*(volatile u8 *)0x04000080)
35#define REG_SOUNDCNT_L (*(volatile u16 *)0x04000080)
36#define REG_SOUNDCNT_X (*(volatile u16 *)0x04000084)
37#define SOUNDCNT_X_ENABLE 0x80
38#define SOUNDCNT_X_ALL_TONES_ON 0x0f
39#define REG_SOUNDBIAS_H (*(volatile u8 *)0x04000089)
40#define REG_WAVE_RAM ((volatile u32 *)0x04000090)
52#define SOUND_COMMAND_CAST(type, routine) ((type)(void (*)(void))(routine))
61#define SOUND_COMMAND_FINISH 0
62#define SOUND_COMMAND_GOTO 1
66#define SOUND_COMMAND_WORK_BYTE 8
68#define SOUND_COMMAND_LFO_SPEED 17
70#define SOUND_COMMAND_MODULATION 19
74#define SOUND_COMMAND_EXTENDED 28
77#define SOUND_COMMAND_RELEASE_KEY 29
78#define SOUND_COMMAND_PCM_RATE 30
80#define SOUND_COMMAND_STOP_TRACK 31
81#define SOUND_COMMAND_FADE 32
82#define SOUND_COMMAND_CALCULATE_OUTPUT 33
85#define SOUND_COMMAND_DETACH_NOTE 34
88#define SOUND_COMMAND_CLEAR_WORK 35
109#define SOUND_FADE_FULL_VOLUME 0x100
110#define SOUND_FADE_STEP 16
void CgbAudio_Initialize(struct CgbNote *notes)
Resets the CGB sound hardware, installs the CGB-aware command handlers and callbacks in the sound wor...
const struct PlayerSlot gSound_PlayerSlots[]
void MusicPlayer_StartSong(struct SoundPlayer *player, const struct SequenceHeader *header)
Starts a song when its priority permits, resetting its tracks and tempo.
void MusicPlayer_FadeOut(struct SoundPlayer *player, u16 speed)
Begins the standard stop-and-clear fade.
SoundCommand gSound_CommandTable[36]
const struct SongEntry gSound_SongTable[]
@ SOUND_WORK_GREATER_BYTE
@ SOUND_WORK_NOT_EQUAL_BYTE
@ SOUND_WORK_LESS_EQUAL_BYTE
@ SOUND_WORK_SUBTRACT_BYTE
@ SOUND_WORK_GREATER_EQUAL
@ SOUND_WORK_GREATER_EQUAL_BYTE
@ SOUND_TRACK_PITCH_DIRTY
@ SOUND_TRACK_UPDATE_VOLUME
@ SOUND_TRACK_UPDATE_PITCH
@ SOUND_TRACK_VOLUME_DIRTY
@ SOUND_PLAYER_TRACK_LIMIT
Most tracks a player takes; MusicPlayer_Initialize caps its count here, and the track masks of the Mu...
@ SOUND_CGB_CHANNEL_COUNT
CGB channels, numbered 1 to 4.
@ SOUND_PCM_NOTE_CAPACITY
The PCM notes in SoundWork.pcmNotes; mode changes and AudioEngine_StopAllChannels clear all 12,...
@ SOUND_MODULATION_VOLUME
void MusicPlayer_SetPitch(struct SoundPlayer *player, u16 mask, s16 pitch)
Sets the semitone and fractional pitch offsets of selected active tracks and marks their pitch for re...
void MusicPlayer_SetLfoSpeed(struct SoundPlayer *player, u32 selectedTracks, u32 speedArgument)
Sets LFO speed on selected active tracks, resetting modulation when stopped.
void MusicPlayer_SetModulationDepth(struct SoundPlayer *player, s32 selectedTracks, s32 depthArgument)
Sets modulation depth on selected active tracks, resetting zero-depth modulation.
void CgbNote_UpdatePanEnvelope(struct CgbNote *note)
Chooses stereo routing and derives peak and sustain levels for a CGB note, writing them into note.
void AudioCommand_InvokeSlot34(struct SoundNote *note)
Detaches a note through the command table entry installed by the driver.
void MusicTrack_DispatchStreamCommand(struct SoundPlayer *player, struct SoundTrack *track)
Reads an extended-command index and invokes its handler.
void MusicPlayer_SetPitchAndUpdateFrequency(struct SoundPlayer *player, u16 scale)
Sets the tempo multiplier and updates the number of ticks advanced per frame.
UNUSED void MusicPlayer_SetPan(struct SoundPlayer *player, u16 mask, s8 pan)
Sets the stereo pan offset of selected active tracks.
void AudioCommand_InvokeSlot35(void *block)
Clears a 64-byte player or track prefix through the driver command table.
void MusicTrack_ClearModulation(struct SoundTrack *track)
Resets the LFO phase and amount, marking the affected output for recalculation.
void MusicTrack_ReadVoiceTarget(struct SoundPlayer *player, struct SoundTrack *track)
Reads an unaligned little-endian voice target address from the sequence.
void MusicPlayer_SetVolume(struct SoundPlayer *player, u16 mask, u16 volume)
Sets the volume scale of active tracks selected by the bit mask and marks their output for recalculat...
STATIC_ASSERT, a compile-time check that emits nothing.
#define STATIC_ASSERT(condition)
C89 permits repeated extern declarations of the same array.
#define offsetof(type, member)
A note on one of the four CGB channels of the hardware: its state and envelope, its levels and pan,...
u8 attack
Frames per attack step.
u8 channelBits
This channel's NR51 bits: 0x11, 0x22, 0x44, 0x88.
u32 frequency
Tone frequency from Cgb_KeyToFrequency (2048 added), or channel 4's NR43 value.
u8 echoLevel
After release, the level held is peak * echoLevel / 256.
u8 outLeft
Velocity and track volume to the left, 0 to 255.
u8 release
Frames per release step.
u8 trigger
Value for NRx4: 7 restart, 6 length on, 2..0 frequency.
u8 echoLength
Frames the echo lasts.
u8 sweep
Channel 1's NR10 sweep; 8 when none.
u8 length
The voice's length.
u8 level
Envelope level 0 to 15 written to the channel.
u8 counter
Frames left in the current envelope step.
u8 peak
Top of the envelope: (outRight + outLeft) / 16, at most 15 when one side plays.
u8 modified
CgbNoteModified: what to write to the channel.
u8 panBits
NR51 bits this note sets: one side or both.
u32 * loadedWave
Channel 3: the pattern last copied into wave RAM.
u8 unk2c[0x14]
0x2c track, 0x30 prev and 0x34 next, as in SoundNote.
u8 state
CgbNoteState and CgbNotePhase; 0 when the channel is free.
u8 sustain
Sustain level 0 to 15, scaled by peak.
u8 key
The key played, before the track's pitch.
u8 decay
Frames per decay step.
u8 sustainLevel
(peak * sustain + 15) / 16.
u8 outRight
Velocity and track volume to the right, 0 to 255.
u8 unk0e[0x0b]
0x10 gate in ticks, 0x11 the song's key, 0x12 velocity, 0x13 priority (a new note of higher priority ...
u8 kind
Channel number 1 to 4 at setup, then the voice's kind; bit 3 rounds the frequency to the sound bias's...
u32 * wave
Channel 3: the 16-byte wave pattern.
An entry of the player table: a player, its tracks and track count, and its priority check.
struct SoundTrack * tracks
trackCount tracks for the player.
struct SoundPlayer * player
u8 unk09
0 in every entry; not named by TBS code.
u16 checkPriority
Copied to the player's checkPriority; 0 everywhere.
An entry of the song table: a song's header and the player table entry that plays it.
u16 slot
Index into gSound_PlayerSlots; AudioCommand_Play gives slot 7's songs the first player from 7 down to...
u16 unk06
The same value as slot in every entry; not named by TBS code.
const struct SequenceHeader * header
A PCM note, one of 12 the mixer renders: its state and envelope, its output levels,...
u8 outRight
Velocity and track volume to the right, 0 to 255.
u8 kind
The voice's kind; bits 2..0 nonzero for a CGB note.
u8 unk07[3]
The voice's release (0x07), the key played (0x08) and the envelope level, 0 to 255 (0x09).
u8 peak
For a PCM note, the mixer writes the envelope's right level here each frame; the name comes from CgbN...
u8 channelBits
CgbNote.channelBits; for a PCM note, the mixer's fractional sample position is the word at 0x1c.
u8 unk0b[0x0e]
0x0b left level, 0x0c echo level, 0x0d echo frames, 0x10 gate in ticks, 0x11 the song's key,...
u8 unk04[2]
The voice's attack (0x04) and decay (0x05).
u8 panBits
CgbNote.panBits; inside the samples-left word for a PCM note.
u8 outLeft
Velocity and track volume to the left, 0 to 255.
struct SoundNote * prev
The note started after this one in the track's list (nearer its head); NULL at the head.
u8 unk1a
Inside the samples-left word for a PCM note.
u8 unk1d[0x0f]
0x1d CGB update bits, 0x1e CGB length, 0x1f CGB sweep, 0x20 the word frequency, 0x24 the voice's targ...
u8 sustain
The voice's sustain level.
u8 sustainLevel
CgbNote.sustainLevel; inside the samples-left word for a PCM note.
struct SoundNote * next
The note started before this one in the track's list; NULL at the end.
struct SoundTrack * track
The track whose list holds this note; NULL once detached.
u8 unk38[8]
Not named by TBS code.
A player, which plays one song: its header and status, its tracks, its tempo and fade.
const struct SequenceHeader * header
The song playing or last played.
u8 checkPriority
Nonzero: a song of lower priority does not replace a playing one.
u16 tempoStep
tempo * tempoScale / 256, added to tempoCount each frame.
u8 unk10[8]
Not named by TBS code.
u16 fadeCounter
Frames left until the next fade step.
u8 unk0a
The last command run: its byte - 0xB1.
u32 ticks
Song ticks played since the song started.
u16 tempoCount
Each 150 in it runs one tick, so a tempoStep of 150 is a tick a frame.
u8 unk2a[2]
Not named by TBS code.
u16 fadeVolume
bits: 8..4 level, 0 to 0x100 in steps of 16 | 1 fade in | 0 pause at the end (SoundFadeFlag).
u32 status
bits: 31 paused | 15..0 tracks active after the last tick.
void(*) nextTick(struct SoundPlayer *player)
The tick routine and player that were first in the chain before this player was added; this player's ...
u8 priority
The song's priority.
u8 trackCount
Tracks this player owns, at most 16.
u16 tempoScale
256 plays at the song's tempo.
u8 * workBytes
gSound_WorkBytes, which the work-byte command uses.
u16 tempo
Twice the tempo command's byte; 150 at start.
const struct SoundVoice * voices
The song's voice table.
u32 lock
SOUND_LOCK when free; raised while the player is changed or ticked.
struct SoundPlayer * nextTickPlayer
Passed to nextTick.
struct SoundTrack * tracks
trackCount tracks.
u16 fadePeriod
Frames between fade steps; 0 when not fading.
A track of a playing song: the song commands it runs, its voice and notes, and the pitch,...
u8 bendRange
Semitones a full bend reaches; 2 at reset.
s8 bend
The bend command's byte - 64: full bend is bendRange.
s8 modAmount
The LFO's output, modDepth * wave / 64: added to the pitch in 1/16 semitone, to the pan,...
u8 unk44[0x0c]
Cursors to return to after each of up to three nested patterns.
u8 unk01[7]
0x01 ticks until the next command, 0x02 pattern depth (0 to 3), 0x03 repeat count,...
u8 pitchHi
Whole semitones of the track's pitch, read as signed and added to each note's key (a sum below 0 play...
u8 pitchLo
The pitch's fraction, 0 to 255 in 1/256 semitone, passed as the fine pitch to the key-to-frequency st...
u8 tailLevel
Each new note's echo level.
u8 lfoSpeed
LFO phase step a tick, 22 at reset; 0 stops the LFO and clears modAmount.
struct SoundNote * notes
The notes this track started, newest first, linked through SoundNote.next; PCM notes from SoundWork....
u8 outVolumeB
Left volume: (127 - pan) * scaled volume / 256.
u8 outVolumeA
Right volume: (pan + 128) * scaled volume / 256.
struct SoundVoice voice
Copied from the player's voice table by the voice command, or set a field at a time by extended comma...
u8 unk1b[3]
0x1b LFO delay in ticks (song command), 0x1c its countdown, reloaded by each note,...
s8 pan
The pan command's byte - 64, -64 to 63; doubled for output.
u8 fine
1/256 semitone, from MusicPlayer_SetPitch.
s8 tune
The tune command's byte - 64: 1/64 semitone.
const u8 * cursor
The next command byte in the song's data, from the header's track pointer; a track's commands end at ...
u8 volume
The song's volume command, scaled by volumeScale / 32.
u8 unk30[0x10]
Not named by TBS code; zeroed with the first 64 bytes at reset.
u8 modDepth
0 to 255, from the modulation command or MusicPlayer_SetModulationDepth; 0 stops the LFO and clears m...
u8 modTarget
SoundModulationTarget.
u8 tailLength
Each new note's echo length in frames.
u8 lfoPhase
0 to 255, wrapping; the wave is phase over 0 to 63, 128 - phase over 64 to 191 and phase - 256 over 1...
s8 panOffset
Added to the doubled pan, from MusicPlayer_SetPan.
s8 keyOffsetB
Semitones, from MusicPlayer_SetPitch.
u8 volumeScale
0 to 64 (full, the reset value): a player volume or fade level of 0 to 0x100 divided by 4.
s8 keyOffsetA
Semitones, from the song's key-shift command.
A voice a track plays its notes with: its kind and base key, the sample or wave it plays,...
const void * target
The PCM sample, the CGB wave pattern, duty or noise width, or for a rhythm or split voice its voice t...
u8 attack
PCM: added to the envelope each frame until 255.
u8 decay
PCM: envelope * decay / 256 a frame. CGB: frames a step.
u8 panOrSweep
CGB channel 1's sweep (NR10) when bit 7 is clear and bits 6..4 are not; else no sweep.
u8 release
PCM: envelope * release / 256 a frame. CGB: frames a step.
u8 kind
bits: 7 rhythm | 6 key split | 3 fixed rate for PCM, bias rounding for CGB | 2..0 CGB channel (0 PCM)...
u8 baseKey
Key a rhythm entry plays every note at.
u8 length
CGB sound length (NRx1); 0 plays until released.
u8 sustain
Level decay stops at: 0 to 255 for PCM, 0 to 15 for CGB.
The sound driver's work: its lock, the mixer's rate and buffers, the PCM and CGB notes,...
s32(*) cgbFrequency(u8 kind, u8 key, u8 fine)
Cgb_KeyToFrequency.
u8 pcmNoteCount
PCM notes in use, 8 at start (mode bits 11..8).
void(*) unk3c(void)
Set to Audio_EmptyCallback by AudioEngine_Initialize; no TBS code reads it by name.
u8 reverb
0 to 127 (mode bits 6..0); 0 skips the reverb pass.
u8 volume
PCM volume 0 to 15, 15 at start (mode bits 15..12).
s8 buffers[2][0x630]
Right (0, DMA 1 to FIFO A) and left (1, DMA 2 to FIFO B) samples, transferPeriod frames of frameSampl...
struct SoundPlayer * tickPlayer
Passed to tick.
u32 lock
SOUND_LOCK when free; raised while the driver changes it.
u8 rate
1 to 12, indexes gSound_FrameLengths (mode bits 19..16).
u8 unk0d[3]
Not named by TBS code.
u32 frameSamples
Samples mixed a frame, from gSound_FrameLengths.
struct SoundNote pcmNotes[12]
pcmNoteCount of them play.
u32 rateStep
2^23 / outputRate, rounded; a note's frequency times it is its step a sample.
struct CgbNote * cgbNotes
gSound_CgbNotes; NULL before CGB setup.
void(*) noteOn(u32 command, struct SoundPlayer *player, struct SoundTrack *track)
MusicTrack_HandleNote, run for song bytes from 0xCF up with the byte.
u8 maxLines
Nonzero: the mixer stops taking notes once the scanline passes this many lines after its start.
void(*) cgbUpdate(void)
Run each mixer frame: Cgb_UpdateChannels.
u8 unk09
Not named by TBS code.
void(*) cgbMute(u8 channel)
CgbChannel_Mute, channel 1 to 4.
SoundCommand * commands
gSound_CommandTable.
u32 outputRate
Samples a second: frameSamples * 59.7275, rounded.
volatile u8 transferCountdown
Frames until the VBlank DMA restart, which reloads it from transferPeriod; also picks the frame of th...
void(*) tick(struct SoundPlayer *player)
First of the chain of player ticks run each mixer frame; NULL for none.
u8 transferPeriod
Frames the buffers hold: 0x630 / frameSamples.
u8 cgbTick
Counts 14 down to 0 once a CGB update; at 0 the envelopes take an extra step.
u8 unk40[0x10]
Not named by TBS code.
void(*) SoundCommand(struct SoundPlayer *player, struct SoundTrack *track)
A command table entry: the driver calls it with the player and the track.
const SoundCommand gSound_ExtendedCommandTable[]
Extended commands; entries zero and three do nothing.
The integer types, TRUE, UNUSED and the fixed-address macros.