958 lines
22 KiB
C
958 lines
22 KiB
C
#include <os_internal.h>
|
|
#include <ultraerror.h>
|
|
#include <libaudio.h>
|
|
#include "n_sndp.h"
|
|
#include "lib/snd.h"
|
|
#include "lib/lib_317f0.h"
|
|
#include "bss.h"
|
|
#include "data.h"
|
|
#include "types.h"
|
|
|
|
u32 var8009c330;
|
|
s16 *var8009c334;
|
|
|
|
struct sndstate *g_SndpAllocStatesHead = NULL;
|
|
struct sndstate *g_SndpAllocStatesTail = NULL;
|
|
struct sndstate *g_SndpFreeStatesHead = NULL;
|
|
N_ALSndPlayer *g_SndPlayer = &var8009c2d0;
|
|
s16 var8005f130 = 0;
|
|
s32 var8005f134 = 0;
|
|
s32 var8005f138 = 0;
|
|
void (*g_SndpAddRefCallback)(ALSound *) = NULL;
|
|
void (*g_SndpRemoveRefCallback)(ALSound *) = NULL;
|
|
|
|
void sndpSetAddRefCallback(void *fn);
|
|
void sndpSetRemoveRefCallback(void *fn);
|
|
void sndpFreeState(struct sndstate *state);
|
|
void func00033bc0(struct sndstate *state);
|
|
|
|
void n_alSndpNew(ALSndpConfig *config)
|
|
{
|
|
u32 i;
|
|
void *ptr;
|
|
N_ALEvent evt;
|
|
|
|
// Init member variables
|
|
g_SndPlayer->maxSounds = config->maxSounds;
|
|
g_SndPlayer->target = NULL;
|
|
g_SndPlayer->frameTime = AL_USEC_PER_FRAME;
|
|
|
|
ptr = alHeapAlloc(config->heap, 1, config->maxStates * sizeof(struct sndstate));
|
|
g_SndPlayer->sndState = ptr;
|
|
|
|
// Init the event queue
|
|
ptr = alHeapAlloc(config->heap, 1, config->maxEvents * sizeof(N_ALEventListItem));
|
|
n_alEvtqNew(&g_SndPlayer->evtq, ptr, config->maxEvents);
|
|
|
|
g_SndpFreeStatesHead = g_SndPlayer->sndState;
|
|
|
|
for (i = 1; i < config->maxStates; i++) {
|
|
struct sndstate *sndstate = g_SndPlayer->sndState;
|
|
alLink(&sndstate[i].node, &sndstate[i - 1].node);
|
|
}
|
|
|
|
sndpSetAddRefCallback(NULL);
|
|
sndpSetRemoveRefCallback(NULL);
|
|
|
|
var8009c334 = alHeapAlloc(config->heap, sizeof(s16), config->unk10);
|
|
|
|
for (i = 0; i < config->unk10; i++) {
|
|
var8009c334[i] = 0x7fff;
|
|
}
|
|
|
|
// Add ourselves to the driver
|
|
g_SndPlayer->node.next = NULL;
|
|
g_SndPlayer->node.handler = (ALVoiceHandler) _n_sndpVoiceHandler;
|
|
g_SndPlayer->node.clientData = g_SndPlayer;
|
|
|
|
n_alSynAddSndPlayer(&g_SndPlayer->node);
|
|
|
|
// Start responding to API events
|
|
evt.type = AL_SNDP_API_EVT;
|
|
|
|
n_alEvtqPostEvent(&g_SndPlayer->evtq, &evt, g_SndPlayer->frameTime, 1);
|
|
|
|
g_SndPlayer->nextDelta = n_alEvtqNextEvent(&g_SndPlayer->evtq, &g_SndPlayer->nextEvent);
|
|
}
|
|
|
|
ALMicroTime _n_sndpVoiceHandler(void *node)
|
|
{
|
|
N_ALSndPlayer *sndp = (N_ALSndPlayer *) node;
|
|
N_ALSndpEvent evt;
|
|
|
|
do {
|
|
switch (sndp->nextEvent.type) {
|
|
case (AL_SNDP_API_EVT):
|
|
evt.common.type = AL_SNDP_API_EVT;
|
|
n_alEvtqPostEvent(&sndp->evtq, (N_ALEvent *)&evt, sndp->frameTime, 1);
|
|
break;
|
|
|
|
default:
|
|
_n_handleEvent((N_ALSndpEvent *)&sndp->nextEvent);
|
|
break;
|
|
}
|
|
|
|
sndp->nextDelta = n_alEvtqNextEvent(&sndp->evtq, &sndp->nextEvent);
|
|
} while (sndp->nextDelta == 0);
|
|
|
|
sndp->curTime += sndp->nextDelta;
|
|
|
|
return sndp->nextDelta;
|
|
}
|
|
|
|
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
|
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
|
|
|
void _n_handleEvent(N_ALSndpEvent *event)
|
|
{
|
|
ALVoiceConfig config;
|
|
ALSound *sound;
|
|
ALKeyMap *keymap;
|
|
ALPan pan;
|
|
N_ALSndpEvent sp94;
|
|
N_ALSndpEvent sp84;
|
|
ALMicroTime delta;
|
|
s32 fxmix;
|
|
s32 vol;
|
|
s32 tmppan;
|
|
s32 sp70;
|
|
s32 isspecial;
|
|
bool done = true;
|
|
bool hasvoice = false;
|
|
struct sndstate *state = NULL;
|
|
struct sndstate *nextstate = NULL;
|
|
s16 numfree;
|
|
s16 numalloced;
|
|
struct sndstate *iterstate;
|
|
N_ALSndpEvent sp44;
|
|
ALMicroTime sp40;
|
|
|
|
do {
|
|
if (nextstate != NULL) {
|
|
sp84.common.state = (N_ALSoundState *)state;
|
|
sp84.common.type = event->common.type;
|
|
sp84.common.unk08 = event->common.unk08;
|
|
event = &sp84;
|
|
}
|
|
|
|
state = (struct sndstate *)event->common.state;
|
|
|
|
if (((uintptr_t) state & 0x80000000) == 0) {
|
|
// empty
|
|
}
|
|
|
|
sound = state->sound;
|
|
|
|
if (sound == NULL) {
|
|
sndpCountStates(&numfree, &numalloced);
|
|
return;
|
|
}
|
|
|
|
keymap = sound->keyMap;
|
|
nextstate = (struct sndstate *)state->node.next;
|
|
|
|
switch (event->common.type) {
|
|
case AL_SNDP_PLAY_EVT:
|
|
if (state->state != AL_STATE5 && state->state != AL_STATE4) {
|
|
return;
|
|
}
|
|
|
|
config.fxBus = state->fxbus;
|
|
config.priority = state->priority;
|
|
config.unityPitch = 0;
|
|
sp70 = var8005f130 >= g_SndPlayer->maxSounds;
|
|
|
|
if (!sp70 || (state->flags & SNDSTATEFLAG_10)) {
|
|
hasvoice = n_alSynAllocVoice(&state->voice, &config);
|
|
}
|
|
|
|
if (!hasvoice) {
|
|
if (state->flags & (SNDSTATEFLAG_02 | SNDSTATEFLAG_10) || state->unk34 > 0) {
|
|
state->state = AL_STATE4;
|
|
state->unk34--;
|
|
n_alEvtqPostEvent(&g_SndPlayer->evtq, &event->msg, 33333, 0);
|
|
} else if (sp70) {
|
|
iterstate = g_SndpAllocStatesTail;
|
|
|
|
do {
|
|
if ((iterstate->flags & (SNDSTATEFLAG_02 | SNDSTATEFLAG_10)) == 0
|
|
&& (iterstate->flags & SNDSTATEFLAG_04)
|
|
&& iterstate->state != AL_STATE3) {
|
|
sp70 = 0;
|
|
sp44.common.type = AL_SNDP_END_EVT;
|
|
sp44.common.state = (N_ALSoundState *)iterstate;
|
|
iterstate->state = AL_STATE3;
|
|
|
|
n_alEvtqPostEvent(&g_SndPlayer->evtq, &sp44.msg, 1000, 0);
|
|
n_alSynSetVol(&iterstate->voice, 0, 1000);
|
|
}
|
|
|
|
iterstate = (struct sndstate *)iterstate->node.prev;
|
|
} while (sp70 && iterstate);
|
|
|
|
if (sp70 == 0) {
|
|
state->unk34 = 2;
|
|
n_alEvtqPostEvent(&g_SndPlayer->evtq, &event->msg, 1001, 0);
|
|
} else {
|
|
func00033090(state);
|
|
}
|
|
} else {
|
|
func00033090(state);
|
|
}
|
|
return;
|
|
}
|
|
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
delta = sound->envelope->attackTime / state->pitch / state->basepitch;
|
|
|
|
if (state->flags & SNDSTATEFLAG_02) {
|
|
state->unk48 = 0;
|
|
} else {
|
|
sp40 = sound->envelope->decayTime / state->pitch / state->basepitch;
|
|
|
|
if (sp40 > 5500000) {
|
|
sp40 = 5500000;
|
|
}
|
|
|
|
state->unk48 = 1000000 + sp40 + g_SndPlayer->curTime;
|
|
|
|
if (state->unk48 < 0) {
|
|
state->unk48 = 0;
|
|
}
|
|
}
|
|
|
|
if (delta > 5500000) {
|
|
func00033090(state);
|
|
return;
|
|
}
|
|
|
|
state->flags |= SNDSTATEFLAG_04;
|
|
state->envvol = sound->envelope->attackVolume;
|
|
state->fxbus = config.fxBus;
|
|
state->endtime = g_SndPlayer->curTime + delta;
|
|
#else
|
|
// This is the same as above, but delta is calculated later
|
|
state->flags |= SNDSTATEFLAG_04;
|
|
state->envvol = sound->envelope->attackVolume;
|
|
state->fxbus = config.fxBus;
|
|
delta = sound->envelope->attackTime / state->pitch / state->basepitch;
|
|
state->endtime = g_SndPlayer->curTime + delta;
|
|
#endif
|
|
|
|
vol = MAX(0, (var8009c334[keymap->keyMin & 0x1f] * (state->envvol * state->vol * sound->sampleVolume / 0x3f01)) / 0x7fff - 1);
|
|
tmppan = state->pan + sound->samplePan - AL_PAN_CENTER;
|
|
pan = MIN(MAX(tmppan, 0), 127);
|
|
|
|
fxmix = (state->fxmix & 0x7f) + (keymap->keyMax & 0xf) * 8;
|
|
fxmix = MIN(127, MAX(0, fxmix));
|
|
fxmix |= state->fxmix & 0x80;
|
|
|
|
n_alSynStartVoiceParams(&state->voice, sound->wavetable, state->pitch * state->basepitch, vol, pan, fxmix, 0, 0, 0, delta);
|
|
state->state = AL_PLAYING;
|
|
var8005f130++;
|
|
|
|
if ((state->flags & SNDSTATEFLAG_02) == 0) {
|
|
if (delta == 0) {
|
|
state->envvol = sound->envelope->decayVolume;
|
|
|
|
vol = MAX(0, (var8009c334[keymap->keyMin & 0x1f] * (state->envvol * state->vol * sound->sampleVolume / 0x3f01)) / 0x7fff - 1);
|
|
|
|
delta = sound->envelope->decayTime / state->basepitch / state->pitch;
|
|
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
if (delta > 5500000) {
|
|
func00033090(state);
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
state->endtime = g_SndPlayer->curTime + delta;
|
|
|
|
n_alSynSetVol(&state->voice, vol, delta);
|
|
|
|
sp94.common.type = AL_SNDP_STOP_EVT;
|
|
sp94.common.state = (N_ALSoundState *)state;
|
|
|
|
n_alEvtqPostEvent(&g_SndPlayer->evtq, &sp94.msg, delta, 0);
|
|
|
|
if (state->flags & SNDSTATEFLAG_20) {
|
|
func00033100(state);
|
|
}
|
|
} else {
|
|
sp94.common.type = AL_SNDP_DECAY_EVT;
|
|
sp94.common.state = (N_ALSoundState *)state;
|
|
delta = sound->envelope->attackTime / state->pitch / state->basepitch;
|
|
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
if (delta > 5500000) {
|
|
func00033090(state);
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
n_alEvtqPostEvent(&g_SndPlayer->evtq, &sp94.msg, delta, 0);
|
|
}
|
|
}
|
|
break;
|
|
case AL_SNDP_STOP_EVT:
|
|
case AL_SNDP_0400_EVT:
|
|
case AL_SNDP_1000_EVT:
|
|
if (event->common.type != AL_SNDP_1000_EVT || (state->flags & SNDSTATEFLAG_02)) {
|
|
switch (state->state) {
|
|
case AL_PLAYING:
|
|
_removeEvents(&g_SndPlayer->evtq, (N_ALSoundState *)state, AL_SNDP_DECAY_EVT);
|
|
delta = sound->envelope->releaseTime / state->basepitch / state->pitch;
|
|
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
if (delta > 5500000) {
|
|
func00033090(state);
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
n_alSynSetVol(&state->voice, 0, delta);
|
|
|
|
if (delta) {
|
|
sp94.common.type = AL_SNDP_END_EVT;
|
|
sp94.common.state = (N_ALSoundState *)state;
|
|
n_alEvtqPostEvent(&g_SndPlayer->evtq, &sp94.msg, delta, 0);
|
|
state->state = AL_STOPPING;
|
|
} else {
|
|
func00033090(state);
|
|
}
|
|
break;
|
|
case AL_STATE4:
|
|
case AL_STATE5:
|
|
func00033090(state);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (event->common.type == AL_SNDP_STOP_EVT) {
|
|
event->common.type = AL_SNDP_1000_EVT;
|
|
}
|
|
}
|
|
break;
|
|
case AL_SNDP_PAN_EVT:
|
|
state->pan = event->common.unk08;
|
|
|
|
if (state->state == AL_PLAYING) {
|
|
tmppan = state->pan - AL_PAN_CENTER + sound->samplePan;
|
|
pan = MIN(MAX(tmppan, AL_PAN_LEFT), AL_PAN_RIGHT);
|
|
|
|
n_alSynSetPan(&state->voice, pan);
|
|
}
|
|
break;
|
|
case AL_SNDP_PITCH_EVT:
|
|
state->pitch = event->pitch.pitch;
|
|
|
|
if (state->state == AL_PLAYING) {
|
|
n_alSynSetPitch(&state->voice, state->pitch * state->basepitch);
|
|
|
|
if (state->flags & SNDSTATEFLAG_20) {
|
|
func00033100(state);
|
|
}
|
|
}
|
|
break;
|
|
case AL_SNDP_FX_EVT:
|
|
state->fxmix = event->common.unk08;
|
|
|
|
if (state->state == AL_PLAYING) {
|
|
fxmix = (state->fxmix & 0x7f) + (keymap->keyMax & 0xf) * 8;
|
|
fxmix = MIN(127, MAX(0, fxmix));
|
|
fxmix |= state->fxmix & 0x80;
|
|
|
|
n_alSynSetFXMix(&state->voice, fxmix);
|
|
}
|
|
break;
|
|
case AL_SNDP_4000_EVT:
|
|
state->fxmix = (u8)(state->fxmix & 0x7f) | (u8)(event->common.unk08 & 0x80);
|
|
|
|
if (state->state == AL_PLAYING) {
|
|
fxmix = (state->fxmix & 0x7f) + (keymap->keyMax & 0xf) * 8;
|
|
fxmix = MIN(127, MAX(0, fxmix));
|
|
fxmix |= state->fxmix & 0x80;
|
|
|
|
n_alSynSetFXMix(&state->voice, fxmix);
|
|
}
|
|
break;
|
|
case AL_SNDP_FXBUS_EVT:
|
|
state->fxbus = event->common.unk08;
|
|
|
|
if (state->fxbus >= n_syn->maxAuxBusses) {
|
|
state->fxbus = 0;
|
|
}
|
|
|
|
if (state->state == AL_PLAYING) {
|
|
state->voice.fxBus = state->fxbus;
|
|
}
|
|
break;
|
|
case AL_SNDP_VOL_EVT:
|
|
state->vol = event->common.unk08;
|
|
|
|
if (state->state == AL_PLAYING) {
|
|
vol = MAX(0, (var8009c334[keymap->keyMin & 0x1f] * (state->envvol * state->vol * sound->sampleVolume / 0x3f01)) / 0x7fff - 1);
|
|
|
|
n_alSynSetVol(&state->voice, vol, MAX(1000, state->endtime - g_SndPlayer->curTime));
|
|
}
|
|
break;
|
|
case AL_SNDP_0800_EVT:
|
|
if (state->state == AL_PLAYING) {
|
|
delta = sound->envelope->releaseTime / state->basepitch / state->pitch;
|
|
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
if (delta > 5500000) {
|
|
func00033090(state);
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
vol = MAX(0, var8009c334[keymap->keyMin & 0x1f] * (state->envvol * state->vol * sound->sampleVolume / 0x3f01) / 0x7fff - 1);
|
|
|
|
n_alSynSetVol(&state->voice, vol, delta);
|
|
}
|
|
break;
|
|
case AL_SNDP_DECAY_EVT:
|
|
if ((state->flags & SNDSTATEFLAG_02) == 0) {
|
|
state->envvol = sound->envelope->decayVolume;
|
|
vol = MAX(0, var8009c334[keymap->keyMin & 0x1f] * (state->envvol * state->vol * sound->sampleVolume / 0x3f01) / 0x7fff - 1);
|
|
delta = sound->envelope->decayTime / state->basepitch / state->pitch;
|
|
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
if (delta > 5500000) {
|
|
func00033090(state);
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
state->endtime = g_SndPlayer->curTime + delta;
|
|
|
|
n_alSynSetVol(&state->voice, vol, delta);
|
|
|
|
sp94.common.type = AL_SNDP_STOP_EVT;
|
|
sp94.common.state = (N_ALSoundState *)state;
|
|
|
|
n_alEvtqPostEvent(&g_SndPlayer->evtq, &sp94.msg, delta, 0);
|
|
|
|
if (state->flags & SNDSTATEFLAG_20) {
|
|
func00033100(state);
|
|
}
|
|
}
|
|
break;
|
|
case AL_SNDP_END_EVT:
|
|
func00033090(state);
|
|
break;
|
|
case AL_SNDP_0200_EVT:
|
|
if (state->flags & SNDSTATEFLAG_10) {
|
|
func00033820(event->msg.msg.generic.data2, event->msg.msg.generic.data, state->vol, state->pan,
|
|
state->pitch, state->fxmix, state->fxbus, state->unk30);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
isspecial = event->common.type & (AL_SNDP_PLAY_EVT
|
|
| AL_SNDP_PITCH_EVT
|
|
| AL_SNDP_DECAY_EVT
|
|
| AL_SNDP_END_EVT
|
|
| AL_SNDP_0200_EVT);
|
|
|
|
if ((state = nextstate) && !isspecial) {
|
|
done = state->flags & SNDSTATEFLAG_01;
|
|
}
|
|
} while (!done && state && !isspecial);
|
|
}
|
|
|
|
void func00033090(struct sndstate *state)
|
|
{
|
|
if (state->flags & SNDSTATEFLAG_04) {
|
|
n_alSynStopVoice(&state->voice);
|
|
n_alSynFreeVoice(&state->voice);
|
|
}
|
|
|
|
sndpFreeState(state);
|
|
|
|
// @todo: Remove cast
|
|
_removeEvents(&g_SndPlayer->evtq, (N_ALSoundState *)state, 0xffff);
|
|
}
|
|
|
|
void func00033100(struct sndstate *state)
|
|
{
|
|
N_ALSndpEvent evt;
|
|
f32 pitch = alCents2Ratio(state->sound->keyMap->detune) * state->pitch;
|
|
|
|
evt.common.type = AL_SNDP_PITCH_EVT;
|
|
evt.common.state = (N_ALSoundState *)state;
|
|
evt.common.unk08 = *(u32 *)&pitch;
|
|
|
|
n_alEvtqPostEvent(&g_SndPlayer->evtq, &evt.msg, 33333, 0);
|
|
}
|
|
|
|
void _removeEvents(ALEventQueue *evtq, N_ALSoundState *state, u16 typemask)
|
|
{
|
|
ALLink *thisNode;
|
|
ALLink *nextNode;
|
|
N_ALEventListItem *thisItem;
|
|
N_ALEventListItem *nextItem;
|
|
N_ALSndpEvent *thisEvent;
|
|
OSIntMask mask;
|
|
|
|
mask = osSetIntMask(OS_IM_NONE);
|
|
|
|
thisNode = evtq->allocList.next;
|
|
|
|
while (thisNode != 0) {
|
|
nextNode = thisNode->next;
|
|
thisItem = (N_ALEventListItem *)thisNode;
|
|
nextItem = (N_ALEventListItem *)nextNode;
|
|
thisEvent = (N_ALSndpEvent *) &thisItem->evt;
|
|
|
|
if (thisEvent->common.state == state && thisEvent->common.type & typemask) {
|
|
if (nextItem) {
|
|
nextItem->delta += thisItem->delta;
|
|
}
|
|
|
|
alUnlink(thisNode);
|
|
alLink(thisNode, &evtq->freeList);
|
|
}
|
|
|
|
thisNode = nextNode;
|
|
}
|
|
|
|
osSetIntMask(mask);
|
|
}
|
|
|
|
u16 sndpCountStates(s16 *numfreeptr, s16 *numallocedptr)
|
|
{
|
|
OSIntMask mask = osSetIntMask(1);
|
|
u16 numalloced;
|
|
u16 numfree;
|
|
u16 numalloced2;
|
|
struct sndstate *state1 = g_SndpAllocStatesHead;
|
|
struct sndstate *state2 = g_SndpFreeStatesHead;
|
|
struct sndstate *state3 = g_SndpAllocStatesTail;
|
|
|
|
for (numalloced = 0; state1; numalloced++, state1 = (struct sndstate *)state1->node.next);
|
|
for (numfree = 0; state2; numfree++, state2 = (struct sndstate *)state2->node.next);
|
|
for (numalloced2 = 0; state3; numalloced2++, state3 = (struct sndstate *)state3->node.prev);
|
|
|
|
*numfreeptr = numfree;
|
|
*numallocedptr = numalloced;
|
|
|
|
osSetIntMask(mask);
|
|
|
|
return numalloced2;
|
|
}
|
|
|
|
void sndpSetAddRefCallback(void *fn)
|
|
{
|
|
g_SndpAddRefCallback = fn;
|
|
}
|
|
|
|
struct sndstate *func00033390(s32 arg0, ALSound *sound)
|
|
{
|
|
struct sndstate *state;
|
|
ALKeyMap *keymap;
|
|
OSIntMask mask;
|
|
s32 sp18;
|
|
|
|
keymap = sound->keyMap;
|
|
|
|
if (++var8005f134 > var8005f138) {
|
|
var8005f138 = var8005f134;
|
|
|
|
if (var8005f134 > 16) {
|
|
// empty
|
|
}
|
|
}
|
|
|
|
mask = osSetIntMask(1);
|
|
state = g_SndpFreeStatesHead;
|
|
|
|
if (state != NULL) {
|
|
g_SndpFreeStatesHead = (struct sndstate *)state->node.next;
|
|
|
|
alUnlink(&state->node);
|
|
|
|
if (g_SndpAllocStatesHead) {
|
|
state->node.next = &g_SndpAllocStatesHead->node;
|
|
state->node.prev = NULL;
|
|
g_SndpAllocStatesHead->node.prev = &state->node;
|
|
g_SndpAllocStatesHead = state;
|
|
} else {
|
|
state->node.next = state->node.prev = NULL;
|
|
g_SndpAllocStatesHead = state;
|
|
g_SndpAllocStatesTail = state;
|
|
}
|
|
|
|
osSetIntMask(mask);
|
|
|
|
sp18 = sound->envelope->decayTime + 1 == 0;
|
|
|
|
state->sound = sound;
|
|
state->priority = sp18 + 64;
|
|
state->state = AL_STATE5;
|
|
state->pitch = 1;
|
|
state->unk34 = 2;
|
|
state->flags = keymap->keyMax & 0xf0;
|
|
state->unk30 = NULL;
|
|
|
|
if (state->flags & SNDSTATEFLAG_20) {
|
|
state->basepitch = alCents2Ratio(keymap->keyBase * 100 - 6000);
|
|
} else {
|
|
state->basepitch = alCents2Ratio(keymap->keyBase * 100 + keymap->detune - 6000);
|
|
}
|
|
|
|
if (sp18) {
|
|
state->flags |= SNDSTATEFLAG_02;
|
|
}
|
|
|
|
state->fxmix = 0;
|
|
state->pan = AL_PAN_CENTER;
|
|
state->vol = 0x7fff;
|
|
|
|
if (g_SndpAddRefCallback != NULL) {
|
|
g_SndpAddRefCallback(state->sound);
|
|
}
|
|
} else {
|
|
osSetIntMask(mask);
|
|
}
|
|
|
|
return state;
|
|
}
|
|
|
|
void sndpSetRemoveRefCallback(void *fn)
|
|
{
|
|
g_SndpRemoveRefCallback = fn;
|
|
}
|
|
|
|
void sndpFreeState(struct sndstate *state)
|
|
{
|
|
var8005f134--;
|
|
|
|
if (g_SndpAllocStatesHead == state) {
|
|
g_SndpAllocStatesHead = (struct sndstate *)state->node.next;
|
|
}
|
|
|
|
if (g_SndpAllocStatesTail == state) {
|
|
g_SndpAllocStatesTail = (struct sndstate *)state->node.prev;
|
|
}
|
|
|
|
alUnlink(&state->node);
|
|
|
|
if (g_SndpFreeStatesHead) {
|
|
state->node.next = &g_SndpFreeStatesHead->node;
|
|
state->node.prev = NULL;
|
|
g_SndpFreeStatesHead->node.prev = &state->node;
|
|
g_SndpFreeStatesHead = state;
|
|
} else {
|
|
state->node.next = state->node.prev = NULL;
|
|
g_SndpFreeStatesHead = state;
|
|
}
|
|
|
|
if (state->flags & SNDSTATEFLAG_04) {
|
|
var8005f130--;
|
|
}
|
|
|
|
state->state = AL_STOPPED;
|
|
|
|
if (state->unk30) {
|
|
if (*state->unk30 == state) {
|
|
*state->unk30 = 0;
|
|
}
|
|
|
|
state->unk30 = NULL;
|
|
}
|
|
|
|
if (g_SndpRemoveRefCallback != NULL) {
|
|
g_SndpRemoveRefCallback(state->sound);
|
|
}
|
|
}
|
|
|
|
void sndSetPriority(struct sndstate *state, u8 priority)
|
|
{
|
|
if (state) {
|
|
state->priority = (s16)priority;
|
|
}
|
|
}
|
|
|
|
s32 sndGetState(struct sndstate *state)
|
|
{
|
|
if (state) {
|
|
return state->state;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
struct sndstate *func00033820(s32 arg0, s16 soundnum, u16 vol, ALPan pan, f32 pitch, u8 fxmix, u8 fxbus, struct sndstate **handleptr)
|
|
{
|
|
struct sndstate *state;
|
|
struct sndstate *state2 = NULL;
|
|
ALKeyMap *keymap;
|
|
ALSound *sound;
|
|
s16 sp4e = 0;
|
|
s32 sp48;
|
|
s32 sp44;
|
|
s32 sp40 = 0;
|
|
s32 abspan;
|
|
N_ALEvent evt;
|
|
N_ALEvent evt2;
|
|
|
|
if (sndIsDisabled()) {
|
|
return NULL;
|
|
}
|
|
|
|
if (soundnum != 0) {
|
|
do {
|
|
sound = sndLoadSound(soundnum);
|
|
state = func00033390(arg0, sound);
|
|
|
|
if (state != NULL) {
|
|
g_SndPlayer->target = state;
|
|
evt.type = AL_SNDP_PLAY_EVT;
|
|
evt.msg.generic.sndstate = state;
|
|
abspan = pan + state->pan - AL_PAN_CENTER;
|
|
|
|
if (abspan > 127) {
|
|
abspan = 127;
|
|
} else if (abspan < 0) {
|
|
abspan = 0;
|
|
}
|
|
|
|
state->pan = abspan;
|
|
state->vol = (u32)(vol * state->vol) >> 15;
|
|
state->pitch *= pitch;
|
|
state->fxmix = fxmix;
|
|
state->fxbus = fxbus;
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
state->soundnum = soundnum;
|
|
state->unk48 = 0;
|
|
#endif
|
|
|
|
sp44 = sound->keyMap->velocityMax * 33333;
|
|
|
|
if (state->flags & SNDSTATEFLAG_10) {
|
|
state->flags &= ~SNDSTATEFLAG_10;
|
|
n_alEvtqPostEvent(&g_SndPlayer->evtq, &evt, sp40 + 1, 0);
|
|
sp48 = sp44 + 1;
|
|
sp4e = soundnum;
|
|
} else {
|
|
n_alEvtqPostEvent(&g_SndPlayer->evtq, &evt, sp44 + 1, 0);
|
|
}
|
|
|
|
state2 = state;
|
|
}
|
|
|
|
sp40 += sp44;
|
|
keymap = sound->keyMap;
|
|
soundnum = keymap->velocityMin + (keymap->keyMin & 0xc0) * 4;
|
|
} while (soundnum && state);
|
|
|
|
if (state2 != NULL) {
|
|
state2->flags |= SNDSTATEFLAG_01;
|
|
state2->unk30 = handleptr;
|
|
|
|
if (sp4e != 0) {
|
|
state2->flags |= SNDSTATEFLAG_10;
|
|
|
|
evt2.type = AL_SNDP_0200_EVT;
|
|
evt2.msg.generic.sndstate = state2;
|
|
evt2.msg.generic.data = sp4e;
|
|
evt2.msg.generic.data2 = arg0;
|
|
|
|
n_alEvtqPostEvent(&g_SndPlayer->evtq, &evt2, sp48, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (handleptr != NULL) {
|
|
*handleptr = state2;
|
|
}
|
|
|
|
return state2;
|
|
}
|
|
|
|
void audioStop(struct sndstate *state)
|
|
{
|
|
N_ALEvent evt;
|
|
|
|
#if VERSION >= VERSION_NTSC_FINAL
|
|
if (state && (state->flags & SNDSTATEFLAG_02)) {
|
|
func00033bc0(state);
|
|
} else {
|
|
evt.type = AL_SNDP_0400_EVT;
|
|
evt.msg.generic.sndstate = state;
|
|
|
|
if (state != NULL) {
|
|
evt.msg.generic.sndstate->flags &= ~SNDSTATEFLAG_10;
|
|
|
|
n_alEvtqPostEvent(&g_SndPlayer->evtq, &evt, 0, 0);
|
|
}
|
|
}
|
|
#elif VERSION >= VERSION_NTSC_1_0
|
|
// NTSC 1.0 lacks the null state check
|
|
if (state->flags & SNDSTATEFLAG_02) {
|
|
func00033bc0(state);
|
|
} else {
|
|
evt.type = AL_SNDP_0400_EVT;
|
|
evt.msg.generic.sndstate = state;
|
|
|
|
if (state != NULL) {
|
|
evt.msg.generic.sndstate->flags &= ~SNDSTATEFLAG_10;
|
|
|
|
n_alEvtqPostEvent(&g_SndPlayer->evtq, &evt, 0, 0);
|
|
}
|
|
}
|
|
#else
|
|
evt.type = AL_SNDP_0400_EVT;
|
|
evt.msg.generic.sndstate = state;
|
|
|
|
if (state != NULL) {
|
|
evt.msg.generic.sndstate->flags &= ~SNDSTATEFLAG_10;
|
|
|
|
n_alEvtqPostEvent(&g_SndPlayer->evtq, &evt, 0, 0);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
void func00033bc0(struct sndstate *state)
|
|
{
|
|
N_ALEvent evt;
|
|
|
|
evt.type = AL_SNDP_END_EVT;
|
|
evt.msg.generic.sndstate = state;
|
|
|
|
if (state) {
|
|
evt.msg.generic.sndstate->flags &= ~SNDSTATEFLAG_10;
|
|
|
|
n_alEvtqPostEvent(&g_SndPlayer->evtq, &evt, 0, 0);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void func00033c30(u8 flags)
|
|
{
|
|
OSIntMask mask = osSetIntMask(1);
|
|
N_ALEvent evt;
|
|
struct sndstate *state = g_SndpAllocStatesHead;
|
|
|
|
while (state) {
|
|
evt.type = AL_SNDP_0400_EVT;
|
|
evt.msg.generic.sndstate = state;
|
|
|
|
if ((state->flags & flags) == flags) {
|
|
evt.msg.generic.sndstate->flags &= ~SNDSTATEFLAG_10;
|
|
n_alEvtqPostEvent(&g_SndPlayer->evtq, &evt, 0, 0);
|
|
}
|
|
|
|
state = (struct sndstate *)state->node.next;
|
|
}
|
|
|
|
osSetIntMask(mask);
|
|
}
|
|
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
void func00033cf0(u8 flags)
|
|
{
|
|
OSIntMask mask = osSetIntMask(1);
|
|
N_ALEvent evt;
|
|
struct sndstate *state = g_SndpAllocStatesHead;
|
|
|
|
while (state) {
|
|
evt.type = AL_SNDP_END_EVT;
|
|
evt.msg.generic.sndstate = state;
|
|
|
|
if ((state->flags & flags) == flags) {
|
|
evt.msg.generic.sndstate->flags &= ~SNDSTATEFLAG_10;
|
|
n_alEvtqPostEvent(&g_SndPlayer->evtq, &evt, 0, 0);
|
|
}
|
|
|
|
state = (struct sndstate *)state->node.next;
|
|
}
|
|
|
|
osSetIntMask(mask);
|
|
}
|
|
#endif
|
|
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
void func00033db0(void)
|
|
{
|
|
func00033cf0(SNDSTATEFLAG_01);
|
|
}
|
|
#endif
|
|
|
|
void func00033dd8(void)
|
|
{
|
|
func00033c30(SNDSTATEFLAG_01);
|
|
}
|
|
|
|
void func00033e00(void)
|
|
{
|
|
func00033c30(SNDSTATEFLAG_01 | SNDSTATEFLAG_10);
|
|
}
|
|
|
|
void func00033e28(void)
|
|
{
|
|
func00033c30(SNDSTATEFLAG_01 | SNDSTATEFLAG_02);
|
|
}
|
|
|
|
void audioPostEvent(struct sndstate *state, s16 type, s32 data)
|
|
{
|
|
N_ALEvent evt;
|
|
|
|
evt.type = type;
|
|
evt.msg.generic.sndstate = state;
|
|
evt.msg.generic.data = data;
|
|
|
|
if (state) {
|
|
n_alEvtqPostEvent(&g_SndPlayer->evtq, &evt, 0, 0);
|
|
} else {
|
|
// empty
|
|
}
|
|
}
|
|
|
|
u16 func00033ec4(u8 index)
|
|
{
|
|
return var8009c334 ? var8009c334[index] : 0;
|
|
}
|
|
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
struct sndstate *sndpGetHeadState(void)
|
|
{
|
|
return g_SndpAllocStatesHead;
|
|
}
|
|
#endif
|
|
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
ALMicroTime sndpGetCurTime(void)
|
|
{
|
|
return g_SndPlayer->curTime;
|
|
}
|
|
#endif
|
|
|
|
void func00033f44(u8 index, u16 volume)
|
|
{
|
|
if (var8009c334) {
|
|
OSIntMask mask = osSetIntMask(1);
|
|
struct sndstate *state = g_SndpAllocStatesHead;
|
|
s32 i;
|
|
N_ALEvent evt;
|
|
|
|
var8009c334[index] = volume;
|
|
|
|
for (i = 0; state != NULL; i++, state = (struct sndstate *)state->node.next) {
|
|
if ((state->sound->keyMap->keyMin & 0x1f) == index) {
|
|
evt.type = AL_SNDP_0800_EVT;
|
|
evt.msg.generic.sndstate = state;
|
|
n_alEvtqPostEvent(&g_SndPlayer->evtq, &evt, 0, 0);
|
|
}
|
|
}
|
|
|
|
osSetIntMask(mask);
|
|
}
|
|
}
|