Advertisement
Kitomas

kit_sdl2_kmixerVoice.c as of 2023-10-05

Oct 6th, 2023
997
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 27.87 KB | None | 0 0
  1. #include "../include/kit_sdl2/kit_kmixer.h"
  2. #include "../_private/include/_kit_privmacro.h"
  3. #include "../_private/include/_kit_kmixerAllPrivate.h"
  4.  
  5. /* example of simd stereo to mono without sse3's hadd
  6. static inline void _sse1_s_to_m(float* dst, __m128 vector){
  7.   __m128 shuffled = _mm_shuffle_ps(vector,vector, _MM_SHUFFLE(2,3,0,1));
  8.   __m128 sum = _mm_add_ps(vector,shuffled);
  9.   __m128 result = _mm_shuffle_ps(sum,sum, _MM_SHUFFLE(3,1,2,0));
  10.   _mm_storel_pi((__m64*)dst,result);
  11. }
  12. */
  13.  
  14.  
  15. //for visual clarity during ProcChannels
  16.  //(this could also just be an enum probably, but w/e)
  17. #define _M_to_M (0) //  mono->mono
  18. #define _M_to_S (1) //  mono->stereo
  19. #define _S_to_M (2) //stereo->mono
  20. #define _S_to_S (3) //stereo->stereo
  21. /* i think i need to fix this
  22. #define _MM256_SHUFFLE(c7,c6,c5,c4,c3,c2,c1,c0) \
  23.   ((_MM_SHUFFLE(c7,c6,c5,c4)<<8)|_MM_SHUFFLE(c3,c2,c1,c0)) */
  24.  
  25.  
  26.  
  27. //converts u8, i16, and i32 samples to f32 samples
  28.  //(will basically just copy input to output if input is also f32)
  29. static inline void _kit_kmixerVoiceProcFromTypeFallback(void* _dataIn, float* dataOut,
  30.                                                         Uint32 numSamples, SDL_AudioFormat typeIn)
  31. { //if nothing else works
  32.   _mono_samples dataIn = { .ptr = _dataIn };
  33.   float rawSample; //used for max(original_sample,-1) basically
  34.   switch(typeIn){
  35.   case AUDIO_U8 : for(Uint32 i=0; i<numSamples; ++i){ rawSample = (float)(dataIn.u_8[i]-0x80)*invi_8;
  36.                                                       dataOut[i] = (rawSample>=-1.0f)?rawSample:-1.0f; } break;
  37.   case AUDIO_S16: for(Uint32 i=0; i<numSamples; ++i){ rawSample = (float) dataIn.i16[i]      *invi16;
  38.                                                       dataOut[i] = (rawSample>=-1.0f)?rawSample:-1.0f; } break;
  39.   case AUDIO_S32: for(Uint32 i=0; i<numSamples; ++i){ rawSample = (float) dataIn.i32[i]      *invi32;
  40.                                                       dataOut[i] = (rawSample>=-1.0f)?rawSample:-1.0f; } }
  41.   //('from f32' is skipped inside VoiceProc, thus this code would never run)
  42.   //case AUDIO_F32: for(Uint32 i=0; i<numSamples; ++i){ dataOut[i] =       dataIn.f32[i];               } }
  43. }
  44. void _kit_kmixerVoiceProcFromType(void* dataIn, void* dataOut,
  45.                                   Uint32 sampleFrames, SDL_AudioFormat typeIn, SDL_bool isStereo)
  46. {
  47.   Uint32 numSamples = sampleFrames<<isStereo;
  48.   _kit_kmixerVoiceProcFromTypeFallback(dataIn,dataOut,numSamples,typeIn);
  49. }
  50.  
  51.  
  52.  
  53.  
  54. //converts f32 samples to u8, i16, and i32 samples
  55. static inline void _kmixerVoiceProcToTypeFallback(float* dataIn, void* _dataOut,
  56.                                                   Uint32 numSamples, SDL_AudioFormat typeOut)
  57. { //if nothing else works
  58.   _mono_samples dataOut = { .ptr = _dataOut };
  59.   float rawSample, rawSampleB;
  60.   switch(typeOut){
  61.   case AUDIO_U8 : for(Uint32 i=0; i<numSamples; ++i){ rawSample      = dataIn[i];
  62.                                                       rawSampleB     = (rawSample>=-1.0f)?rawSample:-1.0f;
  63.                                                       dataOut.u_8[i] = (rawSampleB<=1.0f)?rawSampleB*I_8_MAX+0x80:I_8_MAX; } break;
  64.   case AUDIO_S16: for(Uint32 i=0; i<numSamples; ++i){ rawSample      = dataIn[i];
  65.                                                       rawSampleB     = (rawSample>=-1.0f)?rawSample:-1.0f;
  66.                                                       dataOut.i16[i] = (rawSampleB<=1.0f)?rawSampleB*I16_MAX:I16_MAX; } break;
  67.   case AUDIO_S32: for(Uint32 i=0; i<numSamples; ++i){ rawSample      = dataIn[i];
  68.                                                       rawSampleB     = (rawSample>=-1.0f)?rawSample:-1.0f;
  69.                                                       dataOut.i32[i] = (rawSampleB<=1.0f)?rawSampleB*I32_MAX:I32_MAX; } break;
  70.   case AUDIO_F32: for(Uint32 i=0; i<numSamples; ++i){ rawSample      = dataIn[i];
  71.                                                       rawSampleB     = (rawSample>=-1.0f)?rawSample:-1.0f;
  72.                                                       dataOut.f32[i] = (rawSampleB<=1.0f)?rawSampleB:1.0f; } }
  73. }
  74. void _kit_kmixerVoiceProcToType(void* dataIn, void* dataOut,
  75.                                 Uint32 sampleFrames, SDL_AudioFormat typeOut, SDL_bool isStereo)
  76. {
  77.   Uint32 numSamples = sampleFrames<<isStereo;
  78.   _kmixerVoiceProcToTypeFallback(dataIn,dataOut,numSamples,typeOut);
  79. }
  80.  
  81.  
  82.  
  83.  
  84. //assumes samples are f32
  85. static inline void _kit_kmixerVoiceProcChannelsFallback(float* dataInM, float* dataOutM,
  86.                                                         Uint32 sampleFrames, int channelInfo)
  87. { //if nothing else works
  88.   _stereo_samples_f32* dataInS  = (void*)dataInM;
  89.   _stereo_samples_f32* dataOutS = (void*)dataOutM;
  90.   switch(channelInfo){
  91.   case _M_to_S: for(Uint32 i=0; i<sampleFrames; ++i){ dataOutS[i].l=dataOutS[i].r = dataInM[i]; } break;
  92.   case _S_to_M: for(Uint32 i=0; i<sampleFrames; ++i){ dataOutM[i] = (dataInS[i].l+dataInS[i].r)*.5f; } break;
  93.   case _S_to_S: sampleFrames<<=1; SDL_FALLTHROUGH; //multiply mono by 2 to make length of stereo
  94.   case _M_to_M: for(Uint32 i=0; i<sampleFrames; ++i){ dataOutM[i] = dataInM[i]; }
  95.   }
  96. }
  97. void _kit_kmixerVoiceProcChannels(void* dataIn, void* dataOut, Uint32 sampleFrames, int channelInfo){
  98.   _kit_kmixerVoiceProcChannelsFallback(dataIn,dataOut, sampleFrames,channelInfo);
  99. }
  100.  
  101.  
  102.  
  103.  
  104. #define _CH_INFO(a,b) (((a)<<1)|(b))
  105. //assumes input AND output samples are f32 (intermediate type is determined by the given voice)
  106. int _kit_kmixerVoiceProc(void* data){ //(this is an SDL_ThreadFunction)
  107.   _kit_kmixerVoice* voice = data;
  108.   if(voice->lock == NULL) return -1;
  109.   SDL_LockMutex(voice->lock);
  110.  
  111.  
  112.   void *ibuffer = voice->bufferInput.v,  *obuffer = voice->bufferOutput.v;
  113.   void *ubuffer = voice->bufferUser.v,  *cbuffer = voice->bufferConvert.v;
  114.   void *userdata = voice->spec.userdata,  *_stream = ubuffer;
  115.    ///
  116.   SDL_bool hasInput = voice->inputs!=NULL;
  117.   SDL_bool ustereo = voice->spec.stereo;
  118.   SDL_bool ostereo = voice->stereoOutput;
  119.    ///
  120.   SDL_AudioFormat uformat = voice->spec.format;
  121.   Uint32 frames = voice->spec.samples,  ubuffer_size = voice->spec._size;
  122.  
  123.  
  124.   //convert (if necessary) input type (format) from f32
  125.   int userTypeIsF32 = uformat==AUDIO_F32;
  126.   if(userTypeIsF32) _stream = ibuffer; //input and user are identical; just reroute
  127.   else _kit_kmixerVoiceProcToType(ibuffer, ubuffer, frames,uformat,ustereo);
  128.  
  129.   //the actual user callback
  130.   voice->spec.callback(userdata, _stream, ubuffer_size, hasInput);
  131.  
  132.   //convert (if necessary) to f32 and channels, sending result to output
  133.   int sameChannels = ustereo==ostereo;
  134.   if(sameChannels){
  135.     //convert type (or just copy contents if _stream is f32)
  136.     _kit_kmixerVoiceProcFromType(_stream,obuffer, frames,uformat,ustereo);
  137.   } else if(userTypeIsF32){ //convert channels
  138.     _kit_kmixerVoiceProcChannels(_stream,obuffer, frames,_CH_INFO(ustereo,ostereo));
  139.   } else { //convert type and channels
  140.     _kit_kmixerVoiceProcFromType(_stream,cbuffer, frames,uformat,ustereo);
  141.     _kit_kmixerVoiceProcChannels(cbuffer,obuffer, frames,_CH_INFO(ustereo,ostereo));
  142.   }
  143.  
  144.  
  145.   SDL_UnlockMutex(voice->lock);
  146.   return 0;
  147. }
  148.  
  149.  
  150.  
  151.  
  152. //assumes all samples are f32
  153. //if nothing else works
  154. static inline void _kit_kmixerVoiceMixFallback(_kit_kmixerVoice* voiceO){
  155.   if(voiceO->lock == NULL) return; //skip in case voice was removed
  156.   SDL_LockMutex(voiceO->lock);
  157.  
  158.   Uint32 frames = voiceO->spec.samples;
  159.    //bad things would happen if input buffer is NULL
  160.   memset(voiceO->bufferInput.v, 0, (frames*sizeof(float))<<voiceO->spec.stereo);
  161.   _stereo_samples_f32* osamples = voiceO->bufferInput.s;
  162.   Uint32 samples_len = frames>>(!voiceO->spec.stereo); //so stereo volume can apply to mono
  163.  
  164.   //do the mixing
  165.   kit_coreVector* inputRefs = voiceO->inputRefs;
  166.   _kit_kmixerVoice** refs = inputRefs->data;
  167.   Uint32 refs_len = inputRefs->x;
  168.   for(Uint32 vi=0; vi<refs_len; ++vi){
  169.     _kit_kmixerVoice* ivoice = refs[vi];
  170.     if(ivoice->lock == NULL) continue; //skip in case voice was removed
  171.     SDL_LockMutex(ivoice->lock);
  172.  
  173.     _stereo_samples_f32* isamples = ivoice->bufferOutput.s;
  174.     float volL = ivoice->volL, volR = ivoice->volR;
  175.  
  176.     volL = MIN(volL,1.0f); volR = MIN(volR, 1.0f);
  177.     if(!ivoice->stereoOutput) volR = volL;
  178.  
  179.     if(volL==0 && volR==0) continue; //if volume is effectively muted, then skip the voice
  180.     else if(volL==1.0f && volR==1.0f) goto _do_not_apply_volume; //because sample*1=sample
  181.     else if((volL>=0) && ivoice->applyVolume){
  182.       if(volR<0) volR = volL;
  183.       for(Uint32 i=0; i<samples_len; ++i){
  184.         osamples[i].l += isamples[i].l*volL;
  185.         osamples[i].r += isamples[i].r*volR;
  186.       }
  187.     } else { _do_not_apply_volume:
  188.       for(Uint32 i=0; i<samples_len; ++i){
  189.         osamples[i].l += isamples[i].l;
  190.         osamples[i].r += isamples[i].r;
  191.       }
  192.     }
  193.  
  194.     SDL_UnlockMutex(ivoice->lock);
  195.   }
  196.  
  197.   //hard clip output samples to between -1.0f and 1.0f
  198.   for(Uint32 i=0; i<samples_len; ++i){
  199.     float sampleL = osamples[i].l;
  200.     float sampleR = osamples[i].r;
  201.     osamples[i].l = CLAMP(sampleL, -1.0f,1.0f);
  202.     osamples[i].r = CLAMP(sampleR, -1.0f,1.0f);
  203.   }
  204.  
  205.   SDL_UnlockMutex(voiceO->lock);
  206. }
  207. void _kit_kmixerVoiceMix(_kit_kmixerVoice* voiceO){
  208.   _kit_kmixerVoiceMixFallback(voiceO);
  209. }
  210.  
  211.  
  212.  
  213.  
  214. //used to check whether an element in the raw voice list is valid or not
  215. SDL_bool _kit_kmixerDeviceRawUnitCallback(void* unit, Uint32 size){
  216.   _kit_kmixerVoice* voice = unit;
  217.   return voice->lock == NULL;
  218. }
  219.  
  220.  
  221.  
  222. //same thing, but with ord instead of raw
  223. SDL_bool _kit_kmixerDeviceOrdUnitCallback(void* unit, Uint32 size){
  224.   _kit_kmixerVoice** voice_p = unit;
  225.   if(*voice_p == NULL) return SDL_TRUE;
  226.   return (*voice_p)->lock == NULL;
  227. }
  228.  
  229.  
  230.  
  231. int kit_kmixerVoiceRemove(kit_kmixerDevice* device, Uint32 voiceID){
  232.   _IF_SDLERR(device==NULL,;,"device cannot be NULL")
  233.   _IF_SDLERR(device->_magic.num!=_DEV_MAGIC_NUM,;,"invalid device struct")
  234.   //only allow voice 0 to be removed when device->_closing is set
  235.   _IF_SDLERR(!voiceID && !device->_closing,;,"cannot remove voice 0")
  236.  
  237.   //if bit 31 is set, call is assumed to be the result of recursion
  238.   SDL_bool rootCall = (!(voiceID&U32_MSb)) ? SDL_TRUE : SDL_FALSE;
  239.   voiceID &= I32_MAX; //unset bit 31 now that rootCall is set
  240.  
  241.  
  242.   kit_coreVector** raw_p = &device->_voices.raw;
  243.   _kit_kmixerVoice* voiceI = &VECTOR_INDEX_C(_kit_kmixerVoice, *raw_p, voiceID);
  244.   _IF_GOTO(voiceI->lock==NULL,_noerr_,;) //return normally if voice already removed
  245.   _IF_GOTO_ERROR(SDL_LockMutex(voiceI->lock),;)
  246.  
  247.  
  248.   //loop through and remove any inputs the voice might have (recursive)
  249.   if(voiceI->inputs != NULL){
  250.     Uint32* inputs = voiceI->inputs->data;
  251.     Uint32 inputs_len = voiceI->inputs->x;
  252.     _kit_kmixerVoice* raw = (*raw_p)->data;
  253.  
  254.     for(Uint32 i=0; i<inputs_len; ++i){
  255.       Uint32 index = inputs[i];
  256.       if(!index) continue; //an index of 0 indicates a voice that was already removed
  257.       if(raw[index].lock != NULL) //(bit 31 is set to indicate recursion)
  258.         _IF_GOTO_ERROR(kit_kmixerVoiceRemove(device,U32_MSb|index),;)
  259.     }
  260.  
  261.     //(kit_coreVectorDestroy automatically sets pointer to NULL)
  262.     _IF_GOTO_ERROR(kit_coreVectorDestroy(&voiceI->inputs),;)
  263.     _IF_GOTO_ERROR(kit_coreVectorDestroy(&voiceI->inputRefs),;)
  264.   }
  265.  
  266.  
  267.   //free buffers
  268.   SAFE_FREE(voiceI->bufferInput.v);
  269.   SAFE_FREE(voiceI->bufferUser.v);
  270.   SAFE_FREE(voiceI->bufferConvert.v);
  271.   SAFE_FREE(voiceI->bufferOutput.v);
  272.  
  273.  
  274.   //call the user's 'userdata removal' callback
  275.   if(voiceI->spec.remove != NULL) voiceI->spec.remove(voiceI->spec.userdata);
  276.  
  277.  
  278.   _IF_GOTO_ERROR(SDL_UnlockMutex(voiceI->lock),;)
  279.   SDL_DestroyMutex(voiceI->lock);
  280.   voiceI->lock = NULL; //a mutex of NULL indicates a removed voice
  281.  
  282.  
  283.   //remove reference from ord
  284.   _kit_kmixerVoiceRemoveFromOrd(device, voiceI); //this can't error (yay!)
  285.  
  286.  
  287.   if(rootCall){ //if this call is not the result of recursion
  288.     //trim raw and ord
  289.     _IF_GOTO_ERROR(kit_coreVectorTrim(&device->_voices.raw,'x',_kit_kmixerDeviceRawUnitCallback),;)
  290.     _IF_GOTO_ERROR(kit_coreVectorTrim(&device->_voices.ord,0,_kit_kmixerDeviceOrdUnitCallback),;)
  291.  
  292.     //trim inputs of output voice, potentially destroying inputs if none are left
  293.     voiceI = &VECTOR_INDEX_C(_kit_kmixerVoice, *raw_p, voiceID);
  294.     _kit_kmixerVoice* voiceO = voiceI->output;
  295.     _IF_GOTO(voiceO==NULL,_noerr_,;) //voice 0 doesn't have an output, for example
  296.     _IF_GOTO_ERROR(_kit_kmixerVoiceRemoveInput(voiceO,voiceI->index),;)
  297.   }
  298.  
  299.  
  300.   _noerr_: return  0; // 0 on success
  301.   _error_: return -1; //-1 on failure
  302. }
  303.  
  304.  
  305.  
  306. Uint32 kit_kmixerVoiceAdd(kit_kmixerDevice* device, kit_kmixerVoiceSpec* spec,
  307.                           Uint32 outputVoiceID)
  308. {
  309.   Sint32 newIndex = 0; //0 for error by default
  310.   _kit_kmixerVoice voice = { .lock = NULL }; //voice struct to be copied to raw
  311.   _kit_kmixerVoice* voiceI = NULL; //reference to voice inside raw
  312.  
  313.   SDL_bool inRaw = SDL_FALSE; //set to true if successfully inserted into raw
  314.   SDL_bool success = SDL_FALSE;
  315.   _IF_SDLERR(device==NULL,;,"device cannot be NULL")
  316.   _IF_SDLERR(device->_magic.num!=_DEV_MAGIC_NUM,;,"invalid device struct")
  317.   _IF_GOTO_ERROR(kit_kmixerDeviceLock(device,SDL_TRUE),;)
  318.  
  319.  
  320.   //get reference to output voice
  321.   kit_coreVector** raw_p = &device->_voices.raw;
  322.   Uint32 raw_len = (*raw_p)->x;
  323.   _IF_SDLERR(outputVoiceID>=raw_len,;,"outputVoiceID > voice list size")
  324.   _kit_kmixerVoice* voiceO = &VECTOR_INDEX_C(_kit_kmixerVoice, *raw_p, outputVoiceID);
  325.   _IF_SDLERR(voiceO->lock==NULL,;,"output voice is nonexistent")
  326.  
  327.  
  328.   //fill in info for voice spec and the voice struct itself
  329.   _IF_GOTO_ERROR(_kit_kmixerVoiceAddFillSpec(device, spec),;)
  330.   _IF_GOTO_ERROR(_kit_kmixerVoiceAddFillVoice(spec, voiceO, &voice),;)
  331.  
  332.  
  333.   //add voice to raw
  334.   newIndex = kit_coreVectorInsert(raw_p, &voice, 0,0, _kit_kmixerDeviceRawUnitCallback);
  335.   _IF_GOTO_ERROR(newIndex<0,;)
  336.   voiceI = &VECTOR_INDEX_C(_kit_kmixerVoice, *raw_p, newIndex);
  337.   voiceI->index = newIndex;
  338.   inRaw = SDL_TRUE;
  339.  
  340.  
  341.   //add voice's reference to ord
  342.   _IF_GOTO_ERROR(_kit_kmixerVoiceAddToOrd(device, voiceI),;)
  343.  
  344.  
  345.   //add voice to output's input list
  346.   voiceO = &VECTOR_INDEX_C(_kit_kmixerVoice, *raw_p, outputVoiceID);
  347.   _IF_GOTO_ERROR(_kit_kmixerVoiceAddInput(voiceO, voiceI),;)
  348.  
  349.  
  350.   success = SDL_TRUE;
  351.   _error_:
  352.   if(!success){
  353.     if(inRaw){
  354.       if(voiceI->lock != NULL) SDL_DestroyMutex(voiceI->lock);
  355.       kit_coreVectorDestroy(&voiceI->inputs);
  356.       kit_coreVectorDestroy(&voiceI->inputRefs);
  357.       SAFE_FREE(voiceI->bufferInput.v);
  358.       SAFE_FREE(voiceI->bufferUser.v);
  359.       SAFE_FREE(voiceI->bufferConvert.v);
  360.       SAFE_FREE(voiceI->bufferOutput.v);
  361.       voiceI->lock = NULL;
  362.     } else { //only remove the stack version of voice
  363.       if(voice.lock != NULL) SDL_DestroyMutex(voice.lock);
  364.       kit_coreVectorDestroy(&voice.inputs);
  365.       kit_coreVectorDestroy(&voice.inputRefs);
  366.       SAFE_FREE(voice.bufferInput.v);
  367.       SAFE_FREE(voice.bufferUser.v);
  368.       SAFE_FREE(voice.bufferConvert.v);
  369.       SAFE_FREE(voice.bufferOutput.v);
  370.     }
  371.     newIndex = 0;
  372.   }
  373.   kit_kmixerDeviceLock(device, SDL_FALSE);
  374.   return newIndex;
  375. }
  376.  
  377.  
  378.  
  379.  
  380. int kit_kmixerVoiceRedirect(kit_kmixerDevice* device,
  381.                             Uint32 inputVoiceID, Uint32 outputVoiceID)
  382. {
  383.   int returnStatus = 0;
  384.   _IF_SDLERR(device==NULL,;,"device cannot be NULL")
  385.   _IF_SDLERR(device->_magic.num!=_DEV_MAGIC_NUM,;,"invalid device struct")
  386.   _IF_GOTO_ERROR(kit_kmixerDeviceLock(device,SDL_TRUE),;)
  387.  
  388.   kit_coreVector** raw_p = &device->_voices.raw;
  389.   Uint32 raw_len = (*raw_p)->x;
  390.   _IF_SDLERR(outputVoiceID>=raw_len,;,"outputVoiceID > voice list size")
  391.  
  392.  
  393.   _kit_kmixerVoice* voiceI = &VECTOR_INDEX_C(_kit_kmixerVoice, *raw_p, inputVoiceID);
  394.   _kit_kmixerVoice* voiceO = &VECTOR_INDEX_C(_kit_kmixerVoice, *raw_p, outputVoiceID);
  395.   _kit_kmixerVoice* voiceO_old = voiceI->output;
  396.  
  397.   _IF_SDLERR(voiceO->lock==NULL,;,"output voice is nonexistent")
  398.  
  399.  
  400.   _IF_GOTO_ERROR(_kit_kmixerVoiceRemoveInput(voiceO_old, inputVoiceID),;)
  401.   _IF_GOTO_ERROR(_kit_kmixerVoiceAddInput(voiceO, voiceI),;)
  402.   _kit_kmixerVoiceRemoveFromOrd(device, voiceI);
  403.  
  404.   voiceI->output       = voiceO;
  405.   voiceI->chainStage   = voiceO->chainStage+1;
  406.   voiceI->stereoOutput = voiceO->spec.stereo;
  407.  
  408.   _IF_GOTO_ERROR(_kit_kmixerVoiceAddToOrd(device, voiceI),;)
  409.  
  410.  
  411.   /*!err*/ ++returnStatus;
  412.   _error_: --returnStatus;
  413.   kit_kmixerDeviceLock(device,SDL_FALSE);
  414.   return returnStatus;
  415. }
  416.  
  417.  
  418.  
  419.  
  420. #if defined(_KIT_KMIXER_DEBUG) || defined(_KIT_ALL_DEBUG)
  421. void _kit_kmixerVoice_TestCallback(void* userdata, void* _stream, int size, SDL_bool hasInput){
  422. }
  423. /*
  424. because kmixer compiles with -O3, i get this error if i attempt to compile the test:
  425. "warning:  may be used uninitialized in this function [-Wmaybe-uninitialized]|"
  426. i have very little doubt that this is a bug, so i can't do much about it other than
  427. turn down optimization for this specific function
  428. */
  429. //(for some reason, it started working again after i added some seemingly
  430.  //unrelated stuff, so i'll comment this out for now)
  431. //__attribute__((optimize("-O0")))
  432. int kit_kmixerVoice_Test(){
  433.   float bufferInputA[16], bufferUserA[16], bufferConvertA[16], bufferOutputA[16];
  434.   float bufferInputB[16], bufferUserB[16], bufferConvertB[16], bufferOutputB[16];
  435.   float bufferInputC[16], bufferUserC[16], bufferConvertC[16], bufferOutputC[16];
  436.  
  437.  
  438.   _kit_kmixerVoice voiceA={
  439.     .spec={
  440.       .callback = _kit_kmixerVoice_TestCallback,
  441.       .userdata = NULL,
  442.       .freq     = 44100,
  443.       ._size    = 16*sizeof(float),
  444.       .stereo   = SDL_FALSE,
  445.       .samples  = 16,
  446.       .format   = AUDIO_F32
  447.     },
  448.  
  449.     .bufferInput   = { .v=bufferInputA   },
  450.     .bufferUser    = { .v=bufferUserA    },
  451.     .bufferConvert = { .v=bufferConvertA },
  452.     .bufferOutput  = { .v=bufferOutputA  },
  453.  
  454.     .inputs = NULL,
  455.     .lock   = NULL,
  456.  
  457.     .chainStage = 2,
  458.     .index      = 3,
  459.  
  460.     .volL = 1.0f,
  461.     .volR = 1.0f,
  462.  
  463.     .applyVolume  = SDL_TRUE,
  464.     .stereoOutput = SDL_FALSE,
  465.   };
  466.  
  467.   _kit_kmixerVoice voiceB={
  468.     .spec={
  469.       .callback = _kit_kmixerVoice_TestCallback,
  470.       .userdata = NULL,
  471.       .freq     = 44100,
  472.       ._size    = 16*sizeof(float),
  473.       .stereo   = SDL_FALSE,
  474.       .samples  = 16,
  475.       .format   = AUDIO_F32
  476.     },
  477.  
  478.     .bufferInput   = { .v=bufferInputB   },
  479.     .bufferUser    = { .v=bufferUserB    },
  480.     .bufferConvert = { .v=bufferConvertB },
  481.     .bufferOutput  = { .v=bufferOutputB  },
  482.  
  483.     .inputs = NULL,
  484.     .lock   = NULL,
  485.  
  486.     .chainStage = 2,
  487.     .index      = 2,
  488.  
  489.     .volL = 1.0f,
  490.     .volR = 1.0f,
  491.  
  492.     .applyVolume  = SDL_TRUE,
  493.  
  494.     .stereoOutput = SDL_FALSE,
  495.   };
  496.  
  497.   _kit_kmixerVoice voiceC={
  498.     .spec={
  499.       .callback = _kit_kmixerVoice_TestCallback,
  500.       .userdata = NULL,
  501.       .freq     = 44100,
  502.       ._size    = 16*sizeof(float),
  503.       .stereo   = SDL_FALSE,
  504.       .samples  = 16,
  505.       .format   = AUDIO_F32
  506.     },
  507.  
  508.     .bufferInput   = { .v=bufferInputC   },
  509.     .bufferUser    = { .v=bufferUserC    },
  510.     .bufferConvert = { .v=bufferConvertC },
  511.     .bufferOutput  = { .v=bufferOutputC  },
  512.  
  513.     .inputs = NULL,
  514.     .lock   = NULL,
  515.  
  516.     .chainStage = 1,
  517.     .index      = 1,
  518.  
  519.     .volL = 1.0f,
  520.     .volR = 1.0f,
  521.  
  522.     .applyVolume  = SDL_TRUE,
  523.     .stereoOutput = SDL_FALSE,
  524.   };
  525.  
  526.  
  527.   //example streams
  528.   Uint8  u_8_A[16]={0x00,0x3F,0x10,0x80,0xFF,0x4E,0x24,0x6D,0x21,0xFE,0xED,0x86,0x3A,0xAB,0xDA,0x4C};
  529.   Sint16 i16_A[16]={-32768,13106,-16384,6553,32767,2553,-26214,25937,22337,-13102,9553,-32467,-9830,0,-19661,-22938};
  530.   Sint32 i32_A[16]={-2147483648,2147483647,2,547760950,-978102134,-1901782676,973752665,-2054956051,-1793070550,2100284199,1386177656,-70287364,-799099289,-594127329,1025429360,-570645197};
  531.   float  f32_A[16]={ 0.8,-0.2, 0.0,-0.6,-0.6, 0.4, 1.0, 2.0, 0.6, 0.9, 0.8, 0.3, 0.6,-1.4,-0.1, 0.1};
  532.   float  f32_B[16]={-0.1,-0.4, 0.1, 0.3,-0.6, 0.6, 0.6,-0.6,-0.1, 0.2,-0.2, 0.8, 0.4, 0.8, 0.4, 0.7};
  533.  
  534.  
  535.   //test to and from type conversion
  536.    //u_8
  537.   SDL_memcpy(voiceA.bufferUser.m.u_8, u_8_A, 16*sizeof(Uint8));
  538.   _kit_kmixerVoiceProcFromType(voiceA.bufferUser.m.u_8,voiceA.bufferConvert.m, 16,AUDIO_U8,SDL_FALSE);
  539.   _kit_kmixerVoiceProcToType(voiceA.bufferConvert.m,voiceA.bufferUser.m.u_8, 16,AUDIO_U8,SDL_FALSE);
  540.   for(Uint32 i=0; i<16; ++i){
  541.     if(voiceA.bufferUser.m.u_8[i] != MAX(u_8_A[i],1)){
  542.       SDL_SetError("u_8 type conv. (%u:%X!=%X)",
  543.         i, voiceA.bufferUser.m.u_8[i], MAX(u_8_A[i],1) ); return -999;
  544.     }
  545.   }
  546.    //i16
  547.   SDL_memcpy(voiceA.bufferUser.m.i16, i16_A, 16*sizeof(Sint16));
  548.   _kit_kmixerVoiceProcFromType(voiceA.bufferUser.m.i16,voiceA.bufferConvert.m, 16,AUDIO_S16,SDL_FALSE);
  549.   _kit_kmixerVoiceProcToType(voiceA.bufferConvert.m,voiceA.bufferUser.m.i16, 16,AUDIO_S16,SDL_FALSE);
  550.   for(Uint32 i=0; i<16; ++i){
  551.     if(voiceA.bufferUser.m.i16[i] != MAX(i16_A[i],-32767)){
  552.       SDL_SetError("i16 type conv. (%u:%i!=%i)",
  553.         i, voiceA.bufferUser.m.i16[i], MAX(i16_A[i],-32767) ); return -999;
  554.     }
  555.   }
  556.    //i32 (products of conversion are actually approximations with a max error of 64)
  557.   SDL_memcpy(voiceA.bufferUser.m.i32, i32_A, 16*sizeof(Sint32));
  558.   _kit_kmixerVoiceProcFromType(voiceA.bufferUser.m.i32,voiceA.bufferConvert.m, 16,AUDIO_S32,SDL_FALSE);
  559.   _kit_kmixerVoiceProcToType(voiceA.bufferConvert.m,voiceA.bufferUser.m.i32, 16,AUDIO_S32,SDL_FALSE);
  560.   for(Uint32 i=0; i<16; ++i){
  561.     if((voiceA.bufferUser.m.i32[i] < (MAX(i32_A[i],-2147483647)-64)) &&
  562.        (voiceA.bufferUser.m.i32[i] > (MAX(i32_A[i],-2147483647)+64)))
  563.     {
  564.       SDL_SetError("i32 type conv. (%u:%i!=%i)",
  565.         i, voiceA.bufferUser.m.i32[i], MAX(i32_A[i],-2147483647) ); return -999;
  566.     }
  567.   }
  568.    //f32
  569.   SDL_memcpy(voiceA.bufferUser.m.f32, f32_A, 16*sizeof(float));
  570.   _kit_kmixerVoiceProcFromType(voiceA.bufferUser.m.f32,voiceA.bufferConvert.m, 16,AUDIO_F32,SDL_FALSE);
  571.   _kit_kmixerVoiceProcToType(voiceA.bufferConvert.m,voiceA.bufferUser.m.f32, 16,AUDIO_F32,SDL_FALSE);
  572.   for(Uint32 i=0; i<16; ++i){
  573.     if(voiceA.bufferUser.m.f32[i] != CLAMP(f32_A[i], -1.0f,1.0f)){
  574.       SDL_SetError("f32 type conv. (%u:%.1f!=%.1f)",
  575.         i, voiceA.bufferUser.m.f32[i], CLAMP(f32_A[i], -1.0f,1.0f) ); return -999;
  576.     }
  577.   }
  578.  
  579.  
  580.   //test channel conversion
  581.    //  mono-stereo
  582.   _kit_kmixerVoiceProcChannels(f32_A, voiceA.bufferConvert.s, 8,_M_to_S);
  583.   for(Uint32 i=0; i<16; i+=2){
  584.     //SDL_Log("%2u: %9f, %9f",i, voiceA.bufferConvert.m[i], voiceA.bufferConvert.m[i+1]);
  585.     if(voiceA.bufferConvert.m[i] != voiceA.bufferConvert.m[i+1]){
  586.       SDL_SetError("mn.->st. convert (%u:%.1f!=%.1f)",
  587.         i, voiceA.bufferConvert.m[i], voiceA.bufferConvert.m[i+1] ); return -999;
  588.     }
  589.   }
  590.    //stereo-mono
  591.   _kit_kmixerVoiceProcChannels(f32_A, voiceA.bufferConvert.m,  8,_S_to_M);
  592.   for(Uint32 i=0; i<16; i+=2){
  593.     //SDL_Log("%2u: %9f,%9f -> %9f",i, f32_A[i],f32_A[i+1], voiceA.bufferConvert.m[i>>1]);
  594.     if(voiceA.bufferConvert.m[i>>1] != (f32_A[i]+f32_A[i+1])*.5f){
  595.       SDL_SetError("st.->mn. convert (%u:%.1f!=%.1f)",
  596.         i, voiceA.bufferConvert.m[i>>1], (f32_A[i]+f32_A[i+1])*.5f ); return -999;
  597.     }
  598.   }
  599.    //stereo-stereo
  600.   _kit_kmixerVoiceProcChannels(f32_A, voiceA.bufferConvert.s,  8,_S_to_S);
  601.   for(Uint32 i=0; i<16; ++i){
  602.     //SDL_Log("%2u: %9f",i, voiceA.bufferConvert.m[i]);
  603.     if(voiceA.bufferConvert.m[i] != f32_A[i]){
  604.       SDL_SetError("st.->st. convert (%u:%.1f!=%.1f)",
  605.         i, voiceA.bufferConvert.m[i], f32_A[i] ); return -999;
  606.     }
  607.   }
  608.    //  mono-mono
  609.   _kit_kmixerVoiceProcChannels(f32_A, voiceA.bufferConvert.m, 16,_M_to_M);
  610.   for(Uint32 i=0; i<16; ++i){
  611.     //SDL_Log("%2u: %9f",i, voiceA.bufferConvert.m[i]);
  612.     if(voiceA.bufferConvert.m[i] != f32_A[i]){
  613.       SDL_SetError("mn.->mn. convert (%u:%.1f!=%.1f)",
  614.         i, voiceA.bufferConvert.m[i], f32_A[i] ); return -999;
  615.     }
  616.   }
  617.  
  618.  
  619.   //test VoiceProc itself here
  620.  
  621.  
  622.   //test mixing (might want to add in other volume settings at some point)
  623.   voiceA.lock=SDL_CreateMutex();
  624.   voiceB.lock=SDL_CreateMutex();
  625.   voiceC.lock=SDL_CreateMutex();
  626.   kit_coreVector* ivoices=kit_coreVectorCreate(2,0,0, sizeof(_kit_kmixerVoice),0);
  627.   if(voiceA.lock==NULL || voiceB.lock==NULL || voiceC.lock==NULL || ivoices==NULL){
  628.     if(voiceA.lock != NULL) SDL_DestroyMutex(voiceA.lock);
  629.     if(voiceB.lock != NULL) SDL_DestroyMutex(voiceB.lock);
  630.     if(voiceC.lock != NULL) SDL_DestroyMutex(voiceC.lock);
  631.     if(ivoices != NULL) kit_coreVectorDestroy(&ivoices);
  632.   }
  633.  
  634.   SDL_memcpy(voiceA.bufferOutput.m, f32_A, 16*sizeof(float));
  635.   SDL_memcpy(voiceB.bufferOutput.m, f32_B, 16*sizeof(float));
  636.   _kit_kmixerVoice _ivoices[2]={voiceA,voiceB};
  637.   memcpy(ivoices->data, _ivoices, sizeof(_kit_kmixerVoice)*2);
  638.    //mono, 1.0,1.0
  639.   _kit_kmixerVoiceMix(&voiceC);
  640.   for(Uint32 i=0; i<16; ++i){
  641.     float mixed=voiceC.bufferInput.m[i];
  642.     float real=CLAMP(voiceA.bufferOutput.m[i]+voiceB.bufferOutput.m[i], -1.0f,1.0f);
  643.     if(mixed != real){ SDL_SetError("mn. mixing (%u:%.1f!=%.1f)",
  644.                          i, mixed, real ); return -999;
  645.     }
  646.   }
  647.    //stereo, 1.0,1.0
  648.   voiceA.stereoOutput=SDL_TRUE;
  649.   voiceB.stereoOutput=SDL_TRUE;
  650.   voiceA.spec.samples=8;
  651.   voiceB.spec.samples=8;
  652.   voiceC.spec.samples=8;
  653.   _kit_kmixerVoiceMix(&voiceC);
  654.   for(Uint32 i=0; i<16; ++i){
  655.     float mixed=voiceC.bufferInput.m[i];
  656.     float real=CLAMP(voiceA.bufferOutput.m[i]+voiceB.bufferOutput.m[i], -1.0f,1.0f);
  657.     if(mixed != real){ SDL_SetError("st. mixing (%u:%.1f!=%.1f)",
  658.                          i, mixed, real ); return -999;
  659.     }
  660.   }
  661.  
  662.   if(voiceA.lock != NULL) SDL_DestroyMutex(voiceA.lock);
  663.   if(voiceB.lock != NULL) SDL_DestroyMutex(voiceB.lock);
  664.   if(voiceC.lock != NULL) SDL_DestroyMutex(voiceC.lock);
  665.   if(ivoices != NULL) kit_coreVectorDestroy(&ivoices);
  666.  
  667.  
  668.   //test adding and removing possibly
  669.  
  670.  
  671.   //kit_coreLog("sizeof(_kit_kmixerVoice)=%u",(unsigned int)sizeof(_kit_kmixerVoice));
  672.  
  673.  
  674.   return 0;
  675. }
  676. void kit_kmixerVoicePrintRawOrd(kit_kmixerDevice* device){
  677.   kit_coreVector** raw_p = &device->_voices.raw;
  678.   kit_coreVector** ord_p = &device->_voices.ord;
  679.   Uint32 rawLen = (*raw_p)->x;
  680.   Uint32 ordLen = (*ord_p)->x;
  681.   Uint32 maxStage = (*ord_p)->y-1;
  682.   _kit_kmixerVoice* raw = (*raw_p)->data;
  683.   _kit_kmixerVoice** ord = (*ord_p)->data;
  684.  
  685.  
  686.   printf("\n~~~ RAW ~~~\n");
  687.   for(Uint32 v=0; v<rawLen; ++v){
  688.     _kit_kmixerVoice* voice = &raw[v];
  689.     Uint32             numInputs =    0;
  690.     Uint32*               inputs = NULL;
  691.     _kit_kmixerVoice** inputRefs = NULL;
  692.     if(voice->inputs != NULL){
  693.       numInputs = voice->inputs->x;
  694.          inputs = voice->inputs->data;
  695.       inputRefs = voice->inputRefs->data;
  696.     }
  697.     printf("--- %02u/%02u (%p) ---\n", v, rawLen-1, voice);
  698.  
  699.     printf("  voice%u->inputs     = %p: ",v, voice->inputs);
  700.     if(inputs != NULL){
  701.       printf("{\n    ");
  702.       for(Uint32 i=0; i<numInputs; ++i){
  703.         printf("%02u, ",inputs[i]);
  704.         if((i+1)==numInputs) printf("\n");
  705.         else if((i%5)==4) printf("\n    ");
  706.       }
  707.       printf("  }\n");
  708.     } else printf("(NULL)\n");
  709.  
  710.     printf("  voice%u->inputRefs  = %p: ",v, voice->inputRefs);
  711.     if(inputRefs != NULL){
  712.       printf("{\n    ");
  713.       for(Uint32 i=0; i<numInputs; ++i){
  714.         printf("%p, ",inputRefs[i]);
  715.         if((i+1)==numInputs) printf("\n");
  716.         else if((i%5)==4) printf("\n    ");
  717.       }
  718.       printf("  }\n");
  719.     } else printf("(NULL)\n");
  720.  
  721.     printf("  voice%u->output     = %p\n",v, voice->output);
  722.  
  723.     printf("  voice%u->chainStage = %u\n",v, voice->chainStage);
  724.     printf("  voice%u->index      = %u\n",v, voice->index);
  725.  
  726.     printf("\n");
  727.   }
  728.  
  729.  
  730.   printf("\n~~~ ORD ~~~\n");
  731.   for(Uint32 yi=maxStage; yi!=U32_MAX; --yi){
  732.     printf("stage %02u:  ", yi);
  733.     for(Uint32 xi=0; xi<ordLen; ++xi){
  734.       _kit_kmixerVoice* voice = ord[xi + yi*ordLen];
  735.  
  736.       if(voice == NULL) printf("NL, ");
  737.       else if(voice->lock == NULL) printf("RM, ");
  738.       else printf("%p, ",voice);
  739.       //else printf("%02u, ",voice->index);
  740.     }
  741.     printf("\n");
  742.   }
  743.   printf("\n");
  744. }
  745. #else
  746. int kit_kmixerVoice_Test(){
  747.   SDL_SetError("!defined(_KIT_KMIXER_DEBUG)");
  748.   return 999;
  749. }
  750. void kit_kmixerVoicePrintRawOrd(kit_kmixerDevice* device){}
  751. #endif
  752.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement