1 /* 2 * Copyright (c) 2009, The MilkyTracker Team. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * - Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * - Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * - Neither the name of the <ORGANIZATION> nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 /* 31 * PlayerSTD.h 32 * MilkyPlay 33 * 34 * Created by Peter Barth on Tue Oct 19 2004. 35 * 36 */ 37 #ifndef __PLAYERSTD_H__ 38 #define __PLAYERSTD_H__ 39 40 #include "ChannelMixer.h" 41 #include "PlayerBase.h" 42 #include "XModule.h" 43 44 class PlayerSTD : public PlayerBase 45 { 46 public: 47 struct StatusEventListener 48 { ~StatusEventListenerStatusEventListener49 virtual ~StatusEventListener() { } 50 playerTickStartedStatusEventListener51 virtual void playerTickStarted(PlayerSTD& player, XModule& module) { } playerTickEndedStatusEventListener52 virtual void playerTickEnded(PlayerSTD& player, XModule& module) { } timerTickStartedStatusEventListener53 virtual void timerTickStarted(PlayerSTD& player, XModule& module) { } timerTickEndedStatusEventListener54 virtual void timerTickEnded(PlayerSTD& player, XModule& module) { } patternEndReachedStatusEventListener55 virtual void patternEndReached(PlayerSTD& player, XModule& module, mp_sint32& newOrderIndex) { } 56 }; 57 58 private: 59 enum 60 { 61 XM_MINPERIOD = 50 62 }; 63 64 struct TPrEnv 65 { 66 TEnvelope* envstruc; 67 mp_sint32 a,b,step; 68 mp_uint32 bpmCounter, bpmAdder; 69 70 mp_uint32 timeTrackSize; 71 72 struct TTimeRecord 73 { 74 mp_sword pos; 75 const TEnvelope* envstruc; 76 }; 77 78 TTimeRecord* timeRecord; 79 TPrEnvTPrEnv80 TPrEnv() : 81 timeTrackSize(0), 82 timeRecord(NULL) 83 { 84 } 85 ~TPrEnvTPrEnv86 ~TPrEnv() 87 { 88 delete[] timeRecord; 89 } 90 clearTPrEnv91 void clear() 92 { 93 envstruc = 0; 94 a = b = step = 0; 95 bpmCounter = bpmAdder = 0; 96 97 if (timeTrackSize && timeRecord) 98 memset(timeRecord, 0, sizeof(TTimeRecord)*timeTrackSize); 99 } 100 reallocTimeRecordTPrEnv101 void reallocTimeRecord(mp_uint32 size) 102 { 103 timeTrackSize = size; 104 delete[] timeRecord; 105 timeRecord = new TTimeRecord[size]; 106 } 107 108 void setToTick(mp_uint32 tick); 109 }; 110 111 struct TLastOperands 112 { 113 mp_ubyte portaup; 114 mp_ubyte portadown; 115 mp_ubyte portanote; 116 mp_ubyte fineportaup; 117 mp_ubyte fineportadown; 118 mp_ubyte xfineportaup; 119 mp_ubyte xfineportadown; 120 mp_ubyte volslide; 121 mp_ubyte finevolslide; 122 mp_ubyte gvolslide; 123 mp_ubyte panslide; 124 mp_ubyte arpeg; 125 mp_ubyte retrig; 126 mp_ubyte tremor; 127 mp_ubyte smpoffset; 128 }; 129 130 struct TModuleChannel 131 { 132 mp_uint32 flags; 133 mp_sint32 ins; 134 mp_sint32 smp; 135 bool hasSetVolume; 136 mp_sint32 vol, tremoloVol, finalTremoloVol, tremorVol; 137 bool hasTremolo; 138 mp_sint32 masterVol; 139 mp_sint32 pan; 140 mp_sint32 per, finalVibratoPer, destper; 141 bool hasVibrato; 142 //mp_sint32 c4spd; 143 mp_sint32 currentnote, relnote; 144 mp_sint32 finetune; 145 mp_sword freqadjust; 146 mp_sint32 note, destnote, lastnoportanote; 147 bool validnote; 148 mp_ubyte eff[MP_NUMEFFECTS]; 149 mp_ubyte eop[MP_NUMEFFECTS]; 150 TLastOperands old[MP_NUMEFFECTS]; 151 152 mp_sint32 loopstart; 153 mp_sint32 execloop; 154 mp_sint32 loopcounter; 155 bool isLooping; 156 mp_sint32 loopingValidPosition; 157 158 mp_ubyte vibdepth[MP_NUMEFFECTS]; 159 mp_ubyte vibspeed[MP_NUMEFFECTS]; 160 mp_ubyte vibpos[MP_NUMEFFECTS]; 161 mp_ubyte trmdepth[MP_NUMEFFECTS]; 162 mp_ubyte trmspeed[MP_NUMEFFECTS]; 163 mp_ubyte trmpos[MP_NUMEFFECTS]; 164 mp_ubyte tremorcnt[MP_NUMEFFECTS]; 165 mp_sint32 retrigcounterE9x[MP_NUMEFFECTS]; 166 mp_ubyte retrigmaxE9x[MP_NUMEFFECTS]; 167 mp_sint32 retrigcounterRxx[MP_NUMEFFECTS]; 168 mp_ubyte retrigmaxRxx[MP_NUMEFFECTS]; 169 170 bool keyon; 171 TPrEnv venv; 172 TPrEnv penv; 173 TPrEnv fenv; 174 TPrEnv vibenv; 175 mp_sint32 fadevolstart; 176 mp_sint32 fadevolstep; 177 mp_ubyte avibused; 178 mp_ubyte avibspd; 179 mp_ubyte avibdepth; 180 mp_ubyte avibcnt; 181 mp_ubyte avibsweep; 182 mp_ubyte avibswcnt; 183 clearTModuleChannel184 void clear() 185 { 186 flags = 0; 187 ins = 0; 188 smp = 0; 189 hasSetVolume = 0; 190 vol = tremoloVol = finalTremoloVol = tremorVol = 0; 191 hasTremolo = false; 192 masterVol = 0; 193 pan = 0; 194 per = finalVibratoPer = destper = 0; 195 hasVibrato = 0; 196 currentnote = relnote = 0; 197 finetune = 0; 198 freqadjust = 0; 199 note = destnote = lastnoportanote = 0; 200 validnote = false; 201 memset(&eff, 0, sizeof(eff)); 202 memset(&eop, 0, sizeof(eop)); 203 memset(&old, 0, sizeof(old)); 204 205 loopstart = 0; 206 execloop = 0; 207 loopcounter = 0; 208 isLooping = false; 209 loopingValidPosition = 0; 210 211 memset(&vibdepth, 0, sizeof(vibdepth)); 212 memset(&vibpos, 0, sizeof(vibpos)); 213 memset(&trmdepth, 0, sizeof(trmdepth)); 214 memset(&trmspeed, 0, sizeof(trmspeed)); 215 memset(&trmpos, 0, sizeof(trmpos)); 216 memset(&tremorcnt, 0, sizeof(tremorcnt)); 217 memset(&retrigcounterE9x, 0, sizeof(retrigcounterE9x)); 218 219 memset(&retrigmaxE9x, 0, sizeof(retrigmaxE9x)); 220 memset(&retrigcounterRxx, 0, sizeof(retrigcounterRxx)); 221 memset(&retrigmaxRxx, 0, sizeof(retrigmaxRxx)); 222 223 keyon = false; 224 venv.clear(); 225 penv.clear(); 226 fenv.clear(); 227 vibenv.clear(); 228 229 fadevolstart = 0; 230 fadevolstep = 0; 231 avibused = 0; 232 avibspd = 0; 233 avibdepth = 0; 234 avibcnt = 0; 235 avibsweep = 0; 236 avibswcnt = 0; 237 } 238 reallocTimeRecordTModuleChannel239 void reallocTimeRecord(mp_uint32 size) 240 { 241 venv.reallocTimeRecord(size); 242 penv.reallocTimeRecord(size); 243 fenv.reallocTimeRecord(size); 244 vibenv.reallocTimeRecord(size); 245 } 246 }; 247 248 private: 249 250 static const mp_sint32 vibtab[32]; 251 static const mp_uword lintab[769]; 252 static const mp_uint32 logtab[]; 253 254 StatusEventListener* statusEventListener; 255 256 TModuleChannel* chninfo; // our channel information 257 mp_sint32 lastNumAllocatedChannels; 258 259 mp_uint32* smpoffs; 260 mp_ubyte* attick; 261 262 mp_sint32 patternIndex; // holds current pattern index 263 mp_sint32 numEffects; // current number of effects 264 mp_sint32 numChannels; // current number of channels 265 266 mp_ubyte pbreak; 267 mp_ubyte pbreakpos; 268 mp_sint32 pbreakPriority; 269 mp_ubyte pjump; 270 mp_ubyte pjumppos,pjumprow; 271 mp_sint32 pjumpPriority; 272 bool patDelay; 273 bool haltFlag; 274 mp_sint32 startNextRow; 275 276 mp_sint32 patDelayCount; 277 278 // keep track of what positions we already visited (bitmap) 279 mp_ubyte rowHits[256*256/8]; 280 bool isLooping; 281 282 /////////////////////////////////////////////////////////////////////////////////////////////////// 283 // this information is updated while the song plays 284 /////////////////////////////////////////////////////////////////////////////////////////////////// 285 bool newInsPTFlag; // New instrument PT like 286 bool newInsST3Flag; // New instrument ST3 like 287 bool oldPTInsChangeFlag; // sample without note flag (old PT style) 288 bool playModePT; 289 bool playModePTPitchLimit; 290 bool playModeFT2; 291 bool playModeChopSampleOffset; 292 isRowVisited(mp_sint32 row)293 bool isRowVisited(mp_sint32 row) 294 { 295 return (rowHits[row>>3]>>(row&7))&1; 296 } 297 visitRow(mp_sint32 row)298 void visitRow(mp_sint32 row) 299 { 300 rowHits[row>>3] |= (1<<(row&7)); 301 } 302 303 static void prenvelope(mp_sint32 c, TPrEnv* env, mp_sint32 keyon); // process envelopes 304 305 static mp_sint32 getenvval(mp_sint32 c, TPrEnv* env, mp_sint32 n); // get envelope value 306 307 // This takes the period *with* 8 bit fractional part 308 static mp_sint32 getlinfreq(mp_sint32 per); 309 // This takes the period *with* 8 bit fractional part 310 static mp_sint32 getlogfreq(mp_sint32 per); 311 // this returns a period *without* the 8 bit fractional part 312 static mp_sint32 getlinperiod(mp_sint32 note,mp_sint32 relnote,mp_sint32 finetune); 313 static mp_sint32 interpolate(mp_sint32 eax,mp_sint32 ebx,mp_sint32 ecx,mp_sint32 edi,mp_sint32 esi); 314 // this returns a period *without* the 8 bit fractional part 315 static mp_sint32 getlogperiod(mp_sint32 note,mp_sint32 relnote,mp_sint32 finetune); 316 getbpmrate(mp_uint32 bpm)317 mp_uint32 getbpmrate(mp_uint32 bpm) 318 { 319 // digibooster "real BPM" setting 320 mp_uint32 realCiaTempo = (bpm * (baseBpm << 8) / 125) >> 8; 321 322 if (!realCiaTempo) realCiaTempo++; 323 324 mp_int64 t = ((mp_int64)realCiaTempo)<<(32+2); 325 326 const mp_uint32 timerBase = (mp_uint32)(5.0f*500.0f*(MP_BEATLENGTH*MP_TIMERFREQ / (float)MP_BASEFREQ)); 327 328 return (mp_uint32)(t/timerBase); 329 } 330 getperiod(mp_sint32 note,mp_sint32 relnote,mp_sint32 finetune)331 mp_sint32 getperiod(mp_sint32 note,mp_sint32 relnote,mp_sint32 finetune) 332 { 333 if (playModeFT2) 334 { 335 // FT2 doesn't support lower 3 bits 336 if (finetune > 0) 337 finetune &= 0xF8; 338 else if (finetune < 0) 339 { 340 finetune = -((-finetune + 7) & 0xF8); 341 if (finetune < -128) 342 finetune = -128; 343 } 344 } 345 346 return (module->header.freqtab&1) ? getlinperiod(note,relnote,finetune) : getlogperiod(note,relnote,finetune); 347 } 348 getvolume(mp_sint32 c,mp_sint32 nv)349 mp_sint32 getvolume(mp_sint32 c,mp_sint32 nv) 350 { 351 mp_sint32 vol = (nv*getenvval(c,&chninfo[c].venv,256))>>7; 352 vol = (vol*chninfo[c].fadevolstart)>>16; 353 vol = (vol*chninfo[c].masterVol)>>8; 354 vol = (vol*mainVolume)>>8; 355 return vol; 356 } 357 getpanning(mp_sint32 c,mp_sint32 np)358 mp_sint32 getpanning(mp_sint32 c,mp_sint32 np) 359 { 360 mp_sint32 envpan = getenvval(c,&chninfo[c].penv,128); 361 //if (envpan!=256) cprintf("%i\r\n",envpan); 362 mp_sint32 finalpan = np+(envpan-128)*(128-abs(np-128))/128; 363 if (finalpan<0) finalpan=0; 364 if (finalpan>255) finalpan=255; 365 return finalpan; 366 } 367 getfreq(mp_sint32 c,mp_sint32 per,mp_sword freqadjust)368 mp_sint32 getfreq(mp_sint32 c,mp_sint32 per,mp_sword freqadjust) 369 { 370 if (per<1) return 0; 371 mp_sint32 eval = getenvval(c,&chninfo[c].fenv,128)-128; 372 mp_uint32 freq; 373 374 freq = (module->header.freqtab&1) ? getlinfreq(per) : getlogfreq(per); 375 376 mp_sint32 finalFreq = (freq+(eval*63))+freqadjust; 377 if (finalFreq < 0) finalFreq = 0; 378 379 return finalFreq; 380 } 381 382 mp_sint32 getfinalperiod(mp_sint32 c, mp_sint32 p); 383 384 void playInstrument(mp_sint32 chn, TModuleChannel* chnInf, bool bNoRestart = false); 385 386 void triggerEnvelope(TPrEnv& dstEnv, TEnvelope& srcEnv); 387 void triggerEnvelopes(TModuleChannel* chnInf); 388 void triggerAutovibrato(TModuleChannel* chnInf); 389 void triggerInstrumentFX(TModuleChannel* chnInf); 390 391 void updatePlayModeFlags(); 392 handlePeriodOverflow(mp_sint32 channel)393 void handlePeriodOverflow(mp_sint32 channel) 394 { 395 // PTK/FT1 playmode 396 if (playModePTPitchLimit && options[PlayModeOptionForcePTPitchLimit]) 397 { 398 if (chninfo[channel].per > 856*4) 399 chninfo[channel].per = 856*4; 400 } 401 // FT2 playmode (does nothing right now) 402 else 403 { 404 //if (chninfo[channel].per > 14150) 405 // chninfo[channel].per %= 14150; 406 } 407 } 408 handlePeriodUnderflow(mp_sint32 channel)409 void handlePeriodUnderflow(mp_sint32 channel) 410 { 411 // PTK/FT1 playmode 412 if (playModePTPitchLimit && options[PlayModeOptionForcePTPitchLimit]) 413 { 414 if (chninfo[channel].per < 113*4) 415 chninfo[channel].per = 113*4; 416 } 417 // FT2 playmode (clamp on low value, not what FT2 does btw.) 418 else 419 { 420 if (chninfo[channel].per < XM_MINPERIOD) 421 chninfo[channel].per = XM_MINPERIOD; 422 //chninfo[channel].per &= 0x3FFF; 423 } 424 } 425 426 mp_sint32 calcVibrato(TModuleChannel* chnInf, mp_sint32 effcnt); 427 void doTickEffect(mp_sint32 chn, TModuleChannel* chnInf, mp_sint32 effcnt); 428 void doEffect(mp_sint32 chn, TModuleChannel* chnInf, mp_sint32 effcnt); 429 430 void doTickeffects(); 431 void progressRow(); 432 void update(); 433 void updateBPMIndependent(); 434 435 //void handleQueuedPositions(mp_sint32& poscnt); 436 void setNewPosition(mp_sint32 poscnt); 437 438 void tickhandler(); 439 440 mp_sint32 allocateStructures(); 441 void freeMemory(); 442 443 // stop song by setting flag and setting speed to zero 444 void halt(); 445 446 protected: 447 virtual void clearEffectMemory(); 448 449 public: 450 PlayerSTD(mp_uint32 frequency, 451 StatusEventListener* statusEventListener = NULL); 452 453 virtual ~PlayerSTD(); 454 getType()455 virtual PlayerTypes getType() const { return PlayerType_Generic; } 456 457 virtual mp_sint32 adjustFrequency(mp_uint32 frequency); 458 virtual mp_sint32 setBufferSize(mp_uint32 bufferSize); 459 460 // virtual from mixer class, perform playing here 461 virtual void timerHandler(mp_sint32 currentBeatPacket); 462 463 virtual void restart(mp_uint32 startPosition = 0, mp_uint32 startRow = 0, 464 bool resetMixer = true, 465 const mp_ubyte* customPanningTable = NULL, 466 bool playOneRowOnly = false); 467 468 virtual void reset(); 469 470 virtual void resetAllSpeed(); 471 472 virtual bool grabChannelInfo(mp_sint32 chn, TPlayerChannelInfo& channelInfo) const; 473 474 // milkytracker 475 virtual void playNote(mp_ubyte chn, mp_sint32 note, mp_sint32 ins, mp_sint32 vol = -1); 476 setPanning(mp_ubyte chn,mp_ubyte pan)477 virtual void setPanning(mp_ubyte chn, mp_ubyte pan) { chninfo[chn].pan = pan; } 478 479 #ifdef MILKYTRACKER 480 friend class PlayerController; 481 friend class PlayerGeneric; 482 friend class PlayerStatusTracker; 483 #endif 484 }; 485 486 #endif 487