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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
|
#ifndef D_SND_BGM_HARP_DATA_H
#define D_SND_BGM_HARP_DATA_H
#include "common.h"
#include "d/snd/d_snd_rng_mgr.h"
/**
* This file deals with the pitch of the Goddess' Harp when Link
* is freely strumming. In this case the pitch of the strings
* is adjusted to match the key of background music through sequence variables.
* When Link strums the harp, 12 strings can be heard, but it's actually only four
* notes of the same chord spanning three octaves.
*
* I haven't yet investigated all the data, but a typical chord Link might play
* is Cmaj^7, consisting of C-E-G-B. Link actually plays:
* G3-C4-E4-G4-B4-C5-E5-G5-B5-C6-E6-G6
* B3 is missing, possibly to prevent dissonance at the ends of the scale.
* (Sealed Grounds, before Demise fight, no actual BGM)
*
* TODO: This deals with slightly more than the harp. It additionally
* also deals with the combat hit sounds that also seem to match up in
* pitch with the BGM.
*/
/**
* Contains a single Seq sound var controlling the pitch of a subset of harp strings
* Size: 0x02
*/
struct dSndBgmDataHarpVar_c {
dSndBgmDataHarpVar_c() : field_0x00(0), field_0x01(0) {}
void reset() {
field_0x00 = 0;
field_0x01 = 0;
}
void onFlag() {
field_0x00 |= 1;
}
bool checkFlag() const {
return field_0x00 & 1;
}
/* 0x00 */ u8 field_0x00; // flags
/* 0x01 */ s8 field_0x01; // var
};
/**
* Contains Seq sound vars for all harp strings, represents a "key" in the bgm music
* Size: 0x0C
*/
class dSndBgmDataHarpVarSetBase_c {
public:
dSndBgmDataHarpVarSetBase_c(s32 count);
~dSndBgmDataHarpVarSetBase_c();
void resetVars();
void addVar(u8 value);
s32 getPosition() const {
return mPosition;
}
void setPosition(s32 position) {
mPosition = position;
}
s32 getCount() {
return mCount;
}
s32 getMax() const {
return mMax;
}
s32 getNumBitsSet() {
s32 numBits = 0;
for (int i = 0; i < getCount(); i++) {
if (mpVars[i].checkFlag()) {
numBits++;
}
}
return numBits;
}
dSndBgmDataHarpVar_c *getVar(s32 idx) {
if (idx >= getCount()) {
return nullptr;
}
return &mpVars[idx];
}
s32 getRandomIdx() {
return dSndRngMgr_c::GetInstance()->rndIntRange(0, getCount());
}
s32 getRandomIdxWithBitSet() {
s32 numBitsSet = getNumBitsSet();
s32 idx;
if (numBitsSet <= 0) {
return 0;
} else {
idx = dSndRngMgr_c::GetInstance()->rndIntRange(0, getCount());
while (true) {
if (mpVars[idx].checkFlag()) {
return idx;
}
idx = dSndRngMgr_c::GetInstance()->rndIntRange(0, getCount());
}
}
}
s32 getVal(s32 idx) {
if (idx >= getCount()) {
return 0;
}
return mpVars[idx].field_0x01;
}
dSndBgmDataHarpVar_c *getUnusedVar() {
if (mCount >= mMax) {
return nullptr;
}
return &mpVars[mCount];
}
private:
/* 0x00 */ dSndBgmDataHarpVar_c *mpVars;
/* 0x04 */ s32 mPosition;
/* 0x08 */ s16 mMax;
/* 0x0A */ s16 mCount;
};
class dSndBgmDataHarpVarSet_c : public dSndBgmDataHarpVarSetBase_c {
public:
dSndBgmDataHarpVarSet_c() : dSndBgmDataHarpVarSetBase_c(4) {}
private:
};
/**
* Contains parsed seq data for harp strings for a single bgm sound
*/
class dSndBgmHarpDataBase_c {
public:
dSndBgmHarpDataBase_c();
void resetVars();
s32 getIdxForPosition(s32 position);
dSndBgmDataHarpVarSetBase_c *getUsableVarSet(s32 idx);
void addVar(s32 position, s32 value, s32 unk);
void setField_0x08(s32 value);
protected:
dSndBgmDataHarpVarSetBase_c *getVarSet(s32 idx);
/* 0x00 */ dSndBgmDataHarpVarSetBase_c *mpVarSets;
/* 0x04 */ s16 mMax;
/* 0x06 */ s16 mCount;
/* 0x08 */ s32 field_0x08;
};
class dSndBgmHarpData_c : public dSndBgmHarpDataBase_c {
public:
dSndBgmHarpData_c();
~dSndBgmHarpData_c();
/**
* Writes the Seq sound variables that control the pitch
* of the individual harp strings.
*/
void writeSeqVars(s32 idx);
private:
static const u32 NUM_SETS = 300;
};
#endif
|