Advertisement
Kitomas

_kit_kmixerVoicePrivate.h as of 2023-10-05

Oct 6th, 2023
1,217
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.51 KB | None | 0 0
  1. #ifndef _KIT_KMIXERVOICEPRIVATE_H
  2. #define _KIT_KMIXERVOICEPRIVATE_H
  3.  
  4.  
  5. #include "../../include/kit_sdl2/kit_core.h"
  6. #include "_kit_kmixerPrivate.h"
  7.  
  8. #ifdef __cplusplus
  9. extern "C" {
  10. #endif
  11.  
  12.  
  13.  
  14.  
  15. typedef union {
  16.   void*           v;
  17.   _mono_samples   m;
  18.   _stereo_samples s;
  19. } _kit_kmixerVoiceBuffer;
  20.  
  21. typedef union {
  22.   void*                v;
  23.   float*               m;
  24.   _stereo_samples_f32* s;
  25. } _kit_kmixerVoiceBufferF;
  26.  
  27.  
  28. typedef struct _kit_kmixerVoice _kit_kmixerVoice;
  29. struct _kit_kmixerVoice { //128B
  30.   //(lock is compared with NULL to check if voice is valid)
  31.   SDL_mutex*           lock; //to make sure a voice doesn't get deleted while it's processing
  32.   kit_coreVector*    inputs; //list of input voice indexes, if any (can be NULL)
  33.   kit_coreVector* inputRefs; //list of input voice references, if any (can be NULL)
  34.   _kit_kmixerVoice*  output; //reference to output voice struct
  35.  
  36.   _kit_kmixerVoiceBufferF   bufferInput; //input buffer (aka the mixing stage's output)
  37.   _kit_kmixerVoiceBuffer     bufferUser; //buffer to be filled in or modified by the user
  38.   _kit_kmixerVoiceBufferF bufferConvert; //sometimes used for buffer conversion (always stereo size)
  39.   _kit_kmixerVoiceBufferF  bufferOutput; //final output buffer (aka a mixing stage input)
  40.  
  41.   kit_kmixerVoiceSpec  spec; //contains info for bufferUser, given by the user
  42.  
  43.   Uint32         chainStage; //the voice's current position in the processing chain
  44.   Uint32              index; //index of this specific voice in the device's voice list
  45.  
  46.   //volume can actually be <0, but for volL it will override applyVolume to SDL_FALSE,
  47.    //and for volR, volR would then be set to volL
  48.   float                volL; //left ear volume (or total volume if mono); 0.0 -> 1.0
  49.   float                volR; //right ear volume (ignored if mono); 0.0 -> 1.0
  50.  
  51.   SDL_bool      applyVolume; //if SDL_TRUE, apply volume when mixing voice's output
  52.   SDL_bool     stereoOutput; //output is mono if SDL_FALSE, stereo if SDL_TRUE
  53. };
  54.  
  55.  
  56.  
  57. extern int _kit_kmixerVoiceProc(void* data);
  58.  
  59.  
  60. extern void _kit_kmixerVoiceMix(_kit_kmixerVoice* voiceO);
  61.  
  62.  
  63. extern SDL_bool _kit_kmixerDeviceOrdUnitCallback(void* unit, Uint32 size);
  64.  
  65.  
  66.  
  67.  
  68. //output voice is locked here
  69. static inline int _kit_kmixerVoiceRemoveInput(_kit_kmixerVoice* voiceO,
  70.                                               Uint32 indexI)
  71. {
  72.   _IF_GOTO_ERROR(SDL_LockMutex(voiceO->lock),;)
  73.  
  74.   Uint32*               oinputs = voiceO->inputs->data;
  75.   _kit_kmixerVoice** oinputRefs = voiceO->inputRefs->data;
  76.   Uint32            oinputs_len = voiceO->inputs->x;
  77.  
  78.  
  79.   //remove input from output voice's input list
  80.   for(Uint32 i=0; i<oinputs_len; ++i){
  81.     if(oinputs[i] == indexI){
  82.       oinputs[i] = 0;
  83.       oinputRefs[i] = NULL;
  84.       break;
  85.     }
  86.   }
  87.  
  88.  
  89.   //trim input list(s) to make sure only active inputs are included
  90.   _IF_GOTO_ERROR(kit_coreVectorTrim(&voiceO->inputs,'x',NULL),;)
  91.   _IF_GOTO_ERROR(kit_coreVectorTrim(&voiceO->inputRefs,'x',NULL),;)
  92.   if(!voiceO->inputs->lens[0]){ //destroy input(Ref)s if all inputs have been removed
  93.     kit_coreVectorDestroy(&voiceO->inputs);
  94.     kit_coreVectorDestroy(&voiceO->inputRefs);
  95.   }
  96.  
  97.  
  98.   _IF_GOTO_ERROR(SDL_UnlockMutex(voiceO->lock),;)
  99.  
  100.   /*!err*/ return  0;
  101.   _error_: return -1;
  102. }
  103.  
  104.  
  105.  
  106. //output is also locked here
  107. static inline int _kit_kmixerVoiceAddInput(_kit_kmixerVoice* voiceO,
  108.                                            _kit_kmixerVoice* voiceI)
  109. {
  110.   _IF_GOTO_ERROR(SDL_LockMutex(voiceO->lock),;)
  111.  
  112.  
  113.   if(voiceO->inputs == NULL){ //if inputs == NULL, inputRefs should also be NULL
  114.     voiceO->inputs = kit_coreVectorCreate(1,1,1, sizeof(Uint32),0);
  115.     voiceO->inputRefs = kit_coreVectorCreate(1,1,1, sizeof(_kit_kmixerVoice*),0);
  116.     _IF_GOTO_ERROR(voiceO->inputs==NULL,;)
  117.     _IF_GOTO_ERROR(voiceO->inputRefs==NULL,;)
  118.   }
  119.  
  120.  
  121.   //insert the input's index and reference into output
  122.   Uint32 indexI = voiceI->index;
  123.   _IF_GOTO_ERROR(kit_coreVectorInsert(&voiceO->inputs, &indexI, 0,0, NULL)==U32_MAX,;)
  124.   _IF_GOTO_ERROR(kit_coreVectorInsert(&voiceO->inputRefs, &voiceI, 0,0, NULL)==U32_MAX,;)
  125.  
  126.  
  127.   _IF_GOTO_ERROR(SDL_UnlockMutex(voiceO->lock),;)
  128.  
  129.   /*!err*/ return  0;
  130.   _error_: return -1;
  131. }
  132.  
  133.  
  134.  
  135.  
  136. static inline int _kit_kmixerVoiceAddFillSpec(kit_kmixerDevice* device,
  137.                                               kit_kmixerVoiceSpec* vspec)
  138. {
  139.   _kit_kmixerVoice* voice0 = device->_voices.raw->data;
  140.  
  141.  
  142.   vspec->freq    = voice0->spec.freq;
  143.   vspec->samples = voice0->spec.samples;
  144.   vspec->_size   = voice0->spec.samples<<vspec->stereo;
  145.  
  146.   switch(vspec->format){
  147.   case AUDIO_F32:                    SDL_FALLTHROUGH;
  148.   case AUDIO_S32: vspec->_size *= 2; SDL_FALLTHROUGH;
  149.   case AUDIO_S16: vspec->_size *= 2; SDL_FALLTHROUGH;
  150.   case AUDIO_U8 : break;
  151.   default: _IS_SDLERR(;,"spec's format is invalid"); }
  152.  
  153.  
  154.   /*!err*/ return  0;
  155.   _error_: return -1;
  156. }
  157.  
  158.  
  159.  
  160. static inline int _kit_kmixerVoiceAddFillVoice(kit_kmixerVoiceSpec* vspec,
  161.                                                _kit_kmixerVoice* voiceO,
  162.                                                _kit_kmixerVoice* voiceI)
  163. {
  164.   kit_coreMemset(voiceI, 0, sizeof(_kit_kmixerVoice));
  165.  
  166.   Uint32 stereo_f32_size   = sizeof(float)*vspec->samples*2;
  167.   Uint32 bufferUser_size   = vspec->_size;
  168.   Uint32 bufferOutput_size = (sizeof(float)*vspec->samples)<<voiceO->spec.stereo;
  169.  
  170.  
  171.   voiceI->lock = SDL_CreateMutex();
  172.   _IF_GOTO_ERROR(voiceI->lock==NULL,;)
  173.  
  174.   voiceI->inputs    = NULL; //created when the first input is added
  175.   voiceI->inputRefs = NULL;
  176.   voiceI->output    = voiceO;
  177.  
  178.   voiceI->bufferInput.v   = SDL_malloc(stereo_f32_size);
  179.   voiceI->bufferUser.v    = SDL_malloc(bufferUser_size);
  180.   voiceI->bufferConvert.v = SDL_malloc(stereo_f32_size);
  181.   voiceI->bufferOutput.v  = SDL_malloc(bufferOutput_size);
  182.  
  183.   voiceI->spec = *vspec;
  184.  
  185.   //set chain processing stage one higher,
  186.    //to ensure this voice is processed before the output
  187.   voiceI->chainStage = voiceO->chainStage+1;
  188.   //(voiceI->index is handled later inside VoiceAdd)
  189.  
  190.   voiceI->volL = 1.0f;
  191.   voiceI->volR = (voiceI->spec.stereo) ? 1.0f : -1.0f;
  192.  
  193.   voiceI->applyVolume  = SDL_TRUE;
  194.   voiceI->stereoOutput = voiceO->spec.stereo;
  195.  
  196.  
  197.   /*!err*/ return  0;
  198.   _error_: return -1;
  199. }
  200.  
  201.  
  202.  
  203.  
  204. static inline void _kit_kmixerVoiceRemoveFromOrd(kit_kmixerDevice* device,
  205.                                                  _kit_kmixerVoice* voiceI)
  206. {
  207.   kit_coreVector** ord_p = &device->_voices.ord;
  208.  
  209.   Uint32 index = voiceI->index;
  210.   Uint32 chainStage = voiceI->chainStage;
  211.   _kit_kmixerVoice** chainRefs = &VECTOR_INDEX_A(_kit_kmixerVoice*, *ord_p, 0,chainStage,0);
  212.   Uint32 stageLen = VECTOR_LENS_A(*ord_p, chainStage,0);
  213.  
  214.   //do a linear search through the voice's chain stage...
  215.   for(Uint32 i=0; i<stageLen; ++i){
  216.     if(chainRefs[i]->index == index){
  217.       chainRefs[i] = NULL; //...setting the reference to NULL if found
  218.       break;
  219.     }
  220.   }
  221. }
  222.  
  223.  
  224.  
  225. static inline int _kit_kmixerVoiceAddToOrd(kit_kmixerDevice* device,
  226.                                            _kit_kmixerVoice* voiceI)
  227. {
  228.   Uint32 chainStage = voiceI->chainStage;
  229.   kit_coreVector** ord_p = &device->_voices.ord;
  230.   if(chainStage >= (*ord_p)->y){ //extend ord to accomodate new chain stage
  231.     _IF_GOTO_ERROR(kit_coreVectorSet(ord_p, 0,chainStage+1,0),;)
  232.   }
  233.  
  234.   _IF_GOTO_ERROR(kit_coreVectorInsert(ord_p, &voiceI, chainStage,0,
  235.                                       _kit_kmixerDeviceOrdUnitCallback)==U32_MAX,;)
  236.  
  237.   /*!err*/ return  0;
  238.   _error_: return -1;
  239. }
  240.  
  241.  
  242.  
  243.  
  244. #ifdef __cplusplus
  245. }
  246. #endif
  247.  
  248. #endif /* _KIT_KMIXERVOICEPRIVATE_H */
  249.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement