Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libmeteor/source/audio/sound4.cpp
2 views
1
// Meteor - A Nintendo Gameboy Advance emulator
2
// Copyright (C) 2009-2011 Philippe Daouadi
3
//
4
// This program is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// This program is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17
#include "ameteor/audio/sound4.hpp"
18
#include "../globals.hpp"
19
20
namespace AMeteor
21
{
22
namespace Audio
23
{
24
static bool Noise7Stages[127];
25
static bool Noise15Stages[32767];
26
27
void InitNoise ()
28
{
29
unsigned short i = 0x7f;
30
bool* pNoise = Noise7Stages;
31
do
32
{
33
*pNoise++ = i & 1;
34
i = (i >> 1) | (((i & 1) << 6) ^ ((i & 2) << 5));
35
} while (i != 0x7f);
36
37
i = 0x7fff;
38
pNoise = Noise15Stages;
39
do
40
{
41
*pNoise++ = i & 1;
42
i = (i >> 1) | (((i & 1) << 14) ^ ((i & 2) << 13));
43
} while (i != 0x7fff);
44
}
45
46
Sound4::Sound4 (uint16_t& cntl, uint16_t& cnth, uint16_t freq) :
47
m_cntl(cntl),
48
m_cnth(cnth),
49
m_on(false),
50
m_posP(0),
51
m_posN(0),
52
m_posE(0),
53
m_sample(0),
54
m_speriod(16*1024*1024/freq),
55
m_envelope(0),
56
m_length(0),
57
m_timed(false),
58
m_div(4*8/2)
59
{
60
}
61
62
void Sound4::Reset ()
63
{
64
m_on = false;
65
m_timed = false;
66
m_length = 0;
67
m_envelope = 0;
68
m_posP = m_posE = m_posN = 0;
69
m_sample = 0;
70
m_div = 4*8/2;
71
}
72
73
void Sound4::ResetSound ()
74
{
75
m_on = true;
76
m_timed = (m_cnth & (0x1 << 14));
77
m_length = (64 - (m_cntl & 0x3F)) * ((16*1024*1024)/256);
78
m_envelope = m_cntl >> 12;
79
m_div = ((m_cnth & 0x7) ? 4*8*(m_cnth & 0x7) : 4*8/2);
80
m_posE = m_posP = 0;
81
}
82
83
void Sound4::SoundTick ()
84
{
85
// rest is the number of processor clock ticks that were not yet taken by
86
// the noise clock divider (if the total divider is 8 and we have 10
87
// ticks of the processor clock, only 8 were taken by the noise clock),
88
// the rest will be taken by the next call of SoundTick()
89
uint16_t rest = m_posP + m_speriod;
90
// advance is the number of noise ticks that have passed
91
uint16_t advance = m_posP + m_speriod;
92
93
// time of one sound tick in cycles
94
uint32_t tick = m_div;
95
// if shift is 111X in binary
96
if (((m_cnth >> 5) & 0x7) == 0x7)
97
// not used
98
// assume 13
99
tick *= 1 << 14;
100
else
101
tick *= (2 << ((m_cnth >> 4) & 0xF));
102
103
rest %= tick;
104
advance /= tick;
105
106
m_posP = rest;
107
m_posN += advance;
108
// we have this modulo on posN so that when you switch from 15 stages to
109
// 7 stages and then you switch back, you won't restart the 15 stages
110
// pattern from the beginning
111
// don't know if GBA handle this like that
112
m_posN %= 32768;
113
114
m_posE += m_speriod;
115
if (m_length > m_speriod)
116
m_length -= m_speriod;
117
else
118
{
119
if (m_timed)
120
m_on = false;
121
m_length = 0;
122
}
123
124
uint32_t steptime = ((m_cntl >> 8) & 0x7) * ((16*1024*1024)/64);
125
if (steptime && m_posE > steptime)
126
{
127
if (m_cnth & (0x1 << 11))
128
{
129
if (m_envelope < 15)
130
++m_envelope;
131
}
132
else
133
{
134
if (m_envelope > 0)
135
--m_envelope;
136
}
137
138
m_posE -= steptime;
139
}
140
141
if (m_on && m_envelope)
142
{
143
if (m_cnth & (0x1 << 3))
144
m_sample = Noise7Stages[m_posN % 128];
145
else
146
m_sample = Noise15Stages[m_posN];
147
148
m_sample = m_sample ? 127 : -127;
149
m_sample = (((int16_t)m_sample) * m_envelope)/15;
150
}
151
else
152
m_sample = 0;
153
}
154
155
bool Sound4::SaveState (std::ostream& stream)
156
{
157
SS_WRITE_VAR(m_on);
158
SS_WRITE_VAR(m_posP);
159
SS_WRITE_VAR(m_posE);
160
SS_WRITE_VAR(m_posN);
161
SS_WRITE_VAR(m_sample);
162
SS_WRITE_VAR(m_envelope);
163
SS_WRITE_VAR(m_length);
164
SS_WRITE_VAR(m_timed);
165
SS_WRITE_VAR(m_div);
166
167
return true;
168
}
169
170
bool Sound4::LoadState (std::istream& stream)
171
{
172
SS_READ_VAR(m_on);
173
SS_READ_VAR(m_posP);
174
SS_READ_VAR(m_posE);
175
SS_READ_VAR(m_posN);
176
SS_READ_VAR(m_sample);
177
SS_READ_VAR(m_envelope);
178
SS_READ_VAR(m_length);
179
SS_READ_VAR(m_timed);
180
SS_READ_VAR(m_div);
181
182
return true;
183
}
184
}
185
}
186
187