Advertisement
Kitomas

work for 2024-08-30 (0/5)

Aug 29th, 2024
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 25.84 KB | None | 0 0
  1. /******************************************************************************/
  2. /******************************************************************************/
  3. //"ksdl2\src\main.cpp":
  4. #include <kit/all.hpp>
  5.  
  6. using namespace kit;
  7.  
  8. #define SDL_MAIN_HANDLED
  9. #include "./lodepng/lodepng.hpp"
  10. #include "./kit_sdl2/_kit_common.hpp"
  11.  
  12.  
  13.  
  14.  
  15. void _SurfaceSetColorKey(SDL_Surface* surf, bool enable, u32 key,
  16.                          const char* funcname)
  17. {
  18.   if(SDL_SetColorKey(surf, enable, key))
  19.     THROW_ERRORF("%s: \"%s\"", funcname, SDL_GetError());
  20.  
  21. }
  22.  
  23.  
  24.  
  25.  
  26.  
  27.  
  28. void watch(Event& event, void* userdata){
  29.   if(event.type != KEVENT_WIN_SIZE_CHANGED) return;
  30.  
  31.   if(userdata){
  32.     ((Window*)userdata)->renewSurface();
  33.   }
  34.  
  35.   kit_LogInfo("size changed (%llu)", time::getTicks());
  36.  
  37. }
  38.  
  39.  
  40.  
  41. int main(/*int argc, char** argv*/){ try { {
  42.   initSubsystems(KINIT_EVENTS|KINIT_AUDIO);
  43.   srand(time::getTicks());
  44.  
  45.  
  46.   Window win(nullptr, 640, 480, WINFLAG_RESIZABLE);
  47.   win.renewSurface();
  48.  
  49.   Surface livereact("live_reaction.png");
  50.  
  51.  
  52.  
  53.   bool enabled = true;
  54.   EventWatch evtWatch(watch, &win);
  55.  
  56.  
  57.   bool fullscreen = false;
  58.  
  59.   bool run = true;
  60.   while(run){
  61.     if(!enabled) win.renewSurface();
  62.  
  63.     Event evt;
  64.     while(run && pollEvent(&evt))
  65.     switch(evt.type){
  66.       case KEVENT_QUIT: run = false; break;
  67.       case KEVENT_KEY_DOWN: {
  68.         switch(evt.key.vkey){
  69.           case VKEY_F11: win.setFullscreen(2*(fullscreen^=1)); break;
  70.           case VKEY_RETURN: evtWatch.setState((enabled^=1)); break;
  71.           default:;
  72.           win.fillRects((u32)rand());
  73.         }
  74.  
  75.         //win.warpMouse(-50,-50);
  76.       } break;
  77.       case KEVENT_WIN_RESIZED: {
  78.       } break;
  79.       default:;
  80.     }
  81.  
  82.     //livereact.blit(win, nullptr, nullptr);
  83.     win.updateSurface();
  84.  
  85.     SDL_Delay(16);
  86.  
  87.   }
  88.  
  89.  
  90.  
  91.  
  92. }
  93.   _getnumallocs
  94.   quitSubsystems(KINIT_EVERYTHING);
  95.   _getnumallocs
  96.   return 0;
  97.  
  98. } catch(const char* errorText){
  99. #ifdef _DEBUG
  100.   kit_LogError("FATAL EXCEPTION OCCURRED: \"%s\"\n", errorText);
  101. #else
  102.   showMsgBox(fstr("Error: %-14s", errorText),
  103.              "FATAL EXCEPTION OCCURRED!", MSGBOX_ERROR);
  104. #endif /* _DEBUG */
  105.  
  106.   //redundant, since quitSubsystems(KINIT_EVERYTHING)
  107.    //frees all thread errors automatically anyway
  108.   //freeThreadErrors();
  109.  
  110.   _getnumallocs
  111.   quitSubsystems(KINIT_EVERYTHING);
  112.   _getnumallocs
  113.  
  114.   return -1;
  115. }}
  116. /******************************************************************************/
  117. /******************************************************************************/
  118. //"ksdl2\src\kit_sdl2\kit_AudioCallbackWrapper.cpp":
  119. #include "_kit_common.hpp"
  120.  
  121.  
  122. namespace kit {
  123.  
  124.  
  125.  
  126.  
  127.  
  128. //workaround for having _AudioCallbackWrapper pause the device,
  129.  //without having to call SDL_PauseAudioDevice inside the callback itself
  130. //(this may potentially cut off playback before the current buffer plays, idk)
  131. static int _AudioPauseThread(void* data){
  132.   _AudioDeviceOpaque* opq = (_AudioDeviceOpaque*)data;
  133.   SDL_AudioDeviceID devID = opq->info_p->deviceID;
  134.  
  135.   //wait for the callback to exit before actually pausing
  136.   SDL_LockAudioDevice(devID);
  137.  
  138.   SDL_PauseAudioDevice(devID, 1);
  139.   opq->fadeOut = false;
  140.   opq->playing = false;
  141.  
  142.   SDL_UnlockAudioDevice(devID);
  143.  
  144.   return 0;
  145.  
  146. }
  147.  
  148. static inline bool startPauseThread(_AudioDeviceOpaque* opq){
  149.   SDL_Thread* pauseThread = SDL_CreateThread(_AudioPauseThread, "kADPause", opq);
  150.  
  151.   if(pauseThread){
  152.     SDL_DetachThread(pauseThread);
  153.  
  154.   } else {
  155.     opq->fadeDelay = KIT_U32_MAX;
  156.     opq->fadeOut   = false;
  157.     opq->playing   = false;
  158.  
  159.   }
  160.  
  161.   return pauseThread != nullptr;
  162.  
  163. }
  164.  
  165.  
  166.  
  167.  
  168.  
  169. //not inlined
  170.  //(also, stream_len is in total samples, not sample frames)
  171. static void apply_fade(_AudioDeviceOpaque* opq,
  172.                        f32* stream, u32 stream_len)
  173. {
  174.   f32 fadeDelta   = opq->fadeDelta;
  175.   f32 fadeVolume  = opq->fadeVolume;
  176.   u32 fadeDelay   = opq->fadeDelay;
  177.   u8  numChannels = opq->info_p->numChannels;
  178.  
  179.   u32 smp = 0; //this index is shared, as the loops can jump to others at will
  180.  
  181.  
  182.  
  183.   //FADING OUT
  184.   if(opq->fadeOut){
  185.     _FadeOut:;
  186.     for(; smp<stream_len; ++smp){
  187.       //if audio device starts fading in mid-fadeout, jump to the fade-in loop
  188.       if(!opq->fadeOut) goto _FadeIn;
  189.  
  190.       stream[smp] *= fadeVolume;
  191.  
  192.       //only change fadeVolume every numChannels samples,
  193.        //so that there's 1 fadeVolume state per sample frame
  194.       if(!((smp+1)%numChannels)) fadeVolume -= fadeDelta;
  195.  
  196.       //to enforce a minimum volume
  197.       if(fadeVolume < 0.0f) fadeVolume = 0.0f;
  198.  
  199.     }
  200.  
  201.     //trigger pause thread if fade out is complete
  202.     if(fadeVolume == 0.0f)
  203.       startPauseThread(opq);
  204.  
  205.  
  206.  
  207.   //FADING IN
  208.   } else if(fadeVolume < 1.0f){
  209.     //let stream warm up before fading in (if fadeDelay != 0)
  210.     for(; (fadeDelay)&&(smp<stream_len); ++smp){
  211.       stream[smp] = 0.0f;
  212.       if(!((smp+1)%numChannels)) --fadeDelay;
  213.  
  214.     }
  215.  
  216.  
  217.     _FadeIn:;
  218.     for(; smp<stream_len; ++smp){
  219.       if(opq->fadeOut) goto _FadeOut;
  220.  
  221.       stream[smp] *= fadeVolume;
  222.  
  223.       if(!((smp+1)%numChannels)) fadeVolume += fadeDelta;
  224.  
  225.       if(fadeVolume > 1.0f) fadeVolume = 1.0f;
  226.  
  227.     }
  228.  
  229.  
  230.   }
  231.  
  232.  
  233.  
  234.   //update relevant data in opq
  235.   opq->fadeVolume = fadeVolume;
  236.   opq->fadeDelay  = fadeDelay;
  237.  
  238. }
  239.  
  240.  
  241.  
  242.  
  243.  
  244. //for multiplying the by inverse of stuff
  245. #define INV_S8  0.0078125000000000000000000000000f // = 1.0f/0x80
  246. #define INV_S16 0.0000305175781250000000000000000f // = 1.0f/0x8000
  247. #define INV_S32 0.0000000004656612873077392578125f // = 1.0f/0x80000000
  248.  
  249. #define fmtconvloop for(u32 i=0; i<length; ++i) to
  250.  
  251.  
  252. //used for output devices
  253.  //(length should be in samples, not sample frames)
  254. static inline void fmt_to_f32(Mono_smp from, f32* to,
  255.                               u32 length, u16 from_fmt)
  256. {
  257.   switch(from_fmt){
  258.     case SMPFMT_U8 : fmtconvloop[i] = ((f32)from.u8_ [i]-0x80  )*INV_S8 ; break;
  259.     case SMPFMT_S8 : fmtconvloop[i] = ((f32)from.s8_ [i]       )*INV_S8 ; break;
  260.     case SMPFMT_U16: fmtconvloop[i] = ((f32)from.u16_[i]-0x8000)*INV_S16; break;
  261.     case SMPFMT_S16: fmtconvloop[i] = ((f32)from.s16_[i]       )*INV_S16; break;
  262.     case SMPFMT_S32: fmtconvloop[i] = ((f32)from.s32_[i]       )*INV_S32; break;
  263.     case SMPFMT_F32: memory::copy(to, from.f32_, length*sizeof(f32));    break;
  264.     //(f32 samples aren't hard-clipped! make sure to keep them -1.0f -> 1.0f)
  265.   }
  266. }
  267.  
  268.  
  269. //used for input devices
  270.  //(again, length should be in samples, not sample frames)
  271. static inline void f32_to_fmt(f32* from, Mono_smp to,
  272.                               u32 length, u16 to_fmt)
  273. {
  274.   //(input f32 samples aren't hard-clipped here either!)
  275.   switch(to_fmt){
  276.     case SMPFMT_U8 : fmtconvloop.u8_ [i] = (u8 )(from[i]*0x7F + 0x80    ); break;
  277.     case SMPFMT_S8 : fmtconvloop.s8_ [i] = (s8 )(from[i]*0x7F           ); break;
  278.     case SMPFMT_U16: fmtconvloop.u16_[i] = (u16)(from[i]*0x7FFF + 0x8000); break;
  279.     case SMPFMT_S16: fmtconvloop.s16_[i] = (s16)(from[i]*0x7FFF         ); break;
  280.     case SMPFMT_S32: fmtconvloop.s32_[i] = (s32)(from[i]*0x7FFFFFFF     ); break;
  281.     case SMPFMT_F32: memory::copy(to.f32_, from, length*sizeof(f32));
  282.   }
  283. }
  284.  
  285.  
  286.  
  287.  
  288.  
  289. void _AudioCallbackWrapper(void* userdata, u8* _stream, int len){
  290.   u64 timeStartTicks = SDL_GetPerformanceCounter();
  291.   u64 timeStartMS    = SDL_GetTicks64();
  292.  
  293.  
  294.   AudioDevice* device = (AudioDevice*)userdata;
  295.   f32*         stream = (f32*)_stream;
  296.   u32     stream_size = len;
  297.   u32      stream_len = len / sizeof(f32); //samples, not sample frames
  298.  
  299.  
  300.   _AudioDeviceOpaque* opq = (_AudioDeviceOpaque*)KIT_GET_CLASS_OPAQUE(device);
  301.   AudioDeviceInfo* info_p = opq->info_p;
  302.   info_p->timeStartTicks  = timeStartTicks;
  303.   info_p->timeStartMS     = timeStartMS;
  304.  
  305.  
  306.  
  307.   //if pause thread failed to start,
  308.    //simply write zeros to stream (if !isInput) and exit
  309.   if(opq->fadeDelay == KIT_U32_MAX){
  310.     if(!info_p->isInput) memory::set(stream, 0, stream_size);
  311.     return;
  312.  
  313.   }
  314.  
  315.  
  316.  
  317.   s32 callbackReturn = -1; //'abort playback' by default
  318.  
  319.   if(!info_p->isInput){ //buffer will be written to
  320.     //(memset 0 the _user_ buffer, not the sdl stream)
  321.     if(info_p->zeroBuffer) memory::set(opq->buffer, 0, opq->buffer_size);
  322.  
  323.     try { //attempt to call user callback
  324.       if(info_p->callback)
  325.         callbackReturn = info_p->callback(opq->buffer, info_p);
  326.  
  327.     } catch(const char* errortext){
  328.       kit_LogError("IN AUDIO CALLBACK: \"%s\"", errortext);
  329.       freeThreadErrors();
  330.       //set back to 0, since used callback failed
  331.       memory::set(stream, 0, stream_size);
  332.  
  333.     }
  334.  
  335.     //copy buffer to stream (X to f32)
  336.     fmt_to_f32(opq->buffer, stream, stream_len, info_p->sampleFormat);
  337.  
  338.     //apply fade to output stream
  339.     apply_fade(opq, stream, stream_len);
  340.  
  341.  
  342.   } else { //buffer will be read from
  343.     //apply fade to input stream
  344.     apply_fade(opq, stream, stream_len);
  345.  
  346.     //copy stream to buffer (f32 to X)
  347.     f32_to_fmt(stream, opq->buffer, stream_len, info_p->sampleFormat);
  348.  
  349.     try { //attempt to call user callback
  350.       if(info_p->callback)
  351.         callbackReturn = info_p->callback(opq->buffer, info_p);
  352.  
  353.     } catch(const char* errortext){
  354.       kit_LogError("IN AUDIO CALLBACK: \"%s\"", errortext);
  355.       freeThreadErrors();
  356.  
  357.     }
  358.  
  359.   }
  360.  
  361.  
  362.  
  363.   opq->fadeOut = callbackReturn != 0;
  364.  
  365.   if(callbackReturn < 0) startPauseThread(opq);
  366.  
  367. }
  368.  
  369.  
  370.  
  371.  
  372.  
  373. }; /* namespace kit */
  374. /******************************************************************************/
  375. /******************************************************************************/
  376. //"ksdl2\src\kit_sdl2\kit_AudioData.cpp":
  377. #include "_kit_common.hpp"
  378.  
  379. #define ADATA_IS_INVALID (!_valid && !_constructing)
  380.  
  381.  
  382. namespace kit {
  383.  
  384.  
  385.  
  386.  
  387.  
  388. //
  389.  
  390.  
  391.  
  392.  
  393.  
  394. }; /* namespace kit */
  395. /******************************************************************************/
  396. /******************************************************************************/
  397. //"ksdl2\src\kit_sdl2\kit_AudioData_LoadVorbis.cpp":
  398. #include "_kit_common.hpp"
  399.  
  400. #include "../stb_vorbis/stb_vorbis.hpp"
  401.  
  402. namespace kit {
  403.  
  404.  
  405.  
  406.  
  407.  
  408.  
  409.  
  410. }; /* namespace kit */
  411. /******************************************************************************/
  412. /******************************************************************************/
  413. //"ksdl2\src\kit_sdl2\kit_AudioDevice.cpp":
  414. #include "_kit_common.hpp"
  415.  
  416. #define INDEX_FUNC "AudioDevice::AudioDevice(index)"
  417. #define NAME_FUNC  "AudioDevice::AudioDevice(name)"
  418.  
  419. #define DEVICE_IS_INVALID (!_valid && !_constructing)
  420.  
  421. //i don't think i ended up using these lol
  422. #define CONSTRUCTOR_ERR(_txt) PUSH_ERRORF("%s: " _txt , funcname)
  423. #define CONSTRUCTOR_ERRSDL    PUSH_ERRORF("%s: \"%s\"", funcname, SDL_GetError())
  424.  
  425. #define DEV_PTR ((_AudioDeviceOpaque*)_opq)
  426.  
  427.  
  428. namespace kit {
  429.  
  430.  
  431.  
  432.  
  433.  
  434. //in "kit_AudioCallbackWrapper.cpp"
  435. void _AudioCallbackWrapper(void* userdata, u8* _stream, int len);
  436.  
  437.  
  438.  
  439.  
  440.  
  441. static inline u32 _count_bits(u32 num){
  442.   u32 count = 0;
  443.  
  444.   while(num > 0){
  445.     if(num&1) ++count;
  446.     num >>= 1;
  447.   }
  448.  
  449.   return count;
  450.  
  451. }
  452.  
  453.  
  454. //not inlined
  455. bool _validate_smpfmt(u16 sampleFormat, bool allow0 = false){
  456.   switch(sampleFormat){
  457.     case SMPFMT_U8    :
  458.     case SMPFMT_S8    :
  459.     case SMPFMT_U16LSB:
  460.     case SMPFMT_S16LSB:
  461.   //case SMPFMT_U16MSB:
  462.   //case SMPFMT_S16MSB:
  463.     case SMPFMT_S32LSB:
  464.   //case SMPFMT_S32MSB:
  465.     case SMPFMT_F32LSB:
  466.   //case SMPFMT_F32MSB:
  467.     break;
  468.  
  469.     case 0:
  470.       if(allow0) break;
  471.       else SDL_FALLTHROUGH;
  472.  
  473.     default:
  474.       return false;
  475.  
  476.   }
  477.  
  478.   return true;
  479.  
  480. }
  481.  
  482.  
  483. static inline void validate_desired(const AudioDeviceInfo* desired,
  484.                                     const char* funcname)
  485. {
  486.   if(desired->sampleRate > KIT_S32_MAX)
  487.     THROW_ERRORF("%s: desired->sampleRate > KIT_S32_MAX", funcname);
  488.  
  489.   if(_count_bits(desired->sampleFrames) > 1)
  490.     THROW_ERRORF("%s: desired->sampleFrames is not a power of 2", funcname);
  491.  
  492.   if(!_validate_smpfmt(desired->sampleFormat, true)){
  493.     THROW_ERRORF("%s: desired->sampleFormat of 0x%04X is invalid",
  494.                       funcname, desired->sampleFormat);
  495.   }
  496.  
  497.   if(desired->numChannels > 8)
  498.     THROW_ERRORF("%s: desired->numChannels > 8", funcname);
  499.  
  500.   if(desired->callback == nullptr)
  501.     THROW_ERRORF("%s: desired->callback = nullptr", funcname);
  502.  
  503. }
  504.  
  505.  
  506. static inline s32 get_dev_params(SDL_AudioSpec& want,
  507.                                  const AudioDeviceInfo* desired,
  508.                                  AudioDevice* device)
  509. {
  510.   want.freq     = (s32)((desired->sampleRate) ? desired->sampleRate : 48000);
  511.   want.format   = AUDIO_F32LSB;
  512.   want.channels = (desired->numChannels) ? desired->numChannels : 2;
  513.   want.samples  = (desired->sampleFrames) ? desired->sampleFrames : 4096;
  514.   want.callback = _AudioCallbackWrapper;
  515.   want.userdata = device;
  516.  
  517.   s32 allowed_changes = 0;
  518.   if(!desired->sampleRate  ) allowed_changes |= SDL_AUDIO_ALLOW_FREQUENCY_CHANGE;
  519.   //underlying stream must be f32, so this one should never be set
  520. //if(!desired->sampleFormat) allowed_changes |= SDL_AUDIO_ALLOW_FORMAT_CHANGE;
  521.   if(!desired->numChannels ) allowed_changes |= SDL_AUDIO_ALLOW_CHANNELS_CHANGE;
  522.   if(!desired->sampleFrames) allowed_changes |= SDL_AUDIO_ALLOW_SAMPLES_CHANGE;
  523.  
  524.   return allowed_changes;
  525.  
  526. }
  527.  
  528.  
  529. static inline AudioDeviceInfo set_dev_info(SDL_AudioDeviceID      deviceID,
  530.                                            SDL_AudioSpec          have,
  531.                                            const AudioDeviceInfo* desired)
  532. {
  533.   AudioDeviceInfo info;
  534. //info.timeStartTicks  = 0;
  535. //info.timeStartMS     = 0;
  536.   info.deviceID        = deviceID;
  537.   info.sampleRate      = have.freq;
  538.   info.sampleFrames    = have.samples;
  539.   info.sampleFormat    = have.format;
  540.   info.sampleFrameSize = KIT_AUDIO_BYTESIZE(have.format)*have.channels;
  541.   info.numChannels     = have.channels;
  542.   info.isInput         = desired->isInput;
  543.   info.zeroBuffer      = desired->zeroBuffer;
  544.   info.callback        = desired->callback;
  545.   info.userdata        = desired->userdata;
  546.  
  547.   return info;
  548.  
  549. }
  550.  
  551.  
  552.  
  553.  
  554.  
  555. AudioDevice::AudioDevice(s32 index, //-1 to use default device
  556.                          const AudioDeviceInfo* desired,
  557.                          bool disableFadeDelay)
  558. {
  559.   //check if desired is nullptr, since ->isInput is necessary to get device name
  560.   if(desired  == nullptr) THROW_ERROR(INDEX_FUNC ": desired = nullptr");
  561.  
  562.   const char* name = nullptr;
  563.  
  564.   if(index >= 0){
  565.     name = SDL_GetAudioDeviceName(index, desired->isInput);
  566.  
  567.     if(name == nullptr)
  568.       THROW_ERRORF(INDEX_FUNC ": \"%s\"", SDL_GetError());
  569.  
  570.   }
  571.  
  572.   _construct(name, desired, disableFadeDelay);
  573.  
  574. }
  575.  
  576.  
  577.  
  578.  
  579.  
  580. void AudioDevice::_construct(const char* name,
  581.                              const AudioDeviceInfo* desired,
  582.                              bool disableFadeDelay,
  583.                              bool indexed)
  584. {
  585.   _type = KIT_CLASSTYPE_AUDIODEVICE;
  586.  
  587.   const char* funcname = (indexed) ? INDEX_FUNC : NAME_FUNC;
  588.  
  589.   if(desired  == nullptr) THROW_ERRORF("%s: desired = nullptr", funcname);
  590.  
  591.   AudioDeviceInfo* info_p = (AudioDeviceInfo*)&info; //info is normally const
  592.  
  593.  
  594.  
  595.   //a few domain checks
  596.   validate_desired(desired, funcname);
  597.  
  598.   SDL_AudioSpec want, have;
  599.   s32 allowed_changes = get_dev_params(want, desired, this);
  600.  
  601.  
  602.  
  603.   //actually create the device
  604.   SDL_AudioDeviceID deviceID = SDL_OpenAudioDevice(name, desired->isInput,
  605.                                                    &want, &have, allowed_changes);
  606.  
  607.   if(!deviceID) THROW_ERRORF("%s: \"%s\"", funcname, SDL_GetError());
  608.  
  609.   if(desired->sampleFormat) have.format = desired->sampleFormat;
  610.  
  611.   *info_p = set_dev_info(deviceID, have, desired);
  612.  
  613.  
  614.  
  615.   _opq = memory::alloc(sizeof(_AudioDeviceOpaque));
  616.  
  617.   if(_opq == nullptr){
  618.     SDL_CloseAudioDevice(info.deviceID);
  619.     THROW_ERRORF("%s: failed to allocate memory for opaque struct", funcname);
  620.  
  621.   }
  622.  
  623.   memory::set(_opq, 0, sizeof(_AudioDeviceOpaque));
  624.  
  625.  
  626.  
  627.   DEV_PTR->info_p      = info_p;
  628.   DEV_PTR->buffer_size = info.sampleFrames * info.sampleFrameSize;
  629.   DEV_PTR->buffer      = memory::allocSIMD(DEV_PTR->buffer_size);
  630.   DEV_PTR->fadeDelta   = 1.0f / ((f32)info.sampleRate*FADEDELTA_SEC);
  631. //DEV_PTR->fadeVolume  = 0.0f; //(the prior memset makes setting to 0 redundant)
  632. //DEV_PTR->fadeDelay   = 0;
  633. //DEV_PTR->fadeOut     = false;
  634.   DEV_PTR->noFadeDelay = disableFadeDelay;
  635. //DEV_PTR->playing     = false;
  636.  
  637.   if(DEV_PTR->buffer == nullptr){
  638.     memory::free(&_opq);
  639.     SDL_CloseAudioDevice(info.deviceID);
  640.     THROW_ERRORF("%s: failed to allocate memory for audio buffer", funcname);
  641.  
  642.   }
  643.  
  644.   memory::set(DEV_PTR->buffer, 0, DEV_PTR->buffer_size);
  645.  
  646.  
  647.  
  648.   _valid = true;
  649.   _constructing = false;
  650.  
  651. }
  652.  
  653.  
  654.  
  655.  
  656.  
  657. AudioDevice::~AudioDevice(){
  658.   if(!_valid) return;
  659.   _valid = false;
  660.  
  661.   if(info.deviceID != 0) SDL_CloseAudioDevice(info.deviceID);
  662.   if(_opq != nullptr){
  663.     memory::freeSIMD(&DEV_PTR->buffer);
  664.     memory::free(&_opq);
  665.   }
  666.  
  667. }
  668.  
  669.  
  670.  
  671.  
  672.  
  673. bool AudioDevice::isPlaying(){
  674.   if(DEVICE_IS_INVALID)
  675.     THROW_ERROR("AudioDevice::isPlaying(): invalid AudioDevice");
  676.  
  677.   //return SDL_GetAudioDeviceStatus(info.deviceID) == SDL_AUDIO_PLAYING;
  678.   return DEV_PTR->playing;
  679.  
  680. }
  681.  
  682.  
  683.  
  684.  
  685.  
  686. bool AudioDevice::isActive(){
  687.   if(DEVICE_IS_INVALID)
  688.     THROW_ERROR("AudioDevice::isActive(): invalid AudioDevice");
  689.  
  690.   return SDL_GetAudioDeviceStatus(info.deviceID) == SDL_AUDIO_PLAYING;
  691.   //return DEV_PTR->playing;
  692.  
  693. }
  694.  
  695.  
  696.  
  697.  
  698.  
  699. void AudioDevice::setCallback(AudioCallback callback){
  700.   if(DEVICE_IS_INVALID)
  701.     THROW_ERROR("AudioDevice::setCallback(): invalid AudioDevice");
  702.  
  703.   if(callback == nullptr)
  704.     THROW_ERROR("AudioDevice::setCallback(): callback = nullptr");
  705.  
  706.   SDL_LockAudioDevice(info.deviceID);
  707.  
  708.   ((AudioDeviceInfo*)&info)->callback = callback;
  709.  
  710.   SDL_UnlockAudioDevice(info.deviceID);
  711.  
  712. }
  713.  
  714.  
  715.  
  716.  
  717. void AudioDevice::setUserdata(void* userdata){
  718.   if(DEVICE_IS_INVALID)
  719.     THROW_ERROR("AudioDevice::setUserdata(): invalid AudioDevice");
  720.  
  721.   SDL_LockAudioDevice(info.deviceID);
  722.  
  723.   ((AudioDeviceInfo*)&info)->userdata = userdata;
  724.  
  725.   SDL_UnlockAudioDevice(info.deviceID);
  726.  
  727. }
  728.  
  729.  
  730.  
  731.  
  732. void AudioDevice::setPlayback(bool playing){
  733.   if(DEVICE_IS_INVALID)
  734.     THROW_ERROR("AudioDevice::setPlayback(): invalid AudioDevice");
  735.  
  736.  
  737.   //this should occur when _AudioCallbackWrapper
  738.    //fails to trigger the pause thread
  739.   if(DEV_PTR->fadeDelay == KIT_U32_MAX){
  740.     SDL_LockAudioDevice(info.deviceID);
  741.  
  742.     SDL_PauseAudioDevice(info.deviceID, true);
  743.  
  744.     DEV_PTR->fadeVolume = 0.0f;
  745.     DEV_PTR->fadeDelay  = 0;
  746.     DEV_PTR->fadeOut    = false;
  747.     DEV_PTR->playing    = false;
  748.  
  749.     SDL_UnlockAudioDevice(info.deviceID);
  750.  
  751.   }
  752.  
  753.  
  754.   DEV_PTR->fadeOut = !playing;
  755.   if(playing && !DEV_PTR->playing){
  756.     //the purpose of fadeDelay is to mute for some samples
  757.      //to give the sdl audio device some time to warm up,
  758.      //otherwise artifacts start to occur (for me, anyway)
  759.     if(!DEV_PTR->noFadeDelay) DEV_PTR->fadeDelay = (u32)(info.sampleRate * FADEDELAY_SEC);
  760.     else                      DEV_PTR->fadeDelay = 0;
  761.  
  762.     DEV_PTR->fadeVolume = 0.0f;
  763.     DEV_PTR->playing    = true;
  764.  
  765.     SDL_PauseAudioDevice(info.deviceID, false);
  766.  
  767.   }
  768.  
  769. }
  770.  
  771.  
  772.  
  773.  
  774. void AudioDevice::setPlaybackAndWait(bool playing){
  775.   if(DEVICE_IS_INVALID)
  776.     THROW_ERROR("AudioDevice::setPlaybackAndWait(): invalid AudioDevice");
  777.  
  778.  
  779.   bool wasPlaying = DEV_PTR->playing;
  780.  
  781.   setPlayback(playing);
  782.  
  783.  
  784.   if(playing && !wasPlaying && !DEV_PTR->noFadeDelay){
  785.     time::sleep((u32)( FADETOTAL_SEC*1000 ));
  786.  
  787.   } else {
  788.     time::sleep((u32)( FADEDELTA_SEC*1000 ));
  789.  
  790.   }
  791.  
  792. }
  793.  
  794.  
  795.  
  796.  
  797.  
  798. void AudioDevice::lock(bool locked){
  799.   if(DEVICE_IS_INVALID)
  800.     THROW_ERROR("AudioDevice::lock(): invalid AudioDevice");
  801.  
  802.   if(locked) SDL_LockAudioDevice(info.deviceID);
  803.   else       SDL_UnlockAudioDevice(info.deviceID);
  804.  
  805. }
  806.  
  807.  
  808.  
  809.  
  810.  
  811. }; /* namespace kit */
  812. /******************************************************************************/
  813. /******************************************************************************/
  814. //"ksdl2\src\kit_sdl2\kit_AudioStream.cpp":
  815. #include "_kit_common.hpp"
  816.  
  817. #define STREAM_IS_INVALID (!_valid && !_constructing)
  818.  
  819. #define STRM_PTR ((SDL_AudioStream*)_opq)
  820.  
  821.  
  822. namespace kit {
  823.  
  824.  
  825.  
  826.  
  827.  
  828. bool _validate_smpfmt(u16 sampleFormat, bool allow0 = false);
  829.  
  830.  
  831.  
  832.  
  833.  
  834. AudioStream::AudioStream(const AudioDeviceInfo* src_p,
  835.                          const AudioDeviceInfo* dst_p)
  836. {
  837.   _type = KIT_CLASSTYPE_AUDIOSTREAM;
  838.  
  839.  
  840.   if(src_p == nullptr) THROW_ERROR("AudioStream::AudioStream(): src_p = nullptr");
  841.   if(dst_p == nullptr) THROW_ERROR("AudioStream::AudioStream(): dst_p = nullptr");
  842.  
  843.  
  844.   if(src_p->sampleRate > KIT_S32_MAX)
  845.     THROW_ERROR("AudioStream::AudioStream(): src_p->sampleRate > KIT_S32_MAX");
  846.  
  847.   if(dst_p->sampleRate > KIT_S32_MAX)
  848.     THROW_ERROR("AudioStream::AudioStream(): dst_p->sampleRate > KIT_S32_MAX");
  849.  
  850.  
  851.   if(!_validate_smpfmt(src_p->sampleFormat))
  852.     THROW_ERROR("AudioStream::AudioStream(): src_p->sampleFormat is invalid");
  853.  
  854.   if(!_validate_smpfmt(dst_p->sampleFormat))
  855.     THROW_ERROR("AudioStream::AudioStream(): dst_p->sampleFormat is invalid");
  856.  
  857.  
  858.   if(src_p->numChannels == 0  ||  src_p->numChannels > 8)
  859.     THROW_ERROR("AudioStream::AudioStream(): src_p->numChannels must be 1 -> 8");
  860.  
  861.   if(dst_p->numChannels == 0  ||  dst_p->numChannels > 8)
  862.     THROW_ERROR("AudioStream::AudioStream(): dst_p->numChannels must be 1 -> 8");
  863.  
  864.  
  865.  
  866.   //since src and dst are normally const,
  867.    //they're punned so that they can be set
  868.   AudioDeviceInfo* _src_p = (AudioDeviceInfo*)&src;
  869.   AudioDeviceInfo* _dst_p = (AudioDeviceInfo*)&dst;
  870.  
  871.   *_src_p = *src_p;
  872.   *_dst_p = *dst_p;
  873.  
  874.   _src_p->sampleFrameSize = src.numChannels * KIT_AUDIO_BYTESIZE(src.sampleFormat);
  875.   _dst_p->sampleFrameSize = dst.numChannels * KIT_AUDIO_BYTESIZE(dst.sampleFormat);
  876.  
  877.  
  878.   _opq = SDL_NewAudioStream(src.sampleFormat, src.numChannels, (s32)src.sampleRate,
  879.                             dst.sampleFormat, dst.numChannels, (s32)dst.sampleRate);
  880.  
  881.   if(_opq == nullptr)
  882.     THROW_ERRORF("AudioStream::AudioStream(): \"%s\"", SDL_GetError());
  883.  
  884.  
  885.  
  886.   _valid = true;
  887.   _constructing = false;
  888.  
  889. }
  890.  
  891.  
  892.  
  893.  
  894. AudioStream::~AudioStream(){
  895.   if(!_valid) return;
  896.   _valid = false;
  897.  
  898.   if(_opq != nullptr){
  899.     SDL_FreeAudioStream(STRM_PTR);
  900.     _opq = nullptr;
  901.  
  902.   }
  903.  
  904. }
  905.  
  906.  
  907.  
  908.  
  909.  
  910. u32 AudioStream::getAvailableBytes(){
  911.   if(STREAM_IS_INVALID)
  912.     THROW_ERROR("AudioStream::getNumAvailable(): invalid AudioStream");
  913.  
  914.   s32 result = SDL_AudioStreamAvailable(STRM_PTR);
  915.  
  916.   if(result < 0)
  917.     THROW_ERRORF("AudioStream::getNumAvailable(): \"%s\"", SDL_GetError());
  918.  
  919.   return (u32)result;
  920.  
  921. }
  922.  
  923.  
  924.  
  925.  
  926.  
  927. void AudioStream::flush(){
  928.   if(STREAM_IS_INVALID)
  929.     THROW_ERROR("AudioStream::flush(): invalid AudioStream");
  930.  
  931.   //as of 2024-08-03, the SDL2 wiki does not even tell you what this returns,
  932.    //but most SDL calls with int returns of this type use 0 and -1 for
  933.    //success and failure respectively. so, hopefully my hunch is right :D
  934.   if(SDL_AudioStreamFlush(STRM_PTR) != 0)
  935.     THROW_ERRORF("AudioStream::flush(): \"%s\"", SDL_GetError());
  936.  
  937. }
  938.  
  939.  
  940.  
  941.  
  942.  
  943. void AudioStream::clear(){
  944.   if(STREAM_IS_INVALID)
  945.     THROW_ERROR("AudioStream::clear(): invalid AudioStream");
  946.  
  947.   SDL_AudioStreamClear(STRM_PTR);
  948.  
  949. }
  950.  
  951.  
  952.  
  953.  
  954.  
  955. u32 AudioStream::get(void* buffer_dst, u32 buffer_size){
  956.   if(STREAM_IS_INVALID)
  957.     THROW_ERROR("AudioStream::get(): invalid AudioStream");
  958.  
  959.   if(buffer_dst == nullptr)
  960.     THROW_ERROR("AudioStream::get(): buffer_dst = nullptr");
  961.  
  962.   if(buffer_size > KIT_S32_MAX)
  963.     THROW_ERROR("AudioStream::get(): buffer_size > KIT_S32_MAX");
  964.  
  965.  
  966.   s32 result = SDL_AudioStreamGet(STRM_PTR, buffer_dst, buffer_size);
  967.  
  968.   if(result < 0)
  969.     THROW_ERRORF("AudioStream::get(): \"%s\"", SDL_GetError());
  970.  
  971.   return (u32)result;
  972.  
  973. }
  974.  
  975.  
  976.  
  977.  
  978.  
  979. void AudioStream::put(void* buffer_src, u32 buffer_size){
  980.   if(STREAM_IS_INVALID)
  981.     THROW_ERROR("AudioStream::put(): invalid AudioStream");
  982.  
  983.   if(buffer_src == nullptr)
  984.     THROW_ERROR("AudioStream::put(): buffer_src = nullptr");
  985.  
  986.   if(buffer_size > KIT_S32_MAX)
  987.     THROW_ERROR("AudioStream::put(): buffer_size > KIT_S32_MAX");
  988.  
  989.  
  990.   if(SDL_AudioStreamPut(STRM_PTR, buffer_src, buffer_size) < 0)
  991.     THROW_ERRORF("AudioStream::put(): \"%s\"", SDL_GetError());
  992.  
  993. }
  994.  
  995.  
  996.  
  997.  
  998.  
  999. }; /* namespace kit */
  1000. /******************************************************************************/
  1001. /******************************************************************************/
  1002. //"ksdl2\src\kit_sdl2\kit_EventWatch.cpp":
  1003. #include "_kit_common.hpp"
  1004.  
  1005.  
  1006. namespace kit {
  1007.  
  1008.  
  1009.  
  1010.  
  1011.  
  1012. //found in "kit_func_convertEvent.cpp"
  1013. bool _convertEvent(SDL_Event& e_sdl, Event& e_kit);
  1014.  
  1015.  
  1016.  
  1017.  
  1018.  
  1019. static int _EventWatchCallbackWrapper(void* EventWatch_ptr, SDL_Event* e_sdl){
  1020.   //ignore all poll sentinel events
  1021.   if(e_sdl->type == SDL_POLLSENTINEL) return 0;
  1022.  
  1023.   //if _disabled is nonzero, exit early
  1024.   if(KIT_GET_CLASS_DATA(EventWatch_ptr)&0xff) return 0;
  1025.  
  1026.   EventWatchCallback callback = (EventWatchCallback)KIT_GET_CLASS_OPAQUE(EventWatch_ptr);
  1027.   void*              userdata = KIT_GET_CLASS_OPAQUE2(EventWatch_ptr);
  1028.  
  1029.  
  1030.   Event e_kit;
  1031.  
  1032.   //only invoke callback if event conversion was successful
  1033.   if(_convertEvent(*e_sdl, e_kit)  &&  callback != nullptr){
  1034.     try {
  1035.       callback(e_kit, userdata);
  1036.  
  1037.     } catch(const char* errortext){
  1038.       kit_LogError("IN EVENTWATCH CALLBACK: \"%s\"", errortext);
  1039.       freeThreadErrors();
  1040.  
  1041.     }
  1042.  
  1043.   }
  1044.  
  1045.   return 0;
  1046.  
  1047. }
  1048.  
  1049.  
  1050.  
  1051.  
  1052.  
  1053. EventWatch::EventWatch(EventWatchCallback callback, void* userdata,
  1054.                        EventWatchDestructorCallback onDestruction)
  1055. {
  1056.   _type = KIT_CLASSTYPE_EVENTWATCH;
  1057.  
  1058.   if(callback == nullptr)
  1059.     THROW_ERROR("EventWatch::EventWatch(): callback = nullptr");
  1060.  
  1061.   _callback      = callback;
  1062.   _userdata      = userdata;
  1063.   _onDestruction = onDestruction;
  1064.  
  1065.   SDL_AddEventWatch(_EventWatchCallbackWrapper, this);
  1066.  
  1067.   _valid = true;
  1068.   _constructing = false;
  1069.  
  1070. }
  1071.  
  1072.  
  1073.  
  1074.  
  1075. EventWatch::~EventWatch(){
  1076.   if(!_valid) return;
  1077.   _valid = false;
  1078.  
  1079.   SDL_DelEventWatch(_EventWatchCallbackWrapper, this);
  1080.  
  1081.   if(_onDestruction != nullptr)
  1082.     _onDestruction(_userdata);
  1083.  
  1084. }
  1085.  
  1086.  
  1087.  
  1088.  
  1089.  
  1090. }; /* namespace kit */
  1091.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement