diff options
Diffstat (limited to 'arm7/lib/src/SND_util.c')
-rw-r--r-- | arm7/lib/src/SND_util.c | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/arm7/lib/src/SND_util.c b/arm7/lib/src/SND_util.c new file mode 100644 index 00000000..5c0b220b --- /dev/null +++ b/arm7/lib/src/SND_util.c @@ -0,0 +1,109 @@ +#include "SND_util.h" + +#include "syscall.h" + +// TODO remove this extern once the static const definition of it is here +extern s8 sLfoSinTable[0x21]; + +u16 SND_CalcTimer(int timer, int pitch) +{ + int octave = 0; + int pitch_normalized = -pitch; + + while (pitch_normalized < 0) + { + octave--; + pitch_normalized += 768; + } + + while (pitch_normalized >= 768) + { + octave++; + pitch_normalized -= 768; + } + + u64 result = SVC_GetPitchTable(pitch_normalized); + + result += 0x10000; + result *= timer; + + int shift = octave - 16; + + if (shift <= 0) + { + shift = -shift; + result >>= shift; + } + else if (shift < 32) + { + // clamp in case timer value overflows + u64 tmp = result & ~0uLL << (32 - shift); + if (tmp != 0) + return 0xFFFF; + result <<= shift; + } + else + { + return 0xFFFF; + } + + if (result < 0x10) + result = 0x10; + else if (result > 0xFFFF) + result = 0xFFFF; + + return (u16)result; +} + +u16 SND_CalcChannelVolume(int value) +{ + if (value < SND_VOL_DB_MIN) + value = SND_VOL_DB_MIN; + else if (value > 0) + value = 0; + + int result = SVC_GetVolumeTable(value + (-SND_VOL_DB_MIN)); + int div; + + if (value < -240) + div = 3; + else if (value < -120) + div = 2; + else if (value < -60) + div = 1; + else + div = 0; + + return (u16)(result | (div << 8)); +} + +s8 SND_SinIdx(int x) +{ + // BUG: UB for out of range values + + if (x < 0x20) + { + return sLfoSinTable[x]; + } + else if (x < 0x40) + { + return sLfoSinTable[0x40 - x]; + } + else if (x < 0x60) + { + return (s8)(-sLfoSinTable[x - 0x40]); + } + else + { + return (s8)(-sLfoSinTable[0x20 - (x - 0x60)]); + } +} + +u16 SND_CalcRandom(void) +{ + static u32 state = 0x12345678; + + // values from "Numerical Recipes" + state = state * 1664525u + 1013904223u; + return (u16)(state >> 16u); +} |