SHARE
TWEET

pt2play v1.43

8bitbubsy Sep 29th, 2013 (edited) 836 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2. ** PT2PLAY v1.43 - 16th of August 2017 - http://16-bits.org
  3. ** ========================================================
  4. **             - NOT BIG ENDIAN SAFE! -
  5. **
  6. ** Very accurate C port of ProTracker 2.3D's replayer, by
  7. ** Olav "8bitbubsy" Sørensen. Based on a ProTracker 2.3D disassembly
  8. ** using the PT1.2A source code for labels (names).
  9. ** It is NOT recommended to use pt2play with non-ProTracker .MODs.
  10. ** Also, do NOT use a lower audio rate than 32kHz! This will cause problems
  11. ** with low sample periods (high rates) and BLEP.
  12. **
  13. ** The BLEP (Band-Limited Step) and filter routines were coded by aciddose.
  14. ** This makes the replayer sound much similar to a real Amiga.
  15. **
  16. ** You need to link winmm.lib for this to compile (-lwinmm).
  17. ** Alternatively, you can wrap around your own audio callback for using
  18. ** pt2play on other platforms.
  19. **
  20. ** pt2play.h:
  21. **
  22. ** #include <stdint.h>
  23. **
  24. ** enum
  25. ** {
  26. **     CIA_TEMPO_MODE    = 0,
  27. **     VBLANK_TEMPO_MODE = 1
  28. ** };
  29. **
  30. ** int8_t pt2play_Init(uint32_t outputFreq);
  31. ** void pt2play_Close(void);
  32. ** void pt2play_PauseSong(int8_t pause);
  33. ** void pt2play_PlaySong(uint8_t *moduleData, int8_t tempoMode);
  34. ** void pt2play_SetStereoSep(uint8_t percentage);
  35. */
  36.  
  37. /* == USER ADJUSTABLE SETTINGS == */
  38. #define STEREO_SEP (15)    /* --> Stereo separation in percent - 0 = mono, 100 = hard pan (like Amiga) */
  39. #define NORM_FACTOR (4.0f) /* --> Slightly increase this value if the song is too loud. Decrease if too quiet... */
  40. #define USE_HIGHPASS       /* --> 5.2Hz high-pass filter present in all Amigas - comment out for a speed-up */
  41. //#define USE_LOWPASS      /* --> 4.4kHz low-pass filter in all Amigas except A1200 - comment out for sharper sound */
  42. #define USE_BLEP           /* --> Reduces some unwanted aliasing (closer to real Amiga) - comment out to disable */
  43. //#define ENABLE_E8_EFFECT /* --> Enable E8x (Karplus-Strong) - comment out this line if E8x is used for something else */
  44. #define LED_FILTER         /* --> Process the "LED" filter - comment out to disable */
  45.  
  46. #ifdef _MSC_VER
  47. #define inline __forceinline
  48. #endif
  49.  
  50. /* used for faster windows.h parsing when compiling */
  51. #ifndef WIN32_LEAN_AND_MEAN
  52. #define WIN32_LEAN_AND_MEAN
  53. #endif
  54.  
  55. #include <stdio.h>
  56. #include <stdlib.h>
  57. #include <stdint.h>
  58. #include <math.h>     /* tanf() */
  59. #include <windows.h>  /* win32 audio mixer */
  60. #include <mmsystem.h> /* win32 audio mixer */
  61.  
  62. enum
  63. {
  64.     CIA_TEMPO_MODE    = 0,
  65.     VBLANK_TEMPO_MODE = 1
  66. };
  67.  
  68. #define PAULA_PAL_CLK 3546895
  69. #define CIA_PAL_CLK   709379
  70.  
  71. /* don't change these two unless you know what you're doing... */
  72. #define MIX_BUF_NUM 7
  73. #define MIX_BUF_LEN 2048
  74.  
  75. #ifdef USE_BLEP /* do not change these! */
  76. #define BLEP_ZC 8
  77. #define BLEP_OS 5
  78. #define BLEP_SP 5
  79. #define BLEP_NS (BLEP_ZC * BLEP_OS / BLEP_SP)
  80. #define BLEP_RNS 7
  81. #endif
  82.  
  83. /* STRUCTS */
  84.  
  85. #ifdef USE_BLEP
  86. typedef struct blep_t
  87. {
  88.     int32_t index, samplesLeft;
  89.     float buffer[BLEP_RNS + 1], lastValue;
  90. } blep_t;
  91. #endif
  92.  
  93. typedef struct ptChannel_t
  94. {
  95.     int8_t *n_start, *n_wavestart, *n_loopstart, n_index, n_volume;
  96.     int8_t n_toneportdirec, n_vibratopos, n_tremolopos, n_pattpos, n_loopcount;
  97.     uint8_t n_wavecontrol, n_glissfunk, n_sampleoffset, n_toneportspeed;
  98.     uint8_t n_vibratocmd, n_tremolocmd, n_finetune, n_funkoffset;
  99.     int16_t n_period, n_note, n_wantedperiod;
  100.     uint16_t n_cmd, n_length, n_replen;
  101. } ptChannel_t;
  102.  
  103. typedef struct paulaVoice_t
  104. {
  105.     const int8_t *SRC_DAT, *DMA_DAT;
  106.     uint32_t SRC_LEN, DMA_LEN, DMA_POS;
  107.     float SRC_VOL, DELTA, FRAC, LASTDELTA, LASTFRAC, PANL, PANR;
  108. } paulaVoice_t;
  109.  
  110. #if defined(USE_HIGHPASS) || defined(USE_LOWPASS)
  111. typedef struct lossyIntegrator_t
  112. {
  113.     float buffer[2], coeff[2];
  114. } lossyIntegrator_t;
  115. #endif
  116.  
  117. #ifdef LED_FILTER
  118. typedef struct ledFilter_t
  119. {
  120.     float led[4];
  121. } ledFilter_t;
  122.  
  123. typedef struct ledFilterCoeff_t
  124. {
  125.     float led, ledFb;
  126. } ledFilterCoeff_t;
  127. #endif
  128.  
  129. /* STATIC DATA */
  130. static int8_t *SampleStarts[31], emptySample[131070], TempoMode, SongPosition, PBreakFlag;
  131. static int8_t DisableMixer, PBreakPosition, PattDelTime, PattDelTime2, PosJumpAssert;
  132. static uint8_t *SongDataPtr, LowMask, Counter, CurrSpeed, SetBPMFlag, SongPlaying;
  133. static uint16_t PatternPos;
  134. static int32_t soundBufferSize;
  135. static uint32_t PattPosOff;
  136. static float f_outputFreq;
  137. static WAVEHDR waveBlocks[MIX_BUF_NUM];
  138. static ptChannel_t ChanTemp[4];
  139. static paulaVoice_t AUD[4];
  140. static HWAVEOUT hWaveOut;
  141. static WAVEFORMATEX wfx;
  142. #ifdef USE_BLEP
  143. static blep_t blep[4], blepVol[4];
  144. #endif
  145. #ifdef USE_HIGHPASS
  146. static lossyIntegrator_t filterHi;
  147. #endif
  148. #ifdef USE_LOWPASS
  149. static lossyIntegrator_t filterLo;
  150. #endif
  151. #ifdef LED_FILTER
  152. static ledFilterCoeff_t filterLEDC;
  153. static ledFilter_t filterLED;
  154. static uint8_t LEDStatus;
  155. #endif
  156. static float *masterBufferL = NULL, *masterBufferR = NULL;
  157. static int8_t *mixerBuffer = NULL;
  158. static int32_t samplesLeft;
  159. static uint32_t samplesPerFrame;
  160. static volatile int8_t mixingMutex, isMixing;
  161.  
  162. /* TABLES */
  163. static const uint8_t FunkTable[16] =
  164. {
  165.     0x00, 0x05, 0x06, 0x07, 0x08, 0x0A, 0x0B, 0x0D,
  166.     0x10, 0x13, 0x16, 0x1A, 0x20, 0x2B, 0x40, 0x80
  167. };
  168.  
  169. static const uint8_t VibratoTable[32] =
  170. {
  171.     0x00, 0x18, 0x31, 0x4A, 0x61, 0x78, 0x8D, 0xA1,
  172.     0xB4, 0xC5, 0xD4, 0xE0, 0xEB, 0xF4, 0xFA, 0xFD,
  173.     0xFF, 0xFD, 0xFA, 0xF4, 0xEB, 0xE0, 0xD4, 0xC5,
  174.     0xB4, 0xA1, 0x8D, 0x78, 0x61, 0x4A, 0x31, 0x18
  175. };
  176.  
  177. static const int16_t PeriodTable[606] =
  178. {
  179.     856,808,762,720,678,640,604,570,538,508,480,453,
  180.     428,404,381,360,339,320,302,285,269,254,240,226,
  181.     214,202,190,180,170,160,151,143,135,127,120,113,0,
  182.     850,802,757,715,674,637,601,567,535,505,477,450,
  183.     425,401,379,357,337,318,300,284,268,253,239,225,
  184.     213,201,189,179,169,159,150,142,134,126,119,113,0,
  185.     844,796,752,709,670,632,597,563,532,502,474,447,
  186.     422,398,376,355,335,316,298,282,266,251,237,224,
  187.     211,199,188,177,167,158,149,141,133,125,118,112,0,
  188.     838,791,746,704,665,628,592,559,528,498,470,444,
  189.     419,395,373,352,332,314,296,280,264,249,235,222,
  190.     209,198,187,176,166,157,148,140,132,125,118,111,0,
  191.     832,785,741,699,660,623,588,555,524,495,467,441,
  192.     416,392,370,350,330,312,294,278,262,247,233,220,
  193.     208,196,185,175,165,156,147,139,131,124,117,110,0,
  194.     826,779,736,694,655,619,584,551,520,491,463,437,
  195.     413,390,368,347,328,309,292,276,260,245,232,219,
  196.     206,195,184,174,164,155,146,138,130,123,116,109,0,
  197.     820,774,730,689,651,614,580,547,516,487,460,434,
  198.     410,387,365,345,325,307,290,274,258,244,230,217,
  199.     205,193,183,172,163,154,145,137,129,122,115,109,0,
  200.     814,768,725,684,646,610,575,543,513,484,457,431,
  201.     407,384,363,342,323,305,288,272,256,242,228,216,
  202.     204,192,181,171,161,152,144,136,128,121,114,108,0,
  203.     907,856,808,762,720,678,640,604,570,538,508,480,
  204.     453,428,404,381,360,339,320,302,285,269,254,240,
  205.     226,214,202,190,180,170,160,151,143,135,127,120,0,
  206.     900,850,802,757,715,675,636,601,567,535,505,477,
  207.     450,425,401,379,357,337,318,300,284,268,253,238,
  208.     225,212,200,189,179,169,159,150,142,134,126,119,0,
  209.     894,844,796,752,709,670,632,597,563,532,502,474,
  210.     447,422,398,376,355,335,316,298,282,266,251,237,
  211.     223,211,199,188,177,167,158,149,141,133,125,118,0,
  212.     887,838,791,746,704,665,628,592,559,528,498,470,
  213.     444,419,395,373,352,332,314,296,280,264,249,235,
  214.     222,209,198,187,176,166,157,148,140,132,125,118,0,
  215.     881,832,785,741,699,660,623,588,555,524,494,467,
  216.     441,416,392,370,350,330,312,294,278,262,247,233,
  217.     220,208,196,185,175,165,156,147,139,131,123,117,0,
  218.     875,826,779,736,694,655,619,584,551,520,491,463,
  219.     437,413,390,368,347,328,309,292,276,260,245,232,
  220.     219,206,195,184,174,164,155,146,138,130,123,116,0,
  221.     868,820,774,730,689,651,614,580,547,516,487,460,
  222.     434,410,387,365,345,325,307,290,274,258,244,230,
  223.     217,205,193,183,172,163,154,145,137,129,122,115,0,
  224.     862,814,768,725,684,646,610,575,543,513,484,457,
  225.     431,407,384,363,342,323,305,288,272,256,242,228,
  226.     216,203,192,181,171,161,152,144,136,128,121,114,0,
  227.  
  228.     /* PT BUGFIX: overflowing arpeggio on -1 finetuned samples, add extra zeroes. */
  229.     0,0,0,0,0,0,0,0,0,0,0,0,0,0
  230. };
  231.  
  232. #ifdef USE_BLEP
  233. static const uint32_t blepData[48] =
  234. {
  235.     0x3F7FE1F1, 0x3F7FD548, 0x3F7FD6A3, 0x3F7FD4E3,
  236.     0x3F7FAD85, 0x3F7F2152, 0x3F7DBFAE, 0x3F7ACCDF,
  237.     0x3F752F1E, 0x3F6B7384, 0x3F5BFBCB, 0x3F455CF2,
  238.     0x3F26E524, 0x3F0128C4, 0x3EACC7DC, 0x3E29E86B,
  239.     0x3C1C1D29, 0xBDE4BBE6, 0xBE3AAE04, 0xBE48DEDD,
  240.     0xBE22AD7E, 0xBDB2309A, 0xBB82B620, 0x3D881411,
  241.     0x3DDADBF3, 0x3DE2C81D, 0x3DAAA01F, 0x3D1E769A,
  242.     0xBBC116D7, 0xBD1402E8, 0xBD38A069, 0xBD0C53BB,
  243.     0xBC3FFB8C, 0x3C465FD2, 0x3CEA5764, 0x3D0A51D6,
  244.     0x3CEAE2D5, 0x3C92AC5A, 0x3BE4CBF7, 0x00000000,
  245.     0x00000000, 0x00000000, 0x00000000, 0x00000000,
  246.     0x00000000, 0x00000000, 0x00000000, 0x00000000
  247. };
  248. #endif
  249.  
  250. /* MACROS */
  251.  
  252. #define SWAP16(x) ((uint16_t)(((x) << 8) | ((x) >> 8)))
  253. #define PTR2WORD(x) ((uint16_t *)(x))
  254. #define LERP(x, y, z) ((x) + ((y) - (x)) * (z))
  255. #define CLAMP16(i) \
  256. { \
  257.     if ((int16_t)(i) != i) \
  258.         i = 0x7FFF ^ (i >> 31); \
  259. }
  260.  
  261. /* CODE START */
  262.  
  263. static void SetReplayerBPM(uint8_t bpm)
  264. {
  265.     uint16_t ciaVal;
  266.     float f_hz, f_smp;
  267.  
  268.     if (f_outputFreq == 0.0f)
  269.         return;
  270.  
  271.     if (bpm < 32)
  272.         bpm = 32;
  273.  
  274.     ciaVal = (uint16_t)(1773447 / bpm); /* yes, truncate here */
  275.     f_hz   = (float)(CIA_PAL_CLK) / ciaVal;
  276.     f_smp  = f_outputFreq / f_hz;
  277.  
  278.     samplesPerFrame = (uint32_t)(f_smp + 0.5f);
  279. }
  280.  
  281. static void PaulaRestartDMA(uint8_t i)
  282. {
  283.     AUD[i].FRAC    = 0.0f;
  284.     AUD[i].DMA_POS = 0;
  285.     AUD[i].DMA_DAT = AUD[i].SRC_DAT;
  286.     AUD[i].DMA_LEN = AUD[i].SRC_LEN;
  287. }
  288.  
  289. static void PaulaSetPeriod(uint8_t i, uint16_t period)
  290. {
  291.     if (period == 0)
  292.     {
  293.         AUD[i].DELTA = 0.0f;
  294.     }
  295.     else
  296.     {
  297.         if (period < 113)
  298.             period = 113;
  299.  
  300.         AUD[i].DELTA = ((float)(PAULA_PAL_CLK) / period) / f_outputFreq;
  301.     }
  302.  
  303.     if (AUD[i].LASTDELTA == 0.0f)
  304.         AUD[i].LASTDELTA = AUD[i].DELTA;
  305. }
  306.  
  307. static void PaulaSetVolume(uint8_t i, uint16_t vol)
  308. {
  309.     if (vol & (1 << 6))
  310.         vol = 0x0040;
  311.     else
  312.         vol &= 0x003F;
  313.  
  314.     AUD[i].SRC_VOL = vol * (1.0f / 64.0f);
  315. }
  316.  
  317. static void PaulaSetLength(uint8_t i, uint16_t len)
  318. {
  319.     AUD[i].SRC_LEN = len * 2;
  320. }
  321.  
  322. static void PaulaSetData(uint8_t i, const int8_t *src)
  323. {
  324.     AUD[i].SRC_DAT = (src == NULL) ? emptySample : src;
  325. }
  326.  
  327. #if defined(USE_HIGHPASS) || defined(USE_LOWPASS)
  328. static void calcCoeffLossyIntegrator(float sr, float hz, lossyIntegrator_t *filter)
  329. {
  330.     filter->coeff[0] = tanf((3.1415927f * hz) / sr);
  331.     filter->coeff[1] = 1.0f / (1.0f + filter->coeff[0]);
  332. }
  333.  
  334. static void clearLossyIntegrator(lossyIntegrator_t *filter)
  335. {
  336.     filter->buffer[0] = 0.0f;
  337.     filter->buffer[1] = 0.0f;
  338. }
  339.  
  340. static inline void lossyIntegrator(lossyIntegrator_t *filter, float *in, float *out)
  341. {
  342.     float output;
  343.  
  344.     /* left channel low-pass */
  345.     output = (filter->coeff[0] * in[0] + filter->buffer[0]) * filter->coeff[1];
  346.     filter->buffer[0] = filter->coeff[0] * (in[0] - output) + output + 1e-10f;
  347.     out[0] = output;
  348.  
  349.     /* right channel low-pass */
  350.     output = (filter->coeff[0] * in[1] + filter->buffer[1]) * filter->coeff[1];
  351.     filter->buffer[1] = filter->coeff[0] * (in[1] - output) + output + 1e-10f;
  352.     out[1] = output;
  353. }
  354.  
  355. static inline void lossyIntegratorHighPass(lossyIntegrator_t *filter, float *in, float *out)
  356. {
  357.     float low[2];
  358.  
  359.     lossyIntegrator(filter, in, low);
  360.  
  361.     out[0] = in[0] - low[0];
  362.     out[1] = in[1] - low[1];
  363. }
  364. #endif
  365.  
  366. #ifdef LED_FILTER
  367. static void calcCoeffLED(float sr, float hz, ledFilterCoeff_t *filter)
  368. {
  369.     if (hz < (sr / 2.0f))
  370.         filter->led = ((2.0f * 3.1415927f) * hz) / sr;
  371.     else
  372.         filter->led = 1.0f;
  373.  
  374.     filter->ledFb = 0.125f + (0.125f / (1.0f - filter->led)); /* Fb = 0.125 : Q ~= 1/sqrt(2) (Butterworth) */
  375. }
  376.  
  377. static void clearLEDFilter(ledFilter_t *filter)
  378. {
  379.     filter->led[0] = 0.0f;
  380.     filter->led[1] = 0.0f;
  381.     filter->led[2] = 0.0f;
  382.     filter->led[3] = 0.0f;
  383. }
  384.  
  385. static inline void lossyIntegratorLED(ledFilterCoeff_t filterC, ledFilter_t *filter, float *in, float *out)
  386. {
  387.     /* left channel */
  388.     filter->led[0] += (filterC.led * (in[0] - filter->led[0])
  389.         + filterC.ledFb * (filter->led[0] - filter->led[1]) + 1e-10f);
  390.     filter->led[1] += (filterC.led * (filter->led[0] - filter->led[1]) + 1e-10f);
  391.     out[0] = filter->led[1];
  392.  
  393.     /* right channel */
  394.     filter->led[2] += (filterC.led * (in[1] - filter->led[2])
  395.         + filterC.ledFb * (filter->led[2] - filter->led[3]) + 1e-10f);
  396.     filter->led[3] += (filterC.led * (filter->led[2] - filter->led[3]) + 1e-10f);
  397.     out[1] = filter->led[3];
  398. }
  399. #endif
  400.  
  401. #ifdef USE_BLEP
  402. static inline void blepAdd(blep_t *b, float offset, float amplitude)
  403. {
  404.     int8_t n;
  405.     uint32_t i;
  406.     const float *blepSrc;
  407.     float f;
  408.  
  409.     i  = (uint32_t)(offset * BLEP_SP);
  410.     blepSrc = (const float *)(blepData) + i + BLEP_OS;
  411.  
  412.     f = (offset * BLEP_SP) - i;
  413.     i = b->index;
  414.     n = BLEP_NS;
  415.  
  416.     while (n--)
  417.     {
  418.         b->buffer[i] += (amplitude * LERP(blepSrc[0], blepSrc[1], f));
  419.         blepSrc += BLEP_SP;
  420.  
  421.         i++;
  422.         i &= BLEP_RNS;
  423.     }
  424.  
  425.     b->samplesLeft = BLEP_NS;
  426. }
  427.  
  428. static inline float blepRun(blep_t *b)
  429. {
  430.     float blepOutput;
  431.  
  432.     blepOutput = b->buffer[b->index];
  433.     b->buffer[b->index] = 0.0f;
  434.  
  435.     b->index++;
  436.     b->index &= BLEP_RNS;
  437.     b->samplesLeft--;
  438.  
  439.     return (blepOutput);
  440. }
  441. #endif
  442.  
  443. static void UpdateFunk(ptChannel_t *ch)
  444. {
  445.     int8_t funkspeed;
  446.  
  447.     funkspeed = ch->n_glissfunk >> 4;
  448.     if (funkspeed > 0)
  449.     {
  450.         ch->n_funkoffset += FunkTable[funkspeed];
  451.         if (ch->n_funkoffset >= 128)
  452.         {
  453.             ch->n_funkoffset = 0;
  454.  
  455.             if ((ch->n_loopstart != NULL) && (ch->n_wavestart != NULL)) /* SAFETY BUG FIX */
  456.             {
  457.                 if (++ch->n_wavestart >= (ch->n_loopstart + (ch->n_replen * 2)))
  458.                       ch->n_wavestart  =  ch->n_loopstart;
  459.  
  460.                 *ch->n_wavestart = -1 - *ch->n_wavestart;
  461.             }
  462.         }
  463.     }
  464. }
  465.  
  466. static void SetGlissControl(ptChannel_t *ch)
  467. {
  468.     ch->n_glissfunk = (ch->n_glissfunk & 0xF0) | (ch->n_cmd & 0x000F);
  469. }
  470.  
  471. static void SetVibratoControl(ptChannel_t *ch)
  472. {
  473.     ch->n_wavecontrol = (ch->n_wavecontrol & 0xF0) | (ch->n_cmd & 0x000F);
  474. }
  475.  
  476. static void SetFineTune(ptChannel_t *ch)
  477. {
  478.     ch->n_finetune = ch->n_cmd & 0x000F;
  479. }
  480.  
  481. static void JumpLoop(ptChannel_t *ch)
  482. {
  483.     if (!Counter)
  484.     {
  485.         if (!(ch->n_cmd & 0x000F))
  486.         {
  487.             ch->n_pattpos = (PatternPos / 16) & 0x00FF;
  488.         }
  489.         else
  490.         {
  491.             if (!ch->n_loopcount)
  492.             {
  493.                 ch->n_loopcount = ch->n_cmd & 0x000F;
  494.             }
  495.             else
  496.             {
  497.                 if (!--ch->n_loopcount)
  498.                     return;
  499.             }
  500.  
  501.             PBreakPosition = ch->n_pattpos;
  502.             PBreakFlag = 1;
  503.         }
  504.     }
  505. }
  506.  
  507. static void SetTremoloControl(ptChannel_t *ch)
  508. {
  509.     ch->n_wavecontrol = ((ch->n_cmd & 0x000F) << 4) | (ch->n_wavecontrol & 0x0F);
  510. }
  511.  
  512. static void KarplusStrong(ptChannel_t *ch)
  513. {
  514. #ifdef ENABLE_E8_EFFECT
  515.     int8_t *smpPtr;
  516.     int16_t dat;
  517.     uint16_t len;
  518.  
  519.     smpPtr = ch->n_loopstart;
  520.     if (smpPtr != NULL) /* SAFETY BUG FIX */
  521.     {
  522.         len = ((ch->n_replen * 2) & 0xFFFF) - 1;
  523.         while (len--)
  524.         {
  525.             dat = smpPtr[1] + smpPtr[0];
  526.  
  527.             /* "arithmetic shift right" on signed number simulation */
  528.             if (dat < 0)
  529.                 dat = 0x8000 | ((uint16_t)(dat) >> 1); /* 0x8000 = 2^16 - 2^(16-1) */
  530.             else
  531.                 dat /= 2;
  532.  
  533.             *smpPtr++ = dat & 0x00FF;
  534.         }
  535.  
  536.         dat = ch->n_loopstart[0] + smpPtr[0];
  537.  
  538.         /* "arithmetic shift right" on signed number simulation */
  539.         if (dat < 0)
  540.             dat = 0x8000 | ((uint16_t)(dat) >> 1);
  541.         else
  542.             dat /= 2;
  543.  
  544.         *smpPtr = dat & 0x00FF;
  545.     }
  546. #else
  547.     (void)(ch);
  548. #endif
  549. }
  550.  
  551. static void DoRetrg(ptChannel_t *ch)
  552. {
  553.     PaulaSetData(ch->n_index, ch->n_start); /* n_start is increased on 9xx */
  554.     PaulaSetLength(ch->n_index, ch->n_length);
  555.     PaulaSetPeriod(ch->n_index, ch->n_period);
  556.     PaulaRestartDMA(ch->n_index);
  557.  
  558.     /* these take effect after the current DMA cycle is done */
  559.     PaulaSetData(ch->n_index, ch->n_loopstart);
  560.     PaulaSetLength(ch->n_index, ch->n_replen);
  561. }
  562.  
  563. static void RetrigNote(ptChannel_t *ch)
  564. {
  565.     if (ch->n_cmd & 0x000F)
  566.     {
  567.         if (!Counter)
  568.         {
  569.             if (ch->n_note & 0x0FFF)
  570.                 return;
  571.         }
  572.  
  573.         if (!(Counter % (ch->n_cmd & 0x000F)))
  574.             DoRetrg(ch);
  575.     }
  576. }
  577.  
  578. static void VolumeSlide(ptChannel_t *ch)
  579. {
  580.     uint8_t cmd;
  581.  
  582.     cmd = ch->n_cmd & 0x00FF;
  583.     if (!(cmd & 0xF0))
  584.     {
  585.         ch->n_volume -= (cmd & 0x0F);
  586.         if (ch->n_volume < 0)
  587.             ch->n_volume = 0;
  588.     }
  589.     else
  590.     {
  591.         ch->n_volume += (cmd >> 4);
  592.         if (ch->n_volume > 64)
  593.             ch->n_volume = 64;
  594.     }
  595. }
  596.  
  597. static void VolumeFineUp(ptChannel_t *ch)
  598. {
  599.     if (!Counter)
  600.     {
  601.         ch->n_volume += (ch->n_cmd & 0x000F);
  602.         if (ch->n_volume > 64)
  603.             ch->n_volume = 64;
  604.     }
  605. }
  606.  
  607. static void VolumeFineDown(ptChannel_t *ch)
  608. {
  609.     if (!Counter)
  610.     {
  611.         ch->n_volume -= (ch->n_cmd & 0x000F);
  612.         if (ch->n_volume < 0)
  613.             ch->n_volume = 0;
  614.     }
  615. }
  616.  
  617. static void NoteCut(ptChannel_t *ch)
  618. {
  619.     if (Counter == (ch->n_cmd & 0x000F))
  620.         ch->n_volume = 0;
  621. }
  622.  
  623. static void NoteDelay(ptChannel_t *ch)
  624. {
  625.     if (Counter == (ch->n_cmd & 0x000F))
  626.     {
  627.         if (ch->n_note & 0x0FFF)
  628.             DoRetrg(ch);
  629.     }
  630. }
  631.  
  632. static void PatternDelay(ptChannel_t *ch)
  633. {
  634.     if (!Counter)
  635.     {
  636.         if (!PattDelTime2)
  637.             PattDelTime = (ch->n_cmd & 0x000F) + 1;
  638.     }
  639. }
  640.  
  641. static void FunkIt(ptChannel_t *ch)
  642. {
  643.     if (!Counter)
  644.     {
  645.         ch->n_glissfunk = ((ch->n_cmd & 0x000F) << 4) | (ch->n_glissfunk & 0x0F);
  646.  
  647.         if (ch->n_glissfunk & 0xF0)
  648.             UpdateFunk(ch);
  649.     }
  650. }
  651.  
  652. static void PositionJump(ptChannel_t *ch)
  653. {
  654.     SongPosition   = (ch->n_cmd & 0x00FF) - 1; /* 0xFF (B00) jumps to pat 0 */
  655.     PBreakPosition = 0;
  656.     PosJumpAssert  = 1;
  657. }
  658.  
  659. static void VolumeChange(ptChannel_t *ch)
  660. {
  661.     ch->n_volume = ch->n_cmd & 0x00FF;
  662.     if (ch->n_volume > 64)
  663.         ch->n_volume = 64;
  664. }
  665.  
  666. static void PatternBreak(ptChannel_t *ch)
  667. {
  668.     PBreakPosition = (((ch->n_cmd & 0x00F0) >> 4) * 10) + (ch->n_cmd & 0x000F);
  669.     if (PBreakPosition > 63)
  670.         PBreakPosition = 0;
  671.  
  672.     PosJumpAssert = 1;
  673. }
  674.  
  675. static void SetSpeed(ptChannel_t *ch)
  676. {
  677.     if (ch->n_cmd & 0x00FF)
  678.     {
  679.         Counter = 0;
  680.  
  681.         if ((TempoMode == VBLANK_TEMPO_MODE) || ((ch->n_cmd & 0x00FF) < 32))
  682.             CurrSpeed = ch->n_cmd & 0x00FF;
  683.         else
  684.             SetBPMFlag = ch->n_cmd & 0x00FF; /* CIA doesn't refresh its registers until the next interrupt, so change it later */
  685.     }
  686. }
  687.  
  688. static void Arpeggio(ptChannel_t *ch)
  689. {
  690.     uint8_t i, dat;
  691.     const int16_t *arpPointer;
  692.  
  693.     dat = Counter % 3;
  694.     if (!dat)
  695.     {
  696.         PaulaSetPeriod(ch->n_index, ch->n_period);
  697.     }
  698.     else
  699.     {
  700.              if (dat == 1) dat = (ch->n_cmd & 0x00F0) >> 4;
  701.         else if (dat == 2) dat =  ch->n_cmd & 0x000F;
  702.  
  703.         arpPointer = &PeriodTable[37 * ch->n_finetune];
  704.         for (i = 0; i < 37; ++i)
  705.         {
  706.             if (ch->n_period >= arpPointer[i])
  707.             {
  708.                 PaulaSetPeriod(ch->n_index, arpPointer[i + dat]);
  709.                 break;
  710.             }
  711.         }
  712.     }
  713. }
  714.  
  715. static void PortaUp(ptChannel_t *ch)
  716. {
  717.     ch->n_period -= ((ch->n_cmd & 0x00FF) & LowMask);
  718.     LowMask = 0xFF;
  719.  
  720.     if ((ch->n_period & 0x0FFF) < 113)
  721.         ch->n_period = (ch->n_period & 0xF000) | 113;
  722.  
  723.     PaulaSetPeriod(ch->n_index, ch->n_period & 0x0FFF);
  724. }
  725.  
  726. static void PortaDown(ptChannel_t *ch)
  727. {
  728.     ch->n_period += ((ch->n_cmd & 0x00FF) & LowMask);
  729.     LowMask = 0xFF;
  730.  
  731.     if ((ch->n_period & 0x0FFF) > 856)
  732.         ch->n_period = (ch->n_period & 0xF000) | 856;
  733.  
  734.     PaulaSetPeriod(ch->n_index, ch->n_period & 0x0FFF);
  735. }
  736.  
  737. static void FilterOnOff(ptChannel_t *ch)
  738. {
  739. #ifdef LED_FILTER
  740.     LEDStatus = !(ch->n_cmd & 0x0001);
  741. #endif
  742. }
  743.  
  744. static void FinePortaUp(ptChannel_t *ch)
  745. {
  746.     if (!Counter)
  747.     {
  748.         LowMask = 0x0F;
  749.         PortaUp(ch);
  750.     }
  751. }
  752.  
  753. static void FinePortaDown(ptChannel_t *ch)
  754. {
  755.     if (!Counter)
  756.     {
  757.         LowMask = 0x0F;
  758.         PortaDown(ch);
  759.     }
  760. }
  761.  
  762. static void SetTonePorta(ptChannel_t *ch)
  763. {
  764.     uint8_t i;
  765.     const int16_t *portaPointer;
  766.     uint16_t note;
  767.  
  768.     note = ch->n_note & 0x0FFF;
  769.     portaPointer = &PeriodTable[37 * ch->n_finetune];
  770.  
  771.     i = 0;
  772.     for (;;)
  773.     {
  774.         /* portaPointer[36] = 0, so i=36 is safe */
  775.         if (note >= portaPointer[i])
  776.             break;
  777.  
  778.         if (++i >= 37)
  779.         {
  780.             i = 35;
  781.             break;
  782.         }
  783.     }
  784.  
  785.     if ((ch->n_finetune & 8) && i) i--;
  786.  
  787.     ch->n_wantedperiod  = portaPointer[i];
  788.     ch->n_toneportdirec = 0;
  789.  
  790.          if (ch->n_period == ch->n_wantedperiod) ch->n_wantedperiod  = 0;
  791.     else if (ch->n_period  > ch->n_wantedperiod) ch->n_toneportdirec = 1;
  792. }
  793.  
  794. static void TonePortNoChange(ptChannel_t *ch)
  795. {
  796.     uint8_t i;
  797.     const int16_t *portaPointer;
  798.  
  799.     if (ch->n_wantedperiod)
  800.     {
  801.         if (ch->n_toneportdirec)
  802.         {
  803.             ch->n_period -= ch->n_toneportspeed;
  804.             if (ch->n_period <= ch->n_wantedperiod)
  805.             {
  806.                 ch->n_period = ch->n_wantedperiod;
  807.                 ch->n_wantedperiod = 0;
  808.             }
  809.         }
  810.         else
  811.         {
  812.             ch->n_period += ch->n_toneportspeed;
  813.             if (ch->n_period >= ch->n_wantedperiod)
  814.             {
  815.                 ch->n_period = ch->n_wantedperiod;
  816.                 ch->n_wantedperiod = 0;
  817.             }
  818.         }
  819.  
  820.         if (!(ch->n_glissfunk & 0x0F))
  821.         {
  822.             PaulaSetPeriod(ch->n_index, ch->n_period);
  823.         }
  824.         else
  825.         {
  826.             portaPointer = &PeriodTable[37 * ch->n_finetune];
  827.  
  828.             i = 0;
  829.             for (;;)
  830.             {
  831.                 /* portaPointer[36] = 0, so i=36 is safe */
  832.                 if (ch->n_period >= portaPointer[i])
  833.                     break;
  834.  
  835.                 if (++i >= 37)
  836.                 {
  837.                     i = 35;
  838.                     break;
  839.                 }
  840.             }
  841.  
  842.             PaulaSetPeriod(ch->n_index, portaPointer[i]);
  843.         }
  844.     }
  845. }
  846.  
  847. static void TonePortamento(ptChannel_t *ch)
  848. {
  849.     if (ch->n_cmd & 0x00FF)
  850.     {
  851.         ch->n_toneportspeed = ch->n_cmd & 0x00FF;
  852.         ch->n_cmd &= 0xFF00;
  853.     }
  854.  
  855.     TonePortNoChange(ch);
  856. }
  857.  
  858. static void VibratoNoChange(ptChannel_t *ch)
  859. {
  860.     uint8_t vibratoTemp;
  861.     int16_t vibratoData;
  862.  
  863.     vibratoTemp = (ch->n_vibratopos / 4) & 31;
  864.     vibratoData = ch->n_wavecontrol & 3;
  865.  
  866.     if (!vibratoData)
  867.     {
  868.         vibratoData = VibratoTable[vibratoTemp];
  869.     }
  870.     else
  871.     {
  872.         if (vibratoData == 1)
  873.         {
  874.             if (ch->n_vibratopos < 0)
  875.                 vibratoData = 255 - (vibratoTemp * 8);
  876.             else
  877.                 vibratoData = vibratoTemp * 8;
  878.         }
  879.         else
  880.         {
  881.             vibratoData = 255;
  882.         }
  883.     }
  884.  
  885.     vibratoData = (vibratoData * (ch->n_vibratocmd & 0x0F)) / 128;
  886.  
  887.     if (ch->n_vibratopos < 0)
  888.         vibratoData = ch->n_period - vibratoData;
  889.     else
  890.         vibratoData = ch->n_period + vibratoData;
  891.  
  892.     PaulaSetPeriod(ch->n_index, vibratoData);
  893.  
  894.     ch->n_vibratopos += ((ch->n_vibratocmd >> 4) * 4);
  895. }
  896.  
  897. static void Vibrato(ptChannel_t *ch)
  898. {
  899.     if (ch->n_cmd & 0x00FF)
  900.     {
  901.         if (ch->n_cmd & 0x000F)
  902.             ch->n_vibratocmd = (ch->n_vibratocmd & 0xF0) | (ch->n_cmd & 0x000F);
  903.  
  904.         if (ch->n_cmd & 0x00F0)
  905.             ch->n_vibratocmd = (ch->n_cmd & 0x00F0) | (ch->n_vibratocmd & 0x0F);
  906.     }
  907.  
  908.     VibratoNoChange(ch);
  909. }
  910.  
  911. static void TonePlusVolSlide(ptChannel_t *ch)
  912. {
  913.     TonePortNoChange(ch);
  914.     VolumeSlide(ch);
  915. }
  916.  
  917. static void VibratoPlusVolSlide(ptChannel_t *ch)
  918. {
  919.     VibratoNoChange(ch);
  920.     VolumeSlide(ch);
  921. }
  922.  
  923. static void Tremolo(ptChannel_t *ch)
  924. {
  925.     int8_t tremoloTemp;
  926.     int16_t tremoloData;
  927.  
  928.     if (ch->n_cmd & 0x00FF)
  929.     {
  930.         if (ch->n_cmd & 0x000F)
  931.             ch->n_tremolocmd = (ch->n_tremolocmd & 0xF0) | (ch->n_cmd & 0x000F);
  932.  
  933.         if (ch->n_cmd & 0x00F0)
  934.             ch->n_tremolocmd = (ch->n_cmd & 0x00F0) | (ch->n_tremolocmd & 0x0F);
  935.     }
  936.  
  937.     tremoloTemp = (ch->n_tremolopos / 4) & 31;
  938.     tremoloData = (ch->n_wavecontrol >> 4) & 3;
  939.  
  940.     if (!tremoloData)
  941.     {
  942.         tremoloData = VibratoTable[tremoloTemp];
  943.     }
  944.     else
  945.     {
  946.         if (tremoloData == 1)
  947.         {
  948.             if (ch->n_vibratopos < 0) /* PT bug, should've been n_tremolopos */
  949.                 tremoloData = 255 - (tremoloTemp * 8);
  950.             else
  951.                 tremoloData = tremoloTemp * 8;
  952.         }
  953.         else
  954.         {
  955.             tremoloData = 255;
  956.         }
  957.     }
  958.  
  959.     tremoloData = (tremoloData * (ch->n_tremolocmd & 0x0F)) / 64;
  960.  
  961.     if (ch->n_tremolopos < 0)
  962.     {
  963.         tremoloData = ch->n_volume - tremoloData;
  964.         if (tremoloData < 0)
  965.             tremoloData = 0;
  966.     }
  967.     else
  968.     {
  969.         tremoloData = ch->n_volume + tremoloData;
  970.         if (tremoloData > 64)
  971.             tremoloData = 64;
  972.     }
  973.  
  974.     PaulaSetVolume(ch->n_index, tremoloData);
  975.  
  976.     ch->n_tremolopos += ((ch->n_tremolocmd >> 4) * 4);
  977. }
  978.  
  979. static void SampleOffset(ptChannel_t *ch)
  980. {
  981.     uint16_t newOffset;
  982.  
  983.     if (ch->n_cmd & 0x00FF)
  984.         ch->n_sampleoffset = ch->n_cmd & 0x00FF;
  985.  
  986.     newOffset = ch->n_sampleoffset * 128;
  987.     if ((ch->n_length <= 32767) && (newOffset < ch->n_length))
  988.     {
  989.         ch->n_length -=  newOffset;
  990.         ch->n_start  += (newOffset * 2);
  991.     }
  992.     else
  993.     {
  994.         ch->n_length = 1; /* this must NOT be set to 0! 1 is the correct value */
  995.     }
  996. }
  997.  
  998. static void E_Commands(ptChannel_t *ch)
  999. {
  1000.     switch ((ch->n_cmd & 0x00F0) >> 4)
  1001.     {
  1002.         case 0x00: FilterOnOff(ch);       break;
  1003.         case 0x01: FinePortaUp(ch);       break;
  1004.         case 0x02: FinePortaDown(ch);     break;
  1005.         case 0x03: SetGlissControl(ch);   break;
  1006.         case 0x04: SetVibratoControl(ch); break;
  1007.         case 0x05: SetFineTune(ch);       break;
  1008.         case 0x06: JumpLoop(ch);          break;
  1009.         case 0x07: SetTremoloControl(ch); break;
  1010.         case 0x08: KarplusStrong(ch);     break;
  1011.         case 0x09: RetrigNote(ch);        break;
  1012.         case 0x0A: VolumeFineUp(ch);      break;
  1013.         case 0x0B: VolumeFineDown(ch);    break;
  1014.         case 0x0C: NoteCut(ch);           break;
  1015.         case 0x0D: NoteDelay(ch);         break;
  1016.         case 0x0E: PatternDelay(ch);      break;
  1017.         case 0x0F: FunkIt(ch);            break;
  1018.     }
  1019. }
  1020.  
  1021. static void CheckMoreEffects(ptChannel_t *ch)
  1022. {
  1023.     switch ((ch->n_cmd & 0x0F00) >> 8)
  1024.     {
  1025.         case 0x09: SampleOffset(ch); break;
  1026.         case 0x0B: PositionJump(ch); break;
  1027.         case 0x0D: PatternBreak(ch); break;
  1028.         case 0x0E: E_Commands(ch);   break;
  1029.         case 0x0F: SetSpeed(ch);     break;
  1030.         case 0x0C: VolumeChange(ch); break;
  1031.  
  1032.         default: PaulaSetPeriod(ch->n_index, ch->n_period); break;
  1033.     }
  1034. }
  1035.  
  1036. static void CheckEffects(ptChannel_t *ch)
  1037. {
  1038.     UpdateFunk(ch);
  1039.  
  1040.     if (ch->n_cmd & 0x0FFF)
  1041.     {
  1042.         switch ((ch->n_cmd & 0x0F00) >> 8)
  1043.         {
  1044.             case 0x00: Arpeggio(ch);            break;
  1045.             case 0x01: PortaUp(ch);             break;
  1046.             case 0x02: PortaDown(ch);           break;
  1047.             case 0x03: TonePortamento(ch);      break;
  1048.             case 0x04: Vibrato(ch);             break;
  1049.             case 0x05: TonePlusVolSlide(ch);    break;
  1050.             case 0x06: VibratoPlusVolSlide(ch); break;
  1051.             case 0x0E: E_Commands(ch);          break;
  1052.             case 0x07:
  1053.                 PaulaSetPeriod(ch->n_index, ch->n_period);
  1054.                 Tremolo(ch);
  1055.             break;
  1056.             case 0x0A:
  1057.                 PaulaSetPeriod(ch->n_index, ch->n_period);
  1058.                 VolumeSlide(ch);
  1059.             break;
  1060.  
  1061.             default: PaulaSetPeriod(ch->n_index, ch->n_period); break;
  1062.         }
  1063.     }
  1064.  
  1065.     PaulaSetVolume(ch->n_index, ch->n_volume);
  1066. }
  1067.  
  1068. static void SetPeriod(ptChannel_t *ch)
  1069. {
  1070.     uint8_t i;
  1071.     uint16_t note;
  1072.  
  1073.     note = ch->n_note & 0x0FFF;
  1074.     for (i = 0; i < 37; ++i)
  1075.     {
  1076.         /* PeriodTable[36] = 0, so i=36 is safe */
  1077.         if (note >= PeriodTable[i])
  1078.             break;
  1079.     }
  1080.  
  1081.     /* BUG: yes it's 'safe' if i=37 because of padding at the end of period table */
  1082.     ch->n_period = PeriodTable[(37 * ch->n_finetune) + i];
  1083.  
  1084.     if ((ch->n_cmd & 0x0FF0) != 0x0ED0) /* no note delay */
  1085.     {
  1086.         if (!(ch->n_wavecontrol & 0x04)) ch->n_vibratopos = 0;
  1087.         if (!(ch->n_wavecontrol & 0x40)) ch->n_tremolopos = 0;
  1088.  
  1089.         PaulaSetLength(ch->n_index, ch->n_length);
  1090.         PaulaSetData(ch->n_index, ch->n_start);
  1091.  
  1092.         if (ch->n_start == NULL)
  1093.         {
  1094.             ch->n_loopstart = NULL;
  1095.             PaulaSetLength(ch->n_index, 1);
  1096.             ch->n_replen = 1;
  1097.         }
  1098.  
  1099.         PaulaSetPeriod(ch->n_index, ch->n_period);
  1100.         PaulaRestartDMA(ch->n_index);
  1101.     }
  1102.  
  1103.     CheckMoreEffects(ch);
  1104. }
  1105.  
  1106. static void PlayVoice(ptChannel_t *ch)
  1107. {
  1108.     uint8_t *dataPtr, sample, cmd;
  1109.     uint16_t sampleOffset, repeat;
  1110.  
  1111.     if (!ch->n_note && !ch->n_cmd)
  1112.         PaulaSetPeriod(ch->n_index, ch->n_period);
  1113.  
  1114.     dataPtr = &SongDataPtr[PattPosOff];
  1115.  
  1116.     ch->n_note = (dataPtr[0] << 8) | dataPtr[1];
  1117.     ch->n_cmd  = (dataPtr[2] << 8) | dataPtr[3];
  1118.  
  1119.     sample = (dataPtr[0] & 0xF0) | (dataPtr[2] >> 4);
  1120.     if ((sample >= 1) && (sample <= 31)) /* SAFETY BUG FIX: don't handle sample-numbers >31 */
  1121.     {
  1122.         sample--;
  1123.         sampleOffset = 42 + (30 * sample);
  1124.  
  1125.         ch->n_start    = SampleStarts[sample];
  1126.         ch->n_finetune = SongDataPtr[sampleOffset + 2] & 0x0F; /* SAFETY BUG FIX: mask finetune */
  1127.         ch->n_volume   = SongDataPtr[sampleOffset + 3];
  1128.         ch->n_length   = *PTR2WORD(&SongDataPtr[sampleOffset + 0]);
  1129.         ch->n_replen   = *PTR2WORD(&SongDataPtr[sampleOffset + 6]);
  1130.  
  1131.         repeat = *PTR2WORD(&SongDataPtr[sampleOffset + 4]);
  1132.         if (repeat > 0)
  1133.         {
  1134.             ch->n_loopstart = ch->n_start + (repeat * 2);
  1135.             ch->n_wavestart = ch->n_loopstart;
  1136.             ch->n_length    = repeat + ch->n_replen;
  1137.         }
  1138.         else
  1139.         {
  1140.             ch->n_loopstart = ch->n_start;
  1141.             ch->n_wavestart = ch->n_start;
  1142.         }
  1143.        
  1144.         if (ch->n_start == NULL)
  1145.             ch->n_loopstart = ch->n_wavestart = emptySample;    
  1146.     }
  1147.  
  1148.     if (ch->n_note & 0x0FFF)
  1149.     {
  1150.         if ((ch->n_cmd & 0x0FF0) == 0x0E50) /* set finetune */
  1151.         {
  1152.             SetFineTune(ch);
  1153.             SetPeriod(ch);
  1154.         }
  1155.         else
  1156.         {
  1157.             cmd = (ch->n_cmd & 0x0F00) >> 8;
  1158.             if ((cmd == 0x03) || (cmd == 0x05))
  1159.             {
  1160.                 SetTonePorta(ch);
  1161.                 CheckMoreEffects(ch);
  1162.             }
  1163.             else if (cmd == 0x09)
  1164.             {
  1165.                 CheckMoreEffects(ch);
  1166.                 SetPeriod(ch);
  1167.             }
  1168.             else
  1169.             {
  1170.                 SetPeriod(ch);
  1171.             }
  1172.         }
  1173.     }
  1174.     else
  1175.     {
  1176.         CheckMoreEffects(ch);
  1177.     }
  1178.  
  1179.     PattPosOff += 4;
  1180. }
  1181.  
  1182. static void NextPosition(void)
  1183. {
  1184.     PatternPos     = PBreakPosition * 16;
  1185.     PBreakPosition = 0;
  1186.     PosJumpAssert  = 0;
  1187.  
  1188.     SongPosition = (SongPosition + 1) & 0x7F;
  1189.     if (SongPosition >= SongDataPtr[950])
  1190.         SongPosition = 0;
  1191. }
  1192.  
  1193. static void IntMusic(void) /* called (SongBPM/2.5) times a second (duration: 1000/(SongBPM/2.5) milliseconds) */
  1194. {
  1195.     uint8_t i;
  1196.    
  1197.     if (!SongPlaying) return;
  1198.  
  1199.     /* PT quirk: CIA refreshes its timer values on the next interrupt, so do the real tempo change here */
  1200.     if (SetBPMFlag != 0)
  1201.     {
  1202.         SetReplayerBPM(SetBPMFlag);
  1203.         SetBPMFlag = 0;
  1204.     }
  1205.  
  1206.     if (++Counter >= CurrSpeed)
  1207.     {
  1208.         Counter = 0;
  1209.  
  1210.         if (!PattDelTime2)
  1211.         {
  1212.             PattPosOff = (1084 + (SongDataPtr[952 + SongPosition] * 1024)) + PatternPos;
  1213.  
  1214.             for (i = 0; i < 4; ++i)
  1215.             {
  1216.                 PlayVoice(&ChanTemp[i]);
  1217.                 PaulaSetVolume(i, ChanTemp[i].n_volume);
  1218.  
  1219.                 /* these take effect after the current DMA cycle is done */
  1220.                 PaulaSetData(i, ChanTemp[i].n_loopstart);
  1221.                 PaulaSetLength(i, ChanTemp[i].n_replen);
  1222.             }
  1223.         }
  1224.         else
  1225.         {
  1226.             for (i = 0; i < 4; ++i)
  1227.                 CheckEffects(&ChanTemp[i]);
  1228.         }
  1229.  
  1230.         PatternPos += 16;
  1231.  
  1232.         if (PattDelTime)
  1233.         {
  1234.             PattDelTime2 = PattDelTime;
  1235.             PattDelTime  = 0;
  1236.         }
  1237.  
  1238.         if (PattDelTime2)
  1239.         {
  1240.             PattDelTime2--;
  1241.             if (PattDelTime2) PatternPos -= 16;
  1242.         }
  1243.  
  1244.         if (PBreakFlag)
  1245.         {
  1246.             PatternPos = PBreakPosition * 16;
  1247.             PBreakPosition = 0;
  1248.             PBreakFlag = 0;
  1249.         }
  1250.  
  1251.         if ((PatternPos >= 1024) || PosJumpAssert)
  1252.             NextPosition();
  1253.     }
  1254.     else
  1255.     {
  1256.         for (i = 0; i < 4; ++i)
  1257.             CheckEffects(&ChanTemp[i]);
  1258.  
  1259.         if (PosJumpAssert)
  1260.             NextPosition();
  1261.     }
  1262. }
  1263.  
  1264. static void moduleInit(uint8_t *moduleData)
  1265. {
  1266.     int8_t pattNum;
  1267.     uint8_t *sampleStarts, i;
  1268.     uint16_t *p;
  1269.  
  1270.     for (i = 0; i < 4; ++i)
  1271.         ChanTemp[i].n_index = i;
  1272.  
  1273.     SongDataPtr = moduleData;
  1274.  
  1275.     pattNum = 0;
  1276.     for (i = 0; i < 128; ++i)
  1277.     {
  1278.         if (SongDataPtr[952 + i] > pattNum)
  1279.             pattNum = SongDataPtr[952 + i];
  1280.     }
  1281.     pattNum++;
  1282.  
  1283.     sampleStarts = &SongDataPtr[1084 + (pattNum * 1024)];
  1284.     for (i = 0; i < 31; ++i)
  1285.     {
  1286.         p = PTR2WORD(&SongDataPtr[42 + (30 * i)]);
  1287.  
  1288.         /* swap bytes in words (Amiga word -> Intel word) */
  1289.         p[0] = SWAP16(p[0]); /* n_length */
  1290.         p[2] = SWAP16(p[2]); /* n_repeat */
  1291.         p[3] = SWAP16(p[3]); /* n_replen */
  1292.  
  1293.         if (p[0] == 0)
  1294.             SampleStarts[i] = NULL; /* set to NULL if empty sample */
  1295.         else
  1296.             SampleStarts[i] = (int8_t *)(sampleStarts);
  1297.  
  1298.         /* loop point sanity checking */
  1299.         if ((p[2] + p[3]) > p[0])
  1300.         {
  1301.             if (((p[2] / 2) + p[3]) <= p[0])
  1302.             {
  1303.                 /* fix for poorly converted STK->PT modules */
  1304.                 p[2] /= 2;
  1305.             }
  1306.             else
  1307.             {
  1308.                 /* loop points are still illegal, deactivate loop */
  1309.                 p[2] = 0;
  1310.                 p[3] = 1;
  1311.             }
  1312.         }
  1313.  
  1314.         if (p[3] <= 1)
  1315.             p[3] = 1; /* fix illegal loop length (f.ex. from "Fasttracker II" .MODs) */
  1316.  
  1317.         if ((p[0] >= 1) && ((p[2] + p[3]) <= 1))
  1318.         {
  1319.             /* if no loop, zero first two samples of data to prevent "beep" */
  1320.             sampleStarts[0] = 0;
  1321.             sampleStarts[1] = 0;
  1322.         }
  1323.  
  1324.         sampleStarts += (p[0] * 2);
  1325.     }
  1326. }
  1327.  
  1328. /* these are used to create equal powered stereo separation */
  1329. static float sinApx(float x)
  1330. {
  1331.     x = x * (2.0f - x);
  1332.     return (x * 1.09742972f + x * x * 0.31678383f);
  1333. }
  1334.  
  1335. static float cosApx(float x)
  1336. {
  1337.     x = (1.0f - x) * (1.0f + x);
  1338.     return (x * 1.09742972f + x * x * 0.31678383f);
  1339. }
  1340. /* ------------------------------------------------- */
  1341.  
  1342. static void calculatePans(int8_t stereoSeparation)
  1343. {
  1344.     uint8_t scaledPanPos;
  1345.     float p;
  1346.  
  1347.     if (stereoSeparation > 100)
  1348.         stereoSeparation = 100;
  1349.  
  1350.     scaledPanPos = (stereoSeparation * 128) / 100;
  1351.  
  1352.     p = (128 - scaledPanPos) * (1.0f / 256.0f);
  1353.     AUD[0].PANL = cosApx(p);
  1354.     AUD[0].PANR = sinApx(p);
  1355.     AUD[3].PANL = cosApx(p);
  1356.     AUD[3].PANR = sinApx(p);
  1357.  
  1358.     p = (128 + scaledPanPos) * (1.0f / 256.0f);
  1359.     AUD[1].PANL = cosApx(p);
  1360.     AUD[1].PANR = sinApx(p);
  1361.     AUD[2].PANL = cosApx(p);
  1362.     AUD[2].PANR = sinApx(p);
  1363. }
  1364.  
  1365. static void mixSampleBlock(int16_t *streamOut, uint32_t numSamples)
  1366. {
  1367.     uint8_t i;
  1368.     int16_t *sndOut;
  1369.     uint16_t j;
  1370.     int32_t smpL, smpR;
  1371.     float tempSample, tempVolume, out_f[2];
  1372.     paulaVoice_t *v;
  1373. #ifdef USE_BLEP
  1374.     blep_t *bSmp, *bVol;
  1375. #endif
  1376.  
  1377.     memset(masterBufferL, 0, sizeof (float) * numSamples);
  1378.     memset(masterBufferR, 0, sizeof (float) * numSamples);
  1379.  
  1380.     for (i = 0; i < 4; ++i)
  1381.     {
  1382.         v = &AUD[i];
  1383.  
  1384. #ifdef USE_BLEP
  1385.         bSmp = &blep[i];
  1386.         bVol = &blepVol[i];
  1387. #endif
  1388.  
  1389.         if (AUD[i].DELTA > 0.0f)
  1390.         {
  1391.             for (j = 0; j < numSamples; ++j)
  1392.             {
  1393.                 tempSample = (v->DMA_DAT == NULL) ? 0.0f : (v->DMA_DAT[v->DMA_POS] * (1.0f / 128.0f));
  1394.                 tempVolume = (v->DMA_DAT == NULL) ? 0.0f : v->SRC_VOL;
  1395.  
  1396. #ifdef USE_BLEP
  1397.                 if (tempSample != bSmp->lastValue)
  1398.                 {
  1399.                     if ((v->LASTDELTA > 0.0f) && (v->LASTDELTA > v->LASTFRAC))
  1400.                         blepAdd(bSmp, v->LASTFRAC / v->LASTDELTA, bSmp->lastValue - tempSample);
  1401.  
  1402.                     bSmp->lastValue = tempSample;
  1403.                 }
  1404.  
  1405.                 if (tempVolume != bVol->lastValue)
  1406.                 {
  1407.                     blepAdd(bVol, 0.0f, bVol->lastValue - tempVolume);
  1408.                     bVol->lastValue = tempVolume;
  1409.                 }
  1410.  
  1411.                 if (bSmp->samplesLeft) tempSample += blepRun(bSmp);
  1412.                 if (bVol->samplesLeft) tempVolume += blepRun(bVol);
  1413. #endif
  1414.  
  1415.                 tempSample *= tempVolume;
  1416.                 masterBufferL[j] += (tempSample * v->PANL);
  1417.                 masterBufferR[j] += (tempSample * v->PANR);
  1418.  
  1419.                 v->FRAC += v->DELTA;
  1420.                 if (v->FRAC >= 1.0f)
  1421.                 {
  1422.                     v->FRAC -= 1.0f;
  1423.  
  1424.                     v->LASTFRAC  = v->FRAC;
  1425.                     v->LASTDELTA = v->DELTA;
  1426.  
  1427.                     if (++v->DMA_POS >= v->DMA_LEN)
  1428.                     {
  1429.                         v->DMA_POS = 0;
  1430.  
  1431.                         /* re-fetch Paula register values now */
  1432.                         v->DMA_LEN = v->SRC_LEN;
  1433.                         v->DMA_DAT = v->SRC_DAT;
  1434.                     }
  1435.                 }
  1436.             }
  1437.         }
  1438.     }
  1439.  
  1440.     sndOut = streamOut;
  1441.     for (j = 0; j < numSamples; ++j)
  1442.     {
  1443.         if (!DisableMixer)
  1444.         {
  1445.             out_f[0] = masterBufferL[j];
  1446.             out_f[1] = masterBufferR[j];
  1447.  
  1448. #ifdef USE_LOWPASS
  1449.             lossyIntegrator(&filterLo, out_f, out_f);
  1450. #endif
  1451.  
  1452. #ifdef LED_FILTER
  1453.             if (LEDStatus)
  1454.                 lossyIntegratorLED(filterLEDC, &filterLED, out_f, out_f);
  1455. #endif
  1456.  
  1457. #ifdef USE_HIGHPASS
  1458.             lossyIntegratorHighPass(&filterHi, out_f, out_f);
  1459. #endif
  1460.  
  1461.             /* normalize amplitude (also invert waveform, like on a real Amiga) */
  1462.             out_f[0] *= (-32767.0f / NORM_FACTOR);
  1463.             out_f[1] *= (-32767.0f / NORM_FACTOR);
  1464.  
  1465.             /* truncate to signed 32-bit integer */
  1466.             smpL = (int32_t)(out_f[0]);
  1467.             smpR = (int32_t)(out_f[1]);
  1468.  
  1469.             /* clamp to 16-bit signed range */
  1470.             CLAMP16(smpL);
  1471.             CLAMP16(smpR);
  1472.  
  1473.             /* truncate to signed 16-bit integer and store in output buffer */
  1474.             *sndOut++ = (int16_t)(smpL);
  1475.             *sndOut++ = (int16_t)(smpR);
  1476.         }
  1477.         else
  1478.         {
  1479.             *sndOut++ = 0;
  1480.             *sndOut++ = 0;
  1481.         }
  1482.     }
  1483. }
  1484.  
  1485. static void CALLBACK waveOutProc(HWAVEOUT _hWaveOut, UINT uMsg,
  1486.     DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
  1487. {
  1488.     int16_t *outputStream;
  1489.     int32_t sampleBlock, samplesTodo;
  1490.     WAVEHDR *waveBlockHeader;
  1491.  
  1492.     /* make compiler happy! (warning C4100) */
  1493.     (void)(dwParam2);
  1494.     (void)(dwInstance);
  1495.  
  1496.     if (uMsg == MM_WOM_DONE)
  1497.     {
  1498.         mixingMutex = 1;
  1499.  
  1500.         waveBlockHeader = (WAVEHDR *)(dwParam1);
  1501.         waveOutUnprepareHeader(_hWaveOut, waveBlockHeader, sizeof (WAVEHDR));
  1502.  
  1503.         if (isMixing)
  1504.         {
  1505.             memcpy(waveBlockHeader->lpData, mixerBuffer, soundBufferSize);
  1506.  
  1507.             waveOutPrepareHeader(_hWaveOut, waveBlockHeader, sizeof (WAVEHDR));
  1508.             waveOutWrite(_hWaveOut, waveBlockHeader, sizeof (WAVEHDR));
  1509.  
  1510.             outputStream = (int16_t *)(mixerBuffer);
  1511.             sampleBlock  = soundBufferSize / 4;
  1512.  
  1513.             while (sampleBlock)
  1514.             {
  1515.                 samplesTodo = (sampleBlock < samplesLeft) ? sampleBlock : samplesLeft;
  1516.                 if (samplesTodo > soundBufferSize)
  1517.                     samplesTodo = soundBufferSize;
  1518.  
  1519.                 if (samplesTodo > 0)
  1520.                 {
  1521.                     mixSampleBlock(outputStream, samplesTodo);
  1522.                     outputStream += (samplesTodo * 2);
  1523.  
  1524.                     sampleBlock -= samplesTodo;
  1525.                     samplesLeft -= samplesTodo;
  1526.                 }
  1527.                 else
  1528.                 {
  1529.                     if (!DisableMixer)
  1530.                         IntMusic();
  1531.  
  1532.                     samplesLeft = samplesPerFrame;
  1533.                 }
  1534.             }
  1535.         }
  1536.  
  1537.         mixingMutex = 0;
  1538.     }
  1539. }
  1540.  
  1541. void pt2play_PauseSong(int8_t pause)
  1542. {
  1543.     DisableMixer = pause ? 1 : 0;
  1544. }
  1545.  
  1546. void pt2play_PlaySong(uint8_t *moduleData, int8_t tempoMode)
  1547. {
  1548.     uint8_t i;
  1549.  
  1550.     DisableMixer = 1;
  1551.  
  1552.     memset(AUD, 0, sizeof (AUD));
  1553.     for (i = 0; i < 4; ++i)
  1554.     {
  1555.         AUD[i].DMA_DAT = NULL;
  1556.         AUD[i].SRC_DAT = NULL;
  1557.     }
  1558.  
  1559.     moduleInit(moduleData);
  1560.     calculatePans(STEREO_SEP);
  1561.  
  1562. #ifdef USE_BLEP
  1563.     memset(blep,    0, sizeof (blep));
  1564.     memset(blepVol, 0, sizeof (blepVol));
  1565. #endif
  1566.  
  1567. #ifdef USE_LOWPASS
  1568.     clearLossyIntegrator(&filterLo);
  1569. #endif
  1570.  
  1571. #ifdef LED_FILTER
  1572.     clearLEDFilter(&filterLED);
  1573. #endif
  1574.  
  1575. #ifdef USE_HIGHPASS
  1576.     clearLossyIntegrator(&filterHi);
  1577. #endif
  1578.  
  1579.     CurrSpeed      = 6;
  1580.     Counter        = 0;
  1581.     SongPosition   = 0;
  1582.     PatternPos     = 0;
  1583.     PattDelTime    = 0;
  1584.     PattDelTime2   = 0;
  1585.     PBreakPosition = 0;
  1586.     PosJumpAssert  = 0;
  1587.     PBreakFlag     = 0;
  1588.     LowMask        = 0xFF;
  1589.     TempoMode      = tempoMode ? VBLANK_TEMPO_MODE : CIA_TEMPO_MODE;
  1590.     SongPlaying    = 1;
  1591.     DisableMixer   = 0;
  1592.  
  1593. #ifdef LED_FILTER
  1594.     LEDStatus = 0;
  1595. #endif
  1596. }
  1597.  
  1598. void pt2play_SetStereoSep(uint8_t percentage)
  1599. {
  1600.     calculatePans(percentage);
  1601. }
  1602.  
  1603. static int8_t openMixer(uint32_t _samplingFrequency, uint32_t _soundBufferSize)
  1604. {
  1605.     uint8_t i;
  1606.     MMRESULT r;
  1607.  
  1608.     if (!hWaveOut)
  1609.     {
  1610.         f_outputFreq        = (float)(_samplingFrequency);
  1611.         soundBufferSize     = _soundBufferSize;
  1612.         masterBufferL       = (float *)(malloc(soundBufferSize * sizeof (float)));
  1613.         masterBufferR       = (float *)(malloc(soundBufferSize * sizeof (float)));
  1614.         wfx.nSamplesPerSec  = _samplingFrequency;
  1615.         wfx.wBitsPerSample  = 16;
  1616.         wfx.nChannels       = 2;
  1617.         wfx.cbSize          = 0;
  1618.         wfx.wFormatTag      = WAVE_FORMAT_PCM;
  1619.         wfx.nBlockAlign     = (wfx.wBitsPerSample * wfx.nChannels) / 8;
  1620.         wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;
  1621.  
  1622.         if ((masterBufferL == NULL) || (masterBufferR == NULL))
  1623.             return (0); /* gets free'd later */
  1624.  
  1625.         r = waveOutOpen(&hWaveOut, WAVE_MAPPER, &wfx, (DWORD_PTR)(waveOutProc), 0L, CALLBACK_FUNCTION);
  1626.         if (r != MMSYSERR_NOERROR) return (0);
  1627.  
  1628.         for (i = 0; i < MIX_BUF_NUM; ++i)
  1629.         {
  1630.             waveBlocks[i].dwBufferLength = soundBufferSize;
  1631.             waveBlocks[i].lpData = (LPSTR)(calloc(soundBufferSize, 1));
  1632.             if (waveBlocks[i].lpData == NULL)
  1633.                 return (0); /* gets free'd later */
  1634.  
  1635.             waveOutPrepareHeader(hWaveOut, &waveBlocks[i], sizeof (WAVEHDR));
  1636.             waveOutWrite(hWaveOut, &waveBlocks[i], sizeof (WAVEHDR));
  1637.         }
  1638.  
  1639.         mixerBuffer = (int8_t *)(calloc(soundBufferSize, 1));
  1640.         if (mixerBuffer == NULL)
  1641.             return (0); /* gets free'd later */
  1642.  
  1643.         SetReplayerBPM(125);
  1644.  
  1645. #ifdef USE_LOWPASS
  1646.         // Amiga 500 RC low-pass filter (R = 360 ohm, C = 0.1uF)
  1647.         // hz = 1 / (2pi * R * C)    = ~4421.0Hz
  1648.         calcCoeffLossyIntegrator(f_outputFreq, 4421.0f, &filterLo);
  1649. #endif
  1650.  
  1651. #ifdef LED_FILTER
  1652.         // Amiga 500 Sallen-Key "LED" filter (R1 = 10k ohm, R2 = 10k ohm, C1 = 6800pf, C2 = 3900pf)
  1653.         // hz = 1 / (2pi * root(R1 * R2 * C1 * C2))    = ~3090.5Hz
  1654.         calcCoeffLED(f_outputFreq, 3090.5f, &filterLEDC);
  1655. #endif
  1656.  
  1657. #ifdef USE_HIGHPASS
  1658.         // Amiga 500 RC high-pass filter (R = 1390 ohm, C = 22uF)
  1659.         // hz = 1 / (2pi * R * C)    = ~5.2Hz
  1660.         calcCoeffLossyIntegrator(f_outputFreq, 5.2f, &filterHi);
  1661. #endif
  1662.  
  1663.         isMixing = 1;
  1664.         return (1);
  1665.     }
  1666.  
  1667.     return (1);
  1668. }
  1669.  
  1670. void pt2play_Close(void)
  1671. {
  1672.     uint8_t i;
  1673.  
  1674.     DisableMixer = 1;
  1675.  
  1676.     if (isMixing)
  1677.     {
  1678.         isMixing = 0;
  1679.         while (mixingMutex);
  1680.  
  1681.         if (hWaveOut)
  1682.         {
  1683.             for (i = 0; i < MIX_BUF_NUM; ++i)
  1684.                 waveOutUnprepareHeader(hWaveOut, &waveBlocks[i], sizeof (WAVEHDR));
  1685.  
  1686.             for (i = 0; i < MIX_BUF_NUM; ++i)
  1687.             {
  1688.                 while (waveBlocks[i].dwFlags & WHDR_PREPARED);
  1689.                 if (waveBlocks[i].lpData != NULL)
  1690.                 {
  1691.                     free(waveBlocks[i].lpData);
  1692.                     waveBlocks[i].lpData = NULL;
  1693.                 }
  1694.             }
  1695.  
  1696.             waveOutReset(hWaveOut);
  1697.             waveOutClose(hWaveOut);
  1698.  
  1699.             hWaveOut = 0;
  1700.  
  1701.             if (mixerBuffer != NULL)
  1702.             {
  1703.                 free(mixerBuffer);
  1704.                 mixerBuffer = NULL;
  1705.             }
  1706.  
  1707.             if (masterBufferL != NULL)
  1708.             {
  1709.                 free(masterBufferL);
  1710.                 masterBufferL = NULL;
  1711.             }
  1712.  
  1713.             if (masterBufferR != NULL)
  1714.             {
  1715.                 free(masterBufferR);
  1716.                 masterBufferR = NULL;
  1717.             }
  1718.         }
  1719.     }
  1720. }
  1721.  
  1722. int8_t pt2play_Init(uint32_t outputFreq)
  1723. {
  1724.     SongPlaying = 0;
  1725.  
  1726.     if (!openMixer(outputFreq, MIX_BUF_LEN))
  1727.     {
  1728.         pt2play_Close();
  1729.         return (0);
  1730.     }
  1731.  
  1732.     return (1);
  1733. }
  1734.  
  1735. /* END OF FILE */
RAW Paste Data
Top