diff options
Diffstat (limited to 'arm7/lib/src/SND_bank.c')
-rw-r--r-- | arm7/lib/src/SND_bank.c | 194 |
1 files changed, 194 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..3437e021 --- /dev/null +++ b/arm7/lib/src/SND_bank.c @@ -0,0 +1,194 @@ +#include "SND_bank.h" + +#include "SND_exChannel.h" +#include "SND_main.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; + } +} |