8bitbubsy

st23play v0.35

Aug 6th, 2019 (edited)
1,552
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 30.78 KB | None | 0 0
  1. /*
  2. ** st23play v0.35 - 31st of December 2020 - 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, 48000);
  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.35:
  34. ** - Note cut didn't work because of an earlier bug
  35. **
  36. ** Changes in v0.34:
  37. ** - Added BLEP synthesis for better audio quality
  38. **
  39. ** Changes in v0.33:
  40. ** - Resampling interpolation downgraded from 3-tap cubic to 2-tap linear.
  41. **   This can sound sharper on lo-fi samples (which most STM songs have).
  42. ** - Audio mixer performance increase
  43. **
  44. ** Changes in v0.32:
  45. ** - Audio mixer performance increase
  46. ** - Added an st23play_GetMasterVol() function
  47. **
  48. ** Changes in v0.31:
  49. ** - Removed some unneeded logic in the audio channel mixer
  50. **
  51. ** Changes in v0.3:
  52. ** - Handle illegal pattern notes (>B-4) as no note (ST2.3 doesn't do this, but I do!)
  53. ** - Added overflow data to notespd table for arpeggio overflow read bug
  54. ** - Handle yet another arpeggio LUT overflow case (thanks x0r)
  55. **
  56. ** Changes in v0.2:
  57. ** - Vibrato and portamento accidentally shared the same memory (not correct)
  58. ** - Pattern separators (in the order list) were not handled correctly
  59. ** - Fixed some differences to match ST2.3's replayer (arp. + pitch up/down)
  60. */
  61.  
  62. /* st23play.h:
  63.  
  64. #pragma once
  65.  
  66. #include <stdint.h>
  67. #include <stdbool.h>
  68.  
  69. bool st23play_PlaySong(const uint8_t *moduleData, uint32_t dataLength, uint32_t audioFreq);
  70. void st23play_Close(void);
  71. void st23play_PauseSong(bool flag); // true/false
  72. void st23play_TogglePause(void);
  73. void st23play_SetMasterVol(uint16_t vol); // 0..256
  74. uint16_t st23play_GetMasterVol(void); // 0..256
  75. char *st23play_GetSongName(void); // max 20 chars (21 with '\0'), string is in code page 437
  76. uint32_t st23play_GetMixerTicks(void); // returns the amount of milliseconds of mixed audio (not realtime)
  77. */
  78.  
  79. #define MIX_BUF_SAMPLES 4096
  80.  
  81. #include <stdio.h>
  82. #include <stdlib.h>
  83. #include <string.h>
  84. #include <stdint.h>
  85. #include <stdbool.h>
  86.  
  87. // don't change these!
  88. #define BLEP_ZC 16
  89. #define BLEP_OS 16
  90. #define BLEP_SP 16
  91. #define BLEP_NS (BLEP_ZC * BLEP_OS / BLEP_SP)
  92. #define BLEP_RNS 31 // RNS = (2^ > NS) - 1
  93.  
  94. #define NUM_CHANNELS 4
  95. #define MAX_SAMPLES 31
  96. #define MAX_ORDERS 128
  97. #define C1FREQ 8192
  98. #define BASE_CLOCK 3546895 /* Amiga PAL Paula clock. ST2.3 uses this one */
  99. #define PERIOD_FACTOR 10 /* x times higher resolution than Amiga periods */
  100.  
  101. #define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
  102.  
  103. // fast 32-bit -> 16-bit clamp
  104. #define CLAMP16(i) if ((int16_t)(i) != i) i = 0x7FFF ^ (i >> 31)
  105.  
  106. typedef struct st_ins_t
  107. {
  108.     uint16_t segm; // for loader
  109.     // -----------
  110.     int8_t *data;
  111.     uint8_t vol;
  112.     uint16_t length, lp_beg, lp_end, c1spd;
  113. } st_ins_t;
  114.  
  115. typedef struct chn_t
  116. {
  117.     // mixer variables
  118.     const int8_t *mdat;
  119.     int32_t mpos, mend, mloopbeg, mlooplen;
  120.     double dDelta, dPhase, dVolume, dLastDelta, dLastPhase, dDeltaMul, dLastDeltaMul;
  121.     // -----------
  122.     bool atreon;
  123.     uint8_t mcnt, avol2, avibcnt, atremor, aorgvol;
  124.     uint8_t alastnfo1, alastnfo2, coms, vols, notes, samples;
  125.     uint8_t infos, lastnote;
  126.     uint16_t mpnt, aspd, ac1spd, aorgspd;
  127. } chn_t;
  128.  
  129. typedef struct blep_t
  130. {
  131.     int32_t index, samplesLeft;
  132.     double dBuffer[BLEP_RNS + 1], dLastValue;
  133. } blep_t;
  134.  
  135. static char songname[20+1];
  136. static volatile bool musicPaused;
  137. static bool breakpat;
  138. static uint8_t vpnt, subcnt, gvolume = 64, tempo = 96, st1[MAX_ORDERS], st2[65536];
  139. static int32_t mastervol = 256, samplesLeft, soundBufferSize, oversamplingFactor, randSeed = 0x12345000;
  140. static uint32_t samplesPerTick, audioRate, sampleCounter;
  141. static st_ins_t smp[MAX_SAMPLES];
  142. static chn_t chn[NUM_CHANNELS];
  143. static double *dMixBuffer, dPer2HzDiv, dPrngState;
  144. static blep_t blep[NUM_CHANNELS], blepVol[NUM_CHANNELS];
  145.  
  146. static const uint16_t notespd[80 + 11] =
  147. {
  148.     17120,16160,15240,14400,13560,12800,12080,11400,10760,10160, 9600, 9070, 0,0,0,0,
  149.      8560, 8080, 7620, 7200, 6780, 6400, 6040, 5700, 5380, 5080, 4800, 4535, 0,0,0,0,
  150.      4280, 4040, 3810, 3600, 3390, 3200, 3020, 2850, 2690, 2540, 2400, 2267, 0,0,0,0,
  151.      2140, 2020, 1905, 1800, 1695, 1600, 1510, 1425, 1345, 1270, 1200, 1133, 0,0,0,0,
  152.      1070, 1010,  952,  900,  847,  800,  755,  712,  672,  635,  600,  566, 0,0,0,0,
  153.      // +11 overflow values from vibsin, for buggy arpeggio routine
  154.         0,   24,   49,   74,   97,  120,  141,  161,  180,  197,  212
  155. };
  156.  
  157. static const int16_t vibsin[64] =
  158. {
  159.      0x00, 0x18, 0x31, 0x4A, 0x61, 0x78, 0x8D, 0xA1,
  160.      0xB4, 0xC5, 0xD4, 0xE0, 0xEB, 0xF4, 0xFA, 0xFD,
  161.      0xFF, 0xFD, 0xFA, 0xF4, 0xEB, 0xE0, 0xD4, 0xC5,
  162.      0xB4, 0xA1, 0x8D, 0x78, 0x61, 0x4A, 0x31, 0x18,
  163.      0x00,-0x18,-0x31,-0x4A,-0x61,-0x78,-0x8D,-0xA1,
  164.     -0xB4,-0xC5,-0xD4,-0xE0,-0xEB,-0xF4,-0xFA,-0xFD,
  165.     -0xFF,-0xFD,-0xFA,-0xF4,-0xEB,-0xE0,-0xD4,-0xC5,
  166.     -0xB4,-0xA1,-0x8D,-0x78,-0x61,-0x4A,-0x31,-0x18
  167. };
  168.  
  169. static const uint8_t slowdowns[16] = { 140,50,25,15,10,7,6,4,3,3,2,2,2,2,1,1 };
  170.  
  171. static const uint64_t minblepdata[] =
  172. {
  173.     0x3FF000320C7E95A6,0x3FF00049BE220FD5,0x3FF0001B92A41ACA,0x3FEFFF4425AA9724,
  174.     0x3FEFFDABDF6CF05C,0x3FEFFB5AF233EF1A,0x3FEFF837E2AE85F3,0x3FEFF4217B80E938,
  175.     0x3FEFEEECEB4E0444,0x3FEFE863A8358B5F,0x3FEFE04126292670,0x3FEFD63072A0D592,
  176.     0x3FEFC9C9CD36F56F,0x3FEFBA90594BD8C3,0x3FEFA7F008BA9F13,0x3FEF913BE2A0E0E2,
  177.     0x3FEF75ACCB01A327,0x3FEF5460F06A4E8F,0x3FEF2C5C0389BD3C,0x3FEEFC8859BF6BCB,
  178.     0x3FEEC3B916FD8D19,0x3FEE80AD74F0AD16,0x3FEE32153552E2C7,0x3FEDD69643CB9778,
  179.     0x3FED6CD380FFA864,0x3FECF374A4D2961A,0x3FEC692F19B34E54,0x3FEBCCCFA695DD5C,
  180.     0x3FEB1D44B168764A,0x3FEA59A8D8E4527F,0x3FE9814D9B10A9A3,0x3FE893C5B62135F2,
  181.     0x3FE790EEEBF9DABD,0x3FE678FACDEE27FF,0x3FE54C763699791A,0x3FE40C4F1B1EB7A3,
  182.     0x3FE2B9D863D4E0F3,0x3FE156CB86586B0B,0x3FDFCA8F5005B828,0x3FDCCF9C3F455DAC,
  183.     0x3FD9C2787F20D06E,0x3FD6A984CAD0F3E5,0x3FD38BB0C452732E,0x3FD0705EC7135366,
  184.     0x3FCABE86754E238F,0x3FC4C0801A6E9A04,0x3FBDECF490C5EA17,0x3FB2DFFACE9CE44B,
  185.     0x3FA0EFD4449F4620,0xBF72F4A65E22806D,0xBFA3F872D761F927,0xBFB1D89F0FD31F7C,
  186.     0xBFB8B1EA652EC270,0xBFBE79B82A37C92D,0xBFC1931B697E685E,0xBFC359383D4C8ADA,
  187.     0xBFC48F3BFF81B06B,0xBFC537BBA8D6B15C,0xBFC557CEF2168326,0xBFC4F6F781B3347A,
  188.     0xBFC41EF872F0E009,0xBFC2DB9F119D54D3,0xBFC13A7E196CB44F,0xBFBE953A67843504,
  189.     0xBFBA383D9C597E74,0xBFB57FBD67AD55D6,0xBFB08E18234E5CB3,0xBFA70B06D699FFD1,
  190.     0xBF9A1CFB65370184,0xBF7B2CEB901D2067,0x3F86D5DE2C267C78,0x3F9C1D9EF73F384D,
  191.     0x3FA579C530950503,0x3FABD1E5FFF9B1D0,0x3FB07DCDC3A4FB5B,0x3FB2724A856EEC1B,
  192.     0x3FB3C1F7199FC822,0x3FB46D0979F5043B,0x3FB47831387E0110,0x3FB3EC4A58A3D527,
  193.     0x3FB2D5F45F8889B3,0x3FB145113E25B749,0x3FAE9860D18779BC,0x3FA9FFD5F5AB96EA,
  194.     0x3FA4EC6C4F47777E,0x3F9F16C5B2604C3A,0x3F9413D801124DB7,0x3F824F668CBB5BDF,
  195.     0xBF55B3FA2EE30D66,0xBF86541863B38183,0xBF94031BBBD551DE,0xBF9BAFC27DC5E769,
  196.     0xBFA102B3683C57EC,0xBFA3731E608CC6E4,0xBFA520C9F5B5DEBD,0xBFA609DC89BE6ECE,
  197.     0xBFA632B83BC5F52F,0xBFA5A58885841AD4,0xBFA471A5D2FF02F3,0xBFA2AAD5CD0377C7,
  198.     0xBFA0686FFE4B9B05,0xBF9B88DE413ACB69,0xBF95B4EF6D93F1C5,0xBF8F1B72860B27FA,
  199.     0xBF8296A865CDF612,0xBF691BEEDABE928B,0x3F65C04E6AF9D4F1,0x3F8035D8FFCDB0F8,
  200.     0x3F89BED23C431BE3,0x3F90E737811A1D21,0x3F941C2040BD7CB1,0x3F967046EC629A09,
  201.     0x3F97DE27ECE9ED89,0x3F98684DE31E7040,0x3F9818C4B07718FA,0x3F97005261F91F60,
  202.     0x3F95357FDD157646,0x3F92D37C696C572A,0x3F8FF1CFF2BEECB5,0x3F898D20C7A72AC4,
  203.     0x3F82BC5B3B0AE2DF,0x3F7784A1B8E9E667,0x3F637BB14081726B,0xBF4B2DACA70C60A9,
  204.     0xBF6EFB00AD083727,0xBF7A313758DC6AE9,0xBF819D6A99164BE0,0xBF8533F57533403B,
  205.     0xBF87CD120DB5D340,0xBF89638549CD25DE,0xBF89FB8B8D37B1BB,0xBF89A21163F9204E,
  206.     0xBF886BA8931297D4,0xBF8673477783D71E,0xBF83D8E1CB165DB8,0xBF80BFEA7216142A,
  207.     0xBF7A9B9BC2E40EBF,0xBF7350E806435A7E,0xBF67D35D3734AB5E,0xBF52ADE8FEAB8DB9,
  208.     0x3F415669446478E4,0x3F60C56A092AFB48,0x3F6B9F4334A4561F,0x3F724FB908FD87AA,
  209.     0x3F75CC56DFE382EA,0x3F783A0C23969A7B,0x3F799833C40C3B82,0x3F79F02721981BF3,
  210.     0x3F7954212AB35261,0x3F77DDE0C5FC15C9,0x3F75AD1C98FE0777,0x3F72E5DACC0849F2,
  211.     0x3F6F5D7E69DFDE1B,0x3F685EC2CA09E1FD,0x3F611D750E54DF3A,0x3F53C6E392A46D17,
  212.     0x3F37A046885F3365,0xBF3BB034D2EE45C2,0xBF5254267B04B482,0xBF5C0516F9CECDC6,
  213.     0xBF61E5736853564D,0xBF64C464B9CC47AB,0xBF669C1AEF258F56,0xBF67739985DD0E60,
  214.     0xBF675AFD6446395B,0xBF666A0C909B4F78,0xBF64BE9879A7A07B,0xBF627AC74B119DBD,
  215.     0xBF5F86B04069DC9B,0xBF597BE8F754AF5E,0xBF531F3EAAE9A1B1,0xBF496D3DE6AD7EA3,
  216.     0xBF3A05FFDE4670CF,0xBF06DF95C93A85CA,0x3F31EE2B2C6547AC,0x3F41E694A378C129,
  217.     0x3F4930BF840E23C9,0x3F4EBB5D05A0D47D,0x3F51404DA0539855,0x3F524698F56B3F33,
  218.     0x3F527EF85309E28F,0x3F51FE70FE2513DE,0x3F50DF1642009B74,0x3F4E7CDA93517CAE,
  219.     0x3F4A77AE24F9A533,0x3F45EE226AA69E10,0x3F411DB747374F52,0x3F387F39D229D97F,
  220.     0x3F2E1B3D39AF5F8B,0x3F18F557BB082715,0xBEFAC04896E68DDB,0xBF20F5BC77DF558A,
  221.     0xBF2C1B6DF3EE94A4,0xBF3254602A816876,0xBF354E90F6EAC26B,0xBF3709F2E5AF1624,
  222.     0xBF379FCCB331CE8E,0xBF37327192ADDAD3,0xBF35EA998A894237,0xBF33F4C4977B3489,
  223.     0xBF317EC5F68E887B,0xBF2D6B1F793EB773,0xBF2786A226B076D9,0xBF219BE6CEC2CA36,
  224.     0xBF17D7F36D2A3A18,0xBF0AAEC5BBAB42AB,0xBEF01818DC224040,0x3EEF2F6E21093846,
  225.     0x3F049D6E0060B71F,0x3F0E598CCAFABEFD,0x3F128BC14BE97261,0x3F148703BC70EF6A,
  226.     0x3F1545E1579CAA25,0x3F14F7DDF5F8D766,0x3F13D10FF9A1BE0C,0x3F1206D5738ECE3A,
  227.     0x3F0F99F6BF17C5D4,0x3F0AA6D7EA524E96,0x3F0588DDF740E1F4,0x3F0086FB6FEA9839,
  228.     0x3EF7B28F6D6F5EED,0x3EEEA300DCBAF74A,0x3EE03F904789777C,0x3EC1BFEB320501ED,
  229.     0xBEC310D8E585A031,0xBED6F55ECA7E151F,0xBEDFDAA5DACDD0B7,0xBEE26944F3CF6E90,
  230.     0xBEE346894453BD1F,0xBEE2E099305CD5A8,0xBEE190385A7EA8B2,0xBEDF4D5FA2FB6BA2,
  231.     0xBEDAD4F371257BA0,0xBED62A9CDEB0AB32,0xBED1A6DF97B88316,0xBECB100096894E58,
  232.     0xBEC3E8A76257D275,0xBEBBF6C29A5150C9,0xBEB296292998088E,0xBEA70A10498F0E5E,
  233.     0xBE99E52D02F887A1,0xBE88C17F4066D432,0xBE702A716CFF56CA,0x3E409F820F781F78,
  234.     0x3E643EA99B770FE7,0x3E67DE40CDE0A550,0x3E64F4D534A2335C,0x3E5F194536BDDF7A,
  235.     0x3E5425CEBE1FA40A,0x3E46D7B7CC631E73,0x3E364746B6582E54,0x3E21FC07B13031DE,
  236.     0x3E064C3D91CF7665,0x3DE224F901A0AFC7,0x3DA97D57859C74A4,0x0000000000000000,
  237.  
  238.     // extra padding needed for interpolation
  239.     0x0000000000000000
  240. };
  241.  
  242. static bool openMixer(uint32_t audioFreq);
  243. static void closeMixer(void);
  244.  
  245. // CODE START
  246.  
  247. const double *get_minblep_table(void) { return (const double *)minblepdata; }
  248.  
  249. #define LERP(x, y, z) ((x) + ((y) - (x)) * (z))
  250.  
  251. void blepAdd(blep_t *b, double dOffset, double dAmplitude)
  252. {
  253.     double f = dOffset * BLEP_SP;
  254.  
  255.     int32_t i = (int32_t)f; // get integer part of f
  256.     const double *dBlepSrc = get_minblep_table() + i;
  257.     f -= i; // remove integer part from f
  258.  
  259.     i = b->index;
  260.     for (int32_t n = 0; n < BLEP_NS; n++)
  261.     {
  262.         b->dBuffer[i] += dAmplitude * LERP(dBlepSrc[0], dBlepSrc[1], f);
  263.         dBlepSrc += BLEP_SP;
  264.  
  265.         i = (i + 1) & BLEP_RNS;
  266.     }
  267.  
  268.     b->samplesLeft = BLEP_NS;
  269. }
  270.  
  271. static void blepVolAdd(blep_t *b, double dAmplitude)
  272. {
  273.     const double *dBlepSrc = get_minblep_table();
  274.  
  275.     int32_t i = b->index;
  276.     for (int32_t n = 0; n < BLEP_NS; n++)
  277.     {
  278.         b->dBuffer[i] += dAmplitude * (*dBlepSrc);
  279.         dBlepSrc += BLEP_SP;
  280.  
  281.         i = (i + 1) & BLEP_RNS;
  282.     }
  283.  
  284.     b->samplesLeft = BLEP_NS;
  285. }
  286.  
  287. static double blepRun(blep_t *b, double dInput)
  288. {
  289.     double dBlepOutput = dInput + b->dBuffer[b->index];
  290.     b->dBuffer[b->index] = 0.0;
  291.  
  292.     b->index = (b->index + 1) & BLEP_RNS;
  293.  
  294.     b->samplesLeft--;
  295.     return dBlepOutput;
  296. }
  297.  
  298. static void setspd(chn_t *c) // updates stspeeds with c->aspd
  299. {
  300.     if (c->aspd < 551)
  301.     {
  302.         c->dDelta = 0.0;
  303.         c->dDeltaMul = 1.0;
  304.     }
  305.     else
  306.     {
  307.         c->dDelta = dPer2HzDiv / (int32_t)c->aspd;
  308.         c->dDeltaMul = 1.0 / c->dDelta;
  309.     }
  310.  
  311.     // for BLEP synthesis
  312.     if (c->dLastDelta == 0.0) c->dLastDelta = c->dDelta;
  313.     if (c->dLastDeltaMul == 0.0) c->dLastDeltaMul = c->dDeltaMul;
  314. }
  315.  
  316. static void _znewtempo(uint8_t val)
  317. {
  318.     uint16_t hz = 50;
  319.  
  320.     tempo = val >> 4;
  321.  
  322.     hz -= (slowdowns[val >> 4] * (val & 15)) >> 4; // can and will underflow
  323.     samplesPerTick = audioRate / hz;
  324. }
  325.  
  326. static void nextpat(void) // 8bitbubsy: this routine is not directly ported, but it's even safer
  327. {
  328.     vpnt++;
  329.     if (vpnt >= MAX_ORDERS || st1[vpnt] == 99) // 8bitbubsy: added vpnt>127 check (prevents Bxx (xx>127) LUT overflow)
  330.         vpnt = 0;
  331.  
  332.     // 8bitbubsy: skip pattern separators
  333.     while (vpnt < MAX_ORDERS && st1[vpnt] == 98)
  334.         vpnt++;
  335.  
  336.     if (vpnt == MAX_ORDERS)
  337.         vpnt = 0;
  338.  
  339.     if (st1[vpnt] == 98)
  340.         return; // panic!
  341.  
  342.     for (int16_t i = 0; i < NUM_CHANNELS; i++)
  343.     {
  344.         chn[i].mpnt = (st1[vpnt] << 10) + (i << 2);
  345.         chn[i].mcnt = 0;
  346.     }
  347. }
  348.  
  349. static void volslide(chn_t *c)
  350. {
  351.     if ((c->infos & 15) == 0)
  352.     {
  353.         c->avol2 += c->infos >> 4;
  354.         if (c->avol2 > 64)
  355.             c->avol2 = 64;
  356.     }
  357.     else
  358.     {
  359.         c->avol2 -= c->infos & 15;
  360.         if ((int8_t)c->avol2 < 0)
  361.             c->avol2 = 0;
  362.     }
  363. }
  364.  
  365. static void toneslide(chn_t *c, bool effectOFlag)
  366. {
  367.     uint8_t info = (effectOFlag || c->infos == 0) ? c->alastnfo2 : c->infos;
  368.     c->alastnfo2 = info;
  369.  
  370.     if (c->aspd == c->aorgspd)
  371.         return;
  372.  
  373.     if (c->aspd > c->aorgspd)
  374.     {
  375.         c->aspd -= info*PERIOD_FACTOR;
  376.         if ((int16_t)c->aspd < (int16_t)c->aorgspd)
  377.             c->aspd = c->aorgspd;
  378.     }
  379.     else
  380.     {
  381.         c->aspd += info*PERIOD_FACTOR;
  382.         if ((int16_t)c->aspd > (int16_t)c->aorgspd)
  383.             c->aspd = c->aorgspd;
  384.     }
  385.  
  386.     setspd(c);
  387. }
  388.  
  389. static void vibrato(chn_t *c, bool effectKFlag)
  390. {
  391.     uint8_t info = (effectKFlag || c->infos == 0) ? c->alastnfo1 : c->infos;
  392.     c->alastnfo1 = info;
  393.  
  394.     c->aspd = c->aorgspd + (((vibsin[c->avibcnt] * (info & 15)) >> 7) * PERIOD_FACTOR);
  395.     setspd(c);
  396.  
  397.     c->avibcnt = (c->avibcnt + (info >> 4)) & 63;
  398. }
  399.  
  400. static void spec2(chn_t *c) // special codes excecuted 5 times
  401. {
  402.     if (c->coms == 9) // tremor
  403.     {
  404.         if (c->atremor != 0)
  405.         {
  406.             c->atremor--;
  407.             return;
  408.         }
  409.  
  410.         if (c->atreon)
  411.         {
  412.             // set to off
  413.             c->atreon = false;
  414.             c->avol2 = 0;
  415.             c->atremor = c->infos & 15;
  416.         }
  417.         else
  418.         {
  419.             // set to on
  420.             c->atreon = true;
  421.             c->avol2 = c->aorgvol;
  422.             c->atremor = c->infos >> 4;
  423.         }
  424.  
  425.         return;
  426.     }
  427.     else if (c->coms == 10) // arpeggio
  428.     {
  429.         uint8_t note, octa, arptick = subcnt % 3;
  430.  
  431.         // 8bitbubsy: weird ST2.3 arpeggio order
  432.         if (arptick == 0)
  433.             note = c->infos & 15;
  434.         else if (arptick == 1)
  435.             note = 0;
  436.         else
  437.             note = c->infos >> 4;
  438.  
  439.         // check for octave overflow
  440.         note += c->lastnote & 15;
  441.         octa = c->lastnote & (255-15);
  442.  
  443.         if (note >= 11) // 8bitbubsy: this ought to be >= 12, a bug in ST2.3
  444.         {
  445.             note -= 12;
  446.             octa += 16;
  447.         }
  448.  
  449.         if (note == 255) // bug
  450.             c->aspd = 59079; // LUT overflow junk (thanks x0r)
  451.         else
  452.             c->aspd = notespd[note | octa];
  453.  
  454.         if (c->ac1spd != 0)
  455.             c->aspd = (c->aspd * C1FREQ) / c->ac1spd;
  456.  
  457.         c->aorgspd = c->aspd;
  458.         setspd(c);
  459.  
  460.         return;
  461.     }
  462.  
  463.     c->atremor = 0;
  464.     c->atreon = true;
  465.  
  466.     if (c->coms == 7) // toneslide
  467.     {
  468.         toneslide(c, false);
  469.         return;
  470.     }
  471.     else if (c->coms == 8) // vibrato
  472.     {
  473.         vibrato(c, false);
  474.         return;
  475.     }
  476.  
  477.     c->avibcnt = 0;
  478.  
  479.     if (c->coms == 5) // pitch slide down
  480.     {
  481.         c->aspd += c->infos * PERIOD_FACTOR;
  482.         setspd(c);
  483.         return;
  484.     }
  485.     else if (c->coms == 6) // pitch slide up
  486.     {
  487.         c->aspd -= c->infos * PERIOD_FACTOR;
  488.         setspd(c);
  489.         return;
  490.     }
  491.     else if (c->coms == 15) // volslide + toneslide
  492.     {
  493.         volslide(c);
  494.         toneslide(c, true);
  495.         return;
  496.     }
  497.     else if (c->coms == 11) // voslide + vibrato
  498.     {
  499.         volslide(c);
  500.         vibrato(c, true);
  501.         return;
  502.     }
  503.  
  504.     if (c->aorgspd != c->aspd)
  505.     {
  506.         c->aspd = c->aorgspd;
  507.         setspd(c);
  508.     }
  509.  
  510.     if (c->coms == 4) // volslide
  511.     {
  512.         volslide(c);
  513.         return;
  514.     }
  515. }
  516.  
  517. static void spec1(chn_t *c) // special codes excecuted only once.
  518. {
  519.     if (c->coms == 1) // A - set tempo
  520.     {
  521.         if (c->infos > 0)
  522.             _znewtempo(c->infos);
  523.     }
  524.     else if (c->coms == 2) // B - position jump
  525.     {
  526.         vpnt = c->coms;
  527.     }
  528.     else if (c->coms == 3) // C - pattern break
  529.     {
  530.         breakpat = true;
  531.     }
  532. }
  533.  
  534. static void donote1(chn_t *c)
  535. {
  536.     st_ins_t *s;
  537.  
  538.     if (c->vols != 65) // custom volume set
  539.         c->avol2 = c->aorgvol = c->vols;
  540.  
  541.     if (c->coms == 7) // toneslide
  542.     {
  543.         if (c->notes != 255)
  544.         {
  545.             // original speed if true one changed with vibrato etc.
  546.             c->aorgspd = notespd[c->notes];
  547.             if (c->ac1spd != 0)
  548.                 c->aorgspd = (c->aorgspd * C1FREQ) / c->ac1spd;
  549.         }
  550.  
  551.         return;
  552.     }
  553.  
  554.     if (c->samples > 0)
  555.     {
  556.         s = &smp[c->samples-1];
  557.         if (c->vols == 65) // default volume specified
  558.             c->avol2 = c->aorgvol = s->vol;
  559.  
  560.         c->ac1spd = s->c1spd;
  561.         if (s->data == NULL)
  562.             c->notes = 254; // quit the note if no sample
  563.  
  564.         c->mdat = s->data;
  565.         c->mpos = 0; // reset pos
  566.  
  567.         if (s->lp_end == 65535) // no loop?
  568.         {
  569.             c->mloopbeg = 65535;
  570.             c->mend = s->length;
  571.         }
  572.         else
  573.         {
  574.             // looping sound
  575.             c->mend = s->lp_end;
  576.             c->mloopbeg = s->lp_beg;
  577.             c->mlooplen = s->lp_end - s->lp_beg; // 8bitbubsy: added for my mixer
  578.         }
  579.     }
  580.  
  581.     // volume set, now calc the speed
  582.  
  583.     if (c->notes == 254)
  584.     {
  585.         // quiet
  586.         c->dPhase = 0.0;
  587.         c->mdat = NULL;
  588.     }
  589.     else if (c->notes != 255)
  590.     {
  591.         c->lastnote = c->notes;
  592.  
  593.         c->aorgspd = notespd[c->notes];
  594.         if (c->ac1spd != 0)
  595.             c->aorgspd = (c->aorgspd * C1FREQ) / c->ac1spd;
  596.  
  597.         c->aspd = c->aorgspd;
  598.         setspd(c);
  599.  
  600.         c->dPhase = 0.0;
  601.         c->mpos = 0;
  602.     }
  603.  
  604.     spec1(c);
  605. }
  606.  
  607. static void getnewnote(chn_t *c)
  608. {
  609.     uint8_t *pattptr = &st2[c->mpnt];
  610.  
  611.     c->mcnt++;
  612.     if (c->mcnt >= 64)
  613.         breakpat = true;
  614.  
  615.     c->notes = pattptr[0];
  616.  
  617.     // 8bitbubsy: added clamping to prevent buffer overflow
  618.     if (c->notes > 75 && c->notes < 254) // B-4 (16*4)+11
  619.         c->notes = 75;
  620.  
  621.     c->samples = pattptr[1] >> 3;
  622.     c->vols = ((pattptr[2] >> 1) & 0x78) | (pattptr[1] & 7);
  623.  
  624.     // 8bitbubsy: sanity clamping
  625.     if (c->vols > 65)
  626.         c->vols = 65; // no volume
  627.  
  628.     c->coms = pattptr[2] & 15;
  629.     c->infos = pattptr[3];
  630.  
  631.     c->mpnt += 16;
  632.     donote1(c);
  633.  
  634.     if (c->coms == 9)
  635.         spec2(c);
  636. }
  637.  
  638. static void imusic(void)
  639. {
  640.     int32_t i;
  641.  
  642.     if (subcnt == 0)
  643.     {
  644.         if (breakpat)
  645.         {
  646.             breakpat = false;
  647.             nextpat();
  648.         }
  649.  
  650.         for (i = 0; i < NUM_CHANNELS; i++)
  651.             getnewnote(&chn[i]);
  652.  
  653.         subcnt = tempo;
  654.         if (subcnt != 0)
  655.             subcnt--;
  656.     }
  657.     else
  658.     {
  659.         subcnt--;
  660.  
  661.         // no new note
  662.         for (i = 0; i < NUM_CHANNELS; i++)
  663.             spec2(&chn[i]);
  664.     }
  665.  
  666.     for (i = 0; i < NUM_CHANNELS; i++)
  667.         chn[i].dVolume = (chn[i].avol2 * gvolume) * (1.0 / 4096.0); // 8bitbubsy: mvol=0..4096 (0..64 in original code)
  668. }
  669.  
  670. /* 8bitbubsy: The ST2.3 mixer has been heavily improved:
  671. ** - No interpolation -> BLEP synthesis
  672. ** - Mixing rate can be higher than 23863Hz
  673. ** - Higher volume precision
  674. ** - Proper wrapping of loop (takes overflow samples into account)
  675. ** - Sample position is now increased _after_ mixing the sample
  676. */
  677.  
  678. static void mixChannels(int32_t numSamples)
  679. {
  680.     double dSmp, dVol;
  681.     blep_t *bSmp, *bVol;
  682.     chn_t *c;
  683.  
  684.     memset(dMixBuffer, 0, numSamples * sizeof (double) * oversamplingFactor);
  685.  
  686.     c = chn;
  687.     bSmp = blep;
  688.     bVol = blepVol;
  689.  
  690.     const int32_t samplesToMix = numSamples * oversamplingFactor;
  691.     for (int32_t i = 0; i < NUM_CHANNELS; i++, c++, bSmp++, bVol++)
  692.     {
  693.         if (c->mdat == NULL)
  694.             continue;
  695.  
  696.         for (int32_t j = 0; j < samplesToMix; j++)
  697.         {
  698.             dSmp = c->mdat[c->mpos] * (1.0 / 128.0);
  699.             dVol = c->dVolume;
  700.  
  701.             if (dSmp != bSmp->dLastValue)
  702.             {
  703.                 if (c->dLastDelta > c->dLastPhase)
  704.                 {
  705.                     // div->mul trick: v->dLastDeltaMul is 1.0 / v->dLastDelta
  706.                     blepAdd(bSmp, c->dLastPhase * c->dLastDeltaMul, bSmp->dLastValue - dSmp);
  707.                 }
  708.  
  709.                 bSmp->dLastValue = dSmp;
  710.             }
  711.  
  712.             if (dVol != bVol->dLastValue)
  713.             {
  714.                 blepVolAdd(bVol, bVol->dLastValue - dVol);
  715.                 bVol->dLastValue = dVol;
  716.             }
  717.  
  718.             if (bSmp->samplesLeft > 0) dSmp = blepRun(bSmp, dSmp);
  719.             if (bVol->samplesLeft > 0) dVol = blepRun(bVol, dVol);
  720.  
  721.             dMixBuffer[j] += dSmp * dVol;
  722.  
  723.             c->dPhase += c->dDelta;
  724.             if (c->dPhase >= 1.0)
  725.             {
  726.                 c->dPhase -= 1.0;
  727.  
  728.                 c->dLastPhase = c->dPhase;
  729.                 c->dLastDelta = c->dDelta;
  730.                 c->dLastDeltaMul = c->dDeltaMul;
  731.  
  732.                 if (++c->mpos >= c->mend)
  733.                 {
  734.                     if (c->mloopbeg == 65535)
  735.                     {
  736.                         // no loop
  737.                         c->mdat = NULL;
  738.                         break;
  739.                     }
  740.                     else
  741.                     {
  742.                         c->mpos = c->mloopbeg;
  743.                     }
  744.                 }
  745.             }
  746.         }
  747.     }
  748. }
  749.  
  750. static inline int32_t random32(void)
  751. {
  752.     // LCG random 32-bit generator (quite good and fast)
  753.     randSeed *= 134775813;
  754.     randSeed++;
  755.     return randSeed;
  756. }
  757.  
  758. static void mixAudio(int16_t *stream, int32_t sampleBlockLength)
  759. {
  760.     if (musicPaused)
  761.     {
  762.         memset(stream, 0, sampleBlockLength * (sizeof (int16_t) * oversamplingFactor));
  763.         return;
  764.     }
  765.  
  766.     mixChannels(sampleBlockLength);
  767.  
  768.     const double *dMixBufferPtr = dMixBuffer;
  769.     if (oversamplingFactor == 1)
  770.     {
  771.         for (int32_t i = 0; i < sampleBlockLength; i++)
  772.         {
  773.             double dOut = dMixBufferPtr[i] * (16384.0 * 0.5);
  774.  
  775.             // 1-bit triangular dithering (high-pass filtered)
  776.             const double dPrng = random32() * (0.5 / INT32_MAX); // -0.5..0.5
  777.             dOut = (dOut + dPrng) - dPrngState;
  778.             dPrngState = dPrng;
  779.             int32_t out32 = (int32_t)dOut;
  780.             CLAMP16(out32);
  781.  
  782.             const int16_t out16 = (int16_t)out32;
  783.             *stream++ = out16;
  784.             *stream++ = out16;
  785.         }
  786.     }
  787.     else
  788.     {
  789.         for (int32_t i = 0; i < sampleBlockLength; i++)
  790.         {
  791.             const double dSample = ((*dMixBufferPtr++) + (*dMixBufferPtr++)) * 0.5;
  792.             double dOut = dSample * (16384.0 * 0.5);
  793.  
  794.             // 1-bit triangular dithering (high-pass filtered)
  795.             const double dPrng = random32() * (0.5 / INT32_MAX); // -0.5..0.5
  796.             dOut = (dOut + dPrng) - dPrngState;
  797.             dPrngState = dPrng;
  798.             int32_t out32 = (int32_t)dOut;
  799.             CLAMP16(out32);
  800.  
  801.             const int16_t out16 = (int16_t)out32;
  802.             *stream++ = out16;
  803.             *stream++ = out16;
  804.         }
  805.     }
  806. }
  807.  
  808. static void st23play_FillAudioBuffer(int16_t *buffer, int32_t samples)
  809. {
  810.     int32_t a, b;
  811.  
  812.     a = samples;
  813.     while (a > 0)
  814.     {
  815.         if (samplesLeft == 0)
  816.         {
  817.             // new replayer tick
  818.             if (!musicPaused)
  819.                 imusic();
  820.  
  821.             samplesLeft = samplesPerTick;
  822.         }
  823.  
  824.         b = a;
  825.         if (b > samplesLeft)
  826.             b = samplesLeft;
  827.  
  828.         mixAudio(buffer, b);
  829.         buffer += (uint32_t)b * 2;
  830.  
  831.         a -= b;
  832.         samplesLeft -= b;
  833.     }
  834.  
  835.     sampleCounter += samples;
  836. }
  837.  
  838. void st23play_Close(void)
  839. {
  840.     closeMixer();
  841.  
  842.     if (dMixBuffer != NULL)
  843.     {
  844.         free(dMixBuffer);
  845.         dMixBuffer = NULL;
  846.     }
  847.  
  848.     for (uint8_t i = 0; i < MAX_SAMPLES; i++)
  849.     {
  850.         if (smp[i].data != NULL)
  851.         {
  852.             free(smp[i].data);
  853.             smp[i].data = NULL;
  854.         }
  855.     }
  856. }
  857.  
  858. void st23play_PauseSong(bool flag)
  859. {
  860.     musicPaused = flag;
  861. }
  862.  
  863. void st23play_TogglePause(void)
  864. {
  865.     musicPaused ^= 1;
  866. }
  867.  
  868. void st23play_SetMasterVol(uint16_t vol)
  869. {
  870.     mastervol = CLAMP(vol, 0, 256);
  871. }
  872.  
  873. uint16_t st23play_GetMasterVol(void)
  874. {
  875.     return (uint16_t)mastervol;
  876. }
  877.  
  878. char *st23play_GetSongName(void)
  879. {
  880.     return songname;
  881. }
  882.  
  883. uint32_t st23play_GetMixerTicks(void)
  884. {
  885.     if (audioRate < 1000)
  886.         return 0;
  887.  
  888.     return sampleCounter / (audioRate / 1000);
  889. }
  890.  
  891. static bool loadSTM(const uint8_t *dat, uint32_t modLen)
  892. {
  893.     uint8_t pats, *pattdata;
  894.     uint16_t a, ver;
  895.     st_ins_t *s;
  896.  
  897.     ver = (dat[30] * 100) + dat[31];
  898.     if (dat[29] != 2 || (ver != 200 && ver != 210 && ver != 220 && ver != 221))
  899.         return false; // unsupported
  900.  
  901.     memset(smp, 0, sizeof (smp));
  902.     memset(st1, 99, sizeof (st1)); // 8bitbubsy: added for safety
  903.  
  904.     memcpy(songname, dat, 20);
  905.     songname[20] = '\0';
  906.  
  907.     gvolume = 64;
  908.  
  909.     tempo = dat[32];
  910.     if (ver < 221)
  911.         tempo = (tempo % 10) + (tempo / 10) * 16;
  912.  
  913.     pats = dat[33];
  914.  
  915.     if (ver > 210)
  916.     {
  917.         gvolume = dat[34];
  918.         if (gvolume > 64) // 8bitbubsy: added for safety
  919.             gvolume = 64;
  920.     }
  921.  
  922.     // load sample information
  923.     s = smp;
  924.     for (a = 0; a < MAX_SAMPLES; a++, s++)
  925.     {
  926.         uint8_t *sdat = (uint8_t *)&dat[48 + (a * 32)];
  927.  
  928.         s->segm = *(uint16_t *)&sdat[14];
  929.         s->length = *(uint16_t *)&sdat[16];
  930.         s->lp_beg = *(uint16_t *)&sdat[18];
  931.         s->lp_end = *(uint16_t *)&sdat[20];
  932.         s->vol = sdat[22];
  933.         s->c1spd = *(uint16_t *)&sdat[24];
  934.  
  935.         if (s->lp_end == 0)
  936.             s->lp_end = 65535;
  937.  
  938.         // 8bitbubsy: added loop overflow handling (not present in ST2.3)
  939.         if (s->lp_end != 65535)
  940.         {
  941.             if (s->lp_end > s->length)
  942.                 s->lp_end = s->length;
  943.  
  944.             if (s->lp_beg >= s->lp_end)
  945.             {
  946.                 s->lp_beg = 0;
  947.                 s->lp_end = 65535;
  948.             }
  949.         }
  950.  
  951.         if (s->vol > 64) // 8bitbubsy: added for safety
  952.             s->vol = 64;
  953.     }
  954.  
  955.     memcpy(st1, &dat[1040], (ver == 200) ? 64 : 128); // read order list
  956.     memset(st2, 0, sizeof (st2)); // wipe pattern data
  957.  
  958.     // load pattern data
  959.     pattdata = (uint8_t *)&dat[(ver == 200) ? (1040+64) : (1040+128)];
  960.     for (a = 0; a < pats; a++)
  961.     {
  962.         for (uint16_t u = 0; u < 1024;)
  963.         {
  964.             uint8_t c = *pattdata++;
  965.             if (c == 251)
  966.             {
  967.                 st2[a*1024+u]=0; u++;
  968.                 st2[a*1024+u]=0; u++;
  969.                 st2[a*1024+u]=0; u++;
  970.                 st2[a*1024+u]=0; u++;
  971.             }
  972.             else if (c == 253)
  973.             {
  974.                 st2[a*1024+u]=254; u++;
  975.                 st2[a*1024+u]=1; u++;
  976.                 st2[a*1024+u]=128; u++;
  977.                 st2[a*1024+u]=0; u++;
  978.             }
  979.             else if (c==252)
  980.             {
  981.                 st2[a*1024+u]=255; u++;
  982.                 st2[a*1024+u]=1; u++;
  983.                 st2[a*1024+u]=128; u++;
  984.                 st2[a*1024+u]=0; u++;
  985.             }
  986.             else
  987.             {
  988.                 st2[a*1024+u]=c; u++;
  989.                 st2[a*1024+u]=*pattdata++; u++;
  990.                 st2[a*1024+u]=*pattdata++; u++;
  991.                 st2[a*1024+u]=*pattdata++; u++;
  992.  
  993.                 if (ver < 221 && (st2[a*1024+u-2] & 15) == 1)
  994.                 {
  995.                     uint8_t d, b;
  996.                     d=st2[a*1024+u-1];
  997.                     b=d/10;
  998.                     d%=10;
  999.                     d+=b*16;
  1000.                     st2[a*1024+u-1]=d;
  1001.                 }
  1002.             }
  1003.         }
  1004.     }
  1005.  
  1006.     // load sample data
  1007.     s = smp;
  1008.     for (a = 0; a < MAX_SAMPLES; a++, s++)
  1009.     {
  1010.         uint32_t smpOffsetInFile = s->segm << 4;
  1011.  
  1012.         if (s->vol == 0 || s->length == 0 || s->c1spd == 0 || smpOffsetInFile >= modLen)
  1013.             continue;
  1014.  
  1015.         s->data = (int8_t *)malloc(s->length);
  1016.         if (s->data == NULL)
  1017.             return false;
  1018.  
  1019.         memcpy(s->data, &dat[smpOffsetInFile], s->length); // copy over sample data
  1020.     }
  1021.  
  1022.     return true;
  1023. }
  1024.  
  1025. bool st23play_PlaySong(const uint8_t *moduleData, uint32_t dataLength, uint32_t audioFreq)
  1026. {
  1027.     st23play_Close();
  1028.     memset(songname, 0, sizeof (songname));
  1029.  
  1030.     if (audioFreq == 0)
  1031.         audioFreq = 44100;
  1032.  
  1033.     audioFreq = CLAMP(audioFreq, 44100, 96000);
  1034.  
  1035.     oversamplingFactor = 2;
  1036.     if (audioFreq >= 64372)
  1037.         oversamplingFactor = 1;
  1038.  
  1039.     dPer2HzDiv = (double)(BASE_CLOCK * PERIOD_FACTOR) / (audioFreq * oversamplingFactor);
  1040.  
  1041.     sampleCounter = 0;
  1042.     musicPaused = true;
  1043.     audioRate = audioFreq;
  1044.     soundBufferSize = MIX_BUF_SAMPLES;
  1045.  
  1046.     dMixBuffer = (double *)malloc(MIX_BUF_SAMPLES * sizeof (double) * oversamplingFactor);
  1047.     if (dMixBuffer == NULL || !openMixer(audioRate) || !loadSTM(moduleData, dataLength))
  1048.         goto playError;
  1049.  
  1050.     memset(chn, 0, sizeof (chn));
  1051.     _znewtempo(tempo);
  1052.     subcnt = 0;
  1053.     breakpat = false;
  1054.     vpnt = 127-1; // will be set to 0 in nextpat()
  1055.     nextpat();
  1056.     dPrngState = 0.0;
  1057.     musicPaused = false;
  1058.     return true;
  1059.  
  1060. playError:
  1061.     st23play_Close();
  1062.     return false;
  1063. }
  1064.  
  1065. // the following must be changed if you want to use another audio API than WinMM
  1066.  
  1067. #ifndef WIN32_LEAN_AND_MEAN
  1068. #define WIN32_LEAN_AND_MEAN
  1069. #endif
  1070.  
  1071. #include <windows.h>
  1072. #include <mmsystem.h>
  1073.  
  1074. #define MIX_BUF_NUM 2
  1075.  
  1076. static volatile BOOL audioRunningFlag;
  1077. static uint8_t currBuffer;
  1078. static int16_t *mixBuffer[MIX_BUF_NUM];
  1079. static HANDLE hThread, hAudioSem;
  1080. static WAVEHDR waveBlocks[MIX_BUF_NUM];
  1081. static HWAVEOUT hWave;
  1082.  
  1083. static DWORD WINAPI mixThread(LPVOID lpParam)
  1084. {
  1085.     WAVEHDR *waveBlock;
  1086.  
  1087.     (void)lpParam;
  1088.  
  1089.     SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
  1090.  
  1091.     while (audioRunningFlag)
  1092.     {
  1093.         waveBlock = &waveBlocks[currBuffer];
  1094.         st23play_FillAudioBuffer((int16_t *)waveBlock->lpData, MIX_BUF_SAMPLES);
  1095.         waveOutWrite(hWave, waveBlock, sizeof (WAVEHDR));
  1096.         currBuffer = (currBuffer + 1) % MIX_BUF_NUM;
  1097.  
  1098.         // wait for buffer fill request
  1099.         WaitForSingleObject(hAudioSem, INFINITE);
  1100.     }
  1101.  
  1102.     return 0;
  1103. }
  1104.  
  1105. static void CALLBACK waveProc(HWAVEOUT hWaveOut, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
  1106. {
  1107.     (void)hWaveOut;
  1108.     (void)uMsg;
  1109.     (void)dwInstance;
  1110.     (void)dwParam1;
  1111.     (void)dwParam2;
  1112.  
  1113.     if (uMsg == WOM_DONE)
  1114.         ReleaseSemaphore(hAudioSem, 1, NULL);
  1115. }
  1116.  
  1117. static void closeMixer(void)
  1118. {
  1119.     int32_t i;
  1120.  
  1121.     audioRunningFlag = false; // make thread end when it's done
  1122.  
  1123.     if (hAudioSem != NULL)
  1124.         ReleaseSemaphore(hAudioSem, 1, NULL);
  1125.  
  1126.     if (hThread != NULL)
  1127.     {
  1128.         WaitForSingleObject(hThread, INFINITE);
  1129.         CloseHandle(hThread);
  1130.         hThread = NULL;
  1131.     }
  1132.  
  1133.     if (hAudioSem != NULL)
  1134.     {
  1135.         CloseHandle(hAudioSem);
  1136.         hAudioSem = NULL;
  1137.     }
  1138.  
  1139.     if (hWave != NULL)
  1140.     {
  1141.         waveOutReset(hWave);
  1142.         for (i = 0; i < MIX_BUF_NUM; i++)
  1143.         {
  1144.             if (waveBlocks[i].dwUser != 0xFFFF)
  1145.                 waveOutUnprepareHeader(hWave, &waveBlocks[i], sizeof (WAVEHDR));
  1146.         }
  1147.  
  1148.         waveOutClose(hWave);
  1149.         hWave = NULL;
  1150.     }
  1151.  
  1152.     for (i = 0; i < MIX_BUF_NUM; i++)
  1153.     {
  1154.         if (mixBuffer[i] != NULL)
  1155.         {
  1156.             free(mixBuffer[i]);
  1157.             mixBuffer[i] = NULL;
  1158.         }
  1159.     }
  1160. }
  1161.  
  1162. static bool openMixer(uint32_t audioFreq)
  1163. {
  1164.     int32_t i;
  1165.     DWORD threadID;
  1166.     WAVEFORMATEX wfx;
  1167.  
  1168.     // don't unprepare headers on error
  1169.     for (i = 0; i < MIX_BUF_NUM; i++)
  1170.         waveBlocks[i].dwUser = 0xFFFF;
  1171.  
  1172.     closeMixer();
  1173.  
  1174.     ZeroMemory(&wfx, sizeof (wfx));
  1175.     wfx.nSamplesPerSec = audioFreq;
  1176.     wfx.wBitsPerSample = 16;
  1177.     wfx.nChannels = 2;
  1178.     wfx.wFormatTag = WAVE_FORMAT_PCM;
  1179.     wfx.nBlockAlign = wfx.nChannels * (wfx.wBitsPerSample / 8);
  1180.     wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
  1181.  
  1182.     samplesLeft = 0;
  1183.     currBuffer = 0;
  1184.  
  1185.     if (waveOutOpen(&hWave, WAVE_MAPPER, &wfx, (DWORD_PTR)&waveProc, 0, CALLBACK_FUNCTION) != MMSYSERR_NOERROR)
  1186.         goto omError;
  1187.  
  1188.     // create semaphore for buffer fill requests
  1189.     hAudioSem = CreateSemaphore(NULL, MIX_BUF_NUM - 1, MIX_BUF_NUM, NULL);
  1190.     if (hAudioSem == NULL)
  1191.         goto omError;
  1192.  
  1193.     // allocate WinMM mix buffers
  1194.     for (i = 0; i < MIX_BUF_NUM; i++)
  1195.     {
  1196.         mixBuffer[i] = (int16_t *)calloc(MIX_BUF_SAMPLES, wfx.nBlockAlign);
  1197.         if (mixBuffer[i] == NULL)
  1198.             goto omError;
  1199.     }
  1200.  
  1201.     // initialize WinMM mix headers
  1202.     memset(waveBlocks, 0, sizeof (waveBlocks));
  1203.     for (i = 0; i < MIX_BUF_NUM; i++)
  1204.     {
  1205.         waveBlocks[i].lpData = (LPSTR)mixBuffer[i];
  1206.         waveBlocks[i].dwBufferLength = MIX_BUF_SAMPLES * wfx.nBlockAlign;
  1207.         waveBlocks[i].dwFlags = WHDR_DONE;
  1208.  
  1209.         if (waveOutPrepareHeader(hWave, &waveBlocks[i], sizeof (WAVEHDR)) != MMSYSERR_NOERROR)
  1210.             goto omError;
  1211.     }
  1212.  
  1213.     // create main mixer thread
  1214.     audioRunningFlag = true;
  1215.     hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)mixThread, NULL, 0, &threadID);
  1216.     if (hThread == NULL)
  1217.         goto omError;
  1218.  
  1219.     return TRUE;
  1220.  
  1221. omError:
  1222.     closeMixer();
  1223.     return FALSE;
  1224. }
  1225.  
  1226. // ---------------------------------------------------------------------------
  1227.  
  1228. // END OF FILE
  1229.  
Add Comment
Please, Sign In to add comment