comparison src/xs_sidplay1.cc @ 660:b0743dc9165d

Change tabs to 4 spaces, everywhere.
author Matti Hamalainen <ccr@tnsp.org>
date Wed, 02 Apr 2008 22:10:05 +0300
parents acaba070cf49
children c21908e9e7d7
comparison
equal deleted inserted replaced
659:04ea91a61225 660:b0743dc9165d
32 #include <sidplay/myendian.h> 32 #include <sidplay/myendian.h>
33 #include <sidplay/fformat.h> 33 #include <sidplay/fformat.h>
34 34
35 35
36 /* Maximum audio frequency supported by libSIDPlay v1 */ 36 /* Maximum audio frequency supported by libSIDPlay v1 */
37 #define SIDPLAY1_MAX_FREQ (48000) 37 #define SIDPLAY1_MAX_FREQ (48000)
38 38
39 39
40 typedef struct { 40 typedef struct {
41 emuEngine *currEng; 41 emuEngine *currEng;
42 emuConfig currConfig; 42 emuConfig currConfig;
43 sidTune *currTune; 43 sidTune *currTune;
44 guint8 *buf; 44 guint8 *buf;
45 size_t bufSize; 45 size_t bufSize;
46 } xs_sidplay1_t; 46 } xs_sidplay1_t;
47 47
48 48
49 /* We need to 'export' all this pseudo-C++ crap */ 49 /* We need to 'export' all this pseudo-C++ crap */
50 extern "C" { 50 extern "C" {
51 51
52 52
53 /* Return song information 53 /* Return song information
54 */ 54 */
55 #define TFUNCTION xs_sidplay1_getinfo 55 #define TFUNCTION xs_sidplay1_getinfo
56 #define TFUNCTION2 xs_sidplay1_updateinfo 56 #define TFUNCTION2 xs_sidplay1_updateinfo
57 #define TTUNEINFO sidTuneInfo 57 #define TTUNEINFO sidTuneInfo
58 #define TTUNE sidTune 58 #define TTUNE sidTune
59 #define TENGINE xs_sidplay1_t 59 #define TENGINE xs_sidplay1_t
60 #include "xs_sidplay.h" 60 #include "xs_sidplay.h"
61 61
62 62
63 /* Check if we can play the given file 63 /* Check if we can play the given file
64 */ 64 */
65 gboolean xs_sidplay1_probe(xs_file_t *f) 65 gboolean xs_sidplay1_probe(xs_file_t *f)
66 { 66 {
67 gchar tmpBuf[4]; 67 gchar tmpBuf[4];
68 68
69 if (!f) return FALSE; 69 if (!f) return FALSE;
70 70
71 if (xs_fread(tmpBuf, sizeof(gchar), 4, f) != 4) 71 if (xs_fread(tmpBuf, sizeof(gchar), 4, f) != 4)
72 return FALSE; 72 return FALSE;
73 73
74 if (!strncmp(tmpBuf, "PSID", 4)) 74 if (!strncmp(tmpBuf, "PSID", 4))
75 return TRUE; 75 return TRUE;
76 else 76 else
77 return FALSE; 77 return FALSE;
78 } 78 }
79 79
80 80
81 /* Initialize SIDPlay1 81 /* Initialize SIDPlay1
82 */ 82 */
83 gboolean xs_sidplay1_init(xs_status_t * myStatus) 83 gboolean xs_sidplay1_init(xs_status_t * myStatus)
84 { 84 {
85 gint tmpFreq; 85 gint tmpFreq;
86 xs_sidplay1_t *myEngine; 86 xs_sidplay1_t *myEngine;
87 assert(myStatus); 87 assert(myStatus);
88 88
89 /* Allocate internal structures */ 89 /* Allocate internal structures */
90 myEngine = (xs_sidplay1_t *) g_malloc0(sizeof(xs_sidplay1_t)); 90 myEngine = (xs_sidplay1_t *) g_malloc0(sizeof(xs_sidplay1_t));
91 if (!myEngine) return FALSE; 91 if (!myEngine) return FALSE;
92 92
93 /* Initialize engine */ 93 /* Initialize engine */
94 myEngine->currEng = new emuEngine(); 94 myEngine->currEng = new emuEngine();
95 if (!myEngine->currEng) { 95 if (!myEngine->currEng) {
96 xs_error("[SIDPlay1] Could not initialize emulation engine.\n"); 96 xs_error("[SIDPlay1] Could not initialize emulation engine.\n");
97 g_free(myEngine); 97 g_free(myEngine);
98 return FALSE; 98 return FALSE;
99 } 99 }
100 100
101 /* Verify endianess */ 101 /* Verify endianess */
102 if (!myEngine->currEng->verifyEndianess()) { 102 if (!myEngine->currEng->verifyEndianess()) {
103 xs_error("[SIDPlay1] Endianess verification failed.\n"); 103 xs_error("[SIDPlay1] Endianess verification failed.\n");
104 delete myEngine->currEng; 104 delete myEngine->currEng;
105 g_free(myEngine); 105 g_free(myEngine);
106 return FALSE; 106 return FALSE;
107 } 107 }
108 108
109 myStatus->sidEngine = myEngine; 109 myStatus->sidEngine = myEngine;
110 110
111 /* Get current configuration */ 111 /* Get current configuration */
112 myEngine->currEng->getConfig(myEngine->currConfig); 112 myEngine->currEng->getConfig(myEngine->currConfig);
113 113
114 /* Configure channel parameters */ 114 /* Configure channel parameters */
115 switch (myStatus->audioChannels) { 115 switch (myStatus->audioChannels) {
116 116
117 case XS_CHN_AUTOPAN: 117 case XS_CHN_AUTOPAN:
118 myEngine->currConfig.channels = SIDEMU_STEREO; 118 myEngine->currConfig.channels = SIDEMU_STEREO;
119 myEngine->currConfig.autoPanning = SIDEMU_CENTEREDAUTOPANNING; 119 myEngine->currConfig.autoPanning = SIDEMU_CENTEREDAUTOPANNING;
120 myEngine->currConfig.volumeControl = SIDEMU_FULLPANNING; 120 myEngine->currConfig.volumeControl = SIDEMU_FULLPANNING;
121 break; 121 break;
122 122
123 case XS_CHN_STEREO: 123 case XS_CHN_STEREO:
124 myEngine->currConfig.channels = SIDEMU_STEREO; 124 myEngine->currConfig.channels = SIDEMU_STEREO;
125 myEngine->currConfig.autoPanning = SIDEMU_NONE; 125 myEngine->currConfig.autoPanning = SIDEMU_NONE;
126 myEngine->currConfig.volumeControl = SIDEMU_NONE; 126 myEngine->currConfig.volumeControl = SIDEMU_NONE;
127 break; 127 break;
128 128
129 case XS_CHN_MONO: 129 case XS_CHN_MONO:
130 default: 130 default:
131 myEngine->currConfig.channels = SIDEMU_MONO; 131 myEngine->currConfig.channels = SIDEMU_MONO;
132 myEngine->currConfig.autoPanning = SIDEMU_NONE; 132 myEngine->currConfig.autoPanning = SIDEMU_NONE;
133 myEngine->currConfig.volumeControl = SIDEMU_NONE; 133 myEngine->currConfig.volumeControl = SIDEMU_NONE;
134 myStatus->audioChannels = XS_CHN_MONO; 134 myStatus->audioChannels = XS_CHN_MONO;
135 break; 135 break;
136 } 136 }
137 137
138 138
139 /* Memory mode settings */ 139 /* Memory mode settings */
140 switch (xs_cfg.memoryMode) { 140 switch (xs_cfg.memoryMode) {
141 case XS_MPU_TRANSPARENT_ROM: 141 case XS_MPU_TRANSPARENT_ROM:
142 myEngine->currConfig.memoryMode = MPU_TRANSPARENT_ROM; 142 myEngine->currConfig.memoryMode = MPU_TRANSPARENT_ROM;
143 break; 143 break;
144 144
145 case XS_MPU_PLAYSID_ENVIRONMENT: 145 case XS_MPU_PLAYSID_ENVIRONMENT:
146 myEngine->currConfig.memoryMode = MPU_PLAYSID_ENVIRONMENT; 146 myEngine->currConfig.memoryMode = MPU_PLAYSID_ENVIRONMENT;
147 break; 147 break;
148 148
149 case XS_MPU_BANK_SWITCHING: 149 case XS_MPU_BANK_SWITCHING:
150 default: 150 default:
151 myEngine->currConfig.memoryMode = MPU_BANK_SWITCHING; 151 myEngine->currConfig.memoryMode = MPU_BANK_SWITCHING;
152 xs_cfg.memoryMode = XS_MPU_BANK_SWITCHING; 152 xs_cfg.memoryMode = XS_MPU_BANK_SWITCHING;
153 break; 153 break;
154 } 154 }
155 155
156 156
157 /* Audio parameters sanity checking and setup */ 157 /* Audio parameters sanity checking and setup */
158 myEngine->currConfig.bitsPerSample = myStatus->audioBitsPerSample; 158 myEngine->currConfig.bitsPerSample = myStatus->audioBitsPerSample;
159 tmpFreq = myStatus->audioFrequency; 159 tmpFreq = myStatus->audioFrequency;
160 160
161 if (myStatus->oversampleEnable) { 161 if (myStatus->oversampleEnable) {
162 if ((tmpFreq * myStatus->oversampleFactor) > SIDPLAY1_MAX_FREQ) { 162 if ((tmpFreq * myStatus->oversampleFactor) > SIDPLAY1_MAX_FREQ) {
163 myStatus->oversampleEnable = FALSE; 163 myStatus->oversampleEnable = FALSE;
164 } else { 164 } else {
165 tmpFreq = (tmpFreq * myStatus->oversampleFactor); 165 tmpFreq = (tmpFreq * myStatus->oversampleFactor);
166 } 166 }
167 } else { 167 } else {
168 if (tmpFreq > SIDPLAY1_MAX_FREQ) 168 if (tmpFreq > SIDPLAY1_MAX_FREQ)
169 tmpFreq = SIDPLAY1_MAX_FREQ; 169 tmpFreq = SIDPLAY1_MAX_FREQ;
170 } 170 }
171 171
172 myEngine->currConfig.frequency = tmpFreq; 172 myEngine->currConfig.frequency = tmpFreq;
173 173
174 switch (myStatus->audioBitsPerSample) { 174 switch (myStatus->audioBitsPerSample) {
175 case XS_RES_8BIT: 175 case XS_RES_8BIT:
176 switch (myStatus->audioFormat) { 176 switch (myStatus->audioFormat) {
177 case FMT_S8: 177 case FMT_S8:
178 myStatus->audioFormat = FMT_S8; 178 myStatus->audioFormat = FMT_S8;
179 myEngine->currConfig.sampleFormat = SIDEMU_SIGNED_PCM; 179 myEngine->currConfig.sampleFormat = SIDEMU_SIGNED_PCM;
180 break; 180 break;
181 181
182 case FMT_U8: 182 case FMT_U8:
183 default: 183 default:
184 myStatus->audioFormat = FMT_U8; 184 myStatus->audioFormat = FMT_U8;
185 myEngine->currConfig.sampleFormat = SIDEMU_UNSIGNED_PCM; 185 myEngine->currConfig.sampleFormat = SIDEMU_UNSIGNED_PCM;
186 break; 186 break;
187 } 187 }
188 break; 188 break;
189 189
190 case XS_RES_16BIT: 190 case XS_RES_16BIT:
191 default: 191 default:
192 switch (myStatus->audioFormat) { 192 switch (myStatus->audioFormat) {
193 case FMT_U16_NE: 193 case FMT_U16_NE:
194 case FMT_U16_LE: 194 case FMT_U16_LE:
195 case FMT_U16_BE: 195 case FMT_U16_BE:
196 myStatus->audioFormat = FMT_U16_NE; 196 myStatus->audioFormat = FMT_U16_NE;
197 myEngine->currConfig.sampleFormat = SIDEMU_UNSIGNED_PCM; 197 myEngine->currConfig.sampleFormat = SIDEMU_UNSIGNED_PCM;
198 break; 198 break;
199 199
200 case FMT_S16_NE: 200 case FMT_S16_NE:
201 case FMT_S16_LE: 201 case FMT_S16_LE:
202 case FMT_S16_BE: 202 case FMT_S16_BE:
203 default: 203 default:
204 myStatus->audioFormat = FMT_S16_NE; 204 myStatus->audioFormat = FMT_S16_NE;
205 myEngine->currConfig.sampleFormat = SIDEMU_SIGNED_PCM; 205 myEngine->currConfig.sampleFormat = SIDEMU_SIGNED_PCM;
206 break; 206 break;
207 } 207 }
208 break; 208 break;
209 } 209 }
210 210
211 /* Clockspeed settings */ 211 /* Clockspeed settings */
212 switch (xs_cfg.clockSpeed) { 212 switch (xs_cfg.clockSpeed) {
213 case XS_CLOCK_NTSC: 213 case XS_CLOCK_NTSC:
214 myEngine->currConfig.clockSpeed = SIDTUNE_CLOCK_NTSC; 214 myEngine->currConfig.clockSpeed = SIDTUNE_CLOCK_NTSC;
215 break; 215 break;
216 216
217 case XS_CLOCK_PAL: 217 case XS_CLOCK_PAL:
218 default: 218 default:
219 myEngine->currConfig.clockSpeed = SIDTUNE_CLOCK_PAL; 219 myEngine->currConfig.clockSpeed = SIDTUNE_CLOCK_PAL;
220 xs_cfg.clockSpeed = XS_CLOCK_PAL; 220 xs_cfg.clockSpeed = XS_CLOCK_PAL;
221 break; 221 break;
222 } 222 }
223 223
224 myEngine->currConfig.forceSongSpeed = xs_cfg.forceSpeed; 224 myEngine->currConfig.forceSongSpeed = xs_cfg.forceSpeed;
225 225
226 226
227 /* Configure rest of the emulation */ 227 /* Configure rest of the emulation */
228 /* if (xs_cfg.forceModel) */ 228 /* if (xs_cfg.forceModel) */
229 myEngine->currConfig.mos8580 = xs_cfg.mos8580; 229 myEngine->currConfig.mos8580 = xs_cfg.mos8580;
230 myEngine->currConfig.emulateFilter = xs_cfg.emulateFilters; 230 myEngine->currConfig.emulateFilter = xs_cfg.emulateFilters;
231 myEngine->currConfig.filterFs = xs_cfg.sid1FilterFs; 231 myEngine->currConfig.filterFs = xs_cfg.sid1FilterFs;
232 myEngine->currConfig.filterFm = xs_cfg.sid1FilterFm; 232 myEngine->currConfig.filterFm = xs_cfg.sid1FilterFm;
233 myEngine->currConfig.filterFt = xs_cfg.sid1FilterFt; 233 myEngine->currConfig.filterFt = xs_cfg.sid1FilterFt;
234 234
235 235
236 /* Now set the emulator configuration */ 236 /* Now set the emulator configuration */
237 if (!myEngine->currEng->setConfig(myEngine->currConfig)) { 237 if (!myEngine->currEng->setConfig(myEngine->currConfig)) {
238 xs_error("[SIDPlay1] Emulator engine configuration failed!\n"); 238 xs_error("[SIDPlay1] Emulator engine configuration failed!\n");
239 return FALSE; 239 return FALSE;
240 } 240 }
241 241
242 /* Create sidtune object */ 242 /* Create sidtune object */
243 myEngine->currTune = new sidTune(0); 243 myEngine->currTune = new sidTune(0);
244 if (!myEngine->currTune) { 244 if (!myEngine->currTune) {
245 xs_error("[SIDPlay1] Could not initialize SIDTune object.\n"); 245 xs_error("[SIDPlay1] Could not initialize SIDTune object.\n");
246 return FALSE; 246 return FALSE;
247 } 247 }
248 248
249 return TRUE; 249 return TRUE;
250 } 250 }
251 251
252 252
253 /* Close SIDPlay1 engine 253 /* Close SIDPlay1 engine
254 */ 254 */
255 void xs_sidplay1_close(xs_status_t * myStatus) 255 void xs_sidplay1_close(xs_status_t * myStatus)
256 { 256 {
257 xs_sidplay1_t *myEngine; 257 xs_sidplay1_t *myEngine;
258 assert(myStatus); 258 assert(myStatus);
259 259
260 myEngine = (xs_sidplay1_t *) myStatus->sidEngine; 260 myEngine = (xs_sidplay1_t *) myStatus->sidEngine;
261 261
262 /* Free internals */ 262 /* Free internals */
263 if (myEngine->currEng) { 263 if (myEngine->currEng) {
264 delete myEngine->currEng; 264 delete myEngine->currEng;
265 myEngine->currEng = NULL; 265 myEngine->currEng = NULL;
266 } 266 }
267 267
268 if (myEngine->currTune) { 268 if (myEngine->currTune) {
269 delete myEngine->currTune; 269 delete myEngine->currTune;
270 myEngine->currTune = NULL; 270 myEngine->currTune = NULL;
271 } 271 }
272 272
273 xs_sidplay1_delete(myStatus); 273 xs_sidplay1_delete(myStatus);
274 274
275 g_free(myEngine); 275 g_free(myEngine);
276 myStatus->sidEngine = NULL; 276 myStatus->sidEngine = NULL;
277 } 277 }
278 278
279 279
280 /* Initialize current song and sub-tune 280 /* Initialize current song and sub-tune
281 */ 281 */
282 gboolean xs_sidplay1_initsong(xs_status_t * myStatus) 282 gboolean xs_sidplay1_initsong(xs_status_t * myStatus)
283 { 283 {
284 xs_sidplay1_t *myEngine; 284 xs_sidplay1_t *myEngine;
285 assert(myStatus); 285 assert(myStatus);
286 286
287 myEngine = (xs_sidplay1_t *) myStatus->sidEngine; 287 myEngine = (xs_sidplay1_t *) myStatus->sidEngine;
288 if (!myEngine) return FALSE; 288 if (!myEngine) return FALSE;
289 289
290 if (!myEngine->currTune) { 290 if (!myEngine->currTune) {
291 xs_error("[SIDPlay1] SID-tune struct pointer was NULL. This should not happen, report to XMMS-SID author.\n"); 291 xs_error("[SIDPlay1] SID-tune struct pointer was NULL. This should not happen, report to XMMS-SID author.\n");
292 return FALSE; 292 return FALSE;
293 } 293 }
294 294
295 if (!myEngine->currTune->getStatus()) { 295 if (!myEngine->currTune->getStatus()) {
296 xs_error("[SIDPlay1] SID-tune status check failed. This should not happen, report to XMMS-SID author.\n"); 296 xs_error("[SIDPlay1] SID-tune status check failed. This should not happen, report to XMMS-SID author.\n");
297 return FALSE; 297 return FALSE;
298 } 298 }
299 299
300 myStatus->isInitialized = TRUE; 300 myStatus->isInitialized = TRUE;
301 301
302 return sidEmuInitializeSong(*myEngine->currEng, *myEngine->currTune, myStatus->currSong); 302 return sidEmuInitializeSong(*myEngine->currEng, *myEngine->currTune, myStatus->currSong);
303 } 303 }
304 304
305 305
306 /* Emulate and render audio data to given buffer 306 /* Emulate and render audio data to given buffer
307 */ 307 */
308 guint xs_sidplay1_fillbuffer(xs_status_t * myStatus, gchar * audioBuffer, guint audioBufSize) 308 guint xs_sidplay1_fillbuffer(xs_status_t * myStatus, gchar * audioBuffer, guint audioBufSize)
309 { 309 {
310 xs_sidplay1_t *myEngine; 310 xs_sidplay1_t *myEngine;
311 assert(myStatus); 311 assert(myStatus);
312 312
313 myEngine = (xs_sidplay1_t *) myStatus->sidEngine; 313 myEngine = (xs_sidplay1_t *) myStatus->sidEngine;
314 if (!myEngine) return 0; 314 if (!myEngine) return 0;
315 315
316 sidEmuFillBuffer(*myEngine->currEng, *myEngine->currTune, audioBuffer, audioBufSize); 316 sidEmuFillBuffer(*myEngine->currEng, *myEngine->currTune, audioBuffer, audioBufSize);
317 317
318 return audioBufSize; 318 return audioBufSize;
319 } 319 }
320 320
321 321
322 /* Load a given SID-tune file 322 /* Load a given SID-tune file
323 */ 323 */
324 gboolean xs_sidplay1_load(xs_status_t * myStatus, gchar * filename) 324 gboolean xs_sidplay1_load(xs_status_t * myStatus, gchar * filename)
325 { 325 {
326 xs_sidplay1_t *myEngine; 326 xs_sidplay1_t *myEngine;
327 assert(myStatus); 327 assert(myStatus);
328 myStatus->isInitialized = FALSE; 328 myStatus->isInitialized = FALSE;
329 329
330 myEngine = (xs_sidplay1_t *) myStatus->sidEngine; 330 myEngine = (xs_sidplay1_t *) myStatus->sidEngine;
331 if (!myEngine) return FALSE; 331 if (!myEngine) return FALSE;
332 332
333 /* Try to get the tune */ 333 /* Try to get the tune */
334 if (!filename) return FALSE; 334 if (!filename) return FALSE;
335 335
336 if (xs_fload_buffer(filename, &(myEngine->buf), &(myEngine->bufSize)) != 0) 336 if (xs_fload_buffer(filename, &(myEngine->buf), &(myEngine->bufSize)) != 0)
337 return FALSE; 337 return FALSE;
338 338
339 if (!myEngine->currTune->load(myEngine->buf, myEngine->bufSize)) 339 if (!myEngine->currTune->load(myEngine->buf, myEngine->bufSize))
340 return FALSE; 340 return FALSE;
341 341
342 return TRUE; 342 return TRUE;
343 } 343 }
344 344
345 345
346 /* Delete INTERNAL information 346 /* Delete INTERNAL information
347 */ 347 */
348 void xs_sidplay1_delete(xs_status_t * myStatus) 348 void xs_sidplay1_delete(xs_status_t * myStatus)
349 { 349 {
350 xs_sidplay1_t *myEngine; 350 xs_sidplay1_t *myEngine;
351 assert(myStatus); 351 assert(myStatus);
352 352
353 myEngine = (xs_sidplay1_t *) myStatus->sidEngine; 353 myEngine = (xs_sidplay1_t *) myStatus->sidEngine;
354 if (!myEngine) return; 354 if (!myEngine) return;
355 355
356 g_free(myEngine->buf); 356 g_free(myEngine->buf);
357 myEngine->buf = NULL; 357 myEngine->buf = NULL;
358 myEngine->bufSize = 0; 358 myEngine->bufSize = 0;
359 } 359 }
360 360
361 361
362 } /* extern "C" */ 362 } /* extern "C" */
363 #endif /* HAVE_SIDPLAY1 */ 363 #endif /* HAVE_SIDPLAY1 */