Advertisement
Kitomas

sfx_callback.cpp as of 2023-12-15

Dec 15th, 2023
897
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.22 KB | None | 0 0
  1. #include "_sfx.hpp"
  2.  
  3.  
  4.  
  5.  
  6. int _sfx_auxCallbackHandler(void* data){
  7.   sfx_class* sfx = (sfx_class*)data;
  8.   std::vector<char>* _stream = sfx->_getAuxStream();
  9.  
  10.   sfx_auxCallback callback = sfx->getAuxCallback();
  11.   void*           userdata = sfx->_getAuxUserdata();
  12.   void*       _stream_data = (void*)_stream->data();
  13.   int         _stream_size = (int)_stream->size();
  14.  
  15.   callback(userdata, _stream_data, _stream_size);
  16.  
  17.   return 0;
  18. }
  19.  
  20.  
  21.  
  22. //workaround for having _sfx_callback pause the device,
  23.  //without having to call SDL_PauseAudioDevice inside the callback itself
  24. int _sfx_pauseThread(void* data){
  25.   sfx_class* sfx = (sfx_class*)data;
  26.   if(sfx->isClosing()) return 0;
  27.   sfx->lockDevice(true);
  28.  
  29.   //might cause problems if sfx is dangling for whatever reason
  30.   try {
  31.     sfx->lock(true);
  32.   } catch(...){
  33.     sfx->lockDevice(false);
  34.     sfx->_getFadeInDelay() = 0xffffffff; //this should work, right?
  35.     return -1;
  36.   }
  37.  
  38.   //make sure current buffer finishes playing
  39.   float bufferLengthSeconds = (float)sfx->getBufferLength() / sfx->getSampleRate();
  40.   SDL_Delay(bufferLengthSeconds*1000 + 10); //+10ms just to be sure
  41.  
  42.   SDL_PauseAudioDevice(sfx->getDeviceID(),1);
  43.   sfx->_setPlaying(false);
  44.  
  45.   sfx->lockDevice(false);
  46.   sfx->lock(false);
  47.   return 0;
  48. }
  49.  
  50.  
  51.  
  52. void _sfx_callback(void* userdata, Uint8* _stream, int size){
  53.   sfx_class*   sfx = (sfx_class*)userdata;
  54.   sfx_f32s* stream = (sfx_f32s*)_stream;
  55.   int          len = size/sizeof(sfx_f32s);
  56.  
  57.   size_t numTracks = sfx->getNumTracks();
  58.   std::vector<sfx_track>& tracks = sfx->_getTracks();
  59.   Uint64 timeStampEnd = sfx->getTimeStampEnd();
  60.   SDL_Thread* auxCallbackThread = nullptr;
  61.  
  62.   sfx->_setTimeStampStart();
  63.   SDL_memset(stream,0,size); //stream must be filled no matter what
  64.   if(sfx->isClosing()) goto _skip_everything_; //if device is closing, exit early
  65.  
  66.   //if previous attempt to pause sfx failed, exit early
  67.   try {
  68.     sfx->lock(true);
  69.   } catch(...){
  70.     sfx->_getFadeInDelay() = 0xffffffff;
  71.     goto _skip_everything_;
  72.   }
  73.   if(sfx->_getFadeInDelay() == 0xffffffff) goto _unlock_device_;
  74.   if(sfx->_getTracksPtr() == nullptr) goto _unlock_device_;
  75.  
  76.  
  77.   //start auxillary callback handler thread, if aux callback is present
  78.   if(sfx->getAuxCallback() != nullptr){
  79.     auxCallbackThread = SDL_CreateThread(_sfx_auxCallbackHandler, "auxCH_Th", sfx);
  80.     //if(auxCallbackThread == nullptr) SDL_LogError()
  81.   }
  82.  
  83.  
  84.   //mix sound effect tracks
  85.   for(size_t ti=0; ti<numTracks; ++ti){
  86.     if(tracks[ti].pcm != nullptr){
  87.       _sfx_mixTrack(tracks[ti],
  88.                     timeStampEnd,
  89.                     stream, len);
  90.     }
  91.   }
  92.  
  93.  
  94.   //wait for auxCallbackThread to finish
  95.    //(passing auxCallbackThread as nullptr is safe here)
  96.   SDL_WaitThread(auxCallbackThread, nullptr);
  97.  
  98.   //mix output of auxillary callback, if enabled
  99.   if(auxCallbackThread != nullptr){
  100.     std::vector<char>* auxStream   = sfx->_getAuxStream();
  101.     SDL_AudioFormat    auxFormat   = sfx->getAuxFormat();
  102.     Uint16             auxChannels = sfx->getAuxChannels();
  103.  
  104.     if(auxStream != nullptr){
  105.       _every_sample_type auxSmp = { .data = auxStream->data() };
  106.       if(( auxStream->size()/((auxFormat&255)/8)/auxChannels ) == (unsigned)len){
  107.         switch(_FORMAT_SWITCH(auxChannels,auxFormat)){ //convert format and data type when mixing
  108.         case fmt_u8  : for(int i=0; i<len; ++i) stream[i] += auxSmp.u8  [i];  break;
  109.         case fmt_i16 : for(int i=0; i<len; ++i) stream[i] += auxSmp.i16 [i];  break;
  110.         case fmt_f32 : for(int i=0; i<len; ++i) stream[i] += auxSmp.f32 [i];  break;
  111.         case fmt_u8s : for(int i=0; i<len; ++i) stream[i] += auxSmp.u8s [i];  break;
  112.         case fmt_i16s: for(int i=0; i<len; ++i) stream[i] += auxSmp.i16s[i];  break;
  113.         case fmt_f32s: for(int i=0; i<len; ++i) stream[i] += auxSmp.f32s[i];  break;
  114.         default: ;//SDL_LogError();
  115.         }
  116.  
  117.       } //else SDL_LogError();
  118.     } //else SDL_LogError();
  119.   }
  120.  
  121.  
  122.   //apply linear fade to reduce popping when pausing and unpausing the device
  123.    //(also apply global volume, hard clipping, and pan)
  124.   _sfx_globalFade(sfx, stream, len);
  125.  
  126.   _unlock_device_  : try { sfx->lock(false); } catch(...){} //just in case
  127.   _skip_everything_: sfx->_setTimeStampEnd();
  128. }
  129.  
  130.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement