Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libmeteor/source/audio/speaker.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/speaker.hpp"
18
#include "../debug.hpp"
19
20
namespace AMeteor
21
{
22
namespace Audio
23
{
24
Speaker::Speaker (uint16_t& cnt1l, uint16_t& cnt1h, uint16_t& cnt1x,
25
uint16_t& cnt2l, uint16_t& cnt2h,
26
uint16_t& cnt4l, uint16_t& cnt4h,
27
uint16_t& cntl, uint16_t& cnth, uint16_t& cntx, uint16_t& bias) :
28
// XXX freq
29
m_sound1(cnt1l, cnt1h, cnt1x, 44100),
30
m_sound2(cnt2l, cnt2h, 44100),
31
m_sound4(cnt4l, cnt4h, 44100),
32
m_cntl(cntl),
33
m_cnth(cnth),
34
m_cntx(cntx),
35
m_bias(bias)
36
{
37
}
38
39
Speaker::~Speaker ()
40
{
41
}
42
43
void Speaker::Reset ()
44
{
45
m_sound1.Reset();
46
m_sound2.Reset();
47
m_sound4.Reset();
48
m_dsa.Reset();
49
m_dsb.Reset();
50
}
51
52
void Speaker::SoundTick ()
53
{
54
int16_t f[2];
55
56
// if master is enabled
57
if (m_cntx & (0x1 << 7))
58
{
59
m_sound1.SoundTick();
60
if (m_sound1.IsOn())
61
m_cntx |= 0x0001;
62
else
63
m_cntx &= 0xFFFE;
64
m_sound2.SoundTick();
65
if (m_sound2.IsOn())
66
m_cntx |= 0x0002;
67
else
68
m_cntx &= 0xFFFD;
69
m_sound4.SoundTick();
70
if (m_sound4.IsOn())
71
m_cntx |= 0x0008;
72
else
73
m_cntx &= 0xFFF7;
74
}
75
76
// left
77
f[0] = MixSample (m_cntl >> 4, m_cnth >> 9);
78
// right
79
f[1] = MixSample (m_cntl, m_cnth >> 8);
80
81
m_sig_frame(f);
82
}
83
84
int16_t Speaker::MixSample (uint16_t cntl, uint8_t cnth)
85
{
86
int16_t sample;
87
88
// if master is enabled
89
if (m_cntx & (0x1 << 7))
90
{
91
int8_t s1, s2, s4;
92
s1 = (cntl & (0x1 << 8)) ? m_sound1.GetSample() : 0;
93
s2 = (cntl & (0x1 << 9)) ? m_sound2.GetSample() : 0;
94
s4 = (cntl & (0x1 << 11)) ? m_sound4.GetSample() : 0;
95
96
int16_t dmg = s1 + s2 + s4;
97
dmg = (dmg * (cntl & 0x7)) / 7;
98
switch (m_cnth & 0x3)
99
{
100
case 0: // 25%
101
dmg /= 4;
102
break;
103
case 1: // 50%
104
dmg /= 2;
105
break;
106
case 2: // 100%
107
break;
108
case 3: // Prohibited
109
met_abort("Invalid SOUNDCNT_H sound # 1-4 volume");
110
break;
111
}
112
113
int16_t sA, sB;
114
sA = (cnth & (0x1 )) ? m_dsa.GetSample() : 0;
115
sB = (cnth & (0x1 << 4)) ? m_dsb.GetSample() : 0;
116
117
if (!(m_cnth & (0x1 << 2)))
118
sA /= 2;
119
if (!(m_cnth & (0x1 << 3)))
120
sB /= 2;
121
122
// TODO when finished put this all together on one line
123
sample = (sA + sB) * 4 + dmg;
124
}
125
else
126
sample = 0;
127
128
sample += m_bias & 0x3FF;
129
if (sample < 0)
130
sample = 0;
131
else if (sample >= 0x400)
132
sample = 0x3FF;
133
sample -= 0x200;
134
sample <<= 6;
135
136
return sample;
137
}
138
139
bool Speaker::SaveState (std::ostream& stream)
140
{
141
#define WRITE(var) \
142
if (!var.SaveState(stream)) \
143
return false
144
WRITE(m_sound1);
145
WRITE(m_sound2);
146
WRITE(m_sound4);
147
WRITE(m_dsa);
148
WRITE(m_dsb);
149
#undef WRITE
150
151
return true;
152
}
153
154
bool Speaker::LoadState (std::istream& stream)
155
{
156
#define READ(var) \
157
if (!var.LoadState(stream)) \
158
return false
159
READ(m_sound1);
160
READ(m_sound2);
161
READ(m_sound4);
162
READ(m_dsa);
163
READ(m_dsb);
164
#undef READ
165
166
return true;
167
}
168
}
169
}
170
171