SHARE
TWEET

st23play v0.31

8bitbubsy Aug 6th, 2019 (edited) 122 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2. ** st23play v0.31 - 29th of August 2019 - https://16-bits.org
  3. ** ==========================================================
  4. **                 - NOT BIG ENDIAN SAFE! -
  5. **
  6. ** Very accurate C port of Scream Tracker 2.3's replayer,
  7. ** by Olav "8bitbubsy" Sørensen. Using the original asm source codes
  8. ** by Sami "PSI" Tammilehto (Future Crew) with permission, plus a
  9. ** disassembly of ST2.3 because the asm code I got was for a newer
  10. ** unreleased version.
  11. **
  12. ** Keep in mind that the original ST2 replayer has been heavily changed
  13. ** between versions, so this one is accurate to how ST2.3 plays .STM files.
  14. **
  15. ** Thanks to Sergei "x0r" Kolzun for pointing out that the replayer
  16. ** code differ between versions, and his ST2 disassembly help was handy.
  17. **
  18. ** You need to link winmm.lib for this to compile (-lwinmm)
  19. ** Alternatively, you can change out the mixer functions at the bottom with
  20. ** your own for your OS.
  21. **
  22. ** Example of st32play usage:
  23. ** #include "st23play.h"
  24. ** #include "songdata.h"
  25. **
  26. ** st23play_PlaySong(songData, songDataLength, true, 44100);
  27. ** mainLoop();
  28. ** st23play_Close();
  29. **
  30. ** To turn a song into an include file like in the example, you can use my
  31. ** win32 bin2h tool from here: https://16-bits.org/etc/bin2h.zip
  32. **
  33. ** Changes in v0.31:
  34. ** - Removed some unneeded logic in the audio channel mixer
  35. **
  36. ** Changes in v0.3:
  37. ** - Handle illegal pattern notes (>B-4) as no note (ST2.3 doesn't do this, but I do!)
  38. ** - Added overflow data to notespd table for arpeggio overflow read bug
  39. ** - Handle yet another arpeggio LUT overflow case (thanks x0r)
  40. **
  41. ** Changes in v0.2:
  42. ** - Vibrato and portamento accidentally shared the same memory (not correct)
  43. ** - Pattern separators (in the order list) were not handled correctly
  44. ** - Fixed some differences to match ST2.3's replayer (arp. + pitch up/down)
  45. */
  46.  
  47. /* st23play.h:
  48.  
  49. #pragma once
  50.  
  51. #include <stdint.h>
  52. #include <stdbool.h>
  53.  
  54. bool st23play_PlaySong(const uint8_t *moduleData, uint32_t dataLength, bool useInterpolationFlag, uint32_t audioFreq);
  55. void st23play_Close(void);
  56. void st23play_PauseSong(bool flag); // true/false
  57. void st23play_TogglePause(void);
  58. void st23play_SetMasterVol(uint16_t vol); // 0..256
  59. void st23play_SetInterpolation(bool flag); // true/false
  60. char *st23play_GetSongName(void); // max 20 chars (21 with '\0'), string is in code page 437
  61. uint32_t st23play_GetMixerTicks(void); // returns the amount of milliseconds of mixed audio (not realtime)
  62. */
  63.  
  64. #define MIX_BUF_SAMPLES 4096
  65.  
  66. #include <stdio.h>
  67. #include <stdlib.h>
  68. #include <string.h>
  69. #include <stdint.h>
  70. #include <stdbool.h>
  71.  
  72. // don't change these!
  73. #define C1FREQ 8192
  74. #define PERIOD_FACTOR 10 /* x times higher resolution than Amiga periods */
  75.  
  76. #define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
  77.  
  78. // fast 32-bit -> 16-bit clamp
  79. #define CLAMP16(i) if ((int16_t)(i) != i) i = 0x7FFF ^ (i >> 31)
  80.  
  81. typedef struct st_ins_t
  82. {
  83.     uint16_t segm; // for loader
  84.     // -----------
  85.     int8_t *data;
  86.     uint8_t vol;
  87.     uint16_t length, lp_beg, lp_end, c1spd;
  88. } st_ins_t;
  89.  
  90. typedef struct chn_t
  91. {
  92.     // mixer variables
  93.     const int8_t *mdat;
  94.     int32_t mvol;
  95.     uint32_t mdelta, mfrac, mpos, mend, mloopbeg, mlooplen;
  96.     // -----------
  97.     bool atreon;
  98.     uint8_t mcnt, avol2, avibcnt, atremor, aorgvol;
  99.     uint8_t alastnfo1, alastnfo2, coms, vols, notes, samples;
  100.     uint8_t infos, lastnote;
  101.     uint16_t mpnt, aspd, ac1spd, aorgspd;
  102. } chn_t;
  103.  
  104. static char songname[20 + 1];
  105. static volatile bool musicPaused, interpolationFlag;
  106. static bool breakpat;
  107. static uint8_t vpnt, subcnt, gvolume = 64, tempo = 96, st1[128], st2[65536];
  108. static int32_t mastervol = 256, samplesLeft, soundBufferSize, *mixBuf;
  109. static uint32_t samplesPerTick, audioRate, sampleCounter;
  110. static st_ins_t smp[31];
  111. static chn_t chn[4];
  112.  
  113. static const uint16_t notespd[80 + 11] =
  114. {
  115.     17120,16160,15240,14400,13560,12800,12080,11400,10760,10160, 9600, 9070, 0,0,0,0,
  116.      8560, 8080, 7620, 7200, 6780, 6400, 6040, 5700, 5380, 5080, 4800, 4535, 0,0,0,0,
  117.      4280, 4040, 3810, 3600, 3390, 3200, 3020, 2850, 2690, 2540, 2400, 2267, 0,0,0,0,
  118.      2140, 2020, 1905, 1800, 1695, 1600, 1510, 1425, 1345, 1270, 1200, 1133, 0,0,0,0,
  119.      1070, 1010,  952,  900,  847,  800,  755,  712,  672,  635,  600,  566, 0,0,0,0,
  120.      // +11 overflow values from vibsin, for buggy arpeggio routine
  121.         0,   24,   49,   74,   97,  120,  141,  161,  180,  197,  212
  122. };
  123.  
  124. static const int16_t vibsin[64] =
  125. {
  126.      0x00, 0x18, 0x31, 0x4A, 0x61, 0x78, 0x8D, 0xA1,
  127.      0xB4, 0xC5, 0xD4, 0xE0, 0xEB, 0xF4, 0xFA, 0xFD,
  128.      0xFF, 0xFD, 0xFA, 0xF4, 0xEB, 0xE0, 0xD4, 0xC5,
  129.      0xB4, 0xA1, 0x8D, 0x78, 0x61, 0x4A, 0x31, 0x18,
  130.      0x00,-0x18,-0x31,-0x4A,-0x61,-0x78,-0x8D,-0xA1,
  131.     -0xB4,-0xC5,-0xD4,-0xE0,-0xEB,-0xF4,-0xFA,-0xFD,
  132.     -0xFF,-0xFD,-0xFA,-0xF4,-0xEB,-0xE0,-0xD4,-0xC5,
  133.     -0xB4,-0xA1,-0x8D,-0x78,-0x61,-0x4A,-0x31,-0x18
  134. };
  135.  
  136. static const uint8_t slowdowns[16] = { 140,50,25,15,10,7,6,4,3,3,2,2,2,2,1,1 };
  137.  
  138. static bool openMixer(uint32_t audioFreq);
  139. static void closeMixer(void);
  140.  
  141. // CODE START
  142.  
  143. static void setspd(chn_t *c) // updates stspeeds with c->aspd
  144. {
  145.     if (c->aspd < 551)
  146.     {
  147.         c->mdelta = 0;
  148.         return;
  149.     }
  150.  
  151.     // 8bitbubsy: this won't overflow, and the result is identical to the original code
  152.     c->mdelta = ((35468950 / (uint32_t)c->aspd) << 16) / audioRate;
  153. }
  154.  
  155. static void _znewtempo(uint8_t val)
  156. {
  157.     uint16_t hz = 50;
  158.  
  159.     tempo = val >> 4;
  160.  
  161.     hz -= (slowdowns[val >> 4] * (val & 15)) >> 4; // can and will underflow
  162.     samplesPerTick = audioRate / hz;
  163. }
  164.  
  165. static void nextpat(void) // 8bitbubsy: this routine is not directly ported, but it's even safer
  166. {
  167.     vpnt++;
  168.     if (vpnt > 127 || st1[vpnt] == 99) // 8bitbubsy: added vpnt>127 check (prevents Bxx (xx>127) LUT overflow)
  169.         vpnt = 0;
  170.  
  171.     // 8bitbubsy: skip pattern separators
  172.     while (vpnt < 128 && st1[vpnt] == 98)
  173.         vpnt++;
  174.  
  175.     if (vpnt == 128)
  176.         vpnt = 0;
  177.  
  178.     if (st1[vpnt] == 98)
  179.         return; // panic!
  180.  
  181.     for (int16_t i = 0; i < 4; i++)
  182.     {
  183.         chn[i].mpnt = (st1[vpnt] << 10) + (i << 2);
  184.         chn[i].mcnt = 0;
  185.     }
  186. }
  187.  
  188. static void volslide(chn_t *c)
  189. {
  190.     if ((c->infos & 15) == 0)
  191.     {
  192.         c->avol2 += c->infos >> 4;
  193.         if (c->avol2 > 64)
  194.             c->avol2 = 64;
  195.     }
  196.     else
  197.     {
  198.         c->avol2 -= c->infos & 15;
  199.         if ((int8_t)c->avol2 < 0)
  200.             c->avol2 = 0;
  201.     }
  202. }
  203.  
  204. static void toneslide(chn_t *c, bool effectOFlag)
  205. {
  206.     uint8_t info = (effectOFlag || c->infos == 0) ? c->alastnfo2 : c->infos;
  207.     c->alastnfo2 = info;
  208.  
  209.     if (c->aspd == c->aorgspd)
  210.         return;
  211.  
  212.     if (c->aspd > c->aorgspd)
  213.     {
  214.         c->aspd -= info*PERIOD_FACTOR;
  215.         if ((int16_t)c->aspd < (int16_t)c->aorgspd)
  216.             c->aspd = c->aorgspd;
  217.     }
  218.     else
  219.     {
  220.         c->aspd += info*PERIOD_FACTOR;
  221.         if ((int16_t)c->aspd > (int16_t)c->aorgspd)
  222.             c->aspd = c->aorgspd;
  223.     }
  224.  
  225.     setspd(c);
  226. }
  227.  
  228. static void vibrato(chn_t *c, bool effectKFlag)
  229. {
  230.     uint8_t info = (effectKFlag || c->infos == 0) ? c->alastnfo1 : c->infos;
  231.     c->alastnfo1 = info;
  232.  
  233.     c->aspd = c->aorgspd + (((vibsin[c->avibcnt] * (info & 15)) >> 7) * PERIOD_FACTOR);
  234.     setspd(c);
  235.  
  236.     c->avibcnt = (c->avibcnt + (info >> 4)) & 63;
  237. }
  238.  
  239. static void spec2(chn_t *c) // special codes excecuted 5 times
  240. {
  241.     if (c->coms == 9) // tremor
  242.     {
  243.         if (c->atremor != 0)
  244.         {
  245.             c->atremor--;
  246.             return;
  247.         }
  248.  
  249.         if (c->atreon)
  250.         {
  251.             // set to off
  252.             c->atreon = false;
  253.             c->avol2 = 0;
  254.             c->atremor = c->infos & 15;
  255.         }
  256.         else
  257.         {
  258.             // set to on
  259.             c->atreon = true;
  260.             c->avol2 = c->aorgvol;
  261.             c->atremor = c->infos >> 4;
  262.         }
  263.  
  264.         return;
  265.     }
  266.     else if (c->coms == 10) // arpeggio
  267.     {
  268.         uint8_t note, octa, arptick = subcnt % 3;
  269.  
  270.         // 8bitbubsy: weird ST2.3 arpeggio order
  271.         if (arptick == 0)
  272.             note = c->infos & 15;
  273.         else if (arptick == 1)
  274.             note = 0;
  275.         else
  276.             note = c->infos >> 4;
  277.  
  278.         // check for octave overflow
  279.         note += c->lastnote & 15;
  280.         octa = c->lastnote & (255-15);
  281.  
  282.         if (note >= 11) // 8bitbubsy: this ought to be >= 12, a bug in ST2.3
  283.         {
  284.             note -= 12;
  285.             octa += 16;
  286.         }
  287.  
  288.         if (note == 255) // bug
  289.             c->aspd = 59079; // LUT overflow junk (thanks x0r)
  290.         else
  291.             c->aspd = notespd[note | octa];
  292.  
  293.         if (c->ac1spd != 0)
  294.             c->aspd = (c->aspd * C1FREQ) / c->ac1spd;
  295.  
  296.         c->aorgspd = c->aspd;
  297.         setspd(c);
  298.  
  299.         return;
  300.     }
  301.  
  302.     c->atremor = 0;
  303.     c->atreon = true;
  304.  
  305.     if (c->coms == 7) // toneslide
  306.     {
  307.         toneslide(c, false);
  308.         return;
  309.     }
  310.     else if (c->coms == 8) // vibrato
  311.     {
  312.         vibrato(c, false);
  313.         return;
  314.     }
  315.  
  316.     c->avibcnt = 0;
  317.  
  318.     if (c->coms == 5) // pitch slide down
  319.     {
  320.         c->aspd += c->infos * PERIOD_FACTOR;
  321.         setspd(c);
  322.         return;
  323.     }
  324.     else if (c->coms == 6) // pitch slide up
  325.     {
  326.         c->aspd -= c->infos * PERIOD_FACTOR;
  327.         setspd(c);
  328.         return;
  329.     }
  330.     else if (c->coms == 15) // volslide + toneslide
  331.     {
  332.         volslide(c);
  333.         toneslide(c, true);
  334.         return;
  335.     }
  336.     else if (c->coms == 11) // voslide + vibrato
  337.     {
  338.         volslide(c);
  339.         vibrato(c, true);
  340.         return;
  341.     }
  342.  
  343.     if (c->aorgspd != c->aspd)
  344.     {
  345.         c->aspd = c->aorgspd;
  346.         setspd(c);
  347.     }
  348.  
  349.     if (c->coms == 4) // volslide
  350.     {
  351.         volslide(c);
  352.         return;
  353.     }
  354. }
  355.  
  356. static void spec1(chn_t *c) // special codes excecuted only once.
  357. {
  358.     if (c->coms == 1) // A - set tempo
  359.     {
  360.         if (c->infos > 0)
  361.             _znewtempo(c->infos);
  362.     }
  363.     else if (c->coms == 2) // B - position jump
  364.     {
  365.         vpnt = c->coms;
  366.     }
  367.     else if (c->coms == 3) // C - pattern break
  368.     {
  369.         breakpat = true;
  370.     }
  371. }
  372.  
  373. static void donote1(chn_t *c)
  374. {
  375.     st_ins_t *s;
  376.  
  377.     if (c->vols != 65)
  378.         c->avol2 = c->aorgvol = c->vols;
  379.  
  380.     if (c->coms == 7) // toneslide
  381.     {
  382.         if (c->notes != 255)
  383.         {
  384.             // original speed if true one changed with vibrato etc.
  385.             c->aorgspd = notespd[c->notes];
  386.             if (c->ac1spd != 0)
  387.                 c->aorgspd = (c->aorgspd * C1FREQ) / c->ac1spd;
  388.         }
  389.  
  390.         return;
  391.     }
  392.  
  393.     if (c->samples > 0)
  394.     {
  395.         s = &smp[c->samples-1];
  396.         if (c->vols == 65) // default volume specified
  397.             c->avol2 = c->aorgvol = s->vol;
  398.  
  399.         c->ac1spd = s->c1spd;
  400.         if (s->data == NULL)
  401.             c->notes = 254; // quit the note if no sample
  402.  
  403.         c->mdat = s->data;
  404.         c->mpos = 0; // reset pos
  405.  
  406.         if (s->lp_end == 65535) // no loop?
  407.         {
  408.             c->mloopbeg = 65535;
  409.             c->mend = s->length;
  410.         }
  411.         else
  412.         {
  413.             // looping sound
  414.             c->mend = s->lp_end;
  415.             c->mloopbeg = s->lp_beg;
  416.             c->mlooplen = s->lp_end - s->lp_beg; // 8bitbubsy: added for my mixer
  417.         }
  418.     }
  419.  
  420.     // volume set, now calc the speed
  421.  
  422.     if (c->notes == 254)
  423.     {
  424.         // quiet
  425.         c->mfrac = 0;
  426.         c->mdat = NULL;
  427.     }
  428.     else if (c->notes != 255)
  429.     {
  430.         c->lastnote = c->notes;
  431.  
  432.         c->aorgspd = notespd[c->notes];
  433.         if (c->ac1spd != 0)
  434.             c->aorgspd = (c->aorgspd * C1FREQ) / c->ac1spd;
  435.         c->aspd = c->aorgspd;
  436.  
  437.         setspd(c);
  438.  
  439.         c->mfrac = 0;
  440.         c->mpos = 0;
  441.     }
  442.  
  443.     spec1(c);
  444. }
  445.  
  446. static void getnewnote(chn_t *c)
  447. {
  448.     uint8_t *pattptr = &st2[c->mpnt];
  449.  
  450.     if (++c->mcnt >= 64)
  451.         breakpat = true;
  452.  
  453.     c->notes = pattptr[0];
  454.  
  455.     // 8bitbubsy: sanity clamping
  456.     if (c->notes > 75) // B-4 (16*4)+11
  457.         c->notes = 255; // no note
  458.  
  459.     c->samples = pattptr[1] >> 3;
  460.     c->vols = ((pattptr[2] >> 1) & 0x78) | (pattptr[1] & 7);
  461.  
  462.     // 8bitbubsy: sanity clamping
  463.     if (c->vols > 65)
  464.         c->vols = 65; // no volume
  465.  
  466.     c->coms = pattptr[2] & 15;
  467.     c->infos = pattptr[3];
  468.  
  469.     c->mpnt += 16;
  470.     donote1(c);
  471.  
  472.     if (c->coms == 9)
  473.         spec2(c);
  474. }
  475.  
  476. static void imusic(void)
  477. {
  478.     int32_t i;
  479.  
  480.     if (subcnt == 0)
  481.     {
  482.         if (breakpat)
  483.         {
  484.             breakpat = false;
  485.             nextpat();
  486.         }
  487.  
  488.         getnewnote(&chn[0]);
  489.         getnewnote(&chn[1]);
  490.         getnewnote(&chn[2]);
  491.         getnewnote(&chn[3]);
  492.  
  493.         subcnt = tempo;
  494.         if (subcnt != 0)
  495.             subcnt--;
  496.     }
  497.     else
  498.     {
  499.         subcnt--;
  500.  
  501.         // no new note
  502.         spec2(&chn[0]);
  503.         spec2(&chn[1]);
  504.         spec2(&chn[2]);
  505.         spec2(&chn[3]);
  506.     }
  507.  
  508.     for (i = 0; i < 4; i++)
  509.         chn[i].mvol = chn[i].avol2 * gvolume; // 8bitbubsy: mvol=0..4096 (0..64 in original code)
  510. }
  511.  
  512. // 3-tap quadratic interpolation
  513. // in: int32_t s1,s2,s3 = -128..127 | f = 0..65535 (frac)
  514. // out: 16-bit s1 (will exceed 16-bits because of overshoot)
  515. #define INTERPOLATE8(s1, s2, s3, f) \
  516. { \
  517.     int32_t s4, frac = f >> 1; \
  518.     \
  519.     s2 <<= 8; \
  520.     s4 = ((s1 + s3) << (8 - 1)) - s2; \
  521.     s4 = ((s4 * frac) >> 16) + s2; \
  522.     s3 = (s1 + s3) << (8 - 1); \
  523.     s1 <<= 8; \
  524.     s3 = (s1 + s3) >> 1; \
  525.     s1 += ((s4 - s3) * frac) >> 14; \
  526. } \
  527.  
  528. #define MIX_SMP_INTRP \
  529.     smpDat = &c->mdat[c->mpos]; \
  530.     sample1 = smpDat[0]; \
  531.     sample2 = smpDat[1]; \
  532.     sample3 = smpDat[2]; \
  533.     INTERPOLATE8(sample1, sample2, sample3, c->mfrac); \
  534.     mixBuf[j] += (sample1 * c->mvol) >> 12; \
  535.  
  536. #define MIX_SMP \
  537.     mixBuf[j] += (c->mdat[c->mpos] * c->mvol) >> (12-8); \
  538.  
  539. #define INC_POS \
  540.     c->mfrac += c->mdelta; \
  541.     c->mpos += c->mfrac >> 16; \
  542.     c->mfrac &= 0xFFFF; \
  543.     \
  544.     if (c->mpos >= c->mend) \
  545.     { \
  546.         if (c->mloopbeg == 65535) /* no loop? */ \
  547.         { \
  548.             c->mdat = NULL; \
  549.             break; \
  550.         } \
  551.         else \
  552.         { \
  553.             do \
  554.             { \
  555.                 c->mpos -= c->mlooplen; \
  556.             } \
  557.             while (c->mpos >= c->mend); \
  558.         } \
  559.     } \
  560.  
  561. static void mixAudio(int16_t *stream, int32_t sampleBlockLength)
  562. {
  563.     const int8_t *smpDat;
  564.     int32_t sample1, sample2, sample3, i, j, out32;
  565.     chn_t *c;
  566.  
  567.     if (musicPaused)
  568.     {
  569.         memset(stream, 0, sampleBlockLength * (sizeof (int16_t) * 2));
  570.         return;
  571.     }
  572.  
  573.     memset(mixBuf, 0, sampleBlockLength * sizeof (int32_t));
  574.  
  575.     /* 8bitbubsy: The ST2.3 mixer has been heavily improved:
  576.      * - No interpolation -> 3-tap quadratic interpolation (toggleable)
  577.      * - Mixing rate can be higher than 23863Hz
  578.      * - Higher volume precision
  579.      * - Proper wrapping of loop (takes overflow samples into account)
  580.      * - Sample position is now increased _after_ mixing the sample
  581.      */
  582.  
  583.     if (interpolationFlag)
  584.     {
  585.         for (i = 0; i < 4; i++)
  586.         {
  587.             c = &chn[i];
  588.             if (c->mdat == NULL)
  589.                 continue;
  590.  
  591.             for (j = 0; j < sampleBlockLength; j++)
  592.             {
  593.                 MIX_SMP_INTRP
  594.                 INC_POS
  595.             }
  596.         }
  597.     }
  598.     else
  599.     {
  600.         for (i = 0; i < 4; i++)
  601.         {
  602.             c = &chn[i];
  603.             if (c->mdat == NULL)
  604.                 continue;
  605.  
  606.             for (j = 0; j < sampleBlockLength; j++)
  607.             {
  608.                 MIX_SMP
  609.                 INC_POS
  610.             }
  611.         }
  612.     }
  613.  
  614.     if (mastervol == 256) // user-adjustable volume is at max
  615.     {
  616.         for (i = 0; i < sampleBlockLength; i++)
  617.         {
  618.             out32 = mixBuf[i] >> 2;
  619.             CLAMP16(out32);
  620.             *stream++ = (int16_t)out32;
  621.             *stream++ = (int16_t)out32;
  622.         }
  623.     }
  624.     else // user-adjustable volume is not at max, adjust amplitude
  625.     {
  626.         for (i = 0; i < sampleBlockLength; i++)
  627.         {
  628.             out32 = mixBuf[i] >> 2;
  629.             CLAMP16(out32);
  630.             out32 = (out32 * mastervol) >> 8;
  631.             *stream++ = (int16_t)out32;
  632.             *stream++ = (int16_t)out32;
  633.         }
  634.     }
  635. }
  636.  
  637. static void st23play_FillAudioBuffer(int16_t *buffer, int32_t samples)
  638. {
  639.     int32_t a, b;
  640.  
  641.     a = samples;
  642.     while (a > 0)
  643.     {
  644.         if (samplesLeft == 0)
  645.         {
  646.             // new replayer tick
  647.             if (!musicPaused)
  648.                 imusic();
  649.  
  650.             samplesLeft = samplesPerTick;
  651.         }
  652.  
  653.         b = a;
  654.         if (b > samplesLeft)
  655.             b = samplesLeft;
  656.  
  657.         mixAudio(buffer, b);
  658.         buffer += (uint32_t)b << 1;
  659.  
  660.         a -= b;
  661.         samplesLeft -= b;
  662.     }
  663.  
  664.     sampleCounter += samples;
  665. }
  666.  
  667. void st23play_Close(void)
  668. {
  669.     closeMixer();
  670.  
  671.     if (mixBuf != NULL)
  672.     {
  673.         free(mixBuf);
  674.         mixBuf = NULL;
  675.     }
  676.  
  677.     for (uint8_t i = 0; i < 31; i++)
  678.     {
  679.         if (smp[i].data != NULL)
  680.         {
  681.             free(smp[i].data);
  682.             smp[i].data = NULL;
  683.         }
  684.     }
  685. }
  686.  
  687. void st23play_PauseSong(bool flag)
  688. {
  689.     musicPaused = flag;
  690. }
  691.  
  692. void st23play_TogglePause(void)
  693. {
  694.     musicPaused ^= 1;
  695. }
  696.  
  697. void st23play_SetMasterVol(uint16_t vol)
  698. {
  699.     mastervol = CLAMP(vol, 0, 256);
  700. }
  701.  
  702. void st23play_SetInterpolation(bool flag)
  703. {
  704.     interpolationFlag = flag;
  705. }
  706.  
  707. char *st23play_GetSongName(void)
  708. {
  709.     return songname;
  710. }
  711.  
  712. uint32_t st23play_GetMixerTicks(void)
  713. {
  714.     if (audioRate < 1000)
  715.         return 0;
  716.  
  717.     return sampleCounter / (audioRate / 1000);
  718. }
  719.  
  720. static bool loadSTM(const uint8_t *dat, uint32_t modLen)
  721. {
  722.     uint8_t pats, *pattdata;
  723.     uint16_t a, ver;
  724.  
  725.     ver = (dat[30] * 100) + dat[31];
  726.     if (dat[29] != 2 || (ver != 200 && ver != 210 && ver != 220 && ver != 221))
  727.         return false; // unsupported
  728.  
  729.     memset(smp, 0, sizeof (smp));
  730.     memset(st1, 99, sizeof (st1)); // 8bitbubsy: added for safety
  731.  
  732.     memcpy(songname, dat, 20);
  733.     songname[20] = '\0';
  734.  
  735.     gvolume = 64;
  736.  
  737.     tempo = dat[32];
  738.     if (ver < 221)
  739.         tempo = (tempo % 10) + (tempo / 10) * 16;
  740.  
  741.     pats = dat[33];
  742.  
  743.     if (ver > 210)
  744.     {
  745.         gvolume = dat[34];
  746.         if (gvolume > 64) // 8bitbubsy: added for safety
  747.             gvolume = 64;
  748.     }
  749.  
  750.     // load sample information
  751.     for (a = 0; a < 31; a++)
  752.     {
  753.         uint8_t *sdat = (uint8_t *)&dat[48 + (a * 32)];
  754.         st_ins_t *s = &smp[a];
  755.  
  756.         s->segm = *(uint16_t *)&sdat[14];
  757.         s->length = *(uint16_t *)&sdat[16];
  758.         s->lp_beg = *(uint16_t *)&sdat[18];
  759.         s->lp_end = *(uint16_t *)&sdat[20];
  760.         s->vol = sdat[22];
  761.         s->c1spd = *(uint16_t *)&sdat[24];
  762.  
  763.         if (s->lp_end == 0)
  764.             s->lp_end = 65535;
  765.  
  766.         // 8bitbubsy: added loop overflow handling (not present in ST2.3)
  767.         if (s->lp_end != 65535)
  768.         {
  769.             if (s->lp_end > s->length)
  770.                 s->lp_end = s->length;
  771.  
  772.             if (s->lp_beg >= s->lp_end)
  773.             {
  774.                 s->lp_beg = 0;
  775.                 s->lp_end = 65535;
  776.             }
  777.         }
  778.  
  779.         if (s->vol > 64) // 8bitbubsy: added for safety
  780.             s->vol = 64;
  781.     }
  782.  
  783.     memcpy(st1, &dat[1040], (ver == 200) ? 64 : 128); // read order list
  784.     memset(st2, 0, sizeof (st2)); // wipe pattern data
  785.  
  786.     // load pattern data
  787.     pattdata = (uint8_t *)&dat[(ver == 200) ? (1040+64) : (1040+128)];
  788.     for (a = 0; a < pats; a++)
  789.     {
  790.         for (uint16_t u = 0; u < 1024;)
  791.         {
  792.             uint8_t c = *pattdata++;
  793.             if (c == 251)
  794.             {
  795.                 st2[a*1024+u]=0; u++;
  796.                 st2[a*1024+u]=0; u++;
  797.                 st2[a*1024+u]=0; u++;
  798.                 st2[a*1024+u]=0; u++;
  799.             }
  800.             else if (c == 253)
  801.             {
  802.                 st2[a*1024+u]=254; u++;
  803.                 st2[a*1024+u]=1; u++;
  804.                 st2[a*1024+u]=128; u++;
  805.                 st2[a*1024+u]=0; u++;
  806.             }
  807.             else if (c==252)
  808.             {
  809.                 st2[a*1024+u]=255; u++;
  810.                 st2[a*1024+u]=1; u++;
  811.                 st2[a*1024+u]=128; u++;
  812.                 st2[a*1024+u]=0; u++;
  813.             }
  814.             else
  815.             {
  816.                 st2[a*1024+u]=c; u++;
  817.                 st2[a*1024+u]=*pattdata++; u++;
  818.                 st2[a*1024+u]=*pattdata++; u++;
  819.                 st2[a*1024+u]=*pattdata++; u++;
  820.  
  821.                 if (ver < 221 && (st2[a*1024+u-2] & 15) == 1)
  822.                 {
  823.                     uint8_t d, b;
  824.                     d=st2[a*1024+u-1];
  825.                     b=d/10;
  826.                     d%=10;
  827.                     d+=b*16;
  828.                     st2[a*1024+u-1]=d;
  829.                 }
  830.             }
  831.         }
  832.     }
  833.  
  834.     // load sample data
  835.     for (a = 0; a < 31; a++)
  836.     {
  837.         st_ins_t *s = &smp[a];
  838.         if (s->vol == 0 || s->length == 0 || s->c1spd == 0 || s->segm*16UL >= modLen)
  839.             continue;
  840.  
  841.         s->data = (int8_t *)malloc(s->length+2);
  842.         if (s->data == NULL)
  843.             return false;
  844.  
  845.         memcpy(s->data, &dat[s->segm<<4], s->length); // copy over sample data
  846.  
  847.         // 8bitbubsy: fix samples after loop/smp.end for branchless resampling interpolation
  848.         if (s->lp_end == 65535)
  849.         {
  850.             s->data[s->length+0] = 0; // no loop
  851.             s->data[s->length+1] = 0;
  852.         }
  853.         else
  854.         {
  855.             s->data[s->lp_end+0] = s->data[s->lp_beg+0]; // loop
  856.             s->data[s->lp_end+1] = s->data[s->lp_beg+1];
  857.         }
  858.     }
  859.  
  860.     return true;
  861. }
  862.  
  863. bool st23play_PlaySong(const uint8_t *moduleData, uint32_t dataLength, bool useInterpolationFlag, uint32_t audioFreq)
  864. {
  865.     st23play_Close();
  866.     memset(songname, 0, sizeof (songname));
  867.  
  868.     if (audioFreq == 0)
  869.         audioFreq = 44100;
  870.  
  871.     sampleCounter = 0;
  872.     musicPaused = true;
  873.     audioRate = audioFreq;
  874.     soundBufferSize = MIX_BUF_SAMPLES;
  875.     interpolationFlag = useInterpolationFlag ? true : false;
  876.  
  877.     mixBuf = (int32_t *)malloc(MIX_BUF_SAMPLES * sizeof (int32_t));
  878.     if (mixBuf == NULL || !openMixer(audioRate) || !loadSTM(moduleData, dataLength))
  879.         goto playError;
  880.  
  881.     memset(chn, 0, sizeof (chn));
  882.     _znewtempo(tempo);
  883.     subcnt = 0;
  884.     breakpat = false;
  885.     vpnt = 127-1; // will be set to 0 in nextpat()
  886.     nextpat();
  887.     musicPaused = false;
  888.     return true;
  889.  
  890. playError:
  891.     st23play_Close();
  892.     return false;
  893. }
  894.  
  895. // the following must be changed if you want to use another audio API than WinMM
  896.  
  897. #ifndef WIN32_LEAN_AND_MEAN
  898. #define WIN32_LEAN_AND_MEAN
  899. #endif
  900.  
  901. #include <windows.h>
  902. #include <mmsystem.h>
  903.  
  904. #define MIX_BUF_NUM 2
  905.  
  906. static volatile BOOL audioRunningFlag;
  907. static uint8_t currBuffer;
  908. static int16_t *mixBuffer[MIX_BUF_NUM];
  909. static HANDLE hThread, hAudioSem;
  910. static WAVEHDR waveBlocks[MIX_BUF_NUM];
  911. static HWAVEOUT hWave;
  912.  
  913. static DWORD WINAPI mixThread(LPVOID lpParam)
  914. {
  915.     WAVEHDR *waveBlock;
  916.  
  917.     (void)lpParam;
  918.  
  919.     SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
  920.  
  921.     while (audioRunningFlag)
  922.     {
  923.         waveBlock = &waveBlocks[currBuffer];
  924.         st23play_FillAudioBuffer((int16_t *)waveBlock->lpData, MIX_BUF_SAMPLES);
  925.         waveOutWrite(hWave, waveBlock, sizeof (WAVEHDR));
  926.         currBuffer = (currBuffer + 1) % MIX_BUF_NUM;
  927.  
  928.         // wait for buffer fill request
  929.         WaitForSingleObject(hAudioSem, INFINITE);
  930.     }
  931.  
  932.     return 0;
  933. }
  934.  
  935. static void CALLBACK waveProc(HWAVEOUT hWaveOut, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
  936. {
  937.     (void)hWaveOut;
  938.     (void)uMsg;
  939.     (void)dwInstance;
  940.     (void)dwParam1;
  941.     (void)dwParam2;
  942.  
  943.     if (uMsg == WOM_DONE)
  944.         ReleaseSemaphore(hAudioSem, 1, NULL);
  945. }
  946.  
  947. static void closeMixer(void)
  948. {
  949.     int32_t i;
  950.  
  951.     audioRunningFlag = false; // make thread end when it's done
  952.  
  953.     if (hAudioSem != NULL)
  954.         ReleaseSemaphore(hAudioSem, 1, NULL);
  955.  
  956.     if (hThread != NULL)
  957.     {
  958.         WaitForSingleObject(hThread, INFINITE);
  959.         CloseHandle(hThread);
  960.         hThread = NULL;
  961.     }
  962.  
  963.     if (hAudioSem != NULL)
  964.     {
  965.         CloseHandle(hAudioSem);
  966.         hAudioSem = NULL;
  967.     }
  968.  
  969.     if (hWave != NULL)
  970.     {
  971.         waveOutReset(hWave);
  972.         for (i = 0; i < MIX_BUF_NUM; i++)
  973.         {
  974.             if (waveBlocks[i].dwUser != 0xFFFF)
  975.                 waveOutUnprepareHeader(hWave, &waveBlocks[i], sizeof (WAVEHDR));
  976.         }
  977.  
  978.         waveOutClose(hWave);
  979.         hWave = NULL;
  980.     }
  981.  
  982.     for (i = 0; i < MIX_BUF_NUM; i++)
  983.     {
  984.         if (mixBuffer[i] != NULL)
  985.         {
  986.             free(mixBuffer[i]);
  987.             mixBuffer[i] = NULL;
  988.         }
  989.     }
  990. }
  991.  
  992. static bool openMixer(uint32_t audioFreq)
  993. {
  994.     int32_t i;
  995.     DWORD threadID;
  996.     WAVEFORMATEX wfx;
  997.  
  998.     // don't unprepare headers on error
  999.     for (i = 0; i < MIX_BUF_NUM; i++)
  1000.         waveBlocks[i].dwUser = 0xFFFF;
  1001.  
  1002.     closeMixer();
  1003.  
  1004.     ZeroMemory(&wfx, sizeof (wfx));
  1005.     wfx.nSamplesPerSec = audioFreq;
  1006.     wfx.wBitsPerSample = 16;
  1007.     wfx.nChannels = 2;
  1008.     wfx.wFormatTag = WAVE_FORMAT_PCM;
  1009.     wfx.nBlockAlign = wfx.nChannels * (wfx.wBitsPerSample / 8);
  1010.     wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
  1011.  
  1012.     samplesLeft = 0;
  1013.     currBuffer = 0;
  1014.  
  1015.     if (waveOutOpen(&hWave, WAVE_MAPPER, &wfx, (DWORD_PTR)&waveProc, 0, CALLBACK_FUNCTION) != MMSYSERR_NOERROR)
  1016.         goto omError;
  1017.  
  1018.     // create semaphore for buffer fill requests
  1019.     hAudioSem = CreateSemaphore(NULL, MIX_BUF_NUM - 1, MIX_BUF_NUM, NULL);
  1020.     if (hAudioSem == NULL)
  1021.         goto omError;
  1022.  
  1023.     // allocate WinMM mix buffers
  1024.     for (i = 0; i < MIX_BUF_NUM; i++)
  1025.     {
  1026.         mixBuffer[i] = (int16_t *)calloc(MIX_BUF_SAMPLES, wfx.nBlockAlign);
  1027.         if (mixBuffer[i] == NULL)
  1028.             goto omError;
  1029.     }
  1030.  
  1031.     // initialize WinMM mix headers
  1032.     memset(waveBlocks, 0, sizeof (waveBlocks));
  1033.     for (i = 0; i < MIX_BUF_NUM; i++)
  1034.     {
  1035.         waveBlocks[i].lpData = (LPSTR)mixBuffer[i];
  1036.         waveBlocks[i].dwBufferLength = MIX_BUF_SAMPLES * wfx.nBlockAlign;
  1037.         waveBlocks[i].dwFlags = WHDR_DONE;
  1038.  
  1039.         if (waveOutPrepareHeader(hWave, &waveBlocks[i], sizeof (WAVEHDR)) != MMSYSERR_NOERROR)
  1040.             goto omError;
  1041.     }
  1042.  
  1043.     // create main mixer thread
  1044.     audioRunningFlag = true;
  1045.     hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)mixThread, NULL, 0, &threadID);
  1046.     if (hThread == NULL)
  1047.         goto omError;
  1048.  
  1049.     return TRUE;
  1050.  
  1051. omError:
  1052.     closeMixer();
  1053.     return FALSE;
  1054. }
  1055.  
  1056. // ---------------------------------------------------------------------------
  1057.  
  1058. // END OF FILE
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top