394 lines
6.8 KiB
C
394 lines
6.8 KiB
C
#include <ultra64.h>
|
|
#include "constants.h"
|
|
#include "types.h"
|
|
|
|
struct typea {
|
|
u8 unk28;
|
|
u8 unk29;
|
|
};
|
|
|
|
struct typeb {
|
|
f32 unk28;
|
|
};
|
|
|
|
typedef struct oscData_s {
|
|
struct oscData_s *next;
|
|
u8 type;
|
|
u8 stateFlags;
|
|
u16 maxCount;
|
|
s32 curCount;
|
|
f32 unk0c;
|
|
f32 unk10;
|
|
u16 unk14;
|
|
u16 unk16;
|
|
f32 unk18;
|
|
f32 unk1c;
|
|
u16 unk20;
|
|
u16 unk22;
|
|
u16 unk24;
|
|
u16 unk26;
|
|
union {
|
|
struct typea a;
|
|
struct typeb b;
|
|
} data;
|
|
} oscData;
|
|
|
|
oscData *freeOscStateList;
|
|
u32 var8009b874;
|
|
oscData oscStates[60];
|
|
u32 var8009c2c8;
|
|
u32 var8009c2cc;
|
|
N_ALSndPlayer var8009c2d0;
|
|
|
|
ALMicroTime updateOsc(void *oscState, f32 *updateVal);
|
|
ALMicroTime updateOscMain(oscData *statePtr, f32 *updateVal);
|
|
void func00030bd8(void *oscState);
|
|
ALMicroTime initOscMain(void **oscState, f32 *initVal, u8 oscType, u8 arg3, u8 oscDepth, u8 arg5, u8 arg6);
|
|
|
|
f32 _depth2Cents(u8 depth)
|
|
{
|
|
f32 x = 1.0309929847717f;
|
|
f32 cents = 1.0f;
|
|
|
|
while (depth) {
|
|
if (depth & 1) {
|
|
cents *= x;
|
|
}
|
|
|
|
x *= x;
|
|
depth >>= 1;
|
|
}
|
|
|
|
return cents;
|
|
}
|
|
|
|
ALMicroTime initOsc(void **oscState, f32 *initVal, u8 oscType, u8 oscRate, u8 oscDepth, u8 oscDelay, u8 arg6)
|
|
{
|
|
oscData *state;
|
|
ALMicroTime result = 0;
|
|
|
|
if (oscDelay == 0) {
|
|
return 0;
|
|
}
|
|
|
|
if (oscType != 1 && oscType != 0x80) {
|
|
return initOscMain(oscState, initVal, oscType, oscRate, oscDepth, oscDelay, arg6);
|
|
}
|
|
|
|
if (freeOscStateList != NULL) {
|
|
state = freeOscStateList;
|
|
freeOscStateList = freeOscStateList->next;
|
|
state->type = oscType;
|
|
*oscState = state;
|
|
result = oscDelay << 14;
|
|
|
|
switch (oscType) {
|
|
case 1:
|
|
state->unk24 = 0;
|
|
state->unk22 = 259 - oscRate;
|
|
state->data.a.unk28 = oscDepth >> 1;
|
|
state->data.a.unk29 = 127 - state->data.a.unk28;
|
|
*initVal = state->data.a.unk29;
|
|
break;
|
|
case 0x80:
|
|
state->data.b.unk28 = _depth2Cents(oscDepth);
|
|
state->unk24 = 0;
|
|
state->unk22 = 259 - oscRate;
|
|
*initVal = 1.0f;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
ALMicroTime updateOsc(void *oscState, f32 *updateVal)
|
|
{
|
|
f32 sp2c;
|
|
oscData *state = oscState;
|
|
ALMicroTime result = AL_USEC_PER_FRAME;
|
|
|
|
if (state->type != 1 && state->type != 0x80) {
|
|
return updateOscMain(oscState, updateVal);
|
|
}
|
|
|
|
switch (state->type) {
|
|
case 0x01:
|
|
state->unk24++;
|
|
|
|
if (state->unk24 >= state->unk22) {
|
|
state->unk24 = 0;
|
|
}
|
|
|
|
sp2c = (f32)state->unk24 / (f32)state->unk22;
|
|
sp2c = sinf(sp2c * M_TAU);
|
|
sp2c = sp2c * state->data.a.unk28;
|
|
*updateVal = state->data.a.unk29 + sp2c;
|
|
break;
|
|
case 0x80:
|
|
state->unk24++;
|
|
|
|
if (state->unk24 >= state->unk22) {
|
|
state->unk24 = 0;
|
|
}
|
|
|
|
sp2c = (f32)state->unk24 / (f32)state->unk22;
|
|
sp2c = sinf(sp2c * M_TAU) * state->data.b.unk28;
|
|
*updateVal = alCents2Ratio(sp2c);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void stopOsc(void *oscState)
|
|
{
|
|
oscData *state = (oscData *)oscState;
|
|
|
|
if (state->type != 1 && state->type != 0x80) {
|
|
func00030bd8(oscState);
|
|
}
|
|
|
|
((oscData*)oscState)->next = freeOscStateList;
|
|
freeOscStateList = (oscData*)oscState;
|
|
}
|
|
|
|
f32 func000301a4(f32 value)
|
|
{
|
|
// Almost value / (32768 / M_PI), but has a precision mismatch
|
|
return sinf(value / 10430.379882812f);
|
|
}
|
|
|
|
extern s32 var8005f150[];
|
|
extern f32 var8005f34c[100];
|
|
|
|
ALMicroTime initOscMain(void **oscState, f32 *initVal, u8 oscType, u8 arg3, u8 oscDepth, u8 arg5, u8 arg6)
|
|
{
|
|
oscData *state;
|
|
f32 oscDepthf;
|
|
|
|
if (arg3 > 99) {
|
|
arg3 = 99;
|
|
}
|
|
|
|
if (arg5 > 127) {
|
|
arg5 = 127;
|
|
}
|
|
|
|
if (arg6 > 127) {
|
|
arg6 = 127;
|
|
}
|
|
|
|
if (freeOscStateList == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
state = freeOscStateList;
|
|
|
|
if (arg6 == 0) {
|
|
state->unk18 = 1;
|
|
state->unk1c = 0;
|
|
} else {
|
|
state->unk18 = 0;
|
|
state->unk1c = 1.0f / ((f32)var8005f150[arg6] / AL_USEC_PER_FRAME);
|
|
}
|
|
|
|
state->type = oscType;
|
|
state->unk14 = 0;
|
|
state->unk16 = 1000000.0f / (f32)var8005f34c[arg3] / AL_USEC_PER_FRAME;
|
|
state->curCount = AL_USEC_PER_FRAME;
|
|
|
|
oscDepthf = oscDepth;
|
|
|
|
if (oscType & 0x80) {
|
|
oscDepthf = _depth2Cents(oscDepthf);
|
|
}
|
|
|
|
oscType &= ~0x80;
|
|
|
|
switch (oscType & ~0x80) {
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
case 5:
|
|
state->unk0c = oscDepthf;
|
|
|
|
if (oscType == 2) {
|
|
state->unk10 = -oscDepthf;
|
|
} else {
|
|
state->unk10 = 0;
|
|
}
|
|
|
|
state->curCount = 500000.0f / (f32)var8005f34c[arg3];
|
|
break;
|
|
case 6:
|
|
case 8:
|
|
case 11:
|
|
case 12:
|
|
state->unk10 = 0;
|
|
state->unk0c = oscDepthf;
|
|
break;
|
|
case 7:
|
|
case 9:
|
|
case 13:
|
|
state->unk10 = oscDepthf / 2.0f;
|
|
state->unk0c = oscDepthf / 2.0f;
|
|
break;
|
|
case 10:
|
|
state->unk10 = -oscDepthf;
|
|
state->unk0c = oscDepthf * 2.0f;
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
|
|
if (state->type & 0x80) {
|
|
*initVal = alCents2Ratio(state->unk10);
|
|
} else {
|
|
*initVal = state->unk10 + 127.0f;
|
|
}
|
|
|
|
*oscState = state;
|
|
|
|
freeOscStateList = freeOscStateList->next;
|
|
|
|
if (arg5) {
|
|
return var8005f150[arg5];
|
|
}
|
|
|
|
return AL_USEC_PER_FRAME;
|
|
}
|
|
|
|
ALMicroTime updateOscMain(oscData *statePtr, f32 *updateVal)
|
|
{
|
|
f32 sp24;
|
|
f32 sp20;
|
|
f32 sp1c;
|
|
|
|
if ((statePtr->type & ~0x80) >= 6) {
|
|
statePtr->unk14++;
|
|
|
|
if (statePtr->unk14 >= statePtr->unk16) {
|
|
statePtr->unk14 = 0;
|
|
}
|
|
|
|
sp20 = (f32)statePtr->unk14 / (f32)statePtr->unk16;
|
|
}
|
|
|
|
if (statePtr->unk1c != 0.0f) {
|
|
statePtr->unk18 += statePtr->unk1c;
|
|
|
|
if (statePtr->unk18 >= 1.0f) {
|
|
statePtr->unk18 = 1.0f;
|
|
statePtr->unk1c = 0.0f;
|
|
}
|
|
}
|
|
|
|
sp24 = statePtr->unk0c;
|
|
|
|
if (statePtr->unk18 != 1.0f) {
|
|
sp24 *= statePtr->unk18;
|
|
}
|
|
|
|
switch (statePtr->type & ~0x80) {
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
case 5:
|
|
if (statePtr->unk14) {
|
|
sp20 = sp24;
|
|
} else {
|
|
sp20 = statePtr->unk10;
|
|
}
|
|
statePtr->unk14 ^= 1;
|
|
break;
|
|
case 6:
|
|
case 7:
|
|
if (sp20 < 0.25f) {
|
|
sp20 *= 4.0f * sp24;
|
|
} else if (sp20 >= 0.75f) {
|
|
sp20 -= 0.75f;
|
|
sp20 *= 4.0f * sp24;
|
|
sp20 -= sp24;
|
|
} else {
|
|
sp20 -= 0.25f;
|
|
sp20 *= 4.0f * sp24;
|
|
sp20 = sp24 - sp20;
|
|
}
|
|
sp20 += statePtr->unk10;
|
|
break;
|
|
case 8:
|
|
case 9:
|
|
sp20 = func000301a4(sp20 * 65536.0f) * sp24 + statePtr->unk10;
|
|
break;
|
|
case 10:
|
|
case 11:
|
|
sp20 *= sp24;
|
|
sp20 += statePtr->unk10;
|
|
break;
|
|
case 12:
|
|
case 13:
|
|
if (sp20 < 0.25f) {
|
|
sp20 *= 4.0f * sp24;
|
|
} else if (sp20 >= 0.75f) {
|
|
sp20 -= 0.75f;
|
|
sp20 *= 4.0f * sp24;
|
|
sp20 -= sp24;
|
|
} else {
|
|
sp20 -= 0.25f;
|
|
sp20 *= 4.0f * sp24;
|
|
sp20 = sp24 - sp20;
|
|
}
|
|
|
|
sp1c = statePtr->unk10 + sp20;
|
|
sp20 = (f32)statePtr->unk14 / (f32)statePtr->unk16;
|
|
sp20 = func000301a4(sp20 * 65536.0f) * sp24 + statePtr->unk10;
|
|
sp20 += sp1c;
|
|
sp20 /= 2.0f;
|
|
break;
|
|
}
|
|
|
|
if (statePtr->type & 0x80) {
|
|
*updateVal = alCents2Ratio(sp20);
|
|
} else {
|
|
*updateVal = sp20 + 127;
|
|
}
|
|
|
|
return statePtr->curCount;
|
|
}
|
|
|
|
void func00030bd8(void *oscState)
|
|
{
|
|
((oscData*)oscState)->next = freeOscStateList;
|
|
freeOscStateList = (oscData*)oscState;
|
|
}
|
|
|
|
void func00030bfc(s32 arg0, s32 count)
|
|
{
|
|
oscData *item;
|
|
s32 i;
|
|
|
|
freeOscStateList = &oscStates[0];
|
|
item = &oscStates[0];
|
|
|
|
for (i = 0; i < count - 1; i++) {
|
|
item->next = &oscStates[i + 1];
|
|
item = item->next;
|
|
}
|
|
|
|
item->next = NULL;
|
|
}
|
|
|
|
void func00030c98(ALSeqpConfig *config)
|
|
{
|
|
config->initOsc = initOsc;
|
|
config->updateOsc = updateOsc;
|
|
config->stopOsc = stopOsc;
|
|
|
|
return;
|
|
}
|