diff options
Diffstat (limited to 'arm7/lib/src')
-rw-r--r-- | arm7/lib/src/SND_bank.c | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/arm7/lib/src/SND_bank.c b/arm7/lib/src/SND_bank.c new file mode 100644 index 00000000..5c9fb3dd --- /dev/null +++ b/arm7/lib/src/SND_bank.c @@ -0,0 +1,155 @@ +#include "SND_bank.h" + +#include "SND_main.h" +#include "SND_exChannel.h" + +#include "mmap.h" + +static const struct SNDWaveData *GetWaveData(const struct SNDBankData *bankData, s32 waveArc, s32 wave); + +BOOL SND_ReadInstData(const struct SNDBankData *bankData, s32 program, s32 midiKey, struct SNDInstData *instData) { + s32 i; + struct SNDDrumSet *drumSet; + struct SNDKeySplit *keySplit; + u32 off; + u8 minKey, maxKey; + + if (program < 0) + return FALSE; + + SNDi_LockMutex(); + + if (program >= bankData->instCount) { + SNDi_UnlockMutex(); + return FALSE; + } + + off = bankData->instOffsets[program]; + instData->type = SND_INST_OFFSET_TYPE(off); + + switch (instData->type) { + case SND_INST_PCM: + case SND_INST_PSG: + case SND_INST_NOISE: + case SND_INST_DIRECTPCM: + case SND_INST_DUMMY: + instData->param = *SND_INST_OFFSET_NORMAL(bankData, off); + break; + case SND_INST_DRUM_TABLE: + drumSet = SND_INST_OFFSET_DRUMS(bankData, off); + + // seperate variables needed for matching + maxKey = drumSet->maxKey; + minKey = drumSet->minKey; + + if (midiKey < minKey || midiKey > maxKey) { + SNDi_UnlockMutex(); + return FALSE; + } + + *instData = drumSet->instruments[midiKey - drumSet->minKey]; + break; + case SND_INST_KEY_SPLIT: + i = 0; + keySplit = SND_INST_OFFSET_KEYSPL(bankData, off); + + while (midiKey > keySplit->key[i]) { + i++; + if (i >= SND_INST_MAX_KEYSPLIT) { + SNDi_UnlockMutex(); + return FALSE; + } + } + *instData = keySplit->instruments[i]; + break; + case SND_INST_ILLEGAL: + default: + SNDi_UnlockMutex(); + return FALSE; + } + + SNDi_UnlockMutex(); + return TRUE; +} + +const struct SNDWaveData *SND_GetWaveDataAddress(const struct SNDWaveArc *waveArc, s32 wave) { + SNDi_LockMutex(); + + const struct SNDWaveData *retval = (const struct SNDWaveData *)waveArc->waveOffsets[wave]; + if (retval != NULL) { + if ((u32)retval < HW_MAIN_MEM) { + retval = (const struct SNDWaveData *)((u32)waveArc + (u32)retval); + } + } else { + retval = NULL; + } + + SNDi_UnlockMutex(); + + return retval; +} + +BOOL SND_NoteOn(struct SNDExChannel *chn, s32 midiKey, s32 velocity, s32 length, const struct SNDBankData *bankData, const struct SNDInstData *instData) { + const struct SNDWaveData *waveData; + u8 release; + BOOL success; + + release = instData->param.envRelease; + + if (release == 0xFF) { + length = -1; + release = 0; + } + + switch (instData->type) { + case SND_INST_PCM: + case SND_INST_DIRECTPCM: + if (instData->type == SND_INST_PCM) { + waveData = GetWaveData(bankData, instData->param.wave[1], instData->param.wave[0]); + } else { + waveData = (const struct SNDWaveData *)((instData->param.wave[1] << 16) | instData->param.wave[0]); + } + + if (waveData == NULL) { + success = FALSE; + } else { + success = SND_StartExChannelPcm(chn, &waveData->param, waveData->sampleData, length); + } + break; + case SND_INST_PSG: + success = SND_StartExChannelPsg(chn, instData->param.wave[0], length); + break; + case SND_INST_NOISE: + success = SND_StartExChannelNoise(chn, length); + break; + default: + success = FALSE; + break; + } + + if (success == FALSE) { + return FALSE; + } else { + chn->midiKey = (u8)midiKey; + chn->rootMidiKey = instData->param.rootKey; + chn->velocity = (u8)velocity; + SND_SetExChannelAttack(chn, instData->param.envAttack); + SND_SetExChannelDecay(chn, instData->param.envDecay); + SND_SetExChannelSustain(chn, instData->param.envSustain); + SND_SetExChannelRelease(chn, release); + chn->initPan = (s8)(instData->param.pan - 0x40); + return TRUE; + } +} + +static const struct SNDWaveData *GetWaveData(const struct SNDBankData *bankData, s32 waveArc, s32 wave) { + const struct SNDWaveArc *arcPtr = bankData->waveArcLinks[waveArc].waveArc; + + if (arcPtr == NULL) { + return NULL; + } else if (wave < arcPtr->waveCount) { + return SND_GetWaveDataAddress(arcPtr, wave); + } else { + return NULL; + } +} |