Mercurial > hg > xmms-sid
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 */ |