comparison src/xs_sidplayfp.cpp @ 957:0e60e5d56fdd

Change how the backend emulator library is initialized for libSIDPlay2 and FP, as it seems the engine configuration has some persistence despite reconfiguration between loaded files if same engine object is retained. This caused, for example, 2SID stereo tunes being played "mono" if played after a normal 1-SID tune. Duh.
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 20 Nov 2012 22:13:48 +0200
parents a5b118c853f5
children 32435407eb9c
comparison
equal deleted inserted replaced
956:fbcd069663e5 957:0e60e5d56fdd
45 class XSSIDPlayFP { 45 class XSSIDPlayFP {
46 public: 46 public:
47 #ifdef HAVE_SIDPLAYFP_V1 47 #ifdef HAVE_SIDPLAYFP_V1
48 sidplayfp emu; 48 sidplayfp emu;
49 SidConfig config; 49 SidConfig config;
50 guint8 *romImages[XS_C64_ROM_IMAGES];
51 #else 50 #else
52 sidplay2 emu; 51 sidplay2 emu;
53 sid2_config_t config; 52 sid2_config_t config;
54 #endif 53 #endif
55 SidTune tune; 54 SidTune tune;
56 55
57 XSSIDPlayFP(void); 56 XSSIDPlayFP(void);
58 virtual ~XSSIDPlayFP(void); 57 virtual ~XSSIDPlayFP(void);
59 }; 58 };
60 59
60 static guint8 *xs_rom_imagedata[XS_C64_ROM_IMAGES];
61 61
62 #ifdef HAVE_RESID_FP_BUILDER 62 #ifdef HAVE_RESID_FP_BUILDER
63 # include <sidplayfp/builders/residfp.h> 63 # include <sidplayfp/builders/residfp.h>
64 #endif 64 #endif
65 65
136 136
137 /* Initialize SIDPlayFP 137 /* Initialize SIDPlayFP
138 */ 138 */
139 gboolean xs_sidplayfp_init(XSEngineState * state) 139 gboolean xs_sidplayfp_init(XSEngineState * state)
140 { 140 {
141 assert(state);
142
143 XSDEBUG("SIDPlayFP backend initializing.\n");
144
145 memset(xs_rom_imagedata, 0, sizeof(xs_rom_imagedata));
146 if (!xs_load_rom_images(xs_rom_imagedata))
147 return FALSE;
148
149 return TRUE;
150 }
151
152
153 /* Close SIDPlayFP engine
154 */
155 void xs_sidplayfp_close(XSEngineState * state)
156 {
157 XSSIDPlayFP *engine = (XSSIDPlayFP *) state->internal;
158
159 XSDEBUG("SIDPlayFP backend shutdown.\n");
160
161 xs_sidplayfp_delete(state);
162 }
163
164
165 /* Initialize current song and sub-tune
166 */
167 gboolean xs_sidplayfp_initsong(XSEngineState * state)
168 {
169 XSSIDPlayFP *engine = (XSSIDPlayFP *) state->internal;
170
171 if (!engine)
172 return FALSE;
173
174 if (!engine->tune.selectSong(state->currSong))
175 {
176 xs_error("[SIDPlayFP] tune.selectSong() failed\n");
177 return FALSE;
178 }
179
180 if (engine->emu.load(&(engine->tune)) < 0)
181 {
182 xs_error("[SIDPlayFP] emu.load() failed\n");
183 return FALSE;
184 }
185
186 if (engine->emu.config(engine->config) < 0)
187 {
188 xs_error("[SIDPlayFP] Emulator engine configuration failed!\n");
189 return FALSE;
190 }
191
192 return TRUE;
193 }
194
195
196 /* Emulate and render audio data to given buffer
197 */
198 guint xs_sidplayfp_fillbuffer(XSEngineState * state, gchar * audioBuffer, guint audioBufSize)
199 {
200 XSSIDPlayFP *engine = (XSSIDPlayFP *) state->internal;
201
202 if (!engine)
203 return 0;
204
205 return engine->emu.play((short *) audioBuffer, audioBufSize / sizeof(short)) * sizeof(short);
206 }
207
208
209 /* Load a given SID-tune file
210 */
211 gboolean xs_sidplayfp_load(XSEngineState * state, gchar * filename)
212 {
141 XSSIDPlayFP *engine; 213 XSSIDPlayFP *engine;
142 assert(state); 214 guint8 *buf = NULL;
143 215 size_t bufSize;
144 XSDEBUG("SIDPlayFP backend initializing.\n");
145 216
146 /* Allocate internal structures */ 217 /* Allocate internal structures */
147 engine = new XSSIDPlayFP(); 218 engine = new XSSIDPlayFP();
148 state->internal = engine; 219 state->internal = engine;
149 if (!engine) 220 if (!engine)
150 return FALSE; 221 {
222 xs_error("Allocating XSSIDPlayFP compound backend object failed.\n");
223 goto error;
224 }
151 225
152 /* Get current configuration */ 226 /* Get current configuration */
153 XSDEBUG("SIDPlayFP emulation configuration\n"); 227 XSDEBUG("SIDPlayFP emulation configuration\n");
154 engine->config = engine->emu.config(); 228 engine->config = engine->emu.config();
155 229
213 ReSIDBuilder *rs = new ReSIDBuilder("ReSID builder"); 287 ReSIDBuilder *rs = new ReSIDBuilder("ReSID builder");
214 #ifdef HAVE_SIDPLAYFP_V1 288 #ifdef HAVE_SIDPLAYFP_V1
215 if (rs && rs->getStatus()) 289 if (rs && rs->getStatus())
216 { 290 {
217 engine->config.sidEmulation = rs; 291 engine->config.sidEmulation = rs;
218 if (!rs->getStatus()) return FALSE; 292 if (!rs->getStatus()) goto error;
219 rs->create((engine->emu.info()).maxsids()); 293 rs->create((engine->emu.info()).maxsids());
220 if (!rs->getStatus()) return FALSE; 294 if (!rs->getStatus()) goto error;
221 } 295 }
222 #else 296 #else
223 if (rs && *rs) 297 if (rs && *rs)
224 { 298 {
225 engine->config.sidEmulation = rs; 299 engine->config.sidEmulation = rs;
226 if (!*rs) return FALSE; 300 if (!*rs) goto error;
227 rs->create((engine->emu.info()).maxsids); 301 rs->create((engine->emu.info()).maxsids);
228 if (!*rs) return FALSE; 302 if (!*rs) goto error;
229 } 303 }
230 #endif 304 #endif
231 rs->bias(0.0f); 305 rs->bias(0.0f);
232 } 306 }
233 break; 307 break;
240 ReSIDfpBuilder *rs = new ReSIDfpBuilder("ReSID builder FP!"); 314 ReSIDfpBuilder *rs = new ReSIDfpBuilder("ReSID builder FP!");
241 #ifdef HAVE_SIDPLAYFP_V1 315 #ifdef HAVE_SIDPLAYFP_V1
242 if (rs && rs->getStatus()) 316 if (rs && rs->getStatus())
243 { 317 {
244 engine->config.sidEmulation = rs; 318 engine->config.sidEmulation = rs;
245 if (!rs->getStatus()) return FALSE; 319 if (!rs->getStatus()) goto error;
246 rs->create((engine->emu.info()).maxsids()); 320 rs->create((engine->emu.info()).maxsids());
247 if (!rs->getStatus()) return FALSE; 321 if (!rs->getStatus()) goto error;
248 } 322 }
249 #else 323 #else
250 if (rs && *rs) 324 if (rs && *rs)
251 { 325 {
252 engine->config.sidEmulation = rs; 326 engine->config.sidEmulation = rs;
253 if (!*rs) return FALSE; 327 if (!*rs) goto error;
254 rs->create((engine->emu.info()).maxsids); 328 rs->create((engine->emu.info()).maxsids);
255 if (!*rs) return FALSE; 329 if (!*rs) goto error;
256 } 330 }
257 #endif 331 #endif
258 // rs->filter6581Curve(0.0); 332 // rs->filter6581Curve(0.0);
259 // rs->filter8580Curve(0.0); 333 // rs->filter8580Curve(0.0);
260 } 334 }
268 engine->config.sidEmulation = (sidbuilder *) hs; 342 engine->config.sidEmulation = (sidbuilder *) hs;
269 #ifdef HAVE_SIDPLAYFP_V1 343 #ifdef HAVE_SIDPLAYFP_V1
270 if (hs && hs->getStatus()) 344 if (hs && hs->getStatus())
271 { 345 {
272 hs->create((engine->emu.info()).maxsids()); 346 hs->create((engine->emu.info()).maxsids());
273 if (!hs->getStatus()) return FALSE; 347 if (!hs->getStatus()) goto error;
274 } 348 }
275 #else 349 #else
276 if (hs && *hs) 350 if (hs && *hs)
277 { 351 {
278 hs->create((engine->emu.info()).maxsids); 352 hs->create((engine->emu.info()).maxsids);
279 if (!*hs) return FALSE; 353 if (!*hs) goto error;
280 } 354 }
281 #endif 355 #endif
282 } 356 }
283 break; 357 break;
284 #endif 358 #endif
285 359
286 default: 360 default:
287 xs_error("[SIDPlayFP] Invalid or unsupported builder selected.\n"); 361 xs_error("[SIDPlayFP] Invalid or unsupported builder selected.\n");
288 return FALSE; 362 goto error;
289 } 363 }
364
290 365
291 if (!engine->config.sidEmulation) 366 if (!engine->config.sidEmulation)
292 { 367 {
293 xs_error("[SIDPlayFP] Could not initialize SIDBuilder object.\n"); 368 xs_error("[SIDPlayFP] Could not initialize SIDBuilder object.\n");
294 return FALSE; 369 goto error;
295 } 370 }
296 371
297 // Setup filter 372 // Setup filter
298 engine->config.sidEmulation->filter(xs_cfg.emulateFilters); 373 engine->config.sidEmulation->filter(xs_cfg.emulateFilters);
299 #ifdef HAVE_SIDPLAYFP_V1 374 #ifdef HAVE_SIDPLAYFP_V1
301 #else 376 #else
302 if (!*(engine->config.sidEmulation)) 377 if (!*(engine->config.sidEmulation))
303 #endif 378 #endif
304 { 379 {
305 xs_error("builder->filter(%d) failed.\n", xs_cfg.emulateFilters); 380 xs_error("builder->filter(%d) failed.\n", xs_cfg.emulateFilters);
306 return FALSE; 381 goto error;
307 } 382 }
308 383
309 XSDEBUG("%s\n", engine->config.sidEmulation->credits()); 384 XSDEBUG("%s\n", engine->config.sidEmulation->credits());
310 385
311 #ifdef HAVE_SIDPLAYFP_V1 386 #ifdef HAVE_SIDPLAYFP_V1
312 memset(engine->romImages, 0, sizeof(engine->romImages)); 387 engine->emu.setRoms(xs_rom_imagedata[0], xs_rom_imagedata[1], xs_rom_imagedata[2]);
313 if (!xs_load_rom_images(engine->romImages)) 388 #endif
314 return FALSE; 389
315 390
316 engine->emu.setRoms(engine->romImages[0], engine->romImages[1], engine->romImages[2]);
317 #endif
318
319 return TRUE;
320 }
321
322
323 /* Close SIDPlayFP engine
324 */
325 void xs_sidplayfp_close(XSEngineState * state)
326 {
327 XSSIDPlayFP *engine = (XSSIDPlayFP *) state->internal;
328
329 XSDEBUG("SIDPlayFP backend shutdown.\n");
330
331 xs_sidplayfp_delete(state);
332
333 if (engine)
334 {
335 delete engine;
336 engine = NULL;
337 }
338
339 state->internal = NULL;
340 }
341
342
343 /* Initialize current song and sub-tune
344 */
345 gboolean xs_sidplayfp_initsong(XSEngineState * state)
346 {
347 XSSIDPlayFP *engine = (XSSIDPlayFP *) state->internal;
348
349 if (!engine)
350 return FALSE;
351
352 if (!engine->tune.selectSong(state->currSong))
353 {
354 xs_error("[SIDPlayFP] tune.selectSong() failed\n");
355 return FALSE;
356 }
357
358 if (engine->emu.load(&(engine->tune)) < 0)
359 {
360 xs_error("[SIDPlayFP] emu.load() failed\n");
361 return FALSE;
362 }
363
364 if (engine->emu.config(engine->config) < 0)
365 {
366 xs_error("[SIDPlayFP] Emulator engine configuration failed!\n");
367 return FALSE;
368 }
369
370 return TRUE;
371 }
372
373
374 /* Emulate and render audio data to given buffer
375 */
376 guint xs_sidplayfp_fillbuffer(XSEngineState * state, gchar * audioBuffer, guint audioBufSize)
377 {
378 XSSIDPlayFP *engine = (XSSIDPlayFP *) state->internal;
379
380 if (!engine)
381 return 0;
382
383 return engine->emu.play((short *) audioBuffer, audioBufSize / sizeof(short)) * sizeof(short);
384 }
385
386
387 /* Load a given SID-tune file
388 */
389 gboolean xs_sidplayfp_load(XSEngineState * state, gchar * filename)
390 {
391 XSSIDPlayFP *engine = (XSSIDPlayFP *) state->internal;
392 gboolean res = FALSE;
393 guint8 *buf = NULL;
394 size_t bufSize;
395
396 if (!engine)
397 return FALSE;
398 391
399 if (!xs_fload_buffer(filename, &buf, &bufSize, XS_SIDBUF_SIZE, TRUE)) 392 if (!xs_fload_buffer(filename, &buf, &bufSize, XS_SIDBUF_SIZE, TRUE))
400 goto error; 393 goto error;
401 394
402 engine->tune.read(buf, bufSize); 395 engine->tune.read(buf, bufSize);
409 { 402 {
410 xs_error("Could not load file '%s'\n", filename); 403 xs_error("Could not load file '%s'\n", filename);
411 goto error; 404 goto error;
412 } 405 }
413 406
414 res = TRUE; 407 g_free(buf);
408 return TRUE;
415 409
416 error: 410 error:
411 if (engine)
412 delete engine;
413 state->internal = NULL;
417 g_free(buf); 414 g_free(buf);
418 return res; 415 return FALSE;
419 } 416 }
420 417
421 418
422 /* Delete INTERNAL information 419 /* Delete INTERNAL information
423 */ 420 */
424 void xs_sidplayfp_delete(XSEngineState * state) 421 void xs_sidplayfp_delete(XSEngineState * state)
425 { 422 {
426 (void) state; 423 XSSIDPlayFP *engine = (XSSIDPlayFP *) state->internal;
427 // XSSIDPlayFP *engine = (XSSIDPlayFP *) state->internal; 424
425 if (engine)
426 delete engine;
427 state->internal = NULL;
428 } 428 }
429 429
430 430
431 /* Hardware backend flushing 431 /* Hardware backend flushing
432 */ 432 */