Skip to content

Commit 3b07d28

Browse files
committed
Cocoa Port: Major refactor to replace the Obj-C class CocoaDSOutput with the C++ class ClientEmulationOutput.
- Also replace more color-related data types from the generic uint32_t type to the more specific Color4u8 type.
1 parent 1638bc0 commit 3b07d28

39 files changed

+4933
-3796
lines changed
Lines changed: 322 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,322 @@
1+
/*
2+
Copyright (C) 2025 DeSmuME team
3+
4+
This file 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 2 of the License, or
7+
(at your option) any later version.
8+
9+
This file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
#include "ClientAudioOutput.h"
19+
20+
#include "ClientExecutionControl.h"
21+
#include "cocoa_globals.h"
22+
23+
#include "../../NDSSystem.h"
24+
25+
ClientAudioOutput::ClientAudioOutput()
26+
{
27+
_platformId = PlatformTypeID_Any;
28+
_typeId = OutputTypeID_Generic | OutputTypeID_Audio;
29+
30+
_volume = MAX_VOLUME;
31+
_engineID = 0;
32+
_spuAdvancedLogic = true;
33+
_interpolationModeID = SPUInterpolation_Cosine;
34+
_syncModeID = ESynchMode_Synchronous;
35+
_syncMethodID = ESynchMethod_N;
36+
_isMuted = false;
37+
_filterID = 0;
38+
39+
_engineString = "None";
40+
_spuInterpolationModeString = "Cosine";
41+
_spuSyncMethodString = "N";
42+
43+
pthread_mutex_init(&_mutexEngine, NULL);
44+
pthread_mutex_init(&_mutexVolume, NULL);
45+
pthread_mutex_init(&_mutexSpuAdvancedLogic, NULL);
46+
pthread_mutex_init(&_mutexSpuInterpolationMode, NULL);
47+
pthread_mutex_init(&_mutexSpuSyncMethod, NULL);
48+
}
49+
50+
ClientAudioOutput::~ClientAudioOutput()
51+
{
52+
pthread_mutex_destroy(&this->_mutexEngine);
53+
pthread_mutex_destroy(&this->_mutexVolume);
54+
pthread_mutex_destroy(&this->_mutexSpuAdvancedLogic);
55+
pthread_mutex_destroy(&this->_mutexSpuInterpolationMode);
56+
pthread_mutex_destroy(&this->_mutexSpuSyncMethod);
57+
}
58+
59+
void ClientAudioOutput::SetEngineByID(int engineID)
60+
{
61+
pthread_mutex_lock(&this->_mutexEngine);
62+
this->_engineID = engineID;
63+
pthread_mutex_unlock(&this->_mutexEngine);
64+
65+
int result = -1;
66+
67+
pthread_rwlock_wrlock(this->_rwlockProducer);
68+
69+
if (engineID != SNDCORE_DUMMY)
70+
{
71+
result = SPU_ChangeSoundCore(engineID, (int)SPU_BUFFER_BYTES);
72+
}
73+
74+
if (result == -1)
75+
{
76+
SPU_ChangeSoundCore(SNDCORE_DUMMY, 0);
77+
}
78+
79+
SoundInterface_struct *soundCore = SPU_SoundCore();
80+
if (soundCore != NULL)
81+
{
82+
this->_engineString = soundCore->Name;
83+
}
84+
85+
pthread_rwlock_unlock(this->_rwlockProducer);
86+
87+
pthread_mutex_lock(&this->_mutexVolume);
88+
89+
if (!this->_isMuted)
90+
{
91+
SPU_SetVolume((int)(this->_volume + 0.5f));
92+
}
93+
94+
pthread_mutex_unlock(&this->_mutexVolume);
95+
}
96+
97+
int ClientAudioOutput::GetEngineByID()
98+
{
99+
return this->_engineID;
100+
}
101+
102+
void ClientAudioOutput::SetVolume(float vol)
103+
{
104+
if (vol < 0.0f)
105+
{
106+
vol = 0.0f;
107+
}
108+
else if (vol > MAX_VOLUME)
109+
{
110+
vol = MAX_VOLUME;
111+
}
112+
113+
pthread_mutex_lock(&this->_mutexVolume);
114+
115+
this->_volume = vol;
116+
117+
if (!this->_isMuted)
118+
{
119+
SPU_SetVolume((int)(vol + 0.5f));
120+
}
121+
122+
pthread_mutex_unlock(&this->_mutexVolume);
123+
}
124+
125+
float ClientAudioOutput::GetVolume()
126+
{
127+
pthread_mutex_lock(&this->_mutexVolume);
128+
const float vol = this->_volume;
129+
pthread_mutex_unlock(&this->_mutexVolume);
130+
131+
return vol;
132+
}
133+
134+
void ClientAudioOutput::SetSPUAdvancedLogic(bool theState)
135+
{
136+
pthread_mutex_lock(&this->_mutexSpuAdvancedLogic);
137+
this->_spuAdvancedLogic = theState;
138+
pthread_mutex_unlock(&this->_mutexSpuAdvancedLogic);
139+
140+
pthread_rwlock_wrlock(this->_rwlockProducer);
141+
CommonSettings.spu_advanced = theState;
142+
pthread_rwlock_unlock(this->_rwlockProducer);
143+
}
144+
145+
bool ClientAudioOutput::GetSPUAdvancedLogic()
146+
{
147+
return this->_spuAdvancedLogic;
148+
}
149+
150+
void ClientAudioOutput::SetSPUInterpolationModeByID(SPUInterpolationMode interpModeID)
151+
{
152+
pthread_mutex_lock(&this->_mutexSpuInterpolationMode);
153+
this->_interpolationModeID = interpModeID;
154+
pthread_mutex_unlock(&this->_mutexSpuInterpolationMode);
155+
156+
pthread_rwlock_wrlock(this->_rwlockProducer);
157+
CommonSettings.spuInterpolationMode = interpModeID;
158+
pthread_rwlock_unlock(this->_rwlockProducer);
159+
160+
switch (interpModeID)
161+
{
162+
case SPUInterpolation_None:
163+
this->_spuInterpolationModeString = "None";
164+
break;
165+
166+
case SPUInterpolation_Linear:
167+
this->_spuInterpolationModeString = "Linear";
168+
break;
169+
170+
case SPUInterpolation_Cosine:
171+
this->_spuInterpolationModeString = "Cosine";
172+
break;
173+
174+
case SPUInterpolation_CatmullRom:
175+
this->_spuInterpolationModeString = "Catmull-Rom";
176+
break;
177+
178+
default:
179+
break;
180+
}
181+
}
182+
183+
SPUInterpolationMode ClientAudioOutput::GetSPUInterpolationModeByID()
184+
{
185+
return this->_interpolationModeID;
186+
}
187+
188+
void ClientAudioOutput::SetSPUSyncModeByID(ESynchMode syncModeID)
189+
{
190+
pthread_mutex_lock(&this->_mutexSpuSyncMethod);
191+
this->_syncModeID = syncModeID;
192+
pthread_mutex_unlock(&this->_mutexSpuSyncMethod);
193+
194+
pthread_rwlock_wrlock(this->_rwlockProducer);
195+
CommonSettings.SPU_sync_mode = syncModeID;
196+
SPU_SetSynchMode(CommonSettings.SPU_sync_mode, CommonSettings.SPU_sync_method);
197+
pthread_rwlock_unlock(this->_rwlockProducer);
198+
199+
if (syncModeID == ESynchMode_DualSynchAsynch)
200+
{
201+
this->_spuSyncMethodString = "Dual SPU Sync/Async";
202+
}
203+
else
204+
{
205+
switch (this->_syncMethodID)
206+
{
207+
case ESynchMethod_N:
208+
this->_spuSyncMethodString = "\"N\" Sync Method";
209+
break;
210+
211+
case ESynchMethod_Z:
212+
this->_spuSyncMethodString = "\"Z\" Sync Method";
213+
break;
214+
215+
case ESynchMethod_P:
216+
this->_spuSyncMethodString = "\"P\" Sync Method";
217+
break;
218+
219+
default:
220+
break;
221+
}
222+
}
223+
}
224+
225+
ESynchMode ClientAudioOutput::GetSPUSyncModeByID()
226+
{
227+
return this->_syncModeID;
228+
}
229+
230+
void ClientAudioOutput::SetSPUSyncMethodByID(ESynchMethod syncMethodID)
231+
{
232+
pthread_mutex_lock(&this->_mutexSpuSyncMethod);
233+
this->_syncMethodID = syncMethodID;
234+
pthread_mutex_unlock(&this->_mutexSpuSyncMethod);
235+
236+
pthread_rwlock_wrlock(this->_rwlockProducer);
237+
CommonSettings.SPU_sync_method = syncMethodID;
238+
SPU_SetSynchMode(CommonSettings.SPU_sync_mode, CommonSettings.SPU_sync_method);
239+
pthread_rwlock_unlock(this->_rwlockProducer);
240+
241+
if (this->_syncModeID == ESynchMode_DualSynchAsynch)
242+
{
243+
this->_spuInterpolationModeString = "Dual SPU Sync/Async";
244+
}
245+
else
246+
{
247+
switch (syncMethodID)
248+
{
249+
case ESynchMethod_N:
250+
this->_spuSyncMethodString = "\"N\" Sync Method";
251+
break;
252+
253+
case ESynchMethod_Z:
254+
this->_spuSyncMethodString = "\"Z\" Sync Method";
255+
break;
256+
257+
case ESynchMethod_P:
258+
this->_spuSyncMethodString = "\"P\" Sync Method";
259+
break;
260+
261+
default:
262+
break;
263+
}
264+
}
265+
}
266+
267+
ESynchMethod ClientAudioOutput::GetSPUSyncMethodByID()
268+
{
269+
return this->_syncMethodID;
270+
}
271+
272+
void ClientAudioOutput::SetMute(bool theState)
273+
{
274+
pthread_mutex_lock(&this->_mutexVolume);
275+
276+
this->_isMuted = theState;
277+
278+
if (theState)
279+
{
280+
SPU_SetVolume(0);
281+
}
282+
else
283+
{
284+
SPU_SetVolume((int)(this->_volume + 0.5f));
285+
}
286+
287+
pthread_mutex_unlock(&this->_mutexVolume);
288+
}
289+
290+
bool ClientAudioOutput::IsMuted()
291+
{
292+
pthread_mutex_lock(&this->_mutexVolume);
293+
const bool isMuted = this->_isMuted;
294+
pthread_mutex_unlock(&this->_mutexVolume);
295+
296+
return isMuted;
297+
}
298+
299+
void ClientAudioOutput::SetFilterByID(int filterID)
300+
{
301+
this->_filterID = filterID;
302+
}
303+
304+
int ClientAudioOutput::GetFilterByID()
305+
{
306+
return this->_filterID;
307+
}
308+
309+
const char* ClientAudioOutput::GetEngineString()
310+
{
311+
return this->_engineString.c_str();
312+
}
313+
314+
const char* ClientAudioOutput::GetSPUInterpolationModeString()
315+
{
316+
return this->_spuInterpolationModeString.c_str();
317+
}
318+
319+
const char* ClientAudioOutput::GetSPUSyncMethodString()
320+
{
321+
return this->_spuSyncMethodString.c_str();
322+
}

0 commit comments

Comments
 (0)