8bitbubsy

kolibrimod (small .mod replayer)

Sep 11th, 2016 (edited)
953
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /* kolibrimod - small 1..99ch .MOD replayer by 8bitbubsy - 2nd of December 2020 - remember to link winmm.lib!
  2. ** License: BSD-3 clause
  3. */
  4.  
  5. #define AUDIO_RATE 44100
  6. #define AUDIO_BUF_LEN 1024
  7.  
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <stdint.h>
  12. #include <stdbool.h>
  13. #include <conio.h> // _getch()
  14. #include <math.h> // ceil()
  15. #include <windows.h> // Sleep(), mixer stuff
  16.  
  17. #define FRAC_BITS 24
  18. #define FRAC_SCALE (1UL << FRAC_BITS)
  19. #define FRAC_MASK (FRAC_SCALE-1)
  20. #define BPM2SAMPLES_PER_TICK(x) ((audioFreq * 2.5) / (x))
  21. #define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
  22. #define CLAMP16(i) if ((int16_t)(i) != i) i = 0x7FFF ^ (i >> 31)
  23. #define PERIOD2DELTA(p) (int32_t)((dBaseClk / (int32_t)(p)) + 0.5)
  24.  
  25. typedef struct
  26. {
  27.     uint8_t note, sample, efx, param;
  28. } note_t;
  29.  
  30. typedef struct
  31. {
  32.     bool loopFlag;
  33.     int8_t *data;
  34.     uint8_t finetune, volume;
  35.     uint32_t length, loopStart, loopLength;
  36. } sample_t;
  37.  
  38. typedef struct
  39. {
  40.     int8_t *sampleData, *swapData;
  41.     int16_t panL, panR, volL, volR;
  42.     bool loopFlag, swapLoopFlag;
  43.     uint32_t sampleEnd, loopStart, loopLength, swapSampleEnd, swapLoopStart, swapLoopLength, oldPos, pos;
  44.     uint32_t frac, delta;
  45. } voice_t;
  46.  
  47. typedef struct
  48. {
  49.     bool noteFlag, sampleLoopFlag;
  50.     int8_t vol, volOut, finetune, *invLoopPtr, *sampleData, *invLoopStartPtr, E6Row, E6Cnt;
  51.     uint8_t note, efx, efx2, portaMem, vibratoDepth, vibratoSpeed, glissandoMode, lastSample;
  52.     uint8_t tremoloDepth, tremoloSpeed, vibratoPos, vibratoType, tremoloPos, tremoloType, invLoopSpeed, invLoopPos;
  53.     uint16_t period, toPeriod, periodOut;
  54.     int32_t sampleOffsetMem, sampleOffset, invLoopLen, sampleLength, sampleLoopStart, sampleLoopLength;
  55. } channel_t;
  56.  
  57. static volatile bool isMixing;
  58. static bool newPosFlag, patLoop, ptMode, periodsCalculated;
  59. static char songName[20+1];
  60. static int8_t modSpeed, pattNum, tickExtendFactor, newRow, row, *mixerBuffer;
  61. static uint8_t modOrder, restartPos, orderNum, orders[128];
  62. static uint16_t modTick, minPeriod = 113*4, maxPeriod = 856*4;
  63. static int32_t pattSize, channels, audioFreq, mixBuffer[AUDIO_BUF_LEN*2];
  64. static note_t *patterns[128], *patternPtr;
  65. static sample_t samples[31];
  66. static double dBaseClk = 3546895*4, dSamplesPerTick, dTickSampleCounter;
  67. static const uint8_t invLoopTab[16] = { 0, 5, 6, 7, 8, 10, 11, 13, 16, 19, 22, 26, 32, 43, 64, 128 };
  68. static const uint8_t arpTab[32] = { 0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1 };
  69. static uint16_t periodTab[16][96];
  70. static const uint16_t loadPeriods[96] = // Amiga period table for converting period to note on load
  71. {
  72.     6848, 6464, 6096, 5760, 5424, 5120, 4832, 4560, 4304, 4064, 3840, 3624,
  73.     3424, 3232, 3048, 2880, 2712, 2560, 2416, 2280, 2152, 2032, 1920, 1812,
  74.     1712, 1616, 1524, 1440, 1356, 1280, 1208, 1140, 1076, 1016,  960,  906,
  75.      856,  808,  762,  720,  678,  640,  604,  570,  538,  508,  480,  453,
  76.      428,  404,  381,  360,  339,  320,  302,  285,  269,  254,  240,  226,
  77.      214,  202,  190,  180,  170,  160,  151,  143,  135,  127,  120,  113,
  78.      107,  101,   95,   90,   85,   80,   75,   71,   67,   63,   60,   56,
  79.       53,   50,   47,   45,   42,   40,   37,   35,   33,   31,   30,   28
  80. };
  81. static const uint16_t ft2Periods[96] = // FT2 Amiga period table
  82. {
  83.     27392, 25856, 24384, 23040, 21696, 20480, 19328, 18240, 17216, 16256, 15360, 14512,
  84.     13696, 12928, 12192, 11520, 10848, 10240,  9664,  9120,  8608,  8128,  7680,  7256,
  85.      6848,  6464,  6096,  5760,  5424,  5120,  4832,  4560,  4304,  4064,  3840,  3628,
  86.      3424,  3232,  3048,  2880,  2712,  2560,  2416,  2280,  2152,  2032,  1920,  1814,
  87.      1712,  1616,  1524,  1440,  1356,  1280,  1208,  1140,  1076,  1016,   960,   907,
  88.       856,   808,   762,   720,   678,   640,   604,   570,   538,   508,   480,   453,
  89.       428,   404,   381,   360,   339,   320,   302,   285,   269,   254,   240,   227,
  90.       214,   202,   190,   180,   169,   160,   151,   142,   134,   127,   120,   113
  91. };
  92. static const double dFTuneMul[16] = // x = exp2(((i ^ 8) - 8) * / -(12.0 * 8.0));
  93. {
  94.     1.0000000000000000,0.9928057204912689,0.9856631986401874,0.9785720620877002,
  95.     0.9715319411536059,0.9645424688172866,0.9576032806985737,0.9507140150387501,
  96.     1.0594630943592953,1.0518410207292894,1.0442737824274138,1.0367609849529913,
  97.     1.0293022366434919,1.0218971486541166,1.0145453349375237,1.0072464122237039
  98. };
  99. static const uint8_t sinusTab[32] =
  100. {
  101.     0x00,0x18,0x31,0x4A,0x61,0x78,0x8D,0xA1,0xB4,0xC5,0xD4,0xE0,0xEB,0xF4,0xFA,0xFD,
  102.     0xFF,0xFD,0xFA,0xF4,0xEB,0xE0,0xD4,0xC5,0xB4,0xA1,0x8D,0x78,0x61,0x4A,0x31,0x18
  103. };
  104. static voice_t voice[100];
  105. static channel_t channel[100];
  106. static WAVEHDR waveBlocks[4];
  107. static HWAVEOUT hWaveOut;
  108. static WAVEFORMATEX wfx;
  109.  
  110. static void tickReplayer(void);
  111.  
  112. static void calcFinetunedPeriodTab(void)
  113. {
  114.     for (int32_t ftune = 0; ftune < 16; ftune++)
  115.     {
  116.         for (int32_t note = 0; note < 96; note++)
  117.             periodTab[ftune][note] = (uint16_t)(int32_t)((ft2Periods[note] * dFTuneMul[ftune]) + 0.5);
  118.     }
  119. }
  120.  
  121. static uint8_t periodToNote(uint16_t period, uint8_t ftune)
  122. {
  123.     int32_t i;
  124.     for (i = 0; i < 96; i++) if (period >= periodTab[ftune][i]) break;
  125.     return (uint8_t)i;
  126. }
  127.  
  128. // mixes one output sample w/ linear interpolation
  129. #define MIX_SMP \
  130.     sample = smpPtr[0] << 8; \
  131.     sample2 = smpPtr[1] << 8; \
  132.     sample = sample + (((sample2-sample) * (int32_t)(v->frac >> (FRAC_BITS-15))) >> 15); \
  133.     (*curMixPtr++) += sample * v->volL; \
  134.     (*curMixPtr++) += sample * v->volR; \
  135.     v->frac += v->delta; \
  136.     smpPtr += v->frac >> FRAC_BITS; \
  137.     v->frac &= FRAC_MASK; \
  138.  
  139. static void mixChannels(int32_t *mixPtr, uint32_t numSamples)
  140. {
  141.     voice_t *v = voice;
  142.     for (int32_t i = 0; i < channels; i++, v++)
  143.     {
  144.         if (v->sampleData == NULL || v->sampleEnd <= 0 || v->delta == 0) continue; // voice is not active
  145.         int32_t sample, sample2, *curMixPtr = mixPtr;
  146.         uint32_t samplesLeft = numSamples;
  147.         while (samplesLeft)
  148.         {
  149.             uint32_t x = (v->sampleEnd-1) - v->pos;
  150.             if (x > 65535) x = 65535;
  151.             x = (x << 16) | ((v->frac >> (FRAC_BITS-16)) ^ 0xFFFF);
  152.             uint32_t samplesToMix = (x / v->delta) + 1;
  153.             if (samplesToMix > samplesLeft) samplesToMix = samplesLeft;
  154.             samplesLeft -= samplesToMix;
  155.  
  156.             const int8_t *smpPtr = v->sampleData + v->pos;
  157.             for (uint32_t j = 0; j < (samplesToMix & 15); j++)
  158.             {
  159.                 MIX_SMP
  160.             }
  161.             samplesToMix >>= 4;
  162.             for (uint32_t j = 0; j < samplesToMix; j++)
  163.             {
  164.                 MIX_SMP MIX_SMP MIX_SMP MIX_SMP
  165.                 MIX_SMP MIX_SMP MIX_SMP MIX_SMP
  166.                 MIX_SMP MIX_SMP MIX_SMP MIX_SMP
  167.                 MIX_SMP MIX_SMP MIX_SMP MIX_SMP
  168.             }
  169.  
  170.             v->pos = (uint32_t)(smpPtr - v->sampleData);
  171.             if (v->pos >= v->sampleEnd) // end of sample?
  172.             {
  173.                 if (v->swapData == NULL) // no sample swap to do
  174.                 {
  175.                     if (v->loopFlag)
  176.                     {
  177.                         do
  178.                         {
  179.                             v->pos -= v->loopLength;
  180.                         }
  181.                         while (v->pos >= v->sampleEnd);
  182.                     }
  183.                     else
  184.                     {
  185.                         v->sampleData = NULL;
  186.                         break;
  187.                     }
  188.                 }
  189.                 else // do sample swapping
  190.                 {
  191.                     if (!v->swapLoopFlag)
  192.                     {
  193.                         v->sampleData = NULL; // illegal swap, turn off voice
  194.                         break;
  195.                     }
  196.  
  197.                     v->sampleData = v->swapData;
  198.                     v->sampleEnd = v->swapSampleEnd;
  199.                     v->loopStart = v->swapLoopStart;
  200.                     v->loopLength = v->swapLoopLength;
  201.                     v->loopFlag = v->swapLoopFlag;
  202.                     v->pos = v->loopStart;
  203.                     v->swapData = NULL; // current sample swap has finished
  204.                 }
  205.             }
  206.         }
  207.     }
  208. }
  209.  
  210. static void CALLBACK waveOutProc(HWAVEOUT _hWaveOut, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
  211. {
  212.     if (uMsg != MM_WOM_DONE) return;
  213.     WAVEHDR *waveBlockHeader = (WAVEHDR *)dwParam1;
  214.     waveOutUnprepareHeader(_hWaveOut, waveBlockHeader, sizeof (WAVEHDR));
  215.  
  216.     if (!isMixing) return;
  217.     memcpy(waveBlockHeader->lpData, mixerBuffer, AUDIO_BUF_LEN * 4);
  218.     waveOutPrepareHeader(_hWaveOut, waveBlockHeader, sizeof (WAVEHDR));
  219.     waveOutWrite(_hWaveOut, waveBlockHeader, sizeof (WAVEHDR));
  220.  
  221.     memset(mixBuffer, 0, AUDIO_BUF_LEN * (2 * sizeof (int32_t)));
  222.  
  223.     int32_t *mixBufferPtr = mixBuffer;
  224.     int32_t samplesLeft = AUDIO_BUF_LEN;
  225.     while (samplesLeft > 0)
  226.     {
  227.         if (dTickSampleCounter <= 0.0)
  228.         {
  229.             tickReplayer();
  230.             dTickSampleCounter += dSamplesPerTick;
  231.         }
  232.  
  233.         const int32_t remainingTick = (int32_t)ceil(dTickSampleCounter);
  234.         int32_t samplesToMix = samplesLeft;
  235.         if (samplesToMix > remainingTick) samplesToMix = remainingTick;
  236.  
  237.         mixChannels(mixBufferPtr, samplesToMix);
  238.         mixBufferPtr += samplesToMix*2;
  239.         samplesLeft -= samplesToMix;
  240.         dTickSampleCounter -= samplesToMix;
  241.     }
  242.  
  243.     mixBufferPtr = mixBuffer;
  244.     int16_t *streamOut = (int16_t *)mixerBuffer;
  245.     for (int32_t i = 0; i < AUDIO_BUF_LEN; i++)
  246.     {
  247.         int32_t smpL = *mixBufferPtr++ >> 10;
  248.         int32_t smpR = *mixBufferPtr++ >> 10;
  249.         CLAMP16(smpL);
  250.         CLAMP16(smpR);
  251.         *streamOut++ = (int16_t)smpL;
  252.         *streamOut++ = (int16_t)smpR;
  253.     }
  254.  
  255.     (void)dwParam2;
  256.     (void)dwInstance;
  257. }
  258.  
  259. #define ID(x) !strcmp(magic, x)
  260. static bool getNumbersOfChannels(FILE *in)
  261. {
  262.     char magic[5]; magic[4] = '\0';
  263.     fseek(in, 1080, SEEK_SET);
  264.     fread(magic, 1, 4, in);
  265.     rewind(in);
  266.  
  267.     ptMode = false;
  268.     channels = 0;
  269.     if (ID("M.K.") || ID("M!K!") || ID("NSMS") || ID("LARD") || ID("PATT")) { ptMode = true; channels = 4; } // ProTracker (or compatible)
  270.     else if (magic[1] == 'C' && magic[2] == 'H' && magic[3] == 'N') channels = magic[0] - '0'; // FT2/others
  271.     else if (magic[2] == 'C' && magic[3] == 'H') channels = ((magic[0] - '0') * 10) + (magic[1] - '0'); // FT2/others
  272.  
  273.     if (channels < 1 || channels > 99) return false;
  274.     pattSize = channels * (64 * 4);
  275.     return true;
  276. }
  277.  
  278. static void freeData(void)
  279. {
  280.     for (int32_t i = 0; i < 128; i++)
  281.     {
  282.         if (patterns[i] != NULL)
  283.         {
  284.             free(patterns[i]);
  285.             patterns[i] = NULL;
  286.         }
  287.     }
  288.  
  289.     for (int32_t i = 0; i < 31; i++)
  290.     {
  291.         if (samples[i].data != NULL)
  292.         {
  293.             free(samples[i].data);
  294.             samples[i].data = NULL;
  295.         }
  296.     }
  297. }
  298.  
  299. bool kolibrimodLoad(FILE *in, int32_t audioOutputFreq)
  300. {
  301.     freeData();
  302.  
  303.     if (!periodsCalculated) { calcFinetunedPeriodTab(); periodsCalculated = true; }
  304.     if (!getNumbersOfChannels(in)) return false;
  305.  
  306.     rewind(in);
  307.     fread(songName, 1, 20, in); songName[20] = '\0';
  308.     fseek(in, 950, SEEK_SET);
  309.     fread(&orderNum, 1, 1, in);
  310.     fread(&restartPos, 1, 1, in);
  311.     if (orderNum > 128) return false; // too many orders!
  312.  
  313.     // count number of patterns
  314.     pattNum = 0;
  315.     fseek(in, 952, SEEK_SET);
  316.     for (uint8_t i = 0; i < 128; i++)
  317.     {
  318.         orders[i] = (uint8_t)fgetc(in);
  319.         if (orders[i] > pattNum) pattNum = orders[i];
  320.     }
  321.     pattNum++;
  322.  
  323.     // read sample structs
  324.     memset(samples, 0, sizeof (samples));
  325.     fseek(in, 20, SEEK_SET);
  326.     sample_t *smp = samples;
  327.     for (int32_t i = 0; i < 31; i++, smp++)
  328.     {
  329.         fseek(in, 22, SEEK_CUR);
  330.         uint8_t bytes[8]; fread(bytes, 1, 8, in);
  331.         smp->finetune = bytes[2] & 0xF;
  332.         smp->volume = (bytes[3] > 64) ? 64 : bytes[3];
  333.         smp->length = ((bytes[0] << 8) | bytes[1]) * 2;
  334.         smp->loopStart = ((bytes[4] << 8) | bytes[5]) * 2;
  335.         smp->loopLength = ((bytes[6] << 8) | bytes[7]) * 2;
  336.         smp->loopFlag = (smp->loopStart+smp->loopLength) > 2;
  337.     }
  338.  
  339.     // load pattern data
  340.     fseek(in, 1084, SEEK_SET);
  341.     for (int32_t i = 0; i < pattNum; i++)
  342.     {
  343.         patterns[i] = (note_t *)malloc(pattSize);
  344.         if (patterns[i] == NULL) { freeData(); return false; };
  345.         note_t *p = patterns[i];
  346.         for (int32_t j = 0; j < channels*64; j++, p++)
  347.         {
  348.             uint8_t bytes[4]; fread(bytes, 1, 4, in);
  349.             uint16_t period = ((bytes[0] & 0x0F) << 8) | bytes[1];
  350.             if (ptMode && period > 0 && period < 113 || period > 856) // scan for extended periods
  351.                 ptMode = false;
  352.        
  353.             int32_t k = 0; // convert period to note number (0..95, 96 = none/illegal)
  354.             for (; k < 96; k++)
  355.                 if (period >= loadPeriods[k])
  356.                     break;
  357.  
  358.             p->note = k;
  359.             p->sample = (bytes[0] & 0xF0) | (bytes[2] >> 4);
  360.             p->efx = bytes[2] & 0xF;
  361.             p->param = bytes[3];
  362.         }
  363.     }
  364.  
  365.     // load sample data
  366.     fseek(in, 1084 + (pattSize * pattNum), SEEK_SET);
  367.     smp = samples;
  368.     for (int32_t i = 0; i < 31; i++, smp++)
  369.     {
  370.         if (smp->length == 0) continue;
  371.         smp->data = (int8_t *)malloc(smp->length+1);
  372.         if (smp->data == NULL) { freeData(); return false; };
  373.         fread(smp->data, 1, smp->length, in);
  374.  
  375.         // fix end-sample for branchless interpolation
  376.         const int32_t sampleEnd = smp->loopFlag ? (smp->loopStart+smp->loopLength) : smp->length;
  377.         smp->data[sampleEnd] = smp->loopFlag ? smp->data[smp->loopStart] : 0;
  378.     }
  379.  
  380.     if (!ptMode) // set FT2 base clock and period range
  381.     {
  382.         dBaseClk = 8363 * 1712;
  383.         minPeriod = 1;
  384.         maxPeriod = 32000-1;
  385.     }
  386.  
  387.     memset(&wfx, 0, sizeof (wfx));
  388.     audioFreq = audioOutputFreq;
  389.     wfx.nSamplesPerSec = audioFreq;
  390.     wfx.wBitsPerSample = 16;
  391.     wfx.nChannels = 2;
  392.     wfx.wFormatTag = WAVE_FORMAT_PCM;
  393.     wfx.nBlockAlign = (wfx.wBitsPerSample * wfx.nChannels) / 8;
  394.     wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;
  395.     mixerBuffer = (int8_t *)calloc(AUDIO_BUF_LEN*4, 1);
  396.  
  397.     waveOutOpen(&hWaveOut, WAVE_MAPPER, &wfx, (DWORD_PTR)waveOutProc, 0, CALLBACK_FUNCTION);
  398.     for (int32_t i = 0; i < 4; i++)
  399.     {
  400.         waveBlocks[i].dwBufferLength = AUDIO_BUF_LEN*4;
  401.         waveBlocks[i].lpData = (LPSTR)calloc(AUDIO_BUF_LEN*4, 1);
  402.         waveOutPrepareHeader(hWaveOut, &waveBlocks[i], sizeof (WAVEHDR));
  403.         waveOutWrite(hWaveOut, &waveBlocks[i], sizeof (WAVEHDR));
  404.     }
  405.  
  406.     dBaseClk *= (double)FRAC_SCALE / audioOutputFreq;
  407.     return true;
  408. }
  409.  
  410. bool kolibrimodPlay(void)
  411. {
  412.     memset(channel, 0, sizeof (channel));
  413.     memset(voice, 0, sizeof (voice));
  414.  
  415.     for (int32_t i = 0; i < channels; i++) // set up initial LRRL channel pannings
  416.     {
  417.         voice[i].panL = voice[i].panR = 128;
  418.         if (ptMode)
  419.         {
  420.             voice[i].panR = !((i + 1) & 2) ? 103 : 153; // 25% stereo separation (LRRL..)
  421.             voice[i].panL = 256 - voice[i].panR;
  422.         }
  423.     }
  424.  
  425.     dSamplesPerTick = BPM2SAMPLES_PER_TICK(125);
  426.     dTickSampleCounter = 0.0; // zero tick sample counter so that it will instantly initiate a tick
  427.     modSpeed = 6;
  428.     modTick = modSpeed-1; // don't render a tick of silence
  429.     row = newRow = modOrder = 0;
  430.     tickExtendFactor = 1; // 1 = no delay
  431.     newPosFlag = patLoop = false;
  432.     isMixing = true;
  433.     patternPtr = patterns[orders[modOrder]];
  434.     return true;
  435. }
  436.  
  437. void kolibrimodFree(void)
  438. {
  439.     isMixing = false;
  440.     for (int32_t i = 0; i < 4; i++)
  441.         waveOutUnprepareHeader(hWaveOut, &waveBlocks[i], sizeof (WAVEHDR));
  442.  
  443.     for (int32_t i = 0; i < 4; i++)
  444.     {
  445.         while (waveBlocks[i].dwFlags & WHDR_PREPARED) SleepEx(1, 1); // wait
  446.         if (waveBlocks[i].lpData != NULL) free(waveBlocks[i].lpData); waveBlocks[i].lpData = NULL;
  447.     }
  448.  
  449.     waveOutReset(hWaveOut);
  450.     waveOutClose(hWaveOut);
  451.  
  452.     if (mixerBuffer != NULL)
  453.     {
  454.         free(mixerBuffer);
  455.         mixerBuffer = NULL;
  456.     }
  457.  
  458.     freeData();
  459. }
  460.  
  461. static void triggerVoice(channel_t *c, voice_t *v)
  462. {
  463.     v->sampleData = c->sampleData;
  464.     v->loopStart = c->sampleLoopStart;
  465.     v->loopFlag = c->sampleLoopFlag;
  466.     v->sampleEnd = v->loopFlag ? (c->sampleLoopStart + c->sampleLoopLength) : c->sampleLength;
  467.     v->loopLength = c->sampleLoopLength;
  468.     v->swapData = NULL;
  469.     v->frac = 0;
  470.     c->period = c->toPeriod;
  471.  
  472.     v->pos = v->oldPos = c->sampleOffset; // 9xx sample offset * 256
  473.     if (v->pos >= v->sampleEnd)
  474.     {
  475.         if (v->loopFlag)
  476.             v->pos = v->loopStart;
  477.         else
  478.             v->sampleData = NULL; // cut voice
  479.     }
  480. }
  481.  
  482. static void portamento(channel_t *c)
  483. {
  484.     if (c->period == 0 || c->toPeriod == 0) return;
  485.  
  486.     if (c->period > c->toPeriod)
  487.     {
  488.         c->period -= c->portaMem*4;
  489.         if ((int16_t)c->period <= c->toPeriod) c->period = c->toPeriod;
  490.     }
  491.     else if (c->period < c->toPeriod)
  492.     {
  493.         c->period += c->portaMem*4;
  494.         if (c->period >= c->toPeriod) c->period = c->toPeriod;
  495.     }
  496.  
  497.     c->periodOut = c->period;
  498.     if (c->glissandoMode != 0) // semitones slide
  499.     {
  500.         const uint8_t note = periodToNote(c->periodOut, c->finetune);
  501.         if (note < 96) c->periodOut = periodTab[c->finetune][note];
  502.     }
  503. }
  504.  
  505. static uint16_t getWaveform(channel_t *c, bool tremoloFlag)
  506. {
  507.     const uint8_t type = tremoloFlag ? c->tremoloType : c->vibratoType;
  508.     uint8_t pos = ((tremoloFlag ? c->tremoloPos : c->vibratoPos) >> 2) & 0x1F;
  509.  
  510.     uint8_t data;
  511.          if (type == 0) { data = sinusTab[pos]; }
  512.     else if (type == 1) { data = pos << 3; if (c->vibratoPos >= 128) data = ~data; } // PT2/FT2 bug: always uses vibrato pos
  513.     else                { data = 255; }
  514.  
  515.     return tremoloFlag ? ((data * c->tremoloDepth) >> 6) : ((data * c->vibratoDepth) >> (7-2));
  516. }
  517.  
  518. static void vibrato(channel_t *c)
  519. {
  520.     const uint16_t data = getWaveform(c, false);
  521.     c->periodOut = c->period + ((c->vibratoPos < 128) ? data : -data);
  522.     if (modTick > 0) c->vibratoPos += c->vibratoSpeed;
  523. }
  524.  
  525. static void tremolo(channel_t *c)
  526. {
  527.     const uint16_t data = getWaveform(c, true);
  528.     c->volOut = c->vol + ((c->tremoloPos < 128) ? data : -data);
  529.     c->volOut = CLAMP(c->volOut, 0, 64);
  530.     if (modTick > 0) c->tremoloPos += c->tremoloSpeed;
  531. }
  532.  
  533. static void volumeSlide(channel_t *c)
  534. {
  535.     if (modTick == 0) return;
  536.     c->vol += (c->efx2 & 0xF0) ? (c->efx2 >> 4) : -(c->efx2 & 0xF);
  537.     c->vol = CLAMP(c->vol, 0, 64);
  538. }
  539.  
  540. static void invertLoop(channel_t *c) // ProTracker only
  541. {
  542.     if ((c->invLoopPos += invLoopTab[c->invLoopSpeed]) < 128) return;
  543.     c->invLoopPos = 0;
  544.     if (c->invLoopPtr == NULL) return;
  545.     if (++c->invLoopPtr >= c->invLoopStartPtr+c->invLoopLen) c->invLoopPtr = c->invLoopStartPtr;
  546.     *c->invLoopPtr = -1 - *c->invLoopPtr;
  547. }
  548.  
  549. static void retrigNote(channel_t *c, voice_t *v) // E9x effect
  550. {
  551.     if (c->efx2 > 0x90 && !(modTick == 0 && c->noteFlag) && !(modTick % (c->efx2 & 0xF)))
  552.     {
  553.         v->pos = v->oldPos;
  554.         v->frac = 0;
  555.     }
  556. }
  557.  
  558. static void checkEfx(void)
  559. {
  560.     uint16_t period;
  561.     channel_t *c = channel;
  562.     voice_t *v = voice;
  563.     for (int32_t i = 0; i < channels; i++, c++, v++) // do effects
  564.     {
  565.         if (ptMode && modTick > 0) invertLoop(c);
  566.  
  567.         if (c->efx != 0 || c->efx2 != 0)
  568.         {
  569.             if (c->efx == 0x4) { if (c->efx2&0xF) c->vibratoDepth = c->efx2&0xF; if (c->efx2&0xF0) c->vibratoSpeed = (c->efx2>>4)*4; vibrato(c); }
  570.             if (c->efx == 0x7) { if (c->efx2&0xF) c->tremoloDepth = c->efx2&0xF; if (c->efx2&0xF0) c->tremoloSpeed = (c->efx2>>4)*4; tremolo(c); }
  571.             if (c->efx == 0x6) { vibrato(c); volumeSlide(c); }
  572.  
  573.             if (modTick == 0)
  574.             {   // tick=0 effects
  575.                      if (c->efx == 0x8) { if (!ptMode) { v->panR = c->efx2; v->panL = 256-c->efx2; } }
  576.                 else if (c->efx == 0xB) { newPosFlag = true; newRow = 0; modOrder = c->efx2 - 1; }
  577.                 else if (c->efx == 0xC) { c->vol = (c->efx2 > 64) ? 64 : c->efx2; }
  578.                 else if (c->efx == 0xD) { newPosFlag = true; newRow = ((c->efx2 >> 4) * 10) + (c->efx2 & 0xF); if (newRow > 63) newRow = 0; }
  579.                 else if (c->efx == 0xE)
  580.                 {
  581.                          if ((c->efx2&0xF0)==0x10) { if (c->period > 0) { c->period -= (c->efx2 & 0xF)*4; if ((int16_t)c->period < minPeriod) c->period = minPeriod; } }
  582.                     else if ((c->efx2&0xF0)==0x20) { if (c->period > 0) { c->period += (c->efx2 & 0xF)*4; if ((int16_t)c->period > maxPeriod) c->period = maxPeriod; } }
  583.                     else if ((c->efx2&0xF0)==0x30) { c->glissandoMode = c->efx2 & 0xF; }
  584.                     else if ((c->efx2&0xF0)==0x40) { c->vibratoType = c->efx2 & 0xF; }
  585.                     else if ((c->efx2&0xF0)==0x50) { c->finetune = ptMode ? (c->efx2 & 0xF) : (c->efx2 - 8) & 0xF; }
  586.                     else if ((c->efx2&0xF0)==0x60) { if (c->efx2==0x60) c->E6Row = row; else { if (!c->E6Cnt) c->E6Cnt = c->efx2&0xF;
  587.                                                                            else if (!--c->E6Cnt) return; newRow = c->E6Row; patLoop = true; }}
  588.                     else if ((c->efx2&0xF0)==0x70) { c->tremoloType = c->efx2 & 0xF; }
  589.                     else if ((c->efx2&0xF0)==0x90) retrigNote(c, v);
  590.                     else if ((c->efx2&0xF0)==0xA0) { c->vol += c->efx2 & 0xF; if (c->vol > 64) c->vol = 64; }
  591.                     else if ((c->efx2&0xF0)==0xB0) { c->vol -= c->efx2 & 0xF; if (c->vol < 0) c->vol = 0; }
  592.                     else if ((c->efx2&0xF0)==0xE0) { tickExtendFactor = (c->efx2 & 0xF) + 1; }
  593.                     else if ((c->efx2&0xF0)==0xF0) { if (ptMode) { c->invLoopSpeed = c->efx2 & 0xF; invertLoop(c); } }
  594.                 }
  595.                 else if (c->efx == 0xF) if (c->efx2 < 0x20) { if (c->efx2) modSpeed = c->efx2; } else { dSamplesPerTick = BPM2SAMPLES_PER_TICK(c->efx2); }
  596.             }
  597.             else
  598.             {   // tick>0 effects
  599.                      if (c->efx == 0x1) { if (c->period > 0) { c->period -= c->efx2*4; if ((int16_t)c->period < minPeriod) c->period = minPeriod; } }
  600.                 else if (c->efx == 0x2) { if (c->period > 0) { c->period += c->efx2*4; if ((int16_t)c->period > maxPeriod) c->period = maxPeriod; } }
  601.                 else if (c->efx == 0x3) { if (c->efx2) c->portaMem = c->efx2; portamento(c); }
  602.                 else if (c->efx == 0x5) { portamento(c); volumeSlide(c); }
  603.                 else if (c->efx == 0xE) { if ((c->efx2 & 0xF0) == 0x90) retrigNote(c, v); }
  604.                 else if (c->efx == 0xA) { volumeSlide(c); }
  605.             }
  606.         }
  607.        
  608.              if ((c->efx == 0xE) && (c->efx2 & 0xF0) == 0xC0) { if (modTick == (c->efx2 & 0xF)) c->vol = 0; }
  609.         else if ((c->efx == 0xE) && (c->efx2 & 0xF0) == 0xD0) { if (modTick == (c->efx2 & 0xF) && c->noteFlag) triggerVoice(c, v); }
  610.  
  611.         period = c->period;
  612.         if (c->efx == 0 && c->efx2 != 0 && period > 0) // do arpeggio here
  613.         {
  614.             uint8_t note = periodToNote(period, c->finetune);
  615.             if (note < 96)
  616.             {
  617.                 const uint8_t arpTick = arpTab[modTick];
  618.                      if (arpTick == 1) note += c->efx2 >> 4;
  619.                 else if (arpTick == 2) note += c->efx2 & 0xF;
  620.                 if (note > 95) note = 95;
  621.                 period = periodTab[c->finetune][note];
  622.             }
  623.         }
  624.  
  625.         // vibrato and portamento modifies the output period directly
  626.         if (c->efx != 4 && c->efx != 6 && c->efx != 3 && c->efx != 5) c->periodOut = period;
  627.         v->delta = (c->periodOut > 0) ? PERIOD2DELTA(c->periodOut) : 0;
  628.  
  629.         if (c->efx != 7) c->volOut = c->vol; // tremolo modifies the output volume directly
  630.         v->volL = (c->volOut * v->panL) >> 5;
  631.         v->volR = (c->volOut * v->panR) >> 5;
  632.     }
  633. }
  634.  
  635. static void tickReplayer(void)
  636. {
  637.     if (++modTick >= modSpeed*tickExtendFactor)
  638.     {
  639.         modTick = 0;
  640.         tickExtendFactor = 1; // reset EEx (pattern delay). 1 = no delay
  641.  
  642.         channel_t *c = channel;
  643.         voice_t *v = voice;
  644.         for (uint8_t i = 0; i < channels; i++, c++, v++) // read pattern data
  645.         {
  646.             const note_t *note = &patternPtr[(row*channels) + i];
  647.  
  648.             c->noteFlag = note->note < 96;
  649.             uint16_t period = c->noteFlag ? ft2Periods[note->note] : 0;
  650.             c->efx = note->efx;
  651.             c->efx2 = note->param;
  652.  
  653.             const bool noteDelay = (c->efx == 0xE) && ((c->efx2 & 0xF0) == 0xD0);
  654.             const bool porta = (c->efx == 0x3 || c->efx == 0x5);
  655.  
  656.             const uint8_t sample = note->sample;
  657.             if (sample >= 1 && sample <= 31) // sample found in pattern data
  658.             {
  659.                 sample_t *s = &samples[sample-1];
  660.                 c->finetune = s->finetune;
  661.                 c->volOut = c->vol = s->volume;
  662.                 c->sampleLength = s->length;
  663.                 c->sampleLoopStart = s->loopStart;
  664.                 c->sampleLoopLength = s->loopLength;
  665.                 c->sampleLoopFlag = s->loopFlag;
  666.                 c->sampleData = s->data;
  667.                 c->sampleOffset = 0;
  668.  
  669.                 if (!ptMode) v->panL = v->panR = 128; // reset panning (FT2 mode)
  670.  
  671.                 if (sample != c->lastSample && ptMode && (v->sampleData != NULL) && (!period || porta))
  672.                 {   // do ProTracker sample swap (if voice is active and no pattern note)
  673.                     v->swapData = c->sampleData;
  674.                     v->swapLoopStart = c->sampleLoopStart;
  675.                     v->swapLoopLength = c->sampleLoopLength;
  676.                     v->swapLoopFlag = c->sampleLoopFlag;
  677.                     v->swapSampleEnd = v->swapLoopFlag ? (c->sampleLoopStart + c->sampleLoopLength) : c->sampleLength;
  678.                 }
  679.  
  680.                 c->invLoopLen = c->sampleLoopLength;
  681.                 c->invLoopPtr = c->invLoopStartPtr = &c->sampleData[c->sampleLoopStart];
  682.                 c->lastSample = sample;
  683.             }
  684.  
  685.             if (c->efx == 0x9) // 9xx "set sample offset" efx must be handled here
  686.             {
  687.                 if (c->efx2 > 0) c->sampleOffsetMem = c->efx2 << 8;
  688.                 c->sampleOffset = c->sampleOffsetMem;
  689.             }
  690.  
  691.             if (c->noteFlag) // note found in pattern data
  692.             {
  693.                 if (c->efx == 0xE && (c->efx2 & 0xF0) == 0x50) // set-finetune efx must be handled here as well
  694.                     c->finetune = ptMode ? (c->efx2 & 0xF) : (c->efx2 - 8) & 0xF;
  695.  
  696.                 c->note = note->note;
  697.                 c->toPeriod = periodTab[c->finetune][c->note];
  698.  
  699.                 // trigger sample if no portamento (3xx and 5xy) and no note delay
  700.                 if (c->efx != 0x03 && c->efx != 0x05 && !noteDelay)
  701.                 {
  702.                     c->vibratoPos = c->tremoloPos = 0; // reset vibrato/tremolo position
  703.                     triggerVoice(c, v);
  704.                     c->periodOut = c->period = c->toPeriod; // set initial period
  705.                 }
  706.             }
  707.         }
  708.  
  709.         checkEfx();
  710.  
  711.         if (patLoop) // handle pattern loop (E6x)
  712.         {
  713.             row = newRow;
  714.             newRow = 0;
  715.             newPosFlag = patLoop = false;
  716.         }
  717.         else if (++row >= 64) newPosFlag = true; // increase row like normal
  718.     }
  719.     else checkEfx();
  720.  
  721.     if (newPosFlag) // handle position jump (Bxx), pattern break (Dxx) or end of pattern
  722.     {
  723.         row = newRow;
  724.         newRow = 0;
  725.         newPosFlag = false;
  726.         if (++modOrder >= orderNum)
  727.             modOrder = (restartPos < orderNum) ? restartPos : 0; // loop (wrap) song
  728.         patternPtr = patterns[orders[modOrder]];
  729.     }
  730. }
  731.  
  732. int main(int argc, char *argv[]) // please edit this for your own use!
  733. {
  734. #ifdef _DEBUG
  735.     FILE *f = fopen("debug.mod", "rb");
  736. #else
  737.     if (argc != 2)
  738.     {
  739.         printf("Usage: kolibrimod.exe <module>\n");
  740.         return -1;
  741.     }
  742.  
  743.     FILE *f = fopen(argv[1], "rb");
  744. #endif
  745.     if (f == NULL)
  746.     {
  747.         printf("ERROR: Can't open file!\n");
  748.         return 1;
  749.     }
  750.  
  751.     if (!kolibrimodLoad(f, AUDIO_RATE))
  752.     {
  753.         printf("ERROR: This .MOD is not supported!\n");
  754.         return 1;
  755.     }
  756.  
  757.     fclose(f);
  758.     kolibrimodPlay();
  759.  
  760.     printf("Playing \"%s\" (%dHz - %d channels)\nPress any key to stop...\n",
  761.         songName, audioFreq, channels);
  762.     while (!_getch()) Sleep(250);
  763.     kolibrimodFree();
  764.  
  765.     return 0;
  766. }
  767.  
RAW Paste Data