summaryrefslogtreecommitdiff
path: root/src/code
diff options
context:
space:
mode:
authorengineer124 <47598039+engineer124@users.noreply.github.com>2022-05-30 04:31:43 +1000
committerGitHub <noreply@github.com>2022-05-29 14:31:43 -0400
commit8f1fd58f22518857a1131582af0d41adfde2dad9 (patch)
tree6115a622cb48d5d3996feddc8e9d64b5699ec763 /src/code
parentd39ce024581cbbcf22ceb686835a15ab92b53359 (diff)
Audio Docs: Adsr Decay Rate (#1238)
* Init adsr decay docs * cleanup * cleanup * Revert some docs * Cleaner docs * count hex to dec * scaled updates per frame * Consistency * Oops, fix meaning * Avoid `decayRate` conflict with reverb `decayRate` * PR suggestion
Diffstat (limited to 'src/code')
-rw-r--r--src/code/audio_effects.c23
-rw-r--r--src/code/audio_heap.c43
-rw-r--r--src/code/audio_playback.c8
-rw-r--r--src/code/audio_seqplayer.c14
4 files changed, 50 insertions, 38 deletions
diff --git a/src/code/audio_effects.c b/src/code/audio_effects.c
index b87186719..13156e883 100644
--- a/src/code/audio_effects.c
+++ b/src/code/audio_effects.c
@@ -223,23 +223,21 @@ void Audio_AdsrInit(AdsrState* adsr, AdsrEnvelope* envelope, s16* volOut) {
f32 Audio_AdsrUpdate(AdsrState* adsr) {
u8 state = adsr->action.s.state;
+
switch (state) {
case ADSR_STATE_DISABLED:
return 0.0f;
- case ADSR_STATE_INITIAL: {
+ case ADSR_STATE_INITIAL:
if (adsr->action.s.hang) {
adsr->action.s.state = ADSR_STATE_HANG;
break;
}
// fallthrough
- }
-
case ADSR_STATE_START_LOOP:
adsr->envIndex = 0;
adsr->action.s.state = ADSR_STATE_LOOP;
// fallthrough
-
retry:
case ADSR_STATE_LOOP:
adsr->delay = adsr->envelope[adsr->envIndex].delay;
@@ -247,18 +245,21 @@ f32 Audio_AdsrUpdate(AdsrState* adsr) {
case ADSR_DISABLE:
adsr->action.s.state = ADSR_STATE_DISABLED;
break;
+
case ADSR_HANG:
adsr->action.s.state = ADSR_STATE_HANG;
break;
+
case ADSR_GOTO:
adsr->envIndex = adsr->envelope[adsr->envIndex].arg;
goto retry;
+
case ADSR_RESTART:
adsr->action.s.state = ADSR_STATE_INITIAL;
break;
default:
- adsr->delay *= gAudioContext.audioBufferParameters.unk_24;
+ adsr->delay *= gAudioContext.audioBufferParameters.updatesPerFrameScaled;
if (adsr->delay == 0) {
adsr->delay = 1;
}
@@ -273,19 +274,18 @@ f32 Audio_AdsrUpdate(AdsrState* adsr) {
break;
}
// fallthrough
-
case ADSR_STATE_FADE:
adsr->current += adsr->velocity;
- if (--adsr->delay <= 0) {
+ adsr->delay--;
+ if (adsr->delay <= 0) {
adsr->action.s.state = ADSR_STATE_LOOP;
}
// fallthrough
-
case ADSR_STATE_HANG:
break;
case ADSR_STATE_DECAY:
- case ADSR_STATE_RELEASE: {
+ case ADSR_STATE_RELEASE:
adsr->current -= adsr->fadeOutVel;
if (adsr->sustain != 0.0f && state == ADSR_STATE_DECAY) {
if (adsr->current < adsr->sustain) {
@@ -301,10 +301,9 @@ f32 Audio_AdsrUpdate(AdsrState* adsr) {
adsr->action.s.state = ADSR_STATE_DISABLED;
}
break;
- }
case ADSR_STATE_SUSTAIN:
- adsr->delay -= 1;
+ adsr->delay--;
if (adsr->delay == 0) {
adsr->action.s.state = ADSR_STATE_RELEASE;
}
@@ -324,8 +323,10 @@ f32 Audio_AdsrUpdate(AdsrState* adsr) {
if (adsr->current < 0.0f) {
return 0.0f;
}
+
if (adsr->current > 1.0f) {
return 1.0f;
}
+
return adsr->current;
}
diff --git a/src/code/audio_heap.c b/src/code/audio_heap.c
index 3dc51979c..82d1a2e95 100644
--- a/src/code/audio_heap.c
+++ b/src/code/audio_heap.c
@@ -10,32 +10,40 @@ void AudioHeap_DiscardSampleCaches(void);
void AudioHeap_DiscardSampleBank(s32 sampleBankId);
void AudioHeap_DiscardSampleBanks(void);
-f32 func_800DDE20(f32 arg0) {
- return 256.0f * gAudioContext.audioBufferParameters.unkUpdatesPerFrameScaled / arg0;
+/**
+ * Effectively scales `updatesPerFrameInv` by the reciprocal of `scaleInv`
+ * `updatesPerFrameInvScaled` is just `updatesPerFrameInv` scaled down by a factor of 256.0f
+ * i.e. (256.0f * `updatesPerFrameInvScaled`) is just `updatesPerFrameInv`
+ */
+f32 AudioHeap_CalculateAdsrDecay(f32 scaleInv) {
+ return (256.0f * gAudioContext.audioBufferParameters.updatesPerFrameInvScaled) / scaleInv;
}
-void func_800DDE3C(void) {
+/**
+ * Initialize the decay rate table used for decaying notes as part of adsr
+ */
+void AudioHeap_InitAdsrDecayTable(void) {
s32 i;
- gAudioContext.unk_3520[255] = func_800DDE20(0.25f);
- gAudioContext.unk_3520[254] = func_800DDE20(0.33f);
- gAudioContext.unk_3520[253] = func_800DDE20(0.5f);
- gAudioContext.unk_3520[252] = func_800DDE20(0.66f);
- gAudioContext.unk_3520[251] = func_800DDE20(0.75f);
+ gAudioContext.adsrDecayTable[255] = AudioHeap_CalculateAdsrDecay(0.25f);
+ gAudioContext.adsrDecayTable[254] = AudioHeap_CalculateAdsrDecay(0.33f);
+ gAudioContext.adsrDecayTable[253] = AudioHeap_CalculateAdsrDecay(0.5f);
+ gAudioContext.adsrDecayTable[252] = AudioHeap_CalculateAdsrDecay(0.66f);
+ gAudioContext.adsrDecayTable[251] = AudioHeap_CalculateAdsrDecay(0.75f);
for (i = 128; i < 251; i++) {
- gAudioContext.unk_3520[i] = func_800DDE20(251 - i);
+ gAudioContext.adsrDecayTable[i] = AudioHeap_CalculateAdsrDecay(251 - i);
}
for (i = 16; i < 128; i++) {
- gAudioContext.unk_3520[i] = func_800DDE20(4 * (143 - i));
+ gAudioContext.adsrDecayTable[i] = AudioHeap_CalculateAdsrDecay(4 * (143 - i));
}
for (i = 1; i < 16; i++) {
- gAudioContext.unk_3520[i] = func_800DDE20(60 * (23 - i));
+ gAudioContext.adsrDecayTable[i] = AudioHeap_CalculateAdsrDecay(60 * (23 - i));
}
- gAudioContext.unk_3520[0] = 0.0f;
+ gAudioContext.adsrDecayTable[0] = 0.0f;
}
void AudioHeap_ResetLoadStatus(void) {
@@ -826,9 +834,10 @@ void AudioHeap_Init(void) {
gAudioContext.audioBufferParameters.samplesPerUpdateMax = gAudioContext.audioBufferParameters.samplesPerUpdate + 8;
gAudioContext.audioBufferParameters.samplesPerUpdateMin = gAudioContext.audioBufferParameters.samplesPerUpdate - 8;
gAudioContext.audioBufferParameters.resampleRate = 32000.0f / (s32)gAudioContext.audioBufferParameters.frequency;
- gAudioContext.audioBufferParameters.unkUpdatesPerFrameScaled =
+ gAudioContext.audioBufferParameters.updatesPerFrameInvScaled =
(1.0f / 256.0f) / gAudioContext.audioBufferParameters.updatesPerFrame;
- gAudioContext.audioBufferParameters.unk_24 = gAudioContext.audioBufferParameters.updatesPerFrame * 0.25f;
+ gAudioContext.audioBufferParameters.updatesPerFrameScaled =
+ gAudioContext.audioBufferParameters.updatesPerFrame / 4.0f;
gAudioContext.audioBufferParameters.updatesPerFrameInv = 1.0f / gAudioContext.audioBufferParameters.updatesPerFrame;
gAudioContext.sampleDmaBufSize1 = spec->sampleDmaBufSize1;
gAudioContext.sampleDmaBufSize2 = spec->sampleDmaBufSize2;
@@ -898,8 +907,10 @@ void AudioHeap_Init(void) {
gAudioContext.maxAudioCmds * sizeof(u64));
}
- gAudioContext.unk_3520 = AudioHeap_Alloc(&gAudioContext.notesAndBuffersPool, 0x100 * sizeof(f32));
- func_800DDE3C();
+ // Initialize the decay rate table for adsr
+ gAudioContext.adsrDecayTable = AudioHeap_Alloc(&gAudioContext.notesAndBuffersPool, 256 * sizeof(f32));
+ AudioHeap_InitAdsrDecayTable();
+
for (i = 0; i < 4; i++) {
gAudioContext.synthesisReverbs[i].useReverb = 0;
}
diff --git a/src/code/audio_playback.c b/src/code/audio_playback.c
index 4edc18db3..7c9a29d7f 100644
--- a/src/code/audio_playback.c
+++ b/src/code/audio_playback.c
@@ -125,7 +125,7 @@ void Audio_NoteSetResamplingRate(NoteSubEu* noteSubEu, f32 resamplingRateInput)
}
void Audio_NoteInit(Note* note) {
- if (note->playbackState.parentLayer->adsr.releaseRate == 0) {
+ if (note->playbackState.parentLayer->adsr.decayIndex == 0) {
Audio_AdsrInit(&note->playbackState.adsr, note->playbackState.parentLayer->channel->adsr.envelope,
&note->playbackState.adsrVolScaleUnused);
} else {
@@ -506,10 +506,10 @@ void Audio_SeqLayerDecayRelease(SequenceLayer* layer, s32 target) {
} else {
note->playbackState.unk_04 = 1;
note->playbackState.adsr.action.s.decay = true;
- if (layer->adsr.releaseRate == 0) {
- note->playbackState.adsr.fadeOutVel = gAudioContext.unk_3520[layer->channel->adsr.releaseRate];
+ if (layer->adsr.decayIndex == 0) {
+ note->playbackState.adsr.fadeOutVel = gAudioContext.adsrDecayTable[layer->channel->adsr.decayIndex];
} else {
- note->playbackState.adsr.fadeOutVel = gAudioContext.unk_3520[layer->adsr.releaseRate];
+ note->playbackState.adsr.fadeOutVel = gAudioContext.adsrDecayTable[layer->adsr.decayIndex];
}
note->playbackState.adsr.sustain =
((f32)(s32)(layer->channel->adsr.sustain) * note->playbackState.adsr.current) / 256.0f;
diff --git a/src/code/audio_seqplayer.c b/src/code/audio_seqplayer.c
index 3f4b15978..413e8c8e2 100644
--- a/src/code/audio_seqplayer.c
+++ b/src/code/audio_seqplayer.c
@@ -139,7 +139,7 @@ void AudioSeq_InitSequenceChannel(SequenceChannel* channel) {
channel->someOtherPriority = 1;
channel->delay = 0;
channel->adsr.envelope = gDefaultEnvelope;
- channel->adsr.releaseRate = 0xF0;
+ channel->adsr.decayIndex = 0xF0;
channel->adsr.sustain = 0;
channel->vibratoRateTarget = 0x800;
channel->vibratoRateStart = 0x800;
@@ -181,7 +181,7 @@ s32 AudioSeq_SeqChannelSetLayer(SequenceChannel* channel, s32 layerIdx) {
layer = channel->layers[layerIdx];
layer->channel = channel;
layer->adsr = channel->adsr;
- layer->adsr.releaseRate = 0;
+ layer->adsr.decayIndex = 0;
layer->enabled = true;
layer->finished = false;
layer->stopSomething = false;
@@ -543,7 +543,7 @@ s32 AudioSeq_SeqLayerProcessScriptStep2(SequenceLayer* layer) {
}
if (cmd == 0xFF) {
- layer->adsr.releaseRate = 0;
+ layer->adsr.decayIndex = 0;
}
break;
@@ -588,7 +588,7 @@ s32 AudioSeq_SeqLayerProcessScriptStep2(SequenceLayer* layer) {
// fallthrough
case 0xCF:
- layer->adsr.releaseRate = AudioSeq_ScriptReadU8(state);
+ layer->adsr.decayIndex = AudioSeq_ScriptReadU8(state);
break;
case 0xCC:
@@ -664,7 +664,7 @@ s32 AudioSeq_SeqLayerProcessScriptStep4(SequenceLayer* layer, s32 cmd) {
}
sound = &drum->sound;
layer->adsr.envelope = (AdsrEnvelope*)drum->envelope;
- layer->adsr.releaseRate = (u8)drum->releaseRate;
+ layer->adsr.decayIndex = (u8)drum->adsrDecayIndex;
if (!layer->ignoreDrumPan) {
layer->pan = drum->pan;
}
@@ -937,7 +937,7 @@ u8 AudioSeq_GetInstrument(SequenceChannel* channel, u8 instId, Instrument** inst
return 0;
}
adsr->envelope = inst->envelope;
- adsr->releaseRate = inst->releaseRate;
+ adsr->decayIndex = inst->adsrDecayIndex;
*instOut = inst;
instId += 2;
return instId;
@@ -1118,7 +1118,7 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) {
break;
case 0xD9:
command = (u8)parameters[0];
- channel->adsr.releaseRate = command;
+ channel->adsr.decayIndex = command;
break;
case 0xD8:
command = (u8)parameters[0];