SHARE
TWEET

pt2play v1.4

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