SHARE
TWEET

ft2play v1.02

8bitbubsy Jan 27th, 2018 (edited) 783 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2. ** ft2play v1.02 - 21st of June 2019 - https://16-bits.org
  3. ** =======================================================
  4. **                 - NOT BIG ENDIAN SAFE! -
  5. **
  6. ** Very accurate C port of Fasttracker 2's replayer (.XM/.MOD/.FT),
  7. ** by Olav "8bitbubsy" Sørensen. Using the original pascal+asm source
  8. ** codes by Fredrik "Mr.H" Huss (Triton). I have permission to make this
  9. ** C port public.
  10. **
  11. ** You need to link winmm.lib for this to compile (-lwinmm)
  12. ** Alternatively, you can change out the mixer functions at the bottom with
  13. ** your own for your OS.
  14. **
  15. ** Example of ft2play usage:
  16. ** #include "ft2play.h"
  17. ** #include "songdata.h"
  18. **
  19. ** ft2play_PlaySong(songData, songDataLength, true, true, 44100);
  20. ** mainLoop();
  21. ** ft2play_Close();
  22. **
  23. ** To turn a song into an include file like in the example, you can use my win32
  24. ** bin2h tool from here: https://16-bits.org/etc/bin2h.zip
  25. **
  26. ** Changes in v1.02:
  27. ** - Added finer volume calculation resolution
  28. ** - Code cleanup
  29. **
  30. ** Changes in v1.01:
  31. ** - Fixed: The interpolation routine was slightly wrong when playing backwards
  32. **   on pingpong-samples.
  33. ** - Small mixer optimization for very tight sample loops
  34. ** - Some small fixes to the .MOD loader (15-sample format)
  35. **
  36. ** Changes in v1.00:
  37. ** - Fixed an overflow bug if pingpong-looped samples had a loop-length of 1
  38. ** - Code cleanup (uses the "bool" type now, spaces -> tabs, comment style
  39. **   change)
  40. **
  41. ** Changes in v0.99:
  42. ** - Resampling interpolation was changed from 2-tap linear to 3-tap quadratic
  43. **   for less muddy sound.
  44. **
  45. ** Changes in v0.98:
  46. ** - Some code cleanup to match the replayer code in the FT2 clone
  47. ** - Very minor optimization to the replayer rate calculation routine
  48. **
  49. ** Changes in v0.97:
  50. ** - Audio channel mixer optimizations
  51. **
  52. ** Changes in v0.96:
  53. ** - Removed some unneeded logic in the audio channel mixer
  54. **
  55. ** Changes in v0.95:
  56. ** - Turned some unneeded 64-bit calculations into 32-bit
  57. ** - Support loading .MODs with odd (1,3,5..31) channel numbers
  58. **
  59. ** Changes in v0.94:
  60. ** - .MOD/.FT playback was completely broken, sorry!
  61. **
  62. ** Changes in v0.93:
  63. ** - Linear interpolation is done with 16-bit fractional precision instead of
  64. **   15-bit.
  65. **
  66. ** Changes in v0.92:
  67. ** - Added a function to retrieve song name
  68. **
  69. ** Changes in v0.91:
  70. ** - Now uses much faster audio channel mixer from my FT2 clone project
  71. ** - Added support for loading .MOD/.FT files
  72. ** - WinMM mixer has been rewritten to be safe (don't use syscalls in callback)
  73. ** - Some small fixes
  74. ** - Some small changes to the ft2play functions (easier to use and safer!)
  75. */
  76.  
  77. /* ft2play.h:
  78.  
  79. #pragma once
  80.  
  81. #include <stdint.h>
  82. #include <stdbool.h>
  83.  
  84. bool ft2play_PlaySong(const uint8_t *moduleData, uint32_t dataLength, bool useInterpolationFlag, bool useVolumeRampingFlag, uint32_t audioFreq);
  85. void ft2play_Close(void);
  86. void ft2play_PauseSong(bool flag); // true/false
  87. void ft2play_TogglePause(void);
  88. void ft2play_SetMasterVol(uint16_t vol); // 0..256
  89. void ft2play_SetAmp(uint8_t ampFactor); // 1..32
  90. void ft2play_SetInterpolation(bool flag); // true/false
  91. void ft2play_SetVolumeRamping(bool flag); // true/false
  92. char *ft2play_GetSongName(void); // max 20 chars (21 with '\0'), string is in code page 437
  93. uint32_t ft2play_GetMixerTicks(void); // returns the amount of milliseconds of mixed audio (not realtime)
  94. */
  95.  
  96. #define MIX_BUF_SAMPLES 4096
  97.  
  98. #ifndef _USE_MATH_DEFINES
  99. #define _USE_MATH_DEFINES
  100. #endif
  101.  
  102. #include <stdio.h>
  103. #include <stdlib.h>
  104. #include <string.h>
  105. #include <stdint.h>
  106. #include <stdbool.h>
  107. #include <math.h>
  108.  
  109. #define LOOP_FIX_LEN 4
  110.  
  111. #define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
  112.  
  113. #define SWAP16(value) \
  114. ( \
  115.     (((uint16_t)((value) & 0x00FF)) << 8) | \
  116.     (((uint16_t)((value) & 0xFF00)) >> 8)   \
  117. )
  118.  
  119. // fast 32-bit -> 16-bit clamp
  120. #define CLAMP16(i) if ((int16_t)(i) != i) i = 0x7FFF ^ (i >> 31);
  121.  
  122. enum
  123. {
  124.     IS_Vol = 1,
  125.     IS_Period = 2,
  126.     IS_NyTon = 4,
  127.     IS_Pan = 8,
  128.     IS_QuickVol = 16
  129. };
  130.  
  131. #ifdef _MSC_VER
  132. #pragma pack(push)
  133. #pragma pack(1)
  134. #endif
  135. typedef struct songMODInstrHeaderTyp_t
  136. {
  137.     char name[22];
  138.     uint16_t len;
  139.     uint8_t fine, vol;
  140.     uint16_t repS, repL;
  141. }
  142. #ifdef __GNUC__
  143. __attribute__ ((packed))
  144. #endif
  145. songMODInstrHeaderTyp;
  146.  
  147. typedef struct songMOD31HeaderTyp_t
  148. {
  149.     char name[20];
  150.     songMODInstrHeaderTyp instr[31];
  151.     uint8_t len, repS, songTab[128];
  152.     char sig[4];
  153. }
  154. #ifdef __GNUC__
  155. __attribute__ ((packed))
  156. #endif
  157. songMOD31HeaderTyp;
  158.  
  159. typedef struct songMOD15HeaderTyp_t
  160. {
  161.     char name[20];
  162.     songMODInstrHeaderTyp instr[15];
  163.     uint8_t len, repS, songTab[128];
  164. }
  165. #ifdef __GNUC__
  166. __attribute__ ((packed))
  167. #endif
  168. songMOD15HeaderTyp;
  169.  
  170. typedef struct songHeaderTyp_t
  171. {
  172.     char sig[17], name[21], progName[20];
  173.     uint16_t ver;
  174.     int32_t headerSize;
  175.     uint16_t len, repS, antChn, antPtn, antInstrs, flags, defTempo, defSpeed;
  176.     uint8_t songTab[256];
  177. }
  178. #ifdef __GNUC__
  179. __attribute__ ((packed))
  180. #endif
  181. songHeaderTyp;
  182.  
  183. typedef struct sampleHeaderTyp_t
  184. {
  185.     int32_t len, repS, repL;
  186.     uint8_t vol;
  187.     int8_t fine;
  188.     uint8_t typ, pan;
  189.     int8_t relTon;
  190.     uint8_t skrap;
  191.     char name[22];
  192. }
  193. #ifdef __GNUC__
  194. __attribute__ ((packed))
  195. #endif
  196. sampleHeaderTyp;
  197.  
  198. typedef struct instrHeaderTyp_t
  199. {
  200.     int32_t instrSize;
  201.     char name[22];
  202.     uint8_t typ;
  203.     uint16_t antSamp;
  204.     int32_t sampleSize;
  205.     uint8_t ta[96];
  206.     int16_t envVP[12][2], envPP[12][2];
  207.     uint8_t envVPAnt, envPPAnt, envVSust, envVRepS, envVRepE, envPSust, envPRepS;
  208.     uint8_t envPRepE, envVTyp, envPTyp, vibTyp, vibSweep, vibDepth, vibRate;
  209.     uint16_t fadeOut;
  210.     uint8_t midiOn, midiChannel;
  211.     int16_t midiProgram, midiBend;
  212.     int8_t mute;
  213.     uint8_t reserved[15];
  214.     sampleHeaderTyp samp[32];
  215. }
  216. #ifdef __GNUC__
  217. __attribute__ ((packed))
  218. #endif
  219. instrHeaderTyp;
  220.  
  221. typedef struct patternHeaderTyp_t
  222. {
  223.     int32_t patternHeaderSize;
  224.     uint8_t typ;
  225.     uint16_t pattLen, dataLen;
  226. }
  227. #ifdef __GNUC__
  228. __attribute__ ((packed))
  229. #endif
  230. patternHeaderTyp;
  231. #ifdef _MSC_VER
  232. #pragma pack(pop)
  233. #endif
  234.  
  235. typedef struct songTyp_t
  236. {
  237.     uint8_t antChn, pattDelTime, pattDelTime2, pBreakPos, songTab[256];
  238.     bool pBreakFlag, posJumpFlag;
  239.     int16_t songPos, pattNr, pattPos, pattLen;
  240.     uint16_t len, repS, speed, tempo, globVol, timer, ver;
  241.     char name[21];
  242. } songTyp;
  243.  
  244. typedef struct sampleTyp_t // DO NOT TOUCH!
  245. {
  246.     int32_t len, repS, repL;
  247.     uint8_t vol;
  248.     int8_t fine;
  249.     uint8_t typ, pan;
  250.     int8_t relTon;
  251.     uint8_t reserved;
  252.     char name[22];
  253.     int8_t *pek;
  254. } sampleTyp;
  255.  
  256. typedef struct instrTyp_t // DO NOT TOUCH!
  257. {
  258.     uint8_t ta[96];
  259.     int16_t envVP[12][2], envPP[12][2];
  260.     uint8_t envVPAnt, envPPAnt;
  261.     uint8_t envVSust, envVRepS, envVRepE;
  262.     uint8_t envPSust, envPRepS, envPRepE;
  263.     uint8_t envVTyp, envPTyp;
  264.     uint8_t vibTyp, vibSweep, vibDepth, vibRate;
  265.     uint16_t fadeOut;
  266.     uint8_t midiOn, midiChannel;
  267.     int16_t midiProgram, midiBend;
  268.     uint8_t mute, reserved[15];
  269.     int16_t antSamp;
  270.     sampleTyp samp[16];
  271. } instrTyp;
  272.  
  273. typedef struct stmTyp_t
  274. {
  275.     volatile uint8_t status, tmpStatus;
  276.     int8_t relTonNr, fineTune;
  277.     uint8_t sampleNr, stOff, effTyp, eff, smpOffset, tremorSave, tremorPos;
  278.     uint8_t globVolSlideSpeed, panningSlideSpeed, mute, waveCtrl, portaDir;
  279.     uint8_t glissFunk, vibPos, tremPos, vibSpeed, vibDepth, tremSpeed, tremDepth;
  280.     uint8_t pattPos, loopCnt, volSlideSpeed, fVolSlideUpSpeed, fVolSlideDownSpeed;
  281.     uint8_t fPortaUpSpeed, fPortaDownSpeed, ePortaUpSpeed, ePortaDownSpeed;
  282.     uint8_t portaUpSpeed, portaDownSpeed, retrigSpeed, retrigCnt, retrigVol;
  283.     uint8_t volKolVol, tonNr, envPPos, eVibPos, envVPos, realVol, oldVol, outVol;
  284.     uint8_t oldPan, outPan, finalPan;
  285.     bool envSustainActive;
  286.     int16_t realPeriod, envVIPValue, envPIPValue;
  287.     uint16_t finalVol, outPeriod, finalPeriod, instrNr, tonTyp, wantPeriod, portaSpeed;
  288.     uint16_t envVCnt, envVAmp, envPCnt, envPAmp, eVibAmp, eVibSweep;
  289.     uint16_t fadeOutAmp, fadeOutSpeed;
  290.     int32_t smpStartPos;
  291.     sampleTyp *smpPtr;
  292.     instrTyp *instrPtr;
  293. } stmTyp;
  294.  
  295. typedef struct tonTyp_t
  296. {
  297.     uint8_t ton, instr, vol, effTyp, eff;
  298. } tonTyp;
  299.  
  300. typedef void (*mixRoutine)(void *, int32_t);
  301.  
  302. typedef struct
  303. {
  304.     const int8_t *SBase8, *SRevBase8;
  305.     const int16_t *SBase16, *SRevBase16;
  306.     bool backwards, isFadeOutVoice;
  307.     uint8_t SPan;
  308.     uint16_t SVol;
  309.     int32_t SLVol1, SRVol1, SLVol2, SRVol2, SLVolIP, SRVolIP, SVolIPLen, SPos, SLen, SRepS, SRepL;
  310.     uint32_t SPosDec, SFrq, SFrqRev;
  311.     void (*mixRoutine)(void *, int32_t); // function pointer to mix routine
  312. } voice_t;
  313.  
  314. typedef struct
  315. {
  316.     uint8_t *_ptr, *_base;
  317.     bool _eof;
  318.     uint32_t _cnt, _bufsiz;
  319. } MEM;
  320.  
  321. #define MAX_NOTES ((12 * 10 * 16) + 16)
  322. #define MAX_VOICES 32
  323. #define INSTR_SIZE 232
  324. #define INSTR_HEADER_SIZE 263
  325.  
  326. static const uint32_t panningTab[257] =
  327. {
  328.         0, 4096, 5793, 7094, 8192, 9159,10033,10837,11585,12288,12953,13585,14189,14768,15326,15864,
  329.     16384,16888,17378,17854,18318,18770,19212,19644,20066,20480,20886,21283,21674,22058,22435,22806,
  330.     23170,23530,23884,24232,24576,24915,25249,25580,25905,26227,26545,26859,27170,27477,27780,28081,
  331.     28378,28672,28963,29251,29537,29819,30099,30377,30652,30924,31194,31462,31727,31991,32252,32511,
  332.     32768,33023,33276,33527,33776,34024,34270,34514,34756,34996,35235,35472,35708,35942,36175,36406,
  333.     36636,36864,37091,37316,37540,37763,37985,38205,38424,38642,38858,39073,39287,39500,39712,39923,
  334.     40132,40341,40548,40755,40960,41164,41368,41570,41771,41972,42171,42369,42567,42763,42959,43154,
  335.     43348,43541,43733,43925,44115,44305,44494,44682,44869,45056,45242,45427,45611,45795,45977,46160,
  336.     46341,46522,46702,46881,47059,47237,47415,47591,47767,47942,48117,48291,48465,48637,48809,48981,
  337.     49152,49322,49492,49661,49830,49998,50166,50332,50499,50665,50830,50995,51159,51323,51486,51649,
  338.     51811,51972,52134,52294,52454,52614,52773,52932,53090,53248,53405,53562,53719,53874,54030,54185,
  339.     54340,54494,54647,54801,54954,55106,55258,55410,55561,55712,55862,56012,56162,56311,56459,56608,
  340.     56756,56903,57051,57198,57344,57490,57636,57781,57926,58071,58215,58359,58503,58646,58789,58931,
  341.     59073,59215,59357,59498,59639,59779,59919,60059,60199,60338,60477,60615,60753,60891,61029,61166,
  342.     61303,61440,61576,61712,61848,61984,62119,62254,62388,62523,62657,62790,62924,63057,63190,63323,
  343.     63455,63587,63719,63850,63982,64113,64243,64374,64504,64634,64763,64893,65022,65151,65279,65408,
  344.     65536
  345. };
  346.  
  347. static const uint16_t amigaPeriod[12 * 8] =
  348. {
  349.     4*1712,4*1616,4*1524,4*1440,4*1356,4*1280,4*1208,4*1140,4*1076,4*1016,4*960,4*906,
  350.     2*1712,2*1616,2*1524,2*1440,2*1356,2*1280,2*1208,2*1140,2*1076,2*1016,2*960,2*906,
  351.     1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,906,
  352.     856,808,762,720,678,640,604,570,538,508,480,453,
  353.     428,404,381,360,339,320,302,285,269,254,240,226,
  354.     214,202,190,180,170,160,151,143,135,127,120,113,
  355.     107,101,95,90,85,80,75,71,67,63,60,56,
  356.     53,50,47,45,42,40,37,35,33,31,30,28
  357. };
  358.  
  359. static const uint16_t amigaFinePeriod[12 * 8] =
  360. {
  361.     907,900,894,887,881,875,868,862,856,850,844,838,
  362.     832,826,820,814,808,802,796,791,785,779,774,768,
  363.     762,757,752,746,741,736,730,725,720,715,709,704,
  364.     699,694,689,684,678,675,670,665,660,655,651,646,
  365.     640,636,632,628,623,619,614,610,604,601,597,592,
  366.     588,584,580,575,570,567,563,559,555,551,547,543,
  367.     538,535,532,528,524,520,516,513,508,505,502,498,
  368.     494,491,487,484,480,477,474,470,467,463,460,457
  369. };
  370.  
  371. static const uint8_t vibTab[32] =
  372. {
  373.     0,  24,  49, 74, 97,120,141,161,
  374.     180,197,212,224,235,244,250,253,
  375.     255,253,250,244,235,224,212,197,
  376.     180,161,141,120, 97, 74, 49, 24
  377. };
  378.  
  379. static int8_t *vibSineTab;
  380. static volatile bool interpolationFlag, volumeRampingFlag, moduleLoaded, musicPaused, songPlaying;
  381. static bool linearFrqTab;
  382. static int16_t *linearPeriods, *amigaPeriods, *note2Period;
  383. static uint16_t pattLens[256], oldPeriod;
  384. static int32_t masterVol, amp, quickVolSizeVal, pmpLeft, soundBufferSize, *mixBufferL, *mixBufferR;
  385. static uint32_t *logTab, speedVal, sampleCounter, realReplayRate, frequenceDivFactor, frequenceMulFactor;
  386. static uint32_t oldRate, oldSFrq, oldSFrqRev = 0xFFFFFFFF;
  387. static songTyp song;
  388. static tonTyp *patt[256];
  389. static stmTyp stm[MAX_VOICES];
  390. static tonTyp nilPatternLine;
  391. static instrTyp *instr[1 + 128];
  392. static voice_t voice[MAX_VOICES * 2];
  393. static mixRoutine mixRoutineTable[24];
  394.  
  395. static MEM *mopen(const uint8_t *src, uint32_t length);
  396. static void mclose(MEM **buf);
  397. static size_t mread(void *buffer, size_t size, size_t count, MEM *buf);
  398. static bool meof(MEM *buf);
  399. static void mseek(MEM *buf, int32_t offset, int32_t whence);
  400. static bool openMixer(uint32_t audioFreq);
  401. static void closeMixer(void);
  402.  
  403. // CODE START
  404.  
  405. static void setSpeed(uint16_t bpm)
  406. {
  407.     if (bpm > 0)
  408.         speedVal = ((realReplayRate + realReplayRate) + (realReplayRate >> 1)) / bpm;
  409. }
  410.  
  411. static void retrigVolume(stmTyp *ch)
  412. {
  413.     ch->realVol = ch->oldVol;
  414.     ch->outVol = ch->oldVol;
  415.     ch->outPan = ch->oldPan;
  416.     ch->status |= (IS_Vol + IS_Pan + IS_QuickVol);
  417. }
  418.  
  419. static void retrigEnvelopeVibrato(stmTyp *ch)
  420. {
  421.     instrTyp *ins;
  422.  
  423.     if (!(ch->waveCtrl & 0x04)) ch->vibPos = 0;
  424.     if (!(ch->waveCtrl & 0x40)) ch->tremPos = 0;
  425.  
  426.     ch->retrigCnt = 0;
  427.     ch->tremorPos = 0;
  428.  
  429.     ch->envSustainActive = true;
  430.  
  431.     ins = ch->instrPtr;
  432.  
  433.     if (ins->envVTyp & 1)
  434.     {
  435.         ch->envVCnt = 65535;
  436.         ch->envVPos = 0;
  437.     }
  438.  
  439.     if (ins->envPTyp & 1)
  440.     {
  441.         ch->envPCnt = 65535;
  442.         ch->envPPos = 0;
  443.     }
  444.  
  445.     ch->fadeOutSpeed = ins->fadeOut; // FT2 doesn't check if fadeout is more than 4095
  446.     ch->fadeOutAmp = 32768;
  447.  
  448.     if (ins->vibDepth > 0)
  449.     {
  450.         ch->eVibPos = 0;
  451.  
  452.         if (ins->vibSweep > 0)
  453.         {
  454.             ch->eVibAmp = 0;
  455.             ch->eVibSweep = (ins->vibDepth << 8) / ins->vibSweep;
  456.         }
  457.         else
  458.         {
  459.             ch->eVibAmp = ins->vibDepth << 8;
  460.             ch->eVibSweep = 0;
  461.         }
  462.     }
  463. }
  464.  
  465. static void keyOff(stmTyp *ch)
  466. {
  467.     instrTyp *ins;
  468.  
  469.     ch->envSustainActive = false;
  470.  
  471.     ins = ch->instrPtr;
  472.  
  473.     if (!(ins->envPTyp & 1)) // yes, FT2 does this (!)
  474.     {
  475.         if (ch->envPCnt >= ins->envPP[ch->envPPos][0])
  476.             ch->envPCnt = ins->envPP[ch->envPPos][0]-1;
  477.     }
  478.  
  479.     if (ins->envVTyp & 1)
  480.     {
  481.         if (ch->envVCnt >= ins->envVP[ch->envVPos][0])
  482.             ch->envVCnt = ins->envVP[ch->envVPos][0]-1;
  483.     }
  484.     else
  485.     {
  486.         ch->realVol = 0;
  487.         ch->outVol = 0;
  488.         ch->status |= (IS_Vol + IS_QuickVol);
  489.     }
  490. }
  491.  
  492. // 100% FT2-accurate routine, do not touch!
  493. static uint32_t getFrequenceValue(uint16_t period)
  494. {
  495.     uint8_t shift;
  496.     uint16_t index;
  497.     uint32_t rate;
  498.  
  499.     if (period == 0)
  500.         return 0;
  501.        
  502.     if (period == oldPeriod)
  503.         return oldRate; // added check: prevent this calculation if it would yield the same
  504.  
  505.     if (linearFrqTab)
  506.     {
  507.         index = (12 * 192 * 4) - period;
  508.         shift = (14 - (index / 768)) & 0x1F;
  509.  
  510.         // this converts to fast code even on x86 (imul + shrd)
  511.         rate = ((uint64_t)logTab[index % 768] * frequenceMulFactor) >> 24;
  512.         if (shift > 0)
  513.             rate >>= shift;
  514.     }
  515.     else
  516.     {
  517.         rate = frequenceDivFactor / period;
  518.     }
  519.    
  520.     oldPeriod = period;
  521.     oldRate = rate;
  522.  
  523.     return rate;
  524. }
  525.  
  526. static void startTone(uint8_t ton, uint8_t effTyp, uint8_t eff, stmTyp *ch)
  527. {
  528.     uint8_t smp;
  529.     uint16_t tmpTon;
  530.     sampleTyp *s;
  531.     instrTyp *ins;
  532.  
  533.     if (ton == 97)
  534.     {
  535.         keyOff(ch);
  536.         return;
  537.     }
  538.  
  539.     // if we came from Rxy (retrig), we didn't check note (Ton) yet
  540.     if (ton == 0)
  541.     {
  542.         ton = ch->tonNr;
  543.         if (ton == 0)
  544.             return; // if still no note, return
  545.     }
  546.  
  547.     ch->tonNr = ton;
  548.  
  549.     if (instr[ch->instrNr] != NULL)
  550.         ins = instr[ch->instrNr];
  551.     else
  552.         ins = instr[0]; // placeholder for empty instruments
  553.  
  554.     ch->instrPtr = ins;
  555.     ch->mute = ins->mute;
  556.  
  557.     if (ton > 96) // added security check
  558.         ton = 96;
  559.  
  560.     smp = ins->ta[ton-1] & 0x0F;
  561.  
  562.     s = &ins->samp[smp];
  563.     ch->smpPtr = s;
  564.     ch->relTonNr = s->relTon;
  565.  
  566.     ton += ch->relTonNr;
  567.     if (ton >= 12*10)
  568.         return;
  569.  
  570.     ch->oldVol = s->vol;
  571.     ch->oldPan = s->pan;
  572.  
  573.     if (effTyp == 0x0E && (eff & 0xF0) == 0x50)
  574.         ch->fineTune = ((eff & 0x0F) * 16) - 128; // result is now -128 .. 127
  575.     else
  576.         ch->fineTune = s->fine;
  577.  
  578.     if (ton > 0)
  579.     {
  580.         tmpTon = ((ton - 1) * 16) + (((ch->fineTune >> 3) + 16) & 0xFF);
  581.  
  582.         if (tmpTon < MAX_NOTES) // should always happen, but FT2 does this check
  583.         {
  584.             ch->realPeriod = note2Period[tmpTon];
  585.             ch->outPeriod = ch->realPeriod;
  586.         }
  587.     }
  588.  
  589.     ch->status |= (IS_Period + IS_Vol + IS_Pan + IS_NyTon + IS_QuickVol);
  590.  
  591.     if (effTyp == 9)
  592.     {
  593.         if (eff)
  594.             ch->smpOffset = ch->eff;
  595.  
  596.         ch->smpStartPos = ch->smpOffset * 256;
  597.     }
  598.     else
  599.     {
  600.         ch->smpStartPos = 0;
  601.     }
  602. }
  603.  
  604. static void multiRetrig(stmTyp *ch)
  605. {
  606.     uint8_t cnt;
  607.     int16_t vol;
  608.  
  609.     cnt = ch->retrigCnt + 1;
  610.     if (cnt < ch->retrigSpeed)
  611.     {
  612.         ch->retrigCnt = cnt;
  613.         return;
  614.     }
  615.  
  616.     ch->retrigCnt = 0;
  617.  
  618.     vol = ch->realVol;
  619.     switch (ch->retrigVol)
  620.     {
  621.         case 0x1: vol -= 1; break;
  622.         case 0x2: vol -= 2; break;
  623.         case 0x3: vol -= 4; break;
  624.         case 0x4: vol -= 8; break;
  625.         case 0x5: vol -= 16; break;
  626.         case 0x6: vol = (vol >> 1) + (vol >> 3) + (vol >> 4); break;
  627.         case 0x7: vol >>= 1; break;
  628.         case 0x8: break; // does not change the volume
  629.         case 0x9: vol += 1; break;
  630.         case 0xA: vol += 2; break;
  631.         case 0xB: vol += 4; break;
  632.         case 0xC: vol += 8; break;
  633.         case 0xD: vol += 16; break;
  634.         case 0xE: vol = (vol >> 1) + vol; break;
  635.         case 0xF: vol += vol; break;
  636.         default: break;
  637.     }
  638.     vol = CLAMP(vol, 0, 64);
  639.  
  640.     ch->realVol = (uint8_t)vol;
  641.     ch->outVol  = ch->realVol;
  642.  
  643.     if (ch->volKolVol >= 0x10 && ch->volKolVol <= 0x50)
  644.     {
  645.         ch->outVol  = ch->volKolVol - 0x10;
  646.         ch->realVol = ch->outVol;
  647.     }
  648.     else if (ch->volKolVol >= 0xC0 && ch->volKolVol <= 0xCF)
  649.     {
  650.         ch->outPan = (ch->volKolVol & 0x0F) << 4;
  651.     }
  652.  
  653.     startTone(0, 0, 0, ch);
  654. }
  655.  
  656. static void checkMoreEffects(stmTyp *ch)
  657. {
  658.     int8_t envPos;
  659.     bool envUpdate;
  660.     uint8_t tmpEff;
  661.     int16_t newEnvPos;
  662.     uint16_t i;
  663.     instrTyp *ins;
  664.  
  665.     ins = ch->instrPtr;
  666.  
  667.     // Bxx - position jump
  668.     if (ch->effTyp == 11)
  669.     {
  670.         song.songPos = (int16_t)ch->eff - 1;
  671.         song.pBreakPos = 0;
  672.         song.posJumpFlag = true;
  673.     }
  674.  
  675.     // Dxx - pattern break
  676.     else if (ch->effTyp == 13)
  677.     {
  678.         song.posJumpFlag = true;
  679.  
  680.         tmpEff = ((ch->eff >> 4) * 10) + (ch->eff & 0x0F);
  681.         if (tmpEff <= 63)
  682.             song.pBreakPos = tmpEff;
  683.         else
  684.             song.pBreakPos = 0;
  685.     }
  686.  
  687.     // Exx - E effects
  688.     else if (ch->effTyp == 14)
  689.     {
  690.         // E1x - fine period slide up
  691.         if ((ch->eff & 0xF0) == 0x10)
  692.         {
  693.             tmpEff = ch->eff & 0x0F;
  694.             if (tmpEff == 0)
  695.                 tmpEff = ch->fPortaUpSpeed;
  696.  
  697.             ch->fPortaUpSpeed = tmpEff;
  698.  
  699.             ch->realPeriod -= tmpEff * 4;
  700.             if (ch->realPeriod < 1)
  701.                 ch->realPeriod = 1;
  702.  
  703.             ch->outPeriod = ch->realPeriod;
  704.             ch->status |= IS_Period;
  705.         }
  706.  
  707.         // E2x - fine period slide down
  708.         else if ((ch->eff & 0xF0) == 0x20)
  709.         {
  710.             tmpEff = ch->eff & 0x0F;
  711.             if (tmpEff == 0)
  712.                 tmpEff = ch->fPortaDownSpeed;
  713.  
  714.             ch->fPortaDownSpeed = tmpEff;
  715.  
  716.             ch->realPeriod += tmpEff * 4;
  717.             if (ch->realPeriod > 32000-1)
  718.                 ch->realPeriod = 32000-1;
  719.  
  720.             ch->outPeriod = ch->realPeriod;
  721.             ch->status   |= IS_Period;
  722.         }
  723.  
  724.         // E3x - set glissando type
  725.         else if ((ch->eff & 0xF0) == 0x30) ch->glissFunk = ch->eff & 0x0F;
  726.  
  727.         // E4x - set vibrato waveform
  728.         else if ((ch->eff & 0xF0) == 0x40) ch->waveCtrl = (ch->waveCtrl & 0xF0) | (ch->eff & 0x0F);
  729.  
  730.         // E5x (set finetune) is handled in StartTone()
  731.  
  732.         // E6x - pattern loop
  733.         else if ((ch->eff & 0xF0) == 0x60)
  734.         {
  735.             if (ch->eff == 0x60) // E60, empty param
  736.             {
  737.                 ch->pattPos = song.pattPos & 0xFF;
  738.             }
  739.             else
  740.             {
  741.                 if (ch->loopCnt == 0)
  742.                 {
  743.                     ch->loopCnt = ch->eff & 0x0F;
  744.                     song.pBreakPos  = ch->pattPos;
  745.                     song.pBreakFlag = true;
  746.                 }
  747.                 else
  748.                 {
  749.                     if (--ch->loopCnt > 0)
  750.                     {
  751.                         song.pBreakPos  = ch->pattPos;
  752.                         song.pBreakFlag = true;
  753.                     }
  754.                 }
  755.             }
  756.         }
  757.  
  758.         // E7x - set tremolo waveform
  759.         else if ((ch->eff & 0xF0) == 0x70) ch->waveCtrl = ((ch->eff & 0x0F) << 4) | (ch->waveCtrl & 0x0F);
  760.  
  761.         // EAx - fine volume slide up
  762.         else if ((ch->eff & 0xF0) == 0xA0)
  763.         {
  764.             tmpEff = ch->eff & 0x0F;
  765.             if (tmpEff == 0)
  766.                 tmpEff = ch->fVolSlideUpSpeed;
  767.  
  768.             ch->fVolSlideUpSpeed = tmpEff;
  769.  
  770.             // unsigned clamp
  771.             if (ch->realVol <= 64-tmpEff)
  772.                 ch->realVol += tmpEff;
  773.             else
  774.                 ch->realVol = 64;
  775.  
  776.             ch->outVol = ch->realVol;
  777.             ch->status |= IS_Vol;
  778.         }
  779.  
  780.         // EBx - fine volume slide down
  781.         else if ((ch->eff & 0xF0) == 0xB0)
  782.         {
  783.             tmpEff = ch->eff & 0x0F;
  784.             if (tmpEff == 0)
  785.                 tmpEff = ch->fVolSlideDownSpeed;
  786.  
  787.             ch->fVolSlideDownSpeed = tmpEff;
  788.  
  789.             // unsigned clamp
  790.             if (ch->realVol >= tmpEff)
  791.                 ch->realVol -= tmpEff;
  792.             else
  793.                 ch->realVol = 0;
  794.  
  795.             ch->outVol = ch->realVol;
  796.             ch->status |= IS_Vol;
  797.         }
  798.  
  799.         // ECx - note cut
  800.         else if ((ch->eff & 0xF0) == 0xC0)
  801.         {
  802.             if (ch->eff == 0xC0) // empty param
  803.             {
  804.                 ch->realVol = 0;
  805.                 ch->outVol = 0;
  806.                 ch->status |= (IS_Vol + IS_QuickVol);
  807.             }
  808.         }
  809.  
  810.         // EEx - pattern delay
  811.         else if ((ch->eff & 0xF0) == 0xE0)
  812.         {
  813.             if (song.pattDelTime2 == 0)
  814.                 song.pattDelTime = (ch->eff & 0x0F) + 1;
  815.         }
  816.     }
  817.  
  818.     // Fxx - set speed/tempo
  819.     else if (ch->effTyp == 15)
  820.     {
  821.         if (ch->eff >= 32)
  822.         {
  823.             song.speed = ch->eff;
  824.             setSpeed(song.speed);
  825.         }
  826.         else
  827.         {
  828.             song.tempo = ch->eff;
  829.             song.timer = ch->eff;
  830.         }
  831.     }
  832.  
  833.     // Gxx - set global volume
  834.     else if (ch->effTyp == 16)
  835.     {
  836.         song.globVol = ch->eff;
  837.         if (song.globVol > 64)
  838.             song.globVol = 64;
  839.  
  840.         for (i = 0; i < song.antChn; i++) // update all voice volumes
  841.             stm[i].status |= IS_Vol;
  842.     }
  843.  
  844.     // Lxx - set vol and pan envelope position
  845.     else if (ch->effTyp == 21)
  846.     {
  847.         // *** VOLUME ENVELOPE ***
  848.         if (ins->envVTyp & 1)
  849.         {
  850.             ch->envVCnt = ch->eff - 1;
  851.  
  852.             envPos = 0;
  853.             envUpdate = true;
  854.             newEnvPos = ch->eff;
  855.  
  856.             if (ins->envVPAnt > 1)
  857.             {
  858.                 envPos++;
  859.                 for (i = 0; i < ins->envVPAnt-1; i++)
  860.                 {
  861.                     if (newEnvPos < ins->envVP[envPos][0])
  862.                     {
  863.                         envPos--;
  864.  
  865.                         newEnvPos -= ins->envVP[envPos][0];
  866.                         if (newEnvPos == 0)
  867.                         {
  868.                             envUpdate = false;
  869.                             break;
  870.                         }
  871.  
  872.                         if (ins->envVP[envPos+1][0] <= ins->envVP[envPos][0])
  873.                         {
  874.                             envUpdate = true;
  875.                             break;
  876.                         }
  877.  
  878.                         ch->envVIPValue = ((ins->envVP[envPos+1][1] - ins->envVP[envPos][1]) & 0xFF) << 8;
  879.                         ch->envVIPValue /= (ins->envVP[envPos+1][0] - ins->envVP[envPos][0]);
  880.  
  881.                         ch->envVAmp = (ch->envVIPValue * (newEnvPos - 1)) + ((ins->envVP[envPos][1] & 0xFF) << 8);
  882.  
  883.                         envPos++;
  884.  
  885.                         envUpdate = false;
  886.                         break;
  887.                     }
  888.  
  889.                     envPos++;
  890.                 }
  891.  
  892.                 if (envUpdate)
  893.                     envPos--;
  894.             }
  895.  
  896.             if (envUpdate)
  897.             {
  898.                 ch->envVIPValue = 0;
  899.                 ch->envVAmp = (ins->envVP[envPos][1] & 0xFF) << 8;
  900.             }
  901.  
  902.             if (envPos >= ins->envVPAnt)
  903.             {
  904.                 envPos = ins->envVPAnt - 1;
  905.                 if (envPos < 0)
  906.                     envPos = 0;
  907.             }
  908.  
  909.             ch->envVPos = envPos;
  910.         }
  911.  
  912.         // *** PANNING ENVELOPE ***
  913.         if (ins->envVTyp & 2) // probably an FT2 bug
  914.         {
  915.             ch->envPCnt = ch->eff - 1;
  916.  
  917.             envPos = 0;
  918.             envUpdate = true;
  919.             newEnvPos = ch->eff;
  920.  
  921.             if (ins->envPPAnt > 1)
  922.             {
  923.                 envPos++;
  924.                 for (i = 0; i < ins->envPPAnt-1; i++)
  925.                 {
  926.                     if (newEnvPos < ins->envPP[envPos][0])
  927.                     {
  928.                         envPos--;
  929.  
  930.                         newEnvPos -= ins->envPP[envPos][0];
  931.                         if (newEnvPos == 0)
  932.                         {
  933.                             envUpdate = false;
  934.                             break;
  935.                         }
  936.  
  937.                         if (ins->envPP[envPos+1][0] <= ins->envPP[envPos][0])
  938.                         {
  939.                             envUpdate = true;
  940.                             break;
  941.                         }
  942.  
  943.                         ch->envPIPValue = ((ins->envPP[envPos+1][1] - ins->envPP[envPos][1]) & 0xFF) << 8;
  944.                         ch->envPIPValue /= (ins->envPP[envPos+1][0] - ins->envPP[envPos][0]);
  945.  
  946.                         ch->envPAmp = (ch->envPIPValue * (newEnvPos - 1)) + ((ins->envPP[envPos][1] & 0xFF) << 8);
  947.  
  948.                         envPos++;
  949.  
  950.                         envUpdate = false;
  951.                         break;
  952.                     }
  953.  
  954.                     envPos++;
  955.                 }
  956.  
  957.                 if (envUpdate)
  958.                     envPos--;
  959.             }
  960.  
  961.             if (envUpdate)
  962.             {
  963.                 ch->envPIPValue = 0;
  964.                 ch->envPAmp = (ins->envPP[envPos][1] & 0xFF) << 8;
  965.             }
  966.  
  967.             if (envPos >= ins->envPPAnt)
  968.             {
  969.                 envPos = ins->envPPAnt - 1;
  970.                 if (envPos < 0)
  971.                     envPos = 0;
  972.             }
  973.  
  974.             ch->envPPos = envPos;
  975.         }
  976.     }
  977. }
  978.  
  979. static void checkEffects(stmTyp *ch)
  980. {
  981.     uint8_t tmpEff, tmpEffHi, volKol;
  982.  
  983.     // this one is manipulated by vol column effects, then used for multiretrig (FT2 quirk)
  984.     volKol = ch->volKolVol;
  985.  
  986.     // *** VOLUME COLUMN EFFECTS (TICK 0) ***
  987.  
  988.     // set volume
  989.     if (ch->volKolVol >= 0x10 && ch->volKolVol <= 0x50)
  990.     {
  991.         volKol -= 16;
  992.  
  993.         ch->outVol = volKol;
  994.         ch->realVol = volKol;
  995.  
  996.         ch->status |= (IS_Vol + IS_QuickVol);
  997.     }
  998.  
  999.     // fine volume slide down
  1000.     else if ((ch->volKolVol & 0xF0) == 0x80)
  1001.     {
  1002.         volKol = ch->volKolVol & 0x0F;
  1003.  
  1004.         // unsigned clamp
  1005.         if (ch->realVol >= volKol)
  1006.             ch->realVol -= volKol;
  1007.         else
  1008.             ch->realVol = 0;
  1009.  
  1010.         ch->outVol  = ch->realVol;
  1011.         ch->status |= IS_Vol;
  1012.     }
  1013.  
  1014.     // fine volume slide up
  1015.     else if ((ch->volKolVol & 0xF0) == 0x90)
  1016.     {
  1017.         volKol = ch->volKolVol & 0x0F;
  1018.  
  1019.         // unsigned clamp
  1020.         if (ch->realVol <= 64-volKol)
  1021.             ch->realVol += volKol;
  1022.         else
  1023.             ch->realVol = 64;
  1024.  
  1025.         ch->outVol  = ch->realVol;
  1026.         ch->status |= IS_Vol;
  1027.     }
  1028.  
  1029.     // set vibrato speed
  1030.     else if ((ch->volKolVol & 0xF0) == 0xA0)
  1031.     {
  1032.         volKol = (ch->volKolVol & 0x0F) << 2;
  1033.         ch->vibSpeed = volKol;
  1034.     }
  1035.  
  1036.     // set panning
  1037.     else if ((ch->volKolVol & 0xF0) == 0xC0)
  1038.     {
  1039.         volKol <<= 4;
  1040.  
  1041.         ch->outPan = volKol;
  1042.         ch->status |= IS_Pan;
  1043.     }
  1044.  
  1045.     // *** MAIN EFFECTS (TICK 0) ***
  1046.  
  1047.     if (ch->effTyp == 0 && ch->eff == 0) return; // no effect
  1048.  
  1049.     // Cxx - set volume
  1050.     if (ch->effTyp == 12)
  1051.     {
  1052.         ch->realVol = ch->eff;
  1053.         if (ch->realVol > 64)
  1054.             ch->realVol = 64;
  1055.  
  1056.         ch->outVol = ch->realVol;
  1057.         ch->status |= (IS_Vol + IS_QuickVol);
  1058.  
  1059.         return;
  1060.     }
  1061.  
  1062.     // 8xx - set panning
  1063.     else if (ch->effTyp == 8)
  1064.     {
  1065.         ch->outPan  = ch->eff;
  1066.         ch->status |= IS_Pan;
  1067.  
  1068.         return;
  1069.     }
  1070.  
  1071.     // Rxy - note multi retrigger
  1072.     else if (ch->effTyp == 27)
  1073.     {
  1074.         tmpEff = ch->eff & 0x0F;
  1075.         if (tmpEff == 0)
  1076.             tmpEff = ch->retrigSpeed;
  1077.  
  1078.         ch->retrigSpeed = tmpEff;
  1079.  
  1080.         tmpEffHi = ch->eff >> 4;
  1081.         if (tmpEffHi == 0)
  1082.             tmpEffHi = ch->retrigVol;
  1083.  
  1084.         ch->retrigVol = tmpEffHi;
  1085.  
  1086.         if (volKol == 0)
  1087.             multiRetrig(ch);
  1088.  
  1089.         return;
  1090.     }
  1091.  
  1092.     // X1x - extra fine period slide up
  1093.     else if (ch->effTyp == 33 && (ch->eff & 0xF0) == 0x10)
  1094.     {
  1095.         tmpEff = ch->eff & 0x0F;
  1096.         if (tmpEff == 0)
  1097.             tmpEff = ch->ePortaUpSpeed;
  1098.  
  1099.         ch->ePortaUpSpeed = tmpEff;
  1100.  
  1101.         ch->realPeriod -= tmpEff;
  1102.         if (ch->realPeriod < 1)
  1103.             ch->realPeriod = 1;
  1104.  
  1105.         ch->outPeriod = ch->realPeriod;
  1106.         ch->status |= IS_Period;
  1107.  
  1108.         return;
  1109.     }
  1110.  
  1111.     // X2x - extra fine period slide down
  1112.     else if (ch->effTyp == 33 && (ch->eff & 0xF0) == 0x20)
  1113.     {
  1114.         tmpEff = ch->eff & 0x0F;
  1115.         if (tmpEff == 0)
  1116.             tmpEff = ch->ePortaDownSpeed;
  1117.  
  1118.         ch->ePortaDownSpeed = tmpEff;
  1119.  
  1120.         ch->realPeriod += tmpEff;
  1121.         if (ch->realPeriod > 32000-1)
  1122.             ch->realPeriod = 32000-1;
  1123.  
  1124.         ch->outPeriod = ch->realPeriod;
  1125.         ch->status |= IS_Period;
  1126.  
  1127.         return;
  1128.     }
  1129.  
  1130.     checkMoreEffects(ch);
  1131. }
  1132.  
  1133. static void fixTonePorta(stmTyp *ch, tonTyp *p, uint8_t inst)
  1134. {
  1135.     uint16_t portaTmp;
  1136.  
  1137.     if (p->ton > 0)
  1138.     {
  1139.         if (p->ton == 97)
  1140.         {
  1141.             keyOff(ch);
  1142.         }
  1143.         else
  1144.         {
  1145.             portaTmp = ((((p->ton - 1) + ch->relTonNr) & 0xFF) * 16) + (((ch->fineTune >> 3) + 16) & 0xFF);
  1146.             if (portaTmp < MAX_NOTES)
  1147.             {
  1148.                 ch->wantPeriod = note2Period[portaTmp];
  1149.  
  1150.                      if (ch->wantPeriod == ch->realPeriod) ch->portaDir = 0;
  1151.                 else if (ch->wantPeriod  > ch->realPeriod) ch->portaDir = 1;
  1152.                 else ch->portaDir = 2;
  1153.             }
  1154.         }
  1155.     }
  1156.  
  1157.     if (inst > 0)
  1158.     {
  1159.         retrigVolume(ch);
  1160.         if (p->ton != 97)
  1161.             retrigEnvelopeVibrato(ch);
  1162.     }
  1163. }
  1164.  
  1165. static void getNewNote(stmTyp *ch, tonTyp *p)
  1166. {
  1167.     uint8_t inst;
  1168.     bool checkEfx;
  1169.  
  1170.     ch->volKolVol = p->vol;
  1171.  
  1172.     if (ch->effTyp == 0)
  1173.     {
  1174.         if (ch->eff > 0)
  1175.         {
  1176.             // we have an arpeggio running, set period back
  1177.             ch->outPeriod = ch->realPeriod;
  1178.             ch->status |= IS_Period;
  1179.         }
  1180.     }
  1181.     else
  1182.     {
  1183.         if (ch->effTyp == 4 || ch->effTyp == 6)
  1184.         {
  1185.             // we have a vibrato running
  1186.             if (p->effTyp != 4 && p->effTyp != 6)
  1187.             {
  1188.                 // but it's ending at the next (this) row, so set period back
  1189.                 ch->outPeriod = ch->realPeriod;
  1190.                 ch->status |= IS_Period;
  1191.             }
  1192.         }
  1193.     }
  1194.  
  1195.     ch->effTyp = p->effTyp;
  1196.     ch->eff = p->eff;
  1197.     ch->tonTyp = (p->instr << 8) | p->ton;
  1198.  
  1199.     // 'inst' var is used for later if checks...
  1200.     inst = p->instr;
  1201.     if (inst > 0)
  1202.     {
  1203.         if (inst <= 128)
  1204.             ch->instrNr = inst;
  1205.         else
  1206.             inst = 0;
  1207.     }
  1208.  
  1209.     checkEfx = true;
  1210.     if (p->effTyp == 0x0E)
  1211.     {
  1212.         if (p->eff >= 0xD1 && p->eff <= 0xDF)
  1213.             return; // we have a note delay (ED1..EDF)
  1214.         else if (p->eff == 0x90)
  1215.             checkEfx = false;
  1216.     }
  1217.  
  1218.     if (checkEfx)
  1219.     {
  1220.         if ((ch->volKolVol & 0xF0) == 0xF0) // gxx
  1221.         {
  1222.             if ((ch->volKolVol & 0x0F) > 0)
  1223.                 ch->portaSpeed = (ch->volKolVol & 0x0F) << 6;
  1224.  
  1225.             fixTonePorta(ch, p, inst);
  1226.             checkEffects(ch);
  1227.  
  1228.             return;
  1229.         }
  1230.  
  1231.         if (p->effTyp == 3 || p->effTyp == 5) // 3xx or 5xx
  1232.         {
  1233.             if (p->effTyp != 5 && p->eff != 0)
  1234.                 ch->portaSpeed = p->eff << 2;
  1235.  
  1236.             fixTonePorta(ch, p, inst);
  1237.             checkEffects(ch);
  1238.  
  1239.             return;
  1240.         }
  1241.  
  1242.         if (p->effTyp == 0x14 && p->eff == 0) // K00 (KeyOff - only handle tick 0 here)
  1243.         {
  1244.             keyOff(ch);
  1245.  
  1246.             if (inst)
  1247.                 retrigVolume(ch);
  1248.  
  1249.             checkEffects(ch);
  1250.             return;
  1251.         }
  1252.  
  1253.         if (p->ton == 0)
  1254.         {
  1255.             if (inst > 0)
  1256.             {
  1257.                 retrigVolume(ch);
  1258.                 retrigEnvelopeVibrato(ch);
  1259.             }
  1260.  
  1261.             checkEffects(ch);
  1262.             return;
  1263.         }
  1264.     }
  1265.  
  1266.     if (p->ton == 97)
  1267.         keyOff(ch);
  1268.     else
  1269.         startTone(p->ton, p->effTyp, p->eff, ch);
  1270.  
  1271.     if (inst > 0)
  1272.     {
  1273.         retrigVolume(ch);
  1274.  
  1275.         if (p->ton != 97)
  1276.             retrigEnvelopeVibrato(ch);
  1277.     }
  1278.  
  1279.     checkEffects(ch);
  1280. }
  1281.  
  1282. static void fixaEnvelopeVibrato(stmTyp *ch)
  1283. {
  1284.     bool envInterpolateFlag, envDidInterpolate;
  1285.     uint8_t envPos;
  1286.     int16_t autoVibVal, panTmp;
  1287.     uint16_t autoVibAmp, tmpPeriod, envVal;
  1288.     int32_t vol, tmp32;
  1289.     instrTyp *ins;
  1290.     double dVol;
  1291.  
  1292.     ins = ch->instrPtr;
  1293.  
  1294.     // *** FADEOUT ***
  1295.     if (!ch->envSustainActive)
  1296.     {
  1297.         ch->status |= IS_Vol;
  1298.  
  1299.         // unsigned clamp + reset
  1300.         if (ch->fadeOutAmp >= ch->fadeOutSpeed)
  1301.         {
  1302.             ch->fadeOutAmp -= ch->fadeOutSpeed;
  1303.         }
  1304.         else
  1305.         {
  1306.             ch->fadeOutAmp = 0;
  1307.             ch->fadeOutSpeed = 0;
  1308.         }
  1309.     }
  1310.  
  1311.     if (ch->mute != 1)
  1312.     {
  1313.         // *** VOLUME ENVELOPE ***
  1314.         envVal = 0;
  1315.         if (ins->envVTyp & 1)
  1316.         {
  1317.             envDidInterpolate = false;
  1318.             envPos = ch->envVPos;
  1319.  
  1320.             if (++ch->envVCnt == ins->envVP[envPos][0])
  1321.             {
  1322.                 ch->envVAmp = (ins->envVP[envPos][1] & 0xFF) << 8;
  1323.  
  1324.                 envPos++;
  1325.                 if (ins->envVTyp & 4)
  1326.                 {
  1327.                     envPos--;
  1328.  
  1329.                     if (envPos == ins->envVRepE)
  1330.                     {
  1331.                         if (!(ins->envVTyp & 2) || envPos != ins->envVSust || ch->envSustainActive)
  1332.                         {
  1333.                             envPos = ins->envVRepS;
  1334.  
  1335.                             ch->envVCnt = ins->envVP[envPos][0];
  1336.                             ch->envVAmp = (ins->envVP[envPos][1] & 0xFF) << 8;
  1337.                         }
  1338.                     }
  1339.  
  1340.                     envPos++;
  1341.                 }
  1342.  
  1343.                 if (envPos < ins->envVPAnt)
  1344.                 {
  1345.                     envInterpolateFlag = true;
  1346.                     if ((ins->envVTyp & 2) && ch->envSustainActive)
  1347.                     {
  1348.                         if (envPos-1 == ins->envVSust)
  1349.                         {
  1350.                             envPos--;
  1351.                             ch->envVIPValue = 0;
  1352.                             envInterpolateFlag = false;
  1353.                         }
  1354.                     }
  1355.  
  1356.                     if (envInterpolateFlag)
  1357.                     {
  1358.                         ch->envVPos = envPos;
  1359.  
  1360.                         ch->envVIPValue = 0;
  1361.                         if (ins->envVP[envPos][0] > ins->envVP[envPos-1][0])
  1362.                         {
  1363.                             ch->envVIPValue = ((ins->envVP[envPos][1] - ins->envVP[envPos-1][1]) & 0xFF) << 8;
  1364.                             ch->envVIPValue /= (ins->envVP[envPos][0] - ins->envVP[envPos-1][0]);
  1365.  
  1366.                             envVal = ch->envVAmp;
  1367.                             envDidInterpolate = true;
  1368.                         }
  1369.                     }
  1370.                 }
  1371.                 else
  1372.                 {
  1373.                     ch->envVIPValue = 0;
  1374.                 }
  1375.             }
  1376.  
  1377.             if (!envDidInterpolate)
  1378.             {
  1379.                 ch->envVAmp += ch->envVIPValue;
  1380.  
  1381.                 envVal = ch->envVAmp;
  1382.                 if ((envVal >> 8) > 0x40)
  1383.                 {
  1384.                     if ((envVal >> 8) > (0x40+0xC0)/2)
  1385.                         envVal = 16384;
  1386.                     else
  1387.                         envVal = 0;
  1388.  
  1389.                     ch->envVIPValue = 0;
  1390.                 }
  1391.             }
  1392.  
  1393.             /* old integer method with bad precision (FT2 way)
  1394.             envVal >>= 8;
  1395.             ch->finalVol = (song.globVol * (((envVal * ch->outVol) * ch->fadeOutAmp) >> (16 + 2))) >> 7;
  1396.             */
  1397.  
  1398.             /* calculate with four times more precision (+ rounding).
  1399.             ** also, env. range is now 0..16384 instead of being shifted to 0..64. */
  1400.  
  1401.             dVol = song.globVol * ch->outVol * ch->fadeOutAmp;
  1402.             dVol *= envVal; // we need a float mul because it would overflow 32-bit integer
  1403.             dVol *= 1.0 / ((64.0 * 64.0 * 32768.0 * 16384.0) / 2048.0); // 0..2048 (real FT2 is 0..256)
  1404.  
  1405.             vol = (int32_t)(dVol + 0.5);
  1406.             ch->finalVol = (uint16_t)(CLAMP(vol, 0, 2048));
  1407.  
  1408.             ch->status |= IS_Vol;
  1409.         }
  1410.         else
  1411.         {
  1412.             /* old integer method with bad precision (FT2 way)
  1413.             ch->finalVol = (song.globVol * (((ch->outVol << 4) * ch->fadeOutAmp) >> 16)) >> 7;
  1414.             */
  1415.  
  1416.             dVol = song.globVol * ch->outVol * ch->fadeOutAmp;
  1417.             dVol *= 1.0 / ((64.0 * 64.0 * 32768.0) / 2048.0); // 0..2048 (real FT2 is 0..256)
  1418.  
  1419.             vol = (int32_t)(dVol + 0.5);
  1420.             ch->finalVol = (uint16_t)(CLAMP(vol, 0, 2048));
  1421.         }
  1422.     }
  1423.     else
  1424.     {
  1425.         ch->finalVol = 0;
  1426.     }
  1427.  
  1428.     // *** PANNING ENVELOPE ***
  1429.  
  1430.     envVal = 0;
  1431.     if (ins->envPTyp & 1)
  1432.     {
  1433.         envDidInterpolate = false;
  1434.         envPos = ch->envPPos;
  1435.  
  1436.         if (++ch->envPCnt == ins->envPP[envPos][0])
  1437.         {
  1438.             ch->envPAmp = (ins->envPP[envPos][1] & 0xFF) << 8;
  1439.  
  1440.             envPos++;
  1441.             if (ins->envPTyp & 4)
  1442.             {
  1443.                 envPos--;
  1444.  
  1445.                 if (envPos == ins->envPRepE)
  1446.                 {
  1447.                     if (!(ins->envPTyp & 2) || envPos != ins->envPSust || ch->envSustainActive)
  1448.                     {
  1449.                         envPos = ins->envPRepS;
  1450.  
  1451.                         ch->envPCnt = ins->envPP[envPos][0];
  1452.                         ch->envPAmp = (ins->envPP[envPos][1] & 0xFF) << 8;
  1453.                     }
  1454.                 }
  1455.  
  1456.                 envPos++;
  1457.             }
  1458.  
  1459.             if (envPos < ins->envPPAnt)
  1460.             {
  1461.                 envInterpolateFlag = true;
  1462.                 if ((ins->envPTyp & 2) && ch->envSustainActive)
  1463.                 {
  1464.                     if (envPos-1 == ins->envPSust)
  1465.                     {
  1466.                         envPos--;
  1467.                         ch->envPIPValue = 0;
  1468.                         envInterpolateFlag = false;
  1469.                     }
  1470.                 }
  1471.  
  1472.                 if (envInterpolateFlag)
  1473.                 {
  1474.                     ch->envPPos = envPos;
  1475.  
  1476.                     ch->envPIPValue = 0;
  1477.                     if (ins->envPP[envPos][0] > ins->envPP[envPos-1][0])
  1478.                     {
  1479.                         ch->envPIPValue = ((ins->envPP[envPos][1] - ins->envPP[envPos-1][1]) & 0xFF) << 8;
  1480.                         ch->envPIPValue /= (ins->envPP[envPos][0] - ins->envPP[envPos-1][0]);
  1481.  
  1482.                         envVal = ch->envPAmp;
  1483.                         envDidInterpolate = true;
  1484.                     }
  1485.                 }
  1486.             }
  1487.             else
  1488.             {
  1489.                 ch->envPIPValue = 0;
  1490.             }
  1491.         }
  1492.  
  1493.         if (!envDidInterpolate)
  1494.         {
  1495.             ch->envPAmp += ch->envPIPValue;
  1496.  
  1497.             envVal = ch->envPAmp;
  1498.             if ((envVal >> 8) > 0x40)
  1499.             {
  1500.                 if ((envVal >> 8) > (0x40+0xC0)/2)
  1501.                     envVal = 16384;
  1502.                 else
  1503.                     envVal = 0;
  1504.  
  1505.                 ch->envPIPValue = 0;
  1506.             }
  1507.         }
  1508.  
  1509.         panTmp = ch->outPan - 128;
  1510.         if (panTmp > 0)
  1511.             panTmp = 0 - panTmp;
  1512.         panTmp += 128;
  1513.  
  1514.         envVal -= (32 * 256);
  1515.  
  1516.         ch->finalPan = ch->outPan + ((((int16_t)envVal * (panTmp << 3)) >> 16) & 0xFF);
  1517.         ch->status |= IS_Pan;
  1518.     }
  1519.     else
  1520.     {
  1521.         ch->finalPan = ch->outPan;
  1522.     }
  1523.  
  1524.     // *** AUTO VIBRATO ***
  1525.     if (ins->vibDepth > 0)
  1526.     {
  1527.         if (ch->eVibSweep > 0)
  1528.         {
  1529.             autoVibAmp = ch->eVibSweep;
  1530.             if (ch->envSustainActive)
  1531.             {
  1532.                 autoVibAmp += ch->eVibAmp;
  1533.                 if ((autoVibAmp >> 8) > ins->vibDepth)
  1534.                 {
  1535.                     autoVibAmp = ins->vibDepth << 8;
  1536.                     ch->eVibSweep = 0;
  1537.                 }
  1538.  
  1539.                 ch->eVibAmp = autoVibAmp;
  1540.             }
  1541.         }
  1542.         else
  1543.         {
  1544.             autoVibAmp = ch->eVibAmp;
  1545.         }
  1546.  
  1547.         ch->eVibPos += ins->vibRate;
  1548.  
  1549.         // square
  1550.         if (ins->vibTyp == 1)
  1551.             autoVibVal = (ch->eVibPos > 127) ? 64 : -64;
  1552.  
  1553.         // ramp up
  1554.         else if (ins->vibTyp == 2)
  1555.             autoVibVal = (((ch->eVibPos >> 1) + 64) & 127) - 64;
  1556.  
  1557.         // ramp down
  1558.         else if (ins->vibTyp == 3)
  1559.             autoVibVal = (((0 - (ch->eVibPos >> 1)) + 64) & 127) - 64;
  1560.  
  1561.         // sine
  1562.         else
  1563.             autoVibVal = vibSineTab[ch->eVibPos];
  1564.  
  1565.         autoVibVal <<= 2;
  1566.  
  1567.         tmp32 = ((autoVibVal * (int16_t)autoVibAmp) >> 16) & 0x8000FFFF;
  1568.         tmpPeriod = ch->outPeriod + (int16_t)tmp32;
  1569.         if (tmpPeriod > 32000-1)
  1570.             tmpPeriod = 0;
  1571.  
  1572.         ch->finalPeriod = tmpPeriod;
  1573.         ch->status |= IS_Period;
  1574.     }
  1575.     else
  1576.     {
  1577.         ch->finalPeriod = ch->outPeriod;
  1578.     }
  1579. }
  1580.  
  1581. static int16_t relocateTon(int16_t period, int8_t relativeNote, stmTyp *ch)
  1582. {
  1583.     int8_t fineTune;
  1584.     int32_t loPeriod, hiPeriod, tmpPeriod, tableIndex;
  1585.  
  1586.     fineTune = (ch->fineTune >> 3) + 16;
  1587.     hiPeriod = 8 * 12 * 16;
  1588.     loPeriod = 0;
  1589.  
  1590.     for (int8_t i = 0; i < 8; i++)
  1591.     {
  1592.         tmpPeriod = (((loPeriod + hiPeriod) >> 1) & 0xFFFFFFF0) + fineTune;
  1593.  
  1594.         tableIndex = tmpPeriod - 8;
  1595.         if (tableIndex < 0) // added security check
  1596.             tableIndex = 0;
  1597.  
  1598.         if (period >= note2Period[tableIndex])
  1599.             hiPeriod = tmpPeriod - fineTune;
  1600.         else
  1601.             loPeriod = tmpPeriod - fineTune;
  1602.     }
  1603.  
  1604.     tmpPeriod = loPeriod + fineTune + (relativeNote << 4);
  1605.     if (tmpPeriod < 0) // added security check
  1606.         tmpPeriod = 0;
  1607.  
  1608.     if (tmpPeriod >= ((8*12*16)+15)-1) // FT2 bug: off-by-one edge case
  1609.         tmpPeriod = (8*12*16)+15;
  1610.  
  1611.     return note2Period[tmpPeriod];
  1612. }
  1613.  
  1614. static void tonePorta(stmTyp *ch)
  1615. {
  1616.     if (ch->portaDir == 0)
  1617.         return;
  1618.  
  1619.     if (ch->portaDir > 1)
  1620.     {
  1621.         ch->realPeriod -= ch->portaSpeed;
  1622.         if (ch->realPeriod <= ch->wantPeriod)
  1623.         {
  1624.             ch->portaDir = 1;
  1625.             ch->realPeriod = ch->wantPeriod;
  1626.         }
  1627.     }
  1628.     else
  1629.     {
  1630.         ch->realPeriod += ch->portaSpeed;
  1631.         if (ch->realPeriod >= ch->wantPeriod)
  1632.         {
  1633.             ch->portaDir = 1;
  1634.             ch->realPeriod = ch->wantPeriod;
  1635.         }
  1636.     }
  1637.  
  1638.     if (ch->glissFunk) // semi-tone slide flag
  1639.         ch->outPeriod = relocateTon(ch->realPeriod, 0, ch);
  1640.     else
  1641.         ch->outPeriod = ch->realPeriod;
  1642.  
  1643.     ch->status |= IS_Period;
  1644. }
  1645.  
  1646. static void volume(stmTyp *ch) // actually volume slide
  1647. {
  1648.     uint8_t tmpEff = ch->eff;
  1649.     if (tmpEff == 0)
  1650.         tmpEff = ch->volSlideSpeed;
  1651.  
  1652.     ch->volSlideSpeed = tmpEff;
  1653.  
  1654.     if ((tmpEff & 0xF0) == 0)
  1655.     {
  1656.         // unsigned clamp
  1657.         if (ch->realVol >= tmpEff)
  1658.             ch->realVol -= tmpEff;
  1659.         else
  1660.             ch->realVol = 0;
  1661.     }
  1662.     else
  1663.     {
  1664.         // unsigned clamp
  1665.         if (ch->realVol <= 64-(tmpEff>>4))
  1666.             ch->realVol += tmpEff >> 4;
  1667.         else
  1668.             ch->realVol = 64;
  1669.     }
  1670.  
  1671.     ch->outVol = ch->realVol;
  1672.     ch->status |= IS_Vol;
  1673. }
  1674.  
  1675. static void vibrato2(stmTyp *ch)
  1676. {
  1677.     uint8_t tmpVib = (ch->vibPos / 4) & 0x1F;
  1678.  
  1679.     switch (ch->waveCtrl & 0x03)
  1680.     {
  1681.         // 0: sine
  1682.         case 0: tmpVib = vibTab[tmpVib]; break;
  1683.  
  1684.         // 1: ramp
  1685.         case 1:
  1686.         {
  1687.             tmpVib *= 8;
  1688.             if (ch->vibPos >= 128)
  1689.                 tmpVib ^= 0xFF;
  1690.         }
  1691.         break;
  1692.  
  1693.         // 2/3: square
  1694.         default: tmpVib = 255; break;
  1695.     }
  1696.  
  1697.     tmpVib = (tmpVib * ch->vibDepth) / 32;
  1698.  
  1699.     if (ch->vibPos >= 128)
  1700.         ch->outPeriod = ch->realPeriod - tmpVib;
  1701.     else
  1702.         ch->outPeriod = ch->realPeriod + tmpVib;
  1703.  
  1704.     ch->status |= IS_Period;
  1705.     ch->vibPos += ch->vibSpeed;
  1706. }
  1707.  
  1708. static void vibrato(stmTyp *ch)
  1709. {
  1710.     if (ch->eff > 0)
  1711.     {
  1712.         if ((ch->eff & 0x0F) > 0) ch->vibDepth = ch->eff & 0x0F;
  1713.         if ((ch->eff & 0xF0) > 0) ch->vibSpeed = (ch->eff >> 4) * 4;
  1714.     }
  1715.  
  1716.     vibrato2(ch);
  1717. }
  1718.  
  1719. static void doEffects(stmTyp *ch)
  1720. {
  1721.     int8_t note;
  1722.     uint8_t tmpEff, tremorData, tremorSign, tmpTrem;
  1723.     int16_t tremVol;
  1724.     uint16_t i, tick;
  1725.  
  1726.     // *** VOLUME COLUMN EFFECTS (TICKS >0) ***
  1727.  
  1728.     // volume slide down
  1729.     if ((ch->volKolVol & 0xF0) == 0x60)
  1730.     {
  1731.         // unsigned clamp
  1732.         if (ch->realVol >= (ch->volKolVol & 0x0F))
  1733.             ch->realVol -= ch->volKolVol & 0x0F;
  1734.         else
  1735.             ch->realVol = 0;
  1736.  
  1737.         ch->outVol = ch->realVol;
  1738.         ch->status |= IS_Vol;
  1739.     }
  1740.  
  1741.     // volume slide up
  1742.     else if ((ch->volKolVol & 0xF0) == 0x70)
  1743.     {
  1744.         // unsigned clamp
  1745.         if (ch->realVol <= 64-(ch->volKolVol & 0x0F))
  1746.             ch->realVol += ch->volKolVol & 0x0F;
  1747.         else
  1748.             ch->realVol = 64;
  1749.  
  1750.         ch->outVol = ch->realVol;
  1751.         ch->status |= IS_Vol;
  1752.     }
  1753.  
  1754.     // vibrato (+ set vibrato depth)
  1755.     else if ((ch->volKolVol & 0xF0) == 0xB0)
  1756.     {
  1757.         if (ch->volKolVol != 0xB0)
  1758.             ch->vibDepth = ch->volKolVol & 0x0F;
  1759.  
  1760.         vibrato2(ch);
  1761.     }
  1762.  
  1763.     // pan slide left
  1764.     else if ((ch->volKolVol & 0xF0) == 0xD0)
  1765.     {
  1766.         // unsigned clamp + a bug when the parameter is 0
  1767.         if ((ch->volKolVol & 0x0F) == 0 || ch->outPan < (ch->volKolVol & 0x0F))
  1768.             ch->outPan = 0;
  1769.         else
  1770.             ch->outPan -= ch->volKolVol & 0x0F;
  1771.  
  1772.         ch->status |= IS_Pan;
  1773.     }
  1774.  
  1775.     // pan slide right
  1776.     else if ((ch->volKolVol & 0xF0) == 0xE0)
  1777.     {
  1778.         // unsigned clamp
  1779.         if (ch->outPan <= 255-(ch->volKolVol & 0x0F))
  1780.             ch->outPan += ch->volKolVol & 0x0F;
  1781.         else
  1782.             ch->outPan = 255;
  1783.  
  1784.         ch->status |= IS_Pan;
  1785.     }
  1786.  
  1787.     // tone portamento
  1788.     else if ((ch->volKolVol & 0xF0) == 0xF0) tonePorta(ch);
  1789.  
  1790.     // *** MAIN EFFECTS (TICKS >0) ***
  1791.  
  1792.     if ((ch->eff == 0 && ch->effTyp == 0) || ch->effTyp >= 36) return; // no effect
  1793.  
  1794.     // 0xy - Arpeggio
  1795.     if (ch->effTyp == 0)
  1796.     {
  1797.         tick = song.timer;
  1798.  
  1799.         // FT2 'out of boundary LUT read' arp simulation
  1800.              if (tick  < 16) tick %= 3;
  1801.         else if (tick == 16) tick  = 0;
  1802.         else tick = 2;
  1803.  
  1804.         if (tick == 0)
  1805.         {
  1806.             ch->outPeriod = ch->realPeriod;
  1807.         }
  1808.         else
  1809.         {
  1810.             if (tick == 1)
  1811.                 note = ch->eff >> 4;
  1812.             else
  1813.                 note = ch->eff & 0xF; // tick 2
  1814.  
  1815.             ch->outPeriod = relocateTon(ch->realPeriod, note, ch);
  1816.         }
  1817.  
  1818.         ch->status |= IS_Period;
  1819.     }
  1820.  
  1821.     // 1xx - period slide up
  1822.     else if (ch->effTyp == 1)
  1823.     {
  1824.         tmpEff = ch->eff;
  1825.         if (tmpEff == 0)
  1826.             tmpEff = ch->portaUpSpeed;
  1827.  
  1828.         ch->portaUpSpeed = tmpEff;
  1829.  
  1830.         ch->realPeriod -= tmpEff * 4;
  1831.         if (ch->realPeriod < 1)
  1832.             ch->realPeriod = 1;
  1833.  
  1834.         ch->outPeriod = ch->realPeriod;
  1835.         ch->status |= IS_Period;
  1836.     }
  1837.  
  1838.     // 2xx - period slide down
  1839.     else if (ch->effTyp == 2)
  1840.     {
  1841.         tmpEff = ch->eff;
  1842.         if (tmpEff == 0)
  1843.             tmpEff = ch->portaDownSpeed;
  1844.  
  1845.         ch->portaDownSpeed = tmpEff;
  1846.  
  1847.         ch->realPeriod += tmpEff * 4;
  1848.         if (ch->realPeriod > 32000-1)
  1849.             ch->realPeriod = 32000-1;
  1850.  
  1851.         ch->outPeriod = ch->realPeriod;
  1852.         ch->status |= IS_Period;
  1853.     }
  1854.  
  1855.     // 3xx - tone portamento
  1856.     else if (ch->effTyp == 3) tonePorta(ch);
  1857.  
  1858.     // 4xy - vibrato
  1859.     else if (ch->effTyp == 4) vibrato(ch);
  1860.  
  1861.     // 5xy - tone portamento + volume slide
  1862.     else if (ch->effTyp == 5)
  1863.     {
  1864.         tonePorta(ch);
  1865.         volume(ch);
  1866.     }
  1867.  
  1868.     // 6xy - vibrato + volume slide
  1869.     else if (ch->effTyp == 6)
  1870.     {
  1871.         vibrato2(ch);
  1872.         volume(ch);
  1873.     }
  1874.  
  1875.     // 7xy - tremolo
  1876.     else if (ch->effTyp == 7)
  1877.     {
  1878.         tmpEff = ch->eff;
  1879.         if (tmpEff > 0)
  1880.         {
  1881.             if ((tmpEff & 0x0F) > 0) ch->tremDepth = tmpEff & 0x0F;
  1882.             if ((tmpEff & 0xF0) > 0) ch->tremSpeed = (tmpEff >> 4) * 4;
  1883.         }
  1884.  
  1885.         tmpTrem = (ch->tremPos / 4) & 0x1F;
  1886.         switch ((ch->waveCtrl >> 4) & 3)
  1887.         {
  1888.             // 0: sine
  1889.             case 0: tmpTrem = vibTab[tmpTrem]; break;
  1890.  
  1891.             // 1: ramp
  1892.             case 1:
  1893.             {
  1894.                 tmpTrem *= 8;
  1895.                 if (ch->vibPos >= 128) tmpTrem ^= 0xFF; // FT2 bug, should've been TremPos
  1896.             }
  1897.             break;
  1898.  
  1899.             // 2/3: square
  1900.             default: tmpTrem = 255; break;
  1901.         }
  1902.         tmpTrem = (tmpTrem * ch->tremDepth) / 64;
  1903.  
  1904.         if (ch->tremPos >= 128)
  1905.         {
  1906.             tremVol = ch->realVol - tmpTrem;
  1907.             if (tremVol < 0)
  1908.                 tremVol = 0;
  1909.         }
  1910.         else
  1911.         {
  1912.             tremVol = ch->realVol + tmpTrem;
  1913.             if (tremVol > 64)
  1914.                 tremVol = 64;
  1915.         }
  1916.  
  1917.         ch->outVol = tremVol & 0xFF;
  1918.         ch->tremPos += ch->tremSpeed;
  1919.         ch->status |= IS_Vol;
  1920.     }
  1921.  
  1922.     // Axy - volume slide
  1923.     else if (ch->effTyp == 10) volume(ch); // actually volume slide
  1924.  
  1925.     // Exy - E effects
  1926.     else if (ch->effTyp == 14)
  1927.     {
  1928.         // E9x - note retrigger
  1929.         if ((ch->eff & 0xF0) == 0x90)
  1930.         {
  1931.             if (ch->eff != 0x90) // E90 is handled in getNewNote()
  1932.             {
  1933.                 if ((song.tempo-song.timer) % (ch->eff & 0x0F) == 0)
  1934.                 {
  1935.                     startTone(0, 0, 0, ch);
  1936.                     retrigEnvelopeVibrato(ch);
  1937.                 }
  1938.             }
  1939.         }
  1940.  
  1941.         // ECx - note cut
  1942.         else if ((ch->eff & 0xF0) == 0xC0)
  1943.         {
  1944.             if (((song.tempo-song.timer) & 0xFF) == (ch->eff & 0x0F))
  1945.             {
  1946.                 ch->outVol = 0;
  1947.                 ch->realVol = 0;
  1948.                 ch->status |= (IS_Vol + IS_QuickVol);
  1949.             }
  1950.         }
  1951.  
  1952.         // EDx - note delay
  1953.         else if ((ch->eff & 0xF0) == 0xD0)
  1954.         {
  1955.             if (((song.tempo-song.timer) & 0xFF) == (ch->eff & 0x0F))
  1956.             {
  1957.                 startTone(ch->tonTyp & 0xFF, 0, 0, ch);
  1958.  
  1959.                 if ((ch->tonTyp & 0xFF00) > 0)
  1960.                     retrigVolume(ch);
  1961.  
  1962.                 retrigEnvelopeVibrato(ch);
  1963.  
  1964.                 if (ch->volKolVol >= 0x10 && ch->volKolVol <= 0x50)
  1965.                 {
  1966.                     ch->outVol = ch->volKolVol - 16;
  1967.                     ch->realVol = ch->outVol;
  1968.                 }
  1969.                 else if (ch->volKolVol >= 0xC0 && ch->volKolVol <= 0xCF)
  1970.                 {
  1971.                     ch->outPan = (ch->volKolVol & 0x0F) << 4;
  1972.                 }
  1973.             }
  1974.         }
  1975.     }
  1976.  
  1977.     // Hxy - global volume slide
  1978.     else if (ch->effTyp == 17)
  1979.     {
  1980.         tmpEff = ch->eff;
  1981.         if (tmpEff == 0)
  1982.             tmpEff = ch->globVolSlideSpeed;
  1983.  
  1984.         ch->globVolSlideSpeed = tmpEff;
  1985.  
  1986.         if ((tmpEff & 0xF0) == 0)
  1987.         {
  1988.             // unsigned clamp
  1989.             if (song.globVol >= tmpEff)
  1990.                 song.globVol -= tmpEff;
  1991.             else
  1992.                 song.globVol = 0;
  1993.         }
  1994.         else
  1995.         {
  1996.             // unsigned clamp
  1997.             if (song.globVol <= 64-(tmpEff>>4))
  1998.                 song.globVol += tmpEff >> 4;
  1999.             else
  2000.                 song.globVol = 64;
  2001.         }
  2002.  
  2003.         for (i = 0; i < song.antChn; i++) // update all voice volumes
  2004.             stm[i].status |= IS_Vol;
  2005.     }
  2006.  
  2007.     // Kxx - key off
  2008.     else if (ch->effTyp == 20)
  2009.     {
  2010.         if (((song.tempo-song.timer) & 31) == (ch->eff & 0x0F))
  2011.             keyOff(ch);
  2012.     }
  2013.  
  2014.     // Pxy - panning slide
  2015.     else if (ch->effTyp == 25)
  2016.     {
  2017.         tmpEff = ch->eff;
  2018.         if (tmpEff == 0)
  2019.             tmpEff = ch->panningSlideSpeed;
  2020.  
  2021.         ch->panningSlideSpeed = tmpEff;
  2022.  
  2023.         if ((tmpEff & 0xF0) == 0)
  2024.         {
  2025.             // unsigned clamp
  2026.             if (ch->outPan >= tmpEff)
  2027.                 ch->outPan -= tmpEff;
  2028.             else
  2029.                 ch->outPan = 0;
  2030.         }
  2031.         else
  2032.         {
  2033.             tmpEff >>= 4;
  2034.  
  2035.             // unsigned clamp
  2036.             if (ch->outPan <= 255-tmpEff)
  2037.                 ch->outPan += tmpEff;
  2038.             else
  2039.                 ch->outPan = 255;
  2040.         }
  2041.  
  2042.         ch->status |= IS_Pan;
  2043.     }
  2044.  
  2045.     // Rxy - multi note retrig
  2046.     else if (ch->effTyp == 27) multiRetrig(ch);
  2047.  
  2048.     // Txy - tremor
  2049.     else if (ch->effTyp == 29)
  2050.     {
  2051.         tmpEff = ch->eff;
  2052.         if (tmpEff == 0)
  2053.             tmpEff = ch->tremorSave;
  2054.  
  2055.         ch->tremorSave = tmpEff;
  2056.  
  2057.         tremorSign = ch->tremorPos & 0x80;
  2058.         tremorData = ch->tremorPos & 0x7F;
  2059.  
  2060.         tremorData--;
  2061.         if ((tremorData & 0x80) > 0)
  2062.         {
  2063.             if (tremorSign == 0x80)
  2064.             {
  2065.                 tremorSign = 0x00;
  2066.                 tremorData = tmpEff & 0x0F;
  2067.             }
  2068.             else
  2069.             {
  2070.                 tremorSign = 0x80;
  2071.                 tremorData = tmpEff >> 4;
  2072.             }
  2073.         }
  2074.  
  2075.         ch->tremorPos = tremorData | tremorSign;
  2076.  
  2077.         ch->outVol = tremorSign ? ch->realVol : 0;
  2078.         ch->status |= (IS_Vol + IS_QuickVol);
  2079.     }
  2080. }
  2081.  
  2082. static void voiceUpdateVolumes(uint8_t i, uint8_t status)
  2083. {
  2084.     int32_t volL, volR;
  2085.     voice_t *v, *f;
  2086.  
  2087.     v = &voice[i];
  2088.  
  2089.     volL = v->SVol * amp; // 0..2047 * 1..32 = 0..65504
  2090.  
  2091.     // (0..65504 * 0..65536) >> 4 = 0..268304384
  2092.     volR = ((uint32_t)volL * panningTab[v->SPan]) >> 4;
  2093.     volL = ((uint32_t)volL * panningTab[256 - v->SPan]) >> 4;
  2094.  
  2095.     if (!volumeRampingFlag)
  2096.     {
  2097.         v->SLVol2 = volL;
  2098.         v->SRVol2 = volR;
  2099.     }
  2100.     else
  2101.     {
  2102.         v->SLVol1 = volL;
  2103.         v->SRVol1 = volR;
  2104.  
  2105.         if (status & IS_NyTon)
  2106.         {
  2107.             // sample is about to start, ramp out/in at the same time
  2108.  
  2109.             // setup "fade out" voice (only if current voice volume>0)
  2110.             if (v->SLVol2 > 0 || v->SRVol2 > 0)
  2111.             {
  2112.                 f = &voice[MAX_VOICES + i];
  2113.                
  2114.                 *f = *v; // copy voice
  2115.  
  2116.                 f->SVolIPLen = quickVolSizeVal;
  2117.                 f->SLVolIP = -f->SLVol2 / f->SVolIPLen;
  2118.                 f->SRVolIP = -f->SRVol2 / f->SVolIPLen;
  2119.  
  2120.                 f->isFadeOutVoice = true;
  2121.             }
  2122.  
  2123.             // make current voice fade in when it starts
  2124.             v->SLVol2 = 0;
  2125.             v->SRVol2 = 0;
  2126.         }
  2127.  
  2128.         // ramp volume changes
  2129.  
  2130.         /* FT2 has two internal volume ramping lengths:
  2131.         ** IS_QuickVol: 5ms (audioFreq / 200)
  2132.         ** Normal: The duration of a tick (speedVal) */
  2133.  
  2134.         if (volL == v->SLVol2 && volR == v->SRVol2)
  2135.         {
  2136.             v->SVolIPLen = 0; // there is no volume change
  2137.         }
  2138.         else
  2139.         {
  2140.             v->SVolIPLen = (status & IS_QuickVol) ? quickVolSizeVal : speedVal;
  2141.             v->SLVolIP = (volL - v->SLVol2) / v->SVolIPLen;
  2142.             v->SRVolIP = (volR - v->SRVol2) / v->SVolIPLen;
  2143.         }
  2144.     }
  2145. }
  2146.  
  2147. static void mix_SaveIPVolumes(void) // for volume ramping
  2148. {
  2149.     voice_t *v;
  2150.  
  2151.     for (int32_t i = 0; i < song.antChn; i++)
  2152.     {
  2153.         v = &voice[i];
  2154.         v->SLVol2 = v->SLVol1;
  2155.         v->SRVol2 = v->SRVol1;
  2156.         v->SVolIPLen = 0;
  2157.     }
  2158. }
  2159.  
  2160. static void voiceTrigger(uint8_t i, sampleTyp *s, int32_t position)
  2161. {
  2162.     bool sampleIs16Bit;
  2163.     uint8_t loopType;
  2164.     int32_t oldSLen, length, loopBegin, loopLength;
  2165.     voice_t *v;
  2166.  
  2167.     v = &voice[i];
  2168.  
  2169.     length = s->len;
  2170.     loopBegin = s->repS;
  2171.     loopLength = s->repL;
  2172.     loopType = s->typ & 3;
  2173.     sampleIs16Bit = (s->typ >> 4) & 1;
  2174.  
  2175.     if (sampleIs16Bit)
  2176.     {
  2177.         length >>= 1;
  2178.         loopBegin >>= 1;
  2179.         loopLength >>= 1;
  2180.     }
  2181.  
  2182.     if (s->pek == NULL || length < 1)
  2183.     {
  2184.         v->mixRoutine = NULL; // shut down voice (illegal parameters)
  2185.         return;
  2186.     }
  2187.  
  2188.     if (loopLength < 1) // disable loop if loopLength is below 1
  2189.         loopType = 0;
  2190.  
  2191.     if (sampleIs16Bit)
  2192.     {
  2193.         v->SBase16 = (const int16_t *)s->pek;
  2194.         v->SRevBase16 = &v->SBase16[loopBegin + (loopBegin + loopLength)]; // for pingpong loops
  2195.     }
  2196.     else
  2197.     {
  2198.         v->SBase8 = s->pek;
  2199.         v->SRevBase8 = &v->SBase8[loopBegin + (loopBegin + loopLength)]; // for pingpong loops
  2200.     }
  2201.  
  2202.     v->backwards = false;
  2203.     v->SLen = (loopType > 0) ? (loopBegin + loopLength) : length;
  2204.     v->SRepS = loopBegin;
  2205.     v->SRepL = loopLength;
  2206.     v->SPos = position;
  2207.     v->SPosDec = 0; // position fraction
  2208.  
  2209.     // if 9xx position overflows, shut down voice
  2210.     oldSLen = (loopType > 0) ? (loopBegin + loopLength) : length;
  2211.     if (v->SPos >= oldSLen)
  2212.     {
  2213.         v->mixRoutine = NULL;
  2214.         return;
  2215.     }
  2216.  
  2217.     v->mixRoutine = mixRoutineTable[(sampleIs16Bit * 12) + (volumeRampingFlag * 6) + (interpolationFlag * 3) + loopType];
  2218. }
  2219.  
  2220. static void mix_UpdateChannelVolPanFrq(void)
  2221. {
  2222.     uint8_t status;
  2223.     uint16_t vol;
  2224.     stmTyp *ch;
  2225.     voice_t *v;
  2226.  
  2227.     for (uint8_t i = 0; i < song.antChn; i++)
  2228.     {
  2229.         ch = &stm[i];
  2230.         v  = &voice[i];
  2231.  
  2232.         status = ch->status;
  2233.         if (status != 0)
  2234.         {
  2235.             ch->status = 0;
  2236.  
  2237.             // volume change
  2238.             if (status & IS_Vol)
  2239.             {
  2240.                 vol = ch->finalVol;
  2241.                 if (vol > 0) // yes, FT2 does this! now it's 0..255 instead
  2242.                     vol--;
  2243.  
  2244.                 v->SVol = vol;
  2245.             }
  2246.  
  2247.             // panning change
  2248.             if (status & IS_Pan)
  2249.                 v->SPan = ch->finalPan;
  2250.  
  2251.             // update mixing volumes if vol/pan change
  2252.             if (status & (IS_Vol + IS_Pan))
  2253.                 voiceUpdateVolumes(i, status);
  2254.  
  2255.             // frequency change
  2256.             if (status & IS_Period)
  2257.             {
  2258.                 v->SFrq = getFrequenceValue(ch->finalPeriod);
  2259.  
  2260.                 if (v->SFrq != oldSFrq)
  2261.                 {
  2262.                     oldSFrq = v->SFrq;
  2263.  
  2264.                     oldSFrqRev = 0xFFFFFFFF;
  2265.                     if (oldSFrq != 0)
  2266.                         oldSFrqRev /= oldSFrq;
  2267.                 }
  2268.  
  2269.                 v->SFrqRev = oldSFrqRev;
  2270.             }
  2271.  
  2272.             // sample trigger (note)
  2273.             if (status & IS_NyTon)
  2274.                 voiceTrigger(i, ch->smpPtr, ch->smpStartPos);
  2275.         }
  2276.     }
  2277. }
  2278.  
  2279. /* ----------------------------------------------------------------------- */
  2280. /*                          GENERAL MIXER MACROS                           */
  2281. /* ----------------------------------------------------------------------- */
  2282.  
  2283. #define GET_VOL \
  2284.     CDA_LVol = v->SLVol2; \
  2285.     CDA_RVol = v->SRVol2; \
  2286.  
  2287. #define SET_VOL_BACK \
  2288.     v->SLVol2 = CDA_LVol; \
  2289.     v->SRVol2 = CDA_RVol; \
  2290.  
  2291. #define GET_DELTA delta = v->SFrq;
  2292.  
  2293. #define GET_MIXER_VARS \
  2294.     audioMixL = mixBufferL; \
  2295.     audioMixR = mixBufferR; \
  2296.     mixInMono = (CDA_LVol == CDA_RVol); \
  2297.     realPos = v->SPos; \
  2298.     pos = v->SPosDec; \
  2299.  
  2300. #define GET_MIXER_VARS_RAMP \
  2301.     audioMixL = mixBufferL; \
  2302.     audioMixR = mixBufferR; \
  2303.     CDA_LVolIP = v->SLVolIP; \
  2304.     CDA_RVolIP = v->SRVolIP; \
  2305.     mixInMono = (v->SLVol2 == v->SRVol2) && (CDA_LVolIP == CDA_RVolIP); \
  2306.     realPos = v->SPos; \
  2307.     pos = v->SPosDec; \
  2308.  
  2309. #define SET_BASE8 \
  2310.     CDA_LinearAdr = v->SBase8; \
  2311.     smpPtr = CDA_LinearAdr + realPos; \
  2312.  
  2313. #define SET_BASE16 \
  2314.     CDA_LinearAdr = v->SBase16; \
  2315.     smpPtr = CDA_LinearAdr + realPos; \
  2316.  
  2317. #define SET_BASE8_BIDI \
  2318.     CDA_LinearAdr = v->SBase8; \
  2319.     CDA_LinAdrRev = v->SRevBase8; \
  2320.  
  2321. #define SET_BASE16_BIDI \
  2322.     CDA_LinearAdr = v->SBase16; \
  2323.     CDA_LinAdrRev = v->SRevBase16; \
  2324.  
  2325. #define INC_POS \
  2326.     pos += delta; \
  2327.     smpPtr += pos >> 16; \
  2328.     pos &= 0xFFFF; \
  2329.  
  2330. #define INC_POS_BIDI \
  2331.     pos += CDA_IPValL; \
  2332.     smpPtr += pos >> 16; \
  2333.     smpPtr += CDA_IPValH; \
  2334.     pos &= 0xFFFF; \
  2335.  
  2336. #define SET_BACK_MIXER_POS \
  2337.     v->SPosDec = pos; \
  2338.     v->SPos = realPos; \
  2339.  
  2340. /* ----------------------------------------------------------------------- */
  2341. /*                          SAMPLE RENDERING MACROS                        */
  2342. /* ----------------------------------------------------------------------- */
  2343.  
  2344. #define VOLUME_RAMPING \
  2345.     CDA_LVol += CDA_LVolIP; \
  2346.     CDA_RVol += CDA_RVolIP; \
  2347.  
  2348. // all the 64-bit MULs here convert to fast logic on most 32-bit CPUs
  2349.  
  2350. #define RENDER_8BIT_SMP \
  2351.     sample = *smpPtr << 20; \
  2352.     *audioMixL++ += ((int64_t)sample * CDA_LVol) >> 32; \
  2353.     *audioMixR++ += ((int64_t)sample * CDA_RVol) >> 32; \
  2354.  
  2355. #define RENDER_8BIT_SMP_MONO \
  2356.     sample = *smpPtr << 20; \
  2357.     sample = ((int64_t)sample * CDA_LVol) >> 32; \
  2358.     *audioMixL++ += sample; \
  2359.     *audioMixR++ += sample; \
  2360.  
  2361. #define RENDER_16BIT_SMP \
  2362.     sample = *smpPtr << 12; \
  2363.     *audioMixL++ += ((int64_t)sample * CDA_LVol) >> 32; \
  2364.     *audioMixR++ += ((int64_t)sample * CDA_RVol) >> 32; \
  2365.  
  2366. #define RENDER_16BIT_SMP_MONO \
  2367.     sample = *smpPtr << 12; \
  2368.     sample = ((int64_t)sample * CDA_LVol) >> 32; \
  2369.     *audioMixL++ += sample; \
  2370.     *audioMixR++ += sample; \
  2371.  
  2372. // 3-tap quadratic interpolation (default - slower, but better quality)
  2373.  
  2374. // in: int32_t s1,s2,s3 = -128..127 | f = 0..65535 (frac) | out: s1 (will exceed 16-bits because of overshoot)
  2375. #define INTERPOLATE8(s1, s2, s3, f) \
  2376. { \
  2377.     int32_t s4, frac = f >> 1; \
  2378.     \
  2379.     s2 <<= 8; \
  2380.     s4 = ((s1 + s3) << (8 - 1)) - s2; \
  2381.     s4 = ((s4 * frac) >> 16) + s2; \
  2382.     s3 = (s1 + s3) << (8 - 1); \
  2383.     s1 <<= 8; \
  2384.     s3 = (s1 + s3) >> 1; \
  2385.     s1 += ((s4 - s3) * frac) >> 14; \
  2386. } \
  2387.  
  2388. // in: int32_t s1,s2,s3 = -32768..32767 | f = 0..65535 (frac) | out: s1 (will exceed 16-bits because of overshoot)
  2389. #define INTERPOLATE16(s1, s2, s3, f) \
  2390. { \
  2391.     int32_t s4, frac = f >> 1; \
  2392.     \
  2393.     s4 = ((s1 + s3) >> 1) - s2; \
  2394.     s4 = ((s4 * frac) >> 16) + s2; \
  2395.     s3 = (s1 + s3) >> 1; \
  2396.     s3 = (s1 + s3) >> 1; \
  2397.     s1 += ((s4 - s3) * frac) >> 14; \
  2398. } \
  2399.  
  2400. #define RENDER_8BIT_SMP_INTRP \
  2401.     sample = smpPtr[0]; \
  2402.     sample2 = smpPtr[1]; \
  2403.     sample3 = smpPtr[2]; \
  2404.     INTERPOLATE8(sample, sample2, sample3, pos) \
  2405.     sample <<= 12; \
  2406.     *audioMixL++ += ((int64_t)sample * CDA_LVol) >> 32; \
  2407.     *audioMixR++ += ((int64_t)sample * CDA_RVol) >> 32; \
  2408.  
  2409. #define RENDER_8BIT_SMP_MONO_INTRP \
  2410.     sample = smpPtr[0]; \
  2411.     sample2 = smpPtr[1]; \
  2412.     sample3 = smpPtr[2]; \
  2413.     INTERPOLATE8(sample, sample2, sample3, pos) \
  2414.     sample <<= 12; \
  2415.     sample = ((int64_t)sample * CDA_LVol) >> 32; \
  2416.     *audioMixL++ += sample; \
  2417.     *audioMixR++ += sample; \
  2418.  
  2419. #define RENDER_16BIT_SMP_INTRP \
  2420.     sample = smpPtr[0]; \
  2421.     sample2 = smpPtr[1]; \
  2422.     sample3 = smpPtr[2]; \
  2423.     INTERPOLATE16(sample, sample2, sample3, pos) \
  2424.     sample <<= 12; \
  2425.     *audioMixL++ += ((int64_t)sample * CDA_LVol) >> 32; \
  2426.     *audioMixR++ += ((int64_t)sample * CDA_RVol) >> 32; \
  2427.  
  2428. #define RENDER_16BIT_SMP_MONO_INTRP \
  2429.     sample = smpPtr[0]; \
  2430.     sample2 = smpPtr[1]; \
  2431.     sample3 = smpPtr[2]; \
  2432.     INTERPOLATE16(sample, sample2, sample3, pos) \
  2433.     sample <<= 12; \
  2434.     sample = ((int64_t)sample * CDA_LVol) >> 32; \
  2435.     *audioMixL++ += sample; \
  2436.     *audioMixR++ += sample; \
  2437.  
  2438. /* ----------------------------------------------------------------------- */
  2439. /*                      SAMPLES-TO-MIX LIMITING MACROS                     */
  2440. /* ----------------------------------------------------------------------- */
  2441.  
  2442. #define LIMIT_MIX_NUM \
  2443.     i = (v->SLen - 1) - realPos; \
  2444.     if (i > 65535) \
  2445.         i = 65535; \
  2446.     \
  2447.     samplesToMix = (((((uint64_t)i << 16) | (pos ^ 0xFFFF)) * v->SFrqRev) >> 32) + 1; \
  2448.     if (samplesToMix > (uint32_t)CDA_BytesLeft) \
  2449.         samplesToMix = CDA_BytesLeft; \
  2450.  
  2451. #define LIMIT_MIX_NUM_RAMP \
  2452.     if (v->SVolIPLen == 0) \
  2453.     { \
  2454.         CDA_LVolIP = 0; \
  2455.         CDA_RVolIP = 0; \
  2456.         \
  2457.         if (v->isFadeOutVoice) \
  2458.         { \
  2459.             v->mixRoutine = NULL; /* fade out voice is done, shut it down */ \
  2460.             return; \
  2461.         } \
  2462.     } \
  2463.     else \
  2464.     { \
  2465.         if (samplesToMix > (uint32_t)v->SVolIPLen) \
  2466.             samplesToMix = v->SVolIPLen; \
  2467.         \
  2468.         v->SVolIPLen -= samplesToMix; \
  2469.     } \
  2470.  
  2471. #define START_BIDI \
  2472.     if (v->backwards) \
  2473.     { \
  2474.         delta = 0 - v->SFrq; \
  2475.         CDA_IPValH = (int32_t)delta >> 16; \
  2476.         realPos = ~realPos; \
  2477.         smpPtr = CDA_LinAdrRev + realPos; \
  2478.         pos ^= 0xFFFF; \
  2479.     } \
  2480.     else \
  2481.     { \
  2482.         delta = v->SFrq; \
  2483.         CDA_IPValH = delta >> 16; \
  2484.         smpPtr = CDA_LinearAdr + realPos; \
  2485.     } \
  2486.     \
  2487.     CDA_IPValL = delta & 0xFFFF; \
  2488.  
  2489. #define END_BIDI \
  2490.     if (v->backwards) \
  2491.     { \
  2492.         pos ^= 0xFFFF; \
  2493.         realPos = (int32_t)(smpPtr - CDA_LinAdrRev); \
  2494.         realPos = ~realPos; \
  2495.     } \
  2496.     else \
  2497.     { \
  2498.         realPos = (int32_t)(smpPtr - CDA_LinearAdr); \
  2499.     } \
  2500.     \
  2501.  
  2502. /* ----------------------------------------------------------------------- */
  2503. /*                     SAMPLE END/LOOP WRAPPING MACROS                     */
  2504. /* ----------------------------------------------------------------------- */
  2505.  
  2506. #define HANDLE_SAMPLE_END \
  2507.     realPos = (int32_t)(smpPtr - CDA_LinearAdr); \
  2508.     if (realPos >= v->SLen) \
  2509.     { \
  2510.         v->mixRoutine = NULL; \
  2511.         return; \
  2512.     } \
  2513.  
  2514. #define WRAP_LOOP \
  2515.     realPos = (int32_t)(smpPtr - CDA_LinearAdr); \
  2516.     while (realPos >= v->SLen) \
  2517.         realPos -= v->SRepL; \
  2518.     smpPtr = CDA_LinearAdr + realPos; \
  2519.  
  2520. #define WRAP_BIDI_LOOP \
  2521.     while (realPos >= v->SLen) \
  2522.     { \
  2523.         realPos -= v->SRepL; \
  2524.         v->backwards ^= 1; \
  2525.     } \
  2526.  
  2527. /* ----------------------------------------------------------------------- */
  2528. /*                       VOLUME=0 OPTIMIZATION MACROS                      */
  2529. /* ----------------------------------------------------------------------- */
  2530.  
  2531. #define VOL0_OPTIMIZATION_NO_LOOP \
  2532.     pos = v->SPosDec + ((v->SFrq & 0xFFFF) * numSamples); \
  2533.     realPos = v->SPos + ((v->SFrq >> 16) * numSamples) + (pos >> 16); \
  2534.     \
  2535.     if (realPos >= v->SLen) \
  2536.     { \
  2537.         v->mixRoutine = NULL; /* shut down voice */ \
  2538.         return; \
  2539.     } \
  2540.     \
  2541.     pos &= 0xFFFF; \
  2542.     SET_BACK_MIXER_POS
  2543.  
  2544. #define VOL0_OPTIMIZATION_LOOP \
  2545.     pos  = v->SPosDec + ((v->SFrq & 0xFFFF) * numSamples); \
  2546.     realPos = v->SPos + ((v->SFrq >> 16) * numSamples) + (pos >> 16); \
  2547.     \
  2548.     while (realPos >= v->SLen) \
  2549.         realPos -= v->SRepL; \
  2550.     \
  2551.     pos &= 0xFFFF; \
  2552.     SET_BACK_MIXER_POS
  2553.  
  2554. #define VOL0_OPTIMIZATION_BIDI_LOOP \
  2555.     pos = v->SPosDec + ((v->SFrq & 0xFFFF) * numSamples); \
  2556.     realPos = v->SPos + ((v->SFrq >> 16) * numSamples) + (pos >> 16); \
  2557.     \
  2558.     while (realPos >= v->SLen) \
  2559.     { \
  2560.         realPos -= v->SRepL; \
  2561.         v->backwards ^= 1; \
  2562.     } \
  2563.     \
  2564.     pos &= 0xFFFF; \
  2565.     SET_BACK_MIXER_POS
  2566.  
  2567. /* ----------------------------------------------------------------------- */
  2568. /*                          8-BIT MIXING ROUTINES                          */
  2569. /* ----------------------------------------------------------------------- */
  2570.  
  2571. static void mix8bNoLoop(voice_t *v, uint32_t numSamples)
  2572. {
  2573.     const int8_t *CDA_LinearAdr;
  2574.     bool mixInMono;
  2575.     int32_t realPos, sample, *audioMixL, *audioMixR, CDA_BytesLeft;
  2576.     register const int8_t *smpPtr;
  2577.     register int32_t CDA_LVol, CDA_RVol;
  2578.     register uint32_t pos, delta;
  2579.     uint32_t i, samplesToMix;
  2580.  
  2581.     GET_VOL
  2582.  
  2583.     if ((CDA_LVol | CDA_RVol) == 0)
  2584.     {
  2585.         VOL0_OPTIMIZATION_NO_LOOP
  2586.         return;
  2587.     }
  2588.  
  2589.     GET_MIXER_VARS
  2590.     GET_DELTA
  2591.     SET_BASE8
  2592.  
  2593.     CDA_BytesLeft = numSamples;
  2594.     while (CDA_BytesLeft > 0)
  2595.     {
  2596.         LIMIT_MIX_NUM
  2597.         CDA_BytesLeft -= samplesToMix;
  2598.  
  2599.         if (mixInMono)
  2600.         {
  2601.             if (samplesToMix & 1)
  2602.             {
  2603.                 RENDER_8BIT_SMP_MONO
  2604.                 INC_POS
  2605.             }
  2606.             samplesToMix >>= 1;
  2607.             for (i = 0; i < samplesToMix; i++)
  2608.             {
  2609.                 RENDER_8BIT_SMP_MONO
  2610.                 INC_POS
  2611.                 RENDER_8BIT_SMP_MONO
  2612.                 INC_POS
  2613.             }
  2614.         }
  2615.         else
  2616.         {
  2617.             if (samplesToMix & 1)
  2618.             {
  2619.                 RENDER_8BIT_SMP
  2620.                 INC_POS
  2621.             }
  2622.             samplesToMix >>= 1;
  2623.             for (i = 0; i < samplesToMix; i++)
  2624.             {
  2625.                 RENDER_8BIT_SMP
  2626.                 INC_POS
  2627.                 RENDER_8BIT_SMP
  2628.                 INC_POS
  2629.             }
  2630.         }
  2631.  
  2632.         HANDLE_SAMPLE_END
  2633.     }
  2634.  
  2635.     SET_BACK_MIXER_POS
  2636. }
  2637.  
  2638. static void mix8bLoop(voice_t *v, uint32_t numSamples)
  2639. {
  2640.     const int8_t *CDA_LinearAdr;
  2641.     bool mixInMono;
  2642.     int32_t realPos, sample, *audioMixL, *audioMixR, CDA_BytesLeft;
  2643.     register const int8_t *smpPtr;
  2644.     register int32_t CDA_LVol, CDA_RVol;
  2645.     register uint32_t pos, delta;
  2646.     uint32_t i, samplesToMix;
  2647.  
  2648.     GET_VOL
  2649.  
  2650.     if ((CDA_LVol | CDA_RVol) == 0)
  2651.     {
  2652.         VOL0_OPTIMIZATION_LOOP
  2653.         return;
  2654.     }
  2655.  
  2656.     GET_MIXER_VARS
  2657.     GET_DELTA
  2658.     SET_BASE8
  2659.  
  2660.     CDA_BytesLeft = numSamples;
  2661.     while (CDA_BytesLeft > 0)
  2662.     {
  2663.         LIMIT_MIX_NUM
  2664.         CDA_BytesLeft -= samplesToMix;
  2665.  
  2666.         if (mixInMono)
  2667.         {
  2668.             if (samplesToMix & 1)
  2669.             {
  2670.                 RENDER_8BIT_SMP_MONO
  2671.                 INC_POS
  2672.             }
  2673.             samplesToMix >>= 1;
  2674.             for (i = 0; i < samplesToMix; i++)
  2675.             {
  2676.                 RENDER_8BIT_SMP_MONO
  2677.                 INC_POS
  2678.                 RENDER_8BIT_SMP_MONO
  2679.                 INC_POS
  2680.             }
  2681.         }
  2682.         else
  2683.         {
  2684.             if (samplesToMix & 1)
  2685.             {
  2686.                 RENDER_8BIT_SMP
  2687.                 INC_POS
  2688.             }
  2689.             samplesToMix >>= 1;
  2690.             for (i = 0; i < samplesToMix; i++)
  2691.             {
  2692.                 RENDER_8BIT_SMP
  2693.                 INC_POS
  2694.                 RENDER_8BIT_SMP
  2695.                 INC_POS
  2696.             }
  2697.         }
  2698.  
  2699.         WRAP_LOOP
  2700.     }
  2701.  
  2702.     SET_BACK_MIXER_POS
  2703. }
  2704.  
  2705. static void mix8bBidiLoop(voice_t *v, uint32_t numSamples)
  2706. {
  2707.     bool mixInMono;
  2708.     const int8_t *CDA_LinearAdr, *CDA_LinAdrRev;
  2709.     int32_t realPos, sample, *audioMixL, *audioMixR, CDA_BytesLeft;
  2710.     register const int8_t *smpPtr;
  2711.     register int32_t CDA_LVol, CDA_RVol, CDA_IPValL, CDA_IPValH;
  2712.     register uint32_t pos;
  2713.     uint32_t delta, i, samplesToMix;
  2714.  
  2715.     GET_VOL
  2716.  
  2717.     if ((CDA_LVol | CDA_RVol) == 0)
  2718.     {
  2719.         VOL0_OPTIMIZATION_BIDI_LOOP
  2720.         return;
  2721.     }
  2722.  
  2723.     GET_MIXER_VARS
  2724.     SET_BASE8_BIDI
  2725.  
  2726.     CDA_BytesLeft = numSamples;
  2727.     while (CDA_BytesLeft > 0)
  2728.     {
  2729.         LIMIT_MIX_NUM
  2730.         CDA_BytesLeft -= samplesToMix;
  2731.  
  2732.         START_BIDI
  2733.         if (mixInMono)
  2734.         {
  2735.             if (samplesToMix & 1)
  2736.             {
  2737.                 RENDER_8BIT_SMP_MONO
  2738.                 INC_POS_BIDI
  2739.             }
  2740.             samplesToMix >>= 1;
  2741.             for (i = 0; i < samplesToMix; i++)
  2742.             {
  2743.                 RENDER_8BIT_SMP_MONO
  2744.                 INC_POS_BIDI
  2745.                 RENDER_8BIT_SMP_MONO
  2746.                 INC_POS_BIDI
  2747.             }
  2748.         }
  2749.         else
  2750.         {
  2751.             if (samplesToMix & 1)
  2752.             {
  2753.                 RENDER_8BIT_SMP
  2754.                 INC_POS_BIDI
  2755.             }
  2756.             samplesToMix >>= 1;
  2757.             for (i = 0; i < samplesToMix; i++)
  2758.             {
  2759.                 RENDER_8BIT_SMP
  2760.                 INC_POS_BIDI
  2761.                 RENDER_8BIT_SMP
  2762.                 INC_POS_BIDI
  2763.             }
  2764.         }
  2765.         END_BIDI
  2766.  
  2767.         WRAP_BIDI_LOOP
  2768.     }
  2769.     SET_BACK_MIXER_POS
  2770. }
  2771.  
  2772. static void mix8bNoLoopIntrp(voice_t *v, uint32_t numSamples)
  2773. {
  2774.     const int8_t *CDA_LinearAdr;
  2775.     bool mixInMono;
  2776.     int32_t realPos, sample, sample2, sample3, *audioMixL, *audioMixR, CDA_BytesLeft;
  2777.     register const int8_t *smpPtr;
  2778.     register int32_t CDA_LVol, CDA_RVol;
  2779.     register uint32_t pos, delta;
  2780.     uint32_t i, samplesToMix;
  2781.  
  2782.     GET_VOL
  2783.  
  2784.     if ((CDA_LVol | CDA_RVol) == 0)
  2785.     {
  2786.         VOL0_OPTIMIZATION_NO_LOOP
  2787.         return;
  2788.     }
  2789.  
  2790.     GET_MIXER_VARS
  2791.     GET_DELTA
  2792.     SET_BASE8
  2793.  
  2794.     CDA_BytesLeft = numSamples;
  2795.     while (CDA_BytesLeft > 0)
  2796.     {
  2797.         LIMIT_MIX_NUM
  2798.         CDA_BytesLeft -= samplesToMix;
  2799.  
  2800.         if (mixInMono)
  2801.         {
  2802.             if (samplesToMix & 1)
  2803.             {
  2804.                 RENDER_8BIT_SMP_MONO_INTRP
  2805.                 INC_POS
  2806.             }
  2807.             samplesToMix >>= 1;
  2808.             for (i = 0; i < samplesToMix; i++)
  2809.             {
  2810.                 RENDER_8BIT_SMP_MONO_INTRP
  2811.                 INC_POS
  2812.                 RENDER_8BIT_SMP_MONO_INTRP
  2813.                 INC_POS
  2814.             }
  2815.         }
  2816.         else
  2817.         {
  2818.             if (samplesToMix & 1)
  2819.             {
  2820.                 RENDER_8BIT_SMP_INTRP
  2821.                 INC_POS
  2822.             }
  2823.             samplesToMix >>= 1;
  2824.             for (i = 0; i < samplesToMix; i++)
  2825.             {
  2826.                 RENDER_8BIT_SMP_INTRP
  2827.                 INC_POS
  2828.                 RENDER_8BIT_SMP_INTRP
  2829.                 INC_POS
  2830.             }
  2831.         }
  2832.  
  2833.         HANDLE_SAMPLE_END
  2834.     }
  2835.  
  2836.     SET_BACK_MIXER_POS
  2837. }
  2838.  
  2839. static void mix8bLoopIntrp(voice_t *v, uint32_t numSamples)
  2840. {
  2841.     const int8_t *CDA_LinearAdr;
  2842.     bool mixInMono;
  2843.     int32_t realPos, sample, sample2, sample3, *audioMixL, *audioMixR, CDA_BytesLeft;
  2844.     register const int8_t *smpPtr;
  2845.     register int32_t CDA_LVol, CDA_RVol;
  2846.     register uint32_t pos, delta;
  2847.     uint32_t i, samplesToMix;
  2848.  
  2849.     GET_VOL
  2850.  
  2851.     if ((CDA_LVol | CDA_RVol) == 0)
  2852.     {
  2853.         VOL0_OPTIMIZATION_LOOP
  2854.         return;
  2855.     }
  2856.  
  2857.     GET_MIXER_VARS
  2858.     GET_DELTA
  2859.     SET_BASE8
  2860.  
  2861.     CDA_BytesLeft = numSamples;
  2862.     while (CDA_BytesLeft > 0)
  2863.     {
  2864.         LIMIT_MIX_NUM
  2865.         CDA_BytesLeft -= samplesToMix;
  2866.  
  2867.         if (mixInMono)
  2868.         {
  2869.             if (samplesToMix & 1)
  2870.             {
  2871.                 RENDER_8BIT_SMP_MONO_INTRP
  2872.                 INC_POS
  2873.             }
  2874.             samplesToMix >>= 1;
  2875.             for (i = 0; i < samplesToMix; i++)
  2876.             {
  2877.                 RENDER_8BIT_SMP_MONO_INTRP
  2878.                 INC_POS
  2879.                 RENDER_8BIT_SMP_MONO_INTRP
  2880.                 INC_POS
  2881.             }
  2882.         }
  2883.         else
  2884.         {
  2885.             if (samplesToMix & 1)
  2886.             {
  2887.                 RENDER_8BIT_SMP_INTRP
  2888.                 INC_POS
  2889.             }
  2890.             samplesToMix >>= 1;
  2891.             for (i = 0; i < samplesToMix; i++)
  2892.             {
  2893.                 RENDER_8BIT_SMP_INTRP
  2894.                 INC_POS
  2895.                 RENDER_8BIT_SMP_INTRP
  2896.                 INC_POS
  2897.             }
  2898.         }
  2899.  
  2900.         WRAP_LOOP
  2901.     }
  2902.  
  2903.     SET_BACK_MIXER_POS
  2904. }
  2905.  
  2906. static void mix8bBidiLoopIntrp(voice_t *v, uint32_t numSamples)
  2907. {
  2908.     bool mixInMono;
  2909.     const int8_t *CDA_LinearAdr, *CDA_LinAdrRev;
  2910.     int32_t realPos, sample, sample2, sample3, *audioMixL, *audioMixR, CDA_BytesLeft;
  2911.     register const int8_t *smpPtr;
  2912.     register int32_t CDA_LVol, CDA_RVol, CDA_IPValL, CDA_IPValH;
  2913.     register uint32_t pos;
  2914.     uint32_t delta, i, samplesToMix;
  2915.  
  2916.     GET_VOL
  2917.  
  2918.     if ((CDA_LVol | CDA_RVol) == 0)
  2919.     {
  2920.         VOL0_OPTIMIZATION_BIDI_LOOP
  2921.         return;
  2922.     }
  2923.  
  2924.     GET_MIXER_VARS
  2925.     SET_BASE8_BIDI
  2926.  
  2927.     CDA_BytesLeft = numSamples;
  2928.     while (CDA_BytesLeft > 0)
  2929.     {
  2930.         LIMIT_MIX_NUM
  2931.         CDA_BytesLeft -= samplesToMix;
  2932.  
  2933.         START_BIDI
  2934.         if (mixInMono)
  2935.         {
  2936.             if (samplesToMix & 1)
  2937.             {
  2938.                 RENDER_8BIT_SMP_MONO_INTRP
  2939.                 INC_POS_BIDI
  2940.             }
  2941.             samplesToMix >>= 1;
  2942.             for (i = 0; i < samplesToMix; i++)
  2943.             {
  2944.                 RENDER_8BIT_SMP_MONO_INTRP
  2945.                 INC_POS_BIDI
  2946.                 RENDER_8BIT_SMP_MONO_INTRP
  2947.                 INC_POS_BIDI
  2948.             }
  2949.         }
  2950.         else
  2951.         {
  2952.             if (samplesToMix & 1)
  2953.             {
  2954.                 RENDER_8BIT_SMP_INTRP
  2955.                 INC_POS_BIDI
  2956.             }
  2957.             samplesToMix >>= 1;
  2958.             for (i = 0; i < samplesToMix; i++)
  2959.             {
  2960.                 RENDER_8BIT_SMP_INTRP
  2961.                 INC_POS_BIDI
  2962.                 RENDER_8BIT_SMP_INTRP
  2963.                 INC_POS_BIDI
  2964.             }
  2965.         }
  2966.         END_BIDI
  2967.  
  2968.         WRAP_BIDI_LOOP
  2969.     }
  2970.  
  2971.     SET_BACK_MIXER_POS
  2972. }
  2973.  
  2974. static void mix8bRampNoLoop(voice_t *v, uint32_t numSamples)
  2975. {
  2976.     const int8_t *CDA_LinearAdr;
  2977.     bool mixInMono;
  2978.     int32_t realPos, sample, *audioMixL, *audioMixR, CDA_BytesLeft, CDA_LVolIP, CDA_RVolIP;
  2979.     register const int8_t *smpPtr;
  2980.     register int32_t CDA_LVol, CDA_RVol;
  2981.     register uint32_t pos, delta;
  2982.     uint32_t i, samplesToMix;
  2983.  
  2984.     if ((v->SLVol1 | v->SRVol1 | v->SLVol2 | v->SRVol2) == 0)
  2985.     {
  2986.         VOL0_OPTIMIZATION_NO_LOOP
  2987.         return;
  2988.     }
  2989.  
  2990.     GET_MIXER_VARS_RAMP
  2991.     GET_DELTA
  2992.     SET_BASE8
  2993.  
  2994.     CDA_BytesLeft = numSamples;
  2995.     while (CDA_BytesLeft > 0)
  2996.     {
  2997.         LIMIT_MIX_NUM
  2998.         LIMIT_MIX_NUM_RAMP
  2999.         CDA_BytesLeft -= samplesToMix;
  3000.  
  3001.         GET_VOL
  3002.         if (mixInMono)
  3003.         {
  3004.             if (samplesToMix & 1)
  3005.             {
  3006.                 RENDER_8BIT_SMP_MONO
  3007.                 VOLUME_RAMPING
  3008.                 INC_POS
  3009.             }
  3010.             samplesToMix >>= 1;
  3011.             for (i = 0; i < samplesToMix; i++)
  3012.             {
  3013.                 RENDER_8BIT_SMP_MONO
  3014.                 VOLUME_RAMPING
  3015.                 INC_POS
  3016.                 RENDER_8BIT_SMP_MONO
  3017.                 VOLUME_RAMPING
  3018.                 INC_POS
  3019.             }
  3020.         }
  3021.         else
  3022.         {
  3023.             if (samplesToMix & 1)
  3024.             {
  3025.                 RENDER_8BIT_SMP
  3026.                 VOLUME_RAMPING
  3027.                 INC_POS
  3028.             }
  3029.             samplesToMix >>= 1;
  3030.             for (i = 0; i < samplesToMix; i++)
  3031.             {
  3032.                 RENDER_8BIT_SMP
  3033.                 VOLUME_RAMPING
  3034.                 INC_POS
  3035.                 RENDER_8BIT_SMP
  3036.                 VOLUME_RAMPING
  3037.                 INC_POS
  3038.             }
  3039.         }
  3040.         SET_VOL_BACK
  3041.  
  3042.         HANDLE_SAMPLE_END
  3043.     }
  3044.  
  3045.     SET_BACK_MIXER_POS
  3046. }
  3047.  
  3048. static void mix8bRampLoop(voice_t *v, uint32_t numSamples)
  3049. {
  3050.     const int8_t *CDA_LinearAdr;
  3051.     bool mixInMono;
  3052.     int32_t realPos, sample, *audioMixL, *audioMixR, CDA_BytesLeft, CDA_LVolIP, CDA_RVolIP;
  3053.     register const int8_t *smpPtr;
  3054.     register int32_t CDA_LVol, CDA_RVol;
  3055.     register uint32_t pos, delta;
  3056.     uint32_t i, samplesToMix;
  3057.  
  3058.     if ((v->SLVol1 | v->SRVol1 | v->SLVol2 | v->SRVol2) == 0)
  3059.     {
  3060.         VOL0_OPTIMIZATION_LOOP
  3061.         return;
  3062.     }
  3063.  
  3064.     GET_MIXER_VARS_RAMP
  3065.     GET_DELTA
  3066.     SET_BASE8
  3067.  
  3068.     CDA_BytesLeft = numSamples;
  3069.     while (CDA_BytesLeft > 0)
  3070.     {
  3071.         LIMIT_MIX_NUM
  3072.         LIMIT_MIX_NUM_RAMP
  3073.         CDA_BytesLeft -= samplesToMix;
  3074.  
  3075.         GET_VOL
  3076.         if (mixInMono)
  3077.         {
  3078.             if (samplesToMix & 1)
  3079.             {
  3080.                 RENDER_8BIT_SMP
  3081.                 VOLUME_RAMPING
  3082.                 INC_POS
  3083.             }
  3084.             samplesToMix >>= 1;
  3085.             for (i = 0; i < samplesToMix; i++)
  3086.             {
  3087.                 RENDER_8BIT_SMP_MONO
  3088.                 VOLUME_RAMPING
  3089.                 INC_POS
  3090.                 RENDER_8BIT_SMP_MONO
  3091.                 VOLUME_RAMPING
  3092.                 INC_POS
  3093.             }
  3094.         }
  3095.         else
  3096.         {
  3097.             if (samplesToMix & 1)
  3098.             {
  3099.                 RENDER_8BIT_SMP
  3100.                 VOLUME_RAMPING
  3101.                 INC_POS
  3102.             }
  3103.             samplesToMix >>= 1;
  3104.             for (i = 0; i < samplesToMix; i++)
  3105.             {
  3106.                 RENDER_8BIT_SMP
  3107.                 VOLUME_RAMPING
  3108.                 INC_POS
  3109.                 RENDER_8BIT_SMP
  3110.                 VOLUME_RAMPING
  3111.                 INC_POS
  3112.             }
  3113.         }
  3114.         SET_VOL_BACK
  3115.  
  3116.         WRAP_LOOP
  3117.     }
  3118.  
  3119.     SET_BACK_MIXER_POS
  3120. }
  3121.  
  3122. static void mix8bRampBidiLoop(voice_t *v, uint32_t numSamples)
  3123. {
  3124.     bool mixInMono;
  3125.     const int8_t *CDA_LinearAdr, *CDA_LinAdrRev;
  3126.     int32_t realPos, sample, *audioMixL, *audioMixR, CDA_BytesLeft, CDA_LVolIP, CDA_RVolIP;
  3127.     register const int8_t *smpPtr;
  3128.     register int32_t CDA_LVol, CDA_RVol, CDA_IPValL, CDA_IPValH;
  3129.     register uint32_t pos;
  3130.     uint32_t delta, i, samplesToMix;
  3131.  
  3132.     if ((v->SLVol1 | v->SRVol1 | v->SLVol2 | v->SRVol2) == 0)
  3133.     {
  3134.         VOL0_OPTIMIZATION_BIDI_LOOP
  3135.         return;
  3136.     }
  3137.  
  3138.     GET_MIXER_VARS_RAMP
  3139.     SET_BASE8_BIDI
  3140.  
  3141.     CDA_BytesLeft = numSamples;
  3142.     while (CDA_BytesLeft > 0)
  3143.     {
  3144.         LIMIT_MIX_NUM
  3145.         LIMIT_MIX_NUM_RAMP
  3146.         CDA_BytesLeft -= samplesToMix;
  3147.  
  3148.         GET_VOL
  3149.         START_BIDI
  3150.         if (mixInMono)
  3151.         {
  3152.             if (samplesToMix & 1)
  3153.             {
  3154.                 RENDER_8BIT_SMP_MONO
  3155.                 VOLUME_RAMPING
  3156.                 INC_POS_BIDI
  3157.             }
  3158.             samplesToMix >>= 1;
  3159.             for (i = 0; i < samplesToMix; i++)
  3160.             {
  3161.                 RENDER_8BIT_SMP_MONO
  3162.                 VOLUME_RAMPING
  3163.                 INC_POS_BIDI
  3164.                 RENDER_8BIT_SMP_MONO
  3165.                 VOLUME_RAMPING
  3166.                 INC_POS_BIDI
  3167.             }
  3168.         }
  3169.         else
  3170.         {
  3171.             if (samplesToMix & 1)
  3172.             {
  3173.                 RENDER_8BIT_SMP
  3174.                 VOLUME_RAMPING
  3175.                 INC_POS_BIDI
  3176.             }
  3177.             samplesToMix >>= 1;
  3178.             for (i = 0; i < samplesToMix; i++)
  3179.             {
  3180.                 RENDER_8BIT_SMP
  3181.                 VOLUME_RAMPING
  3182.                 INC_POS_BIDI
  3183.                 RENDER_8BIT_SMP
  3184.                 VOLUME_RAMPING
  3185.                 INC_POS_BIDI
  3186.             }
  3187.         }
  3188.         END_BIDI
  3189.         SET_VOL_BACK
  3190.  
  3191.         WRAP_BIDI_LOOP
  3192.     }
  3193.  
  3194.     SET_BACK_MIXER_POS
  3195. }
  3196.  
  3197. static void mix8bRampNoLoopIntrp(voice_t *v, uint32_t numSamples)
  3198. {
  3199.     const int8_t *CDA_LinearAdr;
  3200.     bool mixInMono;
  3201.     int32_t realPos, sample, sample2, sample3, *audioMixL, *audioMixR, CDA_BytesLeft, CDA_LVolIP, CDA_RVolIP;
  3202.     register const int8_t *smpPtr;
  3203.     register int32_t CDA_LVol, CDA_RVol;
  3204.     register uint32_t pos, delta;
  3205.     uint32_t i, samplesToMix;
  3206.  
  3207.     if ((v->SLVol1 | v->SRVol1 | v->SLVol2 | v->SRVol2) == 0)
  3208.     {
  3209.         VOL0_OPTIMIZATION_NO_LOOP
  3210.         return;
  3211.     }
  3212.  
  3213.     GET_MIXER_VARS_RAMP
  3214.     GET_DELTA
  3215.     SET_BASE8
  3216.  
  3217.     CDA_BytesLeft = numSamples;
  3218.     while (CDA_BytesLeft > 0)
  3219.     {
  3220.         LIMIT_MIX_NUM
  3221.         LIMIT_MIX_NUM_RAMP
  3222.         CDA_BytesLeft -= samplesToMix;
  3223.  
  3224.         GET_VOL
  3225.         if (mixInMono)
  3226.         {
  3227.             if (samplesToMix & 1)
  3228.             {
  3229.                 RENDER_8BIT_SMP_MONO_INTRP
  3230.                 VOLUME_RAMPING
  3231.                 INC_POS
  3232.             }
  3233.             samplesToMix >>= 1;
  3234.             for (i = 0; i < samplesToMix; i++)
  3235.             {
  3236.                 RENDER_8BIT_SMP_MONO_INTRP
  3237.                 VOLUME_RAMPING
  3238.                 INC_POS
  3239.                 RENDER_8BIT_SMP_MONO_INTRP
  3240.                 VOLUME_RAMPING
  3241.                 INC_POS
  3242.             }
  3243.         }
  3244.         else
  3245.         {
  3246.             if (samplesToMix & 1)
  3247.             {
  3248.                 RENDER_8BIT_SMP_INTRP
  3249.                 VOLUME_RAMPING
  3250.                 INC_POS
  3251.             }
  3252.             samplesToMix >>= 1;
  3253.             for (i = 0; i < samplesToMix; i++)
  3254.             {
  3255.                 RENDER_8BIT_SMP_INTRP
  3256.                 VOLUME_RAMPING
  3257.                 INC_POS
  3258.                 RENDER_8BIT_SMP_INTRP
  3259.                 VOLUME_RAMPING
  3260.                 INC_POS
  3261.             }
  3262.         }
  3263.         SET_VOL_BACK
  3264.  
  3265.         HANDLE_SAMPLE_END
  3266.     }
  3267.  
  3268.     SET_BACK_MIXER_POS
  3269. }
  3270.  
  3271. static void mix8bRampLoopIntrp(voice_t *v, uint32_t numSamples)
  3272. {
  3273.     const int8_t *CDA_LinearAdr;
  3274.     bool mixInMono;
  3275.     int32_t realPos, sample, sample2, sample3, *audioMixL, *audioMixR, CDA_BytesLeft, CDA_LVolIP, CDA_RVolIP;
  3276.     register const int8_t *smpPtr;
  3277.     register int32_t CDA_LVol, CDA_RVol;
  3278.     register uint32_t pos, delta;
  3279.     uint32_t i, samplesToMix;
  3280.  
  3281.     if ((v->SLVol1 | v->SRVol1 | v->SLVol2 | v->SRVol2) == 0)
  3282.     {
  3283.         VOL0_OPTIMIZATION_LOOP
  3284.         return;
  3285.     }
  3286.  
  3287.     GET_MIXER_VARS_RAMP
  3288.     GET_DELTA
  3289.     SET_BASE8
  3290.  
  3291.     CDA_BytesLeft = numSamples;
  3292.     while (CDA_BytesLeft > 0)
  3293.     {
  3294.         LIMIT_MIX_NUM
  3295.         LIMIT_MIX_NUM_RAMP
  3296.         CDA_BytesLeft -= samplesToMix;
  3297.  
  3298.         GET_VOL
  3299.         if (mixInMono)
  3300.         {
  3301.             if (samplesToMix & 1)
  3302.             {
  3303.                 RENDER_8BIT_SMP_MONO_INTRP
  3304.                 VOLUME_RAMPING
  3305.                 INC_POS
  3306.             }
  3307.             samplesToMix >>= 1;
  3308.             for (i = 0; i < samplesToMix; i++)
  3309.             {
  3310.                 RENDER_8BIT_SMP_MONO_INTRP
  3311.                 VOLUME_RAMPING
  3312.                 INC_POS
  3313.                 RENDER_8BIT_SMP_MONO_INTRP
  3314.                 VOLUME_RAMPING
  3315.                 INC_POS
  3316.             }
  3317.         }
  3318.         else
  3319.         {
  3320.             if (samplesToMix & 1)
  3321.             {
  3322.                 RENDER_8BIT_SMP_INTRP
  3323.                 VOLUME_RAMPING
  3324.                 INC_POS
  3325.             }
  3326.             samplesToMix >>= 1;
  3327.             for (i = 0; i < samplesToMix; i++)
  3328.             {
  3329.                 RENDER_8BIT_SMP_INTRP
  3330.                 VOLUME_RAMPING
  3331.                 INC_POS
  3332.                 RENDER_8BIT_SMP_INTRP
  3333.                 VOLUME_RAMPING
  3334.                 INC_POS
  3335.             }
  3336.         }
  3337.         SET_VOL_BACK
  3338.  
  3339.         WRAP_LOOP
  3340.     }
  3341.  
  3342.     SET_BACK_MIXER_POS
  3343. }
  3344.  
  3345. static void mix8bRampBidiLoopIntrp(voice_t *v, uint32_t numSamples)
  3346. {
  3347.     bool mixInMono;
  3348.     const int8_t *CDA_LinearAdr, *CDA_LinAdrRev;
  3349.     int32_t realPos, sample, sample2, sample3, *audioMixL, *audioMixR, CDA_BytesLeft, CDA_LVolIP, CDA_RVolIP;
  3350.     register const int8_t *smpPtr;
  3351.     register int32_t CDA_LVol, CDA_RVol, CDA_IPValL, CDA_IPValH;
  3352.     register uint32_t pos;
  3353.     uint32_t delta, i, samplesToMix;
  3354.  
  3355.     if ((v->SLVol1 | v->SRVol1 | v->SLVol2 | v->SRVol2) == 0)
  3356.     {
  3357.         VOL0_OPTIMIZATION_BIDI_LOOP
  3358.         return;
  3359.     }
  3360.  
  3361.     GET_MIXER_VARS_RAMP
  3362.     SET_BASE8_BIDI
  3363.  
  3364.     CDA_BytesLeft = numSamples;
  3365.     while (CDA_BytesLeft > 0)
  3366.     {
  3367.         LIMIT_MIX_NUM
  3368.         LIMIT_MIX_NUM_RAMP
  3369.         CDA_BytesLeft -= samplesToMix;
  3370.  
  3371.         GET_VOL
  3372.         START_BIDI
  3373.         if (mixInMono)
  3374.         {
  3375.             if (samplesToMix & 1)
  3376.             {
  3377.                 RENDER_8BIT_SMP_MONO_INTRP
  3378.                 VOLUME_RAMPING
  3379.                 INC_POS_BIDI
  3380.             }
  3381.             samplesToMix >>= 1;
  3382.             for (i = 0; i < samplesToMix; i++)
  3383.             {
  3384.                 RENDER_8BIT_SMP_MONO_INTRP
  3385.                 VOLUME_RAMPING
  3386.                 INC_POS_BIDI
  3387.                 RENDER_8BIT_SMP_MONO_INTRP
  3388.                 VOLUME_RAMPING
  3389.                 INC_POS_BIDI
  3390.             }
  3391.         }
  3392.         else
  3393.         {
  3394.             if (samplesToMix & 1)
  3395.             {
  3396.                 RENDER_8BIT_SMP_INTRP
  3397.                 VOLUME_RAMPING
  3398.                 INC_POS_BIDI
  3399.             }
  3400.             samplesToMix >>= 1;
  3401.             for (i = 0; i < samplesToMix; i++)
  3402.             {
  3403.                 RENDER_8BIT_SMP_INTRP
  3404.                 VOLUME_RAMPING
  3405.                 INC_POS_BIDI
  3406.                 RENDER_8BIT_SMP_INTRP
  3407.                 VOLUME_RAMPING
  3408.                 INC_POS_BIDI
  3409.             }
  3410.         }
  3411.         END_BIDI
  3412.         SET_VOL_BACK
  3413.  
  3414.         WRAP_BIDI_LOOP
  3415.     }
  3416.     SET_BACK_MIXER_POS
  3417. }
  3418.  
  3419. /* ----------------------------------------------------------------------- */
  3420. /*                          16-BIT MIXING ROUTINES                         */
  3421. /* ----------------------------------------------------------------------- */
  3422.  
  3423. static void mix16bNoLoop(voice_t *v, uint32_t numSamples)
  3424. {
  3425.     bool mixInMono;
  3426.     const int16_t *CDA_LinearAdr;
  3427.     int32_t realPos, sample, *audioMixL, *audioMixR, CDA_BytesLeft;
  3428.     register const int16_t *smpPtr;
  3429.     register int32_t CDA_LVol, CDA_RVol;
  3430.     register uint32_t pos, delta;
  3431.     uint32_t i, samplesToMix;
  3432.  
  3433.     GET_VOL
  3434.  
  3435.     if ((CDA_LVol | CDA_RVol) == 0)
  3436.     {
  3437.         VOL0_OPTIMIZATION_NO_LOOP
  3438.         return;
  3439.     }
  3440.  
  3441.     GET_MIXER_VARS
  3442.     GET_DELTA
  3443.     SET_BASE16
  3444.  
  3445.     CDA_BytesLeft = numSamples;
  3446.     while (CDA_BytesLeft > 0)
  3447.     {
  3448.         LIMIT_MIX_NUM
  3449.         CDA_BytesLeft -= samplesToMix;
  3450.  
  3451.         if (mixInMono)
  3452.         {
  3453.             if (samplesToMix & 1)
  3454.             {
  3455.                 RENDER_16BIT_SMP_MONO
  3456.                 INC_POS
  3457.             }
  3458.             samplesToMix >>= 1;
  3459.             for (i = 0; i < samplesToMix; i++)
  3460.             {
  3461.                 RENDER_16BIT_SMP_MONO
  3462.                 INC_POS
  3463.                 RENDER_16BIT_SMP_MONO
  3464.                 INC_POS
  3465.             }
  3466.         }
  3467.         else
  3468.         {
  3469.             if (samplesToMix & 1)
  3470.             {
  3471.                 RENDER_16BIT_SMP
  3472.                 INC_POS
  3473.             }
  3474.             samplesToMix >>= 1;
  3475.             for (i = 0; i < samplesToMix; i++)
  3476.             {
  3477.                 RENDER_16BIT_SMP
  3478.                 INC_POS
  3479.                 RENDER_16BIT_SMP
  3480.                 INC_POS
  3481.             }
  3482.         }
  3483.  
  3484.         HANDLE_SAMPLE_END
  3485.     }
  3486.  
  3487.     SET_BACK_MIXER_POS
  3488. }
  3489.  
  3490. static void mix16bLoop(voice_t *v, uint32_t numSamples)
  3491. {
  3492.     bool mixInMono;
  3493.     const int16_t *CDA_LinearAdr;
  3494.     int32_t realPos, sample, *audioMixL, *audioMixR, CDA_BytesLeft;
  3495.     register const int16_t *smpPtr;
  3496.     register int32_t CDA_LVol, CDA_RVol;
  3497.     register uint32_t pos, delta;
  3498.     uint32_t i, samplesToMix;
  3499.  
  3500.     GET_VOL
  3501.  
  3502.     if ((CDA_LVol | CDA_RVol) == 0)
  3503.     {
  3504.         VOL0_OPTIMIZATION_LOOP
  3505.         return;
  3506.     }
  3507.  
  3508.     GET_MIXER_VARS
  3509.     GET_DELTA
  3510.     SET_BASE16
  3511.  
  3512.     CDA_BytesLeft = numSamples;
  3513.     while (CDA_BytesLeft > 0)
  3514.     {
  3515.         LIMIT_MIX_NUM
  3516.         CDA_BytesLeft -= samplesToMix;
  3517.  
  3518.         if (mixInMono)
  3519.         {
  3520.             if (samplesToMix & 1)
  3521.             {
  3522.                 RENDER_16BIT_SMP_MONO
  3523.                 INC_POS
  3524.             }
  3525.             samplesToMix >>= 1;
  3526.             for (i = 0; i < samplesToMix; i++)
  3527.             {
  3528.                 RENDER_16BIT_SMP_MONO
  3529.                 INC_POS
  3530.                 RENDER_16BIT_SMP_MONO
  3531.                 INC_POS
  3532.             }
  3533.         }
  3534.         else
  3535.         {
  3536.             if (samplesToMix & 1)
  3537.             {
  3538.                 RENDER_16BIT_SMP
  3539.                 INC_POS
  3540.             }
  3541.             samplesToMix >>= 1;
  3542.             for (i = 0; i < samplesToMix; i++)
  3543.             {
  3544.                 RENDER_16BIT_SMP
  3545.                 INC_POS
  3546.                 RENDER_16BIT_SMP
  3547.                 INC_POS
  3548.             }
  3549.         }
  3550.  
  3551.         WRAP_LOOP
  3552.     }
  3553.  
  3554.     SET_BACK_MIXER_POS
  3555. }
  3556.  
  3557. static void mix16bBidiLoop(voice_t *v, uint32_t numSamples)
  3558. {
  3559.     bool mixInMono;
  3560.     const int16_t *CDA_LinearAdr, *CDA_LinAdrRev;
  3561.     int32_t realPos, sample, *audioMixL, *audioMixR, CDA_BytesLeft;
  3562.     register const int16_t *smpPtr;
  3563.     register int32_t CDA_LVol, CDA_RVol, CDA_IPValL, CDA_IPValH;
  3564.     register uint32_t pos;
  3565.     uint32_t delta, i, samplesToMix;
  3566.  
  3567.     GET_VOL
  3568.  
  3569.     if ((CDA_LVol | CDA_RVol) == 0)
  3570.     {
  3571.         VOL0_OPTIMIZATION_BIDI_LOOP
  3572.         return;
  3573.     }
  3574.  
  3575.     GET_MIXER_VARS
  3576.     SET_BASE16_BIDI
  3577.  
  3578.     CDA_BytesLeft = numSamples;
  3579.     while (CDA_BytesLeft > 0)
  3580.     {
  3581.         LIMIT_MIX_NUM
  3582.         CDA_BytesLeft -= samplesToMix;
  3583.  
  3584.         START_BIDI
  3585.         if (mixInMono)
  3586.         {
  3587.             if (samplesToMix & 1)
  3588.             {
  3589.                 RENDER_16BIT_SMP_MONO
  3590.                 INC_POS_BIDI
  3591.             }
  3592.             samplesToMix >>= 1;
  3593.             for (i = 0; i < samplesToMix; i++)
  3594.             {
  3595.                 RENDER_16BIT_SMP_MONO
  3596.                 INC_POS_BIDI
  3597.                 RENDER_16BIT_SMP_MONO
  3598.                 INC_POS_BIDI
  3599.             }
  3600.         }
  3601.         else
  3602.         {
  3603.             if (samplesToMix & 1)
  3604.             {
  3605.                 RENDER_16BIT_SMP
  3606.                 INC_POS_BIDI
  3607.             }
  3608.             samplesToMix >>= 1;
  3609.             for (i = 0; i < samplesToMix; i++)
  3610.             {
  3611.                 RENDER_16BIT_SMP
  3612.                 INC_POS_BIDI
  3613.                 RENDER_16BIT_SMP
  3614.                 INC_POS_BIDI
  3615.             }
  3616.         }
  3617.         END_BIDI
  3618.  
  3619.         WRAP_BIDI_LOOP
  3620.     }
  3621.  
  3622.     SET_BACK_MIXER_POS
  3623. }
  3624.  
  3625. static void mix16bNoLoopIntrp(voice_t *v, uint32_t numSamples)
  3626. {
  3627.     bool mixInMono;
  3628.     const int16_t *CDA_LinearAdr;
  3629.     int32_t realPos, sample, sample2, sample3, *audioMixL, *audioMixR, CDA_BytesLeft;
  3630.     register const int16_t *smpPtr;
  3631.     register int32_t CDA_LVol, CDA_RVol;
  3632.     register uint32_t pos, delta;
  3633.     uint32_t i, samplesToMix;
  3634.  
  3635.     GET_VOL
  3636.  
  3637.     if ((CDA_LVol | CDA_RVol) == 0)
  3638.     {
  3639.         VOL0_OPTIMIZATION_NO_LOOP
  3640.         return;
  3641.     }
  3642.  
  3643.     GET_MIXER_VARS
  3644.     GET_DELTA
  3645.     SET_BASE16
  3646.  
  3647.     CDA_BytesLeft = numSamples;
  3648.     while (CDA_BytesLeft > 0)
  3649.     {
  3650.         LIMIT_MIX_NUM
  3651.         CDA_BytesLeft -= samplesToMix;
  3652.  
  3653.         if (mixInMono)
  3654.         {
  3655.             if (samplesToMix & 1)
  3656.             {
  3657.                 RENDER_16BIT_SMP_MONO_INTRP
  3658.                 INC_POS
  3659.             }
  3660.             samplesToMix >>= 1;
  3661.             for (i = 0; i < samplesToMix; i++)
  3662.             {
  3663.                 RENDER_16BIT_SMP_MONO_INTRP
  3664.                 INC_POS
  3665.                 RENDER_16BIT_SMP_MONO_INTRP
  3666.                 INC_POS
  3667.             }
  3668.         }
  3669.         else
  3670.         {
  3671.             if (samplesToMix & 1)
  3672.             {
  3673.                 RENDER_16BIT_SMP_INTRP
  3674.                 INC_POS
  3675.             }
  3676.             samplesToMix >>= 1;
  3677.             for (i = 0; i < samplesToMix; i++)
  3678.             {
  3679.                 RENDER_16BIT_SMP_INTRP
  3680.                 INC_POS
  3681.                 RENDER_16BIT_SMP_INTRP
  3682.                 INC_POS
  3683.             }
  3684.         }
  3685.  
  3686.         HANDLE_SAMPLE_END
  3687.     }
  3688.  
  3689.     SET_BACK_MIXER_POS
  3690. }
  3691.  
  3692. static void mix16bLoopIntrp(voice_t *v, uint32_t numSamples)
  3693. {
  3694.     bool mixInMono;
  3695.     const int16_t *CDA_LinearAdr;
  3696.     int32_t realPos, sample, sample2, sample3, *audioMixL, *audioMixR, CDA_BytesLeft;
  3697.     register const int16_t *smpPtr;
  3698.     register int32_t CDA_LVol, CDA_RVol;
  3699.     register uint32_t pos, delta;
  3700.     uint32_t i, samplesToMix;
  3701.  
  3702.     GET_VOL
  3703.  
  3704.     if ((CDA_LVol| CDA_RVol) == 0)
  3705.     {
  3706.         VOL0_OPTIMIZATION_LOOP
  3707.         return;
  3708.     }
  3709.  
  3710.     GET_MIXER_VARS
  3711.     GET_DELTA
  3712.     SET_BASE16
  3713.  
  3714.     CDA_BytesLeft = numSamples;
  3715.     while (CDA_BytesLeft > 0)
  3716.     {
  3717.         LIMIT_MIX_NUM
  3718.         CDA_BytesLeft -= samplesToMix;
  3719.  
  3720.         if (mixInMono)
  3721.         {
  3722.             if (samplesToMix & 1)
  3723.             {
  3724.                 RENDER_16BIT_SMP_MONO_INTRP
  3725.                 INC_POS
  3726.             }
  3727.             samplesToMix >>= 1;
  3728.             for (i = 0; i < samplesToMix; i++)
  3729.             {
  3730.                 RENDER_16BIT_SMP_MONO_INTRP
  3731.                 INC_POS
  3732.                 RENDER_16BIT_SMP_MONO_INTRP
  3733.                 INC_POS
  3734.             }
  3735.         }
  3736.         else
  3737.         {
  3738.             if (samplesToMix & 1)
  3739.             {
  3740.                 RENDER_16BIT_SMP_INTRP
  3741.                 INC_POS
  3742.             }
  3743.             samplesToMix >>= 1;
  3744.             for (i = 0; i < samplesToMix; i++)
  3745.             {
  3746.                 RENDER_16BIT_SMP_INTRP
  3747.                 INC_POS
  3748.                 RENDER_16BIT_SMP_INTRP
  3749.                 INC_POS
  3750.             }
  3751.         }
  3752.  
  3753.         WRAP_LOOP
  3754.     }
  3755.  
  3756.     SET_BACK_MIXER_POS
  3757. }
  3758.  
  3759. static void mix16bBidiLoopIntrp(voice_t *v, uint32_t numSamples)
  3760. {
  3761.     bool mixInMono;
  3762.     const int16_t *CDA_LinearAdr, *CDA_LinAdrRev;
  3763.     int32_t realPos, sample, sample2, sample3, *audioMixL, *audioMixR, CDA_BytesLeft;
  3764.     register const int16_t *smpPtr;
  3765.     register int32_t CDA_LVol, CDA_RVol, CDA_IPValL, CDA_IPValH;
  3766.     register uint32_t pos;
  3767.     uint32_t delta, i, samplesToMix;
  3768.  
  3769.     GET_VOL
  3770.  
  3771.     if ((CDA_LVol | CDA_RVol) == 0)
  3772.     {
  3773.         VOL0_OPTIMIZATION_BIDI_LOOP
  3774.         return;
  3775.     }
  3776.  
  3777.     GET_MIXER_VARS
  3778.     SET_BASE16_BIDI
  3779.  
  3780.     CDA_BytesLeft = numSamples;
  3781.     while (CDA_BytesLeft > 0)
  3782.     {
  3783.         LIMIT_MIX_NUM
  3784.         CDA_BytesLeft -= samplesToMix;
  3785.  
  3786.         START_BIDI
  3787.         if (mixInMono)
  3788.         {
  3789.             if (samplesToMix & 1)
  3790.             {
  3791.                 RENDER_16BIT_SMP_MONO_INTRP
  3792.                 INC_POS_BIDI
  3793.             }
  3794.             samplesToMix >>= 1;
  3795.             for (i = 0; i < samplesToMix; i++)
  3796.             {
  3797.                 RENDER_16BIT_SMP_MONO_INTRP
  3798.                 INC_POS_BIDI
  3799.                 RENDER_16BIT_SMP_MONO_INTRP
  3800.                 INC_POS_BIDI
  3801.             }
  3802.         }
  3803.         else
  3804.         {
  3805.             if (samplesToMix & 1)
  3806.             {
  3807.                 RENDER_16BIT_SMP_INTRP
  3808.                 INC_POS_BIDI
  3809.             }
  3810.             samplesToMix >>= 1;
  3811.             for (i = 0; i < samplesToMix; i++)
  3812.             {
  3813.                 RENDER_16BIT_SMP_INTRP
  3814.                 INC_POS_BIDI
  3815.                 RENDER_16BIT_SMP_INTRP
  3816.                 INC_POS_BIDI
  3817.             }
  3818.         }
  3819.         END_BIDI
  3820.  
  3821.         WRAP_BIDI_LOOP
  3822.     }
  3823.  
  3824.     SET_BACK_MIXER_POS
  3825. }
  3826.  
  3827. static void mix16bRampNoLoop(voice_t *v, uint32_t numSamples)
  3828. {
  3829.     bool mixInMono;
  3830.     const int16_t *CDA_LinearAdr;
  3831.     int32_t realPos, sample, *audioMixL, *audioMixR, CDA_BytesLeft, CDA_LVolIP, CDA_RVolIP;
  3832.     register const int16_t *smpPtr;
  3833.     register int32_t CDA_LVol, CDA_RVol;
  3834.     register uint32_t pos, delta;
  3835.     uint32_t i, samplesToMix;
  3836.  
  3837.     if ((v->SLVol1 | v->SRVol1 | v->SLVol2 | v->SRVol2) == 0)
  3838.     {
  3839.         VOL0_OPTIMIZATION_NO_LOOP
  3840.         return;
  3841.     }
  3842.  
  3843.     GET_MIXER_VARS_RAMP
  3844.     GET_DELTA
  3845.     SET_BASE16
  3846.  
  3847.     CDA_BytesLeft = numSamples;
  3848.     while (CDA_BytesLeft > 0)
  3849.     {
  3850.         LIMIT_MIX_NUM
  3851.         LIMIT_MIX_NUM_RAMP
  3852.         CDA_BytesLeft -= samplesToMix;
  3853.  
  3854.         GET_VOL
  3855.         if (mixInMono)
  3856.         {
  3857.             if (samplesToMix & 1)
  3858.             {
  3859.                 RENDER_16BIT_SMP_MONO
  3860.                 VOLUME_RAMPING
  3861.                 INC_POS
  3862.             }
  3863.             samplesToMix >>= 1;
  3864.             for (i = 0; i < samplesToMix; i++)
  3865.             {
  3866.                 RENDER_16BIT_SMP_MONO
  3867.                 VOLUME_RAMPING
  3868.                 INC_POS
  3869.                 RENDER_16BIT_SMP_MONO
  3870.                 VOLUME_RAMPING
  3871.                 INC_POS
  3872.             }
  3873.         }
  3874.         else
  3875.         {
  3876.             if (samplesToMix & 1)
  3877.             {
  3878.                 RENDER_16BIT_SMP
  3879.                 VOLUME_RAMPING
  3880.                 INC_POS
  3881.             }
  3882.             samplesToMix >>= 1;
  3883.             for (i = 0; i < samplesToMix; i++)
  3884.             {
  3885.                 RENDER_16BIT_SMP
  3886.                 VOLUME_RAMPING
  3887.                 INC_POS
  3888.                 RENDER_16BIT_SMP
  3889.                 VOLUME_RAMPING
  3890.                 INC_POS
  3891.             }
  3892.         }
  3893.         SET_VOL_BACK
  3894.  
  3895.         HANDLE_SAMPLE_END
  3896.     }
  3897.  
  3898.     SET_BACK_MIXER_POS
  3899. }
  3900.  
  3901. static void mix16bRampLoop(voice_t *v, uint32_t numSamples)
  3902. {
  3903.     bool mixInMono;
  3904.     const int16_t *CDA_LinearAdr;
  3905.     int32_t realPos, sample, *audioMixL, *audioMixR, CDA_BytesLeft, CDA_LVolIP, CDA_RVolIP;
  3906.     register const int16_t *smpPtr;
  3907.     register int32_t CDA_LVol, CDA_RVol;
  3908.     register uint32_t pos, delta;
  3909.     uint32_t i, samplesToMix;
  3910.  
  3911.     if ((v->SLVol1 | v->SRVol1 | v->SLVol2 | v->SRVol2) == 0)
  3912.     {
  3913.         VOL0_OPTIMIZATION_LOOP
  3914.         return;
  3915.     }
  3916.  
  3917.     GET_MIXER_VARS_RAMP
  3918.     GET_DELTA
  3919.     SET_BASE16
  3920.  
  3921.     CDA_BytesLeft = numSamples;
  3922.     while (CDA_BytesLeft > 0)
  3923.     {
  3924.         LIMIT_MIX_NUM
  3925.         LIMIT_MIX_NUM_RAMP
  3926.         CDA_BytesLeft -= samplesToMix;
  3927.  
  3928.         GET_VOL
  3929.         if (mixInMono)
  3930.         {
  3931.             if (samplesToMix & 1)
  3932.             {
  3933.                 RENDER_16BIT_SMP_MONO
  3934.                 VOLUME_RAMPING
  3935.                 INC_POS
  3936.             }
  3937.             samplesToMix >>= 1;
  3938.             for (i = 0; i < samplesToMix; i++)
  3939.             {
  3940.                 RENDER_16BIT_SMP_MONO
  3941.                 VOLUME_RAMPING
  3942.                 INC_POS
  3943.                 RENDER_16BIT_SMP_MONO
  3944.                 VOLUME_RAMPING
  3945.                 INC_POS
  3946.             }
  3947.         }
  3948.         else
  3949.         {
  3950.             if (samplesToMix & 1)
  3951.             {
  3952.                 RENDER_16BIT_SMP
  3953.                 VOLUME_RAMPING
  3954.                 INC_POS
  3955.             }
  3956.             samplesToMix >>= 1;
  3957.             for (i = 0; i < samplesToMix; i++)
  3958.             {
  3959.                 RENDER_16BIT_SMP
  3960.                 VOLUME_RAMPING
  3961.                 INC_POS
  3962.                 RENDER_16BIT_SMP
  3963.                 VOLUME_RAMPING
  3964.                 INC_POS
  3965.             }
  3966.         }
  3967.         SET_VOL_BACK
  3968.  
  3969.         WRAP_LOOP
  3970.     }
  3971.  
  3972.     SET_BACK_MIXER_POS
  3973. }
  3974.  
  3975. static void mix16bRampBidiLoop(voice_t *v, uint32_t numSamples)
  3976. {
  3977.     bool mixInMono;
  3978.     const int16_t *CDA_LinearAdr, *CDA_LinAdrRev;
  3979.     int32_t realPos, sample, *audioMixL, *audioMixR, CDA_BytesLeft, CDA_LVolIP, CDA_RVolIP;
  3980.     register const int16_t *smpPtr;
  3981.     register int32_t CDA_LVol, CDA_RVol, CDA_IPValL, CDA_IPValH;
  3982.     register uint32_t pos;
  3983.     uint32_t delta, i, samplesToMix;
  3984.  
  3985.     if ((v->SLVol1 | v->SRVol1 | v->SLVol2 | v->SRVol2) == 0)
  3986.     {
  3987.         VOL0_OPTIMIZATION_BIDI_LOOP
  3988.         return;
  3989.     }
  3990.  
  3991.     GET_MIXER_VARS_RAMP
  3992.     SET_BASE16_BIDI
  3993.  
  3994.     CDA_BytesLeft = numSamples;
  3995.     while (CDA_BytesLeft > 0)
  3996.     {
  3997.         LIMIT_MIX_NUM
  3998.         LIMIT_MIX_NUM_RAMP
  3999.         CDA_BytesLeft -= samplesToMix;
  4000.  
  4001.         GET_VOL
  4002.         START_BIDI
  4003.         if (mixInMono)
  4004.         {
  4005.             if (samplesToMix & 1)
  4006.             {
  4007.                 RENDER_16BIT_SMP_MONO
  4008.                 VOLUME_RAMPING
  4009.                 INC_POS_BIDI
  4010.             }
  4011.             samplesToMix >>= 1;
  4012.             for (i = 0; i < samplesToMix; i++)
  4013.             {
  4014.                 RENDER_16BIT_SMP_MONO
  4015.                 VOLUME_RAMPING
  4016.                 INC_POS_BIDI
  4017.                 RENDER_16BIT_SMP_MONO
  4018.                 VOLUME_RAMPING
  4019.                 INC_POS_BIDI
  4020.             }
  4021.         }
  4022.         else
  4023.         {
  4024.             if (samplesToMix & 1)
  4025.             {
  4026.                 RENDER_16BIT_SMP
  4027.                 VOLUME_RAMPING
  4028.                 INC_POS_BIDI
  4029.             }
  4030.             samplesToMix >>= 1;
  4031.             for (i = 0; i < samplesToMix; i++)
  4032.             {
  4033.                 RENDER_16BIT_SMP
  4034.                 VOLUME_RAMPING
  4035.                 INC_POS_BIDI
  4036.                 RENDER_16BIT_SMP
  4037.                 VOLUME_RAMPING
  4038.                 INC_POS_BIDI
  4039.             }
  4040.         }
  4041.         END_BIDI
  4042.         SET_VOL_BACK
  4043.  
  4044.         WRAP_BIDI_LOOP
  4045.     }
  4046.  
  4047.     SET_BACK_MIXER_POS
  4048. }
  4049.  
  4050. static void mix16bRampNoLoopIntrp(voice_t *v, uint32_t numSamples)
  4051. {
  4052.     bool mixInMono;
  4053.     const int16_t *CDA_LinearAdr;
  4054.     int32_t realPos, sample, sample2, sample3, *audioMixL, *audioMixR, CDA_BytesLeft, CDA_LVolIP, CDA_RVolIP;
  4055.     register const int16_t *smpPtr;
  4056.     register int32_t CDA_LVol, CDA_RVol;
  4057.     register uint32_t pos, delta;
  4058.     uint32_t i, samplesToMix;
  4059.  
  4060.     if ((v->SLVol1 | v->SRVol1 | v->SLVol2 | v->SRVol2) == 0)
  4061.     {
  4062.         VOL0_OPTIMIZATION_NO_LOOP
  4063.         return;
  4064.     }
  4065.  
  4066.     GET_MIXER_VARS_RAMP
  4067.     GET_DELTA
  4068.     SET_BASE16
  4069.  
  4070.     CDA_BytesLeft = numSamples;
  4071.     while (CDA_BytesLeft > 0)
  4072.     {
  4073.         LIMIT_MIX_NUM
  4074.         LIMIT_MIX_NUM_RAMP
  4075.         CDA_BytesLeft -= samplesToMix;
  4076.  
  4077.         GET_VOL
  4078.         if (mixInMono)
  4079.         {
  4080.             if (samplesToMix & 1)
  4081.             {
  4082.                 RENDER_16BIT_SMP_MONO_INTRP
  4083.                 VOLUME_RAMPING
  4084.                 INC_POS
  4085.             }
  4086.             samplesToMix >>= 1;
  4087.             for (i = 0; i < samplesToMix; i++)
  4088.             {
  4089.                 RENDER_16BIT_SMP_MONO_INTRP
  4090.                 VOLUME_RAMPING
  4091.                 INC_POS
  4092.                 RENDER_16BIT_SMP_MONO_INTRP
  4093.                 VOLUME_RAMPING
  4094.                 INC_POS
  4095.             }
  4096.         }
  4097.         else
  4098.         {
  4099.             if (samplesToMix & 1)
  4100.             {
  4101.                 RENDER_16BIT_SMP_INTRP
  4102.                 VOLUME_RAMPING
  4103.                 INC_POS
  4104.             }
  4105.             samplesToMix >>= 1;
  4106.             for (i = 0; i < samplesToMix; i++)
  4107.             {
  4108.                 RENDER_16BIT_SMP_INTRP
  4109.                 VOLUME_RAMPING
  4110.                 INC_POS
  4111.                 RENDER_16BIT_SMP_INTRP
  4112.                 VOLUME_RAMPING
  4113.                 INC_POS
  4114.             }
  4115.         }
  4116.         SET_VOL_BACK
  4117.  
  4118.         HANDLE_SAMPLE_END
  4119.     }
  4120.  
  4121.     SET_BACK_MIXER_POS
  4122. }
  4123.  
  4124. static void mix16bRampLoopIntrp(voice_t *v, uint32_t numSamples)
  4125. {
  4126.     bool mixInMono;
  4127.     const int16_t *CDA_LinearAdr;
  4128.     int32_t realPos, sample, sample2, sample3, *audioMixL, *audioMixR, CDA_BytesLeft, CDA_LVolIP, CDA_RVolIP;
  4129.     register const int16_t *smpPtr;
  4130.     register int32_t CDA_LVol, CDA_RVol;
  4131.     register uint32_t pos, delta;
  4132.     uint32_t i, samplesToMix;
  4133.  
  4134.     if ((v->SLVol1 | v->SRVol1 | v->SLVol2 | v->SRVol2) == 0)
  4135.     {
  4136.         VOL0_OPTIMIZATION_LOOP
  4137.         return;
  4138.     }
  4139.  
  4140.     GET_MIXER_VARS_RAMP
  4141.     GET_DELTA
  4142.     SET_BASE16
  4143.  
  4144.     CDA_BytesLeft = numSamples;
  4145.     while (CDA_BytesLeft > 0)
  4146.     {
  4147.         LIMIT_MIX_NUM
  4148.         LIMIT_MIX_NUM_RAMP
  4149.         CDA_BytesLeft -= samplesToMix;
  4150.  
  4151.         GET_VOL
  4152.         if (mixInMono)
  4153.         {
  4154.             if (samplesToMix & 1)
  4155.             {
  4156.                 RENDER_16BIT_SMP_MONO_INTRP
  4157.                 VOLUME_RAMPING
  4158.                 INC_POS
  4159.             }
  4160.             samplesToMix >>= 1;
  4161.             for (i = 0; i < samplesToMix; i++)
  4162.             {
  4163.                 RENDER_16BIT_SMP_MONO_INTRP
  4164.                 VOLUME_RAMPING
  4165.                 INC_POS
  4166.                 RENDER_16BIT_SMP_MONO_INTRP
  4167.                 VOLUME_RAMPING
  4168.                 INC_POS
  4169.             }
  4170.         }
  4171.         else
  4172.         {
  4173.             if (samplesToMix & 1)
  4174.             {
  4175.                 RENDER_16BIT_SMP_INTRP
  4176.                 VOLUME_RAMPING
  4177.                 INC_POS
  4178.             }
  4179.             samplesToMix >>= 1;
  4180.             for (i = 0; i < samplesToMix; i++)
  4181.             {
  4182.                 RENDER_16BIT_SMP_INTRP
  4183.                 VOLUME_RAMPING
  4184.                 INC_POS
  4185.                 RENDER_16BIT_SMP_INTRP
  4186.                 VOLUME_RAMPING
  4187.                 INC_POS
  4188.             }
  4189.         }
  4190.         SET_VOL_BACK
  4191.  
  4192.         WRAP_LOOP
  4193.     }
  4194.  
  4195.     SET_BACK_MIXER_POS
  4196. }
  4197.  
  4198. static void mix16bRampBidiLoopIntrp(voice_t *v, uint32_t numSamples)
  4199. {
  4200.     bool mixInMono;
  4201.     const int16_t *CDA_LinearAdr, *CDA_LinAdrRev;
  4202.     int32_t realPos, sample, sample2, sample3, *audioMixL, *audioMixR, CDA_BytesLeft, CDA_LVolIP, CDA_RVolIP;
  4203.     register const int16_t *smpPtr;
  4204.     register int32_t CDA_LVol, CDA_RVol, CDA_IPValL, CDA_IPValH;
  4205.     register uint32_t pos;
  4206.     uint32_t delta, i, samplesToMix;
  4207.  
  4208.     if ((v->SLVol1 | v->SRVol1 | v->SLVol2 | v->SRVol2) == 0)
  4209.     {
  4210.         VOL0_OPTIMIZATION_BIDI_LOOP
  4211.         return;
  4212.     }
  4213.  
  4214.     GET_MIXER_VARS_RAMP
  4215.     SET_BASE16_BIDI
  4216.  
  4217.     CDA_BytesLeft = numSamples;
  4218.     while (CDA_BytesLeft > 0)
  4219.     {
  4220.         LIMIT_MIX_NUM
  4221.         LIMIT_MIX_NUM_RAMP
  4222.         CDA_BytesLeft -= samplesToMix;
  4223.  
  4224.         GET_VOL
  4225.         START_BIDI
  4226.         if (mixInMono)
  4227.         {
  4228.             if (samplesToMix & 1)
  4229.             {
  4230.                 RENDER_16BIT_SMP_MONO_INTRP
  4231.                 VOLUME_RAMPING
  4232.                 INC_POS_BIDI
  4233.             }
  4234.             samplesToMix >>= 1;
  4235.             for (i = 0; i < samplesToMix; i++)
  4236.             {
  4237.                 RENDER_16BIT_SMP_MONO_INTRP
  4238.                 VOLUME_RAMPING
  4239.                 INC_POS_BIDI
  4240.                 RENDER_16BIT_SMP_MONO_INTRP
  4241.                 VOLUME_RAMPING
  4242.                 INC_POS_BIDI
  4243.             }
  4244.         }
  4245.         else
  4246.         {
  4247.             if (samplesToMix & 1)
  4248.             {
  4249.                 RENDER_16BIT_SMP_INTRP
  4250.                 VOLUME_RAMPING
  4251.                 INC_POS_BIDI
  4252.             }
  4253.             samplesToMix >>= 1;
  4254.             for (i = 0; i < samplesToMix; i++)
  4255.             {
  4256.                 RENDER_16BIT_SMP_INTRP
  4257.                 VOLUME_RAMPING
  4258.                 INC_POS_BIDI
  4259.                 RENDER_16BIT_SMP_INTRP
  4260.                 VOLUME_RAMPING
  4261.                 INC_POS_BIDI
  4262.             }
  4263.         }
  4264.         END_BIDI
  4265.         SET_VOL_BACK
  4266.  
  4267.         WRAP_BIDI_LOOP
  4268.     }
  4269.  
  4270.     SET_BACK_MIXER_POS
  4271. }
  4272.  
  4273. mixRoutine mixRoutineTable[24] =
  4274. {
  4275.     (mixRoutine)mix8bNoLoop,
  4276.     (mixRoutine)mix8bLoop,
  4277.     (mixRoutine)mix8bBidiLoop,
  4278.     (mixRoutine)mix8bNoLoopIntrp,
  4279.     (mixRoutine)mix8bLoopIntrp,
  4280.     (mixRoutine)mix8bBidiLoopIntrp,
  4281.     (mixRoutine)mix8bRampNoLoop,
  4282.     (mixRoutine)mix8bRampLoop,
  4283.     (mixRoutine)mix8bRampBidiLoop,
  4284.     (mixRoutine)mix8bRampNoLoopIntrp,
  4285.     (mixRoutine)mix8bRampLoopIntrp,
  4286.     (mixRoutine)mix8bRampBidiLoopIntrp,
  4287.     (mixRoutine)mix16bNoLoop,
  4288.     (mixRoutine)mix16bLoop,
  4289.     (mixRoutine)mix16bBidiLoop,
  4290.     (mixRoutine)mix16bNoLoopIntrp,
  4291.     (mixRoutine)mix16bLoopIntrp,
  4292.     (mixRoutine)mix16bBidiLoopIntrp,
  4293.     (mixRoutine)mix16bRampNoLoop,
  4294.     (mixRoutine)mix16bRampLoop,
  4295.     (mixRoutine)mix16bRampBidiLoop,
  4296.     (mixRoutine)mix16bRampNoLoopIntrp,
  4297.     (mixRoutine)mix16bRampLoopIntrp,
  4298.     (mixRoutine)mix16bRampBidiLoopIntrp
  4299. };
  4300.  
  4301. // -----------------------------------------------------------------------
  4302.  
  4303. static inline void noNewAllChannels(void)
  4304. {
  4305.     for (uint8_t i = 0; i < song.antChn; i++)
  4306.     {
  4307.         doEffects(&stm[i]);
  4308.         fixaEnvelopeVibrato(&stm[i]);
  4309.     }
  4310. }
  4311.  
  4312. static void getNextPos(void)
  4313. {
  4314.     if (song.timer == 1)
  4315.     {
  4316.         song.pattPos++;
  4317.  
  4318.         if (song.pattDelTime > 0)
  4319.         {
  4320.             song.pattDelTime2 = song.pattDelTime;
  4321.             song.pattDelTime = 0;
  4322.         }
  4323.  
  4324.         if (song.pattDelTime2 > 0)
  4325.         {
  4326.             if (--song.pattDelTime2 > 0)
  4327.                 song.pattPos--;
  4328.         }
  4329.  
  4330.         if (song.pBreakFlag)
  4331.         {
  4332.             song.pBreakFlag = false;
  4333.             song.pattPos = song.pBreakPos;
  4334.         }
  4335.  
  4336.         if (song.pattPos >= song.pattLen || song.posJumpFlag)
  4337.         {
  4338.             song.pattPos = song.pBreakPos;
  4339.             song.pBreakPos = 0;
  4340.             song.posJumpFlag = false;
  4341.  
  4342.             if (++song.songPos >= song.len)
  4343.                 song.songPos = song.repS;
  4344.  
  4345.             song.pattNr = song.songTab[song.songPos & 0xFF];
  4346.             song.pattLen = pattLens[song.pattNr & 0xFF];
  4347.         }
  4348.     }
  4349. }
  4350.  
  4351. static void mainPlayer(void) // periodically called from mixer
  4352. {
  4353.     uint8_t i;
  4354.     bool readNewNote;
  4355.  
  4356.     if (!songPlaying)
  4357.         return;
  4358.  
  4359.     readNewNote = false;
  4360.     if (--song.timer == 0)
  4361.     {
  4362.         song.timer = song.tempo;
  4363.         readNewNote = true;
  4364.     }
  4365.  
  4366.     if (readNewNote)
  4367.     {
  4368.         if (song.pattDelTime2 == 0)
  4369.         {
  4370.             for (i = 0; i < song.antChn; i++)
  4371.             {
  4372.                 if (patt[song.pattNr] != NULL)
  4373.                     getNewNote(&stm[i], &patt[song.pattNr][(song.pattPos * song.antChn) + i]);
  4374.                 else
  4375.                     getNewNote(&stm[i], &nilPatternLine);
  4376.  
  4377.                 fixaEnvelopeVibrato(&stm[i]);
  4378.             }
  4379.         }
  4380.         else
  4381.         {
  4382.             noNewAllChannels();
  4383.         }
  4384.     }
  4385.     else
  4386.     {
  4387.         noNewAllChannels();
  4388.     }
  4389.  
  4390.     getNextPos();
  4391. }
  4392.  
  4393. static void stopVoice(uint8_t i)
  4394. {
  4395.     voice_t *v;
  4396.  
  4397.     v = &voice[i];
  4398.     memset(v, 0, sizeof (voice_t));
  4399.     v->SPan = 128;
  4400.  
  4401.     // clear "fade out" voice too
  4402.  
  4403.     v = &voice[MAX_VOICES + i];
  4404.     memset(v, 0, sizeof (voice_t));
  4405.     v->SPan = 128;
  4406. }
  4407.  
  4408. static void stopVoices(void)
  4409. {
  4410.     stmTyp *ch;
  4411.  
  4412.     for (uint8_t i = 0; i < song.antChn; i++)
  4413.     {
  4414.         ch = &stm[i];
  4415.  
  4416.         ch->tonTyp = 0;
  4417.         ch->relTonNr = 0;
  4418.         ch->instrNr = 0;
  4419.         ch->instrPtr = instr[0]; // placeholder instrument
  4420.         ch->status = IS_Vol;
  4421.         ch->realVol = 0;
  4422.         ch->outVol = 0;
  4423.         ch->oldVol = 0;
  4424.         ch->finalVol = 0;
  4425.         ch->oldPan = 128;
  4426.         ch->outPan = 128;
  4427.         ch->finalPan = 128;
  4428.         ch->vibDepth = 0;
  4429.         ch->smpPtr = NULL;
  4430.         ch->portaDir = 0; // FT2 bugfix: weird 3xx behavior if not used with note
  4431.  
  4432.         stopVoice(i);
  4433.     }
  4434.    
  4435.     oldPeriod = 0;
  4436.     oldRate = 0;
  4437.     oldSFrq = 0;
  4438.     oldSFrqRev = 0xFFFFFFFF;
  4439. }
  4440.  
  4441. static void setPos(int16_t songPos, int16_t pattPos)
  4442. {
  4443.     if (songPos > -1)
  4444.     {
  4445.         song.songPos = songPos;
  4446.         if (song.len > 0 && song.songPos >= song.len)
  4447.             song.songPos = song.len - 1;
  4448.  
  4449.         song.pattNr = song.songTab[songPos];
  4450.         song.pattLen = pattLens[song.pattNr];
  4451.     }
  4452.  
  4453.     if (pattPos > -1)
  4454.     {
  4455.         song.pattPos = pattPos;
  4456.         if (song.pattPos >= song.pattLen)
  4457.             song.pattPos = song.pattLen - 1;
  4458.     }
  4459.  
  4460.     song.timer = 1;
  4461. }
  4462.  
  4463. static void freeInstr(uint16_t ins)
  4464. {
  4465.     if (instr[ins] == NULL)
  4466.         return;
  4467.  
  4468.     for (uint8_t i = 0; i < 16; i++)
  4469.     {
  4470.         if (instr[ins]->samp[i].pek != NULL)
  4471.         {
  4472.             free(instr[ins]->samp[i].pek);
  4473.             instr[ins]->samp[i].pek = NULL;
  4474.         }
  4475.     }
  4476.  
  4477.     free(instr[ins]);
  4478.     instr[ins] = NULL;
  4479. }
  4480.  
  4481. static void freeAllInstr(void)
  4482. {
  4483.     for (uint16_t i = 0; i < 128; i++)
  4484.         freeInstr(i);
  4485. }
  4486.  
  4487. static void freeAllPatterns(void)
  4488. {
  4489.     for (uint16_t i = 0; i < 256; i++)
  4490.     {
  4491.         if (patt[i] != NULL)
  4492.         {
  4493.             free(patt[i]);
  4494.             patt[i] = NULL;
  4495.         }
  4496.     }
  4497. }
  4498.  
  4499. static bool allocateInstr(uint16_t i)
  4500. {
  4501.     instrTyp *p;
  4502.  
  4503.     if (instr[i] == NULL)
  4504.     {
  4505.         p = (instrTyp *)calloc(1, sizeof (instrTyp));
  4506.         if (p == NULL)
  4507.             return 0;
  4508.  
  4509.         for (uint8_t j = 0; j < 16; j++)
  4510.         {
  4511.             p->samp[j].pan = 128;
  4512.             p->samp[j].vol = 64;
  4513.         }
  4514.  
  4515.         instr[i] = p;
  4516.         return true;
  4517.     }
  4518.  
  4519.     return false;
  4520. }
  4521.  
  4522. static void delta2Samp(int8_t *p, uint32_t len, uint8_t typ)
  4523. {
  4524.     int8_t *p8, news8, olds8L, olds8R;
  4525.     int16_t *p16, news16, olds16L, olds16R;
  4526.     uint32_t i;
  4527.  
  4528.     if (typ & 16) len /= 2; // 16-bit
  4529.     if (typ & 32) len /= 2; // stereo
  4530.  
  4531.     if (typ & 32)
  4532.     {
  4533.         if (typ & 16)
  4534.         {
  4535.             p16 = (int16_t *)p;
  4536.  
  4537.             olds16L = 0;
  4538.             olds16R = 0;
  4539.  
  4540.             for (i = 0; i < len; i++)
  4541.             {
  4542.                 news16 = p16[i] + olds16L;
  4543.                 p16[i] = news16;
  4544.                 olds16L = news16;
  4545.  
  4546.                 news16 = p16[len+i] + olds16R;
  4547.                 p16[len+i] = news16;
  4548.                 olds16R = news16;
  4549.             }
  4550.         }
  4551.         else
  4552.         {
  4553.             p8 = (int8_t *)p;
  4554.  
  4555.             olds8L = 0;
  4556.             olds8R = 0;
  4557.  
  4558.             for (i = 0; i < len; i++)
  4559.             {
  4560.                 news8 = p8[i] + olds8L;
  4561.                 p8[i] = news8;
  4562.                 olds8L = news8;
  4563.  
  4564.                 news8 = p8[len+i] + olds8R;
  4565.                 p8[len+i] = news8;
  4566.                 olds8R = news8;
  4567.             }
  4568.         }
  4569.     }
  4570.     else
  4571.     {
  4572.         if (typ & 16)
  4573.         {
  4574.             p16 = (int16_t *)p;
  4575.  
  4576.             olds16L = 0;
  4577.             for (i = 0; i < len; i++)
  4578.             {
  4579.                 news16 = p16[i] + olds16L;
  4580.                 p16[i] = news16;
  4581.                 olds16L = news16;
  4582.             }
  4583.         }
  4584.         else
  4585.         {
  4586.             p8 = (int8_t *)p;
  4587.  
  4588.             olds8L = 0;
  4589.             for (i = 0; i < len; i++)
  4590.             {
  4591.                 news8 = p8[i] + olds8L;
  4592.                 p8[i] = news8;
  4593.                 olds8L = news8;
  4594.             }
  4595.         }
  4596.     }
  4597. }
  4598.  
  4599. static bool loadInstrHeader(MEM *f, uint16_t i)
  4600. {
  4601.     uint8_t j;
  4602.     uint32_t readSize;
  4603.     instrHeaderTyp ih;
  4604.     sampleTyp *s;
  4605.  
  4606.     memset(&ih, 0, INSTR_HEADER_SIZE);
  4607.  
  4608.     mread(&ih.instrSize, 4, 1, f);
  4609.  
  4610.     readSize = ih.instrSize;
  4611.     if (readSize < 4 || readSize > INSTR_HEADER_SIZE)
  4612.         readSize = INSTR_HEADER_SIZE;
  4613.  
  4614.     // load instrument data into temp buffer
  4615.     mread(ih.name, readSize - 4, 1, f); // -4 = skip ih.instrSize
  4616.  
  4617.     // FT2 bugfix: skip instrument header data if instrSize is above INSTR_HEADER_SIZE
  4618.     if (ih.instrSize > INSTR_HEADER_SIZE)
  4619.         mseek(f, ih.instrSize - INSTR_HEADER_SIZE, SEEK_CUR);
  4620.  
  4621.     if (ih.antSamp > 16)
  4622.         return false;
  4623.  
  4624.     if (ih.antSamp > 0)
  4625.     {
  4626.         if (!allocateInstr(i))
  4627.             return false;
  4628.  
  4629.         // sanitize stuff for malicious instruments
  4630.         if (ih.mute     !=    1) ih.mute        = 0;
  4631.         if (ih.vibDepth >  0x0F) ih.vibDepth    = 0x0F;
  4632.         if (ih.vibRate  >  0x3F) ih.vibRate     = 0x3F;
  4633.         if (ih.vibTyp   >     3) ih.vibTyp      = 0;
  4634.  
  4635.         for (j = 0; j < 96; j++)
  4636.         {
  4637.             if (ih.ta[j] > 0x0F)
  4638.                 ih.ta[j] = 0x0F;
  4639.         }
  4640.         // ---------------------------------------
  4641.  
  4642.         // copy over final instrument data
  4643.         memcpy(instr[i], ih.ta, INSTR_SIZE);
  4644.         instr[i]->antSamp = ih.antSamp;
  4645.  
  4646.         if (instr[i]->envVPAnt > 12) instr[i]->envVPAnt = 12;
  4647.         if (instr[i]->envVRepS > 11) instr[i]->envVRepS = 11;
  4648.         if (instr[i]->envVRepE > 11) instr[i]->envVRepE = 11;
  4649.         if (instr[i]->envVSust > 11) instr[i]->envVSust = 11;
  4650.         if (instr[i]->envPPAnt > 12) instr[i]->envPPAnt = 12;
  4651.         if (instr[i]->envPRepS > 11) instr[i]->envPRepS = 11;
  4652.         if (instr[i]->envPRepE > 11) instr[i]->envPRepE = 11;
  4653.         if (instr[i]->envPSust > 11) instr[i]->envPSust = 11;
  4654.  
  4655.         mread(ih.samp, ih.antSamp * sizeof (sampleHeaderTyp), 1, f);
  4656.  
  4657.         for (j = 0; j < ih.antSamp; j++)
  4658.         {
  4659.             s = &instr[i]->samp[j];
  4660.             memcpy(s, &ih.samp[j], 12+4+24);
  4661.             // s->pek is set up later
  4662.  
  4663.             // sanitize stuff for malicious modules
  4664.             if (s->vol > 64)
  4665.                 s->vol = 64;
  4666.  
  4667.             s->relTon = CLAMP(s->relTon, -48, 71);
  4668.         }
  4669.     }
  4670.  
  4671.     return true;
  4672. }
  4673.  
  4674. // adds wrapped samples after loop/end (for branchless mixer interpolation)
  4675. static void fixSample(sampleTyp *s)
  4676. {
  4677.     uint8_t loopType;
  4678.     int16_t *ptr16;
  4679.     int32_t loopStart, loopLen, loopEnd, len;
  4680.  
  4681.     if (s->pek == NULL)
  4682.         return; // empty sample
  4683.  
  4684.     loopType = s->typ & 3;
  4685.     if (loopType == 0)
  4686.     {
  4687.         len = s->len;
  4688.  
  4689.         // no loop (don't mess with fixed, fixSpar of fixedPos)
  4690.  
  4691.         if (s->typ & 16)
  4692.         {
  4693.             if (len < 2)
  4694.                 return;
  4695.  
  4696.             len  /= 2;
  4697.             ptr16 = (int16_t *)(s->pek);
  4698.  
  4699.             ptr16[len+0] = 0;
  4700.             ptr16[len+1] = 0;
  4701.         }
  4702.         else
  4703.         {
  4704.             if (len < 1)
  4705.                 return;
  4706.  
  4707.             s->pek[len+0] = 0;
  4708.             s->pek[len+1] = 0;
  4709.         }
  4710.  
  4711.         return;
  4712.     }
  4713.     else if (loopType == 1)
  4714.     {
  4715.         // forward loop
  4716.  
  4717.         if (s->typ & 16)
  4718.         {
  4719.             // 16-bit sample
  4720.  
  4721.             if (s->repL < 2)
  4722.                 return;
  4723.  
  4724.             loopStart = s->repS / 2;
  4725.             loopEnd = (s->repS + s->repL) / 2;
  4726.             ptr16 = (int16_t *)s->pek;
  4727.  
  4728.             ptr16[loopEnd+0] = ptr16[loopStart+0];
  4729.             ptr16[loopEnd+1] = ptr16[loopStart+1];
  4730.         }
  4731.         else
  4732.         {
  4733.             // 8-bit sample
  4734.  
  4735.             if (s->repL < 1)
  4736.                 return;
  4737.  
  4738.             loopStart = s->repS;
  4739.             loopEnd = s->repS + s->repL;
  4740.  
  4741.             s->pek[loopEnd+0] = s->pek[loopStart+0];
  4742.             s->pek[loopEnd+1] = s->pek[loopStart+1];
  4743.         }
  4744.     }
  4745.     else
  4746.     {
  4747.         // pingpong loop
  4748.  
  4749.         if (s->typ & 16)
  4750.         {
  4751.             // 16-bit sample
  4752.  
  4753.             if (s->repL < 2)
  4754.                 return;
  4755.  
  4756.             loopStart = s->repS / 2;
  4757.             loopLen = s->repL / 2;
  4758.             loopEnd = loopStart + loopLen;
  4759.             ptr16 = (int16_t *)s->pek;
  4760.  
  4761.             ptr16[loopEnd+0] = ptr16[loopEnd-1];
  4762.             if (loopLen >= 2)
  4763.                 ptr16[loopEnd+1] = ptr16[loopEnd-2];
  4764.             else
  4765.                 ptr16[loopEnd+1] = ptr16[loopStart];
  4766.         }
  4767.         else
  4768.         {
  4769.             // 8-bit sample
  4770.  
  4771.             if (s->repL < 1)
  4772.                 return;
  4773.  
  4774.             loopStart = s->repS;
  4775.             loopLen = s->repL;
  4776.             loopEnd = loopStart + loopLen;
  4777.  
  4778.             s->pek[loopEnd+0] = s->pek[loopEnd-1];
  4779.             if (loopLen >= 2)
  4780.                 s->pek[loopEnd+1] = s->pek[loopEnd-2];
  4781.             else
  4782.                 s->pek[loopEnd+1] = s->pek[loopStart];
  4783.         }
  4784.     }
  4785. }
  4786.  
  4787. static void checkSampleRepeat(sampleTyp *s)
  4788. {
  4789.     if (s->repS < 0) s->repS = 0;
  4790.     if (s->repL < 0) s->repL = 0;
  4791.     if (s->repS > s->len) s->repS = s->len;
  4792.     if (s->repS+s->repL > s->len) s->repL = s->len - s->repS;
  4793.     if (s->repL == 0) s->typ &= ~3; // non-FT2 fix: force loop off if looplen is 0
  4794. }
  4795.  
  4796. static bool loadInstrSample(MEM *f, uint16_t i)
  4797. {
  4798.     int8_t *newPtr;
  4799.     int32_t l;
  4800.     sampleTyp *s;
  4801.  
  4802.     if (instr[i] == NULL)
  4803.         return true; // empty instrument
  4804.  
  4805.     for (uint16_t j = 0; j < instr[i]->antSamp; j++)
  4806.     {
  4807.         s = &instr[i]->samp[j];
  4808.  
  4809.         // if a sample has both forward loop and pingpong loop set, make it pingpong loop only (FT2 behavior)
  4810.         if ((s->typ & 3) == 3)
  4811.             s->typ &= 0xFE;
  4812.  
  4813.         l = s->len;
  4814.         if (l <= 0)
  4815.         {
  4816.             s->pek = NULL;
  4817.             s->len = 0;
  4818.             s->repL = 0;
  4819.             s->repS = 0;
  4820.  
  4821.             if (s->typ & 32)
  4822.                 s->typ &= ~32; // remove stereo flag
  4823.         }
  4824.         else
  4825.         {
  4826.             s->pek = (int8_t *)malloc(l + LOOP_FIX_LEN);
  4827.             if (s->pek == NULL)
  4828.                 return false;
  4829.  
  4830.             mread(s->pek, l, 1, f);
  4831.             delta2Samp(s->pek, l, s->typ);
  4832.  
  4833.             if (s->typ & 32) // stereo sample - already downmixed to mono in delta2samp()
  4834.             {
  4835.                 s->typ &= ~32; // remove stereo flag
  4836.  
  4837.                 s->len /= 2;
  4838.                 s->repL /= 2;
  4839.                 s->repS /= 2;
  4840.  
  4841.                 newPtr = (int8_t *)realloc(s->pek, s->len + LOOP_FIX_LEN);
  4842.                 if (newPtr != NULL)
  4843.                     s->pek = newPtr;
  4844.             }
  4845.         }
  4846.  
  4847.         // NON-FT2 FIX: align to 2-byte if 16-bit sample
  4848.         if (s->typ & 16)
  4849.         {
  4850.             s->repL &= 0xFFFFFFFE;
  4851.             s->repS &= 0xFFFFFFFE;
  4852.             s->len &= 0xFFFFFFFE;
  4853.         }
  4854.  
  4855.         checkSampleRepeat(s);
  4856.         fixSample(s);
  4857.     }
  4858.  
  4859.     return true;
  4860. }
  4861.  
  4862. static void unpackPatt(uint8_t *dst, uint16_t inn, uint16_t len, uint8_t antChn)
  4863. {
  4864.     uint8_t note, data, *src;
  4865.     int32_t srcEnd, srcIdx;
  4866.  
  4867.     if (dst == NULL)
  4868.         return;
  4869.  
  4870.     src = dst + inn;
  4871.     srcEnd = len * (sizeof (tonTyp) * antChn);
  4872.     srcIdx = 0;
  4873.  
  4874.     for (int32_t i = 0; i < len; i++)
  4875.     {
  4876.         for (int32_t j = 0; j < antChn; j++)
  4877.         {
  4878.             if (srcIdx >= srcEnd)
  4879.                 return; // error!
  4880.  
  4881.             note = *src++;
  4882.             if (note & 0x80)
  4883.             {
  4884.                 data = 0; if (note & 0x01) data = *src++; *dst++ = data;
  4885.                 data = 0; if (note & 0x02) data = *src++; *dst++ = data;
  4886.                 data = 0; if (note & 0x04) data = *src++; *dst++ = data;
  4887.                 data = 0; if (note & 0x08) data = *src++; *dst++ = data;
  4888.                 data = 0; if (note & 0x10) data = *src++; *dst++ = data;
  4889.             }
  4890.             else
  4891.             {
  4892.                 *dst++ = note;
  4893.                 *dst++ = *src++;
  4894.                 *dst++ = *src++;
  4895.                 *dst++ = *src++;
  4896.                 *dst++ = *src++;
  4897.             }
  4898.  
  4899.             // if note is overflowing (>97), remove it
  4900.             if (*(dst-5) > 97)
  4901.                 *(dst-5) = 0;
  4902.  
  4903.             // non-FT2 security fix: if effect is above 35 (Z), clear effect and parameter
  4904.             if (*(dst-2) > 35)
  4905.             {
  4906.                 *(dst-2) = 0;
  4907.                 *(dst-1) = 0;
  4908.             }
  4909.  
  4910.             srcIdx += sizeof (tonTyp);
  4911.         }
  4912.     }
  4913. }
  4914.  
  4915. static bool patternEmpty(uint16_t nr)
  4916. {
  4917.     uint8_t *scanPtr;
  4918.     uint32_t scanLen;
  4919.  
  4920.     if (patt[nr] == NULL)
  4921.         return true;
  4922.  
  4923.     scanPtr = (uint8_t *)patt[nr];
  4924.     scanLen = pattLens[nr] * (song.antChn * 5);
  4925.  
  4926.     for (uint32_t i = 0; i < scanLen; i++)
  4927.     {
  4928.         if (scanPtr[i] != 0)
  4929.             return false;
  4930.     }
  4931.  
  4932.     return true;
  4933. }
  4934.  
  4935. static bool loadPatterns(MEM *f, uint16_t antPtn)
  4936. {
  4937.     uint8_t tmpLen, *pattPtr;
  4938.     uint16_t a;
  4939.     patternHeaderTyp ph;
  4940.  
  4941.     for (uint16_t i = 0; i < antPtn; i++)
  4942.     {
  4943.         mread(&ph.patternHeaderSize, 4, 1, f);
  4944.         mread(&ph.typ, 1, 1, f);
  4945.  
  4946.         ph.pattLen = 0;
  4947.         if (song.ver == 0x0102)
  4948.         {
  4949.             mread(&tmpLen, 1, 1, f);
  4950.             mread(&ph.dataLen, 2, 1, f);
  4951.             ph.pattLen = (uint16_t)tmpLen + 1; // +1 in v1.02
  4952.  
  4953.             if (ph.patternHeaderSize > 8)
  4954.                 mseek(f, ph.patternHeaderSize - 8, SEEK_CUR);
  4955.         }
  4956.         else
  4957.         {
  4958.             mread(&ph.pattLen, 2, 1, f);
  4959.             mread(&ph.dataLen, 2, 1, f);
  4960.  
  4961.             if (ph.patternHeaderSize > 9)
  4962.                 mseek(f, ph.patternHeaderSize - 9, SEEK_CUR);
  4963.         }
  4964.  
  4965.         if (meof(f))
  4966.         {
  4967.             mclose(&f);
  4968.             return false;
  4969.         }
  4970.  
  4971.         pattLens[i] = ph.pattLen;
  4972.         if (ph.dataLen)
  4973.         {
  4974.             a = ph.pattLen * (sizeof (tonTyp) * song.antChn);
  4975.  
  4976.             patt[i] = (tonTyp *)malloc(a + 16); // + 16 = a little extra for safety
  4977.             if (patt[i] == NULL)
  4978.                 return false;
  4979.  
  4980.             pattPtr = (uint8_t *)patt[i];
  4981.  
  4982.             memset(pattPtr, 0, a);
  4983.             mread(&pattPtr[a - ph.dataLen], 1, ph.dataLen, f);
  4984.             unpackPatt(pattPtr, a - ph.dataLen, ph.pattLen, song.antChn);
  4985.         }
  4986.  
  4987.         if (patternEmpty(i))
  4988.         {
  4989.             if (patt[i] != NULL)
  4990.             {
  4991.                 free(patt[i]);
  4992.                 patt[i] = NULL;
  4993.             }
  4994.  
  4995.             pattLens[i] = 64;
  4996.         }
  4997.  
  4998.         if (pattLens[i] > 256)
  4999.             pattLens[i] = 64;
  5000.     }
  5001.  
  5002.     return true;
  5003. }
  5004.  
  5005. static bool loadMusicMOD(MEM *f, uint32_t fileLength)
  5006. {
  5007.     uint8_t bytes[4];
  5008.     bool modIsUST, modIsFEST, modIsNT;
  5009.     int16_t i, j, k, ai;
  5010.     uint16_t a, b, period, ciaPeriod;
  5011.     tonTyp *ton;
  5012.     sampleTyp *s;
  5013.     songMOD31HeaderTyp h_MOD31;
  5014.     songMOD15HeaderTyp h_MOD15;
  5015.  
  5016.     const char modSig[32][5] =
  5017.     {
  5018.         "1CHN", "2CHN", "3CHN", "4CHN", "5CHN", "6CHN", "7CHN", "8CHN",
  5019.         "9CHN", "10CH", "11CH", "12CH", "13CH", "14CH", "15CH", "16CH",
  5020.         "17CH", "18CH", "19CH", "20CH", "21CH", "22CH", "23CH", "24CH",
  5021.         "25CH", "26CH", "27CH", "28CH", "29CH", "30CH", "31CH", "32CH"
  5022.     };
  5023.  
  5024.     // start loading MOD
  5025.  
  5026.     if (fileLength < 1596 || fileLength > 20842494) // minimum and maximum possible size for an FT2 .mod
  5027.     {
  5028.         mclose(&f);
  5029.         return false;
  5030.     }
  5031.  
  5032.     mseek(f, 0, SEEK_SET);
  5033.  
  5034.     if (mread(&h_MOD31, sizeof (h_MOD31), 1, f) != 1)
  5035.     {
  5036.         mclose(&f);
  5037.         return false;
  5038.     }
  5039.  
  5040.     modIsFEST = false;
  5041.     modIsNT = false;
  5042.     modIsUST = false;
  5043.  
  5044.     if (!strncmp(h_MOD31.sig, "N.T.", 4))
  5045.     {
  5046.         j = 4;
  5047.         modIsNT = true;
  5048.     }
  5049.     else if (!strncmp(h_MOD31.sig, "FEST", 4) || !strncmp(h_MOD31.sig, "M&K!", 4))
  5050.     {
  5051.         modIsFEST = true;
  5052.         modIsNT   = true;
  5053.         j = 4;
  5054.     }
  5055.     else if (!strncmp(h_MOD31.sig, "M!K!", 4) || !strncmp(h_MOD31.sig, "M.K.", 4) || !strncmp(h_MOD31.sig, "FLT4", 4))
  5056.     {
  5057.         j = 4;
  5058.     }
  5059.     else if (!strncmp(h_MOD31.sig, "OCTA", 4) || !strncmp(h_MOD31.sig, "FLT8", 4) || !strncmp(h_MOD31.sig, "CD81", 4))
  5060.     {
  5061.         j = 8;
  5062.     }
  5063.     else
  5064.     {
  5065.         j = 0;
  5066.         for (i = 0; i < 32; i++)
  5067.         {
  5068.             if (!strncmp(h_MOD31.sig, modSig[i], 4))
  5069.             {
  5070.                 j = i + 1;
  5071.                 break;
  5072.             }
  5073.             else if (j == 31)
  5074.             {
  5075.                 j = -1; // ID not recignized
  5076.             }
  5077.         }
  5078.     }
  5079.  
  5080.     // unsupported MOD
  5081.     if (j == -1)
  5082.     {
  5083.         mclose(&f);
  5084.         return false;
  5085.     }
  5086.  
  5087.     if (j > 0)
  5088.     {
  5089.         modIsUST = false;
  5090.         if (fileLength < sizeof (h_MOD31))
  5091.         {
  5092.             mclose(&f);
  5093.             return false;
  5094.         }
  5095.  
  5096.         song.antChn = (uint8_t)j;
  5097.         song.len = h_MOD31.len;
  5098.         song.repS = h_MOD31.repS;
  5099.         memcpy(song.songTab, h_MOD31.songTab, 128);
  5100.         ai = 31;
  5101.     }
  5102.     else
  5103.     {
  5104.         modIsUST = true;
  5105.         if (fileLength < sizeof (h_MOD15))
  5106.         {
  5107.             mclose(&f);
  5108.             return false;
  5109.         }
  5110.  
  5111.         mseek(f, 0, SEEK_SET);
  5112.         if (mread(&h_MOD15, 1, sizeof (h_MOD15), f) != sizeof (h_MOD15))
  5113.         {
  5114.             mclose(&f);
  5115.             return false;
  5116.         }
  5117.  
  5118.         song.antChn = 4;
  5119.         song.len = h_MOD15.len;
  5120.         song.repS = h_MOD15.repS;
  5121.         memcpy(song.songTab, h_MOD15.songTab, 128);
  5122.         ai = 15;
  5123.     }
  5124.  
  5125.     if (song.antChn == 0 || song.len < 1)
  5126.     {
  5127.         mclose(&f);
  5128.         return false;
  5129.     }
  5130.  
  5131.     if (!strncmp(h_MOD31.sig, "M.K.", 4) && song.len == 129)
  5132.         song.len = 127; // fixes a specific copy of beatwave.mod by Sidewinder
  5133.  
  5134.     if (song.len > 128 || (modIsUST && (song.repS == 0 || song.repS > 220)))
  5135.     {
  5136.         mclose(&f);
  5137.         return false;
  5138.     }
  5139.  
  5140.     // trim off spaces at end of name
  5141.     for (i = 19; i >= 0; i--)
  5142.     {
  5143.         if (h_MOD31.name[i] == ' ' || h_MOD31.name[i] == 0x1A)
  5144.             h_MOD31.name[i] = '\0';
  5145.         else
  5146.             break;
  5147.     }
  5148.  
  5149.     memcpy(song.name, h_MOD31.name, 20);
  5150.     song.name[20] = '\0';
  5151.  
  5152.     b = 0;
  5153.     for (a = 0; a < 128; a++)
  5154.     {
  5155.         if (song.songTab[a] > b)
  5156.             b = song.songTab[a];
  5157.     }
  5158.  
  5159.     for (a = 0; a <= b; a++)
  5160.     {
  5161.         patt[a] = (tonTyp *)calloc(64 * song.antChn, sizeof (tonTyp));
  5162.         if (patt[a] == NULL)
  5163.         {
  5164.             freeAllPatterns();
  5165.             mclose(&f);
  5166.             return false;
  5167.         }
  5168.  
  5169.         pattLens[a] = 64;
  5170.         for (j = 0; j < 64; j++)
  5171.         {
  5172.             for (k = 0; k < song.antChn; k++)
  5173.             {
  5174.                 ton = &patt[a][(j * song.antChn) + k];
  5175.                 mread(bytes, 1, 4, f);
  5176.  
  5177.                 // period to note
  5178.                 period = ((bytes[0] & 0x0F) << 8) | bytes[1];
  5179.                 for (i = 0; i < 8*12; i++)
  5180.                 {
  5181.                     if (period >= amigaPeriod[i])
  5182.                     {
  5183.                         ton->ton = (uint8_t)i + 1;
  5184.                         break;
  5185.                     }
  5186.                 }
  5187.  
  5188.                 ton->instr = (bytes[0] & 0xF0) | (bytes[2] >> 4);
  5189.                 ton->effTyp = bytes[2] & 0x0F;
  5190.                 ton->eff = bytes[3];
  5191.  
  5192.                 if (ton->effTyp == 0xC)
  5193.                 {
  5194.                     if (ton->eff > 64)
  5195.                         ton->eff = 64;
  5196.                 }
  5197.                 else if (ton->effTyp == 0x1)
  5198.                 {
  5199.                     if (ton->eff == 0)
  5200.                         ton->effTyp = 0;
  5201.                 }
  5202.                 else if (ton->effTyp == 0x2)
  5203.                 {
  5204.                     if (ton->eff == 0)
  5205.                         ton->effTyp = 0;
  5206.                 }
  5207.                 else if (ton->effTyp == 0x5)
  5208.                 {
  5209.                     if (ton->eff == 0)
  5210.                         ton->effTyp = 0x3;
  5211.                 }
  5212.                 else if (ton->effTyp == 0x6)
  5213.                 {
  5214.                     if (ton->eff == 0)
  5215.                         ton->effTyp = 0x4;
  5216.                 }
  5217.                 else if (ton->effTyp == 0xA)
  5218.                 {
  5219.                     if (ton->eff == 0)
  5220.                         ton->effTyp = 0;
  5221.                 }
  5222.                 else if (ton->effTyp == 0xE)
  5223.                 {
  5224.                     // check if certain E commands are empty
  5225.                     if (ton->eff == 0x10 || ton->eff == 0x20 || ton->eff == 0xA0 || ton->eff == 0xB0)
  5226.                     {
  5227.                         ton->effTyp = 0;
  5228.                         ton->eff = 0;
  5229.                     }
  5230.                 }
  5231.  
  5232.                 if (modIsUST)
  5233.                 {
  5234.                     if (ton->effTyp == 0x01)
  5235.                     {
  5236.                         // arpeggio
  5237.                         ton->effTyp = 0x00;
  5238.                     }
  5239.                     else if (ton->effTyp == 0x02)
  5240.                     {
  5241.                         // pitch slide
  5242.                         if (ton->eff & 0xF0)
  5243.                         {
  5244.                             ton->effTyp = 0x02;
  5245.                             ton->eff >>= 4;
  5246.                         }
  5247.                         else if (ton->eff & 0x0F)
  5248.                         {
  5249.                             ton->effTyp = 0x01;
  5250.                         }
  5251.                     }
  5252.  
  5253.                     // I don't remember why I did this...
  5254.                     if (ton->effTyp == 0x0D && ton->eff > 0)
  5255.                         ton->effTyp = 0x0A;
  5256.                 }
  5257.  
  5258.                 if (modIsNT && ton->effTyp == 0x0D)
  5259.                     ton->eff = 0;
  5260.             }
  5261.         }
  5262.  
  5263.         if (patternEmpty(a))
  5264.             pattLens[a] = 64;
  5265.     }
  5266.  
  5267.     for (a = 0; a < ai; a++)
  5268.     {
  5269.         if (!allocateInstr(1 + a))
  5270.         {
  5271.             freeAllPatterns();
  5272.             freeAllInstr();
  5273.             mclose(&f);
  5274.             return false;
  5275.         }
  5276.  
  5277.         if (h_MOD31.instr[a].len > 0)
  5278.         {
  5279.             s = &instr[1 + a]->samp[0];
  5280.  
  5281.             s->len = 2 * SWAP16(h_MOD31.instr[a].len);
  5282.  
  5283.             s->pek = (int8_t *)malloc(s->len + LOOP_FIX_LEN);
  5284.             if (s->pek == NULL)
  5285.             {
  5286.                 freeAllPatterns();
  5287.                 freeAllInstr();
  5288.                 mclose(&f);
  5289.                 return false;
  5290.             }
  5291.  
  5292.             if (modIsFEST)
  5293.                 h_MOD31.instr[a].fine = (32 - (h_MOD31.instr[a].fine & 0x1F)) >> 1;
  5294.  
  5295.             if (!modIsUST)
  5296.                 s->fine = 8 * ((2 * ((h_MOD31.instr[a].fine & 0x0F) ^ 8)) - 16);
  5297.             else
  5298.                 s->fine = 0;
  5299.  
  5300.             s->pan = 128;
  5301.  
  5302.             s->vol = h_MOD31.instr[a].vol;
  5303.             if (s->vol > 64) s->vol = 64;
  5304.  
  5305.             s->repS = 2 * SWAP16(h_MOD31.instr[a].repS);
  5306.  
  5307.             if (modIsUST)
  5308.                 s->repS /= 2;
  5309.  
  5310.             s->repL = 2 * SWAP16(h_MOD31.instr[a].repL);
  5311.  
  5312.             if (s->repL <= 2)
  5313.             {
  5314.                 s->repS = 0;
  5315.                 s->repL = 0;
  5316.             }
  5317.  
  5318.             if (s->repS+s->repL > s->len)
  5319.             {
  5320.                 if (s->repS >= s->len)
  5321.                 {
  5322.                     s->repS = 0;
  5323.                     s->repL = 0;
  5324.                 }
  5325.                 else
  5326.                 {
  5327.                     s->repL = s->len - s->repS;
  5328.                 }
  5329.             }
  5330.  
  5331.             if (s->repL > 2)
  5332.                 s->typ = 1;
  5333.             else
  5334.                 s->typ = 0;
  5335.  
  5336.             if (modIsUST && (s->repS > 2 && s->repS < s->len))
  5337.             {
  5338.                 s->len -= s->repS;
  5339.                 mseek(f, s->repS, SEEK_CUR);
  5340.                 s->repS = 0;
  5341.             }
  5342.  
  5343.             mread(s->pek, 1, s->len, f);
  5344.             fixSample(s);
  5345.         }
  5346.     }
  5347.  
  5348.     song.speed = 125;
  5349.  
  5350.     if (modIsUST)
  5351.     {
  5352.         // repS is initialBPM in UST MODs
  5353.  
  5354.         if (song.repS != 120) // 120 is a special case and means 50Hz (125BPM)
  5355.         {
  5356.             if (song.repS > 239)
  5357.                 song.repS = 239;
  5358.  
  5359.             // convert UST tempo to BPM
  5360.  
  5361.             // convert UST tempo to BPM
  5362.             const double dPALAmigaCiaClk = 709379.0;
  5363.             ciaPeriod = (240 - song.repS) * 122;
  5364.             song.speed = (uint16_t)round((dPALAmigaCiaClk / ciaPeriod) * (125.0 / 50.0));
  5365.         }
  5366.  
  5367.         song.repS = 0;
  5368.     }
  5369.     else if (song.repS >= song.len)
  5370.     {
  5371.         song.repS = 0;
  5372.     }
  5373.  
  5374.     mclose(&f);
  5375.  
  5376.     song.tempo = 6;
  5377.  
  5378.     note2Period = amigaPeriods;
  5379.  
  5380.     stopVoices();
  5381.     setPos(0, 0);
  5382.  
  5383.     // instr 0 is a placeholder for empty instruments
  5384.     allocateInstr(0);
  5385.     instr[0]->samp[0].vol = 0;
  5386.  
  5387.     moduleLoaded = true;
  5388.     return true;
  5389. }
  5390.  
  5391. static bool loadMusic(const uint8_t *moduleData, uint32_t dataLength)
  5392. {
  5393.     uint16_t i;
  5394.     songHeaderTyp h;
  5395.     MEM *f;
  5396.  
  5397.     freeAllInstr();
  5398.     freeAllPatterns();
  5399.     memset(&song, 0, sizeof (song));
  5400.  
  5401.     moduleLoaded = false;
  5402.  
  5403.     linearFrqTab = 0;
  5404.  
  5405.     f = mopen(moduleData, dataLength);
  5406.     if (f == NULL) return false;
  5407.  
  5408.     // start loading
  5409.     mread(&h, sizeof (h), 1, f);
  5410.  
  5411.     if (memcmp(h.sig, "Extended Module: ", 17) != 0)
  5412.         return loadMusicMOD(f, dataLength);
  5413.  
  5414.     if (h.ver < 0x0102 || h.ver > 0x104)
  5415.     {
  5416.         mclose(&f);
  5417.         return false;
  5418.     }
  5419.  
  5420.     if (h.len > 256 || h.antPtn > 256 || h.antChn == 0 || h.antChn > MAX_VOICES || h.antInstrs > 128)
  5421.     {
  5422.         mclose(&f);
  5423.         return false;
  5424.     }
  5425.  
  5426.     mseek(f, 60 + h.headerSize, SEEK_SET);
  5427.     if (meof(f))
  5428.     {
  5429.         mclose(&f);
  5430.         return false;
  5431.     }
  5432.  
  5433.     song.len = h.len;
  5434.     song.repS = h.repS;
  5435.     song.antChn = (uint8_t)h.antChn;
  5436.     song.speed = h.defSpeed ? h.defSpeed : 125;
  5437.     song.tempo = h.defTempo ? h.defTempo : 6;
  5438.     song.ver = h.ver;
  5439.     linearFrqTab = h.flags & 1;
  5440.  
  5441.     song.speed = CLAMP(song.speed, 32, 255);
  5442.     if (song.tempo > 31)
  5443.         song.tempo = 31;
  5444.  
  5445.     if (song.globVol > 64)
  5446.         song.globVol = 64;
  5447.  
  5448.     if (song.len == 0)
  5449.         song.len = 1; // songTmp.songTab is already empty
  5450.     else
  5451.         memcpy(song.songTab, h.songTab, song.len);
  5452.  
  5453.     if (song.ver < 0x0104)
  5454.     {
  5455.         // old FT2 format
  5456.  
  5457.         for (i = 1; i <= h.antInstrs; i++)
  5458.         {
  5459.             if (!loadInstrHeader(f, i))
  5460.             {
  5461.                 freeAllInstr();
  5462.                 mclose(&f);
  5463.                 return false;
  5464.             }
  5465.         }
  5466.  
  5467.         if (!loadPatterns(f, h.antPtn))
  5468.         {
  5469.             freeAllInstr();
  5470.             mclose(&f);
  5471.             return false;
  5472.         }
  5473.  
  5474.         for (i = 1; i <= h.antInstrs; i++)
  5475.         {
  5476.             if (!loadInstrSample(f, i))
  5477.             {
  5478.                 freeAllInstr();
  5479.                 mclose(&f);
  5480.                 return false;
  5481.             }
  5482.         }
  5483.     }
  5484.     else
  5485.     {
  5486.         // current FT2 format
  5487.  
  5488.         if (!loadPatterns(f, h.antPtn))
  5489.         {
  5490.             mclose(&f);
  5491.             return false;
  5492.         }
  5493.  
  5494.         for (i = 1; i <= h.antInstrs; i++)
  5495.         {
  5496.             if (!loadInstrHeader(f, i))
  5497.             {
  5498.                 freeAllInstr();
  5499.                 mclose(&f);
  5500.                 return false;
  5501.             }
  5502.  
  5503.             if (!loadInstrSample(f, i))
  5504.             {
  5505.                 freeAllInstr();
  5506.                 mclose(&f);
  5507.                 return false;
  5508.             }
  5509.         }
  5510.     }
  5511.  
  5512.     mclose(&f);
  5513.  
  5514.     note2Period = linearFrqTab ? linearPeriods : amigaPeriods;
  5515.  
  5516.     if (song.repS > song.len)
  5517.         song.repS = 0;
  5518.  
  5519.     setSpeed(song.speed);
  5520.     stopVoices();
  5521.     setPos(0, 0);
  5522.  
  5523.     // instr 0 is a placeholder for empty instruments
  5524.     allocateInstr(0);
  5525.     instr[0]->samp[0].vol = 0;
  5526.  
  5527.     moduleLoaded = true;
  5528.     return true;
  5529. }
  5530.  
  5531. void ft2play_SetMasterVol(uint16_t vol)
  5532. {
  5533.     if (vol > 256)
  5534.         vol = 256;
  5535.  
  5536.     masterVol = vol;
  5537. }
  5538.  
  5539. void ft2play_SetAmp(uint8_t ampFactor)
  5540. {
  5541.     ampFactor = CLAMP(ampFactor, 1, 32);
  5542.     if (amp != ampFactor)
  5543.     {
  5544.         amp = ampFactor;
  5545.  
  5546.         // make all channels update volume because of amp change
  5547.         for (uint32_t i = 0; i < song.antChn; i++)
  5548.             stm[i].status |= IS_Vol;
  5549.     }
  5550. }
  5551.  
  5552. void ft2play_SetInterpolation(bool flag)
  5553. {
  5554.     interpolationFlag = flag;
  5555.     stopVoices();
  5556. }
  5557.  
  5558. void ft2play_SetVolumeRamping(bool flag)
  5559. {
  5560.     volumeRampingFlag = flag;
  5561.     stopVoices();
  5562. }
  5563.  
  5564. char *ft2play_GetSongName(void)
  5565. {
  5566.     return song.name;
  5567. }
  5568.  
  5569. static void mixAudio(int16_t *stream, int32_t sampleBlockLength)
  5570. {
  5571.     int32_t i, out32;
  5572.     voice_t *v;
  5573.  
  5574.     if (musicPaused)
  5575.     {
  5576.         memset(stream, 0, sampleBlockLength * sizeof (int16_t) * 2);
  5577.         return;
  5578.     }
  5579.  
  5580.     memset(mixBufferL, 0, sampleBlockLength * sizeof (int32_t));
  5581.     memset(mixBufferR, 0, sampleBlockLength * sizeof (int32_t));
  5582.  
  5583.     // mix channels
  5584.     for (i = 0; i < song.antChn; i++)
  5585.     {
  5586.         // mix normal voice
  5587.         v = &voice[i];
  5588.  
  5589.         // call the mixing routine currently set for the voice
  5590.         if (v->mixRoutine != NULL)
  5591.             v->mixRoutine(v, sampleBlockLength);
  5592.  
  5593.         // mix fade-out voice
  5594.         v = &voice[MAX_VOICES + i];
  5595.  
  5596.         // call the mixing routine currently set for the voice
  5597.         if (v->mixRoutine != NULL)
  5598.             v->mixRoutine(v, sampleBlockLength);
  5599.     }
  5600.  
  5601.     if (masterVol == 256) // max master volume
  5602.     {
  5603.         for (i = 0; i < sampleBlockLength; i++)
  5604.         {
  5605.             out32 = mixBufferL[i] >> 8;
  5606.             CLAMP16(out32);
  5607.             *stream++ = (int16_t)out32;
  5608.  
  5609.             out32 = mixBufferR[i] >> 8;
  5610.             CLAMP16(out32);
  5611.             *stream++ = (int16_t)out32;
  5612.         }
  5613.     }
  5614.     else
  5615.     {
  5616.         for (i = 0; i < sampleBlockLength; i++)
  5617.         {
  5618.             out32 = ((mixBufferL[i] >> 8) * masterVol) >> 8;
  5619.             CLAMP16(out32);
  5620.             *stream++ = (int16_t)out32;
  5621.  
  5622.             out32 = ((mixBufferR[i] >> 8) * masterVol) >> 8;
  5623.             CLAMP16(out32);
  5624.             *stream++ = (int16_t)out32;
  5625.         }
  5626.     }
  5627. }
  5628.  
  5629. static void ft2play_FillAudioBuffer(int16_t *buffer, uint16_t samples)
  5630. {
  5631.     int32_t a, b;
  5632.  
  5633.     a = samples; // must NOT exceed 65535!
  5634.     while (a > 0)
  5635.     {
  5636.         if (pmpLeft == 0)
  5637.         {
  5638.             // new replayer tick
  5639.             if (!musicPaused)
  5640.             {
  5641.                 if (volumeRampingFlag)
  5642.                     mix_SaveIPVolumes();
  5643.  
  5644.                 mainPlayer();
  5645.                 mix_UpdateChannelVolPanFrq();
  5646.             }
  5647.  
  5648.             pmpLeft = speedVal;
  5649.         }
  5650.  
  5651.         b = a;
  5652.         if (b > pmpLeft)
  5653.             b = pmpLeft;
  5654.  
  5655.         mixAudio(buffer, b);
  5656.         buffer += (uint32_t)b * 2;
  5657.  
  5658.         a -= b;
  5659.         pmpLeft -= b;
  5660.     }
  5661.  
  5662.     sampleCounter += samples;
  5663. }
  5664.  
  5665. void ft2play_Close(void)
  5666. {
  5667.     closeMixer();
  5668.  
  5669.     freeAllInstr();
  5670.     freeAllPatterns();
  5671.  
  5672.     if (mixBufferL != NULL)
  5673.     {
  5674.         free(mixBufferL);
  5675.         mixBufferL = NULL;
  5676.     }
  5677.  
  5678.     if (mixBufferR != NULL)
  5679.     {
  5680.         free(mixBufferR);
  5681.         mixBufferR = NULL;
  5682.     }
  5683.  
  5684.     if (logTab != NULL)
  5685.     {
  5686.         free(logTab);
  5687.         logTab = NULL;
  5688.     }
  5689.  
  5690.     if (vibSineTab != NULL)
  5691.     {
  5692.         free(vibSineTab);
  5693.         vibSineTab = NULL;
  5694.     }
  5695.  
  5696.     if (amigaPeriods != NULL)
  5697.     {
  5698.         free(amigaPeriods);
  5699.         amigaPeriods = NULL;
  5700.     }
  5701.  
  5702.     if (linearPeriods != NULL)
  5703.     {
  5704.         free(linearPeriods);
  5705.         linearPeriods = NULL;
  5706.     }
  5707. }
  5708.  
  5709. void ft2play_PauseSong(bool flag)
  5710. {
  5711.     musicPaused = flag;
  5712. }
  5713.  
  5714. void ft2play_TogglePause(void)
  5715. {
  5716.     musicPaused ^= 1;
  5717. }
  5718.  
  5719. uint32_t ft2play_GetMixerTicks(void)
  5720. {
  5721.     if (realReplayRate < 1000)
  5722.         return 0;
  5723.  
  5724.     return sampleCounter / (realReplayRate / 1000);
  5725. }
  5726.  
  5727. bool ft2play_PlaySong(const uint8_t *moduleData, uint32_t dataLength, bool useInterpolationFlag, bool useVolumeRampingFlag, uint32_t audioFreq)
  5728. {
  5729.     int16_t noteVal;
  5730.     uint16_t i, k;
  5731.  
  5732.     if (audioFreq == 0)
  5733.         audioFreq = 44100;
  5734.  
  5735.     audioFreq = CLAMP(audioFreq, 11025, 96000);
  5736.  
  5737.     musicPaused = true;
  5738.  
  5739.     ft2play_Close();
  5740.     memset(song.name, 0, sizeof (song.name));
  5741.  
  5742.     sampleCounter = 0;
  5743.  
  5744.     // initialize replayer and mixer
  5745.  
  5746.     mixBufferL = (int32_t *)malloc(MIX_BUF_SAMPLES * sizeof (int32_t));
  5747.     mixBufferR = (int32_t *)malloc(MIX_BUF_SAMPLES * sizeof (int32_t));
  5748.  
  5749.     if (mixBufferL == NULL || mixBufferR == NULL)
  5750.     {
  5751.         ft2play_Close();
  5752.         return false;
  5753.     }
  5754.  
  5755.     // allocate memory for pointers
  5756.  
  5757.     if (linearPeriods == NULL)
  5758.         linearPeriods = (int16_t *)malloc(sizeof (int16_t) * ((12 * 10 * 16) + 16));
  5759.  
  5760.     if (amigaPeriods == NULL)
  5761.         amigaPeriods = (int16_t *)malloc(sizeof (int16_t) * ((12 * 10 * 16) + 16));
  5762.  
  5763.     if (vibSineTab == NULL)
  5764.         vibSineTab = (int8_t *)malloc(256);
  5765.  
  5766.     if (logTab == NULL)
  5767.         logTab = (uint32_t *)malloc(sizeof (uint32_t) * 768);
  5768.  
  5769.     if (linearPeriods == NULL || amigaPeriods == NULL || vibSineTab == NULL || logTab == NULL)
  5770.     {
  5771.         ft2play_Close();
  5772.         return false;
  5773.     }
  5774.  
  5775.     // generate tables, bit-exact to original FT2
  5776.  
  5777.     // log table
  5778.     for (i = 0; i < 768; i++)
  5779.         logTab[i] = (uint32_t)round(16777216.0 * exp((i / 768.0) * M_LN2));
  5780.  
  5781.     // linear table
  5782.     for (i = 0; i < (12*10*16)+16; i++)
  5783.         linearPeriods[i] = (((12 * 10 * 16) + 16) * 4) - (i * 4);
  5784.  
  5785.     /* amiga period table
  5786.     ** This has a LUT read overflow in real FT2 making the last 17 values trash. We patch those later. */
  5787.     k = 0;
  5788.     for (i = 0; i < 10; i++)
  5789.     {
  5790.         for (uint16_t j = 0; j < 96; j++)
  5791.         {
  5792.             noteVal = ((amigaFinePeriod[j] * 64) + (-1 + (1 << i))) >> (i + 1);
  5793.  
  5794.             amigaPeriods[k++] = noteVal;
  5795.             amigaPeriods[k++] = noteVal; // copy for interpolation applied later
  5796.         }
  5797.     }
  5798.  
  5799.     // interpolate between points
  5800.     for (i = 0; i < (12*10*8)+7; i++)
  5801.         amigaPeriods[(i * 2) + 1] = (amigaPeriods[i * 2] + amigaPeriods[(i * 2) + 2]) / 2;
  5802.  
  5803.     // the following 17 values are confirmed to be the correct table LUT overflow values in real FT2
  5804.     amigaPeriods[1919] = 22; amigaPeriods[1920] = 16; amigaPeriods[1921] =  8; amigaPeriods[1922] =  0;
  5805.     amigaPeriods[1923] = 16; amigaPeriods[1924] = 32; amigaPeriods[1925] = 24; amigaPeriods[1926] = 16;
  5806.     amigaPeriods[1927] =  8; amigaPeriods[1928] =  0; amigaPeriods[1929] = 16; amigaPeriods[1930] = 32;
  5807.     amigaPeriods[1931] = 24; amigaPeriods[1932] = 16; amigaPeriods[1933] =  8; amigaPeriods[1934] =  0;
  5808.     amigaPeriods[1935] =  0;
  5809.  
  5810.     // generate auto-vibrato table (value-exact to FT2's table)
  5811.     for (i = 0; i < 256; i++)
  5812.         vibSineTab[i] = (int8_t)round(64.0 * sin((-i * (2.0 * M_PI)) / 256.0));
  5813.  
  5814.     if (!loadMusic(moduleData, dataLength))
  5815.     {
  5816.         ft2play_Close();
  5817.         return false;
  5818.     }
  5819.  
  5820.     realReplayRate = audioFreq;
  5821.     soundBufferSize = MIX_BUF_SAMPLES * 4; // samples -> bytes
  5822.     interpolationFlag = useInterpolationFlag ? true : false;
  5823.     volumeRampingFlag = useVolumeRampingFlag ? true : false;
  5824.  
  5825.     // for voice delta calculation
  5826.     frequenceDivFactor = (uint32_t)round(65536.0 * 1712.0 / realReplayRate * 8363.0);
  5827.     frequenceMulFactor = (uint32_t)round(256.0 * 65536.0 / realReplayRate * 8363.0);
  5828.  
  5829.     // for volume ramping
  5830.     quickVolSizeVal = realReplayRate / 200;
  5831.  
  5832.     ft2play_SetAmp(10);
  5833.     ft2play_SetMasterVol(256);
  5834.  
  5835.     stopVoices();
  5836.  
  5837.     song.globVol = 64;
  5838.  
  5839.     if (song.speed == 0)
  5840.         song.speed = 125;
  5841.  
  5842.     setSpeed(song.speed);
  5843.  
  5844.     setPos(0, 0);
  5845.     songPlaying = true;
  5846.  
  5847.     if (!openMixer(realReplayRate))
  5848.     {
  5849.         ft2play_Close();
  5850.         return false;
  5851.     }
  5852.  
  5853.     musicPaused = false;
  5854.     return true;
  5855. }
  5856.  
  5857. static MEM *mopen(const uint8_t *src, uint32_t length)
  5858. {
  5859.     MEM *b;
  5860.  
  5861.     if (src == NULL || length == 0)
  5862.         return NULL;
  5863.  
  5864.     b = (MEM *)malloc(sizeof (MEM));
  5865.     if (b == NULL)
  5866.         return NULL;
  5867.  
  5868.     b->_base = (uint8_t *)src;
  5869.     b->_ptr = (uint8_t *)src;
  5870.     b->_cnt = length;
  5871.     b->_bufsiz = length;
  5872.     b->_eof = false;
  5873.  
  5874.     return b;
  5875. }
  5876.  
  5877. static void mclose(MEM **buf)
  5878. {
  5879.     if (*buf != NULL)
  5880.     {
  5881.         free(*buf);
  5882.         *buf = NULL;
  5883.     }
  5884. }
  5885.  
  5886. static size_t mread(void *buffer, size_t size, size_t count, MEM *buf)
  5887. {
  5888.     size_t wrcnt;
  5889.     int32_t pcnt;
  5890.  
  5891.     if (buf == NULL || buf->_ptr == NULL)
  5892.         return 0;
  5893.  
  5894.     wrcnt = size * count;
  5895.     if (size == 0 || buf->_eof)
  5896.         return 0;
  5897.  
  5898.     pcnt = ((uint32_t)buf->_cnt > wrcnt) ? wrcnt : buf->_cnt;
  5899.     memcpy(buffer, buf->_ptr, pcnt);
  5900.  
  5901.     buf->_cnt -= pcnt;
  5902.     buf->_ptr += pcnt;
  5903.  
  5904.     if (buf->_cnt <= 0)
  5905.     {
  5906.         buf->_ptr = buf->_base + buf->_bufsiz;
  5907.         buf->_cnt = 0;
  5908.         buf->_eof = true;
  5909.     }
  5910.  
  5911.     return pcnt / size;
  5912. }
  5913.  
  5914. static bool meof(MEM *buf)
  5915. {
  5916.     if (buf == NULL)
  5917.         return true;
  5918.  
  5919.     return buf->_eof;
  5920. }
  5921.  
  5922. static void mseek(MEM *buf, int32_t offset, int32_t whence)
  5923. {
  5924.     if (buf == NULL)
  5925.         return;
  5926.  
  5927.     if (buf->_base)
  5928.     {
  5929.         switch (whence)
  5930.         {
  5931.             case SEEK_SET: buf->_ptr = buf->_base + offset; break;
  5932.             case SEEK_CUR: buf->_ptr += offset; break;
  5933.             case SEEK_END: buf->_ptr = buf->_base + buf->_bufsiz + offset; break;
  5934.             default: break;
  5935.         }
  5936.  
  5937.         buf->_eof = false;
  5938.         if (buf->_ptr >= buf->_base+buf->_bufsiz)
  5939.         {
  5940.             buf->_ptr = buf->_base + buf->_bufsiz;
  5941.             buf->_eof = true;
  5942.         }
  5943.  
  5944.         buf->_cnt = (buf->_base + buf->_bufsiz) - buf->_ptr;
  5945.     }
  5946. }
  5947.  
  5948. // the following must be changed if you want to use another audio API than WinMM
  5949.  
  5950. #ifndef WIN32_LEAN_AND_MEAN
  5951. #define WIN32_LEAN_AND_MEAN
  5952. #endif
  5953.  
  5954. #include <windows.h>
  5955. #include <mmsystem.h>
  5956.  
  5957. #define MIX_BUF_NUM 2
  5958.  
  5959. static volatile BOOL audioRunningFlag;
  5960. static uint8_t currBuffer;
  5961. static int16_t *mixBuffer[MIX_BUF_NUM];
  5962. static HANDLE hThread, hAudioSem;
  5963. static WAVEHDR waveBlocks[MIX_BUF_NUM];
  5964. static HWAVEOUT hWave;
  5965.  
  5966. static DWORD WINAPI mixThread(LPVOID lpParam)
  5967. {
  5968.     WAVEHDR *waveBlock;
  5969.  
  5970.     (void)lpParam;
  5971.  
  5972.     SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
  5973.  
  5974.     while (audioRunningFlag)
  5975.     {
  5976.         waveBlock = &waveBlocks[currBuffer];
  5977.         ft2play_FillAudioBuffer((int16_t *)waveBlock->lpData, MIX_BUF_SAMPLES);
  5978.         waveOutWrite(hWave, waveBlock, sizeof (WAVEHDR));
  5979.         currBuffer = (currBuffer + 1) % MIX_BUF_NUM;
  5980.  
  5981.         // wait for buffer fill request
  5982.         WaitForSingleObject(hAudioSem, INFINITE);
  5983.     }
  5984.  
  5985.     return 0;
  5986. }
  5987.  
  5988. static void CALLBACK waveProc(HWAVEOUT hWaveOut, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
  5989. {
  5990.     (void)hWaveOut;
  5991.     (void)uMsg;
  5992.     (void)dwInstance;
  5993.     (void)dwParam1;
  5994.     (void)dwParam2;
  5995.  
  5996.     if (uMsg == WOM_DONE)
  5997.         ReleaseSemaphore(hAudioSem, 1, NULL);
  5998. }
  5999.  
  6000. static void closeMixer(void)
  6001. {
  6002.     int32_t i;
  6003.  
  6004.     audioRunningFlag = false; // make thread end when it's done
  6005.  
  6006.     if (hAudioSem != NULL)
  6007.         ReleaseSemaphore(hAudioSem, 1, NULL);
  6008.  
  6009.     if (hThread != NULL)
  6010.     {
  6011.         WaitForSingleObject(hThread, INFINITE);
  6012.         CloseHandle(hThread);
  6013.         hThread = NULL;
  6014.     }
  6015.  
  6016.     if (hAudioSem != NULL)
  6017.     {
  6018.         CloseHandle(hAudioSem);
  6019.         hAudioSem = NULL;
  6020.     }
  6021.  
  6022.     if (hWave != NULL)
  6023.     {
  6024.         waveOutReset(hWave);
  6025.  
  6026.         for (i = 0; i < MIX_BUF_NUM; i++)
  6027.         {
  6028.             if (waveBlocks[i].dwUser != 0xFFFF)
  6029.                 waveOutUnprepareHeader(hWave, &waveBlocks[i], sizeof (WAVEHDR));
  6030.         }
  6031.  
  6032.         waveOutClose(hWave);
  6033.         hWave = NULL;
  6034.     }
  6035.  
  6036.     for (i = 0; i < MIX_BUF_NUM; i++)
  6037.     {
  6038.         if (mixBuffer[i] != NULL)
  6039.         {
  6040.             free(mixBuffer[i]);
  6041.             mixBuffer[i] = NULL;
  6042.         }
  6043.     }
  6044. }
  6045.  
  6046. static bool openMixer(uint32_t audioFreq)
  6047. {
  6048.     int32_t i;
  6049.     DWORD threadID;
  6050.     WAVEFORMATEX wfx;
  6051.  
  6052.     // don't unprepare headers on error
  6053.     for (i = 0; i < MIX_BUF_NUM; i++)
  6054.         waveBlocks[i].dwUser = 0xFFFF;
  6055.  
  6056.     closeMixer();
  6057.  
  6058.     ZeroMemory(&wfx, sizeof (wfx));
  6059.     wfx.nSamplesPerSec = audioFreq;
  6060.     wfx.wBitsPerSample = 16;
  6061.     wfx.nChannels = 2;
  6062.     wfx.wFormatTag = WAVE_FORMAT_PCM;
  6063.     wfx.nBlockAlign = wfx.nChannels * (wfx.wBitsPerSample / 8);
  6064.     wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
  6065.  
  6066.     pmpLeft = 0;
  6067.     currBuffer = 0;
  6068.  
  6069.     if (waveOutOpen(&hWave, WAVE_MAPPER, &wfx, (DWORD_PTR)&waveProc, 0, CALLBACK_FUNCTION) != MMSYSERR_NOERROR)
  6070.         goto omError;
  6071.  
  6072.     // create semaphore for buffer fill requests
  6073.     hAudioSem = CreateSemaphore(NULL, MIX_BUF_NUM - 1, MIX_BUF_NUM, NULL);
  6074.     if (hAudioSem == NULL)
  6075.         goto omError;
  6076.  
  6077.     // allocate WinMM mix buffers
  6078.     for (i = 0; i < MIX_BUF_NUM; i++)
  6079.     {
  6080.         mixBuffer[i] = (int16_t *)calloc(MIX_BUF_SAMPLES, wfx.nBlockAlign);
  6081.         if (mixBuffer[i] == NULL)
  6082.             goto omError;
  6083.     }
  6084.  
  6085.     // initialize WinMM mix headers
  6086.     memset(waveBlocks, 0, sizeof (waveBlocks));
  6087.     for (i = 0; i < MIX_BUF_NUM; i++)
  6088.     {
  6089.         waveBlocks[i].lpData = (LPSTR)mixBuffer[i];
  6090.         waveBlocks[i].dwBufferLength = MIX_BUF_SAMPLES * wfx.nBlockAlign;
  6091.         waveBlocks[i].dwFlags = WHDR_DONE;
  6092.  
  6093.         if (waveOutPrepareHeader(hWave, &waveBlocks[i], sizeof (WAVEHDR)) != MMSYSERR_NOERROR)
  6094.             goto omError;
  6095.     }
  6096.  
  6097.     // create main mixer thread
  6098.     audioRunningFlag = true;
  6099.     hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)mixThread, NULL, 0, &threadID);
  6100.     if (hThread == NULL)
  6101.         goto omError;
  6102.  
  6103.     return TRUE;
  6104.  
  6105. omError:
  6106.     closeMixer();
  6107.     return FALSE;
  6108. }
  6109.  
  6110. // ---------------------------------------------------------------------------
  6111.  
  6112. // END OF FILE (phew...)
RAW Paste Data