1 /* OpenCP Module Player 2 * copyright (c) '94-'10 Niklas Beisert <nbeisert@physik.tu-muenchen.de> 3 * 4 * ITPlayer - player for Impulse Tracker 2.xx modules 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 * 20 * revision history: (please note changes here) 21 * -nb980510 Niklas Beisert <nbeisert@physik.tu-muenchen.de> 22 * -first release 23 * -kb980717 Tammo Hinrichs <kb@nwn.de> 24 * -fixed many many uncountable small replay bugs 25 * -strange division by zero on song start fixed (occurred when 26 * the player irq/timer routine started before it was supposed 27 * to do so) 28 * -vastly improved channel allocation (uncontrollably vanishing 29 * channels should belong to the past) 30 * -implemented filter handling (not used tho, as the wavetable 31 * system isn't able to handle them, so it's only for playing 32 * filtered ITs right (pitch envelopes dont get messed up anymore)) 33 * -implemented exit on song loop function 34 * -added many many various structures, data types, variables and 35 * functions for the player's display 36 * -again fixed even more uncountable replay bugs (a BIG thanx to 37 * mindbender who didn't only reveal two of them, but made it 38 * possible that around 5 other bugs suddenly appeared after 39 * fixing :) 40 * -finally implemented Amiga frequency table on heavy public 41 * demand (or better: cut/pasted/modified it from the xm player - 42 * be happy with this or not) 43 * (btw: "heavy public demand" == Mindbender again ;)) 44 * -meanwhile, fixed so many replay bugs again that i'd better have 45 * written this player from scratch ;) 46 * -rewritten envelope handling (envelope loops weren't correct and 47 * the routine crashed on some ITs (due to a bug in pulse's saving 48 * routine i think) 49 * -fixed replay bugs again (thx to maxx) 50 * -and again fixed replay bugs (slowly, this is REALLY getting on 51 * my nerves... grmMRMMRMRMRMROARRMRMrmrararharhhHaheaheaheheaHEAHE) 52 * -kbwhenever Tammo Hinrichs <opencp@gmx.net> 53 * -now plays correctly when first order pos contains "+++" 54 * -vibrato tables fixed (were backwards according to some people) 55 * -too fast note retrigs fixed 56 * -ryg990426 Fabian Giesen <fabian@jdcs.su.nw.schule.de> 57 * -bla. again applied some SIMPLE bugfix from kb. this sucks :) 58 * -kb990606 Tammo Hinrichs <opencp@gmx.net> 59 * -bugfixed instrument filter settings 60 * -added filter calls to the mcp 61 * -doj20020901 Dirk Jagdmann <doj@cubic.org> 62 * -enable/disable pattern looping 63 * -ss20040908 Stian Skjelstad <stian@nixia.no> 64 * -copy 5 bytes instead of sizeof(c->delayed) in playtick(). We don't want to touch unmapped memory 65 */ 66 67 68 /* to do: 69 * - midi command parsing 70 * - filter envelopes still to be tested 71 * - fucking damned division overflow error in wavetable device still 72 * has to be found (when using wavetable sound cards). 73 * (fixed due to some zero checks in devwiw/gus/sb32???) 74 */ 75 76 77 #include "config.h" 78 #include <stdlib.h> 79 #include <string.h> 80 #include "types.h" 81 #include "cpiface/cpiface.h" 82 #include "dev/mcp.h" 83 #include "itplay.h" 84 #include "stuff/imsrtns.h" 85 86 87 /* overriding stdlib's one, even though it would do */ 88 #define random(this) it_random(this) 89 static int it_random(struct itplayer *this) 90 { 91 this->randseed=this->randseed*0x15A4E35+12345; 92 return (this->randseed>>16)&32767; 93 } 94 95 static struct itplayer *staticthis=NULL; 96 97 static int8_t sintab[256] = 98 { 99 0, 2, 3, 5, 6, 8, 9, 11, 12, 14, 16, 17, 19, 20, 100 22, 23, 24, 26, 27, 29, 30, 32, 33, 34, 36, 37, 38, 39, 101 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 102 55, 56, 56, 57, 58, 59, 59, 60, 60, 61, 61, 62, 62, 62, 103 63, 63, 63, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 104 63, 63, 63, 62, 62, 62, 61, 61, 60, 60, 59, 59, 58, 57, 105 56, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 106 43, 42, 41, 39, 38, 37, 36, 34, 33, 32, 30, 29, 27, 26, 107 24, 23, 22, 20, 19, 17, 16, 14, 12, 11, 9, 8, 6, 5, 108 3, 2, 0, -2, -3, -5, -6, -8, -9, -11, -12, -14, -16, -17, 109 -19, -20, -22, -23, -24, -26, -27, -29, -30, -32, -33, -34, -36, -37, 110 -38, -39, -41, -42, -43, -44, -45, -46, -47, -48, -49, -50, -51, -52, 111 -53, -54, -55, -56, -56, -57, -58, -59, -59, -60, -60, -61, -61, -62, 112 -62, -62, -63, -63, -63, -64, -64, -64, -64, -64, -64, -64, -64, -64, 113 -64, -64, -63, -63, -63, -62, -62, -62, -61, -61, -60, -60, -59, -59, 114 -58, -57, -56, -56, -55, -54, -53, -52, -51, -50, -49, -48, -47, -46, 115 -45, -44, -43, -42, -41, -39, -38, -37, -36, -34, -33, -32, -30, -29, 116 -27, -26, -24, -23, -22, -20, -19, -17, -16, -14, -12, -11, -9, -8, 117 -6, -5, -3, -2 118 }; 119 120 121 static void playtick(struct itplayer *this); 122 static int range64(int v); 123 static int range128(int v); 124 static void dovibrato(struct itplayer *this, struct it_logchan *c); 125 static void putque(struct itplayer *this, int type, int val1, int val2); 126 static void readque(struct itplayer *this); 127 static void dotremolo(struct itplayer *this, struct it_logchan *c); 128 static void dodelay(struct itplayer *this, struct it_logchan *c); 129 static void dopanbrello(struct itplayer *this, struct it_logchan *c); 130 131 132 static void playtickstatic(void) 133 { 134 playtick(staticthis); 135 } 136 137 static void playnote(struct itplayer *this, struct it_logchan *c, const uint8_t *cmd) 138 { 139 int instchange=0; 140 /* int triginst=0; unused */ 141 int porta, frq; 142 struct it_physchan *p; 143 const struct it_sample *s; 144 const struct it_instrument *in; 145 146 if (cmd[0]) 147 { 148 c->lastnote=cmd[0]; 149 /* this is kind of wierd, but we need to know of retrigger changes already now */ 150 if (cmd[3]==cmdRetrigger) 151 c->retrigpos=cmd[4]>>4|!(cmd[4]&0xf0); /* |!(cmd[4]&0xf0) makes value 0, into 1 */ 152 else 153 c->retrigpos=c->retrigspd; 154 } 155 156 if (cmd[1]) 157 { 158 if (cmd[1]!=c->lastins) 159 instchange=1; 160 c->lastins=cmd[1]; 161 } 162 163 if (c->lastnote==cmdNNoteOff) 164 { 165 if (c->pch) 166 c->pch->noteoff=1; 167 return; 168 } 169 if (c->lastnote==cmdNNoteCut) 170 { 171 if (c->pch) 172 c->pch->notecut=1; 173 return; 174 } 175 if (c->lastnote>=cmdNNoteFade) 176 { 177 if (c->pch) 178 c->pch->notefade=1; 179 return; 180 } 181 if ((c->lastins>this->ninst)||!c->lastins||!c->lastnote||(c->lastnote>=cmdNNoteFade)) 182 return; 183 184 c->curnote=c->lastnote; 185 186 porta=(cmd[3]==cmdPortaNote)||(cmd[3]==cmdPortaVol)||((cmd[2]>=cmdVPortaNote)&&(cmd[2]<(cmdVPortaNote+10))); 187 188 if (!c->pch || c->pch->dead || !c->pch->fadeval) 189 porta=0; 190 191 if (instchange || !porta) 192 c->fnotehit=1; 193 194 do 195 { 196 if (!((!cmd[0]) && cmd[1] && (!instchange) && (!porta) && (cmd[3]!=cmdOffset) && c->pch)) 197 break; 198 199 /* http://eval.sovietrussia.org/wiki/Player_abuse_tests#Ping-pong_loop_and_sample_number 200 * 201 * Bug-fix workaround for cases where you just set instrument number with no note, should not re-trigger note, 202 * just reset volumes 203 */ 204 if (!(p=c->pch)) 205 break; 206 if (p->notecut) 207 break; 208 if (p->dead) 209 break; 210 if (!(s=p->smp)) 211 break; 212 if (!(in=p->inst)) 213 break; 214 c->nna=in->nna; 215 c->vol=((100-in->rv)*s->vol+in->rv*(rand()%65))/100; 216 c->fvol=c->vol; 217 c->pan=(in->dfp&128)?c->cpan:in->dfp; 218 c->pan=(s->dfp&128)?(s->dfp&127):c->pan; 219 c->pan=range64(c->pan+(((c->lastnote-cmdNNote-in->ppc)*in->pps)>>8)); 220 c->pan=/*(in->dfp&128)?c->pan:*/range64(c->pan+((in->rp*(rand() %129 -64))>>6)); 221 c->fpan=c->pan; 222 return; 223 } while(0); /* runs atleast one time */ 224 225 if (c->fnotehit) 226 { 227 int smp; 228 229 if (porta) 230 c->pch->notecut=1; 231 smp=this->instruments[c->lastins-1].keytab[c->lastnote-cmdNNote][1]; 232 if (!smp||(smp>this->nsamp)) 233 return; 234 if (!porta) 235 { 236 if (c->pch) 237 { 238 c->newchan.volenvpos=c->pch->volenvpos; 239 c->newchan.panenvpos=c->pch->panenvpos; 240 c->newchan.pitchenvpos=c->pch->pitchenvpos; 241 c->newchan.filterenvpos=c->pch->filterenvpos; 242 c->newchan=*c->pch; 243 switch (c->nna) 244 { 245 case 0: c->pch->notecut=1; break; 246 case 2: c->pch->noteoff=1; break; 247 case 3: c->pch->notefade=1; break; 248 } 249 c->pch=0; 250 } else { 251 c->newchan.volenvpos=0; 252 c->newchan.panenvpos=0; 253 c->newchan.pitchenvpos=0; 254 c->newchan.filterenvpos=0; 255 } 256 c->pch=&c->newchan; 257 c->pch->avibpos=0; 258 c->pch->avibdep=0; 259 /* c->retrigpos=0; */ 260 } 261 if (this->samples[smp-1].handle==0xFFFF) 262 { 263 fprintf(stderr, "playit/itplay.c: Assert #1\n"); 264 c->pch=0; /* deallocate channel, invalid sample */ 265 return; 266 } 267 268 c->pch->inst=&this->instruments[c->lastins-1]; 269 if (!c->pch->inst) 270 { 271 /* should be unreachable */ 272 fprintf(stderr, "playit/itplay.c: Assert #2\n"); 273 c->pch=0; 274 } 275 c->pch->smp=&this->samples[smp-1]; 276 if (!c->pch->smp) 277 { 278 /* should be unreachable */ 279 fprintf(stderr, "playit/itplay.c: Assert #3\n"); 280 c->pch=0; 281 } 282 c->basenote=c->pch->note=c->lastnote-cmdNNote; 283 c->realnote=c->pch->inst->keytab[c->basenote][0]; 284 c->pch->noteoffset=(60-c->realnote+c->basenote)*256+c->pch->smp->normnote; 285 } 286 287 p=c->pch; 288 s=p->smp; 289 in=p->inst; 290 291 if (cmd[3]==cmdOffset) 292 { 293 if (cmd[4]) 294 c->offset=(c->offset&0xF00)|cmd[4]; 295 p->newsamp=s->handle; 296 p->newpos=c->offset<<8; 297 if (p->newpos>=(signed)this->sampleinfos[s->handle].length) 298 p->newpos=this->sampleinfos[s->handle].length-16; 299 } else if (c->fnotehit) 300 { 301 p->newsamp=s->handle; 302 p->newpos=0; 303 } 304 305 if (c->fnotehit || cmd[1]) 306 { 307 int i; 308 309 if (in->dct) 310 { 311 for (i=0; i<this->npchan; i++) 312 { 313 struct it_physchan *dp=&this->pchannels[i]; 314 if (dp==p) 315 continue; 316 if (dp->lch!=p->lch) 317 continue; 318 if (dp->inst!=p->inst) 319 continue; 320 if ((in->dct!=3)&&(dp->smp!=p->smp)) 321 continue; 322 if ((in->dct==1)&&(dp->note!=p->note)) 323 continue; 324 switch (in->dca) 325 { 326 case 0: dp->notecut=1; break; 327 case 1: dp->noteoff=1; break; 328 case 2: dp->notefade=1; break; 329 } 330 } 331 } 332 333 if (cmd[1]) 334 { 335 p->fadeval=1024; 336 p->fadespd=in->fadeout; 337 p->notefade=0; 338 p->dead=0; 339 p->notecut=0; 340 p->noteoff=0; 341 p->looptype=0; 342 p->volenv=in->envs[0].type&env_type_active; 343 p->panenv=in->envs[1].type&env_type_active; 344 p->penvtype=(in->envs[2].type&env_type_filter); 345 p->pitchenv=(in->envs[2].type&env_type_active) && !p->penvtype; 346 p->filterenv=(in->envs[2].type&env_type_active) && p->penvtype; 347 if (!(in->envs[0].type&env_type_carry)) 348 p->volenvpos=0; 349 if (!(in->envs[1].type&env_type_carry)) 350 p->panenvpos=0; 351 if (!(in->envs[2].type&env_type_carry)) 352 { 353 p->pitchenvpos=0; 354 p->filterenvpos=0; 355 } 356 357 c->nna=in->nna; 358 c->vol=((100-in->rv)*s->vol+in->rv*(rand()%65))/100; 359 c->fvol=c->vol; 360 c->pan=(in->dfp&128)?c->cpan:in->dfp; 361 c->pan=(s->dfp&128)?(s->dfp&127):c->pan; 362 c->pan=range64(c->pan+(((c->lastnote-cmdNNote-in->ppc)*in->pps)>>8)); 363 c->pan=/*(in->dfp&128)?c->pan:*/range64(c->pan+((in->rp*(rand() %129 -64))>>6)); 364 c->fpan=c->pan; 365 c->cutoff=(in->ifp&128)?in->ifp:c->cutoff; 366 c->fcutoff=c->cutoff; 367 c->reso=(in->ifr&128)?in->ifr:c->reso; 368 } 369 } 370 371 if (porta && instchange && !this->geffect) 372 { 373 c->basenote=c->lastnote-cmdNNote; 374 c->realnote=in->keytab[c->basenote][0]; 375 p->noteoffset=(60-c->realnote+c->basenote)*256+s->normnote; 376 } 377 378 frq=p->noteoffset-256*(c->lastnote-cmdNNote); 379 if (!this->linear) 380 frq=mcpGetFreq6848(frq); 381 c->dpitch=frq; 382 if (!porta) 383 c->fpitch=c->pitch=c->dpitch; 384 } 385 386 static void playvcmd(struct itplayer *this, struct it_logchan *c, int vcmd) 387 { 388 c->vcmd=vcmd; 389 if ((vcmd>=cmdVVolume)&&(vcmd<=(cmdVVolume+64))) 390 c->fvol=c->vol=vcmd-cmdVVolume; 391 else if ((vcmd>=cmdVPanning)&&(vcmd<=(cmdVPanning+64))) 392 { 393 c->fpan=c->pan=c->cpan=vcmd-cmdVPanning; 394 c->srnd=0; 395 } else if ((vcmd>=cmdVFVolSlU)&&(vcmd<(cmdVFVolSlU+10))) 396 { 397 if (vcmd!=cmdVFVolSlU) 398 c->vvolslide=vcmd-cmdVFVolSlU; 399 c->fvol=c->vol=range64(c->vol+c->vvolslide); 400 } else if ((vcmd>=cmdVFVolSlD)&&(vcmd<(cmdVFVolSlD+10))) 401 { 402 if (vcmd!=cmdVFVolSlD) 403 c->vvolslide=vcmd-cmdVFVolSlD; 404 c->fvol=c->vol=range64(c->vol-c->vvolslide); 405 } else if ((vcmd>=cmdVVolSlU)&&(vcmd<(cmdVVolSlU+10))) 406 { 407 if (vcmd!=cmdVVolSlU) 408 c->vvolslide=vcmd-cmdVVolSlU; 409 c->fvolslide=ifxVSUp; 410 } else if ((vcmd>=cmdVVolSlD)&&(vcmd<(cmdVVolSlD+10))) 411 { 412 if (vcmd!=cmdVVolSlD) 413 c->vvolslide=vcmd-cmdVVolSlD; 414 c->fvolslide=ifxVSDown; 415 } else if ((vcmd>=cmdVPortaD)&&(vcmd<(cmdVPortaD+10))) 416 { 417 if (vcmd!=cmdVPortaD) 418 c->porta=4*(vcmd-cmdVPortaD); 419 c->vporta=c->porta; 420 c->fpitchslide=ifxPSDown; 421 } else if ((vcmd>=cmdVPortaU)&&(vcmd<(cmdVPortaU+10))) 422 { 423 if (vcmd!=cmdVPortaU) 424 c->porta=4*(vcmd-cmdVPortaU); 425 c->vporta=c->porta; 426 c->fpitchslide=ifxPSUp; 427 } else if ((vcmd>=cmdVPortaNote)&&(vcmd<(cmdVPortaNote+10))) 428 { 429 if (vcmd!=cmdVPortaNote) 430 { 431 int tmp="\x00\x01\x04\x08\x10\x20\x40\x60\x80\xFF"[vcmd-cmdVPortaNote]; 432 if (this->geffect) 433 c->portanote=tmp; 434 else 435 c->porta=tmp; 436 } 437 if (this->geffect) 438 c->vportanote=c->portanote; 439 else 440 c->vporta=c->porta; 441 442 c->fpitchslide=ifxPSToNote; 443 } else if ((vcmd>=cmdVVibrato)&&(vcmd<(cmdVVibrato+10))) 444 { 445 if (vcmd!=cmdVVibrato) 446 c->vibdep=(vcmd-cmdVVibrato)*(this->oldfx?8:4); 447 c->fpitchfx=ifxPXVibrato; 448 dovibrato(this, c); 449 } 450 } 451 452 static int range64(int v) 453 { 454 return (v<0)?0:(v>64)?64:v; 455 } 456 457 static int range128(int v) 458 { 459 return (v<0)?0:(v>128)?128:v; 460 } 461 462 static int rowslide(int data) 463 { 464 if ((data&0x0F)==0x0F) 465 return data>>4; 466 else 467 if ((data&0xF0)==0xF0) 468 return -(data&0xF); 469 return 0; 470 } 471 472 static int rowudslide(int data) 473 { 474 if (data>=0xF0) 475 return (data&0xF)*4; 476 else if (data>=0xE0) 477 return (data&0xF); 478 return 0; 479 } 480 481 static int rowvolslide(int data) 482 { 483 if (data==0xF0) 484 return 0xF; 485 else 486 if (data==0x0F) 487 return -0xF; 488 else 489 return rowslide(data); 490 } 491 492 static int tickslide(int data) 493 { 494 if (!(data&0x0F)) 495 return data>>4; 496 else 497 if (!(data&0xF0)) 498 return -(data&0xF); 499 return 0; 500 } 501 502 static void doretrigger(struct it_logchan *c) 503 { 504 int x; 505 struct it_physchan *p; 506 507 c->retrigpos--; 508 if (c->retrigpos) 509 return; 510 c->retrigpos=c->retrigspd; 511 x=c->vol; 512 switch (c->retrigvol) 513 { 514 case 1: case 2: case 3: case 4: case 5: x-=1<<(c->retrigvol-1); break; 515 case 6: x=(5*x)>>3; break; 516 case 7: x=x>>1; break; 517 case 9: case 10: case 11: case 12: case 13: x+=1<<(c->retrigvol-9); break; 518 case 14: x=(3*x)>>1; break; 519 case 15: x=2*x; break; 520 } 521 c->fvol=c->vol=range64(x); 522 if (!c->pch) 523 return; 524 p=c->pch; 525 p->newpos=0; 526 p->dead=0; 527 } 528 529 static void dotremor(struct it_logchan *c) 530 { 531 if (c->tremoroncounter) 532 c->tremoroncounter--; 533 if (!c->tremoroncounter) 534 { 535 if (c->tremoroffcounter) 536 { 537 c->fvol=0; 538 c->tremoroffcounter--; 539 } else { 540 c->tremoroncounter=c->tremoron; 541 c->tremoroffcounter=c->tremoroff; 542 } 543 } 544 } 545 546 static int ishex(uint8_t c) 547 { 548 return ((c>=48 && c<58) || (c>=65 && c<71)); 549 } 550 551 552 static void parsemidicmd(struct it_logchan *c, char *cmd, int z) 553 { 554 uint8_t bytes[32]; 555 int count=0; 556 while (*cmd) 557 { 558 if (ishex(*cmd)) 559 { 560 int v0=(*cmd)-48; 561 if (v0>9) v0-=7; 562 cmd++; 563 if (ishex(*cmd)) 564 { 565 int v1=(*cmd)-48; 566 if (v1>9) v1-=7; 567 cmd++; 568 bytes[count++]=(v0<<4)|v1; 569 } 570 } else if ((*cmd)=='Z') 571 { 572 bytes[count++]=z; 573 cmd++; 574 } else 575 cmd++; 576 } 577 /* filter commands? */ 578 if (count==4 && bytes[0]==0xf0 && bytes[1]==0xf0) 579 { 580 switch (bytes[2]) 581 { 582 case 0: 583 c->cutoff=c->fcutoff=bytes[3]+128; 584 break; 585 case 1: 586 c->reso=bytes[3]+128; 587 break; 588 } 589 } 590 } 591 592 static void playcmd(struct itplayer *this, struct it_logchan *c, int cmd, int data) 593 { 594 int i; 595 c->command=cmd; 596 switch (cmd) 597 { 598 case cmdSpeed: 599 if (data) 600 this->speed=data; 601 putque(this, queSpeed, -1, this->speed); 602 break; 603 case cmdJump: 604 this->gotorow=0; 605 this->gotoord=data; 606 break; 607 case cmdBreak: 608 if (this->gotoord==-1) 609 this->gotoord=this->curord+1; 610 this->gotorow=data; 611 break; 612 case cmdVolSlide: 613 if (data) 614 c->volslide=data; 615 data=c->volslide; 616 if (!(data&0x0F) && (data&0xF0)) 617 { 618 c->fvolslide=ifxVSUp; 619 c->fx=ifxVolSlideUp; 620 } else if (!(data&0xF0) && (data&0x0F)) 621 { 622 c->fvolslide=ifxVSDown; 623 c->fx=ifxVolSlideDown; 624 } else if ((data&0x0F)>0x0D && (data&0xF0)) 625 c->fx=ifxRowVolSlideUp; 626 else if (((data&0xF0)>0xD0) && (data&0x0F)) 627 c->fx=ifxRowVolSlideDown; 628 c->fvol=c->vol=range64(c->vol+rowvolslide(c->volslide)); 629 break; 630 case cmdPortaD: 631 if (data) 632 c->porta=data; 633 c->eporta=c->porta; 634 c->fpitchslide=ifxPSDown; 635 c->fx=ifxPitchSlideDown; 636 c->fpitch=c->pitch=c->pitch+4*rowudslide(c->eporta); 637 break; 638 case cmdPortaU: 639 if (data) 640 c->porta=data; 641 c->eporta=c->porta; 642 c->fpitchslide=ifxPSUp; 643 c->fx=ifxPitchSlideUp; 644 c->fpitch=c->pitch=c->pitch-4*rowudslide(c->eporta); 645 break; 646 case cmdPortaNote: 647 if (data) 648 { 649 if (this->geffect) 650 c->portanote=data; 651 else 652 c->porta=data; 653 } 654 if (this->geffect) 655 c->eportanote=c->portanote; 656 else 657 c->eporta=c->porta; 658 c->fpitchslide=ifxPSToNote; 659 c->fx=ifxPitchSlideToNote; 660 break; 661 case cmdVibrato: 662 if (data&0xF) 663 c->vibdep=(data&0xF)*(this->oldfx?8:4); 664 if (data>>4) 665 c->vibspd=data>>4; 666 c->fpitchfx=ifxPXVibrato; 667 c->fx=ifxPitchVibrato; 668 dovibrato(this, c); 669 break; 670 case cmdTremor: 671 if (data) 672 { 673 c->tremoron=(data>>4)+(this->oldfx); 674 c->tremoroff=(data&0xF)+(this->oldfx); 675 } 676 if (!c->tremoroff) 677 c->tremoroff=1; 678 if (!c->tremoron) 679 c->tremoron=1; 680 c->fvolfx=ifxVXTremor; 681 c->fx=ifxTremor; 682 dotremor(c); 683 break; 684 case cmdArpeggio: 685 if (data) 686 { 687 c->arpeggio1=data>>4; 688 c->arpeggio2=data&0xF; 689 } 690 c->fpitchfx=ifxPXArpeggio; 691 c->fx=ifxArpeggio; 692 break; 693 case cmdPortaVol: 694 if (data) 695 c->volslide=data; 696 data=c->volslide; 697 c->fpitchslide=ifxPSToNote; 698 c->fx=ifxPitchSlideToNote; 699 if (!(data&0x0F) && (data&0xF0)) 700 { 701 c->fvolslide=ifxVSUp; 702 c->fx=ifxVolSlideUp; 703 } else if (!(data&0xF0) && (data&0x0F)) 704 { 705 c->fvolslide=ifxVSDown; 706 c->fx=ifxVolSlideDown; 707 } else if ((data&0x0F)>0x0D && (data&0xF0)) 708 c->fx=ifxRowVolSlideUp; 709 else if (((data&0xF0)>0xD0) && (data&0x0F)) 710 c->fx=ifxRowVolSlideDown; 711 c->fvol=c->vol=range64(c->vol+rowvolslide(c->volslide)); 712 break; 713 case cmdVibVol: 714 if (data) 715 c->volslide=data; 716 data=c->volslide; 717 c->fpitchfx=ifxPXVibrato; 718 c->fx=ifxPitchVibrato; 719 if (!(data&0x0F) && (data&0xF0)) 720 { 721 c->fvolslide=ifxVSUp; 722 c->fx=ifxVolSlideUp; 723 } else if (!(data&0xF0) && (data&0x0F)) 724 { 725 c->fvolslide=ifxVSDown; 726 c->fx=ifxVolSlideDown; 727 } else if ((data&0x0F)>0x0D && (data&0xF0)) 728 c->fx=ifxRowVolSlideUp; 729 else if (((data&0xF0)>0xD0) && (data&0x0F)) 730 c->fx=ifxRowVolSlideDown; 731 c->fvol=c->vol=range64(c->vol+rowvolslide(c->volslide)); 732 dovibrato(this, c); 733 break; 734 case cmdChanVol: 735 if (data<=64) 736 c->cvol=data; 737 break; 738 case cmdChanVolSlide: 739 if (data) 740 c->cvolslide=data; 741 data=c->cvolslide; 742 if ((data&0x0F)==0 && data&0xF0) 743 c->fx=ifxChanVolSlideUp; 744 else if ((data&0xF0)==0 && data&0x0F) 745 c->fx=ifxChanVolSlideDown; 746 else if ((data&0x0F)>0x0D && data&0xF0) 747 c->fx=ifxRowChanVolSlideUp; 748 else if ((data&0xF0)>0xD0 && data&0x0F) 749 c->fx=ifxRowChanVolSlideDown; 750 c->cvol=range64(c->cvol+rowslide(c->cvolslide)); 751 break; 752 case cmdOffset: 753 c->fx=ifxOffset; 754 break; 755 case cmdPanSlide: 756 if (data) 757 c->panslide=data; 758 data=c->panslide; 759 if (!(data&0x0F)) 760 { 761 c->fpanslide=ifxPnSLeft; 762 c->fx=ifxPanSlideLeft; 763 } else if (!(data&0xF0)) 764 { 765 c->fpanslide=ifxPnSRight; 766 c->fx=ifxPanSlideRight; 767 } 768 c->fpan=c->cpan=c->pan=range64(c->pan-rowslide(c->panslide)); 769 break; 770 case cmdRetrigger: 771 if (data) 772 { 773 c->retrigspd=data&0xF; 774 c->retrigvol=data>>4; 775 } 776 if (!c->retrigspd) 777 c->retrigspd=1; 778 c->fx=ifxRetrig; 779 doretrigger(c); 780 break; 781 case cmdTremolo: 782 if (data&0xF) 783 c->tremdep=data&0xF; 784 if (data>>4) 785 c->tremspd=data>>4; 786 c->fvolfx=ifxVXVibrato; 787 c->fx=ifxVolVibrato; 788 dotremolo(this, c); 789 break; 790 case cmdSpecial: 791 switch (c->specialcmd) 792 { 793 case cmdSVibType: 794 if (c->specialdata<4) 795 c->vibtype=c->specialdata; 796 break; 797 case cmdSTremType: 798 if (c->specialdata<4) 799 c->tremtype=c->specialdata; 800 break; 801 case cmdSPanbrType: 802 if (c->specialdata<4) 803 c->panbrtype=c->specialdata; 804 break; 805 case cmdSPatDelayTick: 806 this->patdelaytick=c->specialdata; 807 break; 808 case cmdSInstFX: 809 switch (c->specialdata) 810 { 811 case cmdSIPastCut: 812 c->fx=ifxPastCut; 813 for (i=0; i<this->npchan; i++) 814 if ((c==this->pchannels[i].lchp)&&(c->pch!=&this->pchannels[i])) 815 this->pchannels[i].notecut=1; 816 break; 817 case cmdSIPastOff: 818 c->fx=ifxPastOff; 819 for (i=0; i<this->npchan; i++) 820 if ((c==this->pchannels[i].lchp)&&(c->pch!=&this->pchannels[i])) 821 this->pchannels[i].noteoff=1; 822 break; 823 case cmdSIPastFade: 824 c->fx=ifxPastFade; 825 for (i=0; i<this->npchan; i++) 826 if ((c==this->pchannels[i].lchp)&&(c->pch!=&this->pchannels[i])) 827 this->pchannels[i].notefade=1; 828 break; 829 case cmdSINNACut: 830 c->nna=0; 831 break; 832 case cmdSINNACont: 833 c->nna=1; 834 break; 835 case cmdSINNAOff: 836 c->nna=2; 837 break; 838 case cmdSINNAFade: 839 c->nna=3; 840 break; 841 case cmdSIVolEnvOff: 842 c->fx=ifxVEnvOff; 843 if (c->pch) 844 c->pch->volenv=0; 845 break; 846 case cmdSIVolEnvOn: 847 c->fx=ifxVEnvOn; 848 if (c->pch) 849 c->pch->volenv=1; 850 break; 851 case cmdSIPanEnvOff: 852 c->fx=ifxPEnvOff; 853 if (c->pch) 854 c->pch->panenv=0; 855 break; 856 case cmdSIPanEnvOn: 857 c->fx=ifxPEnvOn; 858 if (c->pch) 859 c->pch->panenv=1; 860 break; 861 case cmdSIPitchEnvOff: 862 c->fx=ifxFEnvOff; 863 if (c->pch) 864 { 865 if (c->pch->penvtype) 866 c->pch->filterenv=0; 867 else 868 c->pch->pitchenv=0; 869 } 870 break; 871 case cmdSIPitchEnvOn: 872 c->fx=ifxFEnvOn; 873 if (c->pch) 874 { 875 if (c->pch->penvtype) 876 c->pch->filterenv=1; 877 else 878 c->pch->pitchenv=1; 879 } 880 break; 881 } 882 break; 883 case cmdSPanning: 884 c->srnd=0; 885 c->fpan=c->pan=c->cpan=((c->specialdata*0x11)+1)>>2; 886 break; 887 case cmdSSurround: 888 if (c->specialdata==1) 889 c->srnd=1; 890 break; 891 case cmdSOffsetHigh: 892 c->offset=(c->offset&0xFF)|(c->specialdata<<8); 893 break; 894 case cmdSPatLoop: 895 /*if(plLoopPatterns)*/ /* TODO */ 896 { 897 if (!c->specialdata) 898 c->patloopstart=this->currow; 899 else 900 { 901 if (!c->patloopcount) 902 c->patloopcount=c->specialdata; 903 else 904 c->patloopcount--; 905 if (c->patloopcount) 906 { 907 this->gotorow=c->patloopstart; 908 this->gotoord=this->curord; 909 } else { 910 c->patloopstart=this->currow+1; 911 } 912 } 913 } 914 break; 915 case cmdSNoteCut: 916 c->fx=ifxNoteCut; 917 if (!c->specialdata) 918 c->specialdata++; /* SC0 should do the same as SC1 */ 919 break; 920 case cmdSNoteDelay: 921 c->fx=ifxDelay; 922 if (!c->specialdata) 923 c->specialdata++; /* SD0 should do the same as SD1 */ 924 dodelay(this, c); 925 break; 926 case cmdSPatDelayRow: 927 if (!this->patdelayrow) /* only use the first command, per row */ 928 this->patdelayrow=c->specialdata+1; 929 break; 930 case cmdSSetMIDIMacro: 931 c->sfznum=c->specialdata; 932 break; 933 } 934 break; 935 case cmdTempo: 936 if (data) 937 c->tempo=data; 938 if (c->tempo>=0x20) 939 { 940 this->tempo=c->tempo; 941 putque(this, queTempo, -1, this->tempo); 942 } 943 break; 944 case cmdFineVib: 945 if (data&0xF) 946 c->vibdep=(data&0xF<<(this->oldfx))>>1; 947 if (data>>4) 948 c->vibspd=data>>4; 949 dovibrato(this, c); 950 break; 951 case cmdGVolume: 952 if (data<=128) 953 this->gvol=data; 954 putque(this, queGVol, -1, this->gvol); 955 break; 956 case cmdGVolSlide: 957 if (data) 958 c->gvolslide=data; 959 this->gvolslide=data; 960 this->gvol=range128(this->gvol+rowslide(c->gvolslide)); 961 putque(this, queGVol, -1, this->gvol); 962 break; 963 case cmdPanning: 964 c->srnd=0; 965 c->fpan=c->cpan=c->pan=(data+1)>>2; 966 break; 967 case cmdPanbrello: 968 if (data&0xF) 969 c->panbrdep=data&0xF; 970 if (data>>4) 971 c->panbrspd=data>>4; 972 c->fx=ifxPanBrello; 973 dopanbrello(this, c); 974 break; 975 case cmdMIDI: 976 if (this->midicmds) 977 { 978 if (data&0x80) 979 parsemidicmd(c, this->midicmds[data-103], 0); 980 else 981 parsemidicmd(c, this->midicmds[c->sfznum+9], data); 982 } 983 break; 984 /* DEPRECATED - Zxx IS MIDI MACRO TRIGGER 985 case cmdSync: 986 putque(this, queSync, c->newchan.lch, data); 987 */ 988 } 989 } 990 991 static void dovibrato(struct itplayer *this, struct it_logchan *c) 992 { 993 int x; 994 switch (c->vibtype) 995 { 996 case 0: x=sintab[4*(c->vibpos&63)]>>1; break; 997 case 1: x=32-(c->vibpos&63); break; 998 case 2: x=32-(c->vibpos&32); break; 999 default: /* remove a warning */ 1000 case 3: x=(random(this)&63)-32; 1001 } 1002 if (this->curtick || !this->oldfx) 1003 { 1004 c->fpitch-=(c->vibdep*x)>>3; 1005 c->vibpos-=c->vibspd; 1006 } 1007 } 1008 1009 static void dotremolo(struct itplayer *this, struct it_logchan *c) 1010 { 1011 int x; 1012 switch (c->tremtype) 1013 { 1014 case 0: x=sintab[4*(c->trempos&63)]>>1; break; 1015 case 1: x=32-(c->trempos&63); break; 1016 case 2: x=32-(c->trempos&32); break; 1017 default: /* remove a warning */ 1018 case 3: x=(random(this)&63)-32; 1019 } 1020 c->fvol=range64(c->fvol+((c->tremdep*x)>>4)); 1021 c->trempos+=c->tremspd; 1022 } 1023 1024 static void dopanbrello(struct itplayer *this, struct it_logchan *c) 1025 { 1026 int x; 1027 1028 if (c->panbrtype==3) 1029 { 1030 if (c->panbrpos>=c->panbrspd) 1031 { 1032 c->panbrpos=0; 1033 c->panbrrnd=random(this); 1034 } 1035 c->fpan=range64(c->fpan+((c->panbrdep*((c->panbrrnd&255)-128))>>6)); 1036 } else { 1037 switch (c->panbrtype) 1038 { 1039 case 0: x=sintab[c->panbrpos&255]*2; break; 1040 case 1: x=128-(c->panbrpos&255); break; 1041 default: /* remove a warning */ 1042 case 2: x=128-2*(c->panbrpos&128); break; 1043 } 1044 c->fpan=range64(c->fpan+((c->panbrdep*x)>>6)); 1045 } 1046 c->panbrpos+=c->panbrspd; 1047 } 1048 1049 static void doportanote(struct itplayer *this, struct it_logchan *c, int v) /* if v, then do vporta, else eporta */ 1050 { 1051 1052 if (!c->dpitch) 1053 return; 1054 1055 if (c->pitch<c->dpitch) 1056 { 1057 if (v) 1058 c->pitch+=(this->geffect?c->vportanote:c->vporta)*16; 1059 else 1060 c->pitch+=(this->geffect?c->eportanote:c->eporta)*16; 1061 1062 if (c->pitch>c->dpitch) 1063 c->pitch=c->dpitch; 1064 } else { 1065 if (v) 1066 c->pitch-=(this->geffect?c->vportanote:c->vporta)*16; 1067 else 1068 c->pitch-=(this->geffect?c->eportanote:c->eporta)*16; 1069 if (c->pitch<c->dpitch) 1070 c->pitch=c->dpitch; 1071 } 1072 c->fpitch=c->pitch; 1073 if (c->pitch==c->dpitch) 1074 c->dpitch=0; 1075 } 1076 1077 static void dodelay(struct itplayer *this, struct it_logchan *c) 1078 { 1079 if (this->curtick==c->specialdata) 1080 { 1081 if (c->delayed[0]||c->delayed[1]) 1082 playnote(this, c, c->delayed); 1083 if (c->delayed[2]) 1084 playvcmd(this, c, c->delayed[2]); 1085 } else if (((this->curtick+1)==(this->speed+this->patdelaytick))&&(!this->patdelayrow)) 1086 { 1087 /* Impulse Tracker has a bug where a too long delay affects the lastinstrument, even if no note were played. 1088 * 1089 * http://eval.sovietrussia.org/wiki/Player_abuse_tests#Out-of-range_note_delays 1090 */ 1091 if (c->delayed[1]) 1092 c->lastins=c->delayed[1]; 1093 } 1094 1095 } 1096 1097 static int rangepitch(struct itplayer *this, int p) 1098 { 1099 return (p<this->pitchhigh)?this->pitchhigh:(p>this->pitchlow)?this->pitchlow:p; 1100 } 1101 1102 static const uint16_t arpnotetab[] = 1103 { 1104 32768, 30929, 29193, 27554, 1105 26008, 24548, 23170, 21870, 1106 20643, 19484, 18390, 17358, 1107 16384, 15464, 14596, 13777 1108 }; 1109 1110 static void processfx(struct itplayer *this, struct it_logchan *c) 1111 { 1112 switch (c->command) 1113 { 1114 case cmdSpeed: 1115 break; 1116 case cmdJump: 1117 break; 1118 case cmdBreak: 1119 break; 1120 case cmdVolSlide: 1121 c->vol=range64(c->vol+tickslide(c->volslide)); 1122 break; 1123 case cmdPortaD: 1124 if (c->eporta>=0xE0) 1125 break; 1126 c->fpitch=c->pitch=rangepitch(this, c->pitch+c->eporta*16); 1127 break; 1128 case cmdPortaU: 1129 if (c->eporta>=0xE0) 1130 break; 1131 c->fpitch=c->pitch=rangepitch(this, c->pitch-c->eporta*16); 1132 if ((c->pitch==this->pitchhigh)&&c->pch) 1133 c->pch->notecut=1; 1134 break; 1135 case cmdPortaNote: 1136 doportanote(this, c, 0); 1137 break; 1138 case cmdVibrato: 1139 dovibrato(this, c); 1140 break; 1141 case cmdTremor: 1142 dotremor(c); 1143 break; 1144 case cmdArpeggio: 1145 { 1146 int arpnote; 1147 switch (this->curtick%3) 1148 { 1149 default: /* remove a warning */ 1150 case 0: 1151 arpnote=0; 1152 break; 1153 case 1: 1154 arpnote=c->arpeggio1; 1155 break; 1156 case 2: 1157 arpnote=c->arpeggio2; 1158 break; 1159 } 1160 if (this->linear) 1161 c->fpitch=c->fpitch-(arpnote<<8); 1162 else 1163 c->fpitch=(c->fpitch*arpnotetab[arpnote])>>15; 1164 break; 1165 } 1166 case cmdPortaVol: 1167 doportanote(this, c, 0); 1168 c->fvol=c->vol=range64(c->vol+tickslide(c->volslide)); 1169 break; 1170 case cmdVibVol: 1171 dovibrato(this, c); 1172 c->fvol=c->vol=range64(c->vol+tickslide(c->volslide)); 1173 break; 1174 case cmdChanVol: 1175 break; 1176 case cmdChanVolSlide: 1177 c->cvol=range64(c->cvol+tickslide(c->cvolslide)); 1178 break; 1179 case cmdOffset: 1180 break; 1181 case cmdPanSlide: 1182 c->fpan=c->cpan=c->pan=range64(c->pan-tickslide(c->panslide)); 1183 break; 1184 case cmdRetrigger: 1185 doretrigger(c); 1186 break; 1187 case cmdTremolo: 1188 dotremolo(this, c); 1189 break; 1190 case cmdSpecial: 1191 switch (c->specialcmd) 1192 { 1193 case cmdSVibType: 1194 break; 1195 case cmdSTremType: 1196 break; 1197 case cmdSPanbrType: 1198 break; 1199 case cmdSPatDelayTick: 1200 break; 1201 case cmdSInstFX: 1202 break; 1203 case cmdSPanning: 1204 break; 1205 case cmdSSurround: 1206 break; 1207 case cmdSOffsetHigh: 1208 break; 1209 case cmdSPatLoop: 1210 break; 1211 case cmdSNoteCut: 1212 if ((this->curtick>=c->specialdata)&&c->pch&&(!this->patdelayrow)) 1213 c->pch->notecut=1; 1214 break; 1215 case cmdSNoteDelay: 1216 dodelay(this, c); 1217 break; 1218 case cmdSPatDelayRow: 1219 break; 1220 } 1221 break; 1222 case cmdTempo: 1223 if (c->tempo<0x20) 1224 { 1225 this->tempo+=(c->tempo<0x10)?-c->tempo:(c->tempo&0xF); 1226 this->tempo=(this->tempo<0x20)?0x20:(this->tempo>0xFF)?0xFF:this->tempo; 1227 putque(this, queTempo, -1, this->tempo); 1228 } 1229 break; 1230 case cmdFineVib: 1231 dovibrato(this, c); 1232 break; 1233 case cmdGVolume: 1234 break; 1235 case cmdGVolSlide: 1236 this->gvol=range128(this->gvol+tickslide(c->gvolslide)); 1237 putque(this, queGVol, -1, this->gvol); 1238 break; 1239 case cmdPanning: 1240 break; 1241 case cmdPanbrello: 1242 dopanbrello(this, c); 1243 break; 1244 } 1245 1246 1247 if ((c->vcmd>=cmdVVolSlD)&&(c->vcmd<(cmdVVolSlD+10))) 1248 c->fvol=c->vol=range64(c->vol-c->vvolslide); 1249 else if ((c->vcmd>=cmdVVolSlU)&&(c->vcmd<(cmdVVolSlU+10))) 1250 c->fvol=c->vol=range64(c->vol+c->vvolslide); 1251 else if ((c->vcmd>=cmdVVibrato)&&(c->vcmd<(cmdVVibrato+10))) 1252 dovibrato(this, c); 1253 else if ((c->vcmd>=cmdVPortaNote)&&(c->vcmd<(cmdVPortaNote+10))) 1254 doportanote(this, c, 1); 1255 else if ((c->vcmd>=cmdVPortaU)&&(c->vcmd<(cmdVPortaU+10))) 1256 { 1257 c->fpitch=c->pitch=rangepitch(this, c->pitch-c->vporta*16); 1258 if ((c->pitch==this->pitchhigh)&&c->pch) 1259 c->pch->notecut=1; 1260 } else if ((c->vcmd>=cmdVPortaD)&&(c->vcmd<(cmdVPortaD+10))) 1261 c->fpitch=c->pitch=rangepitch(this, c->pitch+c->vporta*16); 1262 } 1263 1264 static void inittickchan(struct it_physchan *p) 1265 { 1266 p->fvol=p->vol; 1267 p->fpan=p->pan; 1268 p->fpitch=p->pitch; 1269 } 1270 1271 static void inittick(struct it_logchan *c) 1272 { 1273 c->fvol=c->vol; 1274 c->fpan=c->pan; 1275 c->fpitch=c->pitch; 1276 } 1277 1278 static void initrow(struct it_logchan *c) 1279 { 1280 c->command=0; 1281 c->vcmd=0; 1282 } 1283 1284 static void updatechan(struct it_logchan *c) 1285 { 1286 struct it_physchan *p; 1287 if (!c->pch) 1288 return; 1289 p=c->pch; 1290 p->vol=(c->vol*c->cvol)>>4; 1291 p->fvol=(c->fvol*c->cvol)>>4; 1292 p->pan=c->pan*4-128; 1293 p->fpan=c->fpan*4-128; 1294 p->cutoff=c->cutoff; 1295 p->fcutoff=c->fcutoff; 1296 p->reso=c->reso; 1297 p->pitch=-c->pitch; 1298 p->fpitch=-c->fpitch; 1299 p->srnd=c->srnd; 1300 } 1301 1302 static int processenvelope(const struct it_envelope *env, int *pos, int noteoff, int env_type_active) 1303 { 1304 int i, x; 1305 1306 for (i=0; i<env->len; i++) 1307 if ((*pos)<env->x[i+1]) 1308 break; 1309 1310 if (env->x[i]==env->x[i+1] || (*pos)==env->x[i]) 1311 x=256*env->y[i]; 1312 else { 1313 float s=(float)((*pos)-env->x[i])/(float)(env->x[i+1]-env->x[i]); 1314 x=256.0*((1-s)*env->y[i]+s*env->y[i+1]); 1315 } 1316 1317 if (env_type_active) 1318 (*pos)++; 1319 1320 if (!noteoff&&(env->type&env_type_slooped)) 1321 { 1322 if ((*pos)==(env->x[env->sloope]+1)) 1323 (*pos)=env->x[env->sloops]; 1324 } else if (env->type&env_type_looped) 1325 { 1326 if ((*pos)==(env->x[env->loope]+1)) 1327 (*pos)=env->x[env->loops]; 1328 } 1329 if ((*pos)>env->x[env->len]) 1330 (*pos)=env->x[env->len]; 1331 1332 return x; 1333 } 1334 1335 static void processchan(struct itplayer *this, struct it_physchan *p) 1336 { 1337 int x; 1338 1339 if (p->volenvpos||p->volenv) 1340 p->fvol=(processenvelope(&p->inst->envs[0], &p->volenvpos, p->noteoff, p->volenv)*p->fvol)>>14; 1341 1342 if (p->volenv) 1343 { 1344 const struct it_envelope *env=&p->inst->envs[0]; 1345 if (p->noteoff&&(p->inst->envs[0].type&env_type_looped)) 1346 p->notefade=1; 1347 if ((p->volenvpos==env->x[env->len])&&!(p->inst->envs[0].type&env_type_looped)&&(!(p->inst->envs[0].type&env_type_slooped)||p->noteoff)) 1348 { 1349 if (!env->y[env->len]) 1350 p->notecut=1; 1351 else 1352 p->notefade=1; 1353 } 1354 } else 1355 if (p->noteoff) 1356 p->notefade=1; 1357 1358 p->fvol=(p->fvol*p->fadeval)>>10; 1359 p->fadeval-=p->notefade?(p->fadeval>p->fadespd)?p->fadespd:p->fadeval:0; 1360 if (!p->fadeval) 1361 p->notecut=1; 1362 1363 p->fvol=(this->gvol*p->fvol)>>7; 1364 p->fvol=(p->smp->gvl*p->fvol)>>6; 1365 p->fvol=(p->inst->gbv*p->fvol)>>7; 1366 1367 1368 if (p->panenvpos||p->panenv) 1369 p->fpan+=processenvelope(&p->inst->envs[1], &p->panenvpos, p->noteoff, p->panenv)>>6; 1370 1371 if (p->srnd) 1372 p->fpan=0; 1373 1374 p->fpan=(this->chsep*p->fpan)>>7; 1375 1376 1377 if (p->pitchenvpos||p->pitchenv) 1378 { 1379 if (this->linear) 1380 p->fpitch+=processenvelope(&p->inst->envs[2], &p->pitchenvpos, p->noteoff, p->pitchenv)>>1; 1381 else { 1382 int e=processenvelope(&p->inst->envs[2], &p->pitchenvpos, p->noteoff, p->pitchenv); 1383 int e2; 1384 int shl=0; 1385 int shr=0; 1386 int fac; 1387 while (e>6144) 1388 { 1389 e-=6144; 1390 shl++; 1391 } 1392 while (e<0) 1393 { 1394 e+=6144; 1395 shr++; 1396 } 1397 e2=0x200-(e&0x1ff); 1398 e>>=9; 1399 fac=(e2*arpnotetab[12-e]+(512-e2)*arpnotetab[11-e])>>9; 1400 fac>>=shr; 1401 fac<<=shl; 1402 p->fpitch=imuldiv(p->fpitch,16384,fac); 1403 } 1404 } 1405 1406 switch (p->smp->vit) 1407 { 1408 case 0: x=sintab[p->avibpos&255]*2; break; 1409 case 1: x=128-(p->avibpos&255); break; 1410 case 2: x=128-(p->avibpos&128); break; 1411 default: /* remove a warning */ 1412 case 3: x=(random(this)&255)-128; 1413 } 1414 p->fpitch+=(x*p->avibdep)>>14; 1415 p->avibpos+=p->smp->vis; 1416 p->avibdep+=p->smp->vir; 1417 if (p->avibdep>(p->smp->vid*256)) 1418 p->avibdep=p->smp->vid*256; 1419 1420 if (p->filterenvpos||p->filterenv) 1421 { 1422 p->fcutoff=p->cutoff&0x7f; 1423 p->fcutoff*=processenvelope(&p->inst->envs[2], &p->filterenvpos, p->noteoff, p->filterenv)+8192; 1424 p->fcutoff>>=14; 1425 p->fcutoff|=0x80; 1426 } 1427 1428 } 1429 1430 static void putchandata(struct itplayer *this, struct it_physchan *p) 1431 { 1432 if (p->newsamp!=-1) 1433 { 1434 mcpSet(p->no, mcpCReset, 0); 1435 mcpSet(p->no, mcpCInstrument, p->newsamp); 1436 p->newsamp=-1; 1437 } 1438 if (p->newpos!=-1) 1439 { 1440 mcpSet(p->no, mcpCPosition, p->newpos); 1441 mcpSet(p->no, mcpCLoop, 1); 1442 mcpSet(p->no, mcpCDirect, 0); 1443 mcpSet(p->no, mcpCStatus, 1); 1444 p->newpos=-1; 1445 p->dead=0; 1446 } 1447 if (p->noteoff&&!p->looptype) 1448 { 1449 mcpSet(p->no, mcpCLoop, 2); 1450 p->looptype=1; 1451 } 1452 if (this->linear) 1453 mcpSet(p->no, mcpCPitch, p->fpitch); 1454 else 1455 mcpSet(p->no, mcpCPitch6848, -p->fpitch); 1456 1457 mcpSet(p->no, mcpCVolume, p->fvol); 1458 mcpSet(p->no, mcpCPanning, p->fpan); 1459 mcpSet(p->no, mcpCSurround, p->srnd); 1460 mcpSet(p->no, mcpCMute, this->channels[p->lch].mute); 1461 mcpSet(p->no, mcpCFilterFreq, p->fcutoff); 1462 mcpSet(p->no, mcpCFilterRez, p->reso); 1463 } 1464 1465 void __attribute__ ((visibility ("internal"))) mutechan(struct itplayer *this, int c, int m) 1466 { 1467 if ((c>=0)||(c<this->nchan)) 1468 this->channels[c].mute=m; 1469 } 1470 1471 static void allocatechan(struct itplayer *this, struct it_logchan *c) 1472 { 1473 int i; 1474 1475 if (c->disabled) 1476 { 1477 c->pch=0; 1478 return; 1479 } 1480 for (i=0; i<this->npchan; i++) 1481 if (this->pchannels[i].lch==-1) 1482 break; 1483 1484 if (i==this->npchan) 1485 for (i=0; i<this->npchan; i++) 1486 if (this->pchannels[i].dead) 1487 break; 1488 1489 /* search for most silent NNAed channel */ 1490 if (i==this->npchan) 1491 { 1492 int bestpch=this->npchan; 1493 int bestvol=0xffffff; 1494 for (i=0; i<this->npchan; i++) 1495 if ((this->pchannels[i].notecut || this->pchannels[i].noteoff || this->pchannels[i].notefade) && this->pchannels[i].fvol<=bestvol) 1496 { 1497 bestpch=i; 1498 bestvol=this->pchannels[i].fvol; 1499 } 1500 i=bestpch; 1501 } 1502 1503 /* when everything fails, search for channel with lowest vol */ 1504 if (i==this->npchan) 1505 { 1506 int bestpch=this->npchan; 1507 int bestvol=c->newchan.fvol; 1508 for (i=0; i<this->npchan; i++) 1509 if (this->pchannels[i].fvol<bestvol ) 1510 { 1511 bestpch=i; 1512 bestvol=this->pchannels[i].fvol; 1513 } 1514 i=bestpch; 1515 } 1516 1517 if (i<this->npchan) 1518 { 1519 if (this->pchannels[i].lch!=-1) 1520 { 1521 if (this->channels[this->pchannels[i].lch].pch==&this->pchannels[i]) 1522 this->channels[this->pchannels[i].lch].pch=0; 1523 } 1524 this->pchannels[i]=c->newchan; 1525 this->pchannels[i].lchp=c; 1526 this->pchannels[i].no=i; 1527 c->pch=&this->pchannels[i]; 1528 } else 1529 c->pch=0; 1530 1531 } 1532 1533 static void getproctime(struct itplayer *this) 1534 { 1535 this->proctime=mcpGet(-1, mcpGCmdTimer); 1536 } 1537 1538 static void putglobdata(struct itplayer *this) 1539 { 1540 mcpSet(-1, mcpGSpeed, 256*2*this->tempo/5); 1541 } 1542 1543 static void putque(struct itplayer *this, int type, int val1, int val2) 1544 { 1545 if (((this->quewpos+1)%this->quelen)==this->querpos) 1546 return; 1547 this->que[this->quewpos][0]=this->proctime; 1548 this->que[this->quewpos][1]=type; 1549 this->que[this->quewpos][2]=val1; 1550 this->que[this->quewpos][3]=val2; 1551 this->quewpos=(this->quewpos+1)%this->quelen; 1552 } 1553 1554 static int gettime(void) 1555 { 1556 return mcpGet(-1, mcpGTimer); 1557 } 1558 1559 static void readque(struct itplayer *this) 1560 { 1561 int i; 1562 int time=gettime(); 1563 while (1) 1564 { 1565 int t, val1, val2; 1566 if (this->querpos==this->quewpos) 1567 break; 1568 t=this->que[this->querpos][0]; 1569 if (time<t) 1570 break; 1571 val1=this->que[this->querpos][2]; 1572 val2=this->que[this->querpos][3]; 1573 switch (this->que[this->querpos][1]) 1574 { 1575 case queSync: 1576 this->realsync=val2; 1577 this->realsynctime=t; 1578 this->channels[val1].realsync=val2; 1579 this->channels[val1].realsynctime=t; 1580 break; 1581 case quePos: 1582 this->realpos=val2; 1583 for (i=0; i<this->nchan; i++) 1584 { 1585 struct it_logchan *c=&this->channels[i]; 1586 if (c->evpos==-1) 1587 { 1588 if (c->evpos0==this->realpos) 1589 { 1590 c->evpos=this->realpos; 1591 c->evtime=t; 1592 } 1593 } else { 1594 switch (c->evmodtype) 1595 { 1596 case 1: 1597 c->evmodpos++; 1598 break; 1599 case 2: 1600 if (!(this->realpos&0xFF)) 1601 c->evmodpos++; 1602 break; 1603 case 3: 1604 if (!(this->realpos&0xFFFF)) 1605 c->evmodpos++; 1606 break; 1607 } 1608 if ((c->evmodpos==c->evmod)&&c->evmod) 1609 { 1610 c->evmodpos=0; 1611 c->evpos=this->realpos; 1612 c->evtime=t; 1613 } 1614 } 1615 } 1616 break; 1617 case queGVol: this->realgvol=val2; break; 1618 case queTempo: this->realtempo=val2; break; 1619 case queSpeed: this->realspeed=val2; break; 1620 }; 1621 this->querpos=(this->querpos+1)%this->quelen; 1622 } 1623 } 1624 1625 static void checkchan(struct itplayer *this, struct it_physchan *p) 1626 { 1627 if (!mcpGet(p->no, mcpCStatus)) 1628 p->dead=1; 1629 if (p->dead&&(this->channels[p->lch].pch!=p)) 1630 p->notecut=1; 1631 if (p->notecut) 1632 { 1633 if (this->channels[p->lch].pch==p) 1634 this->channels[p->lch].pch=0; 1635 p->lch=-1; 1636 mcpSet(p->no, mcpCReset, 0); 1637 return; 1638 } 1639 } 1640 1641 static void playtick(struct itplayer *this) 1642 { 1643 int i; 1644 1645 if (!this->npchan) 1646 return; 1647 1648 getproctime(this); 1649 readque(this); 1650 1651 for (i=0; i<this->nchan; i++) 1652 inittick(&this->channels[i]); 1653 1654 if (this->looped&&this->noloop) 1655 return; 1656 1657 this->curtick++; 1658 if ((this->curtick==(this->speed+this->patdelaytick))&&this->patdelayrow) 1659 { 1660 this->curtick=0; 1661 this->patdelayrow--; 1662 } 1663 1664 if (this->curtick==(this->speed+this->patdelaytick)) 1665 { 1666 this->patdelaytick=0; 1667 this->curtick=0; 1668 for (i=0; i<this->nchan; i++) 1669 { 1670 struct it_logchan *ch=&this->channels[i]; 1671 ch->fnotehit=0; 1672 ch->fvolslide=0; 1673 ch->fpitchslide=0; 1674 ch->fpanslide=0; 1675 ch->fpitchfx=0; 1676 ch->fvolfx=0; 1677 ch->fnotefx=0; 1678 ch->fx=0; 1679 } 1680 this->currow++; 1681 if ((this->gotoord==-1)&&(this->currow==this->patlens[this->orders[this->curord]])) 1682 { 1683 this->gotoord=this->curord+1; 1684 this->gotorow=0; 1685 } 1686 if (this->gotoord!=-1) 1687 { 1688 if (this->gotoord!=this->curord) 1689 for (i=0; i<this->nchan; i++) 1690 { 1691 struct it_logchan *c=&this->channels[i]; 1692 c->patloopcount=0; 1693 c->patloopstart=0; 1694 } 1695 if (this->gotoord>=this->endord) 1696 { 1697 this->gotoord=0; 1698 if (!this->manualgoto && this->noloop) 1699 this->looped=1; 1700 for (i=0; i<this->nchan; i++) 1701 { 1702 struct it_logchan *c=&this->channels[i]; 1703 c->retrigspd=1; 1704 c->tremoron=1; 1705 c->tremoroff=1; 1706 c->tremoroncounter=0; 1707 c->tremoroffcounter=0; 1708 } 1709 } 1710 while (this->orders[this->gotoord]==0xFFFF) 1711 this->gotoord++; 1712 if (this->gotoord==this->endord) 1713 this->gotoord=0; 1714 if (this->gotorow>=this->patlens[this->orders[this->gotoord]]) 1715 { 1716 this->gotoord++; 1717 this->gotorow=0; 1718 while (this->orders[this->gotoord]==0xFFFF) 1719 this->gotoord++; 1720 if (this->gotoord==this->endord) 1721 this->gotoord=0; 1722 } 1723 this->curord=this->gotoord; 1724 this->patptr=this->patterns[this->orders[this->curord]]; 1725 for (this->currow=0; this->currow<this->gotorow; this->currow++) 1726 { 1727 while (*this->patptr) 1728 this->patptr+=6; 1729 this->patptr++; 1730 } 1731 this->gotoord=-1; 1732 } 1733 1734 if (this->looped&&this->noloop) 1735 { 1736 for (i=0; i<this->nchan; i++) 1737 { 1738 mutechan(this, i, 1); 1739 updatechan(&this->channels[i]); 1740 } 1741 return; 1742 } 1743 1744 for (i=0; i<this->nchan; i++) 1745 initrow(&this->channels[i]); 1746 while (*this->patptr) 1747 { 1748 struct it_logchan *c=&this->channels[*this->patptr++-1]; 1749 int delay; 1750 if ((this->patptr[3]==cmdSpecial)&&this->patptr[4]) 1751 { 1752 c->specialcmd=this->patptr[4]>>4; 1753 c->specialdata=this->patptr[4]&0xF; 1754 } 1755 if ((this->patptr[3]==cmdSpecial)&&(c->specialcmd==cmdSNoteDelay)) 1756 { 1757 memcpy(c->delayed, this->patptr, /*sizeof(c->delayed)*/5); /* else we might read unknown unmapped memory */ 1758 delay=1; 1759 } else { 1760 if (this->patptr[0]||this->patptr[1]) 1761 playnote(this, c, this->patptr); 1762 delay=0; 1763 } 1764 if (this->patptr[3]) 1765 playcmd(this, c, this->patptr[3], this->patptr[4]); /* we need notedata to know if Portamento should do anything */ 1766 if (!delay) 1767 if (this->patptr[2]) 1768 playvcmd(this, c, this->patptr[2]); 1769 this->patptr+=5; 1770 } 1771 this->patptr++; 1772 if (this->patdelayrow) /* in case, the first SEx command was SE0, we fetch this by storing SEx+1 to this->patdelayrow */ 1773 this->patdelayrow--; 1774 } else 1775 for (i=0; i<this->nchan; i++) 1776 processfx(this, &this->channels[i]); 1777 1778 this->manualgoto=0; 1779 this->gvolslide=0; 1780 1781 for (i=0; i<this->npchan; i++) 1782 inittickchan(&this->pchannels[i]); 1783 for (i=0; i<this->nchan; i++) 1784 updatechan(&this->channels[i]); 1785 for (i=0; i<this->npchan; i++) 1786 if (this->pchannels[i].lch!=-1) 1787 checkchan(this, &this->pchannels[i]); 1788 for (i=0; i<this->npchan; i++) 1789 if (this->pchannels[i].lch!=-1) 1790 processchan(this, &this->pchannels[i]); 1791 for (i=0; i<this->nchan; i++) 1792 if (this->channels[i].pch==&this->channels[i].newchan) 1793 { 1794 processchan(this, this->channels[i].pch); 1795 allocatechan(this, &this->channels[i]); 1796 } 1797 for (i=0; i<this->npchan; i++) 1798 if (this->pchannels[i].lch!=-1) 1799 putchandata(this, &this->pchannels[i]); 1800 1801 putglobdata(this); 1802 putque(this, quePos, -1, (this->curtick&0xFF)|(this->currow<<8)|(this->curord<<16)); 1803 } 1804 1805 int __attribute__ ((visibility ("internal"))) loadsamples(struct it_module *m) 1806 { 1807 return mcpLoadSamples(m->sampleinfos, m->nsampi); 1808 } 1809 1810 int __attribute__ ((visibility ("internal"))) play(struct itplayer *this, const struct it_module *m, int ch, struct ocpfilehandle_t *file) 1811 { 1812 int i; 1813 staticthis=this; 1814 1815 this->randseed=1; 1816 this->patdelayrow=0; 1817 this->patdelaytick=0; 1818 this->gotoord=0; 1819 this->gotorow=0; 1820 this->endord=m->endord; 1821 this->nord=m->nord; 1822 this->nchan=m->nchan; 1823 this->orders=m->orders; 1824 this->patlens=m->patlens; 1825 this->patterns=m->patterns; 1826 this->ninst=m->ninst; 1827 this->instruments=m->instruments; 1828 this->nsamp=m->nsamp; 1829 this->samples=m->samples; 1830 this->sampleinfos=m->sampleinfos; 1831 this->nsampi=m->nsampi; 1832 this->midicmds=m->midicmds; 1833 this->speed=m->inispeed; 1834 this->tempo=m->initempo; 1835 this->gvol=m->inigvol; 1836 this->chsep=m->chsep; 1837 this->linear=m->linear; 1838 this->oldfx=!!m->oldfx; 1839 this->instmode=m->instmode; 1840 this->geffect=m->geffect; 1841 this->curtick=this->speed-1; 1842 this->currow=0; 1843 this->realpos=0; 1844 this->pitchhigh=-0x6000; 1845 this->pitchlow=0x6000; 1846 this->realsynctime=0; 1847 this->realsync=0; 1848 this->realtempo=this->tempo; 1849 this->realspeed=this->speed; 1850 this->realgvol=this->gvol; 1851 1852 this->curord=0; 1853 while (this->orders[this->curord]==0xFFFF && this->curord<this->nord) 1854 this->curord++; 1855 1856 if (this->curord==this->nord) 1857 return 0; 1858 1859 this->channels=malloc(sizeof(struct it_logchan)*this->nchan); 1860 this->pchannels=malloc(sizeof(struct it_physchan)*ch); 1861 this->quelen=500; 1862 this->que=malloc(sizeof(int)*this->quelen*4); 1863 if (!this->channels||!this->pchannels||!this->que) 1864 { 1865 if (this->channels) 1866 { 1867 free(this->channels); 1868 this->channels=NULL; 1869 }; 1870 if (this->pchannels) 1871 { 1872 free(this->pchannels); 1873 this->pchannels=NULL; 1874 } 1875 if (this->que) 1876 { 1877 free(this->que); 1878 this->que=NULL; 1879 } 1880 return 0; 1881 } 1882 this->querpos=this->quewpos=0; 1883 memset(this->channels, 0, sizeof(*this->channels)*this->nchan); 1884 memset(this->pchannels, 0, sizeof(*this->pchannels)*ch); 1885 for (i=0; i<ch; i++) 1886 this->pchannels[i].lch=-1; 1887 for (i=0; i<this->nchan; i++) 1888 { 1889 struct it_logchan *c=&this->channels[i]; 1890 c->newchan.lch=i; 1891 c->cvol=m->inivol[i]; 1892 c->cpan=m->inipan[i]&127; 1893 c->srnd=c->cpan==100; 1894 c->disabled=m->inipan[i]&128; 1895 c->retrigspd=1; 1896 c->tremoron=1; 1897 c->tremoroff=1; 1898 c->tremoroncounter=0; 1899 c->tremoroffcounter=0; 1900 } 1901 1902 if (!mcpOpenPlayer(ch, playtickstatic, file)) 1903 return 0; 1904 1905 this->npchan=mcpNChan; 1906 1907 return 1; 1908 } 1909 1910 void __attribute__ ((visibility ("internal"))) stop(struct itplayer *this) 1911 { 1912 mcpClosePlayer(); 1913 if (this->channels) 1914 { 1915 free(this->channels); 1916 this->channels=NULL; 1917 }; 1918 if (this->pchannels) 1919 { 1920 free(this->pchannels); 1921 this->pchannels=NULL; 1922 } 1923 if (this->que) 1924 { 1925 free(this->que); 1926 this->que=NULL; 1927 } 1928 } 1929 1930 int __attribute__ ((visibility ("internal"))) getpos(struct itplayer *this) 1931 { 1932 if (this->manualgoto) 1933 return (this->gotorow<<8)|(this->gotoord<<16); 1934 return (this->curtick&0xFF)|(this->currow<<8)|(this->curord<<16); 1935 } 1936 1937 int __attribute__ ((visibility ("internal"))) getrealpos(struct itplayer *this) 1938 { 1939 readque(this); 1940 return this->realpos; 1941 } 1942 1943 int __attribute__ ((visibility ("internal"))) getchansample(struct itplayer *this, int ch, int16_t *buf, int len, uint32_t rate, int opt) 1944 { 1945 int i,n; 1946 unsigned int chn[64]; 1947 n=0; 1948 for (i=0; i<this->npchan; i++) 1949 if (this->pchannels[i].lch==ch) 1950 chn[n++]=i; 1951 mcpMixChanSamples(chn, n, buf, len, rate, opt); 1952 return 1; 1953 } 1954 1955 void __attribute__ ((visibility ("internal"))) itplayer_getrealvol(struct itplayer *this, int ch, int *l, int *r) 1956 { 1957 int i, voll, volr; 1958 1959 *l = *r = 0; 1960 1961 for (i=0; i<this->npchan; i++) 1962 if (this->pchannels[i].lch==ch) 1963 { 1964 mcpGetRealVolume(i, &voll, &volr); 1965 (*l)+=voll; 1966 (*r)+=volr; 1967 } 1968 } 1969 1970 void __attribute__ ((visibility ("internal"))) setpos(struct itplayer *this, int ord, int row) 1971 { 1972 int i; 1973 if (this->curord!=ord) 1974 for (i=0; i<this->npchan; i++) 1975 this->pchannels[i].notecut=1; 1976 this->curtick=this->speed-1; 1977 this->patdelaytick=0; 1978 this->patdelayrow=0; 1979 if ((ord==this->curord)&&(row>this->patlens[this->orders[this->curord]])) 1980 { 1981 row=0; 1982 ord++; 1983 } 1984 this->gotorow=(row>0xFF)?0xFF:(row<0)?0:row; 1985 this->gotoord=((ord>=this->nord)||(ord<0))?0:ord; 1986 this->manualgoto=1; 1987 this->querpos=this->quewpos=0; 1988 this->realpos=(this->gotorow<<8)|(this->gotoord<<16); 1989 } 1990 1991 int __attribute__ ((visibility ("internal"))) getdotsdata(struct itplayer *this, int ch, int pch, int *smp, int *note, int *voll, int *volr, int *sus) 1992 { 1993 struct it_physchan *p; 1994 for (; pch<this->npchan; pch++) 1995 if ((this->pchannels[pch].lch==ch)&&!this->pchannels[pch].dead) 1996 break; 1997 if (pch>=this->npchan) 1998 return -1; 1999 p=&this->pchannels[pch]; 2000 *smp=p->smp->handle; 2001 2002 if (this->linear) 2003 *note=p->noteoffset+p->fpitch; 2004 else 2005 if (p->noteoffset+p->fpitch) 2006 *note=p->noteoffset+mcpGetNote8363(6848*8363/p->fpitch); 2007 else 2008 *note=0; 2009 2010 mcpGetRealVolume(p->no, voll, volr); 2011 *sus=!(p->noteoff||p->notefade); 2012 return pch+1; 2013 } 2014 2015 void __attribute__ ((visibility ("internal"))) getglobinfo(struct itplayer *this, int *tmp, int *bp, int *gv, int *gs) 2016 { 2017 readque(this); 2018 *tmp=this->realspeed; 2019 *bp=this->realtempo; 2020 *gv=this->realgvol; 2021 *gs=this->gvolslide?(this->gvolslide>0?ifxGVSUp:ifxGVSDown):0; 2022 } 2023 2024 int __attribute__ ((visibility ("internal"))) getsync(struct itplayer *this, int ch, int *time) 2025 { 2026 readque(this); 2027 if ((ch<0)||(ch>=this->nchan)) 2028 { 2029 *time=gettime()-this->realsynctime; 2030 return this->realsync; 2031 } else { 2032 *time=gettime()-this->channels[ch].realsynctime; 2033 return this->channels[ch].realsync; 2034 } 2035 } 2036 /* 2037 int __attribute__ ((visibility ("internal"))) getticktime(struct itplayer *this) 2038 { 2039 readque(this); 2040 return 65536*5/(2*this->realtempo); 2041 } 2042 2043 int __attribute__ ((visibility ("internal"))) getrowtime(struct itplayer *this) 2044 { 2045 readque(this); 2046 return 65536*5*this->realspeed/(2*this->realtempo); 2047 }*/ 2048 /* 2049 void __attribute__ ((visibility ("internal"))) setevpos(struct itplayer *this, int ch, int pos, int modtype, int mod) 2050 { 2051 struct it_logchan *c; 2052 if ((ch<0)||(ch>=this->nchan)) 2053 return; 2054 c=&this->channels[ch]; 2055 c->evpos0=pos; 2056 c->evmodtype=modtype; 2057 c->evmod=mod; 2058 c->evmodpos=0; 2059 c->evpos=-1; 2060 c->evtime=-1; 2061 } 2062 */ 2063 /* 2064 int __attribute__ ((visibility ("internal"))) getevpos(struct itplayer *this, int ch, int *time) 2065 { 2066 readque(this); 2067 if ((ch<0)||(ch>=this->nchan)) 2068 { 2069 *time=-1; 2070 return -1; 2071 } 2072 *time=gettime()-this->channels[ch].evtime; 2073 return this->channels[ch].evpos; 2074 } 2075 */ 2076 /* 2077 int __attribute__ ((visibility ("internal"))) findevpos(struct itplayer *this, int pos, int *time) 2078 { 2079 int i; 2080 readque(this); 2081 for (i=0; i<this->nchan; i++) 2082 if (this->channels[i].evpos==pos) 2083 break; 2084 *time=gettime()-this->channels[i].evtime; 2085 return this->channels[i].evpos; 2086 } 2087 */ 2088 2089 void __attribute__ ((visibility ("internal"))) setloop(struct itplayer *this, int s) 2090 { 2091 this->noloop=!s; 2092 } 2093 2094 int __attribute__ ((visibility ("internal"))) getloop(struct itplayer *this) 2095 { 2096 return this->looped; 2097 } 2098 2099 int __attribute__ ((visibility ("internal"))) chanactive(struct itplayer *this, int ch, int *lc) 2100 { 2101 struct it_physchan *p=&this->pchannels[ch]; 2102 *lc=p->lch; 2103 if (!(*lc>-1)&&p->smp&&p->fvol) 2104 return 0; /* force mcpGet to be checked last - stian */ 2105 return mcpGet(ch, mcpCStatus); 2106 } 2107 2108 int __attribute__ ((visibility ("internal"))) lchanactive(struct itplayer *this, int lc) 2109 { 2110 struct it_physchan *p=this->channels[lc].pch; 2111 if (!p) 2112 return 0; /* avoid strange crashes on some archs - stian */ 2113 if (!(p->smp&&p->fvol)) 2114 return 0; /* force mcpGet to be checked last - stian */ 2115 return mcpGet(p->no, mcpCStatus); 2116 } 2117 2118 int __attribute__ ((visibility ("internal"))) getchanins(struct itplayer *this, int ch) 2119 { 2120 struct it_physchan *p=&this->pchannels[ch]; 2121 return p->inst->handle+1; 2122 } 2123 2124 int __attribute__ ((visibility ("internal"))) getchansamp(struct itplayer *this, int ch) 2125 { 2126 struct it_physchan *p=&this->pchannels[ch]; 2127 if (!p->smp) 2128 return 0xFFFF; 2129 return p->smp->handle; 2130 } 2131 2132 2133 void __attribute__ ((visibility ("internal"))) getchaninfo(struct itplayer *this, uint8_t ch, struct it_chaninfo *ci) 2134 { 2135 const struct it_logchan *t=&this->channels[ch]; 2136 if (t->pch) 2137 { 2138 ci->ins=getchanins(this, t->pch->no); 2139 ci->smp=getchansamp(this, t->pch->no); 2140 ci->note=t->curnote+11; 2141 ci->vol=t->vol; 2142 if (!t->pch->fadeval) 2143 ci->vol=0; 2144 ci->pan=t->srnd?16:t->pan>>2; 2145 ci->notehit=t->fnotehit; 2146 ci->volslide=t->fvolslide; 2147 ci->pitchslide=t->fpitchslide; 2148 ci->panslide=t->fpanslide; 2149 ci->volfx=t->fvolfx; 2150 ci->pitchfx=t->fpitchfx; 2151 ci->notefx=t->fnotefx; 2152 ci->fx=t->fx; 2153 } else 2154 memset(ci, 0, sizeof(*ci)); 2155 } 2156 2157 int __attribute__ ((visibility ("internal"))) getchanalloc(struct itplayer *this, uint8_t ch) 2158 { 2159 int num=0; 2160 int i; 2161 for (i=0; i<this->npchan; i++) 2162 { 2163 struct it_physchan *p=&this->pchannels[i]; 2164 if (p->lch==ch && !p->dead) 2165 num++; 2166 } 2167 return num; 2168 } 2169