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