A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 1365 lines 38 kB view raw
1/* MikMod sound library 2 (c) 1998, 1999, 2000 Miodrag Vallat and others - see file AUTHORS for 3 complete list. 4 5 This library is free software; you can redistribute it and/or modify 6 it under the terms of the GNU Library General Public License as 7 published by the Free Software Foundation; either version 2 of 8 the License, or (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU Library General Public License for more details. 14 15 You should have received a copy of the GNU Library General Public 16 License along with this library; if not, write to the Free Software 17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 18 02111-1307, USA. 19*/ 20 21/*============================================================================== 22 23 High-quality sample mixing routines, using a 32 bits mixing buffer, 24 interpolation, and sample smoothing to improve sound quality and remove 25 clicks. 26 27 Future Additions: 28 - Low-Pass filter to remove annoying staticy buzz. 29 30==============================================================================*/ 31 32#ifdef HAVE_CONFIG_H 33#include "config.h" 34#endif 35 36#include "mikmod.h" 37 38#ifndef NO_HQMIXER 39 40#ifdef HAVE_MEMORY_H 41#include <memory.h> 42#endif 43#include <string.h> 44 45#include "mikmod_internals.h" 46 47/* 48 Constant Definitions 49 ==================== 50 51 MAXVOL_FACTOR (was BITSHIFT in virtch.c) 52 Controls the maximum volume of the output data. All mixed data is 53 divided by this number after mixing, so larger numbers result in 54 quieter mixing. Smaller numbers will increase the likeliness of 55 distortion on loud modules. 56 57 REVERBERATION 58 Larger numbers result in shorter reverb duration. Longer reverb 59 durations can cause unwanted static and make the reverb sound more 60 like a crappy echo. 61 62 SAMPLING_SHIFT 63 Specified the shift multiplier which controls by how much the mixing 64 rate is multiplied while mixing. Higher values can improve quality by 65 smoothing the sound and reducing pops and clicks. Note, this is a shift 66 value, so a value of 2 becomes a mixing-rate multiplier of 4, and a 67 value of 3 = 8, etc. 68 69 FRACBITS 70 The number of bits per integer devoted to the fractional part of the 71 number. Generally, this number should not be changed for any reason. 72 73 !!! IMPORTANT !!! All values below MUST ALWAYS be greater than 0 74 75*/ 76 77#define BITSHIFT 9 78#define MAXVOL_FACTOR (1<<BITSHIFT) 79#define REVERBERATION 11000L 80 81#define SAMPLING_SHIFT 2 82#define SAMPLING_FACTOR (1UL<<SAMPLING_SHIFT) 83 84#define FRACBITS 28 85#define FRACMASK ((1UL<<FRACBITS)-1UL) 86 87#define TICKLSIZE 8192 88#define TICKWSIZE (TICKLSIZE * 2) 89#define TICKBSIZE (TICKWSIZE * 2) 90 91#define CLICK_SHIFT_BASE 6 92#define CLICK_SHIFT (CLICK_SHIFT_BASE + SAMPLING_SHIFT) 93#define CLICK_BUFFER (1L << CLICK_SHIFT) 94 95#ifndef MIN 96#define MIN(a,b) (((a)<(b)) ? (a) : (b)) 97#endif 98 99typedef struct VINFO { 100 UBYTE kick; /* =1 -> sample has to be restarted */ 101 UBYTE active; /* =1 -> sample is playing */ 102 UWORD flags; /* 16/8 bits looping/one-shot */ 103 SWORD handle; /* identifies the sample */ 104 ULONG start; /* start index */ 105 ULONG size; /* samplesize */ 106 ULONG reppos; /* loop start */ 107 ULONG repend; /* loop end */ 108 ULONG frq; /* current frequency */ 109 int vol; /* current volume */ 110 int pan; /* current panning position */ 111 112 int click; 113 int rampvol; 114 SLONG lastvalL,lastvalR; 115 int lvolsel,rvolsel; /* Volume factor in range 0-255 */ 116 int oldlvol,oldrvol; 117 118 SLONGLONG current; /* current index in the sample */ 119 SLONGLONG increment; /* increment value */ 120} VINFO; 121 122static SWORD **Samples; 123static VINFO *vinf=NULL,*vnf; 124static long tickleft,samplesthatfit,vc_memory=0; 125static int vc_softchn; 126static SLONGLONG idxsize,idxlpos,idxlend; 127static SLONG *vc_tickbuf=NULL; 128static UWORD vc_mode; 129 130#ifdef _MSC_VER 131/* Weird bug in compiler */ /* FIXME is this still needed? */ 132typedef void (*MikMod_callback_t)(unsigned char *data, size_t len); 133#endif 134 135/* Reverb control variables */ 136 137static int RVc1, RVc2, RVc3, RVc4, RVc5, RVc6, RVc7, RVc8; 138static ULONG RVRindex; 139 140/* For Mono or Left Channel */ 141static SLONG *RVbufL1=NULL,*RVbufL2=NULL,*RVbufL3=NULL,*RVbufL4=NULL, 142 *RVbufL5=NULL,*RVbufL6=NULL,*RVbufL7=NULL,*RVbufL8=NULL; 143 144/* For Stereo only (Right Channel) */ 145static SLONG *RVbufR1=NULL,*RVbufR2=NULL,*RVbufR3=NULL,*RVbufR4=NULL, 146 *RVbufR5=NULL,*RVbufR6=NULL,*RVbufR7=NULL,*RVbufR8=NULL; 147 148#ifdef NATIVE_64BIT_INT 149#define NATIVE SLONGLONG 150#else 151#define NATIVE SLONG 152#endif 153 154/*========== 32 bit sample mixers - only for 32 bit platforms */ 155#ifndef NATIVE_64BIT_INT 156 157static SLONG Mix32MonoNormal(const SWORD* const srce,SLONG* dest,SLONG idx,SLONG increment,SLONG todo) 158{ 159 SWORD sample=0; 160 SLONG i,f; 161 162 while(todo--) { 163 i=idx>>FRACBITS,f=idx&FRACMASK; 164 sample=(SWORD)( (((SLONG)(srce[i]*(FRACMASK+1L-f)) + 165 ((SLONG)srce[i+1]*f)) >> FRACBITS)); 166 idx+=increment; 167 168 if(vnf->rampvol) { 169 *dest++ += (long)( 170 ( ( (SLONG)(vnf->oldlvol*vnf->rampvol) + 171 (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) ) * 172 (SLONG)sample ) >> CLICK_SHIFT ); 173 vnf->rampvol--; 174 } else 175 if(vnf->click) { 176 *dest++ += (long)( 177 ( ( ((SLONG)vnf->lvolsel*(CLICK_BUFFER-vnf->click)) * 178 (SLONG)sample ) + 179 (vnf->lastvalL*vnf->click) ) >> CLICK_SHIFT ); 180 vnf->click--; 181 } else 182 *dest++ +=vnf->lvolsel*sample; 183 } 184 vnf->lastvalL=vnf->lvolsel * sample; 185 186 return idx; 187} 188 189static SLONG Mix32StereoNormal(const SWORD* const srce,SLONG* dest,SLONG idx,SLONG increment,ULONG todo) 190{ 191 SWORD sample=0; 192 SLONG i,f; 193 194 while(todo--) { 195 i=idx>>FRACBITS,f=idx&FRACMASK; 196 sample=(SWORD)(((((SLONG)srce[i]*(FRACMASK+1L-f)) + 197 ((SLONG)srce[i+1] * f)) >> FRACBITS)); 198 idx += increment; 199 200 if(vnf->rampvol) { 201 *dest++ += (long)( 202 ( ( ((SLONG)vnf->oldlvol*vnf->rampvol) + 203 (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) 204 ) * (SLONG)sample ) >> CLICK_SHIFT ); 205 *dest++ += (long)( 206 ( ( ((SLONG)vnf->oldrvol*vnf->rampvol) + 207 (vnf->rvolsel*(CLICK_BUFFER-vnf->rampvol)) 208 ) * (SLONG)sample ) >> CLICK_SHIFT ); 209 vnf->rampvol--; 210 } else 211 if(vnf->click) { 212 *dest++ += (long)( 213 ( ( (SLONG)(vnf->lvolsel*(CLICK_BUFFER-vnf->click)) * 214 (SLONG)sample ) + (vnf->lastvalL * vnf->click) ) 215 >> CLICK_SHIFT ); 216 *dest++ += (long)( 217 ( ( ((SLONG)vnf->rvolsel*(CLICK_BUFFER-vnf->click)) * 218 (SLONG)sample ) + (vnf->lastvalR * vnf->click) ) 219 >> CLICK_SHIFT ); 220 vnf->click--; 221 } else { 222 *dest++ +=vnf->lvolsel*sample; 223 *dest++ +=vnf->rvolsel*sample; 224 } 225 } 226 vnf->lastvalL=vnf->lvolsel*sample; 227 vnf->lastvalR=vnf->rvolsel*sample; 228 229 return idx; 230} 231 232static SLONG Mix32StereoSurround(const SWORD* const srce,SLONG* dest,SLONG idx,SLONG increment,ULONG todo) 233{ 234 SWORD sample=0; 235 long whoop; 236 SLONG i, f; 237 238 while(todo--) { 239 i=idx>>FRACBITS,f=idx&FRACMASK; 240 sample=(SWORD)(((((SLONG)srce[i]*(FRACMASK+1L-f)) + 241 ((SLONG)srce[i+1]*f)) >> FRACBITS)); 242 idx+=increment; 243 244 if(vnf->rampvol) { 245 whoop=(long)( 246 ( ( (SLONG)(vnf->oldlvol*vnf->rampvol) + 247 (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) ) * 248 (SLONG)sample) >> CLICK_SHIFT ); 249 *dest++ +=whoop; 250 *dest++ -=whoop; 251 vnf->rampvol--; 252 } else 253 if(vnf->click) { 254 whoop = (long)( 255 ( ( ((SLONG)vnf->lvolsel*(CLICK_BUFFER-vnf->click)) * 256 (SLONG)sample) + 257 (vnf->lastvalL * vnf->click) ) >> CLICK_SHIFT ); 258 *dest++ +=whoop; 259 *dest++ -=whoop; 260 vnf->click--; 261 } else { 262 *dest++ +=vnf->lvolsel*sample; 263 *dest++ -=vnf->lvolsel*sample; 264 } 265 } 266 vnf->lastvalL=vnf->lvolsel*sample; 267 vnf->lastvalR=vnf->lvolsel*sample; 268 269 return idx; 270} 271#endif 272 273/*========== 64 bit mixers */ 274 275static SLONGLONG MixMonoNormal(const SWORD* const srce,SLONG* dest,SLONGLONG idx,SLONGLONG increment,SLONG todo) 276{ 277 SWORD sample=0; 278 SLONGLONG i,f; 279 280 while(todo--) { 281 i=idx>>FRACBITS,f=idx&FRACMASK; 282 sample=(SWORD)((((SLONGLONG)(srce[i]*(FRACMASK+1L-f)) + 283 ((SLONGLONG)srce[i+1]*f)) >> FRACBITS)); 284 idx+=increment; 285 286 if(vnf->rampvol) { 287 *dest++ += (long)( 288 ( ( (SLONGLONG)(vnf->oldlvol*vnf->rampvol) + 289 (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) ) * 290 (SLONGLONG)sample ) >> CLICK_SHIFT ); 291 vnf->rampvol--; 292 } else 293 if(vnf->click) { 294 *dest++ += (long)( 295 ( ( ((SLONGLONG)vnf->lvolsel*(CLICK_BUFFER-vnf->click)) * 296 (SLONGLONG)sample ) + 297 (vnf->lastvalL*vnf->click) ) >> CLICK_SHIFT ); 298 vnf->click--; 299 } else 300 *dest++ +=vnf->lvolsel*sample; 301 } 302 vnf->lastvalL=vnf->lvolsel * sample; 303 304 return idx; 305} 306 307/* Slowest part... */ 308 309#if defined HAVE_SSE2 || defined HAVE_ALTIVEC 310 311static __inline SWORD GetSample(const SWORD* const srce, SLONGLONG idx) 312{ 313 SLONGLONG i=idx>>FRACBITS; 314 SLONGLONG f=idx&FRACMASK; 315 return (SWORD)(((((SLONGLONG)srce[i]*(FRACMASK+1L-f)) + 316 ((SLONGLONG)srce[i+1] * f)) >> FRACBITS)); 317} 318 319static SLONGLONG MixSIMDStereoNormal(const SWORD* const srce,SLONG* dest,SLONGLONG idx,SLONGLONG increment,ULONG todo) 320{ 321 SWORD vol[8] = {vnf->lvolsel, vnf->rvolsel}; 322 SWORD sample=0; 323 SLONG remain = todo; 324 325 /* Dest can be misaligned */ 326 while(!IS_ALIGNED_16(dest)) { 327 sample=srce[idx >> FRACBITS]; 328 idx += increment; 329 *dest++ += vol[0] * sample; 330 *dest++ += vol[1] * sample; 331 todo--; 332 if(!todo) goto end; 333 } 334 335 /* Srce is always aligned */ 336 337#if defined HAVE_SSE2 338 remain = todo&3; 339 { 340 __m128i v0 = _mm_set_epi16(0, vol[1], 341 0, vol[0], 342 0, vol[1], 343 0, vol[0]); 344 for(todo>>=2;todo; todo--) 345 { 346 SWORD s0 = GetSample(srce, idx); 347 SWORD s1 = GetSample(srce, idx += increment); 348 SWORD s2 = GetSample(srce, idx += increment); 349 SWORD s3 = GetSample(srce, idx += increment); 350 __m128i v1 = _mm_set_epi16(0, s1, 0, s1, 0, s0, 0, s0); 351 __m128i v2 = _mm_set_epi16(0, s3, 0, s3, 0, s2, 0, s2); 352 __m128i v3 = _mm_load_si128((__m128i*)(dest+0)); 353 __m128i v4 = _mm_load_si128((__m128i*)(dest+4)); 354 _mm_store_si128((__m128i*)(dest+0), _mm_add_epi32(v3, _mm_madd_epi16(v0, v1))); 355 _mm_store_si128((__m128i*)(dest+4), _mm_add_epi32(v4, _mm_madd_epi16(v0, v2))); 356 dest+=8; 357 idx += increment; 358 } 359 } 360 361#elif defined HAVE_ALTIVEC 362 remain = todo&3; 363 { 364 SWORD s[8]; 365 vector signed short r0 = vec_ld(0, vol); 366 vector signed short v0 = vec_perm(r0, r0, (vector unsigned char)(0, 1, /* l */ 367 0, 1, /* l */ 368 2, 3, /* r */ 369 2, 1, /* r */ 370 0, 1, /* l */ 371 0, 1, /* l */ 372 2, 3, /* r */ 373 2, 3 /* r */ 374 )); 375 376 for(todo>>=2;todo; todo--) 377 { 378 vector short int r1; 379 vector signed short v1, v2; 380 vector signed int v3, v4, v5, v6; 381 382 /* Load constants */ 383 s[0] = GetSample(srce, idx); 384 s[1] = GetSample(srce, idx += increment); 385 s[2] = GetSample(srce, idx += increment); 386 s[3] = GetSample(srce, idx += increment); 387 s[4] = 0; 388 389 r1 = vec_ld(0, s); 390 v1 = vec_perm(r1, r1, (vector unsigned char) 391 (0*2, 0*2+1, /* s0 */ 392 4*2, 4*2+1, /* 0 */ 393 0*2, 0*2+1, /* s0 */ 394 4*2, 4*2+1, /* 0 */ 395 1*2, 1*2+1, /* s1 */ 396 4*2, 4*2+1, /* 0 */ 397 1*2, 1*2+1, /* s1 */ 398 4*2, 4*2+1 /* 0 */ 399 ) ); 400 v2 = vec_perm(r1, r1, (vector unsigned char) 401 (2*2, 2*2+1, /* s2 */ 402 4*2, 4*2+1, /* 0 */ 403 2*2, 2*2+1, /* s2 */ 404 4*2, 4*2+1, /* 0 */ 405 3*2, 3*2+1, /* s3 */ 406 4*2, 4*2+1, /* 0 */ 407 3*2, 3*2+1, /* s3 */ 408 4*2, 4*2+1 /* 0 */ 409 ) ); 410 411 v3 = vec_ld(0, dest); 412 v4 = vec_ld(0x10, dest); 413 v5 = vec_mule(v0, v1); 414 v6 = vec_mule(v0, v2); 415 416 vec_st(vec_add(v3, v5), 0, dest); 417 vec_st(vec_add(v4, v6), 0x10, dest); 418 419 dest+=8; 420 idx += increment; 421 } 422 } 423#endif /* HAVE_ALTIVEC */ 424 425 /* Remaining bits */ 426 while(remain--) { 427 sample=GetSample(srce, idx); 428 idx+= increment; 429 *dest++ += vol[0] * sample; 430 *dest++ += vol[1] * sample; 431 } 432end: 433 vnf->lastvalL=vnf->lvolsel*sample; 434 vnf->lastvalR=vnf->rvolsel*sample; 435 return idx; 436} 437 438static SLONGLONG MixStereoNormal(const SWORD* const srce,SLONG* dest,SLONGLONG idx,SLONGLONG increment,ULONG todo) 439{ 440 SWORD sample=0; 441 SLONGLONG i,f; 442 443 if (vnf->rampvol) 444 while(todo) { 445 todo--; 446 i=idx>>FRACBITS,f=idx&FRACMASK; 447 sample=(SWORD)(((((SLONGLONG)srce[i]*(FRACMASK+1L-f)) + 448 ((SLONGLONG)srce[i+1] * f)) >> FRACBITS)); 449 idx += increment; 450 451 *dest++ += (long)( 452 ( ( ((SLONGLONG)vnf->oldlvol*vnf->rampvol) + 453 (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) 454 ) * (SLONGLONG)sample ) >> CLICK_SHIFT ); 455 *dest++ += (long)( 456 ( ( ((SLONGLONG)vnf->oldrvol*vnf->rampvol) + 457 (vnf->rvolsel*(CLICK_BUFFER-vnf->rampvol)) 458 ) * (SLONGLONG)sample ) >> CLICK_SHIFT ); 459 vnf->rampvol--; 460 461 if (!vnf->rampvol) 462 break; 463 } 464 465 if (vnf->click) 466 while(todo) { 467 todo--; 468 i=idx>>FRACBITS,f=idx&FRACMASK; 469 sample=(SWORD)(((((SLONGLONG)srce[i]*(FRACMASK+1L-f)) + 470 ((SLONGLONG)srce[i+1] * f)) >> FRACBITS)); 471 idx += increment; 472 473 *dest++ += (long)( 474 ( ( (SLONGLONG)(vnf->lvolsel*(CLICK_BUFFER-vnf->click)) * 475 (SLONGLONG)sample ) + (vnf->lastvalL * vnf->click) ) 476 >> CLICK_SHIFT ); 477 478 *dest++ += (long)( 479 ( ( ((SLONGLONG)vnf->rvolsel*(CLICK_BUFFER-vnf->click)) * 480 (SLONGLONG)sample ) + (vnf->lastvalR * vnf->click) ) 481 >> CLICK_SHIFT ); 482 vnf->click--; 483 484 if (!vnf->click) 485 break; 486 } 487 488 if (todo) 489 { 490 if (md_mode & DMODE_SIMDMIXER) { 491 return MixSIMDStereoNormal(srce, dest, idx, increment, todo); 492 } 493 while(todo) 494 { 495 i=idx>>FRACBITS, 496 f=idx&FRACMASK; 497 sample=(SWORD)(((((SLONGLONG)srce[i]*(FRACMASK+1L-f)) + 498 ((SLONGLONG)srce[i+1] * f)) >> FRACBITS)); 499 idx += increment; 500 501 *dest++ +=vnf->lvolsel*sample; 502 *dest++ +=vnf->rvolsel*sample; 503 todo--; 504 } 505 } 506 vnf->lastvalL=vnf->lvolsel*sample; 507 vnf->lastvalR=vnf->rvolsel*sample; 508 509 return idx; 510} 511 512#else /* HAVE_SSE2 || HAVE_ALTIVEC */ 513static SLONGLONG MixStereoNormal(const SWORD* const srce,SLONG* dest,SLONGLONG idx,SLONGLONG increment,ULONG todo) 514{ 515 SWORD sample=0; 516 SLONGLONG i,f; 517 518 while(todo--) { 519 i=idx>>FRACBITS,f=idx&FRACMASK; 520 sample=(SWORD)(((((SLONGLONG)srce[i]*(FRACMASK+1L-f)) + 521 ((SLONGLONG)srce[i+1] * f)) >> FRACBITS)); 522 idx += increment; 523 524 if(vnf->rampvol) { 525 *dest++ += (long)( 526 ( ( ((SLONGLONG)vnf->oldlvol*vnf->rampvol) + 527 (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) 528 ) * (SLONGLONG)sample ) >> CLICK_SHIFT ); 529 *dest++ += (long)( 530 ( ( ((SLONGLONG)vnf->oldrvol*vnf->rampvol) + 531 (vnf->rvolsel*(CLICK_BUFFER-vnf->rampvol)) 532 ) * (SLONGLONG)sample ) >> CLICK_SHIFT ); 533 vnf->rampvol--; 534 } else 535 if(vnf->click) { 536 *dest++ += (long)( 537 ( ( (SLONGLONG)(vnf->lvolsel*(CLICK_BUFFER-vnf->click)) * 538 (SLONGLONG)sample ) + (vnf->lastvalL * vnf->click) ) 539 >> CLICK_SHIFT ); 540 *dest++ += (long)( 541 ( ( ((SLONGLONG)vnf->rvolsel*(CLICK_BUFFER-vnf->click)) * 542 (SLONGLONG)sample ) + (vnf->lastvalR * vnf->click) ) 543 >> CLICK_SHIFT ); 544 vnf->click--; 545 } else { 546 *dest++ +=vnf->lvolsel*sample; 547 *dest++ +=vnf->rvolsel*sample; 548 } 549 } 550 vnf->lastvalL=vnf->lvolsel*sample; 551 vnf->lastvalR=vnf->rvolsel*sample; 552 553 return idx; 554} 555#endif /* HAVE_SSE2 || HAVE_ALTIVEC */ 556 557 558static SLONGLONG MixStereoSurround(const SWORD* srce,SLONG* dest,SLONGLONG idx,SLONGLONG increment,ULONG todo) 559{ 560 SWORD sample=0; 561 long whoop; 562 SLONGLONG i, f; 563 564 while(todo--) { 565 i=idx>>FRACBITS,f=idx&FRACMASK; 566 sample=(SWORD)(((((SLONGLONG)srce[i]*(FRACMASK+1L-f)) + 567 ((SLONGLONG)srce[i+1]*f)) >> FRACBITS)); 568 idx+=increment; 569 570 if(vnf->rampvol) { 571 whoop=(long)( 572 ( ( (SLONGLONG)(vnf->oldlvol*vnf->rampvol) + 573 (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) ) * 574 (SLONGLONG)sample) >> CLICK_SHIFT ); 575 *dest++ +=whoop; 576 *dest++ -=whoop; 577 vnf->rampvol--; 578 } else 579 if(vnf->click) { 580 whoop = (long)( 581 ( ( ((SLONGLONG)vnf->lvolsel*(CLICK_BUFFER-vnf->click)) * 582 (SLONGLONG)sample) + 583 (vnf->lastvalL * vnf->click) ) >> CLICK_SHIFT ); 584 *dest++ +=whoop; 585 *dest++ -=whoop; 586 vnf->click--; 587 } else { 588 *dest++ +=vnf->lvolsel*sample; 589 *dest++ -=vnf->lvolsel*sample; 590 } 591 } 592 vnf->lastvalL=vnf->lvolsel*sample; 593 vnf->lastvalR=vnf->lvolsel*sample; 594 595 return idx; 596} 597 598static void(*Mix32toFP)(float* dste,const SLONG *srce,NATIVE count); 599static void(*Mix32to16)(SWORD* dste,const SLONG *srce,NATIVE count); 600static void(*Mix32to8)(SBYTE* dste,const SLONG *srce,NATIVE count); 601static void(*MixReverb)(SLONG *srce,NATIVE count); 602 603/* Reverb macros */ 604#define COMPUTE_LOC(n) loc##n = RVRindex % RVc##n 605#define COMPUTE_LECHO(n) RVbufL##n [loc##n ]=speedup+((ReverbPct*RVbufL##n [loc##n ])>>7) 606#define COMPUTE_RECHO(n) RVbufR##n [loc##n ]=speedup+((ReverbPct*RVbufR##n [loc##n ])>>7) 607 608static void MixReverb_Normal(SLONG *srce,NATIVE count) 609{ 610 NATIVE speedup; 611 int ReverbPct; 612 unsigned int loc1,loc2,loc3,loc4,loc5,loc6,loc7,loc8; 613 614 ReverbPct=58+(md_reverb*4); 615 616 COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4); 617 COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8); 618 619 while(count--) { 620 /* Compute the left channel echo buffers */ 621 speedup = *srce >> 3; 622 623 COMPUTE_LECHO(1); COMPUTE_LECHO(2); COMPUTE_LECHO(3); COMPUTE_LECHO(4); 624 COMPUTE_LECHO(5); COMPUTE_LECHO(6); COMPUTE_LECHO(7); COMPUTE_LECHO(8); 625 626 /* Prepare to compute actual finalized data */ 627 RVRindex++; 628 629 COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4); 630 COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8); 631 632 /* left channel */ 633 *srce++ +=RVbufL1[loc1]-RVbufL2[loc2]+RVbufL3[loc3]-RVbufL4[loc4]+ 634 RVbufL5[loc5]-RVbufL6[loc6]+RVbufL7[loc7]-RVbufL8[loc8]; 635 } 636} 637 638static void MixReverb_Stereo(SLONG *srce,NATIVE count) 639{ 640 NATIVE speedup; 641 int ReverbPct; 642 unsigned int loc1,loc2,loc3,loc4,loc5,loc6,loc7,loc8; 643 644 ReverbPct=58+(md_reverb*4); 645 646 COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4); 647 COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8); 648 649 while(count--) { 650 /* Compute the left channel echo buffers */ 651 speedup = *srce >> 3; 652 653 COMPUTE_LECHO(1); COMPUTE_LECHO(2); COMPUTE_LECHO(3); COMPUTE_LECHO(4); 654 COMPUTE_LECHO(5); COMPUTE_LECHO(6); COMPUTE_LECHO(7); COMPUTE_LECHO(8); 655 656 /* Compute the right channel echo buffers */ 657 speedup = srce[1] >> 3; 658 659 COMPUTE_RECHO(1); COMPUTE_RECHO(2); COMPUTE_RECHO(3); COMPUTE_RECHO(4); 660 COMPUTE_RECHO(5); COMPUTE_RECHO(6); COMPUTE_RECHO(7); COMPUTE_RECHO(8); 661 662 /* Prepare to compute actual finalized data */ 663 RVRindex++; 664 665 COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4); 666 COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8); 667 668 /* left channel */ 669 *srce++ +=RVbufL1[loc1]-RVbufL2[loc2]+RVbufL3[loc3]-RVbufL4[loc4]+ 670 RVbufL5[loc5]-RVbufL6[loc6]+RVbufL7[loc7]-RVbufL8[loc8]; 671 672 /* right channel */ 673 *srce++ +=RVbufR1[loc1]-RVbufR2[loc2]+RVbufR3[loc3]-RVbufR4[loc4]+ 674 RVbufR5[loc5]-RVbufR6[loc6]+RVbufR7[loc7]-RVbufR8[loc8]; 675 } 676} 677 678static void (*MixLowPass)(SLONG* srce,NATIVE count); 679 680static int nLeftNR, nRightNR; 681 682static void MixLowPass_Stereo(SLONG* srce,NATIVE count) 683{ 684 int n1 = nLeftNR, n2 = nRightNR; 685 SLONG *pnr = srce; 686 int nr=count; 687 for (; nr; nr--) 688 { 689 int vnr = pnr[0] >> 1; 690 pnr[0] = vnr + n1; 691 n1 = vnr; 692 vnr = pnr[1] >> 1; 693 pnr[1] = vnr + n2; 694 n2 = vnr; 695 pnr += 2; 696 } 697 nLeftNR = n1; 698 nRightNR = n2; 699} 700 701static void MixLowPass_Normal(SLONG* srce,NATIVE count) 702{ 703 int n1 = nLeftNR; 704 SLONG *pnr = srce; 705 int nr=count; 706 for (; nr; nr--) 707 { 708 int vnr = pnr[0] >> 1; 709 pnr[0] = vnr + n1; 710 n1 = vnr; 711 pnr ++; 712 } 713 nLeftNR = n1; 714} 715 716/* Mixing macros */ 717#define EXTRACT_SAMPLE_FP(var,attenuation) var=*srce++*((1.0f / 32768.0f) / (MAXVOL_FACTOR*attenuation)) 718#define CHECK_SAMPLE_FP(var,bound) var=(var>bound)?bound:(var<-bound)?-bound:var 719 720static void Mix32ToFP_Normal(float* dste,const SLONG *srce,NATIVE count) 721{ 722 float x1,x2,tmpx; 723 int i; 724 725 for(count/=SAMPLING_FACTOR;count;count--) { 726 tmpx=0.0f; 727 728 for(i=SAMPLING_FACTOR/2;i;i--) { 729 EXTRACT_SAMPLE_FP(x1,1.0f); EXTRACT_SAMPLE_FP(x2,1.0f); 730 731 CHECK_SAMPLE_FP(x1,1.0f); CHECK_SAMPLE_FP(x2,1.0f); 732 733 tmpx+=x1+x2; 734 } 735 *dste++ =tmpx*(1.0f/SAMPLING_FACTOR); 736 } 737} 738 739static void Mix32ToFP_Stereo(float* dste,const SLONG *srce,NATIVE count) 740{ 741 float x1,x2,x3,x4,tmpx,tmpy; 742 int i; 743 744 for(count/=SAMPLING_FACTOR;count;count--) { 745 tmpx=tmpy=0.0f; 746 747 for(i=SAMPLING_FACTOR/2;i;i--) { 748 EXTRACT_SAMPLE_FP(x1,1.0f); EXTRACT_SAMPLE_FP(x2,1.0f); 749 EXTRACT_SAMPLE_FP(x3,1.0f); EXTRACT_SAMPLE_FP(x4,1.0f); 750 751 CHECK_SAMPLE_FP(x1,1.0f); CHECK_SAMPLE_FP(x2,1.0f); 752 CHECK_SAMPLE_FP(x3,1.0f); CHECK_SAMPLE_FP(x4,1.0f); 753 754 tmpx+=x1+x3; 755 tmpy+=x2+x4; 756 } 757 *dste++ =tmpx*(1.0f/SAMPLING_FACTOR); 758 *dste++ =tmpy*(1.0f/SAMPLING_FACTOR); 759 } 760} 761 762/* Mixing macros */ 763#define EXTRACT_SAMPLE(var,attenuation) var=*srce++/(MAXVOL_FACTOR*attenuation) 764#define CHECK_SAMPLE(var,bound) var=(var>=bound)?bound-1:(var<-bound)?-bound:var 765 766static void Mix32To16_Normal(SWORD* dste,const SLONG *srce,NATIVE count) 767{ 768 NATIVE x1,x2,tmpx; 769 int i; 770 771 for(count/=SAMPLING_FACTOR;count;count--) { 772 tmpx=0; 773 774 for(i=SAMPLING_FACTOR/2;i;i--) { 775 EXTRACT_SAMPLE(x1,1); EXTRACT_SAMPLE(x2,1); 776 777 CHECK_SAMPLE(x1,32768); CHECK_SAMPLE(x2,32768); 778 779 tmpx+=x1+x2; 780 } 781 *dste++ =(SWORD)(tmpx/SAMPLING_FACTOR); 782 } 783} 784 785 786static void Mix32To16_Stereo(SWORD* dste,const SLONG *srce,NATIVE count) 787{ 788 NATIVE x1,x2,x3,x4,tmpx,tmpy; 789 int i; 790 791 for(count/=SAMPLING_FACTOR;count;count--) { 792 tmpx=tmpy=0; 793 794 for(i=SAMPLING_FACTOR/2;i;i--) { 795 EXTRACT_SAMPLE(x1,1); EXTRACT_SAMPLE(x2,1); 796 EXTRACT_SAMPLE(x3,1); EXTRACT_SAMPLE(x4,1); 797 798 CHECK_SAMPLE(x1,32768); CHECK_SAMPLE(x2,32768); 799 CHECK_SAMPLE(x3,32768); CHECK_SAMPLE(x4,32768); 800 801 tmpx+=x1+x3; 802 tmpy+=x2+x4; 803 } 804 *dste++ =(SWORD)(tmpx/SAMPLING_FACTOR); 805 *dste++ =(SWORD)(tmpy/SAMPLING_FACTOR); 806 } 807} 808 809static void Mix32To8_Normal(SBYTE* dste,const SLONG *srce,NATIVE count) 810{ 811 NATIVE x1,x2,tmpx; 812 int i; 813 814 for(count/=SAMPLING_FACTOR;count;count--) { 815 tmpx = 0; 816 817 for(i=SAMPLING_FACTOR/2;i;i--) { 818 EXTRACT_SAMPLE(x1,256); EXTRACT_SAMPLE(x2,256); 819 820 CHECK_SAMPLE(x1,128); CHECK_SAMPLE(x2,128); 821 822 tmpx+=x1+x2; 823 } 824 *dste++ = (SBYTE)((tmpx/SAMPLING_FACTOR)+128); 825 } 826} 827 828static void Mix32To8_Stereo(SBYTE* dste,const SLONG *srce,NATIVE count) 829{ 830 NATIVE x1,x2,x3,x4,tmpx,tmpy; 831 int i; 832 833 for(count/=SAMPLING_FACTOR;count;count--) { 834 tmpx=tmpy=0; 835 836 for(i=SAMPLING_FACTOR/2;i;i--) { 837 EXTRACT_SAMPLE(x1,256); EXTRACT_SAMPLE(x2,256); 838 EXTRACT_SAMPLE(x3,256); EXTRACT_SAMPLE(x4,256); 839 840 CHECK_SAMPLE(x1,128); CHECK_SAMPLE(x2,128); 841 CHECK_SAMPLE(x3,128); CHECK_SAMPLE(x4,128); 842 843 tmpx+=x1+x3; 844 tmpy+=x2+x4; 845 } 846 *dste++ =(SBYTE)((tmpx/SAMPLING_FACTOR)+128); 847 *dste++ =(SBYTE)((tmpy/SAMPLING_FACTOR)+128); 848 } 849} 850 851#if defined HAVE_SSE2 852#define SHIFT_MIX_TO_16 (BITSHIFT + 16 - 16) 853/* TEST: Ok */ 854static void Mix32To16_Stereo_SIMD_4Tap(SWORD* dste, const SLONG* srce, NATIVE count) 855{ 856 int remain = count; 857 858 /* Check unaligned dste buffer. srce is always aligned. */ 859 while(!IS_ALIGNED_16(dste)) 860 { 861 Mix32To16_Stereo(dste, srce, SAMPLING_FACTOR); 862 dste+=2; 863 srce+=8; 864 count--; 865 if(!count) return; 866 } 867 868 /* dste and srce aligned. srce is always aligned. */ 869 remain = count & 15; 870 /* count / 2 for 1 sample */ 871 872 for(count>>=4;count;count--) 873 { 874 /* Load 32bit sample. 1st average */ 875 __m128i v0 = _mm_add_epi32( 876 _mm_srai_epi32(_mm_loadu_si128((__m128i const *)(srce+0)), SHIFT_MIX_TO_16), 877 _mm_srai_epi32(_mm_loadu_si128((__m128i const *)(srce+4)), SHIFT_MIX_TO_16) 878 ); /* v0: s0.l+s2.l | s0.r+s2.r | s1.l+s3.l | s1.r+s3.r */ 879 880 /* 2nd average (s0.l+s2.l+s1.l+s3.l / 4, s0.r+s2.r+s1.r+s3.r / 4). Upper 64bit is unused (1 stereo sample) */ 881 __m128i v1 = _mm_srai_epi32(_mm_add_epi32(v0, mm_hiqq(v0)), 2); 882 /* v1: s0.l+s2.l / 4 | s0.r+s2.r / 4 | s1.l+s3.l+s0.l+s2.l / 4 | s1.r+s3.r+s0.r+s2.r / 4 */ 883 884 __m128i v2 = _mm_add_epi32( 885 _mm_srai_epi32(_mm_loadu_si128((__m128i const *)(srce+8)), SHIFT_MIX_TO_16), 886 _mm_srai_epi32(_mm_loadu_si128((__m128i const *)(srce+12)), SHIFT_MIX_TO_16) 887 ); /* v2: s4.l+s6.l | s4.r+s6.r | s5.l+s7.l | s5.r+s7.r */ 888 889 __m128i v3 = _mm_srai_epi32(_mm_add_epi32(v2, mm_hiqq(v2)), 2); /* Upper 64bit is unused */ 890 /* v3: s4.l+s6.l /4 | s4.r+s6.r / 4| s5.l+s7.l+s4.l+s6.l / 4 | s5.r+s7.r+s4.r+s6.l / 4 */ 891 892 /* pack two stereo samples in one */ 893 __m128i v4 = _mm_unpacklo_epi64(v1, v3); /* v4 = avg(s0,s1,s2,s3) | avg(s4,s5,s6,s7) */ 894 895 __m128i v6; 896 897 /* Load 32bit sample. 1st average (s0.l+s2.l, s0.r+s2.r, s1.l+s3.l, s1.r+s3.r) */ 898 v0 = _mm_add_epi32( 899 _mm_srai_epi32(_mm_loadu_si128((__m128i const *)(srce+16)), SHIFT_MIX_TO_16), 900 _mm_srai_epi32(_mm_loadu_si128((__m128i const *)(srce+20)), SHIFT_MIX_TO_16) 901 ); /* 128bit = 2 stereo samples */ 902 903 /* 2nd average (s0.l+s2.l+s1.l+s3.l / 4, s0.r+s2.r+s1.r+s3.r / 4). Upper 64bit is unused (1 stereo sample) */ 904 v1 = _mm_srai_epi32(_mm_add_epi32(v0, mm_hiqq(v0)), 2); 905 906 v2 = _mm_add_epi32( 907 _mm_srai_epi32(_mm_loadu_si128((__m128i const *)(srce+24)), SHIFT_MIX_TO_16), 908 _mm_srai_epi32(_mm_loadu_si128((__m128i const *)(srce+28)), SHIFT_MIX_TO_16) 909 ); 910 911 v3 = _mm_srai_epi32(_mm_add_epi32(v2, mm_hiqq(v2)), 2); /* Upper 64bit is unused */ 912 913 /* pack two stereo samples in one */ 914 v6 = _mm_unpacklo_epi64(v1, v3); /* v6 = avg(s8,s9,s10,s11) | avg(s12,s13,s14,s15) */ 915 916 _mm_store_si128((__m128i*)dste, _mm_packs_epi32(v4, v6)); /* 4 interpolated stereo sample 32bit to 4 */ 917 918 dste+=8; 919 srce+=32; /* 32 = 4 * 8 */ 920 } 921 922 /* FIXME: THIS PART WRITES PAST DST !! */ 923 if (remain) 924 { 925 Mix32To16_Stereo(dste, srce, remain); 926 } 927} 928 929#elif defined HAVE_ALTIVEC 930#define SHIFT_MIX_TO_16 vec_splat_u32(BITSHIFT + 16 - 16) 931/* TEST: Ok */ 932static void Mix32To16_Stereo_SIMD_4Tap(SWORD* dste, const SLONG* srce, NATIVE count) 933{ 934 int remain = count; 935 936 /* Check unaligned dste buffer. srce is always aligned. */ 937 while(!IS_ALIGNED_16(dste)) 938 { 939 Mix32To16_Stereo(dste, srce, SAMPLING_FACTOR); 940 dste+=2; 941 srce+=8; 942 count--; 943 if(!count) return; 944 } 945 946 /* dste and srce aligned. srce is always aligned. */ 947 remain = count & 15; 948 for(count>>=4;count;count--) 949 { 950 /* Load 32bit sample. 1st average (s0.l+s2.l, s0.r+s2.r, s1.l+s3.l, s1.r+s3.r) */ 951 vector signed int v0 = vec_add( 952 vec_sra(vec_ld(0, srce), SHIFT_MIX_TO_16), /* 128bit = 2 stereo samples */ 953 vec_sra(vec_ld(0x10, srce), SHIFT_MIX_TO_16) 954 ); /* 128bit = 2 stereo samples */ 955 956 /* 2nd average (s0.l+s2.l+s1.l+s3.l / 4, s0.r+s2.r+s1.r+s3.r / 4). Upper 64bit is unused (1 stereo sample) */ 957 vector signed int v1 = vec_sra(vec_add(v0, vec_hiqq(v0)), vec_splat_u32(2)); 958 959 vector signed int v2 = vec_add( 960 vec_sra(vec_ld(0x20, srce), SHIFT_MIX_TO_16), 961 vec_sra(vec_ld(0x30, srce), SHIFT_MIX_TO_16) 962 ); 963 964 vector signed int v3 = vec_sra(vec_add(v2, vec_hiqq(v2)), vec_splat_u32(2)); /* Upper 64bit is unused */ 965 966 /* pack two stereo samples in one */ 967 vector signed int v6, v4 = vec_unpacklo(v1, v3); /* v4 = lo64(v1) | lo64(v3) */ 968 969 /* Load 32bit sample. 1st average (s0.l+s2.l, s0.r+s2.r, s1.l+s3.l, s1.r+s3.r) */ 970 v0 = vec_add( 971 vec_sra(vec_ld(0x40, srce), SHIFT_MIX_TO_16), /* 128bit = 2 stereo samples */ 972 vec_sra(vec_ld(0x50, srce), SHIFT_MIX_TO_16) 973 ); /* 128bit = 2 stereo samples */ 974 975 /* 2nd average (s0.l+s2.l+s1.l+s3.l / 4, s0.r+s2.r+s1.r+s3.r / 4). Upper 64bit is unused (1 stereo sample) */ 976 v1 = vec_sra(vec_add(v0, vec_hiqq(v0)), vec_splat_u32(2)); 977 978 v2 = vec_add( 979 vec_sra(vec_ld(0x60, srce), SHIFT_MIX_TO_16), 980 vec_sra(vec_ld(0x70, srce), SHIFT_MIX_TO_16) 981 ); 982 983 v3 = vec_sra(vec_add(v2, vec_hiqq(v2)), vec_splat_u32(2)); /* Upper 64bit is unused */ 984 985 /* pack two stereo samples in one */ 986 v6 = vec_unpacklo(v1, v3); 987 988 vec_st(vec_packs(v4, v6), 0, dste); /* 4 interpolated stereo sample 32bit to 4 interpolated stereo sample 16bit + saturation */ 989 990 dste+=8; 991 srce+=32; /* 32 = 4 * 8 */ 992 } 993 994 if (remain) 995 { 996 Mix32To16_Stereo(dste, srce, remain); 997 } 998} 999 1000#endif 1001 1002 1003static void AddChannel(SLONG* ptr,NATIVE todo) 1004{ 1005 SLONGLONG end,done; 1006 SWORD *s; 1007 1008 if(!(s=Samples[vnf->handle])) { 1009 vnf->current = vnf->active = 0; 1010 vnf->lastvalL = vnf->lastvalR = 0; 1011 return; 1012 } 1013 1014 /* update the 'current' index so the sample loops, or stops playing if it 1015 reached the end of the sample */ 1016 while(todo>0) { 1017 SLONGLONG endpos; 1018 1019 if(vnf->flags & SF_REVERSE) { 1020 /* The sample is playing in reverse */ 1021 if((vnf->flags&SF_LOOP)&&(vnf->current<idxlpos)) { 1022 /* the sample is looping and has reached the loopstart index */ 1023 if(vnf->flags & SF_BIDI) { 1024 /* sample is doing bidirectional loops, so 'bounce' the 1025 current index against the idxlpos */ 1026 vnf->current = idxlpos+(idxlpos-vnf->current); 1027 vnf->flags &= ~SF_REVERSE; 1028 vnf->increment = -vnf->increment; 1029 } else 1030 /* normal backwards looping, so set the current position to 1031 loopend index */ 1032 vnf->current=idxlend-(idxlpos-vnf->current); 1033 } else { 1034 /* the sample is not looping, so check if it reached index 0 */ 1035 if(vnf->current < 0) { 1036 /* playing index reached 0, so stop playing this sample */ 1037 vnf->current = vnf->active = 0; 1038 break; 1039 } 1040 } 1041 } else { 1042 /* The sample is playing forward */ 1043 if((vnf->flags & SF_LOOP) && 1044 (vnf->current >= idxlend)) { 1045 /* the sample is looping, check the loopend index */ 1046 if(vnf->flags & SF_BIDI) { 1047 /* sample is doing bidirectional loops, so 'bounce' the 1048 current index against the idxlend */ 1049 vnf->flags |= SF_REVERSE; 1050 vnf->increment = -vnf->increment; 1051 vnf->current = idxlend-(vnf->current-idxlend); 1052 } else 1053 /* normal backwards looping, so set the current position 1054 to loopend index */ 1055 vnf->current=idxlpos+(vnf->current-idxlend); 1056 } else { 1057 /* sample is not looping, so check if it reached the last 1058 position */ 1059 if(vnf->current >= idxsize) { 1060 /* yes, so stop playing this sample */ 1061 vnf->current = vnf->active = 0; 1062 break; 1063 } 1064 } 1065 } 1066 1067 end=(vnf->flags&SF_REVERSE)?(vnf->flags&SF_LOOP)?idxlpos:0: 1068 (vnf->flags&SF_LOOP)?idxlend:idxsize; 1069 1070 /* if the sample is not blocked... */ 1071 if((vnf->increment>0 && vnf->current>=end) || 1072 (vnf->increment<0 && vnf->current<=end) || !vnf->increment) { 1073 done=0; 1074 } else { 1075 done=MIN((end-vnf->current)/vnf->increment+1,todo); 1076 if(done<0) done=0; 1077 } 1078 1079 if(!done) { 1080 vnf->active = 0; 1081 break; 1082 } 1083 1084 endpos=vnf->current+done*vnf->increment; 1085 1086 if(vnf->vol || vnf->rampvol) { 1087#ifndef NATIVE_64BIT_INT 1088 /* use the 32 bit mixers as often as we can (they're much faster) */ 1089 if((vnf->current<0x7fffffff)&&(endpos<0x7fffffff)) { 1090 if(vc_mode & DMODE_STEREO) { 1091 if((vnf->pan==PAN_SURROUND)&&(vc_mode&DMODE_SURROUND)) 1092 vnf->current=(SLONGLONG)Mix32StereoSurround 1093 (s,ptr,vnf->current,vnf->increment,done); 1094 else 1095 vnf->current=Mix32StereoNormal 1096 (s,ptr,vnf->current,vnf->increment,done); 1097 } else 1098 vnf->current=Mix32MonoNormal 1099 (s,ptr,vnf->current,vnf->increment,done); 1100 } 1101 else 1102#endif 1103 { 1104 if(vc_mode & DMODE_STEREO) { 1105 if((vnf->pan==PAN_SURROUND)&&(vc_mode&DMODE_SURROUND)) 1106 vnf->current=MixStereoSurround 1107 (s,ptr,vnf->current,vnf->increment,done); 1108 else 1109 vnf->current=MixStereoNormal 1110 (s,ptr,vnf->current,vnf->increment,done); 1111 } else 1112 vnf->current=MixMonoNormal 1113 (s,ptr,vnf->current,vnf->increment,done); 1114 } 1115 } else { 1116 vnf->lastvalL = vnf->lastvalR = 0; 1117 /* update sample position */ 1118 vnf->current=endpos; 1119 } 1120 1121 todo -= done; 1122 ptr += (vc_mode & DMODE_STEREO)?(done<<1):done; 1123 } 1124} 1125 1126#define _IN_VIRTCH_ 1127 1128#define VC1_SilenceBytes VC2_SilenceBytes 1129#define VC1_WriteSamples VC2_WriteSamples 1130#define VC1_WriteBytes VC2_WriteBytes 1131#define VC1_Exit VC2_Exit 1132#define VC1_VoiceSetVolume VC2_VoiceSetVolume 1133#define VC1_VoiceGetVolume VC2_VoiceGetVolume 1134#define VC1_VoiceSetPanning VC2_VoiceSetPanning 1135#define VC1_VoiceGetPanning VC2_VoiceGetPanning 1136#define VC1_VoiceSetFrequency VC2_VoiceSetFrequency 1137#define VC1_VoiceGetFrequency VC2_VoiceGetFrequency 1138#define VC1_VoicePlay VC2_VoicePlay 1139#define VC1_VoiceStop VC2_VoiceStop 1140#define VC1_VoiceStopped VC2_VoiceStopped 1141#define VC1_VoiceGetPosition VC2_VoiceGetPosition 1142#define VC1_SampleUnload VC2_SampleUnload 1143#define VC1_SampleLoad VC2_SampleLoad 1144#define VC1_SampleSpace VC2_SampleSpace 1145#define VC1_SampleLength VC2_SampleLength 1146#define VC1_VoiceRealVolume VC2_VoiceRealVolume 1147 1148#include "virtch_common.c" 1149#undef _IN_VIRTCH_ 1150 1151void VC2_WriteSamples(SBYTE* buf,ULONG todo) 1152{ 1153 int left,portion=0; 1154 SBYTE *buffer; 1155 int t,pan,vol; 1156 1157 todo*=SAMPLING_FACTOR; 1158 1159 while(todo) { 1160 if(!tickleft) { 1161 if(vc_mode & DMODE_SOFT_MUSIC) md_player(); 1162 tickleft=(md_mixfreq*125L*SAMPLING_FACTOR)/(md_bpm*50L); 1163 tickleft&=~(SAMPLING_FACTOR-1); 1164 } 1165 left = MIN(tickleft, (int)todo); 1166 buffer = buf; 1167 tickleft -= left; 1168 todo -= left; 1169 buf += samples2bytes(left)/SAMPLING_FACTOR; 1170 1171 while(left) { 1172 portion = MIN(left, samplesthatfit); 1173 memset(vc_tickbuf,0,portion<<((vc_mode&DMODE_STEREO)?3:2)); 1174 for(t=0;t<vc_softchn;t++) { 1175 vnf = &vinf[t]; 1176 1177 if(vnf->kick) { 1178 vnf->current=((SLONGLONG)(vnf->start))<<FRACBITS; 1179 vnf->kick = 0; 1180 vnf->active = 1; 1181 vnf->click = CLICK_BUFFER; 1182 vnf->rampvol = 0; 1183 } 1184 1185 if(!vnf->frq) vnf->active = 0; 1186 1187 if(vnf->active) { 1188 vnf->increment=((SLONGLONG)(vnf->frq)<<(FRACBITS-SAMPLING_SHIFT)) 1189 /md_mixfreq; 1190 if(vnf->flags&SF_REVERSE) vnf->increment=-vnf->increment; 1191 vol = vnf->vol; pan = vnf->pan; 1192 1193 vnf->oldlvol=vnf->lvolsel;vnf->oldrvol=vnf->rvolsel; 1194 if(vc_mode & DMODE_STEREO) { 1195 if(pan!=PAN_SURROUND) { 1196 vnf->lvolsel=(vol*(PAN_RIGHT-pan))>>8; 1197 vnf->rvolsel=(vol*pan)>>8; 1198 } else { 1199 vnf->lvolsel=vnf->rvolsel=(vol * 256L) / 480; 1200 } 1201 } else 1202 vnf->lvolsel=vol; 1203 1204 idxsize=(vnf->size)?((SLONGLONG)(vnf->size)<<FRACBITS)-1:0; 1205 idxlend=(vnf->repend)?((SLONGLONG)(vnf->repend)<<FRACBITS)-1:0; 1206 idxlpos=(SLONGLONG)(vnf->reppos)<<FRACBITS; 1207 AddChannel(vc_tickbuf,portion); 1208 } 1209 } 1210 1211 if(md_mode & DMODE_NOISEREDUCTION) { 1212 MixLowPass(vc_tickbuf, portion); 1213 } 1214 1215 if(md_reverb) { 1216 if(md_reverb>15) md_reverb=15; 1217 MixReverb(vc_tickbuf,portion); 1218 } 1219 1220 if (vc_callback) { 1221 vc_callback((unsigned char*)vc_tickbuf, portion); 1222 } 1223 1224 if(vc_mode & DMODE_FLOAT) 1225 Mix32toFP((float*)buffer,vc_tickbuf,portion); 1226 else if(vc_mode & DMODE_16BITS) 1227 Mix32to16((SWORD*)buffer,vc_tickbuf,portion); 1228 else 1229 Mix32to8((SBYTE*)buffer,vc_tickbuf,portion); 1230 1231 buffer += samples2bytes(portion) / SAMPLING_FACTOR; 1232 left -= portion; 1233 } 1234 } 1235} 1236 1237int VC2_Init(void) 1238{ 1239 VC_SetupPointers(); 1240 1241 if (!(md_mode&DMODE_HQMIXER)) 1242 return VC1_Init(); 1243 1244 if(!(Samples=(SWORD**)MikMod_amalloc(MAXSAMPLEHANDLES*sizeof(SWORD*)))) { 1245 _mm_errno = MMERR_INITIALIZING_MIXER; 1246 return 1; 1247 } 1248 if(!vc_tickbuf) { 1249 if(!(vc_tickbuf=(SLONG*)MikMod_amalloc((TICKLSIZE+32)*sizeof(SLONG)))) { 1250 _mm_errno = MMERR_INITIALIZING_MIXER; 1251 return 1; 1252 } 1253 } 1254 1255 if(md_mode & DMODE_STEREO) { 1256 Mix32toFP = Mix32ToFP_Stereo; 1257#if ((defined HAVE_ALTIVEC || defined HAVE_SSE2) && (SAMPLING_FACTOR == 4)) 1258 if (md_mode & DMODE_SIMDMIXER) 1259 Mix32to16 = Mix32To16_Stereo_SIMD_4Tap; 1260 else 1261#endif 1262 Mix32to16 = Mix32To16_Stereo; 1263 Mix32to8 = Mix32To8_Stereo; 1264 MixReverb = MixReverb_Stereo; 1265 MixLowPass = MixLowPass_Stereo; 1266 } else { 1267 Mix32toFP = Mix32ToFP_Normal; 1268 Mix32to16 = Mix32To16_Normal; 1269 Mix32to8 = Mix32To8_Normal; 1270 MixReverb = MixReverb_Normal; 1271 MixLowPass = MixLowPass_Normal; 1272 } 1273 1274 md_mode |= DMODE_INTERP; 1275 vc_mode = md_mode; 1276 return 0; 1277} 1278 1279int VC2_PlayStart(void) 1280{ 1281 md_mode|=DMODE_INTERP; 1282 1283 samplesthatfit = TICKLSIZE; 1284 if(vc_mode & DMODE_STEREO) samplesthatfit >>= 1; 1285 tickleft = 0; 1286 1287 RVc1 = (5000L * md_mixfreq) / (REVERBERATION * 10); 1288 RVc2 = (5078L * md_mixfreq) / (REVERBERATION * 10); 1289 RVc3 = (5313L * md_mixfreq) / (REVERBERATION * 10); 1290 RVc4 = (5703L * md_mixfreq) / (REVERBERATION * 10); 1291 RVc5 = (6250L * md_mixfreq) / (REVERBERATION * 10); 1292 RVc6 = (6953L * md_mixfreq) / (REVERBERATION * 10); 1293 RVc7 = (7813L * md_mixfreq) / (REVERBERATION * 10); 1294 RVc8 = (8828L * md_mixfreq) / (REVERBERATION * 10); 1295 1296 if(!(RVbufL1=(SLONG*)MikMod_calloc((RVc1+1),sizeof(SLONG)))) return 1; 1297 if(!(RVbufL2=(SLONG*)MikMod_calloc((RVc2+1),sizeof(SLONG)))) return 1; 1298 if(!(RVbufL3=(SLONG*)MikMod_calloc((RVc3+1),sizeof(SLONG)))) return 1; 1299 if(!(RVbufL4=(SLONG*)MikMod_calloc((RVc4+1),sizeof(SLONG)))) return 1; 1300 if(!(RVbufL5=(SLONG*)MikMod_calloc((RVc5+1),sizeof(SLONG)))) return 1; 1301 if(!(RVbufL6=(SLONG*)MikMod_calloc((RVc6+1),sizeof(SLONG)))) return 1; 1302 if(!(RVbufL7=(SLONG*)MikMod_calloc((RVc7+1),sizeof(SLONG)))) return 1; 1303 if(!(RVbufL8=(SLONG*)MikMod_calloc((RVc8+1),sizeof(SLONG)))) return 1; 1304 1305 /* allocate reverb buffers for the right channel if in stereo mode only. */ 1306 if (vc_mode & DMODE_STEREO) { 1307 if(!(RVbufR1=(SLONG*)MikMod_calloc((RVc1+1),sizeof(SLONG)))) return 1; 1308 if(!(RVbufR2=(SLONG*)MikMod_calloc((RVc2+1),sizeof(SLONG)))) return 1; 1309 if(!(RVbufR3=(SLONG*)MikMod_calloc((RVc3+1),sizeof(SLONG)))) return 1; 1310 if(!(RVbufR4=(SLONG*)MikMod_calloc((RVc4+1),sizeof(SLONG)))) return 1; 1311 if(!(RVbufR5=(SLONG*)MikMod_calloc((RVc5+1),sizeof(SLONG)))) return 1; 1312 if(!(RVbufR6=(SLONG*)MikMod_calloc((RVc6+1),sizeof(SLONG)))) return 1; 1313 if(!(RVbufR7=(SLONG*)MikMod_calloc((RVc7+1),sizeof(SLONG)))) return 1; 1314 if(!(RVbufR8=(SLONG*)MikMod_calloc((RVc8+1),sizeof(SLONG)))) return 1; 1315 } 1316 1317 RVRindex = 0; 1318 return 0; 1319} 1320 1321void VC2_PlayStop(void) 1322{ 1323 MikMod_free(RVbufL1); 1324 MikMod_free(RVbufL2); 1325 MikMod_free(RVbufL3); 1326 MikMod_free(RVbufL4); 1327 MikMod_free(RVbufL5); 1328 MikMod_free(RVbufL6); 1329 MikMod_free(RVbufL7); 1330 MikMod_free(RVbufL8); 1331 MikMod_free(RVbufR1); 1332 MikMod_free(RVbufR2); 1333 MikMod_free(RVbufR3); 1334 MikMod_free(RVbufR4); 1335 MikMod_free(RVbufR5); 1336 MikMod_free(RVbufR6); 1337 MikMod_free(RVbufR7); 1338 MikMod_free(RVbufR8); 1339 1340 RVbufL1=RVbufL2=RVbufL3=RVbufL4=RVbufL5=RVbufL6=RVbufL7=RVbufL8=NULL; 1341 RVbufR1=RVbufR2=RVbufR3=RVbufR4=RVbufR5=RVbufR6=RVbufR7=RVbufR8=NULL; 1342} 1343 1344int VC2_SetNumVoices(void) 1345{ 1346 int t; 1347 1348 md_mode|=DMODE_INTERP; 1349 1350 if(!(vc_softchn=md_softchn)) return 0; 1351 1352 MikMod_free(vinf); 1353 if(!(vinf=(VINFO*)MikMod_calloc(vc_softchn,sizeof(VINFO)))) return 1; 1354 1355 for(t=0;t<vc_softchn;t++) { 1356 vinf[t].frq=10000; 1357 vinf[t].pan=(t&1)?PAN_LEFT:PAN_RIGHT; 1358 } 1359 1360 return 0; 1361} 1362 1363#endif /* ! NO_HQMIXER */ 1364 1365/* ex:set ts=4: */