comparison jssmix.c @ 287:1e89cd081956

Use fixed point everywhere in the mixing internals, to avoid going over sample boundaries.
author Matti Hamalainen <ccr@tnsp.org>
date Thu, 11 Oct 2012 11:09:26 +0300
parents b7e23d91a8c2
children 701c3d22e0f9
comparison
equal deleted inserted replaced
286:a17e54015bd9 287:1e89cd081956
26 { 26 {
27 int mixerID; 27 int mixerID;
28 int outFormat; 28 int outFormat;
29 int outChannels; 29 int outChannels;
30 30
31 int (*jvmMixChannel_FW)(JSSMixer *, JSSChannel *, JMIXER_ADDBUF_TYPE *, const int, const Sint32); 31 int (*jvmMixChannel_FW)(JSSMixer *, JSSChannel *, JMIXER_ADDBUF_TYPE *, const int, const DMFixedPoint);
32 int (*jvmMixChannel_BW)(JSSMixer *, JSSChannel *, JMIXER_ADDBUF_TYPE *, const int, const Sint32); 32 int (*jvmMixChannel_BW)(JSSMixer *, JSSChannel *, JMIXER_ADDBUF_TYPE *, const int, const DMFixedPoint);
33 void (*jvmPostProcess)(JMIXER_ADDBUF_TYPE *, void *, const int); 33 void (*jvmPostProcess)(JMIXER_ADDBUF_TYPE *, void *, const int);
34 } JSSMixingRoutine; 34 } JSSMixingRoutine;
35 35
36 36
37 /* This table should be sorted from fastest to slowest, e.g. MMX/x86 37 /* This table should be sorted from fastest to slowest, e.g. MMX/x86
248 { 248 {
249 // Sample is looped 249 // Sample is looped
250 if (chn->chFlags & jsfBiDi) 250 if (chn->chFlags & jsfBiDi)
251 { 251 {
252 // Bi-directional loop 252 // Bi-directional loop
253 if (FP_GETH(chn->chPos) >= chn->chLoopE) 253 if (chn->chPos.dw >= chn->chLoopE.dw)
254 { 254 {
255 DMFixedPoint end; 255 DMFixedPoint end;
256 FP_SETHL(end, chn->chLoopE + chn->chLoopE, 0); 256 FP_ADD_R(end, chn->chLoopE, chn->chLoopE);
257 FP_SUB_R(chn->chPos, end, chn->chPos); 257 FP_SUB_R(chn->chPos, end, chn->chPos);
258 chn->chDirection = FALSE; 258 chn->chDirection = FALSE;
259 } 259 }
260 } 260 }
261 else 261 else
262 { 262 {
263 // Normal forward loop 263 // Normal forward loop
264 if (FP_GETH(chn->chPos) >= chn->chLoopE) 264 if (chn->chPos.dw >= chn->chLoopE.dw)
265 { 265 {
266 DMFixedPoint diff, end; 266 DMFixedPoint diff;
267 FP_SETHL(end, chn->chLoopE, 0); 267 FP_SUB_R(diff, chn->chPos, chn->chLoopE);
268 FP_SUB_R(diff, chn->chPos, end); 268 FP_ADD_R(chn->chPos, chn->chLoopS, diff);
269 FP_SETHL(chn->chPos, chn->chLoopS, 0);
270 FP_ADD(chn->chPos, diff);
271 } 269 }
272 } 270 }
273 } 271 }
274 else 272 else
275 { 273 {
276 // Normal (non-looped) sample 274 // Normal (non-looped) sample
277 if (FP_GETH(chn->chPos) >= chn->chSize) 275 if (chn->chPos.dw >= chn->chSize.dw)
278 { 276 {
279 chn->chPlaying = FALSE; 277 chn->chPlaying = FALSE;
280 return; 278 return;
281 } 279 }
282 } 280 }
288 { 286 {
289 // Sample is looped 287 // Sample is looped
290 if (chn->chFlags & jsfBiDi) 288 if (chn->chFlags & jsfBiDi)
291 { 289 {
292 // Bi-directional loop 290 // Bi-directional loop
293 if (FP_GETH(chn->chPos) <= chn->chLoopS) 291 if (chn->chPos.dw <= chn->chLoopS.dw)
294 { 292 {
295 DMFixedPoint start; 293 DMFixedPoint start;
296 FP_SETHL(start, chn->chLoopS + chn->chLoopS, 0); 294 FP_ADD_R(start, chn->chLoopS, chn->chLoopS);
297 FP_SUB_R(chn->chPos, start, chn->chPos); 295 FP_SUB_R(chn->chPos, start, chn->chPos);
298 chn->chDirection = TRUE; 296 chn->chDirection = TRUE;
299 } 297 }
300 } 298 }
301 else 299 else
302 { 300 {
303 // Normal forward loop 301 // Normal forward loop
304 if (FP_GETH(chn->chPos) <= chn->chLoopS) 302 if (chn->chPos.dw <= chn->chLoopS.dw)
305 { 303 {
306 DMFixedPoint diff; 304 DMFixedPoint diff;
307 FP_SETHL(diff, chn->chLoopE - chn->chLoopS, 0); 305 FP_SUB_R(diff, chn->chLoopE, chn->chLoopS);
308 FP_ADD(chn->chPos, diff); 306 FP_ADD(chn->chPos, diff);
309 } 307 }
310 } 308 }
311 } 309 }
312 else 310 else
313 { 311 {
314 // Normal (non-looped) sample 312 // Normal (non-looped) sample
315 if (FP_GETH(chn->chPos) <= 0) 313 if (chn->chPos.dw <= 0)
316 { 314 {
317 chn->chPlaying = FALSE; 315 chn->chPlaying = FALSE;
318 return; 316 return;
319 } 317 }
320 } 318 }
324 if (chn->chDirection) 322 if (chn->chDirection)
325 { 323 {
326 DBG("MIX_FW[%p : %d : ", ab, mixDone); 324 DBG("MIX_FW[%p : %d : ", ab, mixDone);
327 if (chn->chFlags & jsfLooped) 325 if (chn->chFlags & jsfLooped)
328 { 326 {
329 DBG("%d (%x)] {loop}\n", chn->chLoopE, chn->chLoopE); 327 DBG("%d (%x)] {loop}\n", FP_GETH(chn->chLoopE), FP_GETH(chn->chLoopE));
330 mixResult = mixer->jvmMixChannel_FW((void *) mixer, chn, 328 mixResult = mixer->jvmMixChannel_FW((void *) mixer, chn,
331 ab, mixDone, chn->chLoopE); 329 ab, mixDone, chn->chLoopE);
332 } 330 }
333 else 331 else
334 { 332 {
335 DBG("%d (%x)]\n", chn->chSize, chn->chSize); 333 DBG("%d (%x)]\n", FP_GETH(chn->chSize), FP_GETH(chn->chSize));
336 mixResult = mixer->jvmMixChannel_FW((void *) mixer, chn, 334 mixResult = mixer->jvmMixChannel_FW((void *) mixer, chn,
337 ab, mixDone, chn->chSize); 335 ab, mixDone, chn->chSize);
338 } 336 }
339 } 337 }
340 else 338 else
346 mixResult = mixer->jvmMixChannel_BW(mixer, chn, 344 mixResult = mixer->jvmMixChannel_BW(mixer, chn,
347 ab, mixDone, chn->chLoopS); 345 ab, mixDone, chn->chLoopS);
348 } 346 }
349 else 347 else
350 { 348 {
349 static const DMFixedPoint zero = { 0 };
351 DBG("%d (%x)]\n", 0, 0); 350 DBG("%d (%x)]\n", 0, 0);
352 mixResult = mixer->jvmMixChannel_BW(mixer, chn, 351 mixResult = mixer->jvmMixChannel_BW(mixer, chn,
353 ab, mixDone, 0); 352 ab, mixDone, zero);
354 } 353 }
355 } 354 }
356 355
357 mixDone -= mixResult; 356 mixDone -= mixResult;
358 ab += mixResult * mixer->outChannels; 357 ab += mixResult * mixer->outChannels;
516 JSSChannel *c; 515 JSSChannel *c;
517 516
518 JSS_LOCK(mixer); 517 JSS_LOCK(mixer);
519 c = &mixer->channels[channel]; 518 c = &mixer->channels[channel];
520 519
520 FP_SETHL(c->chSize, size, 0);
521 FP_SETHL(c->chLoopS, loopS, 0);
522 FP_SETHL(c->chLoopE, loopE, 0);
521 c->chData = data; 523 c->chData = data;
522 c->chSize = size;
523 c->chLoopS = loopS;
524 c->chLoopE = loopE;
525 c->chFlags = flags; 524 c->chFlags = flags;
526 c->chDirection = TRUE; 525 c->chDirection = TRUE;
527 c->chPos.dw = c->chDeltaO.dw = 0; 526 c->chPos.dw = c->chDeltaO.dw = 0;
528 527
529 JSS_UNLOCK(mixer); 528 JSS_UNLOCK(mixer);