Advertisement
Kitomas

sfx.hpp as of 2023-12-15

Dec 15th, 2023
642
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.63 KB | None | 0 0
  1. #pragma once
  2.  
  3. #include <SDL2/SDL.h>
  4.  
  5. #include <algorithm>
  6. #include <string>
  7. #include <vector>
  8.  
  9.  
  10. #define DEFAULT_SAMPLERATE (44100)
  11. #define DEFAULT_BITRATE    (DEFAULT_SAMPLERATE*sizeof(sfx_f32s)*8)
  12. #define DEFAULT_BUFFERLEN (2048)
  13.  
  14.  
  15.  
  16.  
  17. /*******/
  18. /* sfx */
  19. /*******/
  20.  
  21. extern const float _sfx_i8inv;  // = 1/2^7
  22. extern const float _sfx_i16inv; // = 1/2^15
  23.  
  24. //for converting i8/i16 to f32
  25. #define _sfx_u8conv(_v)  ( (float)((Sint8)((_v)-128)) * _sfx_i8inv  )
  26. #define _sfx_i16conv(_v) ( (float)(        (_v)     ) * _sfx_i16inv )
  27.  
  28.  
  29.  
  30. struct sfx_u8s  {
  31.   Uint8  l,r;
  32.   sfx_u8s() : l(0), r(0) {}
  33.   sfx_u8s(const Uint8 _l, const Uint8 _r) : l(_l), r(_r) {}
  34. };
  35.  
  36. struct sfx_i16s {
  37.   Sint16 l,r;
  38.   sfx_i16s() : l(0), r(0) {}
  39.   sfx_i16s(const Sint16 _l, const Sint16 _r) : l(_l), r(_r) {}
  40. };
  41.  
  42. struct sfx_f32s {
  43.   float l,r;
  44.   sfx_f32s() : l(0), r(0) {}
  45.   sfx_f32s(const float& _l, const float& _r) : l(_l), r(_r) {}
  46.   sfx_f32s(const int&    _v) : l(_v), r(_v) {}
  47.   sfx_f32s(const double& _v) : l(_v), r(_v) {}
  48.  
  49.   sfx_f32s(const Uint8&  smp){ l = _sfx_u8conv( smp);  r = _sfx_u8conv( smp); }
  50.   sfx_f32s(const Sint16& smp){ l = _sfx_i16conv(smp);  r = _sfx_i16conv(smp); }
  51.   sfx_f32s(const float& smp){ l = smp;  r = smp; }
  52.  
  53.   sfx_f32s(const sfx_u8s&  smp){ l = _sfx_u8conv( smp.l);  r = _sfx_u8conv( smp.r); }
  54.   sfx_f32s(const sfx_i16s& smp){ l = _sfx_i16conv(smp.l);  r = _sfx_i16conv(smp.r); }
  55.   sfx_f32s(const sfx_f32s& smp){ l = smp.l;  r = smp.r; }
  56.  
  57.  
  58.   sfx_f32s& operator+=(const Uint8&  smp){ l += _sfx_u8conv( smp);  r += _sfx_u8conv( smp);  return *this; }
  59.   sfx_f32s& operator+=(const Sint16& smp){ l += _sfx_i16conv(smp);  r += _sfx_i16conv(smp);  return *this; }
  60.   sfx_f32s& operator+=(const float&  smp){ l += smp;                r += smp;                return *this; }
  61.  
  62.   sfx_f32s& operator+=(const sfx_u8s&  smp){ l += _sfx_u8conv( smp.l);  r += _sfx_u8conv( smp.r);  return *this; }
  63.   sfx_f32s& operator+=(const sfx_i16s& smp){ l += _sfx_i16conv(smp.l);  r += _sfx_i16conv(smp.r);  return *this; }
  64.  
  65.   sfx_f32s& operator+=(const sfx_f32s& smp){ l += smp.l;  r += smp.r;  return *this; }
  66.   sfx_f32s& operator-=(const sfx_f32s& smp){ l -= smp.l;  r -= smp.r;  return *this; }
  67.   sfx_f32s& operator*=(const sfx_f32s& smp){ l *= smp.l;  r *= smp.r;  return *this; }
  68.  
  69.  
  70.   sfx_f32s& clip(){ l = std::clamp(l, -1.0f,1.0f);  r = std::clamp(r, -1.0f,1.0f);  return *this; }
  71.   sfx_f32s& unit(){ l = std::clamp(l,  0.0f,1.0f);  r = std::clamp(r,  0.0f,1.0f);  return *this; }
  72. };
  73.  
  74.  
  75.  
  76.  
  77. /*************/
  78. /* sfx_class */
  79. /*************/
  80.  
  81. typedef void (SDLCALL * sfx_auxCallback) (void* userdata, void* _stream, int size);
  82.  
  83. struct sfx_pcm; //forward declaration
  84.  
  85. struct sfx_track { //64B
  86.   sfx_pcm*         pcm = nullptr; //audio data; track considered available/inactive if nullptr
  87.   Uint64     timeStamp; //result of SDL_GetTicks64() called at time of queueing an audio clip
  88.  
  89.   double      position; //sample position, including fraction
  90.   double         speed; //what amount to increase position by every sample
  91.   double    speedDelta; //what number to apply to speed every sample
  92.  
  93.   sfx_f32s      volume; //left and right channel volumes; 0.0f -> 1.0f
  94.   sfx_f32s volumeDelta; //determines the rate at which volume changes each sample
  95.   float            pan; //the current pan of the track; -1.0f -> 1.0f (should be applied AFTER volume)
  96.  
  97.   Uint16         loops; //number of times to loop before deactivating clip (-1 for endless loop)
  98.   bool      stopOnMute = true; //'deactivate track when volume or speed reaches 0?'
  99.   bool        stopping = false; //used inside _sfx_mixTrack
  100. };
  101.  
  102.  
  103.  
  104. class sfx_class { //???B
  105.   bool                 _valid = false;
  106.   bool               _closing = false;
  107.   bool               _fadeOut = false;
  108.   bool               _playing = false;
  109.   SDL_AudioDeviceID _deviceID = 0;
  110.  
  111.   Uint64 _timeStampStart = 0;
  112.   Uint64   _timeStampEnd = 0;
  113.  
  114.   std::vector<sfx_track>* _tracks = nullptr;
  115.   SDL_mutex*                _lock = nullptr;
  116.  
  117.   sfx_f32s    _volume = 1.0f;
  118.   float          _pan = 1.0f;
  119.  
  120.   Uint32 _fadeInDelay = 0;
  121.   float  _fadeDelta   = 0;
  122.   float  _fadeVolume  = 0;
  123.  
  124.   Uint32      _sampleRate = DEFAULT_SAMPLERATE;
  125.   Uint32    _bufferLength = DEFAULT_BUFFERLEN;
  126.   std::string _deviceName;
  127.  
  128.   sfx_auxCallback    _auxCallback = nullptr;
  129.   void*              _auxUserdata = nullptr;
  130.   std::vector<char>* _auxStream   = nullptr;
  131.   SDL_AudioFormat    _auxFormat   = AUDIO_F32;
  132.   Uint16             _auxChannels = 2;
  133.  
  134.  
  135.  
  136. public:
  137.   //should be used solely by _sfx_callback related stuff
  138.    //(these are hardly public functions; do not touch these, seriously)
  139.   sfx_f32s& _getVolume(){ return _volume; }
  140.   float& _getPan(){ return _pan; }
  141.   Uint32& _getFadeInDelay(){ return _fadeInDelay; }
  142.   float& _getFadeDelta(){ return _fadeDelta; }
  143.   float& _getFadeVolume(){ return _fadeVolume; }
  144.   std::vector<sfx_track>& _getTracks(){ return *_tracks; }
  145.   std::vector<sfx_track>* _getTracksPtr(){ return _tracks; }
  146.   void* _getAuxUserdata(){ return _auxUserdata; }
  147.   std::vector<char>* _getAuxStream(){ return _auxStream; }
  148.  
  149.   void _setPlaying(bool playState){ _playing = playState; }
  150.   void _setTimeStampStart(){ _timeStampStart = SDL_GetTicks64(); }
  151.   void _setTimeStampEnd(){ _timeStampEnd = SDL_GetTicks64(); }
  152.  
  153.  
  154.   //you can use these ones, though
  155.   bool isValid() const { return _valid; }
  156.   bool isClosing() const { return _closing; }
  157.   bool isFadingOut() const { return _fadeOut; }
  158.   bool isPlaying() const { return _playing; }
  159.   SDL_AudioDeviceID getDeviceID() const { return _deviceID; }
  160.   Uint64 getTimeStampStart() const { return _timeStampStart; }
  161.   Uint64 getTimeStampEnd() const { return _timeStampEnd; }
  162.   size_t getNumTracks() const { return _tracks->size(); }
  163.   sfx_f32s getVolume() const { return _volume; }
  164.   sfx_f32s getPan() const { return _pan; }
  165.   Uint32 getSampleRate() const { return _sampleRate; }
  166.   Uint32 getBufferLength() const { return _bufferLength; }
  167.   std::string& getDeviceName(){ return _deviceName; }
  168.   sfx_auxCallback getAuxCallback(){ return _auxCallback; }
  169.   SDL_AudioFormat getAuxFormat(){ return _auxFormat; }
  170.   Uint16 getAuxChannels(){ return _auxChannels; }
  171.  
  172.  
  173.   sfx_class(const Uint32 numTracks,
  174.             const int sampleRate = DEFAULT_SAMPLERATE,
  175.             const std::string& deviceName = "",
  176.             const Uint32 bufferLength = DEFAULT_BUFFERLEN);
  177.  
  178.   ~sfx_class();
  179.  
  180.   void setVolume(sfx_f32s volume);
  181.   void setPan(float pan);
  182.  
  183.  
  184.   void lock(bool lockState);
  185.   void lockDevice(bool lockState);
  186.  
  187.   void pauseDevice(bool pauseState);
  188.   void pauseDeviceAndWait(bool pauseState);
  189.  
  190.  
  191.   void waitForTracks(Uint64 timeoutMS = 8000);
  192.   void waitForTrack(int track, Uint64 timeoutMS = 8000);
  193.  
  194.   int play(const sfx_pcm* pcm,
  195.            sfx_f32s volume = 1.0f,
  196.            double speed = 1.0,
  197.            float pan = 0.0f);
  198.  
  199.   void stop(int track);
  200.   void stopAll();
  201.   void stopAllForced(); //marks tracks as finished, rather than fading out over 10ms
  202.  
  203.  
  204.   Uint32 getNumActiveTracks();
  205.   bool isTrackPlaying(int track);
  206.   sfx_track* getTrackPtr(int track);
  207.  
  208.   void setTrackVolumeDelta(int track, sfx_f32s volumeDeltaSeconds);
  209.   void setTrackSpeedDelta(int track, double speedDeltaSeconds);
  210.   void setAux(sfx_auxCallback callback, void* userdata = nullptr,
  211.               SDL_AudioFormat format = AUDIO_F32, Uint16 channels = 2);
  212. };
  213.  
  214.  
  215.  
  216.  
  217. /***********/
  218. /* sfx_pcm */
  219. /***********/
  220.  
  221. #define SFX_PCM_MAGIC (0x4D43506B)
  222. struct sfx_pcm { //an altered (but backwards compatible) version of kit_acodecPCM; 72B
  223.   Uint32                   magic = 0;                  // (0x00) = 0x4D43506B = "kPCM" (no terminator)
  224.   SDL_AudioFormat         format = AUDIO_F32;          // (0x04) The data format of the stream
  225.   Uint16              headerSize = sizeof(sfx_pcm);    // (0x06) = sizeof(sfx_pcm)
  226.   Uint64                dataSize = 0;                  // (0x08) The size of the PCM buffer, in bytes
  227.  
  228.   Uint64               loopStart = 0;                  // (0x10) Which sample to loop back to
  229.   Uint64                 loopEnd = 0;                  // (0x18) Which sample to restart the loop on
  230.  
  231.   Uint64              numSamples = 0;                  // (0x20) # of sample frames in stream
  232.   Uint32              sampleRate = DEFAULT_SAMPLERATE; // (0x28) The stream's sample rate, in Hz
  233.   Uint32                 bitRate = DEFAULT_BITRATE;    // (0x2C) The audio's bit rate (per second)
  234.  
  235.   Uint16               loopCount = 0;                  // (0x30) # of times to loop audio (0 = no loop, -1 = inf loop)
  236.   Uint16                channels = 2;                  // (0x32) # of interlaced channels in the stream
  237.   Uint8             bitRemainder = 0;                  // (0x34) = bitsPerSample%8
  238.   Uint8                userflags = 0;                  // (0x35) User-defined (is just padding otherwise)
  239.   Uint16                    mode = 0;                  // (0x36) 0 = normal pcm
  240.   std::vector<sfx_f32s>* samples = nullptr;            // (0x38) Sample data (appears as nullptr in file)
  241.   sfx_class*                 sfx = nullptr;            // (0x40) Bound sfx class (appears as nullptr in file)
  242.  
  243.  
  244.   // Samples will be converted to f32s at deviceSampleRate Hz
  245.   sfx_pcm(const std::string& filePath, const sfx_class* sfx_ptr = nullptr);
  246.  
  247.   ~sfx_pcm(){
  248.     magic = 0; //a magic of 0 indicates an invalid pcm struct
  249.     delete samples;
  250.     samples = nullptr; //just in case
  251.   }
  252.  
  253.  
  254.   void print(const size_t samplesToPrint = 0);
  255.  
  256.  
  257.   void setSfx(sfx_class* sfx_ptr){ sfx = sfx_ptr; }
  258.  
  259.  
  260.   int play(sfx_f32s volume = 1.0f, double speed = 1.0, float pan = 0.0f){
  261.     if(sfx != nullptr) return sfx->play(this, volume, speed, pan);
  262.     else throw "no sfx_class instance currently bound";
  263.   }
  264. };
  265.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement