Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /******************************************************************************/
- /******************************************************************************/
- //"2024-11-21\src\kit_sdl2\kit_func_pollEvent.cpp":
- #include "_kit_common.hpp"
- namespace kit {
- //found in "kit_func_convertEvent.cpp"
- bool _convertEvent(SDL_Event& e_sdl, Event& e_kit);
- bool pollEvent(Event* event_p){
- if(!_gl.init.events)
- THROW_ERROR("pollEvent(): events subsystem is uninitialized");
- SDL_Event e_sdl;
- Event e_kit;
- bool queueWasNotEmpty;
- _get_another_event:
- queueWasNotEmpty = SDL_PollEvent((event_p != nullptr) ? &e_sdl : nullptr);
- if(event_p == nullptr) return queueWasNotEmpty;
- e_kit.common.timestamp = e_sdl.common.timestamp;
- //if queue had an event but its type was not recognized by _convertEvent,
- //poll another event until either a supported one is found, or queue empties
- if(queueWasNotEmpty && !_convertEvent(e_sdl, e_kit))
- goto _get_another_event;
- *event_p = e_kit; //should be impossible for event_p to be null here
- return queueWasNotEmpty;
- }
- const char* getEventText(u32 type){
- #ifdef _DEBUG
- const char* eventName;
- switch(type){
- case KEVENT_NULL : eventName = "KEVENT_NULL"; break;
- case KEVENT_COMMON : eventName = "KEVENT_COMMON"; break;
- case KEVENT_DISPLAY : eventName = "KEVENT_DISPLAY"; break;
- case KEVENT_DISPLAY_ORIENTATION : eventName = "KEVENT_DISPLAY_ORIENTATION"; break;
- case KEVENT_DISPLAY_DISCONNECTED: eventName = "KEVENT_DISPLAY_DISCONNECTED"; break;
- case KEVENT_DISPLAY_CONNECTED : eventName = "KEVENT_DISPLAY_CONNECTED"; break;
- case KEVENT_DISPLAY_MOVED : eventName = "KEVENT_DISPLAY_MOVED"; break;
- case KEVENT_WIN : eventName = "KEVENT_WIN"; break;
- case KEVENT_WIN_EXPOSED : eventName = "KEVENT_WIN_EXPOSED"; break;
- case KEVENT_WIN_HIDDEN : eventName = "KEVENT_WIN_HIDDEN"; break;
- case KEVENT_WIN_SHOWN : eventName = "KEVENT_WIN_SHOWN"; break;
- case KEVENT_WIN_MOVED : eventName = "KEVENT_WIN_MOVED"; break;
- case KEVENT_WIN_RESIZED : eventName = "KEVENT_WIN_RESIZED"; break;
- case KEVENT_WIN_SIZE_CHANGED : eventName = "KEVENT_WIN_SIZE_CHANGED"; break;
- case KEVENT_WIN_RESTORED : eventName = "KEVENT_WIN_RESTORED"; break;
- case KEVENT_WIN_MINIMIZED : eventName = "KEVENT_WIN_MINIMIZED"; break;
- case KEVENT_WIN_MAXIMIZED : eventName = "KEVENT_WIN_MAXIMIZED"; break;
- case KEVENT_WIN_MFOCUS_LOST : eventName = "KEVENT_WIN_MFOCUS_LOST"; break;
- case KEVENT_WIN_MFOCUS_GAINED : eventName = "KEVENT_WIN_MFOCUS_GAINED"; break;
- case KEVENT_WIN_KFOCUS_LOST : eventName = "KEVENT_WIN_KFOCUS_LOST"; break;
- case KEVENT_WIN_KFOCUS_GAINED : eventName = "KEVENT_WIN_KFOCUS_GAINED"; break;
- case KEVENT_WIN_CLOSE : eventName = "KEVENT_WIN_CLOSE"; break;
- case KEVENT_WIN_TAKE_FOCUS : eventName = "KEVENT_WIN_TAKE_FOCUS"; break;
- case KEVENT_WIN_HIT_TEST : eventName = "KEVENT_WIN_HIT_TEST"; break;
- case KEVENT_WIN_ICCPROF_CHANGED : eventName = "KEVENT_WIN_ICCPROF_CHANGED"; break;
- case KEVENT_WIN_DISPLAY_CHANGED : eventName = "KEVENT_WIN_DISPLAY_CHANGED"; break;
- case KEVENT_KEY : eventName = "KEVENT_KEY"; break;
- case KEVENT_KEY_DOWN : eventName = "KEVENT_KEY_DOWN"; break;
- case KEVENT_KEY_UP : eventName = "KEVENT_KEY_UP"; break;
- case KEVENT_KEYMAPCHANGED : eventName = "KEVENT_KEYMAPCHANGED"; break;
- case KEVENT_MOUSE : eventName = "KEVENT_MOUSE"; break;
- case KEVENT_MOUSE_MOVED : eventName = "KEVENT_MOUSE_MOVED"; break;
- case KEVENT_MOUSE_UP : eventName = "KEVENT_MOUSE_UP"; break;
- case KEVENT_MOUSE_DOWN : eventName = "KEVENT_MOUSE_DOWN"; break;
- case KEVENT_MOUSE_WHEEL : eventName = "KEVENT_MOUSE_WHEEL"; break;
- case KEVENT_JOY : eventName = "KEVENT_JOY"; break;
- case KEVENT_JOY_AXIS : eventName = "KEVENT_JOY_AXIS"; break;
- case KEVENT_JOY_TRACKBALL : eventName = "KEVENT_JOY_TRACKBALL"; break;
- case KEVENT_JOY_HAT : eventName = "KEVENT_JOY_HAT"; break;
- case KEVENT_JOY_BUTTON_UP : eventName = "KEVENT_JOY_BUTTON_UP"; break;
- case KEVENT_JOY_BUTTON_DOWN : eventName = "KEVENT_JOY_BUTTON_DOWN"; break;
- case KEVENT_JOY_DEVICE_REMOVED : eventName = "KEVENT_JOY_DEVICE_REMOVED"; break;
- case KEVENT_JOY_DEVICE_ADDED : eventName = "KEVENT_JOY_DEVICE_ADDED"; break;
- case KEVENT_JOY_BATTERY : eventName = "KEVENT_JOY_BATTERY"; break;
- case KEVENT_CTLR : eventName = "KEVENT_CTLR"; break;
- case KEVENT_CTLR_AXIS : eventName = "KEVENT_CTLR_AXIS"; break;
- case KEVENT_CTLR_BUTTON_UP : eventName = "KEVENT_CTLR_BUTTON_UP"; break;
- case KEVENT_CTLR_BUTTON_DOWN : eventName = "KEVENT_CTLR_BUTTON_DOWN"; break;
- case KEVENT_CTLR_DEVICE_REMOVED : eventName = "KEVENT_CTLR_DEVICE_REMOVED"; break;
- case KEVENT_CTLR_DEVICE_ADDED : eventName = "KEVENT_CTLR_DEVICE_ADDED"; break;
- case KEVENT_CTLR_DEVICE_REMAPPED: eventName = "KEVENT_CTLR_DEVICE_REMAPPED"; break;
- case KEVENT_CTLR_TOUCHPAD_UP : eventName = "KEVENT_CTLR_TOUCHPAD_UP"; break;
- case KEVENT_CTLR_TOUCHPAD_DOWN : eventName = "KEVENT_CTLR_TOUCHPAD_DOWN"; break;
- case KEVENT_CTLR_TOUCHPAD_MOVED : eventName = "KEVENT_CTLR_TOUCHPAD_MOVED"; break;
- case KEVENT_CTLR_SENSOR : eventName = "KEVENT_CTLR_SENSOR"; break;
- case KEVENT_ADEV : eventName = "KEVENT_ADEV"; break;
- case KEVENT_ADEV_ADDED : eventName = "KEVENT_ADEV_ADDED"; break;
- case KEVENT_ADEV_REMOVED : eventName = "KEVENT_ADEV_REMOVED"; break;
- case KEVENT_DROP : eventName = "KEVENT_DROP"; break;
- case KEVENT_DROP_FILE : eventName = "KEVENT_DROP_FILE"; break;
- case KEVENT_DROP_TEXT : eventName = "KEVENT_DROP_TEXT"; break;
- case KEVENT_DROP_BEGIN : eventName = "KEVENT_DROP_BEGIN"; break;
- case KEVENT_DROP_COMPLETE : eventName = "KEVENT_DROP_COMPLETE"; break;
- case KEVENT_QUIT : eventName = "KEVENT_QUIT"; break;
- case KEVENT_USER : eventName = "KEVENT_USER"; break;
- case KEVENT_RENDER : eventName = "KEVENT_RENDER"; break;
- case KEVENT_RENDER_TARGETS_RESET: eventName = "KEVENT_RENDER_TARGETS_RESET"; break;
- case KEVENT_RENDER_DEVICE_RESET : eventName = "KEVENT_RENDER_DEVICE_RESET "; break;
- case KEVENT_CLIPBOARDUPDATE : eventName = "KEVENT_CLIPBOARDUPDATE"; break;
- default : eventName = "KEVENT_UNKNOWN";
- }
- return eventName;
- #else
- (void)type; //be gone, unused parameter warning
- return "\"getEventText()\" is only available in the debug build!";
- #endif /* _DEBUG */
- }
- }; /* namespace kit */
- /******************************************************************************/
- /******************************************************************************/
- //"2024-11-21\src\kit_sdl2\kit_lodepng_custom.cpp":
- #include "_kit_common.hpp"
- namespace kit {
- namespace png {
- void* lodepng_malloc(size_t size){
- #ifdef LODEPNG_MAX_ALLOC
- if(size > LODEPNG_MAX_ALLOC) return 0;
- #endif
- return memory::alloc(size);
- }
- // NOTE: when realloc returns NULL, it leaves the original memory untouched
- void* lodepng_realloc(void* ptr, size_t new_size){
- #ifdef LODEPNG_MAX_ALLOC
- if(new_size > LODEPNG_MAX_ALLOC) return 0;
- #endif
- return memory::realloc(&ptr, new_size);
- }
- void lodepng_free(void* ptr){
- memory::free(&ptr);
- }
- //i rewrote lodepng's file io functions to only use SDL functions
- #ifndef LODEPNG_NO_COMPILE_DISK
- #undef LONG_MAX
- #define LONG_MAX (2147483647)
- unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename) {
- *out = (unsigned char*)SDL_LoadFile(filename, outsize);
- if(*out == nullptr){
- return 78;
- } else {
- ++numAllocations; //a subsequent call to memory::free should undo this
- return 0;
- }
- }
- // write given buffer to the file, overwriting the file, it doesn't append to it.
- unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename) {
- SDL_RWops* file = SDL_RWFromFile(filename, "wb");
- if(file == nullptr) return 79;
- size_t bytesWritten = SDL_RWwrite(file, buffer, 1, buffersize);
- SDL_RWclose(file);
- if(bytesWritten < buffersize) return 79;
- else return 0;
- }
- /*
- #undef LONG_MAX
- #define LONG_MAX (2147483647)
- #include <stdio.h>
- // returns negative value on error. This should be pure C compatible, so no fstat.
- static long lodepng_filesize(const char* filename) {
- FILE* file;
- long size;
- file = fopen(filename, "rb");
- if(!file) return -1;
- if(fseek(file, 0, SEEK_END) != 0) {
- fclose(file);
- return -1;
- }
- size = ftell(file);
- // It may give LONG_MAX as directory size, this is invalid for us.
- if(size == LONG_MAX) size = -1;
- fclose(file);
- return size;
- }
- // load file into buffer that already has the correct allocated size. Returns error code.
- static unsigned lodepng_buffer_file(unsigned char* out, size_t size, const char* filename) {
- FILE* file;
- size_t readsize;
- file = fopen(filename, "rb");
- if(!file) return 78;
- readsize = fread(out, 1, size, file);
- fclose(file);
- if(readsize != size) return 78;
- return 0;
- }
- unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename) {
- long size = lodepng_filesize(filename);
- if(size < 0) return 78;
- *outsize = (size_t)size;
- *out = (unsigned char*)lodepng_malloc((size_t)size);
- if(!(*out) && size > 0) return 83; // the above malloc failed
- return lodepng_buffer_file(*out, (size_t)size, filename);
- }
- // write given buffer to the file, overwriting the file, it doesn't append to it.
- unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename) {
- FILE* file;
- file = fopen(filename, "wb" );
- if(!file) return 79;
- fwrite(buffer, 1, buffersize, file);
- fclose(file);
- return 0;
- }
- */
- #endif /* LODEPNG_NO_COMPILE_DISK */
- }; /* namespace png */
- }; /* namespace kit */
- /******************************************************************************/
- /******************************************************************************/
- //"2024-11-21\src\kit_sdl2\kit_memory.cpp":
- #include "_kit_common.hpp"
- //turns something into a void**
- //(this makes some code here easier for me to read)
- #define VPP(_ptr_p) ((void**)(_ptr_p))
- namespace kit {
- size_t numAllocations = 0;
- void* memory::alloc(size_t size){
- void* newHeapMemory = SDL_malloc(size);
- if(newHeapMemory != nullptr) ++numAllocations;
- return newHeapMemory;
- }
- void memory::free(void* ptr_p){
- if(VPP(ptr_p) != nullptr && *VPP(ptr_p) != nullptr){
- --numAllocations;
- SDL_free(*VPP(ptr_p));
- *VPP(ptr_p) = nullptr;
- }
- }
- void* memory::realloc(void* ptr_p, size_t newSize){
- void* ptr_new = nullptr;
- if(VPP(ptr_p) != nullptr){
- ptr_new = SDL_realloc(*VPP(ptr_p), newSize);
- if(ptr_new != nullptr){
- if(*VPP(ptr_p) == nullptr) ++numAllocations;
- *VPP(ptr_p) = ptr_new;
- }
- }
- return ptr_new;
- }
- void* memory::alloc2(size_t size){
- void* newHeapMemory = SDL_malloc(size);
- if(newHeapMemory == nullptr)
- THROW_ERROR("memory::alloc2(): failed to allocate memory");
- ++numAllocations;
- return newHeapMemory;
- }
- void memory::free2(void* ptr_p){
- if( VPP(ptr_p) == nullptr) THROW_ERROR("memory::free2(): ptr_p == nullptr");
- if(*VPP(ptr_p) == nullptr) THROW_ERROR("memory::free2(): *ptr_p == nullptr");
- --numAllocations;
- SDL_free(*VPP(ptr_p));
- *VPP(ptr_p) = nullptr;
- }
- void* memory::realloc2(void* ptr_p, size_t newSize){
- void* ptr_new = nullptr;
- if(VPP(ptr_p) != nullptr){
- ptr_new = SDL_realloc(*VPP(ptr_p), newSize);
- if(ptr_new != nullptr){
- if(*VPP(ptr_p) == nullptr) ++numAllocations; //if memory is new, not realloc'd
- *VPP(ptr_p) = ptr_new;
- }
- } else {
- THROW_ERROR("memory::realloc2(): ptr_p = nullptr");
- }
- if(ptr_new == nullptr)
- THROW_ERROR("memory::realloc2(): failed to reallocate memory");
- return ptr_new;
- }
- size_t memory::getNumAllocations(){
- return numAllocations;
- }
- //currently just a wrapper, but now i can make my own implementation
- //whenever i want, without replacing every call to memset with it
- void* memory::set(void* ptr, s32 value, size_t size){
- if(ptr == nullptr) return nullptr; //now it's safe to pass nullptr :D
- return SDL_memset(ptr, value, size);
- }
- void* memory::set2(void* ptr, s32 value, size_t size){
- if(ptr == nullptr) THROW_ERROR("memory::set2(): ptr = nullptr");
- return SDL_memset(ptr, value, size);
- }
- void* memory::copy(void* destination, const void* source, size_t size){
- //tbd: maybe make it so that memcpy is only called if dst&src aren't nullptr
- return SDL_memcpy(destination, source, size);
- }
- void* memory::copy2(void* destination, const void* source, size_t size){
- if(destination == nullptr) THROW_ERROR("memory::copy2(): destination = nullptr");
- if(source == nullptr) THROW_ERROR("memory::copy2(): source = nullptr");
- return SDL_memcpy(destination, source, size);
- }
- u32 memory::getSystemRAM_MiB(){
- s32 result = SDL_GetSystemRAM();
- if(result < 0) //hopefully this can't happen
- THROW_ERROR("memory::getSystemRAM_MiB(): SDL_GetSystemRAM() < 0");
- return (u32)result;
- }
- u32 memory::getSIMDAlignment(){
- return SDL_SIMDGetAlignment(); //this shouldn't be any more than 64...
- }
- void* memory::allocSIMD(size_t size){
- void* newHeapMemory = SDL_SIMDAlloc(size);
- if(newHeapMemory != nullptr) ++numAllocations;
- return newHeapMemory;
- }
- void memory::freeSIMD(void* ptr_p){
- if(VPP(ptr_p) != nullptr && *VPP(ptr_p) != nullptr){
- --numAllocations;
- SDL_SIMDFree(*VPP(ptr_p));
- *VPP(ptr_p) = nullptr;
- }
- }
- void* memory::reallocSIMD(void* ptr_p, size_t newSize){
- void* ptr_new = nullptr;
- if(VPP(ptr_p) != nullptr){
- ptr_new = SDL_SIMDRealloc(*VPP(ptr_p), newSize);
- if(ptr_new != nullptr){
- if(*VPP(ptr_p) == nullptr) ++numAllocations;
- *VPP(ptr_p) = ptr_new;
- }
- }
- return ptr_new;
- }
- void* memory::allocSIMD2(size_t size){
- void* newHeapMemory = SDL_SIMDAlloc(size);
- if(newHeapMemory == nullptr)
- THROW_ERROR("memory::allocSIMD2(): failed to allocate memory");
- ++numAllocations;
- return newHeapMemory;
- }
- void memory::freeSIMD2(void* ptr_p){
- if( VPP(ptr_p) == nullptr) THROW_ERROR("memory::freeSIMD2(): ptr_p == nullptr");
- if(*VPP(ptr_p) == nullptr) THROW_ERROR("memory::freeSIMD2(): *ptr_p == nullptr");
- --numAllocations;
- SDL_SIMDFree(*VPP(ptr_p));
- *VPP(ptr_p) = nullptr;
- }
- void* memory::reallocSIMD2(void* ptr_p, size_t newSize){
- void* ptr_new = nullptr;
- if(VPP(ptr_p) != nullptr){
- ptr_new = SDL_SIMDRealloc(*VPP(ptr_p), newSize);
- if(ptr_new != nullptr){
- if(*VPP(ptr_p) == nullptr) ++numAllocations; //if memory is new, not realloc'd
- *VPP(ptr_p) = ptr_new;
- }
- } else {
- THROW_ERROR("memory::reallocSIMD2(): ptr_p = nullptr");
- }
- if(ptr_new == nullptr)
- THROW_ERROR("memory::reallocSIMD2(): failed to reallocate memory");
- return ptr_new;
- }
- memory::Wrapper::Wrapper(size_t size){
- ptr = memory::alloc(size);
- if(ptr == nullptr)
- THROW_ERROR("memory::Wrapper::Wrapper() failed to allocate memory");
- }
- memory::WrapperSIMD::WrapperSIMD(size_t size){
- ptr = memory::allocSIMD(size);
- if(ptr == nullptr)
- THROW_ERROR("memory::WrapperSIMD::WrapperSIMD() failed to allocate memory");
- }
- }; /* namespace kit */
- /******************************************************************************/
- /******************************************************************************/
- //"2024-11-21\src\kit_sdl2\kit_Mutex.cpp":
- #include "_kit_common.hpp"
- #define KIT_MUTEX_NULLPTR "internal mutex = nullptr"
- #define KIT_MUTEX_TIMEDOUT "mutex timed out"
- #define MUTEX_PTR ((SDL_mutex*)_mutex_p)
- using namespace kit;
- Mutex::Mutex(){
- if(_valid) return;
- _type = KIT_CLASSTYPE_MUTEX;
- _mutex_p = SDL_CreateMutex(); //can't use MUTEX_PTR here
- if(MUTEX_PTR == nullptr)
- THROW_ERRORF("Mutex::Mutex(): \"%s\"", SDL_GetError());
- ++numAllocations;
- _valid = true;
- _constructing = false;
- }
- Mutex::~Mutex(){
- if(!_valid) return;
- _valid = false;
- //(destroying a locked mutex will result in undefined behavior!)
- if(MUTEX_PTR != nullptr) SDL_DestroyMutex(MUTEX_PTR);
- _mutex_p = nullptr; //can't use MUTEX_PTR here
- --numAllocations;
- }
- void Mutex::lock(bool locked){
- if(MUTEX_PTR == nullptr)
- THROW_ERROR("Mutex::lock(): " KIT_MUTEX_NULLPTR);
- int result;
- if(locked) result = SDL_LockMutex (MUTEX_PTR);
- else result = SDL_UnlockMutex(MUTEX_PTR);
- if(result < 0){
- THROW_ERRORF("Mutex::lock(): \"%s\"", SDL_GetError());
- } else if(result == SDL_MUTEX_TIMEDOUT){
- THROW_ERROR("Mutex::lock(): " KIT_MUTEX_TIMEDOUT);
- }
- }
- bool Mutex::tryLock(){
- if(MUTEX_PTR == nullptr)
- THROW_ERROR("Mutex::tryLock(): " KIT_MUTEX_NULLPTR);
- int result = SDL_TryLockMutex(MUTEX_PTR);
- if(result < 0) THROW_ERRORF("Mutex::tryLock(): \"%s\"", SDL_GetError());
- return result == 0;
- }
- /******************************************************************************/
- /******************************************************************************/
- //"2024-11-21\src\kit_sdl2\kit_SoundEngine.cpp":
- #include "_kit_common.hpp"
- #define SNDENGINE_IS_INVALID (!_valid || _tracks == nullptr)
- #define SNDENGINE_IS_TRACK_OOB (track >= _tracks_len)
- #define SNDENGINE_IS_MUTEX_NULLPTR (_lock == nullptr)
- #define CHECK_INVALID(_func_name) \
- if(SNDENGINE_IS_INVALID){ THROW_ERROR(_func_name ": invalid SoundEngine"); }
- #define CHECK_TRACK_OOB(_func_name) \
- if(SNDENGINE_IS_TRACK_OOB){ THROW_ERROR(_func_name ": track is out of bounds"); }
- #define CHECK_MUTEX(_func_name) \
- if(SNDENGINE_IS_MUTEX_NULLPTR){ THROW_ERROR(_func_name ": _lock = nullptr"); }
- #define CHECK_INVALID_AND_OOB(_func_name) \
- CHECK_INVALID(_func_name) \
- CHECK_TRACK_OOB(_func_name)
- #define CHECK_INVALID_AND_MUTEX(_func_name) \
- CHECK_INVALID(_func_name) \
- CHECK_MUTEX(_func_name)
- #define CHECK_ALL(_func_name) \
- CHECK_INVALID(_func_name) \
- CHECK_TRACK_OOB(_func_name) \
- CHECK_MUTEX(_func_name)
- #define MUTEX_PTR ((SDL_mutex*)_lock)
- #define LOCK_MUTEX \
- bool locked = false; \
- if(MUTEX_PTR != nullptr){ locked = !SDL_LockMutex(MUTEX_PTR); }
- #define UNLOCK_MUTEX { \
- if(locked){ SDL_UnlockMutex(MUTEX_PTR); } }
- namespace kit {
- #define GOTO_SET_ERROR(_text) { errTxt = _text; goto _err; }
- SoundEngine::SoundEngine(u16 numTracks, f32 _sampleRate){
- if(_valid) return;
- _type = KIT_CLASSTYPE_SOUNDENGINE;
- const char* errTxt = "?";
- if(0) _err: THROW_ERRORF("SoundEngine::SoundEngine(): %s", errTxt);
- if(numTracks < 1)
- GOTO_SET_ERROR("numTracks < 1");
- _tracks_len = numTracks;
- size_t _tracks_size = sizeof(_SoundEngineTrack)*_tracks_len;
- _tracks = (_SoundEngineTrack*)memory::alloc(_tracks_size);
- if(_tracks == nullptr)
- GOTO_SET_ERROR("failed to allocate memory for _tracks");
- memory::set(_tracks, 0, _tracks_size);
- _lock = SDL_CreateMutex();
- if(_lock == nullptr){
- memory::free(&_tracks);
- GOTO_SET_ERROR("failed to create mutex object");
- }
- sampleRate = _sampleRate;
- _valid = true;
- _constructing = false;
- }
- SoundEngine::~SoundEngine(){
- if(!_valid) return;
- _valid = false;
- LOCK_MUTEX;
- if(_tracks != nullptr){
- for(u16 t=0; t<_tracks_len; ++t)
- _tracks[t].audio = nullptr; //maybe redundant
- }
- _tracks_len = 0;
- memory::free(&_tracks);
- UNLOCK_MUTEX;
- if(MUTEX_PTR != nullptr) SDL_DestroyMutex(MUTEX_PTR);
- _lock = nullptr;
- }
- bool SoundEngine::isTrackPlaying(u16 track){
- CHECK_INVALID_AND_OOB("SoundEngine::isTrackPlaying()");
- return _tracks[track].audio != nullptr;
- }
- u16 SoundEngine::getActiveTracks(){
- CHECK_INVALID("SoundEngine::getActiveTracks()");
- u16 activeTracks = 0;
- _SoundEngineTrack* tracks = _tracks;
- LOCK_MUTEX;
- for(u16 t=0; t<_tracks_len; ++t){
- if(tracks[t].audio != nullptr) ++activeTracks;
- }
- UNLOCK_MUTEX;
- return activeTracks;
- }
- void SoundEngine::setVolume(f32 volumeL, f32 volumeR,
- u16 track, bool forced)
- {
- CHECK_INVALID_AND_MUTEX("SoundEngine::setVolume()");
- //normally, anything at or below 0 will cause the clip
- //to stop immediately, but this check couldn't hurt
- Stereo_f32 volumeNew(MAX(volumeL, 0.0f), MAX(volumeR, 0.0f));
- if(track != 0xFFFF){
- CHECK_TRACK_OOB("SoundEngine::setVolume()");
- _SoundEngineTrack& _track = _tracks[track];
- if(_track.audio == nullptr) return; //track is empty; exit early
- LOCK_MUTEX;
- if(forced) _track.vol_old = volumeNew;
- _track.vol_new = volumeNew;
- UNLOCK_MUTEX;
- } else {
- _SoundEngineTrack* tracks = _tracks;
- LOCK_MUTEX;
- if(!forced){
- for(u16 t=0; t<_tracks_len; ++t)
- tracks[t].vol_new = volumeNew;
- } else {
- for(u16 t=0; t<_tracks_len; ++t){
- tracks[t].vol_old = volumeNew;
- tracks[t].vol_new = volumeNew;
- }
- }
- UNLOCK_MUTEX;
- }
- }
- //used to modify speed values to account for different sample rates
- //(volume doesn't need this modifier, since it operates
- //on the destination buffer, NOT the source buffer!)
- #define SMPRATE_MOD_RAW(_src_samplerate) \
- ( (f64)(_src_samplerate)/sampleRate )
- //(this one assumes .audio != nullptr, so just be aware of that)
- #define SMPRATE_MOD(_track_lvalue) \
- SMPRATE_MOD_RAW(_track_lvalue.audio->sampleRate)
- void SoundEngine::setSpeed(f64 speedNew,
- u16 track, bool forced)
- {
- CHECK_INVALID_AND_MUTEX("SoundEngine::setSpeed()");
- //normally, anything at or below 0 will cause the clip
- //to stop immediately, but this check couldn't hurt
- if(speedNew < 0.0) speedNew = 0.0;
- if(track != 0xFFFF){
- CHECK_TRACK_OOB("SoundEngine::setSpeed()");
- _SoundEngineTrack& _track = _tracks[track];
- if(_track.audio == nullptr) return; //track is empty; exit early
- LOCK_MUTEX;
- speedNew *= SMPRATE_MOD(_track);
- if(forced) _track.spd_old = speedNew;
- _track.spd_new = speedNew;
- UNLOCK_MUTEX;
- } else {
- _SoundEngineTrack* tracks = _tracks;
- LOCK_MUTEX;
- if(!forced){
- for(u16 t=0; t<_tracks_len; ++t){
- if(tracks[t].audio == nullptr) continue; //track is empty; next iteration
- tracks[t].spd_new = speedNew*SMPRATE_MOD(tracks[t]);
- }
- } else {
- for(u16 t=0; t<_tracks_len; ++t){
- if(tracks[t].audio == nullptr) continue; //track is empty; next iteration
- f64 _speedNew = speedNew*SMPRATE_MOD(tracks[t]);
- tracks[t].spd_old = _speedNew;
- tracks[t].spd_new = _speedNew;
- }
- }
- UNLOCK_MUTEX;
- }
- }
- void SoundEngine::setVolumeDelta(f32 deltaSecondsL, f32 deltaSecondsR,
- u16 track)
- {
- CHECK_INVALID("SoundEngine::setVolumeDelta()");
- //calculate delta, with a divide-by zero check for deltaSeconds
- //(sampleRate doesn't need it, since mixTracks just exits early in that case)
- Stereo_f32 delta((1.0f/deltaSecondsL) / sampleRate,
- (1.0f/deltaSecondsR) / sampleRate);
- if(!deltaSecondsL) delta.l = 0.0f;
- if(!deltaSecondsR) delta.r = 0.0f;
- if(track != 0xFFFF){
- CHECK_TRACK_OOB("SoundEngine::setVolumeDelta()");
- _tracks[track].volDelta = delta;
- } else {
- _SoundEngineTrack* tracks = _tracks;
- for(u16 t=0; t<_tracks_len; ++t)
- tracks[t].volDelta = delta;
- }
- }
- void SoundEngine::setSpeedDelta(f64 deltaSeconds,
- u16 track)
- {
- CHECK_INVALID("SoundEngine::setSpeedDelta()");
- //calculate delta, with a divide-by zero check for deltaSeconds
- //(sampleRate doesn't need it, since mixTracks just exits early in that case)
- f64 delta = (deltaSeconds != 0) ? ((1.0/deltaSeconds) / sampleRate) : 0.0;
- if(track != 0xFFFF){
- CHECK_TRACK_OOB("SoundEngine::setSpeedDelta()");
- _SoundEngineTrack& _track = _tracks[track];
- if(_track.audio == nullptr) return; //track is empty; exit early
- _track.spdDelta = delta*SMPRATE_MOD(_track);
- } else {
- _SoundEngineTrack* tracks = _tracks;
- for(u16 t=0; t<_tracks_len; ++t){
- if(tracks[t].audio == nullptr) continue; //track is empty; next iteration
- tracks[t].spdDelta = delta*SMPRATE_MOD(tracks[t]);
- }
- }
- }
- #define PLAY_ASSERT(_success, _err_msg) \
- if(!(_success)){ THROW_ERROR("SoundEngine::play(): " _err_msg); }
- u16 SoundEngine::play(const AudioData& audio,
- f32 volumeL, f32 volumeR, f64 speed)
- {
- CHECK_INVALID_AND_MUTEX("SoundEngine::play()");
- PLAY_ASSERT(audio.hdr, "audio.hdr = nullptr");
- PLAY_ASSERT(audio.hdr->format == SMPFMT_F32, "audio.hdr->format != SMPFMT_F32");
- PLAY_ASSERT(audio.hdr->channels == 1 || audio.hdr->channels == 2,
- "audio.hdr->channels is neither mono nor stereo")
- u64 timestamp = time::getMS();
- //will remain and return as 0xFFFF if no available track was found
- u16 queuedTrackNum = 0xFFFF;
- _SoundEngineTrack* tracks = _tracks;
- //(is locking actually necessary here?)
- LOCK_MUTEX; //tbd: if timing problems start to occur, remove the lock
- for(u16 t=0; t<_tracks_len; ++t){
- _SoundEngineTrack& track = tracks[t];
- if(track.audio == nullptr){
- track.timestamp = timestamp;
- //track.position = <set inside callback>;
- track.spd_old = MAX(speed*SMPRATE_MOD_RAW(audio.hdr->sampleRate), 0.0);
- track.spd_new = track.spd_old;
- track.spdDelta = 0.0;
- track.vol_old = Stereo_f32(volumeL, volumeR);
- track.vol_new = Stereo_f32(volumeL, volumeR);
- track.volDelta = Stereo_f32( 0.0f, 0.0f);
- track.volMaster = audio.volume;
- track.loops = audio.hdr->loopCount;
- track.stopping = false;
- //set last to make sure that all relevant members
- //of the track are set before beginning
- track.audio = audio.hdr;
- queuedTrackNum = t; break;
- }
- }
- UNLOCK_MUTEX;
- return queuedTrackNum;
- }
- void SoundEngine::stop(u16 track, bool forced){
- CHECK_INVALID("SoundEngine::stop()");
- //if !forced, 'stop' the track by setting a fade-out of 10ms,
- //whereupon the track will *actually* stop automatically
- Stereo_f32 fadeoutDelta((1.0f/-0.010f) / sampleRate);
- if(track != 0xFFFF){
- CHECK_TRACK_OOB("SoundEngine::stop()");
- _SoundEngineTrack& _track = _tracks[track];
- if(_track.audio == nullptr) return; //track is empty; exit early
- if(!forced) _track.volDelta = fadeoutDelta;
- else _track.audio = nullptr;
- } else {
- _SoundEngineTrack* tracks = _tracks;
- if(!forced){
- for(u16 t=0; t<_tracks_len; ++t)
- tracks[t].volDelta = fadeoutDelta;
- } else {
- for(u16 t=0; t<_tracks_len; ++t)
- tracks[t].audio = nullptr;
- }
- }
- }
- //returns false if timeout is reached, true otherwise
- static inline bool _waitForTrack(const AudioDataHeader*& audio,
- u64 timestampMS, u64 timeoutMS)
- {
- while(audio != nullptr){
- time::sleep(5);
- if((time::getMS()-timestampMS) > timeoutMS) return false;
- }
- return true;
- }
- bool SoundEngine::waitForTrack(u64 timeoutMS, u16 track){
- CHECK_INVALID("SoundEngine::waitForTrack()");
- u64 timestampMS = time::getMS();
- if(timeoutMS == 0) timeoutMS = KIT_U64_MAX; //effectively an infinite timeout
- if(track != 0xFFFF){
- CHECK_TRACK_OOB("SoundEngine::waitForTrack()");
- if(!_waitForTrack(_tracks[track].audio,
- timestampMS, timeoutMS))
- {
- return false;
- }
- } else {
- _SoundEngineTrack* tracks = _tracks;
- for(u16 t=0; t<_tracks_len; ++t){
- if(!_waitForTrack(tracks[t].audio,
- timestampMS, timeoutMS))
- {
- return false;
- }
- }
- /*
- //(alternate method)
- while(getActiveTracks() > 0){
- time::sleep(10);
- if((time::getMS()-timestampMS) > timeoutMS) return false;
- }
- */
- }
- return true; //will return true only if track(s) finished before timeout
- }
- //SoundEngine::mixTracks() is located in "kit_SoundEngine_mixTracks.cpp"
- }; /* namespace kit */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement