blob: 5c0b220bbc3cd20d68227bab9ed9add2b3875a08 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
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);
}
|