Mercurial > hg > xmms-sid
comparison src/xs_sidplay2.cc @ 270:583f5651abff
Cleanups, moved engine configuration to initialization function.
Audio settings "feedback" and oversampling support implemented.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Thu, 23 Dec 2004 17:02:05 +0000 |
parents | e613873c3379 |
children | 45ad9f7c1628 |
comparison
equal
deleted
inserted
replaced
269:f949b83c3f52 | 270:583f5651abff |
---|---|
45 sid2_config_t currConfig; | 45 sid2_config_t currConfig; |
46 SidTune *currTune; | 46 SidTune *currTune; |
47 } t_xs_sidplay2; | 47 } t_xs_sidplay2; |
48 | 48 |
49 | 49 |
50 /* | 50 /* We need to 'export' all this pseudo-C++ crap */ |
51 * We need to 'export' all this pseudo-C++ crap | |
52 */ | |
53 extern "C" { | 51 extern "C" { |
54 | 52 |
55 | 53 |
56 /* | 54 /* Check if we can play the given file |
57 * Check if we can play the given file | |
58 */ | 55 */ |
59 gboolean xs_sidplay2_isourfile(gchar *pcFilename) | 56 gboolean xs_sidplay2_isourfile(gchar *pcFilename) |
60 { | 57 { |
61 SidTune *testTune = new SidTune(pcFilename); | 58 SidTune *testTune = new SidTune(pcFilename); |
62 | 59 |
70 delete testTune; | 67 delete testTune; |
71 return TRUE; | 68 return TRUE; |
72 } | 69 } |
73 | 70 |
74 | 71 |
75 /* | 72 |
76 * Initialize SIDPlay2 | 73 /* Initialize SIDPlay2 |
77 */ | 74 */ |
78 gboolean xs_sidplay2_init(t_xs_status *myStatus) | 75 gboolean xs_sidplay2_init(t_xs_status *myStatus) |
79 { | 76 { |
77 gint tmpFreq; | |
80 t_xs_sidplay2 *myEngine; | 78 t_xs_sidplay2 *myEngine; |
81 assert(myStatus); | 79 assert(myStatus); |
82 | 80 |
83 /* Allocate internal structures */ | 81 /* Allocate internal structures */ |
84 myEngine = (t_xs_sidplay2 *) g_malloc0(sizeof(t_xs_sidplay2)); | 82 myEngine = (t_xs_sidplay2 *) g_malloc0(sizeof(t_xs_sidplay2)); |
96 /* Initialize builder object */ | 94 /* Initialize builder object */ |
97 XSDEBUG("init builder #%i\n", xs_cfg.sid2Builder); | 95 XSDEBUG("init builder #%i\n", xs_cfg.sid2Builder); |
98 #ifdef HAVE_RESID_BUILDER | 96 #ifdef HAVE_RESID_BUILDER |
99 if (xs_cfg.sid2Builder == XS_BLD_RESID) | 97 if (xs_cfg.sid2Builder == XS_BLD_RESID) |
100 { | 98 { |
101 ReSIDBuilder *tmpb = new ReSIDBuilder("SIDPlay2 suxx and is made by a fag - ReSID builder"); | 99 ReSIDBuilder *tmpb = new ReSIDBuilder("SIDPlay2 suxx - ReSID builder"); |
102 | 100 |
103 /* Create the builder -- WHAT IS THIS MEANT FOR??? */ | 101 /* Create the builder -- WHAT IS THIS MEANT FOR??? */ |
104 tmpb->create(myEngine->currEng->info().maxsids); | 102 tmpb->create(myEngine->currEng->info().maxsids); |
105 | 103 |
106 myEngine->currBuilder = (sidbuilder *) tmpb; | 104 myEngine->currBuilder = (sidbuilder *) tmpb; |
117 XSERR("Could not initialize SIDBuilder object.\n"); | 115 XSERR("Could not initialize SIDBuilder object.\n"); |
118 return FALSE; | 116 return FALSE; |
119 } | 117 } |
120 | 118 |
121 XSDEBUG("%s\n", myEngine->currBuilder->credits()); | 119 XSDEBUG("%s\n", myEngine->currBuilder->credits()); |
122 | |
123 | |
124 /* Create the sidtune */ | |
125 myEngine->currTune = new SidTune(0); | |
126 if (!myEngine->currTune) | |
127 { | |
128 XSERR("Could not initialize SIDTune object.\n"); | |
129 return FALSE; | |
130 } | |
131 | |
132 /* OK */ | |
133 myStatus->sidEngine = myEngine; | 120 myStatus->sidEngine = myEngine; |
134 return TRUE; | 121 |
135 } | |
136 | |
137 | |
138 /* | |
139 * Close SIDPlay2 | |
140 */ | |
141 void xs_sidplay2_close(t_xs_status *myStatus) | |
142 { | |
143 t_xs_sidplay2 *myEngine; | |
144 assert(myStatus); | |
145 | |
146 /* Free internals */ | |
147 myEngine = (t_xs_sidplay2 *) myStatus->sidEngine; | |
148 | |
149 if (myEngine->currBuilder) | |
150 { | |
151 delete myEngine->currBuilder; | |
152 myEngine->currBuilder = NULL; | |
153 } | |
154 | |
155 if (myEngine->currEng) | |
156 { | |
157 delete myEngine->currEng; | |
158 myEngine->currEng = NULL; | |
159 } | |
160 | |
161 if (myEngine->currTune) | |
162 { | |
163 delete myEngine->currTune; | |
164 myEngine->currTune = NULL; | |
165 } | |
166 | |
167 xs_sidplay2_deletesid(myStatus); | |
168 | |
169 g_free(myEngine); | |
170 myStatus->sidEngine = NULL; | |
171 } | |
172 | |
173 | |
174 gboolean xs_sidplay2_initsong(t_xs_status *myStatus) | |
175 { | |
176 t_xs_sidplay2 *myEngine = (t_xs_sidplay2 *) myStatus->sidEngine; | |
177 | |
178 if (!myEngine) return FALSE; | |
179 | |
180 if (!myEngine->currTune->selectSong(myStatus->currSong)) | |
181 { | |
182 XSERR("ENGINE selectSong() failed\n"); | |
183 return FALSE; | |
184 } | |
185 | |
186 if (myEngine->currEng->load(myEngine->currTune) < 0) | |
187 { | |
188 XSERR("ENGINE load() failed\n"); | |
189 return FALSE; | |
190 } | |
191 | |
192 return TRUE; | |
193 } | |
194 | |
195 | |
196 guint xs_sidplay2_fillbuffer(t_xs_status *myStatus, gchar *audioBuffer, guint audioBufSize) | |
197 { | |
198 t_xs_sidplay2 *myEngine = (t_xs_sidplay2 *) myStatus->sidEngine; | |
199 | |
200 if (!myEngine) return 0; | |
201 | |
202 return myEngine->currEng->play(audioBuffer, audioBufSize); | |
203 } | |
204 | |
205 | |
206 gboolean xs_sidplay2_loadsid(t_xs_status *myStatus, gchar *pcFilename) | |
207 { | |
208 t_xs_sidplay2 *myEngine = (t_xs_sidplay2 *) myStatus->sidEngine; | |
209 assert(myStatus); | |
210 | |
211 /* Try to get the tune */ | |
212 if (!pcFilename) return FALSE; | |
213 if (!myEngine->currTune->load(pcFilename)) return FALSE; | |
214 | 122 |
215 /* Get current configuration */ | 123 /* Get current configuration */ |
216 myEngine->currConfig = myEngine->currEng->config(); | 124 myEngine->currConfig = myEngine->currEng->config(); |
217 | 125 |
218 /* Configure channels and stuff */ | 126 /* Configure channels and stuff */ |
227 break; | 135 break; |
228 | 136 |
229 case XS_CHN_MONO: | 137 case XS_CHN_MONO: |
230 default: | 138 default: |
231 myEngine->currConfig.playback = sid2_mono; | 139 myEngine->currConfig.playback = sid2_mono; |
140 myStatus->audioChannels = XS_CHN_MONO; | |
232 break; | 141 break; |
233 } | 142 } |
234 | 143 |
235 | 144 |
236 /* Memory mode settings */ | 145 /* Memory mode settings */ |
248 break; | 157 break; |
249 | 158 |
250 case XS_MPU_REAL: | 159 case XS_MPU_REAL: |
251 default: | 160 default: |
252 myEngine->currConfig.environment = sid2_envR; | 161 myEngine->currConfig.environment = sid2_envR; |
162 xs_cfg.memoryMode = XS_MPU_REAL; | |
253 break; | 163 break; |
254 } | 164 } |
255 | 165 |
256 | 166 |
257 /* Clockspeed settings */ | 167 /* Clockspeed settings */ |
261 break; | 171 break; |
262 | 172 |
263 case XS_CLOCK_PAL: | 173 case XS_CLOCK_PAL: |
264 default: | 174 default: |
265 myEngine->currConfig.clockSpeed = myEngine->currConfig.clockDefault = SID2_CLOCK_PAL; | 175 myEngine->currConfig.clockSpeed = myEngine->currConfig.clockDefault = SID2_CLOCK_PAL; |
176 xs_cfg.clockSpeed = XS_CLOCK_PAL; | |
266 break; | 177 break; |
267 } | 178 } |
268 | 179 |
269 | 180 |
270 /* Configure rest of the emulation */ | 181 /* Configure rest of the emulation */ |
271 myEngine->currConfig.sidEmulation = myEngine->currBuilder; | 182 myEngine->currConfig.sidEmulation = myEngine->currBuilder; |
272 myEngine->currConfig.clockForced = xs_cfg.forceSpeed; | 183 myEngine->currConfig.clockForced = xs_cfg.forceSpeed; |
273 myEngine->currConfig.optimisation = (xs_cfg.sid2OptLevel) ? 1 : 0; | 184 myEngine->currConfig.optimisation = (xs_cfg.sid2OptLevel) ? 1 : 0; |
274 myEngine->currConfig.sidDefault = myEngine->currConfig.sidModel = (xs_cfg.mos8580) ? SID2_MOS8580 : SID2_MOS6581; | 185 if (xs_cfg.mos8580) |
186 myEngine->currConfig.sidDefault = SID2_MOS8580; | |
187 else | |
188 myEngine->currConfig.sidDefault = SID2_MOS6581; | |
189 | |
190 myEngine->currConfig.sidModel = myEngine->currConfig.sidDefault; | |
275 myEngine->currConfig.sidSamples = TRUE; // FIXME FIX ME, make configurable! | 191 myEngine->currConfig.sidSamples = TRUE; // FIXME FIX ME, make configurable! |
276 myEngine->currConfig.precision = myStatus->audioBitsPerSample; | 192 |
277 myEngine->currConfig.frequency = myStatus->audioFrequency; | 193 |
194 /* Audio parameters sanity checking and setup */ | |
195 myEngine->currConfig.precision = myStatus->audioBitsPerSample; | |
196 tmpFreq = myStatus->audioFrequency; | |
197 | |
198 if (myStatus->oversampleEnable) | |
199 tmpFreq = (tmpFreq * myStatus->oversampleFactor); | |
200 | |
201 myEngine->currConfig.frequency = tmpFreq; | |
278 | 202 |
279 switch (myStatus->audioBitsPerSample) { | 203 switch (myStatus->audioBitsPerSample) { |
280 case XS_RES_8BIT: | 204 case XS_RES_8BIT: |
281 myStatus->audioFormat = FMT_U8; | 205 myStatus->audioFormat = FMT_U8; |
282 myEngine->currConfig.sampleFormat = SID2_LITTLE_UNSIGNED; | 206 myEngine->currConfig.sampleFormat = SID2_LITTLE_UNSIGNED; |
283 break; | 207 break; |
284 | 208 |
285 case XS_RES_16BIT: | 209 case XS_RES_16BIT: |
210 default: | |
286 switch (myStatus->audioFormat) { | 211 switch (myStatus->audioFormat) { |
287 case FMT_U16_LE: | 212 case FMT_U16_LE: |
288 myEngine->currConfig.sampleFormat = SID2_LITTLE_UNSIGNED; | 213 myEngine->currConfig.sampleFormat = SID2_LITTLE_UNSIGNED; |
289 break; | 214 break; |
290 | 215 |
291 case FMT_U16_BE: | 216 case FMT_U16_BE: |
292 myEngine->currConfig.sampleFormat = SID2_BIG_UNSIGNED; | 217 myEngine->currConfig.sampleFormat = SID2_BIG_UNSIGNED; |
293 break; | 218 break; |
294 | 219 |
295 case FMT_U16_NE: | 220 case FMT_U16_NE: |
296 myStatus->audioFormat = FMT_U16_NE; | |
297 #ifdef WORDS_BIGENDIAN | 221 #ifdef WORDS_BIGENDIAN |
298 myEngine->currConfig.sampleFormat = SID2_BIG_UNSIGNED; | 222 myEngine->currConfig.sampleFormat = SID2_BIG_UNSIGNED; |
299 #else | 223 #else |
300 myEngine->currConfig.sampleFormat = SID2_LITTLE_UNSIGNED; | 224 myEngine->currConfig.sampleFormat = SID2_LITTLE_UNSIGNED; |
301 #endif | 225 #endif |
320 | 244 |
321 } | 245 } |
322 break; | 246 break; |
323 } | 247 } |
324 | 248 |
325 | |
326 /* Now set the emulator configuration */ | 249 /* Now set the emulator configuration */ |
327 if (myEngine->currEng->config(myEngine->currConfig) < 0) | 250 if (myEngine->currEng->config(myEngine->currConfig) < 0) |
328 { | 251 { |
329 XSERR("Emulator engine configuration failed!\n"); | 252 XSERR("Emulator engine configuration failed!\n"); |
330 return FALSE; | 253 return FALSE; |
331 } | 254 } |
332 | 255 |
256 /* Create the sidtune */ | |
257 myEngine->currTune = new SidTune(0); | |
258 if (!myEngine->currTune) | |
259 { | |
260 XSERR("Could not initialize SIDTune object.\n"); | |
261 return FALSE; | |
262 } | |
263 | |
333 return TRUE; | 264 return TRUE; |
334 } | 265 } |
335 | 266 |
336 | 267 |
337 /* | 268 /* Close SIDPlay2 engine |
338 * Delete tune | 269 */ |
270 void xs_sidplay2_close(t_xs_status *myStatus) | |
271 { | |
272 t_xs_sidplay2 *myEngine; | |
273 assert(myStatus); | |
274 | |
275 myEngine = (t_xs_sidplay2 *) myStatus->sidEngine; | |
276 | |
277 /* Free internals */ | |
278 if (myEngine->currBuilder) | |
279 { | |
280 delete myEngine->currBuilder; | |
281 myEngine->currBuilder = NULL; | |
282 } | |
283 | |
284 if (myEngine->currEng) | |
285 { | |
286 delete myEngine->currEng; | |
287 myEngine->currEng = NULL; | |
288 } | |
289 | |
290 if (myEngine->currTune) | |
291 { | |
292 delete myEngine->currTune; | |
293 myEngine->currTune = NULL; | |
294 } | |
295 | |
296 xs_sidplay2_deletesid(myStatus); | |
297 | |
298 g_free(myEngine); | |
299 myStatus->sidEngine = NULL; | |
300 } | |
301 | |
302 | |
303 /* Initialize current song and sub-tune | |
304 */ | |
305 gboolean xs_sidplay2_initsong(t_xs_status *myStatus) | |
306 { | |
307 t_xs_sidplay2 *myEngine; | |
308 assert(myStatus); | |
309 | |
310 myEngine = (t_xs_sidplay2 *) myStatus->sidEngine; | |
311 if (!myEngine) return FALSE; | |
312 | |
313 if (!myEngine->currTune->selectSong(myStatus->currSong)) | |
314 { | |
315 XSERR("currTune->selectSong() failed\n"); | |
316 return FALSE; | |
317 } | |
318 | |
319 if (myEngine->currEng->load(myEngine->currTune) < 0) | |
320 { | |
321 XSERR("currEng->load() failed\n"); | |
322 return FALSE; | |
323 } | |
324 | |
325 return TRUE; | |
326 } | |
327 | |
328 | |
329 /* Emulate and render audio data to given buffer | |
330 */ | |
331 guint xs_sidplay2_fillbuffer(t_xs_status *myStatus, gchar *audioBuffer, guint audioBufSize) | |
332 { | |
333 t_xs_sidplay2 *myEngine; | |
334 assert(myStatus); | |
335 | |
336 myEngine = (t_xs_sidplay2 *) myStatus->sidEngine; | |
337 if (!myEngine) return 0; | |
338 | |
339 return myEngine->currEng->play(audioBuffer, audioBufSize); | |
340 } | |
341 | |
342 | |
343 /* Load a given SID-tune file | |
344 */ | |
345 gboolean xs_sidplay2_loadsid(t_xs_status *myStatus, gchar *pcFilename) | |
346 { | |
347 t_xs_sidplay2 *myEngine; | |
348 assert(myStatus); | |
349 | |
350 myEngine = (t_xs_sidplay2 *) myStatus->sidEngine; | |
351 | |
352 /* Try to get the tune */ | |
353 if (!pcFilename) return FALSE; | |
354 if (!myEngine->currTune->load(pcFilename)) return FALSE; | |
355 | |
356 return TRUE; | |
357 } | |
358 | |
359 | |
360 /* Delete INTERNAL information | |
339 */ | 361 */ |
340 void xs_sidplay2_deletesid(t_xs_status *myStatus) | 362 void xs_sidplay2_deletesid(t_xs_status *myStatus) |
341 { | 363 { |
342 assert(myStatus); | 364 assert(myStatus); |
343 | 365 |
344 /* With the current scheme of handling sidtune-loading, we don't do anything here. */ | 366 /* With the current scheme of handling sidtune-loading, we don't do anything here. */ |
345 } | 367 } |
346 | 368 |
347 | 369 |
348 /* | 370 /* Return song information |
349 * Return song information | |
350 */ | 371 */ |
351 #define TFUNCTION xs_sidplay2_getsidinfo | 372 #define TFUNCTION xs_sidplay2_getsidinfo |
352 #define TTUNEINFO SidTuneInfo | 373 #define TTUNEINFO SidTuneInfo |
353 #define TTUNE SidTune | 374 #define TTUNE SidTune |
354 #include "xs_sidplay.h" | 375 #include "xs_sidplay.h" |