comparison src/xs_sidplayfp.cpp @ 835:d508c7c4bc69

Add libSIDPlay2-FP backend interface module.
author Matti Hamalainen <ccr@tnsp.org>
date Thu, 08 Nov 2012 20:47:49 +0200
parents
children ae1f6418d093
comparison
equal deleted inserted replaced
834:a7ee5dc23e78 835:d508c7c4bc69
1 /*
2 XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS)
3
4 libSIDPlay v2-FP support
5
6 Programmed and designed by Matti 'ccr' Hamalainen <ccr@tnsp.org>
7 (C) Copyright 1999-2012 Tecnic Software productions (TNSP)
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License along
20 with this program; if not, write to the Free Software Foundation, Inc.,
21 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 */
23 #include "xmms-sid.h"
24
25 #ifdef HAVE_SIDPLAY2_FP
26
27 #include <stdio.h>
28 #include "xs_sidplay2.h"
29 #include "xs_config.h"
30
31
32 #ifdef HAVE_SIDPLAY2_FP_V1
33 # include <sidplayfp/SidTune.h>
34 # include <sidplayfp/sidplayfp.h>
35 # include <sidplayfp/event.h>
36 # include <sidplayfp/SidConfig.h>
37 # include <sidplayfp/SidTuneInfo.h>
38 #else
39 # include <sidplayfp/sidplay2.h>
40 # include <sidplayfp/SidTuneMod.h>
41 # include <sidplayfp/event.h>
42 #endif
43
44
45 class XSSIDPlayFP {
46 public:
47 #ifdef HAVE_SIDPLAY2_FP_V1
48 sidplayfp emu;
49 SidConfig config;
50 #else
51 sidplay2 emu;
52 sid2_config_t config;
53 #endif
54 SidTune tune;
55
56 XSSIDPlayFP(void);
57 virtual ~XSSIDPlayFP(void);
58 };
59
60
61 #ifdef HAVE_RESID_BUILDER
62 # include <sidplayfp/builders/residfp.h>
63 # include <sidplayfp/builders/resid.h>
64 #endif
65
66 #ifdef HAVE_HARDSID_BUILDER
67 # include <sidplayfp/builders/hardsid.h>
68 #endif
69
70
71 XSSIDPlayFP::XSSIDPlayFP(void) : tune(0)
72 {
73 }
74
75
76 XSSIDPlayFP::~XSSIDPlayFP(void)
77 {
78 emu.load(NULL);
79 }
80
81
82 /* We need to 'export' all this pseudo-C++ crap */
83 extern "C" {
84
85
86 /* Return song information
87 */
88 #define TFUNCTION xs_sidplayfp_getinfo
89 #define TFUNCTION2 xs_sidplayfp_updateinfo
90 #define TENGINE XSSIDPlayFP
91 #define TTUNEINFO SidTuneInfo
92 #define TTUNE SidTune
93
94 #ifdef HAVE_SIDPLAY2_FP_V1
95 #define sid2_mono SidConfig::MONO
96 #define sid2_stereo SidConfig::STEREO
97 #define SID2_MOS8580 SidConfig::MOS8580
98 #define SID2_MOS6581 SidConfig::MOS6581
99 #define SID2_CLOCK_PAL SidConfig::CLOCK_PAL
100 #define SID2_CLOCK_NTSC SidConfig::CLOCK_NTSC
101 #define SIDTUNE_CLOCK_UNKNOWN SidTuneInfo::CLOCK_UNKNOWN
102 #define SIDTUNE_CLOCK_PAL SidTuneInfo::CLOCK_PAL
103 #define SIDTUNE_CLOCK_NTSC SidTuneInfo::CLOCK_NTSC
104 #define SIDTUNE_CLOCK_ANY SidTuneInfo::CLOCK_ANY
105 #define SIDTUNE_SPEED_VBI SidTuneInfo::SPEED_VBI
106 #define SIDTUNE_SPEED_CIA_1A SidTuneInfo::SPEED_CIA_1A
107 #endif
108
109 #include "xs_sidplay.h"
110
111
112 /* Check if we can play the given file
113 */
114 gboolean xs_sidplayfp_probe(XSFile *f)
115 {
116 gchar tmpBuf[5];
117
118 if (!f) return FALSE;
119
120 if (xs_fread(tmpBuf, sizeof(gchar), 4, f) != 4)
121 return FALSE;
122
123 if (!strncmp(tmpBuf, "PSID", 4) || !strncmp(tmpBuf, "RSID", 4))
124 return TRUE;
125 else
126 return FALSE;
127 }
128
129
130 /* Initialize SIDPlay2
131 */
132 gboolean xs_sidplayfp_init(XSEngineState * state)
133 {
134 XSSIDPlayFP *engine;
135 assert(state);
136
137 /* Allocate internal structures */
138 engine = new XSSIDPlayFP();
139 state->internal = engine;
140 if (!engine)
141 return FALSE;
142
143 /* Get current configuration */
144 engine->config = engine->emu.config();
145
146 /* Configure channels and stuff */
147 engine->config.playback = (state->audioChannels == XS_CHN_MONO) ? sid2_mono : sid2_stereo;
148
149 /* Audio parameters sanity checking and setup */
150 state->audioBitsPerSample = XS_RES_16BIT;
151 engine->config.samplingMethod = SID2_RESAMPLE_INTERPOLATE;
152 engine->config.frequency = state->audioFrequency;
153
154 /* Initialize builder object */
155 XSDEBUG("init builder #%i, maxsids=%i\n", xs_cfg.sid2Builder, (engine->emu.info()).maxsids);
156
157 switch (xs_cfg.sid2Builder)
158 {
159 #ifdef HAVE_RESID_BUILDER
160 case XS_BLD_RESID:
161 {
162 ReSIDBuilder *rs = new ReSIDBuilder("ReSID builder");
163 #ifdef HAVE_SIDPLAY2_FP_V1
164 if (rs && rs->getStatus())
165 {
166 }
167 #else
168 if (rs)
169 {
170 engine->config.sidEmulation = rs;
171 if (!*rs) return FALSE;
172 rs->create((engine->emu.info()).maxsids);
173 if (!*rs) return FALSE;
174 rs->bias(0.0f);
175 }
176 #endif // HAVE_SIDPLAY2_FP_V1
177 }
178 break;
179 #endif // HAVE_RESID_BUILDER
180
181
182 #ifdef HAVE_RESID_FP_BUILDER
183 case XS_BLD_RESID_FP:
184 {
185 ReSIDfpBuilder *rs = new ReSIDfpBuilder("ReSID builder FP!");
186 if (rs)
187 {
188 engine->config.sidEmulation = rs;
189 if (!*rs) return FALSE;
190 rs->create((engine->emu.info()).maxsids);
191 if (!*rs) return FALSE;
192
193 rs->filter6581Curve(0.0);
194 rs->filter8580Curve(0.0);
195 }
196 }
197 break;
198 #endif
199
200 #ifdef HAVE_HARDSID_BUILDER
201 case XS_BLD_HARDSID:
202 {
203 HardSIDBuilder *hs = new HardSIDBuilder("HardSID builder (FP)");
204 engine->config.sidEmulation = (sidbuilder *) hs;
205 if (hs)
206 {
207 hs->create((engine->emu.info()).maxsids);
208 if (!*hs)
209 {
210 xs_error("hardSID->create() failed.\n");
211 return FALSE;
212 }
213 }
214 }
215 break;
216 #endif
217
218 default:
219 xs_error("[SIDPlay2] Invalid or unsupported builder selected.\n");
220 break;
221 }
222
223 if (!engine->config.sidEmulation)
224 {
225 xs_error("[SIDPlay2] Could not initialize SIDBuilder object.\n");
226 return FALSE;
227 }
228
229 // Setup filter
230 engine->config.sidEmulation->filter(xs_cfg.emulateFilters);
231 if (!*(engine->config.sidEmulation))
232 {
233 xs_error("builder->filter(%d) failed.\n", xs_cfg.emulateFilters);
234 return FALSE;
235 }
236
237 XSDEBUG("%s\n", engine->config.sidEmulation->credits());
238
239 /* Clockspeed settings */
240 switch (xs_cfg.clockSpeed)
241 {
242 case XS_CLOCK_NTSC:
243 engine->config.clockDefault = SID2_CLOCK_NTSC;
244 break;
245
246 default:
247 case XS_CLOCK_PAL:
248 engine->config.clockDefault = SID2_CLOCK_PAL;
249 xs_cfg.clockSpeed = XS_CLOCK_PAL;
250 break;
251 }
252
253
254 /* Configure rest of the emulation */
255 engine->config.sidDefault = xs_cfg.mos8580 ? SID2_MOS8580 : SID2_MOS6581;
256 engine->config.clockForced = xs_cfg.forceSpeed;
257
258 #ifndef HAVE_SIDPLAY2_FP_V1
259 engine->config.sidSamples = TRUE;
260 engine->config.sidModel = xs_cfg.forceModel ? engine->config.sidDefault : SID2_MODEL_CORRECT;
261 engine->config.clockSpeed = xs_cfg.forceSpeed ? engine->config.clockDefault : SID2_CLOCK_CORRECT;
262 #endif
263
264 return TRUE;
265 }
266
267
268 /* Close SIDPlay2 engine
269 */
270 void xs_sidplayfp_close(XSEngineState * state)
271 {
272 XSSIDPlayFP *engine = (XSSIDPlayFP *) state->internal;
273
274 xs_sidplayfp_delete(state);
275
276 if (engine)
277 {
278 delete engine;
279 engine = NULL;
280 }
281
282 state->internal = NULL;
283 }
284
285
286 /* Initialize current song and sub-tune
287 */
288 gboolean xs_sidplayfp_initsong(XSEngineState * state)
289 {
290 XSSIDPlayFP *engine = (XSSIDPlayFP *) state->internal;
291
292 if (!engine)
293 return FALSE;
294
295 if (!engine->tune.selectSong(state->currSong))
296 {
297 xs_error("[SIDPlay2] tune.selectSong() failed\n");
298 return FALSE;
299 }
300
301 if (engine->emu.load(&(engine->tune)) < 0)
302 {
303 xs_error("[SIDPlay2] emu.load() failed\n");
304 return FALSE;
305 }
306
307 if (engine->emu.config(engine->config) < 0)
308 {
309 xs_error("[SIDPlay2] Emulator engine configuration failed!\n");
310 return FALSE;
311 }
312
313 return TRUE;
314 }
315
316
317 /* Emulate and render audio data to given buffer
318 */
319 guint xs_sidplayfp_fillbuffer(XSEngineState * state, gchar * audioBuffer, guint audioBufSize)
320 {
321 XSSIDPlayFP *engine = (XSSIDPlayFP *) state->internal;
322
323 if (!engine)
324 return 0;
325
326 #if 1
327 int nsamples = audioBufSize / sizeof(short);
328 return engine->emu.play((short *) audioBuffer, nsamples) * sizeof(short);
329 #else
330 int nsamples = audioBufSize / sizeof(short);
331 fprintf(stderr, "%p, %d -> %d\n", audioBuffer, audioBufSize, nsamples);
332 return 0;
333 #endif
334 }
335
336
337 /* Load a given SID-tune file
338 */
339 gboolean xs_sidplayfp_load(XSEngineState * state, gchar * filename)
340 {
341 XSSIDPlayFP *engine = (XSSIDPlayFP *) state->internal;
342
343 if (!engine || !filename)
344 return FALSE;
345
346 engine->tune.load(filename);
347 if (!engine->tune)
348 {
349 xs_error("Could not load file '%s': %s\n",
350 filename, (engine->tune.getInfo()).statusString);
351 return FALSE;
352 }
353
354 return TRUE;
355 }
356
357
358 /* Delete INTERNAL information
359 */
360 void xs_sidplayfp_delete(XSEngineState * state)
361 {
362 XSSIDPlayFP *engine = (XSSIDPlayFP *) state->internal;
363 }
364
365
366 /* Hardware backend flushing
367 */
368 void xs_sidplayfp_flush(XSEngineState * state)
369 {
370 XSSIDPlayFP *engine = (XSSIDPlayFP *) state->internal;
371
372 #ifdef HAVE_HARDSID_BUILDER
373 if (xs_cfg.sid2Builder == XS_BLD_HARDSID)
374 {
375 ((HardSIDBuilder *) engine->config.sidEmulation)->flush();
376 }
377 #endif
378 }
379
380
381 } /* extern "C" */
382 #endif /* HAVE_SIDPLAY2_FP */