Advertisement
Kitomas

2024-07-19 (10/13)

Jul 19th, 2024
252
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 38.26 KB | None | 0 0
  1. /******************************************************************************/
  2. /******************************************************************************/
  3. //"kit_w32\src\kit_win32\_kit_common_shared.hpp":
  4. #ifndef _KIT_SRC__KIT_COMMON_SHARED_HPP
  5. #define _KIT_SRC__KIT_COMMON_SHARED_HPP
  6.  
  7. #include <kit/all.hpp>
  8. #include "_kit_globals.hpp"
  9. #include "_kit_opaques.hpp"
  10.  
  11.  
  12. namespace kit {
  13.  
  14.  
  15.  
  16.  
  17. //nothing to put here (yet)
  18.  
  19.  
  20.  
  21.  
  22. };
  23.  
  24. #endif /* _KIT_SRC__KIT_COMMON_SHARED_HPP */
  25. /******************************************************************************/
  26. /******************************************************************************/
  27. //"kit_w32\src\kit_win32\_kit_globals.hpp":
  28. #ifndef _KIT_SRC__KIT_GLOBALS_HPP
  29. #define _KIT_SRC__KIT_GLOBALS_HPP
  30.  
  31. //(this file should not be included on its own,
  32.  //rather it should be included as part of _kit_common_shared.hpp)
  33.  
  34.  
  35. /*tbd:
  36. set window icon(s)
  37.  
  38. warp mouse in window and hide mouse when in window
  39.  
  40. draw rectangles
  41.  
  42. add timers
  43.  
  44. WINPOS_UNDEFINED is broken for some reason
  45.  
  46. currently working on:
  47. */
  48.  
  49.  
  50. /* low priority tbd:
  51.   right side of window glitches out when going off-screen?
  52.   Window::setMinimized() breaks things, and it shouldn't be doing that
  53.   add WIN_MINIMIZE, WIN_MAXIMIZE, and WIN_RESTORE events
  54.   check to see if sdl sends a window resize event when minimizing/maximizing
  55.     before or after the minimize/maximize event itself (if at all)
  56.   set process priority
  57.   make "ran out of memory creating _opq" error text global
  58.   BitmapFont:
  59.     set step direction
  60.     set anchor point
  61.     set transparent color
  62.     set offsets
  63.     printCentered
  64.     (look at Bitmap to look for any more get and set functions)
  65.   mention getLastSystemError in win32-related exceptions
  66.   make a thing for getsysteminfo in general
  67.   move relevant _misc_func stuff to _video_func
  68. */
  69.  
  70. #include <windowsx.h>
  71.  
  72. #include <Windows.h>
  73.  
  74. #include <string.h> //using strcpy_s and strnlen_s
  75.  
  76. #include <stdarg.h> //for fstr's stuff
  77. #  include <stdio.h> //
  78.  
  79. #include <portaudio.h> //portaudio my beloved
  80.  
  81.  
  82. #ifdef _DEBUG
  83. #define _printf(_fmt,...) printf(_fmt,__VA_ARGS__)
  84. #else
  85. #define _printf(_fmt,...)
  86. #endif
  87.  
  88. #if defined(_DEBUG)
  89. #include <stdio.h>
  90. #define loghere printf("line %4i: (%s)\n",__LINE__,__FILE__);
  91. #else
  92. #define loghere  /* do {} while(0); */
  93. #endif /* _DEBUG */
  94.  
  95.  
  96. #define KIT_LOCK_SPINCOUNT (2048)
  97.  
  98.  
  99. //used for Window and Bitmap
  100. #define KIT_INITIAL_STRETCH_MODE COLORONCOLOR //basically nearest-neighbor
  101.  
  102.  
  103. //class type ID macros
  104. #define KIT_OPAQUE_PRESENT (0x80000000)
  105. #define KIT_IS_OPAQUE_PRESENT(_type) ( ((_type)&KIT_OPAQUE_PRESENT) != 0 )
  106.  
  107. #define KIT_CLASSTYPE_NULL              (0x0000                     )
  108. #define KIT_CLASSTYPE_MUTEXSIMPLE       (0x0001 | KIT_OPAQUE_PRESENT)
  109. #define KIT_CLASSTYPE_WINDOW            (0x0002 | KIT_OPAQUE_PRESENT)
  110. #define KIT_CLASSTYPE_BITMAP            (0x0003 | KIT_OPAQUE_PRESENT)
  111. #define KIT_CLASSTYPE_FILEIO_BINARYDATA (0x0004                     )
  112. #define KIT_CLASSTYPE_BITMAPFONT        (0x0005                     )
  113. #define KIT_CLASSTYPE_FSTR              (0x0006                     )
  114. #define KIT_CLASSTYPE_AUDIOSTREAM       (0x0007 | KIT_OPAQUE_PRESENT)
  115. #define KIT_CLASSTYPE_THREAD            (0x0008 | KIT_OPAQUE_PRESENT)
  116. #define KIT_CLASSTYPE_TIMER             (0x0009 | KIT_OPAQUE_PRESENT)
  117.  
  118.  
  119. namespace kit {
  120.  
  121.  
  122.  
  123.  
  124. #define KIT_GET_CLASS_TYPE(_ptr)         ( ((_commonClassValues*)(_ptr))->type         )
  125. #define KIT_GET_CLASS_VALID(_ptr)        ( ((_commonClassValues*)(_ptr))->valid        )
  126. #define KIT_GET_CLASS_CONSTRUCTING(_ptr) ( ((_commonClassValues*)(_ptr))->constructing )
  127. #define KIT_GET_CLASS_DATA(_ptr)         ( ((_commonClassValues*)(_ptr))->data         )
  128. #define KIT_GET_CLASS_OPAQUE(_ptr)       ( ((_commonClassValues*)(_ptr))->opq          )
  129.  
  130. #define KIT_IS_CLASS_TYPE(_ptr,_type)   ( KIT_GET_CLASS_TYPE(_ptr) == (_type) )
  131. #define KIT_IS_CLASS_VALID(_ptr)        ( KIT_GET_CLASS_VALID(_ptr) != 0 )
  132. #define KIT_IS_CLASS_CONSTRUCTING(_ptr) ( KIT_GET_CLASS_CONSTRUCTING(_ptr) != 0 )
  133.  
  134. struct _commonClassValues {
  135.   u32  type;
  136.   bool valid; //'is object fully and successfully constructed?'
  137.   bool constructing; //'is object currently inside constructor?'
  138.   //^^this is useful for if public class functions are called inside the
  139.    //constructor itself, but the valid flag is not set to true yet
  140.   u16  data; //purpose varies by class type; unused by some (or it's split into 2 u8)
  141.   _GenericOpaquePtr opq; //nonexistent if type lacks the KIT_OPAQUE_PRESENT flag
  142. };
  143.  
  144.  
  145.  
  146.  
  147. /*++++++++++*/
  148. /*+kit_main+*/
  149. /*++++++++++*/
  150.  
  151. namespace w32 {
  152.   extern HINSTANCE hThisInst;
  153.   extern HINSTANCE hPrevInst;
  154.   extern LPSTR     lpszArg;
  155.   extern int       nCmdShow;
  156.  
  157.   extern LARGE_INTEGER ticksPerSecond; //used in time::getTicksPerSecond()
  158. };
  159.  
  160.  
  161. namespace eventVars {
  162.   extern CRITICAL_SECTION lock;
  163.  
  164.   //eventVars::end indicates what index should be queued to next,
  165.    //while eventVars::next indicates what index should be dequeued next
  166.    //(if they are the same, that means the queue is empty!)
  167.   extern WindowEvent* queue; //length of 2^16 (which is why u16 indexes are used)
  168.   extern u16 next;
  169.   extern u16 end;
  170. };
  171.  
  172.  
  173.  
  174. //returns false if queue is full
  175. static inline bool AddToEventQueue(WindowEvent& event){
  176.   bool success = false;
  177.   EnterCriticalSection(&eventVars::lock);
  178.  
  179.   if((eventVars::end+1) != eventVars::next){
  180.     eventVars::queue[eventVars::end++] = event;
  181.     success = true;
  182.   }
  183.  
  184.   LeaveCriticalSection(&eventVars::lock);
  185.   return success;
  186. }
  187.  
  188.  
  189. //returns a WINEVENT_NULL event if queue is empty
  190. static inline WindowEvent RemoveFromEventQueue(){
  191.   WindowEvent event; //should auto-initialize to type WINEVENT_NULL
  192.   EnterCriticalSection(&eventVars::lock);
  193.  
  194.   if(eventVars::next != eventVars::end){
  195.     event = eventVars::queue[eventVars::next++];
  196.   }
  197.  
  198.   LeaveCriticalSection(&eventVars::lock);
  199.   return event;
  200. }
  201.  
  202. /*++++++++++*/
  203. /*+kit_main+*/
  204. /*++++++++++*/
  205.  
  206.  
  207.  
  208.  
  209. /*++++++++++++*/
  210. /*+kit_Window+*/
  211. /*++++++++++++*/
  212.  
  213. namespace w32 {
  214.   //tbd: maybe put a critical section on winCount specifically
  215.   extern u32         winCount; //number of existing kit::Window instances
  216.   extern const char  winClassName[];
  217.   extern WNDCLASSEXA winClass;
  218.   extern ATOM        winClassAtom;
  219. };
  220.  
  221. /*------------*/
  222. /*-kit_Window-*/
  223. /*------------*/
  224.  
  225.  
  226.  
  227.  
  228. }; /* namespace kit */
  229.  
  230. #endif /* _KIT_SRC__KIT_GLOBALS_HPP */
  231. /******************************************************************************/
  232. /******************************************************************************/
  233. //"kit_w32\src\kit_win32\_kit_opaques.hpp":
  234. #ifndef _KIT_SRC__KIT_OPAQUES_HPP
  235. #define _KIT_SRC__KIT_OPAQUES_HPP
  236.  
  237. //(this file should not be included on its own,
  238.  //rather it should be included as part of _kit_common_shared.hpp)
  239.  
  240. /*
  241. Opaques are included as follows: (classes without opaques are omitted)
  242. [ ] MutexSimple
  243. [X] Bitmap
  244. [X] Window
  245. [X] AudioStream
  246. [X] Thread
  247. */
  248.  
  249.  
  250. namespace kit {
  251.  
  252.  
  253.  
  254.  
  255. struct _WindowOpaque;
  256. struct _BitmapOpaque {
  257.   CRITICAL_SECTION lock;
  258.   BITMAPINFO       info;
  259.   HBITMAP          handle;
  260.   color::ARGB*     pixels;
  261.   shape::point     size;
  262.   HDC              devCtx;
  263.   _WindowOpaque*   window; //window associated with the bitmap
  264.   s32              stretchMode; //stretch mode when used as blit destination (canvas only basically)
  265.   u8              _unused[3];
  266.   //false for CreateDIBitmap() bitmap, true for CreateDIBSection() bitmap
  267.   bool             directAccess;
  268. };
  269.  
  270.  
  271.  
  272.  
  273. union WindowEvent;
  274. struct _WindowOpaque {
  275.   CRITICAL_SECTION lock;
  276.  
  277.   WindowEvent_Key_Mod kmod; //key modifier flags for key events (shift, ctrl, ...)
  278.  
  279.   //set to true after first WINEVENT_MOUSE_MOVE since entering client area
  280.   bool mouseWasMovedBefore;
  281.  
  282.   bool          canvasStretch; //if false, canvas is resized alongside window
  283.   _BitmapOpaque canvas;
  284.  
  285.   shape::point mousePosition;
  286.  
  287.   //true if a virtual key code's key is currently pressed
  288.    //(don't set any key states during KEY_CHAR events, only KEY_UP & KEY_DOWN!)
  289.   bool keyStates[256];
  290.  
  291.   HWND        winHandle;
  292.   shape::rect winRect; //contains both window position, and window size
  293.   u32         winStretchMode;
  294.   DWORD       winFlags;
  295.   DWORD       winFlagsEx;
  296.   u32         winIndex;
  297.   bool        winFullscreen;
  298.   bool        winShown;
  299.   bool        winFocus;
  300.   bool        winClosed; //true if window has been destroyed, false otherwise
  301.   bool        winMinimized;
  302.   bool        winMaximized;
  303. };
  304.  
  305.  
  306.  
  307.  
  308. struct _AudioStreamOpaque {
  309.   CRITICAL_SECTION       lock;
  310.  
  311.   PaStreamParameters     streamInputParams;
  312.   PaStreamParameters     streamOutputParams;
  313.   PaStream*              streamPtr;
  314.  
  315.   AudioStreamInfo        astreamInfo;
  316.   AudioStreamCallback    callback;
  317.   void*                  userdata;
  318.   AudioStreamEndCallback endCallback;
  319. };
  320.  
  321.  
  322. //i really don't feel like making a whole 'kit_audio_shared.hpp'
  323.  //just for this, so i'll keep this here for now
  324. static inline PaSampleFormat ConvertToPaSampleFormat(u16 kitSmpFmt){
  325.   PaSampleFormat paSmpFmt;
  326.   switch(kitSmpFmt){
  327.     case ASTREAM_FMT_U8 : paSmpFmt = paUInt8;   break;
  328.     case ASTREAM_FMT_S8 : paSmpFmt = paInt8;    break;
  329.     case ASTREAM_FMT_S16: paSmpFmt = paInt16;   break;
  330.     case ASTREAM_FMT_S24: paSmpFmt = paInt24;   break;
  331.     case ASTREAM_FMT_S32: paSmpFmt = paInt32;   break;
  332.     case ASTREAM_FMT_F32: paSmpFmt = paFloat32; break;
  333.     default:              paSmpFmt = paCustomFormat; //indicates an error
  334.   }
  335.   return paSmpFmt;
  336. }
  337.  
  338.  
  339.  
  340.  
  341. struct _ThreadOpaque {
  342.   ThreadFunction threadFunc;
  343.   void*          threadUserdata;
  344.   HANDLE         threadHandle;
  345.   DWORD          threadID;
  346.   s32            threadReturn;
  347.   bool           threadDetached;
  348.   bool           threadDone;
  349.   u16           _padding16;
  350. };
  351.  
  352.  
  353.  
  354.  
  355. }; /* namespace kit */
  356.  
  357. #endif /* _KIT_SRC_KIT_OPAQUES_HPP */
  358. /******************************************************************************/
  359. /******************************************************************************/
  360. //"kit_xmp_sfx\include\kit\xmp_sfx.hpp":
  361. #ifndef _KIT_INC_XMP_SFX_HPP
  362. #define _KIT_INC_XMP_SFX_HPP
  363.  
  364. #include "_xmp_sfx_AudioData.hpp"
  365. #include "_xmp_sfx_SoundEngine.hpp"
  366.  
  367.  
  368. #endif /* _KIT_INC_XMP_SFX_HPP */
  369. /******************************************************************************/
  370. /******************************************************************************/
  371. //"kit_xmp_sfx\include\kit\_xmp_sfx_AudioData.hpp":
  372. #ifndef _KIT_INC__XMP_SFX_AUDIODATA_HPP
  373. #define _KIT_INC__XMP_SFX_AUDIODATA_HPP
  374.  
  375. #include <kit/commondef.hpp>
  376.  
  377.  
  378. namespace kit {
  379.  
  380.  
  381.  
  382.  
  383. #define KIT_MAGIC_KPM (0x4D43506B) // = 'kPCM'
  384. #define KIT_MAGIC_QOA (0x66616F71) // = 'qoaf'
  385.  
  386. class AudioData;
  387.  
  388. struct AudioDataHeader { //72B (0x48B)
  389.   u32       magic; // (0x00) = KIT_MAGIC_KPM
  390.   u16      format; // (0x04) = one of AudioStreamFormats enum values
  391.   u16  headerSize; // (0x06) = sizeof(AudioDataHeader)
  392.   u64    dataSize; // (0x08) = size of audio data, in bytes
  393.  
  394.   u64   loopStart; // (0x10) = which sample to loop back to
  395.   u64     loopEnd; // (0x18) = which sample to jump back to loopStart on
  396.  
  397.   u64  numSamples; // (0x20) = # of sample frames in audio data
  398.   u32  sampleRate; // (0x28) = the audio data's sample rate, in Hz
  399.   u32     bitRate; // (0x2C) = the audio's bit rate (per second)
  400.  
  401.   u16   loopCount; // (0x30) = # of times to loop audio (0 = no loop, 0xFFFF = inf loop)
  402.   u16    channels; // (0x32) = # of interlaced channels in the audio data
  403.   u8 bitRemainder; // (0x34) = <bits per sample> % 8
  404.   u8    userflags; // (0x35) = user-defined (is just padding otherwise)
  405.   u16        mode; // (0x36) = 0 for normal PCM data
  406.   void*   samples; // (0x38) = the audio's sample data (appears as nullptr in file)
  407.   AudioData* AD_p; // (0x40) = the associated AudioData class (also nullptr in file)
  408. };
  409.  
  410.  
  411.  
  412. class SoundEngine;
  413.  
  414. class AudioData {
  415.   u32              _type;
  416.   bool            _valid = false;
  417.   bool     _constructing = true;
  418.   u16         _padding16;
  419.   AudioDataHeader* _data = nullptr;
  420.  
  421.  
  422.   //(_parse<format> functions must free what is returned to prevent leaks)
  423.   AudioDataHeader* _parseKPM(BinaryData& fileData);
  424.   AudioDataHeader* _parseQOA(BinaryData& fileData);
  425.  
  426.   void _construct(const char* filePath, u32 convertToSampleRate,
  427.                   bool convertToStereo); //will convert to mono otherwise
  428.  
  429.  
  430. public:
  431.   //master volume for this AudioData clip specifically
  432.   f32 volumeL = 1.0f;
  433.   f32 volumeR = 1.0f;
  434.  
  435.  
  436.   AudioData(const char* filePath, u32 convertToSampleRate,
  437.             bool convertToStereo)
  438.   { _construct(filePath, convertToSampleRate, convertToStereo); }
  439.  
  440.   AudioData(const char* filePath, const SoundEngine* se);
  441.  
  442.   ~AudioData();
  443.  
  444.  
  445.   const AudioDataHeader* getData(){ return _data; }
  446.  
  447.  
  448.   void print(size_t samplesToPrint = 0);
  449. };
  450.  
  451.  
  452.  
  453.  
  454. };
  455.  
  456. #endif /* _KIT_INC__XMP_SFX_AUDIODATA_HPP */
  457. /******************************************************************************/
  458. /******************************************************************************/
  459. //"kit_xmp_sfx\include\kit\_xmp_sfx_SoundEngine.hpp":
  460. #ifndef _KIT_INC__XMP_SFX_SOUNDENGINE_HPP
  461. #define _KIT_INC__XMP_SFX_SOUNDENGINE_HPP
  462.  
  463. #include <kit/commondef.hpp>
  464.  
  465.  
  466. namespace kit {
  467.  
  468.  
  469.  
  470.  
  471. struct _SoundEngineOpaque;
  472.  
  473. class SoundEngine {
  474.   u32                _type;
  475.   bool              _valid = false;
  476.   bool       _constructing = true;
  477.   u16           _padding16;
  478.   _SoundEngineOpaque* _opq = nullptr;
  479.  
  480.  
  481. public:
  482.  
  483.   SoundEngine(s32 sfxNumTracks             = 64,
  484.               bool musicUseNearestNeighbor = false,
  485.               bool musicCheckLoop          = true,
  486.               bool musicNoFilter           = false);
  487.  
  488.   ~SoundEngine();
  489.  
  490.  
  491.   bool streamIsMono();
  492.   f64  streamGetCPULoad();
  493.  
  494.   bool sfxIsTrackPlaying(s32 track);
  495.   u32 sfxGetActiveTracks();
  496.  
  497.   bool musicIsPlaying();
  498.   bool musicIsModuleLoaded();
  499.  
  500.  
  501.   //if stream is mono internally, only the left channel parameter is used
  502.   void streamSetVolume(f32 volumeL, f32 volumeR);
  503.   void streamSetPlayback(bool playing);
  504.   void streamSetPlaybackAndWait(bool playing);
  505.   void streamSetVolumeForced(f32 volumeL, f32 volumeR);
  506.  
  507.   //if stream is mono internally, pan values are completely ignored
  508.   void sfxSetPanAll(f32 pan); //-1.0f -> 1.0f (0.0f for neutral panning)
  509.   void sfxSetPan(s32 track, f32 pan);
  510.   void sfxSetVolumeAll(f32 volumeL, f32 volumeR);
  511.   void sfxSetVolume(s32 track, f32 volumeL, f32 volumeR);
  512.   void sfxSetVolumeDelta(s32 track, f32 deltaSecondsL, f32 deltaSecondsR);
  513.   void sfxSetSpeedDelta(s32 track, f64 deltaSeconds);
  514.   void sfxSetVolumeAllForced(f32 volumeL, f32 volumeR);
  515.   void sfxSetVolumeForced(s32 track, f32 volumeL, f32 volumeR);
  516.  
  517.   void musicSetPan(f32 pan);
  518.   void musicSetVolume(f32 volumeL, f32 volumeR);
  519.   void musicSetPlayback(bool playing);
  520.   //this one shouldn't *break* if the stream isn't playing as well per se,
  521.    //but it won't work as intended, as all this does (in addition to stopping)
  522.    //is sleep for as long as the fade in/out's set duration
  523.   void musicSetPlaybackAndWait(bool playing);
  524.   void musicSetCheckLoop(bool enable);
  525.   void musicSetUseNearest(bool enable);
  526.   void musicSetVolumeForced(f32 volumeL, f32 volumeR);
  527.  
  528.  
  529.   void lock(bool locked = true);
  530.   void unlock(){ lock(false); }
  531.  
  532.  
  533.   void streamStart(){ streamSetPlayback(true); }
  534.   void streamStop(){ streamSetPlayback(false); }
  535.   void streamStopForced();
  536.   void streamStartAndWait(){ streamSetPlaybackAndWait(true); }
  537.   void streamStopAndWait(){ streamSetPlaybackAndWait(false); }
  538.  
  539.  
  540.   //returns false if timeout is reached, returning true otherwise
  541.   bool sfxWaitForTracks(size_t timeoutMS = 0); //0 to wait indefinitely
  542.   bool sfxWaitForTrack(s32 track, size_t timeoutMS = 0);
  543.  
  544.   //returns the track the audio was queued into, or -1 if no empty track was found
  545.   s32 sfxPlay(const AudioData* audio,
  546.               f32 volumeL = 1.0f, f32 volumeR = 1.0f,
  547.               f64 speed = 1.0, f32 pan = 0.0f);
  548.  
  549.   //make sure to stop all tracks before freeing any instances of AudioData,
  550.    //as to avoid any issues relating to dangling pointers
  551.   void sfxStop(s32 track);
  552.   void sfxStopForced(s32 track); //marks tracks as finished, rather than fading out over 10ms
  553.   void sfxStopAll();
  554.   void sfxStopAllForced();
  555.  
  556.  
  557.   void musicLoadModule(const char* filePath);
  558.   void musicReleaseModule();
  559.  
  560.   void musicStart(){ musicSetPlayback(true); }
  561.   void musicStop(){ musicSetPlayback(false); }
  562.   void musicStopForced();
  563.   void musicStartAndWait(){ musicSetPlaybackAndWait(true); }
  564.   void musicStopAndWait(){ musicSetPlaybackAndWait(false); }
  565. };
  566.  
  567.  
  568.  
  569.  
  570. };
  571.  
  572. #endif /* _KIT_INC__XMP_SFX_SOUNDENGINE_HPP */
  573. /******************************************************************************/
  574. /******************************************************************************/
  575. //"kit_xmp_sfx\src\kit_xmp_sfx\kit_SoundEngine_callbackSfx.hpp":
  576. //this is a header rather than a source file, since the sound effect mixer
  577.  //is in the form of an inline function, to avoid the overhead of a normal one
  578. #ifndef _KIT_SRC_KIT_SOUNDENGINE_CALLBACKSFX_HPP
  579. #define _KIT_SRC_KIT_SOUNDENGINE_CALLBACKSFX_HPP
  580.  
  581. #include "_kit_shared.hpp"
  582.  
  583.  
  584. namespace kit {
  585.  
  586.  
  587.  
  588.  
  589. static inline void mixTracksMono(_SoundEngineTrack& track, f64 streamTimeStamp,
  590.                                  f32* dst, s32 dst_len, f64 sampleRate)
  591. {
  592.   //the value volumeDelta is set to if the track hits 0x speed
  593.   const smp_f32s speed0VDelta = -( (1000.0f/_speed0VolDeltaMS) / sampleRate );
  594.  
  595.   //create stack copy of track data
  596.   //(deltas that can be modified at will (without mutex locking) should not be
  597.    //referenced or set, as they might change by the time the delta values are set back)
  598.   _SoundEngineTrack tr = track;
  599.  
  600.   //make copies of relevant data from t.audio
  601.   u64  loopStart = tr.audio->loopStart;
  602.   u64  loopEnd   = tr.audio->loopEnd; //doubles as src_len
  603.   f32* src       = (f32*)tr.audio->samples;
  604.  
  605.   //calculate position based on difference between dac and audio timestamps
  606.   if(tr.timestamp > 0){
  607.     f64 difference = (streamTimeStamp-tr.timestamp) * sampleRate; //in samples
  608.     tr.position = -(difference*tr.speed_old); //starts playing when position reaches 0
  609.  
  610.     track.timestamp = 0; //to ensure that this only occurs once per clip queued
  611.   }
  612.  
  613.   //used for interpolating speed and volume settings from old to new
  614.   f32 t           = 0.0f;
  615.   f32 t_increment = 1.0f/dst_len;
  616.  
  617.  
  618.  
  619.   //mix src audio into dst
  620.   for(s32 i=0; i<dst_len; ++i){
  621.  
  622.     //loop handling (or end-of-clip handling i guess)
  623.     if(tr.position >= loopEnd){ //audio clip finished loop
  624.       if(!tr.loops){ tr.stopping = true; break; } //mark as inactive and break
  625.       if(tr.loops != KIT_U16_MAX) --tr.loops; //decrement loops (unless infinite)
  626.       tr.position -= (u64)tr.position; //basically position %= 1
  627.       tr.position += loopStart; //now new_position = loopStart + old_position%1
  628.  
  629.     } else if(tr.position < 0){ //if clip has yet to start playing
  630.       if(tr.position < -tr.speed_old){
  631.         tr.position += tr.speed_old; //step forward by current speed
  632.         continue;
  633.       } else { //if position >= -speed, the clip should start next sample
  634.         tr.position = 0; //make sure clip starts at 0
  635.       }
  636.  
  637.     }
  638.  
  639.  
  640.     //get sample
  641.     f32 sample = linearSampleMono(src, tr.position, loopEnd);
  642.     //apply volume while interpolating between its old and new state
  643.     sample *= LERP2(tr.volume_old.l, tr.volume_new.l, t);
  644.     //apply master volume provided by the AudioData's .volumeL member
  645.     sample *= tr.volumeMaster.l;
  646.     //(panning is not applied for mono)
  647.     //update position by speed, while interpolating between speed's old and new state
  648.     tr.position += LERP2(tr.speed_old, tr.speed_new, t);
  649.  
  650.     //change old and new volume by volumeDelta
  651.      //(deltas are referenced directly with track instead of tr)
  652.     f32 currentVolumeDelta = track.volumeDelta.l;
  653.     tr.volume_old.l += currentVolumeDelta;
  654.     tr.volume_new.l += currentVolumeDelta;
  655.     //make sure the volume is always between 0.0f and 1.0f
  656.     tr.volume_old.l = CLAMP(tr.volume_old.l, 0.0f, 1.0f);
  657.     tr.volume_new.l = CLAMP(tr.volume_new.l, 0.0f, 1.0f);
  658.  
  659.     //change old and new speed by speedDelta
  660.     f64 currentSpeedDelta = track.speedDelta;
  661.     tr.speed_old += currentSpeedDelta;
  662.     tr.speed_new += currentSpeedDelta;
  663.  
  664.     //raise interpolation t value
  665.     t += t_increment;
  666.  
  667.     //start rapid fade out if clip's new speed <= 0
  668.     if(LERP2(tr.speed_old, tr.speed_new, t) <= 0.0){
  669.       tr.speed_old = tr.speed_new = 0.0;
  670.       //volumeDelta is sorta volatile, so that might need to be accounted for...
  671.       track.volumeDelta = speed0VDelta;
  672.     }
  673.  
  674.   }
  675.  
  676.  
  677.  
  678.   //set relevant old values to the new ones
  679.   track.position   = tr.position;
  680.   track.speed_old  = tr.speed_new; //both old *and* new speeds
  681.   track.speed_new  = tr.speed_new;  //must be set to their new values
  682.   track.volume_old = tr.volume_new; //both old *and* new volumes
  683.   track.volume_new = tr.volume_new;  //must be set to their new values
  684.   track.loops      = tr.loops;
  685.   track.stopping   = tr.stopping;
  686.  
  687.   //check if track needs to be marked as complete
  688.   if(tr.volume_new.l <= 0) track.stopping = true;
  689.   if(track.stopping) track.audio = nullptr;
  690. }
  691.  
  692.  
  693.  
  694.  
  695. static inline void mixTracksStereo(_SoundEngineTrack& track, f64 streamTimeStamp,
  696.                                    smp_f32s* dst, s32 dst_len, f64 sampleRate)
  697. {
  698.   //the value volumeDelta is set to if the track hits 0x speed
  699.   const smp_f32s speed0VDelta = -( (1000.0f/_speed0VolDeltaMS) / sampleRate );
  700.  
  701.   //create stack copy of track data
  702.   //(deltas that can be modified at will (without mutex locking) should not be
  703.    //referenced or set, as they might change by the time the delta values are set back)
  704.   _SoundEngineTrack tr = track;
  705.  
  706.   //make copies of relevant data from t.audio
  707.   u64       loopStart = tr.audio->loopStart;
  708.   u64       loopEnd   = tr.audio->loopEnd; //doubles as src_len
  709.   smp_f32s* src       = (smp_f32s*)tr.audio->samples;
  710.  
  711.   //calculate position based on difference between dac and audio timestamps
  712.   if(tr.timestamp > 0){
  713.     f64 difference = (streamTimeStamp-tr.timestamp) * sampleRate; //in samples
  714.     tr.position = -(difference*tr.speed_old); //starts playing when position reaches 0
  715.  
  716.     track.timestamp = 0; //to ensure that this only occurs once per clip queued
  717.   }
  718.  
  719.   //used for interpolating speed and volume settings from old to new
  720.   f32 t           = 0.0f;
  721.   f32 t_increment = 1.0f/dst_len;
  722.  
  723.  
  724.  
  725.   //mix src audio into dst
  726.   for(s32 i=0; i<dst_len; ++i){
  727.  
  728.     //loop handling (or end-of-clip handling i guess)
  729.     if(tr.position >= loopEnd){ //audio clip finished loop
  730.       if(!tr.loops){ tr.stopping = true; break; } //mark as inactive and break
  731.       if(tr.loops != KIT_U16_MAX) --tr.loops; //decrement loops (unless infinite)
  732.       tr.position -= (u64)tr.position; //basically position %= 1
  733.       tr.position += loopStart; //now new_position = loopStart + old_position%1
  734.  
  735.     } else if(tr.position < 0){ //if clip has yet to start playing
  736.       if(tr.position < -tr.speed_old){
  737.         tr.position += tr.speed_old; //step forward by current speed
  738.         continue;
  739.       } else { //if position >= -speed, the clip should start next sample
  740.         tr.position = 0; //make sure clip starts at 0
  741.       }
  742.  
  743.     }
  744.  
  745.  
  746.     //get sample
  747.     smp_f32s sample = linearSampleStereo(src, tr.position, loopEnd);
  748.     //apply volume while interpolating between its old and new state
  749.     sample *= interpolateF32S(tr.volume_old, tr.volume_new, t);
  750.     //apply master volume provided by the AudioData's .volumeL&R members
  751.     sample *= tr.volumeMaster;
  752.     //mix sample to dst while applying pan WHILE interpolating between old and new
  753.     dst[i] += applyPan(sample, LERP2(tr.pan_old, tr.pan_new, t) );
  754.     //update position by speed, while interpolating between speed's old and new state
  755.     tr.position += LERP2(tr.speed_old, tr.speed_new, t);
  756.  
  757.     //change old and new volume by volumeDelta
  758.      //(deltas are referenced directly with track instead of tr)
  759.     smp_f32s currentVolumeDelta = track.volumeDelta;
  760.     tr.volume_old += currentVolumeDelta;
  761.     tr.volume_new += currentVolumeDelta;
  762.  
  763.     //change old and new speed by speedDelta
  764.     f64 currentSpeedDelta = track.speedDelta;
  765.     tr.speed_old += currentSpeedDelta;
  766.     tr.speed_new += currentSpeedDelta;
  767.     //make sure the volume is always between 0.0f and 1.0f
  768.     tr.volume_old.l = CLAMP(tr.volume_old.l, 0.0f, 1.0f);
  769.     tr.volume_old.r = CLAMP(tr.volume_old.r, 0.0f, 1.0f);
  770.     tr.volume_new.l = CLAMP(tr.volume_new.l, 0.0f, 1.0f);
  771.     tr.volume_new.r = CLAMP(tr.volume_new.r, 0.0f, 1.0f);
  772.  
  773.     //raise interpolation t value
  774.     t += t_increment;
  775.  
  776.     //start rapid fade out if clip's new speed <= 0
  777.     if(LERP2(tr.speed_old, tr.speed_new, t) <= 0.0){
  778.       tr.speed_old = tr.speed_new = 0.0;
  779.       //volumeDelta is sorta volatile, so that might need to be accounted for...
  780.       track.volumeDelta = speed0VDelta;
  781.     }
  782.  
  783.   }
  784.  
  785.  
  786.  
  787.   //set relevant old values to the new ones
  788.   track.position   = tr.position;
  789.   track.speed_old  = tr.speed_new; //both old *and* new speeds
  790.   track.speed_new  = tr.speed_new;  //must be set to their new values
  791.   track.pan_old    = tr.pan_new;
  792.   //track.pan_new  = tr.pan_new; //no need to set this, as no delta is applied to pan
  793.   track.volume_old = tr.volume_new; //both old *and* new volumes
  794.   track.volume_new = tr.volume_new;  //must be set to their new values
  795.   track.loops      = tr.loops;
  796.   track.stopping   = tr.stopping;
  797.  
  798.   //check if track needs to be marked as complete
  799.   if(tr.volume_new.l <= 0  &&  tr.volume_new.r <= 0) track.stopping = true;
  800.   if(track.stopping) track.audio = nullptr;
  801. }
  802.  
  803.  
  804.  
  805.  
  806. }; /* namespace kit */
  807.  
  808. #endif /* _KIT_SRC_KIT_SOUNDENGINE_CALLBACKSFX_HPP */
  809. /******************************************************************************/
  810. /******************************************************************************/
  811. //"kit_xmp_sfx\src\kit_xmp_sfx\_kit_shared.hpp":
  812. #ifndef _KIT_SRC__KIT_SHARED_HPP
  813. #define _KIT_SRC__KIT_SHARED_HPP
  814.  
  815. #include <math.h>
  816.  
  817. #define LIBXMP_STATIC
  818. #include <libxmp-lite/xmp.h>
  819. #include <Windows.h>
  820.  
  821. #include <kit/audio.hpp>
  822. #include <kit/xmp_sfx.hpp>
  823.  
  824.  
  825.  
  826. #ifdef _DEBUG
  827. #include <stdio.h>
  828. #define _printf(_fmt,...) printf(_fmt,__VA_ARGS__)
  829. #else
  830. #define _printf(_fmt,...)
  831. #endif
  832.  
  833. #define loghere _printf("line %4i: (%s)\n",__LINE__,__FILE__);
  834.  
  835.  
  836. #define KIT_LOCK_SPINCOUNT (2048)
  837.  
  838.  
  839. //class type ID macros
  840. #define KIT_OPAQUE_PRESENT (0x80000000)
  841. #define KIT_IS_OPAQUE_PRESENT(_type) ( ((_type)&KIT_OPAQUE_PRESENT) != 0 )
  842.  
  843. //classes from kit_w32
  844. #define KIT_CLASSTYPE_NULL              (0x0000                     )
  845. #define KIT_CLASSTYPE_MUTEXSIMPLE       (0x0001 | KIT_OPAQUE_PRESENT)
  846. #define KIT_CLASSTYPE_WINDOW            (0x0002 | KIT_OPAQUE_PRESENT)
  847. #define KIT_CLASSTYPE_BITMAP            (0x0003 | KIT_OPAQUE_PRESENT)
  848. #define KIT_CLASSTYPE_FILEIO_BINARYDATA (0x0004                     )
  849. #define KIT_CLASSTYPE_BITMAPFONT        (0x0005                     )
  850. #define KIT_CLASSTYPE_FSTR              (0x0006                     )
  851. #define KIT_CLASSTYPE_AUDIOSTREAM       (0x0007 | KIT_OPAQUE_PRESENT)
  852. #define KIT_CLASSTYPE_THREAD            (0x0008 | KIT_OPAQUE_PRESENT)
  853.  
  854. //classes from kit_xmp_sfx
  855. #define KIT_CLASSTYPE_AUDIODATA         (0x1001                     )
  856. #define KIT_CLASSTYPE_SOUNDENGINE       (0x1002 | KIT_OPAQUE_PRESENT)
  857.  
  858.  
  859. namespace kit {
  860.  
  861.  
  862.  
  863.  
  864. #define KIT_GET_CLASS_TYPE(_ptr)         ( ((_commonClassValues*)(_ptr))->type         )
  865. #define KIT_GET_CLASS_VALID(_ptr)        ( ((_commonClassValues*)(_ptr))->valid        )
  866. #define KIT_GET_CLASS_CONSTRUCTING(_ptr) ( ((_commonClassValues*)(_ptr))->constructing )
  867. #define KIT_GET_CLASS_DATA(_ptr)         ( ((_commonClassValues*)(_ptr))->data         )
  868. #define KIT_GET_CLASS_OPAQUE(_ptr)       ( ((_commonClassValues*)(_ptr))->opq          )
  869.  
  870. #define KIT_IS_CLASS_TYPE(_ptr,_type)   ( KIT_GET_CLASS_TYPE(_ptr) == (_type) )
  871. #define KIT_IS_CLASS_VALID(_ptr)        ( KIT_GET_CLASS_VALID(_ptr) != 0 )
  872. #define KIT_IS_CLASS_CONSTRUCTING(_ptr) ( KIT_GET_CLASS_CONSTRUCTING(_ptr) != 0 )
  873.  
  874. struct _commonClassValues {
  875.   u32  type;
  876.   bool valid; //'is object fully and successfully constructed?'
  877.   bool constructing; //'is object currently inside constructor?'
  878.   //^^this is useful for if public class functions are called inside the
  879.    //constructor itself, but the valid flag is not set to true yet
  880.   u16  data; //purpose varies by class type; unused by some (or it's split into 2 u8)
  881.   _GenericOpaquePtr opq; //nonexistent if type lacks the KIT_OPAQUE_PRESENT flag
  882. };
  883.  
  884.  
  885.  
  886.  
  887. //in seconds
  888. #define _totalFadeDelay (0.100f)
  889.  
  890. //linearly fade over the course of 10ms
  891. #define _fadeDeltaSeconds (0.010f)
  892.  
  893. //the most common audio clipping ends at 10-11ms after unpausing,
  894.  //but i've seen clipping as far as ~450ms after unpausing
  895. #define _fadeInDelaySeconds (_totalFadeDelay - _fadeDeltaSeconds)
  896.  
  897.  
  898. //lower clip's volume to 0 within 10ms if speed reaches 0
  899. #define _speed0VolDeltaMS (10.0f)
  900.  
  901.  
  902. //SoundEngine's buffer size, in seconds
  903. #define _soundEngineBufferSize (0.025)
  904.  
  905.  
  906.  
  907.  
  908. #define FORMAT_SWITCH(_channels, _format) \
  909.   ( ((_channels)<<16) | (_format) )
  910.  
  911. enum format_switch_enum {
  912.   fmtsw_u8   = FORMAT_SWITCH(1, ASTREAM_FMT_U8 ),
  913.   fmtsw_s8   = FORMAT_SWITCH(1, ASTREAM_FMT_S8 ),
  914.   fmtsw_s16  = FORMAT_SWITCH(1, ASTREAM_FMT_S16),
  915.   fmtsw_s24  = FORMAT_SWITCH(1, ASTREAM_FMT_S24),
  916.   fmtsw_s32  = FORMAT_SWITCH(1, ASTREAM_FMT_S32),
  917.   fmtsw_f32  = FORMAT_SWITCH(1, ASTREAM_FMT_F32),
  918.  
  919.   fmtsw_u8s  = FORMAT_SWITCH(2, ASTREAM_FMT_U8 ),
  920.   fmtsw_s8s  = FORMAT_SWITCH(2, ASTREAM_FMT_S8 ),
  921.   fmtsw_s16s = FORMAT_SWITCH(2, ASTREAM_FMT_S16),
  922.   fmtsw_s24s = FORMAT_SWITCH(2, ASTREAM_FMT_S24),
  923.   fmtsw_s32s = FORMAT_SWITCH(2, ASTREAM_FMT_S32),
  924.   fmtsw_f32s = FORMAT_SWITCH(2, ASTREAM_FMT_F32),
  925. };
  926.  
  927.  
  928.  
  929.  
  930. #define s8_inv  (0.0078125)                         // = 1.0/2^7
  931. #define s16_inv (0.000030517578125)                 // = 1.0/2^15
  932. #define s24_inv (0.00000011920928955078125)         // = 1.0/2^23
  933. #define s32_inv (0.0000000004656612873077392578125) // = 1.0/2^31
  934.  
  935. //converts formats to f32
  936. #define u8_conv( _v)  (  (f32)( (f64)( (s8)((_v)-128) ) * s8_inv  )  )
  937. #define s8_conv( _v)  (  (f32)( (f64)(       _v       ) * s8_inv  )  )
  938. #define s16_conv(_v)  (  (f32)( (f64)(       _v       ) * s16_inv )  )
  939. #define s24_conv(_v)  (  (f32)( (f64)(       _v       ) * s24_inv )  )
  940. #define s32_conv(_v)  (  (f32)( (f64)(       _v       ) * s32_inv )  )
  941.  
  942.  
  943. //the following 5 sample types are only used when loading audio,
  944.  //as they will all be converted to f32 or smp_f32s for use in sfx
  945. struct smp_u8s  { u8  l,r; };
  946. struct smp_s8s  { s8  l,r; };
  947. struct smp_s32s { s32 l,r; };
  948. struct smp_s24 { //bruh
  949.   s32 v : 24;
  950.   s32 _ :  8;
  951. };
  952. struct smp_s24s { //bruh
  953.   s64 l : 24;
  954.   s64 r : 24;
  955.   s64 _ : 16;
  956. };
  957.  
  958.  
  959. //in addition to sfx loading, smp_s16s is also used for interactions with libxmp
  960. struct smp_s16s {
  961.   s16 l,r;
  962.  
  963.   smp_s16s& operator*=(const f32& smp){ l = (s16)(l*smp);  r = (s16)(r*smp);  return *this; }
  964. };
  965.  
  966.  
  967. struct smp_f32s {
  968.   f32 l,r;
  969.  
  970.   smp_f32s(             ) : l(   0.0f), r(   0.0f) {}
  971.   smp_f32s(const f64& _v) : l((f32)_v), r((f32)_v) {}
  972.  
  973.   smp_f32s(const f32& _l, const f32& _r) : l(     _l), r(     _r) {}
  974.   smp_f32s(const f64& _l, const f64& _r) : l((f32)_l), r((f32)_r) {}
  975.  
  976.   smp_f32s(const     u8  & smp){ l = r = u8_conv( smp  ); }
  977.   smp_f32s(const     s8  & smp){ l = r = s8_conv( smp  ); }
  978.   smp_f32s(const     s16 & smp){ l = r = s16_conv(smp  ); }
  979.   smp_f32s(const smp_s24 & smp){ l = r = s24_conv(smp.v); }
  980.   smp_f32s(const     s32 & smp){ l = r = s32_conv(smp  ); }
  981.   smp_f32s(const     f32 & smp){ l = r =          smp   ; }
  982.  
  983.   smp_f32s(const smp_u8s & smp){ l = u8_conv( smp.l);  r = u8_conv( smp.r); }
  984.   smp_f32s(const smp_s8s & smp){ l = s8_conv( smp.l);  r = s8_conv( smp.r); }
  985.   smp_f32s(const smp_s16s& smp){ l = s16_conv(smp.l);  r = s16_conv(smp.r); }
  986.   smp_f32s(const smp_s24s& smp){ l = s24_conv(smp.l);  r = s24_conv(smp.r); }
  987.   smp_f32s(const smp_s32s& smp){ l = s32_conv(smp.l);  r = s32_conv(smp.r); }
  988.   smp_f32s(const smp_f32s& smp){ l =          smp.l ;  r =          smp.r ; }
  989.  
  990.  
  991.   smp_f32s& operator+=(const     u8 & smp){ l += u8_conv( smp  );  r += u8_conv( smp  );  return *this; }
  992.   smp_f32s& operator+=(const     s8 & smp){ l += s8_conv( smp  );  r += s8_conv( smp  );  return *this; }
  993.   smp_f32s& operator+=(const     s16& smp){ l += s16_conv(smp  );  r += s16_conv(smp  );  return *this; }
  994.   smp_f32s& operator+=(const smp_s24& smp){ l += s24_conv(smp.v);  r += s24_conv(smp.v);  return *this; }
  995.   smp_f32s& operator+=(const     s32& smp){ l += s32_conv(smp  );  r += s32_conv(smp  );  return *this; }
  996.  
  997.   smp_f32s& operator+=(const     f32& smp){ l += smp;              r += smp;              return *this; }
  998.   smp_f32s& operator-=(const     f32& smp){ l -= smp;              r -= smp;              return *this; }
  999.   smp_f32s& operator*=(const     f32& smp){ l *= smp;              r *= smp;              return *this; }
  1000.  
  1001.   smp_f32s& operator+=(const smp_u8s & smp){ l += u8_conv( smp.l);  r += u8_conv( smp.r);  return *this; }
  1002.   smp_f32s& operator+=(const smp_s8s & smp){ l += s8_conv( smp.l);  r += s8_conv( smp.r);  return *this; }
  1003.   smp_f32s& operator+=(const smp_s16s& smp){ l += s16_conv(smp.l);  r += s16_conv(smp.r);  return *this; }
  1004.   smp_f32s& operator+=(const smp_s24s& smp){ l += s24_conv(smp.l);  r += s24_conv(smp.r);  return *this; }
  1005.   smp_f32s& operator+=(const smp_s32s& smp){ l += s32_conv(smp.l);  r += s32_conv(smp.r);  return *this; }
  1006.  
  1007.   smp_f32s& operator+=(const smp_f32s& smp){ l += smp.l;  r += smp.r;  return *this; }
  1008.   smp_f32s& operator-=(const smp_f32s& smp){ l -= smp.l;  r -= smp.r;  return *this; }
  1009.   smp_f32s& operator*=(const smp_f32s& smp){ l *= smp.l;  r *= smp.r;  return *this; }
  1010.  
  1011.  
  1012.   bool operator!=(f32 v) const { return (l != v) || (r != v); }
  1013. };
  1014.  
  1015.  
  1016. union smp_ptr {
  1017.   void*     _data;
  1018.  
  1019.   u8*       _u8;
  1020.   s8*       _s8;
  1021.   s16*      _s16;
  1022.   smp_s24*  _s24;
  1023.   s32*      _s32;
  1024.   f32*      _f32;
  1025.  
  1026.   smp_u8s*  _u8s;
  1027.   smp_s8s*  _s8s;
  1028.   smp_s16s* _s16s;
  1029.   smp_s24s* _s24s;
  1030.   smp_s32s* _s32s;
  1031.   smp_f32s* _f32s;
  1032.  
  1033.   smp_ptr() : _data(nullptr) {}
  1034.   smp_ptr(void* data) : _data(data) {}
  1035. };
  1036.  
  1037.  
  1038. //these two are used inside the xmp thread function
  1039. #define to_s16(_smpIn) ( (s16)(_smpIn*KIT_S16_MAX) )
  1040. static inline smp_s16s to_s16s(const smp_f32s& smpIn){
  1041.   smp_s16s smpOut;
  1042.   smpOut.l = to_s16(smpIn.l);
  1043.   smpOut.r = to_s16(smpIn.r);
  1044.   return smpOut;
  1045. }
  1046.  
  1047.  
  1048.  
  1049.  
  1050. struct _SoundEngineTrack {
  1051.   f64                timestamp; //stream time at time of AudioData being queued
  1052.  
  1053.   f64                 position;
  1054.   f64                speed_old, speed_new;
  1055.   f64               speedDelta;
  1056.   //speedDelta ^^ (and volumeDelta VV) should affect X_new and not X_old,
  1057.    //as to not negatively affect old-to-new interpolation
  1058.   //(also, make sure to lock mutex when editing X_new stuff)
  1059.  
  1060.   f32                  pan_old, pan_new;
  1061.   smp_f32s          volume_old, volume_new;
  1062.   smp_f32s         volumeDelta;
  1063.   smp_f32s        volumeMaster;
  1064.  
  1065.   u16                    loops;
  1066.   bool                stopping;
  1067.  
  1068.   char             _padding[5];
  1069.  
  1070.   const AudioDataHeader* audio;
  1071. };
  1072.  
  1073.  
  1074.  
  1075. struct _SoundEngineOpaque {
  1076.   CRITICAL_SECTION     lock; //the type of mutex object used for synchronization
  1077.   AudioStream*       stream; //pointer to the internal AudioStream class
  1078.   _SoundEngineTrack* tracks; //pointer to array of sound effect tracks
  1079.   xmp_context        xmpCtx; //used in calls to libxmp functions
  1080.   smp_ptr         xmpBuffer; //for s16 and smp_s16s
  1081.  
  1082.   //the new and old values are interpolated between eachother
  1083.    //every invocation of the callback (lock mutex before modifying these!)
  1084.   smp_f32s volumeStream_old, volumeStream_new;
  1085.   f32      panSfx_old,       panSfx_new;
  1086.   smp_f32s volumeSfx_old,    volumeSfx_new;
  1087.   f32      panXmp_old,       panXmp_new;
  1088.   smp_f32s volumeXmp_old,    volumeXmp_new;
  1089.  
  1090.   //fadeDelta = 1.0f / (streamSampleRate*_fadeDeltaSeconds)
  1091.   f32 fadeDelta; //(used for both music and the actual stream)
  1092.   u32 fadeInDelayStream;
  1093.   f32 fadeVolumeStream;
  1094.   f32 fadeVolumeXmp;
  1095.   bool fadeOutStream;
  1096.   bool fadeOutXmp;
  1097.  
  1098.   bool xmpUseNearest; //use nearest-neighbor interpolation
  1099.   bool xmpCheckLoop;  //stop looping when loop counter reaches specified value
  1100.   bool xmpNoFilter;   //disable low-pass filter (this has yet to be implemented)
  1101.   bool xmpModuleLoaded;
  1102.   bool xmpPlaying;
  1103.   bool streamIsMono;
  1104.   bool streamPlaying;
  1105.  
  1106.   char _padding8[3];
  1107.  
  1108.   f64 streamSampleRate;
  1109.   u32 streamSampleFrames;
  1110.  
  1111.   s32 tracks_len;
  1112. };
  1113.  
  1114.  
  1115.  
  1116.  
  1117. static inline bool isFormatValid(u16 format){
  1118.   switch(format){
  1119.     case ASTREAM_FMT_U8 :
  1120.     case ASTREAM_FMT_S8 :
  1121.     case ASTREAM_FMT_S16:
  1122.     case ASTREAM_FMT_S24:
  1123.     case ASTREAM_FMT_S32:
  1124.     case ASTREAM_FMT_F32: return true;
  1125.     default             : return false;
  1126.   }
  1127. }
  1128.  
  1129.  
  1130.  
  1131.  
  1132. #ifndef LERP2
  1133. #define LERP2(_v0,_v1, _t) ( (_v0) + (_t)*((_v1)-(_v0)) )
  1134. #endif
  1135.  
  1136.  
  1137. static inline smp_f32s interpolateF32S(const smp_f32s& smpA,
  1138.                                        const smp_f32s& smpB,
  1139.                                        f32 t_value)
  1140. {
  1141.   return smp_f32s(
  1142.           LERP2(smpA.l, smpB.l, t_value),
  1143.           LERP2(smpA.r, smpB.r, t_value)
  1144.          );
  1145. }
  1146.  
  1147.  
  1148. static inline f32 linearSampleMono(const f32* src, f64 position,
  1149.                                    u64 loopEnd = KIT_U64_MAX)
  1150. {
  1151.   u64 intPosition = (u64)position;
  1152.   f32 modPosition = (f32)(position-intPosition); //the position's fraction
  1153.  
  1154.   f32 smpA = src[   intPosition];
  1155.   f32 smpB = src[(++intPosition)%loopEnd];
  1156.  
  1157.   return LERP2(smpA, smpB, modPosition);
  1158. }
  1159.  
  1160.  
  1161. static inline smp_f32s linearSampleStereo(const smp_f32s* src, f64 position,
  1162.                                           u64 loopEnd = KIT_U64_MAX)
  1163. {
  1164.   u64 intPosition = (u64)position;
  1165.   f32 modPosition = (f32)(position-intPosition); //the position's fraction
  1166.  
  1167.   smp_f32s smpA = src[   intPosition];
  1168.   smp_f32s smpB = src[(++intPosition)%loopEnd];
  1169.  
  1170.   return interpolateF32S(smpA, smpB, modPosition);
  1171. }
  1172.  
  1173.  
  1174.  
  1175. #define convertPan(_pan) CLAMP(_pan, -1.0f, 1.0f)
  1176. //#define convertPan(_pan) CLAMP( (_pan+1.0f)*0.5f, 0.0f, 1.0f )
  1177.  
  1178. #define sqrt2_inv ( 0.70710678f )
  1179.  
  1180. //sort of a work-in-progress
  1181. static inline smp_f32s& applyPan(smp_f32s& sample, f32 pan){
  1182.  
  1183.   if(pan < 0){
  1184.     sample.l += sample.r*(-pan);
  1185.     sample.r *= 1.0f+pan;
  1186.  
  1187.   } else if(pan > 0){
  1188.     sample.r += sample.l*pan;
  1189.     sample.l *= 1.0f-pan;
  1190.  
  1191.   }
  1192.  
  1193.   return sample;
  1194. }
  1195.  
  1196.  
  1197.  
  1198.  
  1199. }; /* namespace kit */
  1200.  
  1201. #endif /* _KIT_SRC__KIT_SHARED_HPP */
  1202.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement