1 #include <cassert>
2 #include <cstring>
3 #include <cmath>
4 #include <climits>
5 #include "string_format.h"
6 #include "../Log.h"
7 #include "../states/RegisterStateFile.h"
8 #include "Iop_SpuBase.h"
9 
10 using namespace Iop;
11 
12 #define INIT_SAMPLE_RATE (44100)
13 #define TIME_SCALE (0x1000)
14 #define LOG_NAME ("iop_spubase")
15 
16 #define INVALID_ADDRESS (~0U)
17 
18 #define STATE_PATH_FORMAT ("iop_spu/spu_%d.xml")
19 #define STATE_REGS_CTRL ("CTRL")
20 #define STATE_REGS_IRQADDR ("IRQADDR")
21 #define STATE_REGS_TRANSFERADDR ("TRANSFERADDR")
22 #define STATE_REGS_TRANSFERMODE ("TRANSFERMODE")
23 #define STATE_REGS_CORE0OUTPUTOFFSET ("CORE0OUTPUTOFFSET")
24 #define STATE_REGS_CHANNELON ("CHANNELON")
25 #define STATE_REGS_CHANNELREVERB ("CHANNELREVERB")
26 #define STATE_REGS_REVERBWORKADDRSTART ("REVERBWORKADDRSTART")
27 #define STATE_REGS_REVERBWORKADDREND ("REVERBWORKADDREND")
28 #define STATE_REGS_REVERBCURRADDR ("REVERBCURRADDR")
29 #define STATE_REGS_REVERB_FORMAT ("REVERB%d")
30 
31 #define STATE_CHANNEL_REGS_PREFIX ("CHANNEL%02d_")
32 #define STATE_CHANNEL_REGS_VOLUMELEFT ("VOLUMELEFT")
33 #define STATE_CHANNEL_REGS_VOLUMERIGHT ("VOLUMERIGHT")
34 #define STATE_CHANNEL_REGS_VOLUMELEFTABS ("VOLUMELEFTABS")
35 #define STATE_CHANNEL_REGS_VOLUMERIGHTABS ("VOLUMERIGHTABS")
36 #define STATE_CHANNEL_REGS_STATUS ("STATUS")
37 #define STATE_CHANNEL_REGS_PITCH ("PITCH")
38 #define STATE_CHANNEL_REGS_ADSRLEVEL ("ADSRLEVEL")
39 #define STATE_CHANNEL_REGS_ADSRRATE ("ADSRRATE")
40 #define STATE_CHANNEL_REGS_ADSRVOLUME ("ADSRVOLUME")
41 #define STATE_CHANNEL_REGS_ADDRESS ("ADDRESS")
42 #define STATE_CHANNEL_REGS_REPEAT ("REPEAT")
43 #define STATE_CHANNEL_REGS_CURRENT ("CURRENT")
44 
45 #define STATE_SAMPLEREADER_REGS_SRCSAMPLEIDX ("SrcSampleIdx")
46 #define STATE_SAMPLEREADER_REGS_SRCSAMPLINGRATE ("SrcSamplingRate")
47 #define STATE_SAMPLEREADER_REGS_NEXTSAMPLEADDR ("NextSampleAddr")
48 #define STATE_SAMPLEREADER_REGS_REPEATADDR ("RepeatAddr")
49 #define STATE_SAMPLEREADER_REGS_IRQADDR ("IrqAddr")
50 #define STATE_SAMPLEREADER_REGS_PITCH ("Pitch")
51 #define STATE_SAMPLEREADER_REGS_S1 ("S1")
52 #define STATE_SAMPLEREADER_REGS_S2 ("S2")
53 #define STATE_SAMPLEREADER_REGS_DONE ("Done")
54 #define STATE_SAMPLEREADER_REGS_NEXTVALID ("NextValid")
55 #define STATE_SAMPLEREADER_REGS_ENDFLAG ("EndFlag")
56 #define STATE_SAMPLEREADER_REGS_IRQPENDING ("IrqPending")
57 #define STATE_SAMPLEREADER_REGS_DIDCHANGEREPEAT ("DidChangeRepeat")
58 #define STATE_SAMPLEREADER_REGS_BUFFER_FORMAT ("%sBuffer%d")
59 
60 bool CSpuBase::g_reverbParamIsAddress[REVERB_PARAM_COUNT] =
61     {
62         true,
63         true,
64         false,
65         false,
66         false,
67         false,
68         false,
69         false,
70         false,
71         false,
72         true,
73         true,
74         true,
75         true,
76         true,
77         true,
78         true,
79         true,
80         true,
81         true,
82         true,
83         true,
84         true,
85         true,
86         true,
87         true,
88         true,
89         true,
90         true,
91         true,
92         false,
93         false};
94 
95 const uint32 CSpuBase::g_linearIncreaseSweepDeltas[0x80] =
96     {
97         0x3A0CC55E, 0x305FF9CE, 0x2976D61E, 0x203FFBDE, 0x1D0662AF, 0x182FFCE7, 0x1359971F, 0x101FFDEF,
98         0x0DD2475F, 0x0C17FE73, 0x0A0233AF, 0x080FFEF7, 0x07144A05, 0x060BFF39, 0x050119D7, 0x03F9DC6C,
99         0x037F3A27, 0x02FE04E5, 0x026B32E3, 0x01EF5BE9, 0x01B514DD, 0x018712AA, 0x01430F6B, 0x0100385E,
100         0x00E129C7, 0x00BE85CF, 0x00A187B5, 0x00801C2F, 0x007094E3, 0x00607F9E, 0x004FE588, 0x003DEB7D,
101         0x00392824, 0x00318930, 0x00271B77, 0x00204E57, 0x001B851B, 0x0017F80F, 0x00141506, 0x0010272B,
102         0x000E0504, 0x000BFC07, 0x000A0A83, 0x0007FD5A, 0x0006C140, 0x00063126, 0x0004F41E, 0x0003E925,
103         0x000389CC, 0x0002F8DF, 0x00027A0F, 0x0002021A, 0x0001C4E6, 0x00017C6F, 0x00014267, 0x0001010D,
104         0x0000DFC9, 0x0000C023, 0x00009E83, 0x00007ECF, 0x00006FE4, 0x00005F1B, 0x00004F41, 0x00003F67,
105         0x000037F2, 0x00002F8D, 0x000027A0, 0x0000203D, 0x00001BF9, 0x00001814, 0x00001405, 0x00000FD9,
106         0x00000D96, 0x00000BE3, 0x00000A02, 0x000007EC, 0x0000070B, 0x000005F1, 0x00000501, 0x000003F6,
107         0x00000385, 0x00000304, 0x00000280, 0x00000200, 0x000001BE, 0x0000017F, 0x00000140, 0x00000100,
108         0x000000DF, 0x000000BF, 0x000000A0, 0x00000080, 0x0000006F, 0x0000005F, 0x00000050, 0x00000040,
109         0x00000037, 0x0000002F, 0x00000028, 0x00000020, 0x0000001B, 0x00000017, 0x00000014, 0x00000010,
110         0x0000000D, 0x0000000B, 0x0000000A, 0x00000008, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
111         0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
112         0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000};
113 
114 const uint32 CSpuBase::g_linearDecreaseSweepDeltas[0x80] =
115     {
116         0x488FF6B5, 0x3A0CC55E, 0x305FF9CE, 0x2976D61E, 0x203FFBDE, 0x1D0662AF, 0x182FFCE7, 0x1359971F,
117         0x101FFDEF, 0x0DD2475F, 0x0C17FE73, 0x0A0233AF, 0x080FFEF7, 0x07144A05, 0x060BFF39, 0x050119D7,
118         0x03F9DC6C, 0x037F3A27, 0x02FE04E5, 0x026B32E3, 0x01EF5BE9, 0x01B514DD, 0x018712AA, 0x01430F6B,
119         0x0100385E, 0x00E129C7, 0x00BE85CF, 0x00A187B5, 0x00801C2F, 0x007094E3, 0x00607F9E, 0x004FE588,
120         0x003DEB7D, 0x00392824, 0x00318930, 0x00271B77, 0x00204E57, 0x001B851B, 0x0017F80F, 0x00141506,
121         0x0010272B, 0x000E0504, 0x000BFC07, 0x000A0A83, 0x0007FD5A, 0x0006C140, 0x00063126, 0x0004F41E,
122         0x0003E925, 0x000389CC, 0x0002F8DF, 0x00027A0F, 0x0002021A, 0x0001C4E6, 0x00017C6F, 0x00014267,
123         0x0001010D, 0x0000DFC9, 0x0000C023, 0x00009E83, 0x00007ECF, 0x00006FE4, 0x00005F1B, 0x00004F41,
124         0x00003F67, 0x000037F2, 0x00002F8D, 0x000027A0, 0x0000203D, 0x00001BF9, 0x00001814, 0x00001405,
125         0x00000FD9, 0x00000D96, 0x00000BE3, 0x00000A02, 0x000007EC, 0x0000070B, 0x000005F1, 0x00000501,
126         0x000003F6, 0x00000385, 0x00000304, 0x00000280, 0x00000200, 0x000001BE, 0x0000017F, 0x00000140,
127         0x00000100, 0x000000DF, 0x000000BF, 0x000000A0, 0x00000080, 0x0000006F, 0x0000005F, 0x00000050,
128         0x00000040, 0x00000037, 0x0000002F, 0x00000028, 0x00000020, 0x0000001B, 0x00000017, 0x00000014,
129         0x00000010, 0x0000000D, 0x0000000B, 0x0000000A, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
130         0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
131         0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000};
132 
CSpuBase(uint8 * ram,uint32 ramSize,unsigned int spuNumber)133 CSpuBase::CSpuBase(uint8* ram, uint32 ramSize, unsigned int spuNumber)
134     : m_ram(ram)
135     , m_ramSize(ramSize)
136     , m_spuNumber(spuNumber)
137     , m_reverbEnabled(true)
138 {
139 	Reset();
140 
141 	//Init log table for ADSR
142 	memset(m_adsrLogTable, 0, sizeof(m_adsrLogTable));
143 
144 	uint32 value = 3;
145 	uint32 columnIncrement = 1;
146 	uint32 column = 0;
147 
148 	for(unsigned int i = 32; i < 160; i++)
149 	{
150 		if(value < 0x3FFFFFFF)
151 		{
152 			value += columnIncrement;
153 			column++;
154 			if(column == 5)
155 			{
156 				column = 1;
157 				columnIncrement *= 2;
158 			}
159 		}
160 		else
161 		{
162 			value = 0x3FFFFFFF;
163 		}
164 		m_adsrLogTable[i] = value;
165 	}
166 }
167 
Reset()168 void CSpuBase::Reset()
169 {
170 	m_ctrl = 0;
171 
172 	m_volumeAdjust = 1.0f;
173 
174 	m_channelOn.f = 0;
175 	m_channelReverb.f = 0;
176 	m_reverbTicks = 0;
177 	m_irqAddr = INVALID_ADDRESS;
178 	m_irqPending = false;
179 	m_transferMode = 0;
180 	m_transferAddr = 0;
181 
182 	m_core0OutputOffset = 0;
183 
184 	m_reverbCurrAddr = 0;
185 	m_reverbWorkAddrStart = 0;
186 	m_reverbWorkAddrEnd = 0x80000;
187 	m_baseSamplingRate = 44100;
188 
189 	memset(m_channel, 0, sizeof(m_channel));
190 	memset(m_reverb, 0, sizeof(m_reverb));
191 
192 	for(unsigned int i = 0; i < MAX_CHANNEL; i++)
193 	{
194 		m_reader[i].Reset();
195 		m_reader[i].SetMemory(m_ram, m_ramSize);
196 	}
197 
198 	m_blockReader.Reset();
199 	m_soundInputDataAddr = (m_spuNumber == 0) ? SOUND_INPUT_DATA_CORE0_BASE : SOUND_INPUT_DATA_CORE1_BASE;
200 	m_blockWritePtr = 0;
201 }
202 
LoadState(Framework::CZipArchiveReader & archive)203 void CSpuBase::LoadState(Framework::CZipArchiveReader& archive)
204 {
205 	auto path = string_format(STATE_PATH_FORMAT, m_spuNumber);
206 
207 	auto registerFile = CRegisterStateFile(*archive.BeginReadFile(path.c_str()));
208 	m_ctrl = registerFile.GetRegister32(STATE_REGS_CTRL);
209 	m_irqAddr = registerFile.GetRegister32(STATE_REGS_IRQADDR);
210 	m_transferMode = registerFile.GetRegister32(STATE_REGS_TRANSFERMODE);
211 	m_transferAddr = registerFile.GetRegister32(STATE_REGS_TRANSFERADDR);
212 	m_core0OutputOffset = registerFile.GetRegister32(STATE_REGS_CORE0OUTPUTOFFSET);
213 	m_channelOn.f = registerFile.GetRegister32(STATE_REGS_CHANNELON);
214 	m_channelReverb.f = registerFile.GetRegister32(STATE_REGS_CHANNELREVERB);
215 	m_reverbWorkAddrStart = registerFile.GetRegister32(STATE_REGS_REVERBWORKADDRSTART);
216 	m_reverbWorkAddrEnd = registerFile.GetRegister32(STATE_REGS_REVERBWORKADDREND);
217 	m_reverbCurrAddr = registerFile.GetRegister32(STATE_REGS_REVERBCURRADDR);
218 
219 	static const uint32 reverbRegisterCount = sizeof(m_reverb) / sizeof(uint128);
220 	for(uint32 i = 0; i < reverbRegisterCount; i++)
221 	{
222 		auto reverbRegisterName = string_format(STATE_REGS_REVERB_FORMAT, i);
223 		reinterpret_cast<uint128*>(m_reverb)[i] = registerFile.GetRegister128(reverbRegisterName.c_str());
224 	}
225 
226 	for(unsigned int i = 0; i < MAX_CHANNEL; i++)
227 	{
228 		auto& channel = m_channel[i];
229 		auto& reader = m_reader[i];
230 		auto channelPrefix = string_format(STATE_CHANNEL_REGS_PREFIX, i);
231 		channel.volumeLeft <<= registerFile.GetRegister32((channelPrefix + STATE_CHANNEL_REGS_VOLUMELEFT).c_str());
232 		channel.volumeRight <<= registerFile.GetRegister32((channelPrefix + STATE_CHANNEL_REGS_VOLUMERIGHT).c_str());
233 		channel.volumeLeftAbs = registerFile.GetRegister32((channelPrefix + STATE_CHANNEL_REGS_VOLUMELEFTABS).c_str());
234 		channel.volumeRightAbs = registerFile.GetRegister32((channelPrefix + STATE_CHANNEL_REGS_VOLUMERIGHTABS).c_str());
235 		channel.status = registerFile.GetRegister32((channelPrefix + STATE_CHANNEL_REGS_STATUS).c_str());
236 		channel.pitch = registerFile.GetRegister32((channelPrefix + STATE_CHANNEL_REGS_PITCH).c_str());
237 		channel.adsrLevel <<= registerFile.GetRegister32((channelPrefix + STATE_CHANNEL_REGS_ADSRLEVEL).c_str());
238 		channel.adsrRate <<= registerFile.GetRegister32((channelPrefix + STATE_CHANNEL_REGS_ADSRRATE).c_str());
239 		channel.adsrVolume = registerFile.GetRegister32((channelPrefix + STATE_CHANNEL_REGS_ADSRVOLUME).c_str());
240 		channel.address = registerFile.GetRegister32((channelPrefix + STATE_CHANNEL_REGS_ADDRESS).c_str());
241 		channel.repeat = registerFile.GetRegister32((channelPrefix + STATE_CHANNEL_REGS_REPEAT).c_str());
242 		channel.current = registerFile.GetRegister32((channelPrefix + STATE_CHANNEL_REGS_CURRENT).c_str());
243 		reader.LoadState(registerFile, channelPrefix);
244 	}
245 }
246 
SaveState(Framework::CZipArchiveWriter & archive)247 void CSpuBase::SaveState(Framework::CZipArchiveWriter& archive)
248 {
249 	auto path = string_format(STATE_PATH_FORMAT, m_spuNumber);
250 
251 	auto registerFile = new CRegisterStateFile(path.c_str());
252 	registerFile->SetRegister32(STATE_REGS_CTRL, m_ctrl);
253 	registerFile->SetRegister32(STATE_REGS_IRQADDR, m_irqAddr);
254 	registerFile->SetRegister32(STATE_REGS_TRANSFERMODE, m_transferMode);
255 	registerFile->SetRegister32(STATE_REGS_TRANSFERADDR, m_transferAddr);
256 	registerFile->SetRegister32(STATE_REGS_CORE0OUTPUTOFFSET, m_core0OutputOffset);
257 	registerFile->SetRegister32(STATE_REGS_CHANNELON, m_channelOn.f);
258 	registerFile->SetRegister32(STATE_REGS_CHANNELREVERB, m_channelReverb.f);
259 	registerFile->SetRegister32(STATE_REGS_REVERBWORKADDRSTART, m_reverbWorkAddrStart);
260 	registerFile->SetRegister32(STATE_REGS_REVERBWORKADDREND, m_reverbWorkAddrEnd);
261 	registerFile->SetRegister32(STATE_REGS_REVERBCURRADDR, m_reverbCurrAddr);
262 
263 	static const uint32 reverbRegisterCount = sizeof(m_reverb) / sizeof(uint128);
264 	for(uint32 i = 0; i < reverbRegisterCount; i++)
265 	{
266 		auto reverbRegisterName = string_format(STATE_REGS_REVERB_FORMAT, i);
267 		registerFile->SetRegister128(reverbRegisterName.c_str(), reinterpret_cast<const uint128*>(m_reverb)[i]);
268 	}
269 
270 	for(unsigned int i = 0; i < MAX_CHANNEL; i++)
271 	{
272 		const auto& channel = m_channel[i];
273 		const auto& reader = m_reader[i];
274 		auto channelPrefix = string_format(STATE_CHANNEL_REGS_PREFIX, i);
275 		registerFile->SetRegister32((channelPrefix + STATE_CHANNEL_REGS_VOLUMELEFT).c_str(), channel.volumeLeft);
276 		registerFile->SetRegister32((channelPrefix + STATE_CHANNEL_REGS_VOLUMERIGHT).c_str(), channel.volumeRight);
277 		registerFile->SetRegister32((channelPrefix + STATE_CHANNEL_REGS_VOLUMELEFTABS).c_str(), channel.volumeLeftAbs);
278 		registerFile->SetRegister32((channelPrefix + STATE_CHANNEL_REGS_VOLUMERIGHTABS).c_str(), channel.volumeRightAbs);
279 		registerFile->SetRegister32((channelPrefix + STATE_CHANNEL_REGS_STATUS).c_str(), channel.status);
280 		registerFile->SetRegister32((channelPrefix + STATE_CHANNEL_REGS_PITCH).c_str(), channel.pitch);
281 		registerFile->SetRegister32((channelPrefix + STATE_CHANNEL_REGS_ADSRLEVEL).c_str(), channel.adsrLevel);
282 		registerFile->SetRegister32((channelPrefix + STATE_CHANNEL_REGS_ADSRRATE).c_str(), channel.adsrRate);
283 		registerFile->SetRegister32((channelPrefix + STATE_CHANNEL_REGS_ADSRVOLUME).c_str(), channel.adsrVolume);
284 		registerFile->SetRegister32((channelPrefix + STATE_CHANNEL_REGS_ADDRESS).c_str(), channel.address);
285 		registerFile->SetRegister32((channelPrefix + STATE_CHANNEL_REGS_REPEAT).c_str(), channel.repeat);
286 		registerFile->SetRegister32((channelPrefix + STATE_CHANNEL_REGS_CURRENT).c_str(), channel.current);
287 		reader.SaveState(registerFile, channelPrefix);
288 	}
289 
290 	archive.InsertFile(registerFile);
291 }
292 
IsEnabled() const293 bool CSpuBase::IsEnabled() const
294 {
295 	return (m_ctrl & 0x8000) != 0;
296 }
297 
SetVolumeAdjust(float volumeAdjust)298 void CSpuBase::SetVolumeAdjust(float volumeAdjust)
299 {
300 	m_volumeAdjust = volumeAdjust;
301 }
302 
SetReverbEnabled(bool enabled)303 void CSpuBase::SetReverbEnabled(bool enabled)
304 {
305 	m_reverbEnabled = enabled;
306 }
307 
GetControl() const308 uint16 CSpuBase::GetControl() const
309 {
310 	return m_ctrl;
311 }
312 
SetControl(uint16 value)313 void CSpuBase::SetControl(uint16 value)
314 {
315 	m_ctrl = value;
316 	if((m_ctrl & CONTROL_IRQ) == 0)
317 	{
318 		ClearIrqPending();
319 	}
320 }
321 
SetBaseSamplingRate(uint32 samplingRate)322 void CSpuBase::SetBaseSamplingRate(uint32 samplingRate)
323 {
324 	m_baseSamplingRate = samplingRate;
325 }
326 
GetIrqPending() const327 bool CSpuBase::GetIrqPending() const
328 {
329 	return m_irqPending;
330 }
331 
ClearIrqPending()332 void CSpuBase::ClearIrqPending()
333 {
334 	m_irqPending = false;
335 }
336 
GetIrqAddress() const337 uint32 CSpuBase::GetIrqAddress() const
338 {
339 	return m_irqAddr;
340 }
341 
SetIrqAddress(uint32 value)342 void CSpuBase::SetIrqAddress(uint32 value)
343 {
344 	m_irqAddr = value & (m_ramSize - 1);
345 }
346 
GetTransferMode() const347 uint16 CSpuBase::GetTransferMode() const
348 {
349 	return m_transferMode;
350 }
351 
SetTransferMode(uint16 transferMode)352 void CSpuBase::SetTransferMode(uint16 transferMode)
353 {
354 	m_transferMode = transferMode;
355 }
356 
GetTransferAddress() const357 uint32 CSpuBase::GetTransferAddress() const
358 {
359 	return m_transferAddr;
360 }
361 
SetTransferAddress(uint32 value)362 void CSpuBase::SetTransferAddress(uint32 value)
363 {
364 	m_transferAddr = value & (m_ramSize - 1);
365 }
366 
GetChannelOn() const367 UNION32_16 CSpuBase::GetChannelOn() const
368 {
369 	return m_channelOn;
370 }
371 
SetChannelOnLo(uint16 value)372 void CSpuBase::SetChannelOnLo(uint16 value)
373 {
374 	m_channelOn.h0 = value;
375 }
376 
SetChannelOnHi(uint16 value)377 void CSpuBase::SetChannelOnHi(uint16 value)
378 {
379 	m_channelOn.h1 = value;
380 }
381 
GetChannelReverb() const382 UNION32_16 CSpuBase::GetChannelReverb() const
383 {
384 	return m_channelReverb;
385 }
386 
SetChannelReverbLo(uint16 value)387 void CSpuBase::SetChannelReverbLo(uint16 value)
388 {
389 	m_channelReverb.h0 = value;
390 }
391 
SetChannelReverbHi(uint16 value)392 void CSpuBase::SetChannelReverbHi(uint16 value)
393 {
394 	m_channelReverb.h1 = value;
395 }
396 
GetReverbParam(unsigned int param) const397 uint32 CSpuBase::GetReverbParam(unsigned int param) const
398 {
399 	assert(param < REVERB_PARAM_COUNT);
400 	return m_reverb[param];
401 }
402 
SetReverbParam(unsigned int param,uint32 value)403 void CSpuBase::SetReverbParam(unsigned int param, uint32 value)
404 {
405 	assert(param < REVERB_PARAM_COUNT);
406 	m_reverb[param] = value;
407 }
408 
GetEndFlags() const409 UNION32_16 CSpuBase::GetEndFlags() const
410 {
411 	UNION32_16 result(0);
412 	for(unsigned int i = 0; i < MAX_CHANNEL; i++)
413 	{
414 		if(m_reader[i].GetEndFlag())
415 		{
416 			result.f |= (1 << i);
417 		}
418 	}
419 	return result;
420 }
421 
ClearEndFlags()422 void CSpuBase::ClearEndFlags()
423 {
424 	for(unsigned int i = 0; i < MAX_CHANNEL; i++)
425 	{
426 		m_reader[i].ClearEndFlag();
427 	}
428 }
429 
GetChannel(unsigned int channelNumber)430 CSpuBase::CHANNEL& CSpuBase::GetChannel(unsigned int channelNumber)
431 {
432 	assert(channelNumber < MAX_CHANNEL);
433 	return m_channel[channelNumber];
434 }
435 
SendKeyOn(uint32 channels)436 void CSpuBase::SendKeyOn(uint32 channels)
437 {
438 	for(unsigned int i = 0; i < MAX_CHANNEL; i++)
439 	{
440 		CHANNEL& channel = m_channel[i];
441 		if(channels & (1 << i))
442 		{
443 			channel.status = KEY_ON;
444 		}
445 	}
446 }
447 
SendKeyOff(uint32 channels)448 void CSpuBase::SendKeyOff(uint32 channels)
449 {
450 	for(unsigned int i = 0; i < MAX_CHANNEL; i++)
451 	{
452 		CHANNEL& channel = m_channel[i];
453 		if(channels & (1 << i))
454 		{
455 			if(channel.status == STOPPED) continue;
456 			if(channel.status == KEY_ON)
457 			{
458 				channel.status = STOPPED;
459 				//Update channel registers since we are doing KEY_ON -> STOPPED transition
460 				auto& reader = m_reader[i];
461 				reader.SetParamsNoRead(channel.address, channel.repeat);
462 				reader.ClearEndFlag();
463 				channel.current = reader.GetCurrent();
464 			}
465 			else
466 			{
467 				channel.status = RELEASE;
468 			}
469 		}
470 	}
471 }
472 
GetReverbWorkAddressStart() const473 uint32 CSpuBase::GetReverbWorkAddressStart() const
474 {
475 	return m_reverbWorkAddrStart;
476 }
477 
SetReverbWorkAddressStart(uint32 address)478 void CSpuBase::SetReverbWorkAddressStart(uint32 address)
479 {
480 	assert(address <= m_ramSize);
481 	m_reverbWorkAddrStart = address;
482 	m_reverbCurrAddr = address;
483 }
484 
GetReverbWorkAddressEnd() const485 uint32 CSpuBase::GetReverbWorkAddressEnd() const
486 {
487 	return m_reverbWorkAddrEnd - 1;
488 }
489 
SetReverbWorkAddressEnd(uint32 address)490 void CSpuBase::SetReverbWorkAddressEnd(uint32 address)
491 {
492 	assert((address & 0xFFFF) == 0xFFFF);
493 	assert(address <= m_ramSize);
494 	m_reverbWorkAddrEnd = address + 1;
495 }
496 
SetReverbCurrentAddress(uint32 address)497 void CSpuBase::SetReverbCurrentAddress(uint32 address)
498 {
499 	m_reverbCurrAddr = address;
500 }
501 
ReceiveDma(uint8 * buffer,uint32 blockSize,uint32 blockAmount)502 uint32 CSpuBase::ReceiveDma(uint8* buffer, uint32 blockSize, uint32 blockAmount)
503 {
504 #ifdef _DEBUG
505 	CLog::GetInstance().Print(LOG_NAME, "Receiving DMA transfer to 0x%08X. Size = 0x%08X bytes.\r\n",
506 	                          m_transferAddr, blockSize * blockAmount);
507 #endif
508 	if(m_transferMode == TRANSFER_MODE_VOICE)
509 	{
510 		if((m_ctrl & CONTROL_DMA) == CONTROL_DMA_STOP)
511 		{
512 			//Genso Suikoden 5 uses this
513 			return 0;
514 		}
515 		if((m_ctrl & CONTROL_DMA) == CONTROL_DMA_READ)
516 		{
517 			//- DMA reads need to be throttled to allow FFX IopSoundDriver to properly synchronize itself
518 			blockAmount = std::min<uint32>(blockAmount, 0x10);
519 			return blockAmount;
520 		}
521 		//- Tsugunai needs voice transfers to be throttled because it starts a DMA transfer
522 		//  and then writes data that is necessary to the transfer callback in memory
523 		//- Some PSF sets (FF4, Xenogears, Xenosaga 2) are sensitive to aggressive throttling (doesn't like 0x10)
524 		blockAmount = std::min<uint32>(blockAmount, 0x100);
525 		assert((m_ctrl & CONTROL_DMA) == CONTROL_DMA_WRITE);
526 		unsigned int blocksTransfered = 0;
527 		for(unsigned int i = 0; i < blockAmount; i++)
528 		{
529 			uint32 copySize = std::min<uint32>(m_ramSize - m_transferAddr, blockSize);
530 			memcpy(m_ram + m_transferAddr, buffer, copySize);
531 			m_transferAddr += blockSize;
532 			m_transferAddr &= m_ramSize - 1;
533 			buffer += blockSize;
534 			blocksTransfered++;
535 		}
536 		return blocksTransfered;
537 	}
538 	else if(
539 	    (m_transferMode == TRANSFER_MODE_BLOCK_CORE0IN) ||
540 	    (m_transferMode == TRANSFER_MODE_BLOCK_CORE1IN))
541 	{
542 		assert(m_transferAddr == 0);
543 		assert((m_spuNumber == 0) || !(m_transferMode == TRANSFER_MODE_BLOCK_CORE0IN));
544 		assert((m_spuNumber == 1) || !(m_transferMode == TRANSFER_MODE_BLOCK_CORE1IN));
545 		assert(m_blockWritePtr <= SOUND_INPUT_DATA_SIZE);
546 
547 		uint32 availableBytes = SOUND_INPUT_DATA_SIZE - m_blockWritePtr;
548 		uint32 availableBlocks = availableBytes / blockSize;
549 		blockAmount = std::min(blockAmount, availableBlocks);
550 
551 		uint32 dstAddr = m_soundInputDataAddr + m_blockWritePtr;
552 		memcpy(m_ram + dstAddr, buffer, blockAmount * blockSize);
553 		m_blockWritePtr += blockAmount * blockSize;
554 
555 		return blockAmount;
556 	}
557 	else
558 	{
559 		return 1;
560 	}
561 }
562 
WriteWord(uint16 value)563 void CSpuBase::WriteWord(uint16 value)
564 {
565 	assert((m_transferAddr + 1) < m_ramSize);
566 	*reinterpret_cast<uint16*>(&m_ram[m_transferAddr]) = value;
567 	m_transferAddr += 2;
568 }
569 
ComputeChannelVolume(const CHANNEL_VOLUME & volume,int32 currentVolume)570 int32 CSpuBase::ComputeChannelVolume(const CHANNEL_VOLUME& volume, int32 currentVolume)
571 {
572 	int32 volumeLevel = 0;
573 	if(!volume.mode.mode)
574 	{
575 		if(volume.volume.phase)
576 		{
577 			volumeLevel = 0x3FFF - volume.volume.volume;
578 		}
579 		else
580 		{
581 			volumeLevel = volume.volume.volume;
582 		}
583 		volumeLevel <<= 17;
584 	}
585 	else
586 	{
587 		assert(volume.sweep.phase == 0);
588 		assert(volume.sweep.slope == 0);
589 		if(volume.sweep.decrease)
590 		{
591 			uint32 sweepDelta = g_linearDecreaseSweepDeltas[volume.sweep.volume];
592 			volumeLevel = currentVolume - sweepDelta;
593 		}
594 		else
595 		{
596 			uint32 sweepDelta = g_linearIncreaseSweepDeltas[volume.sweep.volume];
597 			volumeLevel = currentVolume + sweepDelta;
598 		}
599 		volumeLevel = std::max<int32>(volumeLevel, 0x00000000);
600 		volumeLevel = std::min<int32>(volumeLevel, 0x7FFFFFFF);
601 	}
602 	return volumeLevel;
603 }
604 
MixSamples(int32 inputSample,int32 volumeLevel,int16 * output)605 void CSpuBase::MixSamples(int32 inputSample, int32 volumeLevel, int16* output)
606 {
607 	inputSample = (inputSample * volumeLevel) / 0x7FFF;
608 	int32 resultSample = inputSample + static_cast<int32>(*output);
609 	resultSample = std::max<int32>(resultSample, SHRT_MIN);
610 	resultSample = std::min<int32>(resultSample, SHRT_MAX);
611 	*output = static_cast<int16>(resultSample);
612 }
613 
Render(int16 * samples,unsigned int sampleCount,unsigned int sampleRate)614 void CSpuBase::Render(int16* samples, unsigned int sampleCount, unsigned int sampleRate)
615 {
616 	bool updateReverb = m_reverbEnabled && (m_ctrl & CONTROL_REVERB) && (m_reverbWorkAddrStart < m_reverbWorkAddrEnd);
617 	bool checkIrqs = (m_ctrl & CONTROL_IRQ) && (m_irqAddr != INVALID_ADDRESS);
618 
619 	assert((sampleCount & 0x01) == 0);
620 	//ticks are 44100Hz ticks
621 	unsigned int ticks = sampleCount / 2;
622 	memset(samples, 0, sizeof(int16) * sampleCount);
623 
624 	for(unsigned int j = 0; j < ticks; j++)
625 	{
626 		int16 reverbSample[2] = {0, 0};
627 		//Update channels
628 		for(unsigned int i = 0; i < 24; i++)
629 		{
630 			auto& channel(m_channel[i]);
631 			if((channel.status == STOPPED) && !checkIrqs) continue;
632 			auto& reader(m_reader[i]);
633 			reader.SetIrqAddress(m_irqAddr);
634 			if(channel.status == KEY_ON)
635 			{
636 				reader.SetParamsRead(channel.address, channel.repeat);
637 				reader.ClearEndFlag();
638 				channel.status = ATTACK;
639 				channel.adsrVolume = 0;
640 			}
641 			else
642 			{
643 				if(reader.IsDone())
644 				{
645 					channel.status = STOPPED;
646 					channel.adsrVolume = 0;
647 					reader.ClearIsDone();
648 					//No point in continuing if we don't need to check interrupts
649 					if(!checkIrqs) continue;
650 				}
651 				if(reader.DidChangeRepeat())
652 				{
653 					channel.repeat = reader.GetRepeat();
654 					reader.ClearDidChangeRepeat();
655 				}
656 				//Update repeat in case it has been changed externally (needed for FFX)
657 				reader.SetRepeat(channel.repeat);
658 			}
659 
660 			int16 readSample = 0;
661 			reader.SetPitch(m_baseSamplingRate, channel.pitch);
662 			reader.GetSamples(&readSample, 1, sampleRate);
663 			channel.current = reader.GetCurrent();
664 
665 			if(checkIrqs && reader.GetIrqPending())
666 			{
667 				m_irqPending = true;
668 			}
669 
670 			reader.ClearIrqPending();
671 
672 			//Mix samples
673 			UpdateAdsr(channel);
674 			int32 inputSample = static_cast<int32>(readSample);
675 			//Mix adsrVolume
676 			{
677 				inputSample = (inputSample * static_cast<int32>(channel.adsrVolume >> 16)) / static_cast<int32>(MAX_ADSR_VOLUME >> 16);
678 			}
679 
680 			channel.volumeLeftAbs = ComputeChannelVolume(channel.volumeLeft, channel.volumeLeftAbs);
681 			channel.volumeRightAbs = ComputeChannelVolume(channel.volumeRight, channel.volumeRightAbs);
682 
683 			int32 adjustedLeftVolume = std::min<int32>(0x7FFF, static_cast<int32>(static_cast<float>(channel.volumeLeftAbs >> 16) * m_volumeAdjust));
684 			int32 adjustedRightVolume = std::min<int32>(0x7FFF, static_cast<int32>(static_cast<float>(channel.volumeRightAbs >> 16) * m_volumeAdjust));
685 			MixSamples(inputSample, adjustedLeftVolume, samples + 0);
686 			MixSamples(inputSample, adjustedRightVolume, samples + 1);
687 			//Mix in reverb if enabled for this channel
688 			if(updateReverb && (m_channelReverb.f & (1 << i)))
689 			{
690 				MixSamples(inputSample, adjustedLeftVolume, reverbSample + 0);
691 				MixSamples(inputSample, adjustedRightVolume, reverbSample + 1);
692 			}
693 		}
694 
695 		if(!m_blockReader.CanReadSamples() && (m_blockWritePtr == SOUND_INPUT_DATA_SIZE))
696 		{
697 			//We're ready to consume some data
698 			m_blockReader.FillBlock(m_ram + m_soundInputDataAddr);
699 			m_blockWritePtr = 0;
700 		}
701 
702 		if(m_blockReader.CanReadSamples())
703 		{
704 			int16 sampleL = 0;
705 			int16 sampleR = 0;
706 			m_blockReader.GetSamples(sampleL, sampleR, sampleRate);
707 
708 			MixSamples(sampleL, 0x3FFF, samples + 0);
709 			MixSamples(sampleR, 0x3FFF, samples + 1);
710 		}
711 
712 		//Simulate SPU CORE0 writing its output in RAM and check for potential interrupts
713 		if(m_spuNumber == 0)
714 		{
715 			if(m_irqAddr == (CORE0_OUTPUT_LEFT + m_core0OutputOffset))
716 			{
717 				m_irqPending = true;
718 			}
719 			else if(m_irqAddr == (CORE0_OUTPUT_RIGHT + m_core0OutputOffset))
720 			{
721 				m_irqPending = true;
722 			}
723 			m_core0OutputOffset += 2;
724 			m_core0OutputOffset &= (CORE0_OUTPUT_SIZE - 1);
725 		}
726 
727 		//Update reverb
728 		if(updateReverb)
729 		{
730 			//Feed samples to FIR filter
731 			if(m_reverbTicks & 1)
732 			{
733 				//IIR_INPUT_A0 = buffer[IIR_SRC_A0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L;
734 				//IIR_INPUT_A1 = buffer[IIR_SRC_A1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R;
735 				//IIR_INPUT_B0 = buffer[IIR_SRC_B0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L;
736 				//IIR_INPUT_B1 = buffer[IIR_SRC_B1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R;
737 
738 				float input_sample_l = static_cast<float>(reverbSample[0]) * 0.5f;
739 				float input_sample_r = static_cast<float>(reverbSample[1]) * 0.5f;
740 
741 				float irr_coef = GetReverbCoef(IIR_COEF);
742 				float in_coef_l = GetReverbCoef(IN_COEF_L);
743 				float in_coef_r = GetReverbCoef(IN_COEF_R);
744 
745 				float iir_input_a0 = GetReverbSample(GetReverbOffset(ACC_SRC_A0)) * irr_coef + input_sample_l * in_coef_l;
746 				float iir_input_a1 = GetReverbSample(GetReverbOffset(ACC_SRC_A1)) * irr_coef + input_sample_r * in_coef_r;
747 				float iir_input_b0 = GetReverbSample(GetReverbOffset(ACC_SRC_B0)) * irr_coef + input_sample_l * in_coef_l;
748 				float iir_input_b1 = GetReverbSample(GetReverbOffset(ACC_SRC_B1)) * irr_coef + input_sample_r * in_coef_r;
749 
750 				//IIR_A0 = IIR_INPUT_A0 * IIR_ALPHA + buffer[IIR_DEST_A0] * (1.0 - IIR_ALPHA);
751 				//IIR_A1 = IIR_INPUT_A1 * IIR_ALPHA + buffer[IIR_DEST_A1] * (1.0 - IIR_ALPHA);
752 				//IIR_B0 = IIR_INPUT_B0 * IIR_ALPHA + buffer[IIR_DEST_B0] * (1.0 - IIR_ALPHA);
753 				//IIR_B1 = IIR_INPUT_B1 * IIR_ALPHA + buffer[IIR_DEST_B1] * (1.0 - IIR_ALPHA);
754 
755 				float iir_alpha = GetReverbCoef(IIR_ALPHA);
756 
757 				float iir_a0 = iir_input_a0 * iir_alpha + GetReverbSample(GetReverbOffset(IIR_DEST_A0)) * (1.0f - iir_alpha);
758 				float iir_a1 = iir_input_a1 * iir_alpha + GetReverbSample(GetReverbOffset(IIR_DEST_A1)) * (1.0f - iir_alpha);
759 				float iir_b0 = iir_input_b0 * iir_alpha + GetReverbSample(GetReverbOffset(IIR_DEST_B0)) * (1.0f - iir_alpha);
760 				float iir_b1 = iir_input_b1 * iir_alpha + GetReverbSample(GetReverbOffset(IIR_DEST_B1)) * (1.0f - iir_alpha);
761 
762 				//buffer[IIR_DEST_A0 + 1sample] = IIR_A0;
763 				//buffer[IIR_DEST_A1 + 1sample] = IIR_A1;
764 				//buffer[IIR_DEST_B0 + 1sample] = IIR_B0;
765 				//buffer[IIR_DEST_B1 + 1sample] = IIR_B1;
766 
767 				SetReverbSample(GetReverbOffset(IIR_DEST_A0) + 2, iir_a0);
768 				SetReverbSample(GetReverbOffset(IIR_DEST_A1) + 2, iir_a1);
769 				SetReverbSample(GetReverbOffset(IIR_DEST_B0) + 2, iir_b0);
770 				SetReverbSample(GetReverbOffset(IIR_DEST_B1) + 2, iir_b1);
771 
772 				//ACC0 = buffer[ACC_SRC_A0] * ACC_COEF_A +
773 				//	   buffer[ACC_SRC_B0] * ACC_COEF_B +
774 				//	   buffer[ACC_SRC_C0] * ACC_COEF_C +
775 				//	   buffer[ACC_SRC_D0] * ACC_COEF_D;
776 				//ACC1 = buffer[ACC_SRC_A1] * ACC_COEF_A +
777 				//	   buffer[ACC_SRC_B1] * ACC_COEF_B +
778 				//	   buffer[ACC_SRC_C1] * ACC_COEF_C +
779 				//	   buffer[ACC_SRC_D1] * ACC_COEF_D;
780 
781 				float acc_coef_a = GetReverbCoef(ACC_COEF_A);
782 				float acc_coef_b = GetReverbCoef(ACC_COEF_B);
783 				float acc_coef_c = GetReverbCoef(ACC_COEF_C);
784 				float acc_coef_d = GetReverbCoef(ACC_COEF_D);
785 
786 				float acc0 =
787 				    GetReverbSample(GetReverbOffset(ACC_SRC_A0)) * acc_coef_a +
788 				    GetReverbSample(GetReverbOffset(ACC_SRC_B0)) * acc_coef_b +
789 				    GetReverbSample(GetReverbOffset(ACC_SRC_C0)) * acc_coef_c +
790 				    GetReverbSample(GetReverbOffset(ACC_SRC_D0)) * acc_coef_d;
791 
792 				float acc1 =
793 				    GetReverbSample(GetReverbOffset(ACC_SRC_A1)) * acc_coef_a +
794 				    GetReverbSample(GetReverbOffset(ACC_SRC_B1)) * acc_coef_b +
795 				    GetReverbSample(GetReverbOffset(ACC_SRC_C1)) * acc_coef_c +
796 				    GetReverbSample(GetReverbOffset(ACC_SRC_D1)) * acc_coef_d;
797 
798 				//FB_A0 = buffer[MIX_DEST_A0 - FB_SRC_A];
799 				//FB_A1 = buffer[MIX_DEST_A1 - FB_SRC_A];
800 				//FB_B0 = buffer[MIX_DEST_B0 - FB_SRC_B];
801 				//FB_B1 = buffer[MIX_DEST_B1 - FB_SRC_B];
802 
803 				float fb_a0 = GetReverbSample(GetReverbOffset(MIX_DEST_A0) - GetReverbOffset(FB_SRC_A));
804 				float fb_a1 = GetReverbSample(GetReverbOffset(MIX_DEST_A1) - GetReverbOffset(FB_SRC_A));
805 				float fb_b0 = GetReverbSample(GetReverbOffset(MIX_DEST_B0) - GetReverbOffset(FB_SRC_B));
806 				float fb_b1 = GetReverbSample(GetReverbOffset(MIX_DEST_B1) - GetReverbOffset(FB_SRC_B));
807 
808 				//buffer[MIX_DEST_A0] = ACC0 - FB_A0 * FB_ALPHA;
809 				//buffer[MIX_DEST_A1] = ACC1 - FB_A1 * FB_ALPHA;
810 				//buffer[MIX_DEST_B0] = (FB_ALPHA * ACC0) - FB_A0 * (FB_ALPHA^0x8000) - FB_B0 * FB_X;
811 				//buffer[MIX_DEST_B1] = (FB_ALPHA * ACC1) - FB_A1 * (FB_ALPHA^0x8000) - FB_B1 * FB_X;
812 
813 				float fb_alpha = GetReverbCoef(FB_ALPHA);
814 				float fb_x = GetReverbCoef(FB_X);
815 
816 				SetReverbSample(GetReverbOffset(MIX_DEST_A0), acc0 - fb_a0 * fb_alpha);
817 				SetReverbSample(GetReverbOffset(MIX_DEST_A1), acc1 - fb_a1 * fb_alpha);
818 				SetReverbSample(GetReverbOffset(MIX_DEST_B0), (fb_alpha * acc0) - fb_a0 * -fb_alpha - fb_b0 * fb_x);
819 				SetReverbSample(GetReverbOffset(MIX_DEST_B1), (fb_alpha * acc1) - fb_a1 * -fb_alpha - fb_b1 * fb_x);
820 
821 				m_reverbCurrAddr += 2;
822 				if(m_reverbCurrAddr >= m_reverbWorkAddrEnd)
823 				{
824 					m_reverbCurrAddr = m_reverbWorkAddrStart;
825 				}
826 			}
827 
828 			if(m_reverbWorkAddrStart != 0)
829 			{
830 				float sampleL = 0.333f * (GetReverbSample(GetReverbOffset(MIX_DEST_A0)) + GetReverbSample(GetReverbOffset(MIX_DEST_B0)));
831 				float sampleR = 0.333f * (GetReverbSample(GetReverbOffset(MIX_DEST_A1)) + GetReverbSample(GetReverbOffset(MIX_DEST_B1)));
832 
833 				{
834 					int16* output = samples + 0;
835 					int32 resultSample = static_cast<int32>(sampleL) + static_cast<int32>(*output);
836 					resultSample = std::max<int32>(resultSample, SHRT_MIN);
837 					resultSample = std::min<int32>(resultSample, SHRT_MAX);
838 					*output = static_cast<int16>(resultSample);
839 				}
840 
841 				{
842 					int16* output = samples + 1;
843 					int32 resultSample = static_cast<int32>(sampleR) + static_cast<int32>(*output);
844 					resultSample = std::max<int32>(resultSample, SHRT_MIN);
845 					resultSample = std::min<int32>(resultSample, SHRT_MAX);
846 					*output = static_cast<int16>(resultSample);
847 				}
848 			}
849 
850 			m_reverbTicks++;
851 		}
852 		samples += 2;
853 	}
854 }
855 
GetAdsrDelta(unsigned int index) const856 uint32 CSpuBase::GetAdsrDelta(unsigned int index) const
857 {
858 	return m_adsrLogTable[index + 32];
859 }
860 
GetReverbSample(uint32 address) const861 float CSpuBase::GetReverbSample(uint32 address) const
862 {
863 	uint32 absoluteAddress = m_reverbCurrAddr + address;
864 	while(absoluteAddress >= m_reverbWorkAddrEnd)
865 	{
866 		absoluteAddress -= m_reverbWorkAddrEnd;
867 		absoluteAddress += m_reverbWorkAddrStart;
868 	}
869 	return static_cast<float>(*reinterpret_cast<int16*>(m_ram + absoluteAddress));
870 }
871 
SetReverbSample(uint32 address,float value)872 void CSpuBase::SetReverbSample(uint32 address, float value)
873 {
874 	uint32 absoluteAddress = m_reverbCurrAddr + address;
875 	while(absoluteAddress >= m_reverbWorkAddrEnd)
876 	{
877 		absoluteAddress -= m_reverbWorkAddrEnd;
878 		absoluteAddress += m_reverbWorkAddrStart;
879 	}
880 	value = std::max<float>(value, SHRT_MIN);
881 	value = std::min<float>(value, SHRT_MAX);
882 	int16 intValue = static_cast<int16>(value);
883 	*reinterpret_cast<int16*>(m_ram + absoluteAddress) = intValue;
884 }
885 
GetReverbOffset(unsigned int registerId) const886 uint32 CSpuBase::GetReverbOffset(unsigned int registerId) const
887 {
888 	return m_reverb[registerId];
889 }
890 
GetReverbCoef(unsigned int registerId) const891 float CSpuBase::GetReverbCoef(unsigned int registerId) const
892 {
893 	int16 value = static_cast<int16>(m_reverb[registerId]);
894 	return static_cast<float>(value) / static_cast<float>(0x8000);
895 }
896 
UpdateAdsr(CHANNEL & channel)897 void CSpuBase::UpdateAdsr(CHANNEL& channel)
898 {
899 	static const unsigned int logIndex[8] = {0, 4, 6, 8, 9, 10, 11, 12};
900 	int32 currentAdsrLevel = channel.adsrVolume;
901 	if(channel.status == ATTACK)
902 	{
903 		if(channel.adsrLevel.attackMode == 0)
904 		{
905 			//Linear mode
906 			currentAdsrLevel += GetAdsrDelta((channel.adsrLevel.attackRate ^ 0x7F) - 0x10);
907 		}
908 		else
909 		{
910 			if(currentAdsrLevel < 0x60000000)
911 			{
912 				currentAdsrLevel += GetAdsrDelta((channel.adsrLevel.attackRate ^ 0x7F) - 0x10);
913 			}
914 			else
915 			{
916 				currentAdsrLevel += GetAdsrDelta((channel.adsrLevel.attackRate ^ 0x7F) - 0x18);
917 			}
918 		}
919 		//Terminasion condition
920 		if(currentAdsrLevel < 0)
921 		{
922 			currentAdsrLevel = MAX_ADSR_VOLUME;
923 			channel.status = DECAY;
924 		}
925 	}
926 	else if(channel.status == DECAY)
927 	{
928 		unsigned int decayType = (static_cast<uint32>(currentAdsrLevel) >> 28) & 0x7;
929 		currentAdsrLevel -= GetAdsrDelta((4 * (channel.adsrLevel.decayRate ^ 0x1F)) - 0x18 + logIndex[decayType]);
930 		//Terminasion condition
931 		if(static_cast<unsigned int>((currentAdsrLevel >> 27) & 0xF) <= channel.adsrLevel.sustainLevel)
932 		{
933 			channel.status = SUSTAIN;
934 		}
935 	}
936 	else if(channel.status == SUSTAIN)
937 	{
938 		if(channel.adsrRate.sustainDirection == 0)
939 		{
940 			//Increment
941 			if(channel.adsrRate.sustainMode == 0)
942 			{
943 				currentAdsrLevel += GetAdsrDelta((channel.adsrRate.sustainRate ^ 0x7F) - 0x10);
944 			}
945 			else
946 			{
947 				if(currentAdsrLevel < 0x60000000)
948 				{
949 					currentAdsrLevel += GetAdsrDelta((channel.adsrRate.sustainRate ^ 0x7F) - 0x10);
950 				}
951 				else
952 				{
953 					currentAdsrLevel += GetAdsrDelta((channel.adsrRate.sustainRate ^ 0x7F) - 0x18);
954 				}
955 			}
956 
957 			if(currentAdsrLevel < 0)
958 			{
959 				currentAdsrLevel = MAX_ADSR_VOLUME;
960 			}
961 		}
962 		else
963 		{
964 			//Decrement
965 			if(channel.adsrRate.sustainMode == 0)
966 			{
967 				//Linear
968 				currentAdsrLevel -= GetAdsrDelta((channel.adsrRate.sustainRate ^ 0x7F) - 0x0F);
969 			}
970 			else
971 			{
972 				unsigned int sustainType = (static_cast<uint32>(currentAdsrLevel) >> 28) & 0x7;
973 				currentAdsrLevel -= GetAdsrDelta((channel.adsrRate.sustainRate ^ 0x7F) - 0x1B + logIndex[sustainType]);
974 			}
975 
976 			if(currentAdsrLevel < 0)
977 			{
978 				currentAdsrLevel = 0;
979 			}
980 		}
981 	}
982 	else if(channel.status == RELEASE)
983 	{
984 		if(channel.adsrRate.releaseMode == 0)
985 		{
986 			//Linear
987 			currentAdsrLevel -= GetAdsrDelta((4 * (channel.adsrRate.releaseRate ^ 0x1F)) - 0x0C);
988 		}
989 		else
990 		{
991 			unsigned int releaseType = (static_cast<uint32>(currentAdsrLevel) >> 28) & 0x7;
992 			currentAdsrLevel -= GetAdsrDelta((4 * (channel.adsrRate.releaseRate ^ 0x1F)) - 0x18 + logIndex[releaseType]);
993 		}
994 
995 		if(currentAdsrLevel < 0)
996 		{
997 			currentAdsrLevel = 0;
998 			channel.status = STOPPED;
999 		}
1000 	}
1001 	channel.adsrVolume = static_cast<uint32>(currentAdsrLevel);
1002 }
1003 
1004 ///////////////////////////////////////////////////////
1005 // CSampleReader
1006 ///////////////////////////////////////////////////////
1007 
CSampleReader()1008 CSpuBase::CSampleReader::CSampleReader()
1009 {
1010 	Reset();
1011 }
1012 
Reset()1013 void CSpuBase::CSampleReader::Reset()
1014 {
1015 	m_nextSampleAddr = 0;
1016 	m_repeatAddr = 0;
1017 	m_irqAddr = INVALID_ADDRESS;
1018 	memset(m_buffer, 0, sizeof(m_buffer));
1019 	m_pitch = 0;
1020 	m_srcSampleIdx = 0;
1021 	m_srcSamplingRate = 0;
1022 	m_s1 = 0;
1023 	m_s2 = 0;
1024 	m_done = false;
1025 	m_didChangeRepeat = false;
1026 	m_nextValid = false;
1027 	m_endFlag = false;
1028 	m_irqPending = false;
1029 }
1030 
SetMemory(uint8 * ram,uint32 ramSize)1031 void CSpuBase::CSampleReader::SetMemory(uint8* ram, uint32 ramSize)
1032 {
1033 	m_ram = ram;
1034 	m_ramSize = ramSize;
1035 	assert((ramSize & (ramSize - 1)) == 0);
1036 }
1037 
LoadState(const CRegisterStateFile & registerFile,const std::string & channelPrefix)1038 void CSpuBase::CSampleReader::LoadState(const CRegisterStateFile& registerFile, const std::string& channelPrefix)
1039 {
1040 	m_srcSampleIdx = registerFile.GetRegister32((channelPrefix + STATE_SAMPLEREADER_REGS_SRCSAMPLEIDX).c_str());
1041 	m_srcSamplingRate = registerFile.GetRegister32((channelPrefix + STATE_SAMPLEREADER_REGS_SRCSAMPLINGRATE).c_str());
1042 	m_nextSampleAddr = registerFile.GetRegister32((channelPrefix + STATE_SAMPLEREADER_REGS_NEXTSAMPLEADDR).c_str());
1043 	m_repeatAddr = registerFile.GetRegister32((channelPrefix + STATE_SAMPLEREADER_REGS_REPEATADDR).c_str());
1044 	m_irqAddr = registerFile.GetRegister32((channelPrefix + STATE_SAMPLEREADER_REGS_IRQADDR).c_str());
1045 	m_pitch = registerFile.GetRegister32((channelPrefix + STATE_SAMPLEREADER_REGS_PITCH).c_str());
1046 	m_s1 = registerFile.GetRegister32((channelPrefix + STATE_SAMPLEREADER_REGS_S1).c_str());
1047 	m_s2 = registerFile.GetRegister32((channelPrefix + STATE_SAMPLEREADER_REGS_S2).c_str());
1048 	m_done = registerFile.GetRegister32((channelPrefix + STATE_SAMPLEREADER_REGS_DONE).c_str()) != 0;
1049 	m_nextValid = registerFile.GetRegister32((channelPrefix + STATE_SAMPLEREADER_REGS_NEXTVALID).c_str()) != 0;
1050 	m_endFlag = registerFile.GetRegister32((channelPrefix + STATE_SAMPLEREADER_REGS_ENDFLAG).c_str()) != 0;
1051 	m_irqPending = registerFile.GetRegister32((channelPrefix + STATE_SAMPLEREADER_REGS_IRQPENDING).c_str()) != 0;
1052 	m_didChangeRepeat = registerFile.GetRegister32((channelPrefix + STATE_SAMPLEREADER_REGS_DIDCHANGEREPEAT).c_str()) != 0;
1053 
1054 	static const uint32 bufferRegisterCount = sizeof(m_buffer) / sizeof(uint128);
1055 	for(uint32 i = 0; i < bufferRegisterCount; i++)
1056 	{
1057 		auto bufferRegisterName = string_format(STATE_SAMPLEREADER_REGS_BUFFER_FORMAT, channelPrefix.c_str(), i);
1058 		reinterpret_cast<uint128*>(m_buffer)[i] = registerFile.GetRegister128(bufferRegisterName.c_str());
1059 	}
1060 }
1061 
SaveState(CRegisterStateFile * registerFile,const std::string & channelPrefix) const1062 void CSpuBase::CSampleReader::SaveState(CRegisterStateFile* registerFile, const std::string& channelPrefix) const
1063 {
1064 	registerFile->SetRegister32((channelPrefix + STATE_SAMPLEREADER_REGS_SRCSAMPLEIDX).c_str(), m_srcSampleIdx);
1065 	registerFile->SetRegister32((channelPrefix + STATE_SAMPLEREADER_REGS_SRCSAMPLINGRATE).c_str(), m_srcSamplingRate);
1066 	registerFile->SetRegister32((channelPrefix + STATE_SAMPLEREADER_REGS_NEXTSAMPLEADDR).c_str(), m_nextSampleAddr);
1067 	registerFile->SetRegister32((channelPrefix + STATE_SAMPLEREADER_REGS_REPEATADDR).c_str(), m_repeatAddr);
1068 	registerFile->SetRegister32((channelPrefix + STATE_SAMPLEREADER_REGS_IRQADDR).c_str(), m_irqAddr);
1069 	registerFile->SetRegister32((channelPrefix + STATE_SAMPLEREADER_REGS_PITCH).c_str(), m_pitch);
1070 	registerFile->SetRegister32((channelPrefix + STATE_SAMPLEREADER_REGS_S1).c_str(), m_s1);
1071 	registerFile->SetRegister32((channelPrefix + STATE_SAMPLEREADER_REGS_S2).c_str(), m_s2);
1072 	registerFile->SetRegister32((channelPrefix + STATE_SAMPLEREADER_REGS_DONE).c_str(), m_done);
1073 	registerFile->SetRegister32((channelPrefix + STATE_SAMPLEREADER_REGS_NEXTVALID).c_str(), m_nextValid);
1074 	registerFile->SetRegister32((channelPrefix + STATE_SAMPLEREADER_REGS_ENDFLAG).c_str(), m_endFlag);
1075 	registerFile->SetRegister32((channelPrefix + STATE_SAMPLEREADER_REGS_IRQPENDING).c_str(), m_irqPending);
1076 	registerFile->SetRegister32((channelPrefix + STATE_SAMPLEREADER_REGS_DIDCHANGEREPEAT).c_str(), m_didChangeRepeat);
1077 
1078 	static const uint32 bufferRegisterCount = sizeof(m_buffer) / sizeof(uint128);
1079 	for(uint32 i = 0; i < bufferRegisterCount; i++)
1080 	{
1081 		auto bufferRegisterName = string_format(STATE_SAMPLEREADER_REGS_BUFFER_FORMAT, channelPrefix.c_str(), i);
1082 		registerFile->SetRegister128(bufferRegisterName.c_str(), reinterpret_cast<const uint128*>(m_buffer)[i]);
1083 	}
1084 }
1085 
SetParams(uint32 address,uint32 repeat)1086 void CSpuBase::CSampleReader::SetParams(uint32 address, uint32 repeat)
1087 {
1088 	m_srcSampleIdx = 0;
1089 	m_nextSampleAddr = address;
1090 	m_repeatAddr = repeat;
1091 	m_s1 = 0;
1092 	m_s2 = 0;
1093 	m_nextValid = false;
1094 	m_done = false;
1095 	m_didChangeRepeat = false;
1096 }
1097 
SetParamsRead(uint32 address,uint32 repeat)1098 void CSpuBase::CSampleReader::SetParamsRead(uint32 address, uint32 repeat)
1099 {
1100 	SetParams(address, repeat);
1101 	AdvanceBuffer();
1102 }
1103 
SetParamsNoRead(uint32 address,uint32 repeat)1104 void CSpuBase::CSampleReader::SetParamsNoRead(uint32 address, uint32 repeat)
1105 {
1106 	SetParams(address, repeat);
1107 	memset(m_buffer, 0, sizeof(m_buffer));
1108 }
1109 
SetPitch(uint32 baseSamplingRate,uint16 pitch)1110 void CSpuBase::CSampleReader::SetPitch(uint32 baseSamplingRate, uint16 pitch)
1111 {
1112 	m_srcSamplingRate = baseSamplingRate * pitch / 4096;
1113 }
1114 
GetSamples(int16 * samples,unsigned int sampleCount,unsigned int dstSamplingRate)1115 void CSpuBase::CSampleReader::GetSamples(int16* samples, unsigned int sampleCount, unsigned int dstSamplingRate)
1116 {
1117 	for(unsigned int i = 0; i < sampleCount; i++)
1118 	{
1119 		samples[i] = GetSample(dstSamplingRate);
1120 	}
1121 }
1122 
GetSample(unsigned int dstSamplingRate)1123 int16 CSpuBase::CSampleReader::GetSample(unsigned int dstSamplingRate)
1124 {
1125 	uint32 srcSampleIdx = m_srcSampleIdx / TIME_SCALE;
1126 	int32 srcSampleAlpha = m_srcSampleIdx % TIME_SCALE;
1127 	int32 currentSample = m_buffer[srcSampleIdx];
1128 	int32 nextSample = m_buffer[srcSampleIdx + 1];
1129 	int32 resultSample = (currentSample * (TIME_SCALE - srcSampleAlpha) / TIME_SCALE) +
1130 	                     (nextSample * srcSampleAlpha / TIME_SCALE);
1131 	m_srcSampleIdx += (m_srcSamplingRate * TIME_SCALE) / dstSamplingRate;
1132 	if(srcSampleIdx >= BUFFER_SAMPLES)
1133 	{
1134 		m_srcSampleIdx -= BUFFER_SAMPLES * TIME_SCALE;
1135 		AdvanceBuffer();
1136 	}
1137 	return static_cast<int16>(resultSample);
1138 }
1139 
AdvanceBuffer()1140 void CSpuBase::CSampleReader::AdvanceBuffer()
1141 {
1142 	if(m_nextValid)
1143 	{
1144 		memmove(m_buffer, m_buffer + BUFFER_SAMPLES, sizeof(int16) * BUFFER_SAMPLES);
1145 		UnpackSamples(m_buffer + BUFFER_SAMPLES);
1146 	}
1147 	else
1148 	{
1149 		UnpackSamples(m_buffer);
1150 		UnpackSamples(m_buffer + BUFFER_SAMPLES);
1151 		m_nextValid = true;
1152 	}
1153 }
1154 
UnpackSamples(int16 * dst)1155 void CSpuBase::CSampleReader::UnpackSamples(int16* dst)
1156 {
1157 	int32 workBuffer[BUFFER_SAMPLES];
1158 
1159 	uint8* nextSample = m_ram + m_nextSampleAddr;
1160 
1161 	if(m_nextSampleAddr == m_irqAddr)
1162 	{
1163 		m_irqPending = true;
1164 	}
1165 
1166 	//Read header
1167 	uint8 shiftFactor = nextSample[0] & 0xF;
1168 	uint8 predictNumber = nextSample[0] >> 4;
1169 	uint8 flags = nextSample[1];
1170 	assert(predictNumber < 5);
1171 
1172 	//Get intermediate values
1173 	{
1174 		unsigned int workBufferPtr = 0;
1175 		for(unsigned int i = 2; i < 16; i++)
1176 		{
1177 			uint8 sampleByte = nextSample[i];
1178 			int16 firstSample = ((sampleByte & 0x0F) << 12);
1179 			int16 secondSample = ((sampleByte & 0xF0) << 8);
1180 			firstSample >>= shiftFactor;
1181 			secondSample >>= shiftFactor;
1182 			workBuffer[workBufferPtr++] = firstSample;
1183 			workBuffer[workBufferPtr++] = secondSample;
1184 		}
1185 	}
1186 
1187 	//Generate PCM samples
1188 	{
1189 		// clang-format off
1190 		//Table is 16 entries long to prevent reading indeterminate
1191 		//values if predictNumber is greater or equal to 5.
1192 		//According to some sources, entries at 5 and beyond contain 0 on real hardware
1193 		static const int32 predictorTable[16][2] =
1194 		{
1195 			{0, 0},
1196 			{60, 0},
1197 			{115, -52},
1198 			{98, -55},
1199 			{122, -60},
1200 		};
1201 		// clang-format on
1202 
1203 		for(unsigned int i = 0; i < BUFFER_SAMPLES; i++)
1204 		{
1205 			int32 currentValue = workBuffer[i] * 64;
1206 			currentValue += (m_s1 * predictorTable[predictNumber][0]) / 64;
1207 			currentValue += (m_s2 * predictorTable[predictNumber][1]) / 64;
1208 			m_s2 = m_s1;
1209 			m_s1 = currentValue;
1210 			int32 result = (currentValue + 32) / 64;
1211 			result = std::max<int32>(result, SHRT_MIN);
1212 			result = std::min<int32>(result, SHRT_MAX);
1213 			dst[i] = static_cast<int16>(result);
1214 		}
1215 	}
1216 
1217 	if(flags & 0x04)
1218 	{
1219 		m_repeatAddr = m_nextSampleAddr;
1220 		m_didChangeRepeat = true;
1221 	}
1222 
1223 	m_nextSampleAddr += 0x10;
1224 	assert(m_nextSampleAddr < m_ramSize);
1225 	m_nextSampleAddr &= (m_ramSize - 1);
1226 
1227 	if(flags & 0x01)
1228 	{
1229 		m_endFlag = true;
1230 		m_nextSampleAddr = m_repeatAddr;
1231 
1232 		//If flags is in { 0x01, 0x05, 0x07 }, mute channel (Xenogears requires that)
1233 		if(flags != 0x03)
1234 		{
1235 			m_done = true;
1236 		}
1237 	}
1238 }
1239 
GetRepeat() const1240 uint32 CSpuBase::CSampleReader::GetRepeat() const
1241 {
1242 	return m_repeatAddr;
1243 }
1244 
SetRepeat(uint32 repeatAddr)1245 void CSpuBase::CSampleReader::SetRepeat(uint32 repeatAddr)
1246 {
1247 	m_repeatAddr = repeatAddr;
1248 }
1249 
GetCurrent() const1250 uint32 CSpuBase::CSampleReader::GetCurrent() const
1251 {
1252 	return m_nextSampleAddr;
1253 }
1254 
SetIrqAddress(uint32 irqAddr)1255 void CSpuBase::CSampleReader::SetIrqAddress(uint32 irqAddr)
1256 {
1257 	m_irqAddr = irqAddr;
1258 }
1259 
IsDone() const1260 bool CSpuBase::CSampleReader::IsDone() const
1261 {
1262 	return m_done;
1263 }
1264 
ClearIsDone()1265 void CSpuBase::CSampleReader::ClearIsDone()
1266 {
1267 	m_done = false;
1268 }
1269 
GetEndFlag() const1270 bool CSpuBase::CSampleReader::GetEndFlag() const
1271 {
1272 	return m_endFlag;
1273 }
1274 
ClearEndFlag()1275 void CSpuBase::CSampleReader::ClearEndFlag()
1276 {
1277 	m_endFlag = false;
1278 }
1279 
GetIrqPending() const1280 bool CSpuBase::CSampleReader::GetIrqPending() const
1281 {
1282 	return m_irqPending;
1283 }
1284 
ClearIrqPending()1285 void CSpuBase::CSampleReader::ClearIrqPending()
1286 {
1287 	m_irqPending = false;
1288 }
1289 
DidChangeRepeat() const1290 bool CSpuBase::CSampleReader::DidChangeRepeat() const
1291 {
1292 	return m_didChangeRepeat;
1293 }
1294 
ClearDidChangeRepeat()1295 void CSpuBase::CSampleReader::ClearDidChangeRepeat()
1296 {
1297 	m_didChangeRepeat = false;
1298 }
1299 
1300 ///////////////////////////////////////////////////////
1301 // CBlockSampleReader
1302 ///////////////////////////////////////////////////////
1303 
Reset()1304 void CSpuBase::CBlockSampleReader::Reset()
1305 {
1306 	m_srcSampleIdx = SOUND_INPUT_DATA_SAMPLES * TIME_SCALE;
1307 }
1308 
CanReadSamples() const1309 bool CSpuBase::CBlockSampleReader::CanReadSamples() const
1310 {
1311 	uint32 sampleIdx = (m_srcSampleIdx / TIME_SCALE);
1312 	return (sampleIdx < SOUND_INPUT_DATA_SAMPLES);
1313 }
1314 
FillBlock(const uint8 * block)1315 void CSpuBase::CBlockSampleReader::FillBlock(const uint8* block)
1316 {
1317 	memcpy(m_blockBuffer, block, SOUND_INPUT_DATA_SIZE);
1318 	m_srcSampleIdx = 0;
1319 }
1320 
GetSamples(int16 & sampleL,int16 & sampleR,unsigned int dstSamplingRate)1321 void CSpuBase::CBlockSampleReader::GetSamples(int16& sampleL, int16& sampleR, unsigned int dstSamplingRate)
1322 {
1323 	uint32 srcSampleIdx = m_srcSampleIdx / TIME_SCALE;
1324 	int32 srcSampleAlpha = m_srcSampleIdx % TIME_SCALE;
1325 	assert(srcSampleIdx < SOUND_INPUT_DATA_SAMPLES);
1326 
1327 	auto inputSamples = reinterpret_cast<const int16*>(m_blockBuffer);
1328 	sampleL = inputSamples[0x000 + srcSampleIdx];
1329 	sampleR = inputSamples[0x100 + srcSampleIdx];
1330 
1331 	m_srcSampleIdx += (SRC_SAMPLING_RATE * TIME_SCALE) / dstSamplingRate;
1332 }
1333