diff options
Diffstat (limited to 'arm7/lib')
-rw-r--r-- | arm7/lib/include/SND_channel.h | 4 | ||||
-rw-r--r-- | arm7/lib/include/SND_exChannel.h | 12 | ||||
-rw-r--r-- | arm7/lib/include/SND_lfo.h | 2 | ||||
-rw-r--r-- | arm7/lib/src/SND_channel.c | 116 | ||||
-rw-r--r-- | arm7/lib/src/SND_lfo.c | 2 |
5 files changed, 126 insertions, 10 deletions
diff --git a/arm7/lib/include/SND_channel.h b/arm7/lib/include/SND_channel.h index 718e7e2b..ea179968 100644 --- a/arm7/lib/include/SND_channel.h +++ b/arm7/lib/include/SND_channel.h @@ -3,6 +3,8 @@ #include "nitro/types.h" +#include "SND_exChannel.h" + void SND_SetupChannelPcm( s32 chnIdx, const void *data, @@ -40,6 +42,6 @@ void SND_SetChannelPan(s32 chnIdx, s32 pan); void SND_SetChannelTimer(s32 chnIdx, s32 timer); // TODO move this function to SND_exChannel.c -u16 CalcDecayCoeff(s32 value); +u16 CalcDecayCoeff(int value); #endif //GUARD_SND_CHANNEL_H diff --git a/arm7/lib/include/SND_exChannel.h b/arm7/lib/include/SND_exChannel.h index dfd93f21..fcc3a548 100644 --- a/arm7/lib/include/SND_exChannel.h +++ b/arm7/lib/include/SND_exChannel.h @@ -6,8 +6,6 @@ #include "nitro/SND_exChannel_shared.h" #include "nitro/SND_main_shared.h" -typedef void (*SNDExChannelCallback)(struct SNDExChannel *chn, s32 status, void *userData); - void SND_ExChannelInit(void); void SND_UpdateExChannel(void); void SND_ExChannelMain(BOOL step); @@ -26,10 +24,10 @@ void SND_FreeExChannel(struct SNDExChannel *chn); BOOL SND_IsChannelActive(s32 idx); // TODO internal functions, move these so exChannel -s32 ExChannelSweepUpdate(struct SNDExChannel *chn, BOOL step); -s32 ExChannelLfoUpdate(struct SNDExChannel *chn, BOOL step); -void ExChannelStart(struct SNDExChannel *chn, s32); -s32 ExChannelVolumeCmp(struct SNDExChannel *chn_a, struct SNDExChannel *chn_b); -void ExChannelSetup(struct SNDExChannel *, SNDExChannelCallback callback, void *callbackUserData, s32 priority); +int ExChannelSweepUpdate(struct SNDExChannel *chn, BOOL step); +int ExChannelLfoUpdate(struct SNDExChannel *chn, BOOL step); +void ExChannelStart(struct SNDExChannel *chn, int length); +int ExChannelVolumeCmp(struct SNDExChannel *chn_a, struct SNDExChannel *chn_b); +void ExChannelSetup(struct SNDExChannel *, SNDExChannelCallback callback, void *callbackUserData, int priority); #endif //GUARD_SND_EXCHANNEL_H diff --git a/arm7/lib/include/SND_lfo.h b/arm7/lib/include/SND_lfo.h index 05d4647e..43055c27 100644 --- a/arm7/lib/include/SND_lfo.h +++ b/arm7/lib/include/SND_lfo.h @@ -8,6 +8,6 @@ void SND_InitLfoParam(struct SNDLfoParam *lfoParam); void SND_StartLfo(struct SNDLfo *lfo); void SND_UpdateLfo(struct SNDLfo *lfo); -s32 SND_LfoGetValue(struct SNDLfo *lfo); +int SND_GetLfoValue(struct SNDLfo *lfo); #endif //GUARD_SND_LFO_H 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) { |