Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma once
- #include <SDL2/SDL.h>
- #include <algorithm>
- #include <string>
- #include <vector>
- #define DEFAULT_SAMPLERATE (44100)
- #define DEFAULT_BITRATE (DEFAULT_SAMPLERATE*sizeof(sfx_f32s)*8)
- #define DEFAULT_BUFFERLEN (2048)
- /*******/
- /* sfx */
- /*******/
- extern const float _sfx_i8inv; // = 1/2^7
- extern const float _sfx_i16inv; // = 1/2^15
- //for converting i8/i16 to f32
- #define _sfx_u8conv(_v) ( (float)((Sint8)((_v)-128)) * _sfx_i8inv )
- #define _sfx_i16conv(_v) ( (float)( (_v) ) * _sfx_i16inv )
- struct sfx_u8s {
- Uint8 l,r;
- sfx_u8s() : l(0), r(0) {}
- sfx_u8s(const Uint8 _l, const Uint8 _r) : l(_l), r(_r) {}
- };
- struct sfx_i16s {
- Sint16 l,r;
- sfx_i16s() : l(0), r(0) {}
- sfx_i16s(const Sint16 _l, const Sint16 _r) : l(_l), r(_r) {}
- };
- struct sfx_f32s {
- float l,r;
- sfx_f32s() : l(0), r(0) {}
- sfx_f32s(const float& _l, const float& _r) : l(_l), r(_r) {}
- sfx_f32s(const int& _v) : l(_v), r(_v) {}
- sfx_f32s(const double& _v) : l(_v), r(_v) {}
- sfx_f32s(const Uint8& smp){ l = _sfx_u8conv( smp); r = _sfx_u8conv( smp); }
- sfx_f32s(const Sint16& smp){ l = _sfx_i16conv(smp); r = _sfx_i16conv(smp); }
- sfx_f32s(const float& smp){ l = smp; r = smp; }
- sfx_f32s(const sfx_u8s& smp){ l = _sfx_u8conv( smp.l); r = _sfx_u8conv( smp.r); }
- sfx_f32s(const sfx_i16s& smp){ l = _sfx_i16conv(smp.l); r = _sfx_i16conv(smp.r); }
- sfx_f32s(const sfx_f32s& smp){ l = smp.l; r = smp.r; }
- sfx_f32s& operator+=(const Uint8& smp){ l += _sfx_u8conv( smp); r += _sfx_u8conv( smp); return *this; }
- sfx_f32s& operator+=(const Sint16& smp){ l += _sfx_i16conv(smp); r += _sfx_i16conv(smp); return *this; }
- sfx_f32s& operator+=(const float& smp){ l += smp; r += smp; return *this; }
- sfx_f32s& operator+=(const sfx_u8s& smp){ l += _sfx_u8conv( smp.l); r += _sfx_u8conv( smp.r); return *this; }
- sfx_f32s& operator+=(const sfx_i16s& smp){ l += _sfx_i16conv(smp.l); r += _sfx_i16conv(smp.r); return *this; }
- sfx_f32s& operator+=(const sfx_f32s& smp){ l += smp.l; r += smp.r; return *this; }
- sfx_f32s& operator-=(const sfx_f32s& smp){ l -= smp.l; r -= smp.r; return *this; }
- sfx_f32s& operator*=(const sfx_f32s& smp){ l *= smp.l; r *= smp.r; return *this; }
- sfx_f32s& clip(){ l = std::clamp(l, -1.0f,1.0f); r = std::clamp(r, -1.0f,1.0f); return *this; }
- sfx_f32s& unit(){ l = std::clamp(l, 0.0f,1.0f); r = std::clamp(r, 0.0f,1.0f); return *this; }
- };
- /*************/
- /* sfx_class */
- /*************/
- typedef void (SDLCALL * sfx_auxCallback) (void* userdata, void* _stream, int size);
- struct sfx_pcm; //forward declaration
- struct sfx_track { //64B
- sfx_pcm* pcm = nullptr; //audio data; track considered available/inactive if nullptr
- Uint64 timeStamp; //result of SDL_GetTicks64() called at time of queueing an audio clip
- double position; //sample position, including fraction
- double speed; //what amount to increase position by every sample
- double speedDelta; //what number to apply to speed every sample
- sfx_f32s volume; //left and right channel volumes; 0.0f -> 1.0f
- sfx_f32s volumeDelta; //determines the rate at which volume changes each sample
- float pan; //the current pan of the track; -1.0f -> 1.0f (should be applied AFTER volume)
- Uint16 loops; //number of times to loop before deactivating clip (-1 for endless loop)
- bool stopOnMute = true; //'deactivate track when volume or speed reaches 0?'
- bool stopping = false; //used inside _sfx_mixTrack
- };
- class sfx_class { //???B
- bool _valid = false;
- bool _closing = false;
- bool _fadeOut = false;
- bool _playing = false;
- SDL_AudioDeviceID _deviceID = 0;
- Uint64 _timeStampStart = 0;
- Uint64 _timeStampEnd = 0;
- std::vector<sfx_track>* _tracks = nullptr;
- SDL_mutex* _lock = nullptr;
- sfx_f32s _volume = 1.0f;
- float _pan = 1.0f;
- Uint32 _fadeInDelay = 0;
- float _fadeDelta = 0;
- float _fadeVolume = 0;
- Uint32 _sampleRate = DEFAULT_SAMPLERATE;
- Uint32 _bufferLength = DEFAULT_BUFFERLEN;
- std::string _deviceName;
- sfx_auxCallback _auxCallback = nullptr;
- void* _auxUserdata = nullptr;
- std::vector<char>* _auxStream = nullptr;
- SDL_AudioFormat _auxFormat = AUDIO_F32;
- Uint16 _auxChannels = 2;
- public:
- //should be used solely by _sfx_callback related stuff
- //(these are hardly public functions; do not touch these, seriously)
- sfx_f32s& _getVolume(){ return _volume; }
- float& _getPan(){ return _pan; }
- Uint32& _getFadeInDelay(){ return _fadeInDelay; }
- float& _getFadeDelta(){ return _fadeDelta; }
- float& _getFadeVolume(){ return _fadeVolume; }
- std::vector<sfx_track>& _getTracks(){ return *_tracks; }
- std::vector<sfx_track>* _getTracksPtr(){ return _tracks; }
- void* _getAuxUserdata(){ return _auxUserdata; }
- std::vector<char>* _getAuxStream(){ return _auxStream; }
- void _setPlaying(bool playState){ _playing = playState; }
- void _setTimeStampStart(){ _timeStampStart = SDL_GetTicks64(); }
- void _setTimeStampEnd(){ _timeStampEnd = SDL_GetTicks64(); }
- //you can use these ones, though
- bool isValid() const { return _valid; }
- bool isClosing() const { return _closing; }
- bool isFadingOut() const { return _fadeOut; }
- bool isPlaying() const { return _playing; }
- SDL_AudioDeviceID getDeviceID() const { return _deviceID; }
- Uint64 getTimeStampStart() const { return _timeStampStart; }
- Uint64 getTimeStampEnd() const { return _timeStampEnd; }
- size_t getNumTracks() const { return _tracks->size(); }
- sfx_f32s getVolume() const { return _volume; }
- sfx_f32s getPan() const { return _pan; }
- Uint32 getSampleRate() const { return _sampleRate; }
- Uint32 getBufferLength() const { return _bufferLength; }
- std::string& getDeviceName(){ return _deviceName; }
- sfx_auxCallback getAuxCallback(){ return _auxCallback; }
- SDL_AudioFormat getAuxFormat(){ return _auxFormat; }
- Uint16 getAuxChannels(){ return _auxChannels; }
- sfx_class(const Uint32 numTracks,
- const int sampleRate = DEFAULT_SAMPLERATE,
- const std::string& deviceName = "",
- const Uint32 bufferLength = DEFAULT_BUFFERLEN);
- ~sfx_class();
- void setVolume(sfx_f32s volume);
- void setPan(float pan);
- void lock(bool lockState);
- void lockDevice(bool lockState);
- void pauseDevice(bool pauseState);
- void pauseDeviceAndWait(bool pauseState);
- void waitForTracks(Uint64 timeoutMS = 8000);
- void waitForTrack(int track, Uint64 timeoutMS = 8000);
- int play(const sfx_pcm* pcm,
- sfx_f32s volume = 1.0f,
- double speed = 1.0,
- float pan = 0.0f);
- void stop(int track);
- void stopAll();
- void stopAllForced(); //marks tracks as finished, rather than fading out over 10ms
- Uint32 getNumActiveTracks();
- bool isTrackPlaying(int track);
- sfx_track* getTrackPtr(int track);
- void setTrackVolumeDelta(int track, sfx_f32s volumeDeltaSeconds);
- void setTrackSpeedDelta(int track, double speedDeltaSeconds);
- void setAux(sfx_auxCallback callback, void* userdata = nullptr,
- SDL_AudioFormat format = AUDIO_F32, Uint16 channels = 2);
- };
- /***********/
- /* sfx_pcm */
- /***********/
- #define SFX_PCM_MAGIC (0x4D43506B)
- struct sfx_pcm { //an altered (but backwards compatible) version of kit_acodecPCM; 72B
- Uint32 magic = 0; // (0x00) = 0x4D43506B = "kPCM" (no terminator)
- SDL_AudioFormat format = AUDIO_F32; // (0x04) The data format of the stream
- Uint16 headerSize = sizeof(sfx_pcm); // (0x06) = sizeof(sfx_pcm)
- Uint64 dataSize = 0; // (0x08) The size of the PCM buffer, in bytes
- Uint64 loopStart = 0; // (0x10) Which sample to loop back to
- Uint64 loopEnd = 0; // (0x18) Which sample to restart the loop on
- Uint64 numSamples = 0; // (0x20) # of sample frames in stream
- Uint32 sampleRate = DEFAULT_SAMPLERATE; // (0x28) The stream's sample rate, in Hz
- Uint32 bitRate = DEFAULT_BITRATE; // (0x2C) The audio's bit rate (per second)
- Uint16 loopCount = 0; // (0x30) # of times to loop audio (0 = no loop, -1 = inf loop)
- Uint16 channels = 2; // (0x32) # of interlaced channels in the stream
- Uint8 bitRemainder = 0; // (0x34) = bitsPerSample%8
- Uint8 userflags = 0; // (0x35) User-defined (is just padding otherwise)
- Uint16 mode = 0; // (0x36) 0 = normal pcm
- std::vector<sfx_f32s>* samples = nullptr; // (0x38) Sample data (appears as nullptr in file)
- sfx_class* sfx = nullptr; // (0x40) Bound sfx class (appears as nullptr in file)
- // Samples will be converted to f32s at deviceSampleRate Hz
- sfx_pcm(const std::string& filePath, const sfx_class* sfx_ptr = nullptr);
- ~sfx_pcm(){
- magic = 0; //a magic of 0 indicates an invalid pcm struct
- delete samples;
- samples = nullptr; //just in case
- }
- void print(const size_t samplesToPrint = 0);
- void setSfx(sfx_class* sfx_ptr){ sfx = sfx_ptr; }
- int play(sfx_f32s volume = 1.0f, double speed = 1.0, float pan = 0.0f){
- if(sfx != nullptr) return sfx->play(this, volume, speed, pan);
- else throw "no sfx_class instance currently bound";
- }
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement