summaryrefslogtreecommitdiff
path: root/arm7/lib/src/SND_util.c
blob: 6a939c0221621cf9868a02247f639cb2c1dea3ba (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
#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) {
        // what ???
        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);
}