Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "_sfx.hpp"
- static inline int numBitsU32(Uint32 n){
- int active = 0;
- while(n != 0){
- if(n&1) ++active;
- n >>= 1;
- }
- return active;
- }
- extern void _sfx_callback(void* userdata, Uint8* _stream, int size);
- sfx_class::sfx_class(const Uint32 numTracks,
- const int sampleRate,
- const std::string& deviceName,
- const Uint32 bufferLength)
- {
- if(numTracks == 0) throw "numTracks = 0";
- if(numTracks > 1024) throw "numTracks > 1024";
- if(sampleRate < 1000) throw "sampleRate < 1000";
- if(sampleRate > 384000) throw "sampleRate > 384000";
- if(bufferLength < 32) throw "bufferLength < 32";
- if(bufferLength > 65535) throw "bufferLength > 65535";
- if(numBitsU32(bufferLength) != 1) throw "bufferLength is not a power of 2";
- const char* deviceNameRaw = nullptr;
- if(deviceName != "") deviceNameRaw = deviceName.c_str();
- SDL_AudioSpec specWant, specHave;
- specWant.freq = sampleRate;
- specWant.format = AUDIO_F32;
- specWant.channels = 2;
- specWant.samples = bufferLength;
- specWant.callback = _sfx_callback;
- specWant.userdata = this;
- _deviceID = SDL_OpenAudioDevice(deviceNameRaw,0,&specWant,&specHave,0);
- if(_deviceID == 0) throw SDL_GetError();
- _tracks = new std::vector<sfx_track>(numTracks);
- if(_tracks == nullptr){
- SDL_CloseAudioDevice(_deviceID);
- throw "failed to make tracks vector";
- }
- _lock = SDL_CreateMutex();
- if(_lock == nullptr){
- SDL_CloseAudioDevice(_deviceID);
- delete _tracks;
- throw SDL_GetError();
- }
- _volume = 1.0f;
- _pan = 0.0f;
- _fadeDelta = 1.0f / ( ((float)sampleRate)*_fadeDeltaSeconds );
- _fadeVolume = 0.0f;
- _sampleRate = sampleRate;
- _bufferLength = bufferLength;
- _deviceName = SDL_GetAudioDeviceName(_deviceID,0);
- _valid = true; //set valid to true to indicate success
- }
- void sfx_class::pauseDevice(bool pauseState){
- if(!_valid) throw "invalid sfx_class instance";
- if(_closing) return; //return early if closing
- lock(true);
- //this should occur when _sfx_callback's pause thread fails,
- //or if the callback itself does
- if(_fadeInDelay == 0xffffffff){ //if equal to -1
- SDL_PauseAudioDevice(_deviceID,1);
- _playing = false;
- _fadeInDelay = 0;
- }
- _fadeOut = pauseState;
- if(!pauseState && !_playing){
- //the purpose of fadeInDelay is to mute for some samples
- //to give the sdl audio device some time to warm up,
- //otherwise artifacts start to occur (for me, anyway)
- _fadeInDelay = _sampleRate*_fadeInDelaySeconds;
- if(!_timeStampStart) _timeStampStart = SDL_GetTicks64();
- if(!_timeStampEnd ) _timeStampEnd = SDL_GetTicks64();
- SDL_PauseAudioDevice(_deviceID,0);
- _playing = true;
- }
- lock(false);
- }
- void sfx_class::pauseDeviceAndWait(bool pauseState){
- Uint64 startTimeMS = SDL_GetTicks64();
- bool wasPaused = !_playing;
- pauseDevice(pauseState); //should throw if invalid
- if(_closing) return;
- if(pauseState){
- // *4 seems to completely stop clipping (but not *1 for some reason)
- Uint32 fadeOutMS = _fadeDeltaSeconds*1000 * 4;
- do { SDL_Delay(fadeOutMS); } while(_playing);
- } else if(wasPaused){ //delay only if previously paused
- Uint32 totalDelayMS = _totalFadeDelay*1000;
- Uint32 timeDifferenceMS = SDL_GetTicks64()-startTimeMS;
- SDL_Delay( std::max(totalDelayMS-timeDifferenceMS,0u) );
- }
- }
- int sfx_class::play(const sfx_pcm* pcm){
- if(!_valid) throw "invalid sfx_class instance";
- Uint64 timeStamp = SDL_GetTicks64();
- int queuedTrackID = -1;
- std::vector<sfx_track>& tracksRef = *_tracks;
- size_t numTracks = tracksRef.size();
- for(size_t i=0; i<numTracks; ++i){
- sfx_track& track = tracksRef.at(i);
- if(track.pcm == nullptr){
- track.timeStamp = timeStamp;
- track.speed = 1.0;
- track.speedDelta = 0.0;
- track.volume = 1.0f;
- track.volumeDelta = 0.0f;
- track.pan = 0.0f;
- track.loops = pcm->loopCount;
- track.stopOnMute = true;
- track.stopping = false;
- track.pcm = (sfx_pcm*)pcm;
- queuedTrackID = i; break;
- }
- }
- return queuedTrackID;
- }
Add Comment
Please, Sign In to add comment