summaryrefslogtreecommitdiff
path: root/arm7/lib/src
diff options
context:
space:
mode:
authorMichael Panzlaff <michael.panzlaff@fau.de>2021-07-07 02:27:19 +0200
committerMichael Panzlaff <michael.panzlaff@fau.de>2021-08-25 18:03:47 +0200
commit6fda29badc3e915d019ab6f6c1cddc19d18614b2 (patch)
treeafd1c99f0dca88ae0d3ac2f265e729ff7531bfa2 /arm7/lib/src
parentc607834736e32183b56150e478f90ee7edc233af (diff)
arm7: decompile SND_channel
Diffstat (limited to 'arm7/lib/src')
-rw-r--r--arm7/lib/src/SND_channel.c116
-rw-r--r--arm7/lib/src/SND_lfo.c2
2 files changed, 117 insertions, 1 deletions
diff --git a/arm7/lib/src/SND_channel.c b/arm7/lib/src/SND_channel.c
new file mode 100644
index 00000000..66acf606
--- /dev/null
+++ b/arm7/lib/src/SND_channel.c
@@ -0,0 +1,116 @@
+#include "SND_channel.h"
+
+#include "SND_lfo.h"
+
+// TODO remove this extern once we actually know where this table is
+extern u8 sSampleDataShiftTable[4];
+
+u16 CalcDecayCoeff(int vol) {
+ if (vol == 127)
+ return 0xFFFF;
+ else if (vol == 126)
+ return 0x3C00;
+ else if (vol < 50)
+ return (u16)(vol * 2 + 1);
+ else
+ return (u16)(0x1E00 / (126 - vol));
+}
+
+void ExChannelSetup(struct SNDExChannel *chn, SNDExChannelCallback callback, void *callbackUserData, int priority) {
+ chn->channelLLNext = NULL;
+ chn->callback = callback;
+ chn->callbackUserData = callbackUserData;
+ chn->length = 0;
+ chn->priority = (u8)priority;
+ chn->volume = 127;
+ chn->flags.start = FALSE;
+ chn->flags.autoSweep = TRUE;
+ chn->midiKey = 60;
+ chn->rootMidiKey = 60;
+ chn->velocity = 127;
+ chn->initPan = 0;
+ chn->userDecay = 0;
+ chn->userDecay2 = 0;
+ chn->userPitch = 0;
+ chn->userPan = 0;
+ chn->panRange = 127;
+ chn->sweepPitch = 0;
+ chn->sweepLength = 0;
+ chn->sweepCounter = 0;
+
+ SND_SetExChannelAttack(chn, 127);
+ SND_SetExChannelDecay(chn, 127);
+ SND_SetExChannelSustain(chn, 127);
+ SND_SetExChannelRelease(chn, 127);
+ SND_InitLfoParam(&chn->lfo.param);
+}
+
+void ExChannelStart(struct SNDExChannel *chn, int length) {
+ chn->envAttenuation = -92544;
+ chn->envStatus = 0;
+ chn->length = length;
+ SND_StartLfo(&chn->lfo);
+ chn->flags.start = TRUE;
+ chn->flags.active = TRUE;
+}
+
+int ExChannelVolumeCmp(struct SNDExChannel *chn_a, struct SNDExChannel *chn_b) {
+ int vol_a = chn_a->volume & 0xFF;
+ int vol_b = chn_b->volume & 0xFF;
+
+ vol_a <<= 4;
+ vol_b <<= 4;
+
+ vol_a >>= sSampleDataShiftTable[chn_a->volume >> 8];
+ vol_b >>= sSampleDataShiftTable[chn_b->volume >> 8];
+
+ if (vol_a != vol_b) {
+ if (vol_a < vol_b)
+ return 1;
+ else
+ return -1;
+ }
+ return 0;
+}
+
+int ExChannelSweepUpdate(struct SNDExChannel *chn, BOOL step) {
+ s64 result;
+
+ if (chn->sweepPitch == 0) {
+ result = 0;
+ } else if (chn->sweepCounter >= chn->sweepLength) {
+ result = 0;
+ } else {
+ result = (s64)chn->sweepPitch * (chn->sweepLength - chn->sweepCounter) / chn->sweepLength;
+
+ if (step && chn->flags.autoSweep)
+ chn->sweepCounter++;
+ }
+
+ return (int)result;
+}
+
+int ExChannelLfoUpdate(struct SNDExChannel *chn, BOOL step) {
+ s64 result = SND_GetLfoValue(&chn->lfo);
+
+ if (result != 0) {
+ switch (chn->lfo.param.target) {
+ case SND_LFO_VOLUME:
+ result *= 60;
+ break;
+ case SND_LFO_PITCH:
+ result <<= 6;
+ break;
+ case SND_LFO_PAN:
+ result <<= 6;
+ break;
+ }
+ result >>= 14;
+ }
+
+ if (step) {
+ SND_UpdateLfo(&chn->lfo);
+ }
+
+ return (int)result;
+}
diff --git a/arm7/lib/src/SND_lfo.c b/arm7/lib/src/SND_lfo.c
index eca98197..262c6d27 100644
--- a/arm7/lib/src/SND_lfo.c
+++ b/arm7/lib/src/SND_lfo.c
@@ -32,7 +32,7 @@ void SND_UpdateLfo(struct SNDLfo *lfo) {
}
}
-s32 SND_GetLfoValue(struct SNDLfo *lfo) {
+int SND_GetLfoValue(struct SNDLfo *lfo) {
if (lfo->param.depth == 0) {
return 0;
} else if (lfo->delayCounter < lfo->param.delay) {