summaryrefslogtreecommitdiff
path: root/arm7/lib/src/SND_exChannel.c
diff options
context:
space:
mode:
Diffstat (limited to 'arm7/lib/src/SND_exChannel.c')
-rw-r--r--arm7/lib/src/SND_exChannel.c114
1 files changed, 113 insertions, 1 deletions
diff --git a/arm7/lib/src/SND_exChannel.c b/arm7/lib/src/SND_exChannel.c
index 6081150f..7e41aea3 100644
--- a/arm7/lib/src/SND_exChannel.c
+++ b/arm7/lib/src/SND_exChannel.c
@@ -1,6 +1,5 @@
#include "SND_exChannel.h"
-#include "SND_channel.h"
#include "SND_main.h"
#include "SND_work.h"
#include "SND_util.h"
@@ -14,6 +13,9 @@ extern u8 sAttackCoeffTable[19];
static u32 sLockedChannelMask;
static u32 sWeakLockedChannelMask;
+// TODO remove this extern once we actually know where this table is
+extern u8 sSampleDataShiftTable[4];
+
void SND_ExChannelInit(void) {
struct SNDExChannel *chn;
s32 i;
@@ -468,3 +470,113 @@ int SND_GetLfoValue(struct SNDLfo *lfo) {
return SND_SinIdx((s32)((u32)lfo->counter >> 8)) * lfo->param.depth * lfo->param.range;
}
}
+
+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;
+}