Advertisement
Kitomas

_kit_kmixerDevicePrivate.h as of 2023-10-12

Oct 12th, 2023
857
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.55 KB | None | 0 0
  1. #ifndef _KIT_KMIXERDEVICEPRIVATE_H
  2. #define _KIT_KMIXERDEVICEPRIVATE_H
  3.  
  4.  
  5. #include "../../include/kit_sdl2/kit_kmixer.h"
  6. #include "_kit_privmacro.h"
  7. #include "_kit_kmixerVoicePrivate.h"
  8.  
  9. #ifdef __cplusplus
  10. extern "C" {
  11. #endif
  12.  
  13.  
  14.  
  15.  
  16. #define _DEV_MAGIC_NUM (0x0076654472786D6B) //="kmxrDev\x00"
  17. #define _DEVICE_VALIDITY_CHECK(_nullDeviceAllowed) {                       \
  18.   if(_nullDeviceAllowed){ _IF_GOTO(device==NULL,_noerr_,;) }               \
  19.   else { _IF_SDLERR(device==NULL,;,"device cannot be NULL") }              \
  20.   _IF_SDLERR(device->_magic.num!=_DEV_MAGIC_NUM,;,"invalid device struct") }
  21.  
  22.  
  23.  
  24.  
  25. extern void _kit_kmixerDeviceDoTasks(SDL_ThreadFunction task, kit_coreVector* threads_v,
  26.                                                               kit_coreVector* threadData_v);
  27.  
  28. extern int _kit_kmixerDevicePauseThread(void* data);
  29.  
  30. extern void _kit_kmixerDeviceCallback(void* userdata, Uint8* _stream, int len);
  31.  
  32.  
  33.  
  34.  
  35. static inline void _kit_kmixerDeviceMixThreads(kit_kmixerDevice* device,
  36.                                                _kit_kmixerVoice** voiceRefs,
  37.                                                Uint32 stageVoiceLen)
  38. {
  39.   kit_coreVector* threadData_v   = device->_threadData;
  40.   void**          threadData     = threadData_v->data;
  41.   Uint32          threadData_len = 0; //incremented as data is added
  42.  
  43.  
  44.   for(Uint32 vi=0; vi<stageVoiceLen; ++vi){
  45.     _kit_kmixerVoice* voice = voiceRefs[vi];
  46.     if(voice==NULL || voice->lock==NULL) continue; //skip if voice is completely invalid
  47.  
  48.     //only add the voice to the data queue if it actually has inputs
  49.     if(voice->inputs != NULL) threadData[threadData_len++] = voice;
  50.  
  51.   }
  52.  
  53.  
  54.   VECTOR_LENS_A(threadData_v, 0,0) = threadData_len; //update length to new value
  55.   _kit_kmixerDeviceDoTasks(_kit_kmixerVoiceMix, device->_threads, threadData_v);
  56. }
  57.  
  58.  
  59.  
  60. static inline void _kit_kmixerDeviceProcThreads(kit_kmixerDevice* device,
  61.                                                 _kit_kmixerVoice** voiceRefs,
  62.                                                 Uint32 stageVoiceLen)
  63. {
  64.   kit_coreVector* threadData_v   = device->_threadData;
  65.   void**          threadData     = threadData_v->data;
  66.   Uint32          threadData_len = 0; //incremented as data is added
  67.  
  68.  
  69.   for(Uint32 vi=0; vi<stageVoiceLen; ++vi){
  70.     _kit_kmixerVoice* voice = voiceRefs[vi];
  71.     if(voice==NULL || voice->lock==NULL) continue; //skip if voice is completely invalid
  72.  
  73.     //only add the voice to the data queue if it's not voice 0
  74.     if(voice->output != U32_MAX) threadData[threadData_len++] = voice;
  75.  
  76.   }
  77.  
  78.  
  79.   VECTOR_LENS_A(threadData_v, 0,0) = threadData_len; //update length to new value
  80.   _kit_kmixerDeviceDoTasks(_kit_kmixerVoiceProc, device->_threads, threadData_v);
  81. }
  82.  
  83.  
  84.  
  85.  
  86. //assumes device is already locked
  87. static inline void _kit_kmixerDeviceStereoFade(kit_kmixerDevice* device,
  88.                                                kit_acodecPCM_F32S* stream,
  89.                                                int len)
  90. {
  91.   //get values from device itself
  92.   float  fadeDelta   = device->_fadeDelta;
  93.   float  fadeVolume  = device->_fadeVolume;
  94.   Uint32 fadeInDelay = device->_fadeInDelay;
  95.  
  96.   Uint32 i = 0; //this index is shared, as the loops can jump to others at will
  97.  
  98.  
  99.   //FADING OUT
  100.   if(device->_fadeOut){
  101.     _do_fade_out:
  102.     for(; i<len; ++i){
  103.       if(!device->_fadeOut) goto _do_fade_in;
  104.       stream[i].l *= fadeVolume;
  105.       stream[i].r *= fadeVolume;
  106.       fadeVolume = MAX(fadeVolume-fadeDelta,0);
  107.     }
  108.     //trigger pause thread if fade out is complete
  109.     if(fadeVolume <= 0.0f){
  110.       SDL_Thread* pauseThread = SDL_CreateThread(_kit_kmixerDevicePauseThread,"_PauseTh", device);
  111.       //setting _fadeInDelay to -1 will cause further calls to the device callback
  112.        //to simply memset 0 until kit_kmixerDevicePlay is called again
  113.       if(pauseThread == NULL) device->_fadeInDelay = -1; //0xffffffff
  114.       else SDL_DetachThread(pauseThread); //make sure thread cleans up when finished
  115.     }
  116.  
  117.   //FADING IN
  118.   } else if(fadeVolume < 1.0f){
  119.     //let device warm up before fading in
  120.     for(; (fadeInDelay)&&(i<len); ++i){ //write 0s for fadeInDelaySeconds
  121.       stream[i].l=stream[i].r = 0; --fadeInDelay;
  122.     }
  123.     _do_fade_in:
  124.     for(; i<len; ++i){
  125.       if(device->_fadeOut) goto _do_fade_out;
  126.       else if(fadeVolume >= 1.0f){ fadeVolume = 1.0f; break; }
  127.       stream[i].l *= fadeVolume;
  128.       stream[i].r *= fadeVolume;
  129.       fadeVolume += fadeDelta;
  130.     }
  131.  
  132.   }
  133.  
  134.  
  135.   //update device struct to any relevant new values
  136.   device->_fadeVolume  = fadeVolume;  //update fade volume
  137.   device->_fadeInDelay = fadeInDelay; //update fade in delay
  138. }
  139.  
  140.  
  141.  
  142. //also assumes device is already locked
  143. static inline void _kit_kmixerDeviceMonoFade(kit_kmixerDevice* device,
  144.                                              float* stream, int len)
  145. {
  146.   //get values from device itself
  147.   float  fadeDelta   = device->_fadeDelta;
  148.   float  fadeVolume  = device->_fadeVolume;
  149.   Uint32 fadeInDelay = device->_fadeInDelay;
  150.  
  151.   Uint32 i = 0; //this index is shared, as the loops can jump to others at will
  152.  
  153.  
  154.   //FADING OUT
  155.   if(device->_fadeOut){
  156.     _do_fade_out:
  157.     for(; i<len; ++i){
  158.       if(!device->_fadeOut) goto _do_fade_in;
  159.       stream[i] *= fadeVolume;
  160.       fadeVolume = MAX(fadeVolume-fadeDelta,0);
  161.     }
  162.     //trigger pause thread if fade out is complete
  163.     if(fadeVolume <= 0.0f){
  164.       SDL_Thread* pauseThread = SDL_CreateThread(_kit_kmixerDevicePauseThread,"_PauseTh", device);
  165.       //setting _fadeInDelay to -1 will cause further calls to the device callback
  166.        //to simply memset 0 until kit_kmixerDevicePlay is called again
  167.       if(pauseThread == NULL) device->_fadeInDelay = -1; //0xffffffff
  168.       else SDL_DetachThread(pauseThread); //make sure thread cleans up when finished
  169.     }
  170.  
  171.   //FADING IN
  172.   } else if(fadeVolume < 1.0f){
  173.     //let device warm up before fading in
  174.     for(; (fadeInDelay)&&(i<len); ++i){ //write 0s for fadeInDelaySeconds
  175.       stream[i] = 0; --fadeInDelay;
  176.     }
  177.     _do_fade_in:
  178.     for(; i<len; ++i){
  179.       if(device->_fadeOut) goto _do_fade_out;
  180.       else if(fadeVolume >= 1.0f){ fadeVolume = 1.0f; break; }
  181.       stream[i] *= fadeVolume;
  182.       fadeVolume += fadeDelta;
  183.     }
  184.  
  185.   }
  186.  
  187.  
  188.   //update device struct to any relevant new values
  189.   device->_fadeVolume  = fadeVolume;  //update fade volume
  190.   device->_fadeInDelay = fadeInDelay; //update fade in delay
  191. }
  192.  
  193.  
  194.  
  195.  
  196. static inline SDL_AudioSpec _kit_kmixerDeviceVoiceToAudioSpec(kit_kmixerDevice* device,
  197.                                                               const kit_kmixerVoiceSpec* vspec)
  198. {
  199.   SDL_AudioSpec aspec;
  200.   SDL_bool success = SDL_FALSE;
  201.  
  202.   aspec.freq     = vspec->freq;
  203.   aspec.format   = AUDIO_F32;
  204.   aspec.channels = 1+(vspec->stereo&1);
  205.   aspec.samples  = vspec->samples;
  206.   aspec.callback = _kit_kmixerDeviceCallback;
  207.   aspec.userdata = device;
  208.  
  209.   //assuming 44.1kHz, <=16 sample frames would be well under 1ms lol
  210.    //(even at 8kHz, it would still only be 2ms)
  211.   _IF_SDLERR(aspec.samples<32,;,"samples < 32")
  212.   _IF_SDLERR(count_bits(aspec.samples)>1,;,"samples not a power of 2")
  213.  
  214.   success = SDL_TRUE;
  215.   _error_:
  216.   if(!success) aspec.format = 0; //used to check for failure inside DeviceOpen
  217.   return aspec;
  218. }
  219.  
  220.  
  221.  
  222.  
  223. static inline int _kit_kmixerDeviceFillVoice0(kit_kmixerDevice* device,
  224.                                               kit_kmixerVoiceSpec* vspec)
  225. {
  226.   _kit_kmixerVoice* raw = device->_raw->data;
  227.   SDL_bool stereo = vspec->stereo&1;
  228.   Uint32 bufferSize = (sizeof(float)*vspec->samples)<<stereo;
  229.  
  230.  
  231.   raw->lock=SDL_CreateMutex();
  232.   _IF_GOTO_ERROR(raw->lock==NULL,;)
  233.  
  234.   raw->inputs    =    NULL; //created when a voice gets added
  235.   raw->device    =  device; //lol
  236.   raw->output    = U32_MAX; //unused for voice 0
  237.  
  238.   raw->timeStamp = SDL_GetTicks();
  239.  
  240.    //(voice 0's bufferInput is copied to device callback's _stream)
  241.   raw->bufferInput.data   = SDL_malloc(bufferSize);
  242.   raw->bufferUser.data    = NULL; //unused for voice 0
  243.   raw->bufferConvert.data = NULL; //unused for voice 0
  244.   raw->bufferOutput.data  = NULL; //unused for voice 0
  245.   _IF_SDLERR(raw->bufferInput.data==NULL,;,"!voice 0 bufferInput")
  246.  
  247.  
  248.   //copy voice spec info
  249.   raw->spec        = *vspec;
  250.    //(these two members are exceptions)
  251.   raw->spec._size  = bufferSize;
  252.   raw->spec.format = AUDIO_F32;
  253.  
  254.  
  255.   raw->chainStage = 0;
  256.   raw->index      = 0;
  257.  
  258.   raw->volL = 1.0f;
  259.   raw->volR = (stereo) ? 1.0f : -1.0f;
  260.  
  261.   raw->stereoOutput = stereo;
  262.  
  263.  
  264.   /*!err*/ return  0;
  265.   _error_: return -1;
  266. }
  267.  
  268.  
  269.  
  270.  
  271. #ifdef __cplusplus
  272. }
  273. #endif
  274.  
  275. #endif /* _KIT_KMIXERDEVICEPRIVATE_H */
  276.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement