Mod.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796
  1. //
  2. // Urho3D Engine
  3. // Copyright (c) 2008-2011 Lasse Öörni
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. // Original MOD & XM playback code from JUDAS Soundsystem
  24. // Copyright (c) 1997 Lasse Öörni & Olli Niemitalo
  25. #include "Precompiled.h"
  26. #include "Audio.h"
  27. #include "Channel.h"
  28. #include "Deserializer.h"
  29. #include "Mod.h"
  30. #include "Profiler.h"
  31. #include "Sound.h"
  32. #include <cstring>
  33. #include "DebugNew.h"
  34. static const int AMIGA_CLOCK = 3579545;
  35. static const int MOD_INSTRUMENTS = 31;
  36. static const int MOD_MAXLENGTH = 128;
  37. static const int MOD_MAXCHANNELS = 32;
  38. static const int MOD_INFOBLOCK = 1084;
  39. static const int MOD_NAMEOFFSET = 0;
  40. static const int MOD_INSTROFFSET = 20;
  41. static const int MOD_LENGTHOFFSET = 950;
  42. static const int MOD_ORDEROFFSET = 952;
  43. static const int MOD_IDENTOFFSET = 1080;
  44. const ModIdent Mod::sIdent[] =
  45. {
  46. {"2CHN", 2},
  47. {"M.K.", 4},
  48. {"M!K!", 4},
  49. {"4CHN", 4},
  50. {"6CHN", 6},
  51. {"8CHN", 8},
  52. {"10CH", 10},
  53. {"12CH", 12},
  54. {"14CH", 14},
  55. {"16CH", 16},
  56. {"18CH", 18},
  57. {"20CH", 20},
  58. {"22CH", 22},
  59. {"24CH", 24},
  60. {"26CH", 26},
  61. {"28CH", 28},
  62. {"30CH", 30},
  63. {"32CH", 32}
  64. };
  65. const unsigned short Mod::sPeriodTable[16][12] =
  66. {
  67. {6848, 6464, 6096, 5760, 5424, 5120, 4832, 4560, 4304, 4064, 3840, 3624},
  68. {6800, 6416, 6056, 5720, 5392, 5096, 4808, 4536, 4280, 4040, 3816, 3600},
  69. {6752, 6368, 6016, 5672, 5360, 5056, 4776, 4504, 4256, 4016, 3792, 3576},
  70. {6704, 6328, 5968, 5632, 5320, 5024, 4736, 4472, 4224, 3984, 3760, 3552},
  71. {6656, 6280, 5928, 5592, 5280, 4984, 4704, 4440, 4192, 3960, 3736, 3528},
  72. {6608, 6232, 5888, 5552, 5240, 4952, 4672, 4408, 4160, 3928, 3704, 3496},
  73. {6560, 6192, 5840, 5512, 5208, 4912, 4640, 4376, 4128, 3896, 3680, 3472},
  74. {6512, 6144, 5800, 5472, 5168, 4880, 4600, 4344, 4104, 3872, 3656, 3448},
  75. {7256, 6848, 6464, 6096, 5760, 5424, 5120, 4832, 4560, 4304, 4032, 3840},
  76. {7200, 6800, 6416, 6056, 5720, 5400, 5088, 4808, 4536, 4280, 4040, 3816},
  77. {7152, 6752, 6368, 6016, 5672, 5360, 5056, 4776, 4504, 4256, 4016, 3792},
  78. {7096, 6704, 6328, 5968, 5632, 5320, 5024, 4736, 4472, 4224, 3984, 3760},
  79. {7048, 6656, 6280, 5928, 5592, 5280, 4984, 4704, 4440, 4192, 3952, 3736},
  80. {7000, 6608, 6232, 5888, 5552, 5240, 4952, 4672, 4408, 4160, 3928, 3704},
  81. {6944, 6560, 6192, 5840, 5512, 5208, 4912, 4640, 4376, 4128, 3896, 3680},
  82. {6896, 6512, 6144, 5800, 5472, 5168, 4880, 4600, 4344, 4104, 3872, 3656}
  83. };
  84. Mod::Mod(Audio* audio, const std::string& name) :
  85. Song(audio, name),
  86. mPos(0)
  87. {
  88. }
  89. Mod::~Mod()
  90. {
  91. release();
  92. }
  93. void Mod::load(Deserializer& source, ResourceCache* cache)
  94. {
  95. PROFILE(Mod_Load);
  96. release();
  97. unsigned memoryUse = 0;
  98. // Load info
  99. mInfo = new unsigned char[MOD_INFOBLOCK];
  100. source.read(mInfo.getPtr(), MOD_INFOBLOCK);
  101. mInfo[20] = 0;
  102. memoryUse += MOD_INFOBLOCK;
  103. mNumChannels = 0;
  104. for (unsigned i = 0; i < 18; ++i)
  105. {
  106. if (!memcmp(sIdent[i].mString.c_str(), &mInfo[MOD_IDENTOFFSET], 4))
  107. mNumChannels = sIdent[i].mChannels;
  108. }
  109. if (!mNumChannels)
  110. EXCEPTION("Could not determine mod format from " + source.getName());
  111. // Create tracks
  112. mTracks.resize(mNumChannels);
  113. mPatternLength = mNumChannels * 256;
  114. mLength = mInfo[MOD_LENGTHOFFSET];
  115. unsigned char* order = &mInfo[MOD_ORDEROFFSET];
  116. mNumPatterns = 0;
  117. for (unsigned i = 0; i < MOD_MAXLENGTH; ++i)
  118. if (order[i] > mNumPatterns) mNumPatterns = order[i];
  119. mNumPatterns++;
  120. // Read patterns
  121. mPatterns = new unsigned char[mPatternLength * mNumPatterns];
  122. source.read(mPatterns.getPtr(), mPatternLength * mNumPatterns);
  123. memoryUse += mPatternLength * mNumPatterns;
  124. ModNote* destPtr = (ModNote*)mPatterns.getPtr();
  125. unsigned char* srcPtr = mPatterns;
  126. for (unsigned i = 0; i < mPatternLength * mNumPatterns / 4; ++i)
  127. {
  128. unsigned short period = ((srcPtr[0] & 0x0f) << 8) | srcPtr[1];
  129. unsigned char note = 0, instrument, command;
  130. if (period)
  131. {
  132. int findNote;
  133. int offset = M_MAX_INT;
  134. for (findNote = 0; findNote < 96; ++findNote)
  135. {
  136. if (abs(period - (sPeriodTable[0][findNote % 12] >> (findNote / 12))) < offset)
  137. {
  138. note = findNote + 1;
  139. offset = abs(period - (sPeriodTable[0][findNote % 12] >> (findNote / 12)));
  140. }
  141. }
  142. }
  143. instrument = (srcPtr[0] & 0xf0) | ((srcPtr[2] & 0xf0) >> 4);
  144. command = srcPtr[2] & 0x0f;
  145. destPtr->mNote = note;
  146. destPtr->mInstrNum = instrument;
  147. destPtr->mCommand = command;
  148. srcPtr += 4;
  149. destPtr++;
  150. }
  151. // Load samples
  152. unsigned char *modInstr = &mInfo[MOD_INSTROFFSET];
  153. for (unsigned i = 0; i < MOD_INSTRUMENTS; ++i)
  154. {
  155. ModInstrument instr;
  156. memoryUse += sizeof instr;
  157. int length, repeat, end;
  158. bool looped = false;
  159. length = ((modInstr[22] << 8) | (modInstr[23])) << 1;
  160. repeat = ((modInstr[26] << 8) | (modInstr[27])) << 1;
  161. end = ((modInstr[28] << 8) | (modInstr[29])) << 1;
  162. instr.mFineTune = modInstr[24];
  163. instr.mVolume = modInstr[25];
  164. if (length)
  165. {
  166. if (end > 2)
  167. {
  168. looped = true;
  169. end += repeat;
  170. if (end > length) end = length;
  171. }
  172. else
  173. end = length;
  174. instr.mSound = new Sound();
  175. instr.mSound->setSize(length);
  176. memoryUse += instr.mSound->getMemoryUse();
  177. source.read(instr.mSound->getStart(), length);
  178. if (looped)
  179. instr.mSound->setLoop(repeat, end);
  180. }
  181. mInstruments.push_back(instr);
  182. modInstr += 30;
  183. }
  184. setMemoryUse(memoryUse);
  185. mLoaded = true;
  186. }
  187. void Mod::release()
  188. {
  189. stop();
  190. mLoaded = false;
  191. mTracks.clear();
  192. mInstruments.clear();
  193. mInfo.reset();
  194. mPatterns.reset();
  195. }
  196. void Mod::play(unsigned position)
  197. {
  198. if (!mLoaded)
  199. return;
  200. stop();
  201. if (position >= mLength)
  202. position = 0;
  203. mPos = position;
  204. mLine = 0;
  205. mTickCount = 0;
  206. mTickTempo = 6;
  207. mPatternDelay = 0;
  208. setBpmTempo(125);
  209. setNumChannels(mNumChannels);
  210. for (unsigned i = 0; i < mNumChannels; ++i)
  211. {
  212. ModTrack* tptr = &mTracks[i];
  213. Channel* chptr = mChannels[i];
  214. chptr->setIntPanning(Song::sPanningTable[i & 3]);
  215. memset(tptr, 0, sizeof(ModInstrument));
  216. tptr->mInstr = &mInstruments[0];
  217. }
  218. mPlaying = true;
  219. if (mAudio)
  220. mAudio->addSong(this);
  221. }
  222. void Mod::updatePlayer()
  223. {
  224. // Set new notes or do something else?
  225. if ((!mTickCount) && (!mPatternDelay))
  226. {
  227. ModNote* notePtr;
  228. unsigned char* order = &mInfo[MOD_ORDEROFFSET];
  229. notePtr = (ModNote*)(mPatterns.getPtr() + order[mPos] * mPatternLength + mLine * mNumChannels * sizeof(ModNote));
  230. mPatternBreak = false;
  231. for (unsigned i = 0; i < mNumChannels; ++i)
  232. {
  233. ModTrack* tptr = &mTracks[i];
  234. Channel* chptr = mChannels[i];
  235. tptr->mNewNote = 0;
  236. tptr->mRetrigCount = 0;
  237. // Get note (if any)
  238. if (notePtr->mNote)
  239. {
  240. tptr->mNote = notePtr->mNote - 1;
  241. tptr->mNewNote = 1;
  242. }
  243. // Get effect, effect data etc.
  244. tptr->mEffect = notePtr->mCommand;
  245. tptr->mEffectData = notePtr->mData;
  246. tptr->mNybble1 = notePtr->mData >> 4;
  247. tptr->mNybble2 = notePtr->mData & 0xf;
  248. tptr->mNewInstrNum = notePtr->mInstrNum;
  249. // Set sampleoffset here
  250. if (tptr->mNewInstrNum)
  251. tptr->mUseSoundOffset = false;
  252. if (tptr->mEffect == 0x9)
  253. {
  254. if (tptr->mEffectData) tptr->mSoundOffset = tptr->mEffectData;
  255. tptr->mUseSoundOffset = true;
  256. }
  257. // Start new note if there is one; but check for notedelay
  258. if ((tptr->mEffect != 0xe) || (tptr->mNybble1 != 0xd) || (tptr->mNybble2 == 0))
  259. {
  260. if (tptr->mNewNote) startNewNote(tptr, chptr);
  261. if (tptr->mNewInstrNum)
  262. {
  263. tptr->mInstrNum = tptr->mNewInstrNum - 1;
  264. tptr->mInstr = &mInstruments[tptr->mInstrNum];
  265. tptr->mVolume = tptr->mInstr->mVolume;
  266. chptr->setIntVolume(tptr->mVolume);
  267. }
  268. }
  269. // Reset period if not vibrato or toneportamento
  270. if ((tptr->mEffect < 0x3) || (tptr->mEffect > 0x6))
  271. {
  272. tptr->mPeriod = tptr->mBasePeriod;
  273. }
  274. // Reset volume if not tremolo
  275. if (tptr->mEffect != 0x7)
  276. chptr->setIntVolume(tptr->mVolume);
  277. switch (tptr->mEffect)
  278. {
  279. case 0x0:
  280. break;
  281. // Set portamento speed up
  282. case 0x1:
  283. if (tptr->mEffectData) tptr->mPortaSpeedUp = tptr->mEffectData;
  284. break;
  285. // Set portamento speed down
  286. case 0x2:
  287. if (tptr->mEffectData) tptr->mPortaSpeedDown = tptr->mEffectData;
  288. break;
  289. // Set TP. speed
  290. case 0x3:
  291. if (tptr->mEffectData) tptr->mTonePortaSpeed = tptr->mEffectData;
  292. break;
  293. // Set vibrato
  294. case 0x4:
  295. if (tptr->mNybble1) tptr->mVibratoSpeed = tptr->mNybble1;
  296. if (tptr->mNybble2) tptr->mVibratoDepth = tptr->mNybble2;
  297. break;
  298. // Set tremolo
  299. case 0x7:
  300. if (tptr->mNybble1) tptr->mTremoloSpeed = tptr->mNybble1;
  301. if (tptr->mNybble2) tptr->mTremoloDepth = tptr->mNybble2;
  302. break;
  303. // Set panning
  304. case 0x8:
  305. chptr->setIntPanning(tptr->mEffectData);
  306. break;
  307. // Volume slide speed set
  308. case 0x5:
  309. case 0x6:
  310. case 0xa:
  311. if (tptr->mEffectData)
  312. {
  313. tptr->mVolSpeedUp = tptr->mNybble1;
  314. tptr->mVolSpeedDown = tptr->mNybble2;
  315. }
  316. break;
  317. // Pos. jump
  318. case 0xb:
  319. mLine = 63;
  320. mPos = tptr->mEffectData - 1;
  321. break;
  322. // Set volume
  323. case 0xc:
  324. tptr->mVolume = tptr->mEffectData;
  325. chptr->setIntVolume(tptr->mVolume);
  326. break;
  327. // Pattern break
  328. case 0xd:
  329. if (!mPatternBreak)
  330. {
  331. mPatternBreak = true;
  332. mLine = tptr->mNybble1 * 10 + tptr->mNybble2 - 1;
  333. mPos++;
  334. }
  335. break;
  336. // Extended command
  337. case 0xe:
  338. extendedCommand(tptr, chptr);
  339. break;
  340. // Set tempo
  341. case 0xf:
  342. if (!tptr->mEffectData)
  343. {
  344. mPlaying = false;
  345. break;
  346. }
  347. if (tptr->mEffectData < 32) mTickTempo = tptr->mEffectData;
  348. else setBpmTempo(tptr->mEffectData);
  349. break;
  350. }
  351. if (tptr->mPeriod)
  352. chptr->setIntFrequency(AMIGA_CLOCK / tptr->mPeriod);
  353. notePtr++;
  354. }
  355. }
  356. if (mTickCount)
  357. {
  358. // If tick isn't 0, update continuous effects
  359. for (unsigned i = 0; i < mNumChannels; ++i)
  360. {
  361. Channel* chptr = mChannels[i];
  362. ModTrack* tptr = &mTracks[i];
  363. switch (tptr->mEffect)
  364. {
  365. // Arpeggio
  366. case 0x0:
  367. {
  368. if (tptr->mEffectData)
  369. {
  370. char phase = mTickCount % 3;
  371. switch (phase)
  372. {
  373. unsigned char arpNote;
  374. case 0:
  375. tptr->mPeriod = tptr->mBasePeriod;
  376. break;
  377. case 1:
  378. arpNote = tptr->mNote + tptr->mNybble1;
  379. if (arpNote > 95) arpNote = 95;
  380. tptr->mPeriod = sPeriodTable[tptr->mFineTune][arpNote % 12] >> (arpNote / 12);
  381. break;
  382. case 2:
  383. arpNote = tptr->mNote + tptr->mNybble2;
  384. if (arpNote > 95) arpNote = 95;
  385. tptr->mPeriod = sPeriodTable[tptr->mFineTune][arpNote % 12] >> (arpNote / 12);
  386. break;
  387. }
  388. }
  389. }
  390. break;
  391. // Portamento up
  392. case 0x1:
  393. tptr->mBasePeriod -= tptr->mPortaSpeedUp;
  394. if (tptr->mBasePeriod < 27) tptr->mBasePeriod = 27;
  395. tptr->mPeriod = tptr->mBasePeriod;
  396. break;
  397. // Portamento down
  398. case 0x2:
  399. tptr->mBasePeriod += tptr->mPortaSpeedDown;
  400. if (tptr->mBasePeriod > 7256) tptr->mBasePeriod = 7256;
  401. tptr->mPeriod = tptr->mBasePeriod;
  402. break;
  403. // Toneportamento
  404. case 0x3:
  405. tonePortamento(tptr, chptr);
  406. break;
  407. // Vibrato
  408. case 0x4:
  409. vibrato(tptr, chptr);
  410. break;
  411. // Toneportamento + volslide
  412. case 0x5:
  413. tonePortamento(tptr, chptr);
  414. volumeSlide(tptr, chptr);
  415. break;
  416. // Vibrato + volslide
  417. case 0x6:
  418. vibrato(tptr, chptr);
  419. volumeSlide(tptr, chptr);
  420. break;
  421. // Tremolo
  422. case 0x7:
  423. tptr->mTremoloPhase += tptr->mTremoloSpeed * 4;
  424. chptr->setIntVolume(tptr->mVolume + ((Song::sVibratoTable[tptr->mTremoloType & 3][tptr->mTremoloPhase] * tptr->mTremoloDepth) >> 4));
  425. break;
  426. // Volume slide
  427. case 0xa:
  428. volumeSlide(tptr, chptr);
  429. break;
  430. // Extended command
  431. case 0xe:
  432. extendedCommand(tptr, chptr);
  433. break;
  434. }
  435. if (tptr->mPeriod)
  436. chptr->setIntFrequency(AMIGA_CLOCK / tptr->mPeriod);
  437. }
  438. }
  439. // Advance song
  440. mTickCount++;
  441. if (mTickCount >= mTickTempo)
  442. {
  443. mTickCount = 0;
  444. if (mPatternDelay)
  445. mPatternDelay--;
  446. if (!mPatternDelay)
  447. {
  448. mLine++;
  449. if (mLine >= 64)
  450. {
  451. mLine = 0;
  452. mPos++;
  453. }
  454. if (mPos >= mLength)
  455. mPos = 0;
  456. }
  457. }
  458. }
  459. void Mod::startNewNote(ModTrack* tptr, Channel* chptr)
  460. {
  461. // Change instrument if necessary
  462. if (tptr->mNewInstrNum)
  463. {
  464. tptr->mInstrNum = tptr->mNewInstrNum - 1;
  465. tptr->mInstr = &mInstruments[tptr->mInstrNum];
  466. }
  467. tptr->mFineTune = tptr->mInstr->mFineTune;
  468. if (!(tptr->mVibratoType & 4)) tptr->mVibratoPhase = 0;
  469. if (!(tptr->mTremoloType & 4)) tptr->mTremoloPhase = 0;
  470. if ((tptr->mEffect == 0x3) || (tptr->mEffect == 0x5))
  471. {
  472. // Toneportamento
  473. tptr->mTargetPeriod = sPeriodTable[tptr->mFineTune][tptr->mNote % 12] >> (tptr->mNote / 12);
  474. tptr->mTonePortamento = true;
  475. }
  476. else
  477. {
  478. // Normal note start
  479. tptr->mBasePeriod = sPeriodTable[tptr->mFineTune][tptr->mNote % 12] >> (tptr->mNote / 12);
  480. tptr->mPeriod = tptr->mBasePeriod;
  481. tptr->mTonePortamento = false;
  482. if (tptr->mInstr->mSound)
  483. {
  484. chptr->playLockless(tptr->mInstr->mSound);
  485. if (tptr->mUseSoundOffset)
  486. {
  487. signed char* newPos = tptr->mInstr->mSound->getStart() + (tptr->mSoundOffset << 8);
  488. if (newPos >= tptr->mInstr->mSound->getEnd())
  489. {
  490. if (tptr->mInstr->mSound->isLooped())
  491. chptr->setPlayPositionLockless(tptr->mInstr->mSound->getRepeat());
  492. else
  493. chptr->stopLockless();
  494. }
  495. else
  496. chptr->setPlayPositionLockless(newPos);
  497. }
  498. }
  499. }
  500. }
  501. void Mod::extendedCommand(ModTrack* tptr, Channel* chptr)
  502. {
  503. switch(tptr->mNybble1)
  504. {
  505. // Fine porta up
  506. case 0x1:
  507. if (!mTickCount)
  508. {
  509. if (tptr->mNybble2) tptr->mPortaSpeedUp = tptr->mNybble2;
  510. tptr->mBasePeriod -= tptr->mPortaSpeedUp;
  511. if (tptr->mBasePeriod < 27) tptr->mBasePeriod = 27;
  512. }
  513. break;
  514. // Fine porta down
  515. case 0x2:
  516. if (!mTickCount)
  517. {
  518. if (tptr->mNybble2) tptr->mPortaSpeedDown = tptr->mNybble2;
  519. tptr->mBasePeriod += tptr->mPortaSpeedDown;
  520. if (tptr->mBasePeriod > 7256) tptr->mBasePeriod = 7256;
  521. }
  522. break;
  523. // Set glissando
  524. case 0x3:
  525. if (!mTickCount) tptr->mGlissando = tptr->mNybble2;
  526. break;
  527. // Set vibrato waveform
  528. case 0x4:
  529. if (!mTickCount)
  530. {
  531. tptr->mVibratoType = Song::sVibratoTypeTable[tptr->mNybble2 & 3];
  532. tptr->mVibratoType |= tptr->mNybble2 & 4;
  533. }
  534. break;
  535. // Set finetune
  536. case 0x5:
  537. if ((!mTickCount) && (tptr->mNewNote))
  538. {
  539. tptr->mFineTune = (tptr->mNybble2 - 8) & 15;
  540. tptr->mBasePeriod = sPeriodTable[tptr->mFineTune][tptr->mNote % 12] >> (tptr->mNote / 12);
  541. tptr->mPeriod = tptr->mBasePeriod;
  542. }
  543. break;
  544. // Patternloop
  545. case 0x6:
  546. if (!mTickCount)
  547. {
  548. if (!tptr->mNybble2) tptr->mPatternLoopLine = mLine;
  549. else
  550. {
  551. if (!tptr->mPatternLoopCount)
  552. {
  553. tptr->mPatternLoopCount = tptr->mNybble2;
  554. mLine = tptr->mPatternLoopLine - 1;
  555. }
  556. else
  557. {
  558. tptr->mPatternLoopCount--;
  559. if (tptr->mPatternLoopCount) mLine = tptr->mPatternLoopLine - 1;
  560. }
  561. }
  562. }
  563. break;
  564. // Set tremolo waveform
  565. case 0x7:
  566. if (!mTickCount)
  567. {
  568. tptr->mTremoloType = Song::sVibratoTypeTable[tptr->mNybble2 & 3];
  569. tptr->mTremoloType |= tptr->mNybble2 & 4;
  570. }
  571. break;
  572. // Set panning (undocumented)
  573. case 0x8:
  574. chptr->setIntPanning((tptr->mNybble2 << 4) | tptr->mNybble2);
  575. break;
  576. // Retrig
  577. case 0x9:
  578. if (tptr->mNybble2)
  579. {
  580. if ((!tptr->mNewNote) && (!mTickCount))
  581. {
  582. tptr->mRetrigCount = mTickTempo;
  583. }
  584. if (tptr->mRetrigCount >= tptr->mNybble2)
  585. {
  586. tptr->mRetrigCount = 0;
  587. startNewNote(tptr, chptr);
  588. }
  589. }
  590. tptr->mRetrigCount++;
  591. break;
  592. // Notedelay
  593. case 0xd:
  594. // Don't start on tick 0 or if there's no note
  595. if ((!mTickCount) || (!tptr->mNewNote)) break;
  596. if (mTickCount == tptr->mNybble2)
  597. {
  598. startNewNote(tptr, chptr);
  599. if (tptr->mNewInstrNum)
  600. {
  601. tptr->mVolume = tptr->mInstr->mVolume;
  602. chptr->setIntVolume(tptr->mVolume);
  603. }
  604. }
  605. break;
  606. // Cut note
  607. case 0xc:
  608. if (mTickCount == tptr->mNybble2)
  609. {
  610. tptr->mVolume = 0;
  611. chptr->setIntVolume(0);
  612. }
  613. break;
  614. // Fine volslide up
  615. case 0xa:
  616. if (!mTickCount)
  617. {
  618. if (tptr->mNybble2) tptr->mVolSpeedUp = tptr->mNybble2;
  619. tptr->mVolume += tptr->mVolSpeedUp;
  620. if (tptr->mVolume > 64) tptr->mVolume = 64;
  621. chptr->setIntVolume(tptr->mVolume);
  622. }
  623. break;
  624. // Fine volslide down
  625. case 0xb:
  626. if (!mTickCount)
  627. {
  628. if (tptr->mNybble2) tptr->mVolSpeedDown = tptr->mNybble2;
  629. tptr->mVolume -= tptr->mVolSpeedDown;
  630. if (tptr->mVolume < 0) tptr->mVolume = 0;
  631. chptr->setIntVolume(tptr->mVolume);
  632. }
  633. break;
  634. // Patterndelay
  635. case 0xe:
  636. if (!mTickCount)
  637. mPatternDelay = tptr->mNybble2 + 1;
  638. break;
  639. }
  640. }
  641. void Mod::tonePortamento(ModTrack* tptr, Channel* chptr)
  642. {
  643. if (tptr->mTonePortamento)
  644. {
  645. if (tptr->mBasePeriod < tptr->mTargetPeriod)
  646. {
  647. tptr->mBasePeriod += tptr->mTonePortaSpeed;
  648. if (tptr->mBasePeriod >= tptr->mTargetPeriod)
  649. {
  650. tptr->mBasePeriod = tptr->mTargetPeriod;
  651. tptr->mTonePortamento = false;
  652. }
  653. }
  654. if (tptr->mBasePeriod > tptr->mTargetPeriod)
  655. {
  656. tptr->mBasePeriod -= tptr->mTonePortaSpeed;
  657. if (tptr->mBasePeriod <= tptr->mTargetPeriod)
  658. {
  659. tptr->mBasePeriod = tptr->mTargetPeriod;
  660. tptr->mTonePortamento = false;
  661. }
  662. }
  663. tptr->mPeriod = tptr->mBasePeriod;
  664. if (tptr->mGlissando)
  665. {
  666. int offset = M_MAX_INT;
  667. int sc;
  668. short bestPeriod = 0;
  669. for (sc = 0; sc < 96; sc++)
  670. {
  671. int newOffset = abs(tptr->mPeriod - (sPeriodTable[tptr->mFineTune][sc % 12] >> (sc / 12)));
  672. if (newOffset < offset)
  673. {
  674. bestPeriod = sPeriodTable[tptr->mFineTune][sc % 12] >> (sc / 12);
  675. offset = newOffset;
  676. }
  677. }
  678. tptr->mPeriod = bestPeriod;
  679. }
  680. }
  681. }
  682. void Mod::vibrato(ModTrack* tptr, Channel* chptr)
  683. {
  684. tptr->mVibratoPhase += tptr->mVibratoSpeed * 4;
  685. tptr->mPeriod = tptr->mBasePeriod + ((Song::sVibratoTable[tptr->mVibratoType & 3][tptr->mVibratoPhase] * tptr->mVibratoDepth) >> 5);
  686. if (tptr->mPeriod < 27) tptr->mPeriod = 27;
  687. if (tptr->mPeriod > 7256) tptr->mPeriod = 7256;
  688. }
  689. void Mod::volumeSlide(ModTrack* tptr, Channel* chptr)
  690. {
  691. if (tptr->mVolSpeedUp)
  692. tptr->mVolume += tptr->mVolSpeedUp;
  693. if (tptr->mVolume < 0) tptr->mVolume = 0;
  694. if (tptr->mVolSpeedDown)
  695. tptr->mVolume -= tptr->mVolSpeedDown;
  696. if (tptr->mVolume > 64) tptr->mVolume = 64;
  697. chptr->setIntVolume(tptr->mVolume);
  698. }