SHARE
TWEET

pt2play v1.46

8bitbubsy Sep 29th, 2013 (edited) 878 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2. ** PT2PLAY v1.46 - 2nd of October 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.         /* confirmed behavior on real Amiga */
  298.         if (period < 113)
  299.             period = 113;
  300.  
  301.         AUD[i].DELTA = ((float)(PAULA_PAL_CLK) / period) / f_outputFreq;
  302.     }
  303.  
  304.     if (AUD[i].LASTDELTA == 0.0f)
  305.         AUD[i].LASTDELTA = AUD[i].DELTA;
  306. }
  307.  
  308. static void PaulaSetVolume(uint8_t i, uint16_t vol)
  309. {
  310.     vol &= 0x007F;
  311.     if (vol > 0x40)
  312.         vol = 0x40;
  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 = 2 * len;
  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.     if ((offset < 0.0f) || (offset > 1.0f))
  410.         return;
  411.  
  412.     i  = (uint32_t)(offset * BLEP_SP);
  413.     blepSrc = (const float *)(blepData) + i + BLEP_OS;
  414.  
  415.     f = (offset * BLEP_SP) - i;
  416.     i = b->index;
  417.  
  418.     n = BLEP_NS;
  419.     while (n--)
  420.     {
  421.         b->buffer[i] += (amplitude * LERP(blepSrc[0], blepSrc[1], f));
  422.  
  423.         i++;
  424.         i &= BLEP_RNS;
  425.  
  426.         blepSrc += BLEP_SP;
  427.     }
  428.  
  429.     b->samplesLeft = BLEP_NS;
  430. }
  431.  
  432. static inline float blepRun(blep_t *b)
  433. {
  434.     float blepOutput;
  435.  
  436.     blepOutput = b->buffer[b->index];
  437.     b->buffer[b->index] = 0.0f;
  438.  
  439.     b->index++;
  440.     b->index &= BLEP_RNS;
  441.  
  442.     b->samplesLeft--;
  443.  
  444.     return (blepOutput);
  445. }
  446. #endif
  447.  
  448. static void UpdateFunk(ptChannel_t *ch)
  449. {
  450.     int8_t funkspeed;
  451.  
  452.     funkspeed = ch->n_glissfunk >> 4;
  453.     if (funkspeed > 0)
  454.     {
  455.         ch->n_funkoffset += FunkTable[funkspeed];
  456.         if (ch->n_funkoffset >= 128)
  457.         {
  458.             ch->n_funkoffset = 0;
  459.  
  460.             if ((ch->n_loopstart != NULL) && (ch->n_wavestart != NULL)) /* SAFETY BUG FIX */
  461.             {
  462.                 if (++ch->n_wavestart >= (ch->n_loopstart + (ch->n_replen * 2)))
  463.                       ch->n_wavestart  =  ch->n_loopstart;
  464.  
  465.                 *ch->n_wavestart = -1 - *ch->n_wavestart;
  466.             }
  467.         }
  468.     }
  469. }
  470.  
  471. static void SetGlissControl(ptChannel_t *ch)
  472. {
  473.     ch->n_glissfunk = (ch->n_glissfunk & 0xF0) | (ch->n_cmd & 0x000F);
  474. }
  475.  
  476. static void SetVibratoControl(ptChannel_t *ch)
  477. {
  478.     ch->n_wavecontrol = (ch->n_wavecontrol & 0xF0) | (ch->n_cmd & 0x000F);
  479. }
  480.  
  481. static void SetFineTune(ptChannel_t *ch)
  482. {
  483.     ch->n_finetune = ch->n_cmd & 0x000F;
  484. }
  485.  
  486. static void JumpLoop(ptChannel_t *ch)
  487. {
  488.     if (!Counter)
  489.     {
  490.         if (!(ch->n_cmd & 0x000F))
  491.         {
  492.             ch->n_pattpos = (PatternPos / 16) & 0x00FF;
  493.         }
  494.         else
  495.         {
  496.             if (!ch->n_loopcount)
  497.             {
  498.                 ch->n_loopcount = ch->n_cmd & 0x000F;
  499.             }
  500.             else
  501.             {
  502.                 if (!--ch->n_loopcount)
  503.                     return;
  504.             }
  505.  
  506.             PBreakPosition = ch->n_pattpos;
  507.             PBreakFlag = 1;
  508.         }
  509.     }
  510. }
  511.  
  512. static void SetTremoloControl(ptChannel_t *ch)
  513. {
  514.     ch->n_wavecontrol = ((ch->n_cmd & 0x000F) << 4) | (ch->n_wavecontrol & 0x0F);
  515. }
  516.  
  517. static void KarplusStrong(ptChannel_t *ch)
  518. {
  519. #ifdef ENABLE_E8_EFFECT
  520.     int8_t *smpPtr;
  521.     int16_t dat;
  522.     uint16_t len;
  523.  
  524.     smpPtr = ch->n_loopstart;
  525.     if (smpPtr != NULL) /* SAFETY BUG FIX */
  526.     {
  527.         len = ((ch->n_replen * 2) & 0xFFFF) - 1;
  528.         while (len--)
  529.         {
  530.             dat = smpPtr[1] + smpPtr[0];
  531.  
  532.             /* "arithmetic shift right" on signed number simulation */
  533.             if (dat < 0)
  534.                 dat = 0x8000 | ((uint16_t)(dat) >> 1); /* 0x8000 = 2^16 - 2^(16-1) */
  535.             else
  536.                 dat /= 2;
  537.  
  538.             *smpPtr++ = dat & 0x00FF;
  539.         }
  540.  
  541.         dat = ch->n_loopstart[0] + smpPtr[0];
  542.  
  543.         /* "arithmetic shift right" on signed number simulation */
  544.         if (dat < 0)
  545.             dat = 0x8000 | ((uint16_t)(dat) >> 1);
  546.         else
  547.             dat /= 2;
  548.  
  549.         *smpPtr = dat & 0x00FF;
  550.     }
  551. #else
  552.     (void)(ch);
  553. #endif
  554. }
  555.  
  556. static void DoRetrg(ptChannel_t *ch)
  557. {
  558.     PaulaSetData(ch->n_index, ch->n_start); /* n_start is increased on 9xx */
  559.     PaulaSetLength(ch->n_index, ch->n_length);
  560.     PaulaSetPeriod(ch->n_index, ch->n_period);
  561.     PaulaRestartDMA(ch->n_index);
  562.  
  563.     /* these take effect after the current DMA cycle is done */
  564.     PaulaSetData(ch->n_index, ch->n_loopstart);
  565.     PaulaSetLength(ch->n_index, ch->n_replen);
  566. }
  567.  
  568. static void RetrigNote(ptChannel_t *ch)
  569. {
  570.     if (ch->n_cmd & 0x000F)
  571.     {
  572.         if (!Counter)
  573.         {
  574.             if (ch->n_note & 0x0FFF)
  575.                 return;
  576.         }
  577.  
  578.         if (!(Counter % (ch->n_cmd & 0x000F)))
  579.             DoRetrg(ch);
  580.     }
  581. }
  582.  
  583. static void VolumeSlide(ptChannel_t *ch)
  584. {
  585.     uint8_t cmd;
  586.  
  587.     cmd = ch->n_cmd & 0x00FF;
  588.     if (!(cmd & 0xF0))
  589.     {
  590.         ch->n_volume -= (cmd & 0x0F);
  591.         if (ch->n_volume < 0)
  592.             ch->n_volume = 0;
  593.     }
  594.     else
  595.     {
  596.         ch->n_volume += (cmd >> 4);
  597.         if (ch->n_volume > 64)
  598.             ch->n_volume = 64;
  599.     }
  600. }
  601.  
  602. static void VolumeFineUp(ptChannel_t *ch)
  603. {
  604.     if (!Counter)
  605.     {
  606.         ch->n_volume += (ch->n_cmd & 0x000F);
  607.         if (ch->n_volume > 64)
  608.             ch->n_volume = 64;
  609.     }
  610. }
  611.  
  612. static void VolumeFineDown(ptChannel_t *ch)
  613. {
  614.     if (!Counter)
  615.     {
  616.         ch->n_volume -= (ch->n_cmd & 0x000F);
  617.         if (ch->n_volume < 0)
  618.             ch->n_volume = 0;
  619.     }
  620. }
  621.  
  622. static void NoteCut(ptChannel_t *ch)
  623. {
  624.     if (Counter == (ch->n_cmd & 0x000F))
  625.         ch->n_volume = 0;
  626. }
  627.  
  628. static void NoteDelay(ptChannel_t *ch)
  629. {
  630.     if (Counter == (ch->n_cmd & 0x000F))
  631.     {
  632.         if (ch->n_note & 0x0FFF)
  633.             DoRetrg(ch);
  634.     }
  635. }
  636.  
  637. static void PatternDelay(ptChannel_t *ch)
  638. {
  639.     if (!Counter)
  640.     {
  641.         if (!PattDelTime2)
  642.             PattDelTime = (ch->n_cmd & 0x000F) + 1;
  643.     }
  644. }
  645.  
  646. static void FunkIt(ptChannel_t *ch)
  647. {
  648.     if (!Counter)
  649.     {
  650.         ch->n_glissfunk = ((ch->n_cmd & 0x000F) << 4) | (ch->n_glissfunk & 0x0F);
  651.  
  652.         if (ch->n_glissfunk & 0xF0)
  653.             UpdateFunk(ch);
  654.     }
  655. }
  656.  
  657. static void PositionJump(ptChannel_t *ch)
  658. {
  659.     SongPosition   = (ch->n_cmd & 0x00FF) - 1; /* 0xFF (B00) jumps to pat 0 */
  660.     PBreakPosition = 0;
  661.     PosJumpAssert  = 1;
  662. }
  663.  
  664. static void VolumeChange(ptChannel_t *ch)
  665. {
  666.     ch->n_volume = ch->n_cmd & 0x00FF;
  667.     if ((uint8_t)(ch->n_volume) > 64)
  668.         ch->n_volume = 64;
  669. }
  670.  
  671. static void PatternBreak(ptChannel_t *ch)
  672. {
  673.     PBreakPosition = (((ch->n_cmd & 0x00F0) >> 4) * 10) + (ch->n_cmd & 0x000F);
  674.     if ((uint8_t)(PBreakPosition) > 63)
  675.         PBreakPosition = 0;
  676.  
  677.     PosJumpAssert = 1;
  678. }
  679.  
  680. static void SetSpeed(ptChannel_t *ch)
  681. {
  682.     if (ch->n_cmd & 0x00FF)
  683.     {
  684.         Counter = 0;
  685.  
  686.         if ((TempoMode == VBLANK_TEMPO_MODE) || ((ch->n_cmd & 0x00FF) < 32))
  687.             CurrSpeed = ch->n_cmd & 0x00FF;
  688.         else
  689.             SetBPMFlag = ch->n_cmd & 0x00FF; /* CIA doesn't refresh its registers until the next interrupt, so change it later */
  690.     }
  691. }
  692.  
  693. static void Arpeggio(ptChannel_t *ch)
  694. {
  695.     uint8_t i, dat;
  696.     const int16_t *arpPointer;
  697.  
  698.     dat = Counter % 3;
  699.     if (!dat)
  700.     {
  701.         PaulaSetPeriod(ch->n_index, ch->n_period);
  702.     }
  703.     else
  704.     {
  705.              if (dat == 1) dat = (ch->n_cmd & 0x00F0) >> 4;
  706.         else if (dat == 2) dat =  ch->n_cmd & 0x000F;
  707.  
  708.         arpPointer = &PeriodTable[37 * ch->n_finetune];
  709.         for (i = 0; i < 37; ++i)
  710.         {
  711.             if (ch->n_period >= arpPointer[i])
  712.             {
  713.                 PaulaSetPeriod(ch->n_index, arpPointer[i + dat]);
  714.                 break;
  715.             }
  716.         }
  717.     }
  718. }
  719.  
  720. static void PortaUp(ptChannel_t *ch)
  721. {
  722.     ch->n_period -= ((ch->n_cmd & 0x00FF) & LowMask);
  723.     LowMask = 0xFF;
  724.  
  725.     if ((ch->n_period & 0x0FFF) < 113)
  726.         ch->n_period = (ch->n_period & 0xF000) | 113;
  727.  
  728.     PaulaSetPeriod(ch->n_index, ch->n_period & 0x0FFF);
  729. }
  730.  
  731. static void PortaDown(ptChannel_t *ch)
  732. {
  733.     ch->n_period += ((ch->n_cmd & 0x00FF) & LowMask);
  734.     LowMask = 0xFF;
  735.  
  736.     if ((ch->n_period & 0x0FFF) > 856)
  737.         ch->n_period = (ch->n_period & 0xF000) | 856;
  738.  
  739.     PaulaSetPeriod(ch->n_index, ch->n_period & 0x0FFF);
  740. }
  741.  
  742. static void FilterOnOff(ptChannel_t *ch)
  743. {
  744. #ifdef LED_FILTER
  745.     LEDStatus = !(ch->n_cmd & 0x0001);
  746. #endif
  747. }
  748.  
  749. static void FinePortaUp(ptChannel_t *ch)
  750. {
  751.     if (!Counter)
  752.     {
  753.         LowMask = 0x0F;
  754.         PortaUp(ch);
  755.     }
  756. }
  757.  
  758. static void FinePortaDown(ptChannel_t *ch)
  759. {
  760.     if (!Counter)
  761.     {
  762.         LowMask = 0x0F;
  763.         PortaDown(ch);
  764.     }
  765. }
  766.  
  767. static void SetTonePorta(ptChannel_t *ch)
  768. {
  769.     uint8_t i;
  770.     const int16_t *portaPointer;
  771.     uint16_t note;
  772.  
  773.     note = ch->n_note & 0x0FFF;
  774.     portaPointer = &PeriodTable[37 * ch->n_finetune];
  775.  
  776.     i = 0;
  777.     for (;;)
  778.     {
  779.         /* portaPointer[36] = 0, so i=36 is safe */
  780.         if (note >= portaPointer[i])
  781.             break;
  782.  
  783.         if (++i >= 37)
  784.         {
  785.             i = 35;
  786.             break;
  787.         }
  788.     }
  789.  
  790.     if ((ch->n_finetune & 8) && i) i--;
  791.  
  792.     ch->n_wantedperiod  = portaPointer[i];
  793.     ch->n_toneportdirec = 0;
  794.  
  795.          if (ch->n_period == ch->n_wantedperiod) ch->n_wantedperiod  = 0;
  796.     else if (ch->n_period  > ch->n_wantedperiod) ch->n_toneportdirec = 1;
  797. }
  798.  
  799. static void TonePortNoChange(ptChannel_t *ch)
  800. {
  801.     uint8_t i;
  802.     const int16_t *portaPointer;
  803.  
  804.     if (ch->n_wantedperiod)
  805.     {
  806.         if (ch->n_toneportdirec)
  807.         {
  808.             ch->n_period -= ch->n_toneportspeed;
  809.             if (ch->n_period <= ch->n_wantedperiod)
  810.             {
  811.                 ch->n_period = ch->n_wantedperiod;
  812.                 ch->n_wantedperiod = 0;
  813.             }
  814.         }
  815.         else
  816.         {
  817.             ch->n_period += ch->n_toneportspeed;
  818.             if (ch->n_period >= ch->n_wantedperiod)
  819.             {
  820.                 ch->n_period = ch->n_wantedperiod;
  821.                 ch->n_wantedperiod = 0;
  822.             }
  823.         }
  824.  
  825.         if (!(ch->n_glissfunk & 0x0F))
  826.         {
  827.             PaulaSetPeriod(ch->n_index, ch->n_period);
  828.         }
  829.         else
  830.         {
  831.             portaPointer = &PeriodTable[37 * ch->n_finetune];
  832.  
  833.             i = 0;
  834.             for (;;)
  835.             {
  836.                 /* portaPointer[36] = 0, so i=36 is safe */
  837.                 if (ch->n_period >= portaPointer[i])
  838.                     break;
  839.  
  840.                 if (++i >= 37)
  841.                 {
  842.                     i = 35;
  843.                     break;
  844.                 }
  845.             }
  846.  
  847.             PaulaSetPeriod(ch->n_index, portaPointer[i]);
  848.         }
  849.     }
  850. }
  851.  
  852. static void TonePortamento(ptChannel_t *ch)
  853. {
  854.     if (ch->n_cmd & 0x00FF)
  855.     {
  856.         ch->n_toneportspeed = ch->n_cmd & 0x00FF;
  857.         ch->n_cmd &= 0xFF00;
  858.     }
  859.  
  860.     TonePortNoChange(ch);
  861. }
  862.  
  863. static void VibratoNoChange(ptChannel_t *ch)
  864. {
  865.     uint8_t vibratoTemp;
  866.     int16_t vibratoData;
  867.  
  868.     vibratoTemp = (ch->n_vibratopos / 4) & 31;
  869.     vibratoData = ch->n_wavecontrol & 3;
  870.  
  871.     if (!vibratoData)
  872.     {
  873.         vibratoData = VibratoTable[vibratoTemp];
  874.     }
  875.     else
  876.     {
  877.         if (vibratoData == 1)
  878.         {
  879.             if (ch->n_vibratopos < 0)
  880.                 vibratoData = 255 - (vibratoTemp * 8);
  881.             else
  882.                 vibratoData = vibratoTemp * 8;
  883.         }
  884.         else
  885.         {
  886.             vibratoData = 255;
  887.         }
  888.     }
  889.  
  890.     vibratoData = (vibratoData * (ch->n_vibratocmd & 0x0F)) / 128;
  891.  
  892.     if (ch->n_vibratopos < 0)
  893.         vibratoData = ch->n_period - vibratoData;
  894.     else
  895.         vibratoData = ch->n_period + vibratoData;
  896.  
  897.     PaulaSetPeriod(ch->n_index, vibratoData);
  898.  
  899.     ch->n_vibratopos += ((ch->n_vibratocmd >> 4) * 4);
  900. }
  901.  
  902. static void Vibrato(ptChannel_t *ch)
  903. {
  904.     if (ch->n_cmd & 0x00FF)
  905.     {
  906.         if (ch->n_cmd & 0x000F)
  907.             ch->n_vibratocmd = (ch->n_vibratocmd & 0xF0) | (ch->n_cmd & 0x000F);
  908.  
  909.         if (ch->n_cmd & 0x00F0)
  910.             ch->n_vibratocmd = (ch->n_cmd & 0x00F0) | (ch->n_vibratocmd & 0x0F);
  911.     }
  912.  
  913.     VibratoNoChange(ch);
  914. }
  915.  
  916. static void TonePlusVolSlide(ptChannel_t *ch)
  917. {
  918.     TonePortNoChange(ch);
  919.     VolumeSlide(ch);
  920. }
  921.  
  922. static void VibratoPlusVolSlide(ptChannel_t *ch)
  923. {
  924.     VibratoNoChange(ch);
  925.     VolumeSlide(ch);
  926. }
  927.  
  928. static void Tremolo(ptChannel_t *ch)
  929. {
  930.     int8_t tremoloTemp;
  931.     int16_t tremoloData;
  932.  
  933.     if (ch->n_cmd & 0x00FF)
  934.     {
  935.         if (ch->n_cmd & 0x000F)
  936.             ch->n_tremolocmd = (ch->n_tremolocmd & 0xF0) | (ch->n_cmd & 0x000F);
  937.  
  938.         if (ch->n_cmd & 0x00F0)
  939.             ch->n_tremolocmd = (ch->n_cmd & 0x00F0) | (ch->n_tremolocmd & 0x0F);
  940.     }
  941.  
  942.     tremoloTemp = (ch->n_tremolopos / 4) & 31;
  943.     tremoloData = (ch->n_wavecontrol >> 4) & 3;
  944.  
  945.     if (!tremoloData)
  946.     {
  947.         tremoloData = VibratoTable[tremoloTemp];
  948.     }
  949.     else
  950.     {
  951.         if (tremoloData == 1)
  952.         {
  953.             if (ch->n_vibratopos < 0) /* PT bug, should've been n_tremolopos */
  954.                 tremoloData = 255 - (tremoloTemp * 8);
  955.             else
  956.                 tremoloData = tremoloTemp * 8;
  957.         }
  958.         else
  959.         {
  960.             tremoloData = 255;
  961.         }
  962.     }
  963.  
  964.     tremoloData = (tremoloData * (ch->n_tremolocmd & 0x0F)) / 64;
  965.  
  966.     if (ch->n_tremolopos < 0)
  967.     {
  968.         tremoloData = ch->n_volume - tremoloData;
  969.         if (tremoloData < 0)
  970.             tremoloData = 0;
  971.     }
  972.     else
  973.     {
  974.         tremoloData = ch->n_volume + tremoloData;
  975.         if (tremoloData > 64)
  976.             tremoloData = 64;
  977.     }
  978.  
  979.     PaulaSetVolume(ch->n_index, tremoloData);
  980.  
  981.     ch->n_tremolopos += ((ch->n_tremolocmd >> 4) * 4);
  982. }
  983.  
  984. static void SampleOffset(ptChannel_t *ch)
  985. {
  986.     uint16_t newOffset;
  987.  
  988.     if (ch->n_cmd & 0x00FF)
  989.         ch->n_sampleoffset = ch->n_cmd & 0x00FF;
  990.  
  991.     newOffset = ch->n_sampleoffset * 128;
  992.     if ((ch->n_length <= 32767) && (newOffset < ch->n_length))
  993.     {
  994.         ch->n_length -=  newOffset;
  995.         ch->n_start  += (newOffset * 2);
  996.     }
  997.     else
  998.     {
  999.         ch->n_length = 1; /* this must NOT be set to 0! 1 is the correct value */
  1000.     }
  1001. }
  1002.  
  1003. static void E_Commands(ptChannel_t *ch)
  1004. {
  1005.     switch ((ch->n_cmd & 0x00F0) >> 4)
  1006.     {
  1007.         case 0x00: FilterOnOff(ch);       break;
  1008.         case 0x01: FinePortaUp(ch);       break;
  1009.         case 0x02: FinePortaDown(ch);     break;
  1010.         case 0x03: SetGlissControl(ch);   break;
  1011.         case 0x04: SetVibratoControl(ch); break;
  1012.         case 0x05: SetFineTune(ch);       break;
  1013.         case 0x06: JumpLoop(ch);          break;
  1014.         case 0x07: SetTremoloControl(ch); break;
  1015.         case 0x08: KarplusStrong(ch);     break;
  1016.         case 0x09: RetrigNote(ch);        break;
  1017.         case 0x0A: VolumeFineUp(ch);      break;
  1018.         case 0x0B: VolumeFineDown(ch);    break;
  1019.         case 0x0C: NoteCut(ch);           break;
  1020.         case 0x0D: NoteDelay(ch);         break;
  1021.         case 0x0E: PatternDelay(ch);      break;
  1022.         case 0x0F: FunkIt(ch);            break;
  1023.     }
  1024. }
  1025.  
  1026. static void CheckMoreEffects(ptChannel_t *ch)
  1027. {
  1028.     switch ((ch->n_cmd & 0x0F00) >> 8)
  1029.     {
  1030.         case 0x09: SampleOffset(ch); break;
  1031.         case 0x0B: PositionJump(ch); break;
  1032.         case 0x0D: PatternBreak(ch); break;
  1033.         case 0x0E: E_Commands(ch);   break;
  1034.         case 0x0F: SetSpeed(ch);     break;
  1035.         case 0x0C: VolumeChange(ch); break;
  1036.  
  1037.         default: PaulaSetPeriod(ch->n_index, ch->n_period); break;
  1038.     }
  1039. }
  1040.  
  1041. static void CheckEffects(ptChannel_t *ch)
  1042. {
  1043.     uint8_t effect;
  1044.  
  1045.     UpdateFunk(ch);
  1046.  
  1047.     effect = (ch->n_cmd & 0x0F00) >> 8;
  1048.     if (ch->n_cmd & 0x0FFF)
  1049.     {
  1050.         switch (effect)
  1051.         {
  1052.             case 0x00: Arpeggio(ch);            break;
  1053.             case 0x01: PortaUp(ch);             break;
  1054.             case 0x02: PortaDown(ch);           break;
  1055.             case 0x03: TonePortamento(ch);      break;
  1056.             case 0x04: Vibrato(ch);             break;
  1057.             case 0x05: TonePlusVolSlide(ch);    break;
  1058.             case 0x06: VibratoPlusVolSlide(ch); break;
  1059.             case 0x0E: E_Commands(ch);          break;
  1060.             case 0x07:
  1061.                 PaulaSetPeriod(ch->n_index, ch->n_period);
  1062.                 Tremolo(ch);
  1063.             break;
  1064.             case 0x0A:
  1065.                 PaulaSetPeriod(ch->n_index, ch->n_period);
  1066.                 VolumeSlide(ch);
  1067.             break;
  1068.  
  1069.             default: PaulaSetPeriod(ch->n_index, ch->n_period); break;
  1070.         }
  1071.     }
  1072.  
  1073.     if (effect != 0x07)
  1074.         PaulaSetVolume(ch->n_index, ch->n_volume);
  1075. }
  1076.  
  1077. static void SetPeriod(ptChannel_t *ch)
  1078. {
  1079.     uint8_t i;
  1080.     uint16_t note;
  1081.  
  1082.     note = ch->n_note & 0x0FFF;
  1083.     for (i = 0; i < 37; ++i)
  1084.     {
  1085.         /* PeriodTable[36] = 0, so i=36 is safe */
  1086.         if (note >= PeriodTable[i])
  1087.             break;
  1088.     }
  1089.  
  1090.     /* BUG: yes it's 'safe' if i=37 because of padding at the end of period table */
  1091.     ch->n_period = PeriodTable[(37 * ch->n_finetune) + i];
  1092.  
  1093.     if ((ch->n_cmd & 0x0FF0) != 0x0ED0) /* no note delay */
  1094.     {
  1095.         if (!(ch->n_wavecontrol & 0x04)) ch->n_vibratopos = 0;
  1096.         if (!(ch->n_wavecontrol & 0x40)) ch->n_tremolopos = 0;
  1097.  
  1098.         PaulaSetLength(ch->n_index, ch->n_length);
  1099.         PaulaSetData(ch->n_index, ch->n_start);
  1100.  
  1101.         if (ch->n_start == NULL)
  1102.         {
  1103.             ch->n_loopstart = NULL;
  1104.             PaulaSetLength(ch->n_index, 1);
  1105.             ch->n_replen = 1;
  1106.         }
  1107.  
  1108.         PaulaSetPeriod(ch->n_index, ch->n_period);
  1109.         PaulaRestartDMA(ch->n_index);
  1110.     }
  1111.  
  1112.     CheckMoreEffects(ch);
  1113. }
  1114.  
  1115. static void PlayVoice(ptChannel_t *ch)
  1116. {
  1117.     uint8_t *dataPtr, sample, cmd;
  1118.     uint16_t sampleOffset, repeat;
  1119.  
  1120.     if (!ch->n_note && !ch->n_cmd)
  1121.         PaulaSetPeriod(ch->n_index, ch->n_period);
  1122.  
  1123.     dataPtr = &SongDataPtr[PattPosOff];
  1124.  
  1125.     ch->n_note = (dataPtr[0] << 8) | dataPtr[1];
  1126.     ch->n_cmd  = (dataPtr[2] << 8) | dataPtr[3];
  1127.  
  1128.     sample = (dataPtr[0] & 0xF0) | (dataPtr[2] >> 4);
  1129.     if ((sample >= 1) && (sample <= 31)) /* SAFETY BUG FIX: don't handle sample-numbers >31 */
  1130.     {
  1131.         sample--;
  1132.         sampleOffset = 42 + (30 * sample);
  1133.  
  1134.         ch->n_start    = SampleStarts[sample];
  1135.         ch->n_finetune = SongDataPtr[sampleOffset + 2] & 0x0F; /* SAFETY BUG FIX: mask finetune */
  1136.         ch->n_volume   = SongDataPtr[sampleOffset + 3];
  1137.         ch->n_length   = *PTR2WORD(&SongDataPtr[sampleOffset + 0]);
  1138.         ch->n_replen   = *PTR2WORD(&SongDataPtr[sampleOffset + 6]);
  1139.  
  1140.         repeat = *PTR2WORD(&SongDataPtr[sampleOffset + 4]);
  1141.         if (repeat > 0)
  1142.         {
  1143.             ch->n_loopstart = ch->n_start + (repeat * 2);
  1144.             ch->n_wavestart = ch->n_loopstart;
  1145.             ch->n_length    = repeat + ch->n_replen;
  1146.         }
  1147.         else
  1148.         {
  1149.             ch->n_loopstart = ch->n_start;
  1150.             ch->n_wavestart = ch->n_start;
  1151.         }
  1152.        
  1153.         if (ch->n_start == NULL)
  1154.             ch->n_loopstart = ch->n_wavestart = emptySample;    
  1155.     }
  1156.  
  1157.     if (ch->n_note & 0x0FFF)
  1158.     {
  1159.         if ((ch->n_cmd & 0x0FF0) == 0x0E50) /* set finetune */
  1160.         {
  1161.             SetFineTune(ch);
  1162.             SetPeriod(ch);
  1163.         }
  1164.         else
  1165.         {
  1166.             cmd = (ch->n_cmd & 0x0F00) >> 8;
  1167.             if ((cmd == 0x03) || (cmd == 0x05))
  1168.             {
  1169.                 SetTonePorta(ch);
  1170.                 CheckMoreEffects(ch);
  1171.             }
  1172.             else if (cmd == 0x09)
  1173.             {
  1174.                 CheckMoreEffects(ch);
  1175.                 SetPeriod(ch);
  1176.             }
  1177.             else
  1178.             {
  1179.                 SetPeriod(ch);
  1180.             }
  1181.         }
  1182.     }
  1183.     else
  1184.     {
  1185.         CheckMoreEffects(ch);
  1186.     }
  1187.  
  1188.     PattPosOff += 4;
  1189. }
  1190.  
  1191. static void NextPosition(void)
  1192. {
  1193.     PatternPos     = PBreakPosition * 16;
  1194.     PBreakPosition = 0;
  1195.     PosJumpAssert  = 0;
  1196.  
  1197.     SongPosition = (SongPosition + 1) & 0x7F;
  1198.     if (SongPosition >= SongDataPtr[950])
  1199.         SongPosition = 0;
  1200. }
  1201.  
  1202. static void IntMusic(void) /* called (SongBPM/2.5) times a second (duration: 1000/(SongBPM/2.5) milliseconds) */
  1203. {
  1204.     uint8_t i;
  1205.    
  1206.     if (!SongPlaying) return;
  1207.  
  1208.     /* PT quirk: CIA refreshes its timer values on the next interrupt, so do the real tempo change here */
  1209.     if (SetBPMFlag != 0)
  1210.     {
  1211.         SetReplayerBPM(SetBPMFlag);
  1212.         SetBPMFlag = 0;
  1213.     }
  1214.  
  1215.     if (++Counter >= CurrSpeed)
  1216.     {
  1217.         Counter = 0;
  1218.  
  1219.         if (!PattDelTime2)
  1220.         {
  1221.             PattPosOff = (1084 + (SongDataPtr[952 + SongPosition] * 1024)) + PatternPos;
  1222.  
  1223.             for (i = 0; i < 4; ++i)
  1224.             {
  1225.                 PlayVoice(&ChanTemp[i]);
  1226.                 PaulaSetVolume(i, ChanTemp[i].n_volume);
  1227.  
  1228.                 /* these take effect after the current DMA cycle is done */
  1229.                 PaulaSetData(i, ChanTemp[i].n_loopstart);
  1230.                 PaulaSetLength(i, ChanTemp[i].n_replen);
  1231.             }
  1232.         }
  1233.         else
  1234.         {
  1235.             for (i = 0; i < 4; ++i)
  1236.                 CheckEffects(&ChanTemp[i]);
  1237.         }
  1238.  
  1239.         PatternPos += 16;
  1240.  
  1241.         if (PattDelTime)
  1242.         {
  1243.             PattDelTime2 = PattDelTime;
  1244.             PattDelTime  = 0;
  1245.         }
  1246.  
  1247.         if (PattDelTime2)
  1248.         {
  1249.             PattDelTime2--;
  1250.             if (PattDelTime2) PatternPos -= 16;
  1251.         }
  1252.  
  1253.         if (PBreakFlag)
  1254.         {
  1255.             PatternPos = PBreakPosition * 16;
  1256.             PBreakPosition = 0;
  1257.             PBreakFlag = 0;
  1258.         }
  1259.  
  1260.         if ((PatternPos >= 1024) || PosJumpAssert)
  1261.             NextPosition();
  1262.     }
  1263.     else
  1264.     {
  1265.         for (i = 0; i < 4; ++i)
  1266.             CheckEffects(&ChanTemp[i]);
  1267.  
  1268.         if (PosJumpAssert)
  1269.             NextPosition();
  1270.     }
  1271. }
  1272.  
  1273. static void moduleInit(uint8_t *moduleData)
  1274. {
  1275.     int8_t pattNum;
  1276.     uint8_t *sampleStarts, i;
  1277.     uint16_t *p;
  1278.  
  1279.     for (i = 0; i < 4; ++i)
  1280.         ChanTemp[i].n_index = i;
  1281.  
  1282.     SongDataPtr = moduleData;
  1283.  
  1284.     pattNum = 0;
  1285.     for (i = 0; i < 128; ++i)
  1286.     {
  1287.         if (SongDataPtr[952 + i] > pattNum)
  1288.             pattNum = SongDataPtr[952 + i];
  1289.     }
  1290.     pattNum++;
  1291.  
  1292.     sampleStarts = &SongDataPtr[1084 + (pattNum * 1024)];
  1293.     for (i = 0; i < 31; ++i)
  1294.     {
  1295.         p = PTR2WORD(&SongDataPtr[42 + (30 * i)]);
  1296.  
  1297.         /* swap bytes in words (Amiga word -> Intel word) */
  1298.         p[0] = SWAP16(p[0]); /* n_length */
  1299.         p[2] = SWAP16(p[2]); /* n_repeat */
  1300.         p[3] = SWAP16(p[3]); /* n_replen */
  1301.  
  1302.         if (p[0] == 0)
  1303.             SampleStarts[i] = NULL; /* set to NULL if empty sample */
  1304.         else
  1305.             SampleStarts[i] = (int8_t *)(sampleStarts);
  1306.  
  1307.         /* loop point sanity checking */
  1308.         if ((p[2] + p[3]) > p[0])
  1309.         {
  1310.             if (((p[2] / 2) + p[3]) <= p[0])
  1311.             {
  1312.                 /* fix for poorly converted STK->PT modules */
  1313.                 p[2] /= 2;
  1314.             }
  1315.             else
  1316.             {
  1317.                 /* loop points are still illegal, deactivate loop */
  1318.                 p[2] = 0;
  1319.                 p[3] = 1;
  1320.             }
  1321.         }
  1322.  
  1323.         if (p[3] <= 1)
  1324.             p[3] = 1; /* fix illegal loop length (f.ex. from "Fasttracker II" .MODs) */
  1325.  
  1326.         if ((p[0] >= 1) && ((p[2] + p[3]) <= 1))
  1327.         {
  1328.             /* if no loop, zero first two samples of data to prevent "beep" */
  1329.             sampleStarts[0] = 0;
  1330.             sampleStarts[1] = 0;
  1331.         }
  1332.  
  1333.         sampleStarts += (p[0] * 2);
  1334.     }
  1335. }
  1336.  
  1337. /* these are used to create equal powered stereo separation */
  1338. static float sinApx(float x)
  1339. {
  1340.     x = x * (2.0f - x);
  1341.     return (x * 1.09742972f + x * x * 0.31678383f);
  1342. }
  1343.  
  1344. static float cosApx(float x)
  1345. {
  1346.     x = (1.0f - x) * (1.0f + x);
  1347.     return (x * 1.09742972f + x * x * 0.31678383f);
  1348. }
  1349. /* ------------------------------------------------- */
  1350.  
  1351. static void calculatePans(int8_t stereoSeparation)
  1352. {
  1353.     uint8_t scaledPanPos;
  1354.     float p;
  1355.  
  1356.     if (stereoSeparation > 100)
  1357.         stereoSeparation = 100;
  1358.  
  1359.     scaledPanPos = (stereoSeparation * 128) / 100;
  1360.  
  1361.     p = (128 - scaledPanPos) * (1.0f / 256.0f);
  1362.     AUD[0].PANL = cosApx(p);
  1363.     AUD[0].PANR = sinApx(p);
  1364.     AUD[3].PANL = cosApx(p);
  1365.     AUD[3].PANR = sinApx(p);
  1366.  
  1367.     p = (128 + scaledPanPos) * (1.0f / 256.0f);
  1368.     AUD[1].PANL = cosApx(p);
  1369.     AUD[1].PANR = sinApx(p);
  1370.     AUD[2].PANL = cosApx(p);
  1371.     AUD[2].PANR = sinApx(p);
  1372. }
  1373.  
  1374. static void mixSampleBlock(int16_t *streamOut, uint32_t numSamples)
  1375. {
  1376.     uint8_t i;
  1377.     int16_t *sndOut;
  1378.     uint16_t j;
  1379.     int32_t smpL, smpR;
  1380.     float tempSample, tempVolume, out_f[2];
  1381.     paulaVoice_t *v;
  1382. #ifdef USE_BLEP
  1383.     blep_t *bSmp, *bVol;
  1384. #endif
  1385.  
  1386.     memset(masterBufferL, 0, sizeof (float) * numSamples);
  1387.     memset(masterBufferR, 0, sizeof (float) * numSamples);
  1388.  
  1389.     for (i = 0; i < 4; ++i)
  1390.     {
  1391.         v = &AUD[i];
  1392.  
  1393. #ifdef USE_BLEP
  1394.         bSmp = &blep[i];
  1395.         bVol = &blepVol[i];
  1396. #endif
  1397.         if (AUD[i].DELTA > 0.0f)
  1398.         {
  1399.             for (j = 0; j < numSamples; ++j)
  1400.             {
  1401.                 tempSample = (v->DMA_DAT == NULL) ? 0.0f : (v->DMA_DAT[v->DMA_POS] * (1.0f / 128.0f));
  1402.                 tempVolume = (v->DMA_DAT == NULL) ? 0.0f : v->SRC_VOL;
  1403.  
  1404. #ifdef USE_BLEP
  1405.                 if (tempSample != bSmp->lastValue)
  1406.                 {
  1407.                     if ((v->LASTDELTA > 0.0f) && (v->LASTDELTA > v->LASTFRAC))
  1408.                         blepAdd(bSmp, v->LASTFRAC / v->LASTDELTA, bSmp->lastValue - tempSample);
  1409.  
  1410.                     bSmp->lastValue = tempSample;
  1411.                 }
  1412.  
  1413.                 if (tempVolume != bVol->lastValue)
  1414.                 {
  1415.                     blepAdd(bVol, 0.0f, bVol->lastValue - tempVolume);
  1416.                     bVol->lastValue = tempVolume;
  1417.                 }
  1418.  
  1419.                 if (bSmp->samplesLeft) tempSample += blepRun(bSmp);
  1420.                 if (bVol->samplesLeft) tempVolume += blepRun(bVol);
  1421. #endif
  1422.  
  1423.                 tempSample *= tempVolume;
  1424.                
  1425.                 masterBufferL[j] += (tempSample * v->PANL);
  1426.                 masterBufferR[j] += (tempSample * v->PANR);
  1427.  
  1428.                 v->FRAC += v->DELTA;
  1429.                 if (v->FRAC >= 1.0f)
  1430.                 {
  1431.                     v->FRAC -= 1.0f;
  1432.  
  1433.                     v->LASTFRAC  = v->FRAC;
  1434.                     v->LASTDELTA = v->DELTA;
  1435.  
  1436.                     if (++v->DMA_POS >= v->DMA_LEN)
  1437.                     {
  1438.                         v->DMA_POS = 0;
  1439.  
  1440.                         /* re-fetch Paula register values now */
  1441.                         v->DMA_LEN = v->SRC_LEN;
  1442.                         v->DMA_DAT = v->SRC_DAT;
  1443.                     }
  1444.                 }
  1445.             }
  1446.         }
  1447.     }
  1448.  
  1449.     sndOut = streamOut;
  1450.     for (j = 0; j < numSamples; ++j)
  1451.     {
  1452.         if (!DisableMixer)
  1453.         {
  1454.             out_f[0] = masterBufferL[j];
  1455.             out_f[1] = masterBufferR[j];
  1456.  
  1457. #ifdef USE_LOWPASS
  1458.             lossyIntegrator(&filterLo, out_f, out_f);
  1459. #endif
  1460.  
  1461. #ifdef LED_FILTER
  1462.             if (LEDStatus)
  1463.                 lossyIntegratorLED(filterLEDC, &filterLED, out_f, out_f);
  1464. #endif
  1465.  
  1466. #ifdef USE_HIGHPASS
  1467.             lossyIntegratorHighPass(&filterHi, out_f, out_f);
  1468. #endif
  1469.  
  1470.             /* normalize amplitude */
  1471.             out_f[0] *= (32767.0f / NORM_FACTOR);
  1472.             out_f[1] *= (32767.0f / NORM_FACTOR);
  1473.  
  1474.             /* truncate to signed 32-bit integer */
  1475.             smpL = (int32_t)(out_f[0]);
  1476.             smpR = (int32_t)(out_f[1]);
  1477.  
  1478.             /* clamp to 16-bit signed range */
  1479.             CLAMP16(smpL);
  1480.             CLAMP16(smpR);
  1481.  
  1482.             /* truncate to signed 16-bit integer and store in output buffer */
  1483.             *sndOut++ = (int16_t)(smpL);
  1484.             *sndOut++ = (int16_t)(smpR);
  1485.         }
  1486.         else
  1487.         {
  1488.             *sndOut++ = 0;
  1489.             *sndOut++ = 0;
  1490.         }
  1491.     }
  1492. }
  1493.  
  1494. static void CALLBACK waveOutProc(HWAVEOUT _hWaveOut, UINT uMsg,
  1495.     DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
  1496. {
  1497.     int16_t *outputStream;
  1498.     int32_t sampleBlock, samplesTodo;
  1499.     WAVEHDR *waveBlockHeader;
  1500.  
  1501.     /* make compiler happy! (warning C4100) */
  1502.     (void)(dwParam2);
  1503.     (void)(dwInstance);
  1504.  
  1505.     if (uMsg == MM_WOM_DONE)
  1506.     {
  1507.         mixingMutex = 1;
  1508.  
  1509.         waveBlockHeader = (WAVEHDR *)(dwParam1);
  1510.         waveOutUnprepareHeader(_hWaveOut, waveBlockHeader, sizeof (WAVEHDR));
  1511.  
  1512.         if (isMixing)
  1513.         {
  1514.             memcpy(waveBlockHeader->lpData, mixerBuffer, soundBufferSize);
  1515.  
  1516.             waveOutPrepareHeader(_hWaveOut, waveBlockHeader, sizeof (WAVEHDR));
  1517.             waveOutWrite(_hWaveOut, waveBlockHeader, sizeof (WAVEHDR));
  1518.  
  1519.             outputStream = (int16_t *)(mixerBuffer);
  1520.             sampleBlock  = soundBufferSize / 4;
  1521.  
  1522.             while (sampleBlock)
  1523.             {
  1524.                 samplesTodo = (sampleBlock < samplesLeft) ? sampleBlock : samplesLeft;
  1525.                 if (samplesTodo > soundBufferSize)
  1526.                     samplesTodo = soundBufferSize;
  1527.  
  1528.                 if (samplesTodo > 0)
  1529.                 {
  1530.                     mixSampleBlock(outputStream, samplesTodo);
  1531.                     outputStream += (samplesTodo * 2);
  1532.  
  1533.                     sampleBlock -= samplesTodo;
  1534.                     samplesLeft -= samplesTodo;
  1535.                 }
  1536.                 else
  1537.                 {
  1538.                     if (!DisableMixer)
  1539.                         IntMusic();
  1540.  
  1541.                     samplesLeft = samplesPerFrame;
  1542.                 }
  1543.             }
  1544.         }
  1545.  
  1546.         mixingMutex = 0;
  1547.     }
  1548. }
  1549.  
  1550. void pt2play_PauseSong(int8_t pause)
  1551. {
  1552.     DisableMixer = pause ? 1 : 0;
  1553. }
  1554.  
  1555. void pt2play_PlaySong(uint8_t *moduleData, int8_t tempoMode)
  1556. {
  1557.     uint8_t i;
  1558.  
  1559.     DisableMixer = 1;
  1560.  
  1561.     memset(AUD, 0, sizeof (AUD));
  1562.     for (i = 0; i < 4; ++i)
  1563.     {
  1564.         AUD[i].DMA_DAT = NULL;
  1565.         AUD[i].SRC_DAT = NULL;
  1566.     }
  1567.  
  1568.     moduleInit(moduleData);
  1569.     calculatePans(STEREO_SEP);
  1570.  
  1571. #ifdef USE_BLEP
  1572.     memset(blep,    0, sizeof (blep));
  1573.     memset(blepVol, 0, sizeof (blepVol));
  1574. #endif
  1575.  
  1576. #ifdef USE_LOWPASS
  1577.     clearLossyIntegrator(&filterLo);
  1578. #endif
  1579.  
  1580. #ifdef LED_FILTER
  1581.     clearLEDFilter(&filterLED);
  1582. #endif
  1583.  
  1584. #ifdef USE_HIGHPASS
  1585.     clearLossyIntegrator(&filterHi);
  1586. #endif
  1587.  
  1588.     CurrSpeed      = 6;
  1589.     Counter        = 0;
  1590.     SongPosition   = 0;
  1591.     PatternPos     = 0;
  1592.     PattDelTime    = 0;
  1593.     PattDelTime2   = 0;
  1594.     PBreakPosition = 0;
  1595.     PosJumpAssert  = 0;
  1596.     PBreakFlag     = 0;
  1597.     LowMask        = 0xFF;
  1598.     TempoMode      = tempoMode ? VBLANK_TEMPO_MODE : CIA_TEMPO_MODE;
  1599.     SongPlaying    = 1;
  1600.     DisableMixer   = 0;
  1601.  
  1602. #ifdef LED_FILTER
  1603.     LEDStatus = 0;
  1604. #endif
  1605. }
  1606.  
  1607. void pt2play_SetStereoSep(uint8_t percentage)
  1608. {
  1609.     calculatePans(percentage);
  1610. }
  1611.  
  1612. static int8_t openMixer(uint32_t _samplingFrequency, uint32_t _soundBufferSize)
  1613. {
  1614.     uint8_t i;
  1615.     MMRESULT r;
  1616.  
  1617.     if (!hWaveOut)
  1618.     {
  1619.         f_outputFreq        = (float)(_samplingFrequency);
  1620.         soundBufferSize     = _soundBufferSize;
  1621.         masterBufferL       = (float *)(malloc(soundBufferSize * sizeof (float)));
  1622.         masterBufferR       = (float *)(malloc(soundBufferSize * sizeof (float)));
  1623.         wfx.nSamplesPerSec  = _samplingFrequency;
  1624.         wfx.wBitsPerSample  = 16;
  1625.         wfx.nChannels       = 2;
  1626.         wfx.cbSize          = 0;
  1627.         wfx.wFormatTag      = WAVE_FORMAT_PCM;
  1628.         wfx.nBlockAlign     = (wfx.wBitsPerSample * wfx.nChannels) / 8;
  1629.         wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;
  1630.  
  1631.         if ((masterBufferL == NULL) || (masterBufferR == NULL))
  1632.             return (0); /* gets free'd later */
  1633.  
  1634.         r = waveOutOpen(&hWaveOut, WAVE_MAPPER, &wfx, (DWORD_PTR)(waveOutProc), 0L, CALLBACK_FUNCTION);
  1635.         if (r != MMSYSERR_NOERROR) return (0);
  1636.  
  1637.         for (i = 0; i < MIX_BUF_NUM; ++i)
  1638.         {
  1639.             waveBlocks[i].dwBufferLength = soundBufferSize;
  1640.             waveBlocks[i].lpData = (LPSTR)(calloc(soundBufferSize, 1));
  1641.             if (waveBlocks[i].lpData == NULL)
  1642.                 return (0); /* gets free'd later */
  1643.  
  1644.             waveOutPrepareHeader(hWaveOut, &waveBlocks[i], sizeof (WAVEHDR));
  1645.             waveOutWrite(hWaveOut, &waveBlocks[i], sizeof (WAVEHDR));
  1646.         }
  1647.  
  1648.         mixerBuffer = (int8_t *)(calloc(soundBufferSize, 1));
  1649.         if (mixerBuffer == NULL)
  1650.             return (0); /* gets free'd later */
  1651.  
  1652.         SetReplayerBPM(125);
  1653.  
  1654. #ifdef USE_LOWPASS
  1655.         // Amiga 500 RC low-pass filter (R = 360 ohm, C = 0.1uF)
  1656.         // hz = 1 / (2pi * R * C)    = ~4421.0Hz
  1657.         calcCoeffLossyIntegrator(f_outputFreq, 4421.0f, &filterLo);
  1658. #endif
  1659.  
  1660. #ifdef LED_FILTER
  1661.         // Amiga 500 Sallen-Key "LED" filter (R1 = 10k ohm, R2 = 10k ohm, C1 = 6800pf, C2 = 3900pf)
  1662.         // hz = 1 / (2pi * root(R1 * R2 * C1 * C2))    = ~3090.5Hz
  1663.         calcCoeffLED(f_outputFreq, 3090.5f, &filterLEDC);
  1664. #endif
  1665.  
  1666. #ifdef USE_HIGHPASS
  1667.         // Amiga 500 RC high-pass filter (R = 1390 ohm, C = 22uF)
  1668.         // hz = 1 / (2pi * R * C)    = ~5.2Hz
  1669.         calcCoeffLossyIntegrator(f_outputFreq, 5.2f, &filterHi);
  1670. #endif
  1671.  
  1672.         isMixing = 1;
  1673.         return (1);
  1674.     }
  1675.  
  1676.     return (1);
  1677. }
  1678.  
  1679. void pt2play_Close(void)
  1680. {
  1681.     uint8_t i;
  1682.  
  1683.     DisableMixer = 1;
  1684.  
  1685.     if (isMixing)
  1686.     {
  1687.         isMixing = 0;
  1688.         while (mixingMutex);
  1689.  
  1690.         if (hWaveOut)
  1691.         {
  1692.             for (i = 0; i < MIX_BUF_NUM; ++i)
  1693.                 waveOutUnprepareHeader(hWaveOut, &waveBlocks[i], sizeof (WAVEHDR));
  1694.  
  1695.             for (i = 0; i < MIX_BUF_NUM; ++i)
  1696.             {
  1697.                 while (waveBlocks[i].dwFlags & WHDR_PREPARED) SleepEx(1, 1); // wait
  1698.                
  1699.                 if (waveBlocks[i].lpData != NULL)
  1700.                 {
  1701.                     free(waveBlocks[i].lpData);
  1702.                     waveBlocks[i].lpData = NULL;
  1703.                 }
  1704.             }
  1705.  
  1706.             waveOutReset(hWaveOut);
  1707.             waveOutClose(hWaveOut);
  1708.  
  1709.             hWaveOut = 0;
  1710.  
  1711.             if (mixerBuffer != NULL)
  1712.             {
  1713.                 free(mixerBuffer);
  1714.                 mixerBuffer = NULL;
  1715.             }
  1716.  
  1717.             if (masterBufferL != NULL)
  1718.             {
  1719.                 free(masterBufferL);
  1720.                 masterBufferL = NULL;
  1721.             }
  1722.  
  1723.             if (masterBufferR != NULL)
  1724.             {
  1725.                 free(masterBufferR);
  1726.                 masterBufferR = NULL;
  1727.             }
  1728.         }
  1729.     }
  1730. }
  1731.  
  1732. int8_t pt2play_Init(uint32_t outputFreq)
  1733. {
  1734.     SongPlaying = 0;
  1735.  
  1736.     if (!openMixer(outputFreq, MIX_BUF_LEN))
  1737.     {
  1738.         pt2play_Close();
  1739.         return (0);
  1740.     }
  1741.  
  1742.     return (1);
  1743. }
  1744.  
  1745. /* END OF FILE */
RAW Paste Data
Top