Advertisement
Kitomas

kit_sdl2_kmixerVoice.c as of 2023-8-24

Aug 25th, 2023
935
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 19.76 KB | None | 0 0
  1. #include "../include/kit_sdl2/kit_kmixer.h"
  2. #include "../_private/include/_kit_privmacro.h"
  3. #include "../_private/include/_kit_kmixerPrivate.h"
  4.  
  5.  
  6. //include intrinsic functions
  7. #include <immintrin.h>
  8.  
  9.  
  10.  
  11.  
  12. //for debug testing
  13. #define _ENABLE_SSE   SDL_TRUE
  14. #define _ENABLE_SSE2  SDL_TRUE
  15. #define _ENABLE_SSE3  SDL_TRUE
  16. #define _ENABLE_SSE41 SDL_TRUE
  17. #define _ENABLE_AVX   SDL_TRUE
  18. #define _ENABLE_AVX2  SDL_TRUE
  19.  
  20.  
  21. //bitmasks for _kit_kmixerGlobals.capabilities
  22. #define _SSE_MASK   (1<<5)
  23. #define _SSE2_MASK  (1<<4)
  24. #define _SSE3_MASK  (1<<3)
  25. #define _SSE41_MASK (1<<2) //(SSE4.1)
  26. #define _AVX_MASK   (1<<1)
  27. #define _AVX2_MASK  (1<<0)
  28.  
  29.  
  30. //for visual clarity during ProcChannels
  31.  //(this could also just be an enum probably, but w/e)
  32. #define _M_to_M (0) //  mono->mono
  33. #define _M_to_S (1) //  mono->stereo
  34. #define _S_to_M (2) //stereo->mono
  35. #define _S_to_S (3) //stereo->stereo
  36. #define _MM256_SHUFFLE(c7,c6,c5,c4,c3,c2,c1,c0) \
  37.   ((_MM_SHUFFLE(c7,c6,c5,c4)<<8)|_MM_SHUFFLE(c3,c2,c1,c0))
  38. #define _MN(a,b) ( ((a)<(b))?(a):(b) )
  39. #define _MX(a,b) ( ((a)>(b))?(a):(b) )
  40. #define _CLMP(n, m,x) _MN(_MX(n, m),x)
  41.  
  42.  
  43.  
  44. //used to multiply an int by the inverse of an int to get a normalized float
  45. //(input 8-bit samples will be unsigned, so +=0x80 to convert them to signed first)
  46. const float invi_8=1.0f/0x7f;       //=0.007874015748031496062992125984251968503937
  47. const float invi16=1.0f/0x7fff;     //=0.000030518509475997192297128208258308664204
  48. const float invi32=1.0f/0x7fffffff; //=0.000000000465661287524579692410575082716799
  49.  
  50.  
  51.  
  52.  
  53. //converts u8, i16, and i32 samples to f32 samples
  54. static inline void _kit_kmixerVoiceProcFromTypeFallback(void* _dataIn, float* dataOut,
  55.                                                         Uint32 numSamples, SDL_AudioFormat typeIn)
  56. { //if nothing else works
  57.   _mono_samples dataIn={.ptr=_dataIn};
  58.   float rawSample; //used for max(original_sample,-1) basically
  59.   switch(typeIn){
  60.   case AUDIO_U8 : for(Uint32 i=0; i<numSamples; ++i){ rawSample=(float)(dataIn.u_8[i]-0x80)*invi_8;
  61.                                                       dataOut[i]=(rawSample>=-1.0f)?rawSample:-1.0f; } break;
  62.   case AUDIO_S16: for(Uint32 i=0; i<numSamples; ++i){ rawSample=(float) dataIn.i16[i]      *invi16;
  63.                                                       dataOut[i]=(rawSample>=-1.0f)?rawSample:-1.0f; } break;
  64.   case AUDIO_S32: for(Uint32 i=0; i<numSamples; ++i){ rawSample=(float) dataIn.i32[i]      *invi32;
  65.                                                       dataOut[i]=(rawSample>=-1.0f)?rawSample:-1.0f; } break;
  66.   case AUDIO_F32: for(Uint32 i=0; i<numSamples; ++i){ dataOut[i]=       dataIn.f32[i];               } }
  67. }
  68. void _kit_kmixerVoiceProcFromType(void* dataIn, void* dataOut,
  69.                                   Uint32 sampleFrames, SDL_AudioFormat typeIn, SDL_bool isStereo)
  70. {
  71.   Uint32 numSamples=sampleFrames<<isStereo;
  72.   _kit_kmixerVoiceProcFromTypeFallback(dataIn,dataOut,numSamples,typeIn);
  73. }
  74.  
  75.  
  76.  
  77.  
  78. //converts f32 samples to u8, i16, and i32 samples
  79. static inline void _kmixerVoiceProcToTypeFallback(float* dataIn, void* _dataOut,
  80.                                                   Uint32 numSamples, SDL_AudioFormat typeOut)
  81. { //if nothing else works
  82.   _mono_samples dataOut={.ptr=_dataOut};
  83.   float rawSample, rawSampleB;
  84.   switch(typeOut){
  85.   case AUDIO_U8 : for(Uint32 i=0; i<numSamples; ++i){ rawSample     =dataIn[i];
  86.                                                       rawSampleB    =(rawSample>=-1.0f)?rawSample:-1.0f;
  87.                                                       dataOut.u_8[i]=(rawSampleB<=1.0f)?rawSampleB*0x7f+0x80:0x7f; } break;
  88.   case AUDIO_S16: for(Uint32 i=0; i<numSamples; ++i){ rawSample     =dataIn[i];
  89.                                                       rawSampleB    =(rawSample>=-1.0f)?rawSample:-1.0f;
  90.                                                       dataOut.i16[i]=(rawSampleB<=1.0f)?rawSampleB*0x7fff:0x7fff; } break;
  91.   case AUDIO_S32: for(Uint32 i=0; i<numSamples; ++i){ rawSample     =dataIn[i];
  92.                                                       rawSampleB    =(rawSample>=-1.0f)?rawSample:-1.0f;
  93.                                                       dataOut.i32[i]=(rawSampleB<=1.0f)?rawSampleB*0x7fffffff:0x7fffffff; } break;
  94.   case AUDIO_F32: for(Uint32 i=0; i<numSamples; ++i){ rawSample     =dataIn[i];
  95.                                                       rawSampleB    =(rawSample>=-1.0f)?rawSample:-1.0f;
  96.                                                       dataOut.f32[i]=(rawSampleB<=1.0f)?rawSampleB:1.0f; } }
  97. }
  98. void _kit_kmixerVoiceProcToType(void* dataIn, void* dataOut,
  99.                                 Uint32 sampleFrames, SDL_AudioFormat typeOut, SDL_bool isStereo)
  100. {
  101.   Uint32 numSamples=sampleFrames<<isStereo;
  102.   _kmixerVoiceProcToTypeFallback(dataIn,dataOut,numSamples,typeOut);
  103. }
  104.  
  105.  
  106.  
  107.  
  108. //assumes samples are f32
  109. static inline void _kit_kmixerVoiceProcChannelsFallback(float* dataInM, float* dataOutM,
  110.                                                         Uint32 sampleFrames, int channelInfo)
  111. { //if nothing else works
  112.   _stereo_samples_f32* dataInS =(void*)dataInM;
  113.   _stereo_samples_f32* dataOutS=(void*)dataOutM;
  114.   switch(channelInfo){
  115.   case _M_to_S: for(Uint32 i=0; i<sampleFrames; ++i){ dataOutS[i].l=dataOutS[i].r=dataInM[i]; } break;
  116.   case _S_to_M: for(Uint32 i=0; i<sampleFrames; ++i){ dataOutM[i]=(dataInS[i].l+dataInS[i].r)*.5f; } break;
  117.   case _S_to_S: sampleFrames<<=1; SDL_FALLTHROUGH; //multiply mono by 2 to make length of stereo
  118.   case _M_to_M: for(Uint32 i=0; i<sampleFrames; ++i){ dataOutM[i]=dataInM[i]; }
  119.   }
  120. }
  121. void _kit_kmixerVoiceProcChannels(void* dataIn, void* dataOut, Uint32 sampleFrames, int channelInfo){
  122.   _kit_kmixerVoiceProcChannelsFallback(dataIn,dataOut, sampleFrames,channelInfo);
  123. }
  124.  
  125.  
  126.  
  127.  
  128. //assumes samples are f32
  129. void _kit_kmixerVoiceProcCopy(void* dataIn, void* dataOut, Uint32 sampleFrames, int isStereo){
  130.   SDL_memcpy(dataOut,dataIn, (sampleFrames*sizeof(float))<<isStereo);
  131. }
  132.  
  133.  
  134.  
  135.  
  136. #define _CH_INFO(a,b) (((a)<<1)|(b))
  137. //assumes input AND output samples are f32 (intermediate type is determined by the given voice)
  138. int _kit_kmixerVoiceProc(void* data){ //(this is an SDL_ThreadFunction)
  139.   _kit_kmixerVoice* voice=data;
  140.   SDL_LockMutex(voice->lock);
  141.  
  142.   void *ibuffer=voice->bufferInput.v, *ubuffer=voice->bufferUser.v, *obuffer=voice->bufferOutput.v;
  143.   void *tbuffer=voice->bufferType.v, *cbuffer=voice->bufferChannel.v;
  144.   void *userdata=voice->userdata, *_stream=ubuffer;
  145.    //
  146.   SDL_bool istereo=voice->stereoInput, ustereo=voice->stereoUser, ostereo=voice->stereoOutput;
  147.   SDL_bool hasInput = voice->inputs!=NULL;
  148.    //
  149.   SDL_AudioFormat ifmt=voice->formatInput, ufmt=voice->formatUser, ofmt=voice->formatOutput;
  150.    //
  151.   Uint32 frames=voice->sampleFrames, ubuffer_size=voice->bufferUser_size;
  152.  
  153.   //convert input type & channels (if necessary) before calling the kit_kmixerVoiceCallback
  154.   int sameChannels = (istereo==ustereo)<<4; //shift left by 1 nybble for case readability
  155.   int sameType     =     ifmt==ufmt;
  156.   SDL_bool skipUserBuffer = sameChannels&&sameType;
  157.   switch(sameChannels|sameType){
  158.   case 0x00: //convert channels and type before callback
  159.     //(will change this if i add in the ability to do channel conversion on non-floats)
  160.     SDL_FALLTHROUGH;
  161.   case 0x01: //only convert channels before callback
  162.     if(ufmt!=AUDIO_F32){
  163.       _kit_kmixerVoiceProcChannels(ibuffer,cbuffer, frames,_CH_INFO(istereo,ustereo));
  164.       _kit_kmixerVoiceProcToType(cbuffer,ubuffer, frames,ufmt,ustereo);
  165.     } else _kit_kmixerVoiceProcChannels(ibuffer,ubuffer, frames,_CH_INFO(istereo,ustereo));
  166.     goto voice_callback_case;
  167.   case 0x10: //only convert type before callback
  168.     _kit_kmixerVoiceProcToType(ibuffer, ubuffer, frames,ufmt,istereo);
  169.     SDL_FALLTHROUGH; //goto voice_callback_case;
  170.   case 0x11: voice_callback_case: //feed input directly to callback
  171.     if(skipUserBuffer) _stream=ibuffer; //will only be true on case 0x11
  172.     voice->callback(userdata, _stream, ubuffer_size, hasInput);
  173.   }
  174.  
  175.   //convert user type & channels (if necessary), outputting to bufferOutput
  176.   sameChannels = (ustereo==ostereo)<<4; //shift left by 1 nybble for case readability
  177.   sameType     =     ufmt==ofmt;
  178.   switch(sameChannels|sameType){
  179.   case 0x00: //convert channels & type
  180.     //(will change this if i add in the ability to do channel conversion on non-floats)
  181.     SDL_FALLTHROUGH;
  182.   case 0x01: //convert channels
  183.     if(ufmt!=AUDIO_F32){
  184.       _kit_kmixerVoiceProcFromType(_stream,tbuffer, frames,ufmt,ustereo);
  185.       _kit_kmixerVoiceProcChannels(tbuffer,obuffer, frames,_CH_INFO(ustereo,ostereo));
  186.     } else _kit_kmixerVoiceProcChannels(_stream,obuffer, frames,_CH_INFO(ustereo,ostereo));
  187.     break;
  188.   case 0x10: //convert type
  189.     _kit_kmixerVoiceProcFromType(_stream,tbuffer, frames,ufmt,ustereo);
  190.     _kit_kmixerVoiceProcToType(tbuffer,obuffer, frames,ofmt,ostereo);
  191.     break;
  192.   case 0x11: //just copy contents of _stream to output
  193.     _kit_kmixerVoiceProcCopy(_stream, obuffer, frames, ostereo);
  194.   }
  195.  
  196.   SDL_UnlockMutex(voice->lock);
  197.   return 0;
  198. }
  199.  
  200.  
  201.  
  202.  
  203. //assumes all samples are f32
  204. static inline void _kit_kmixerVoiceMixFallback(_kit_kmixerVoice* ovoice,
  205.                                                _kit_kmixerVoice* ivoices, Uint32 ivoices_len)
  206. { //if nothing else works
  207.   Uint32 frames=ovoice->sampleFrames;
  208.   memset(ovoice->bufferInput.v, 0, (frames*sizeof(float))<<ovoice->stereoInput);
  209.   _stereo_samples_f32* osamples=ovoice->bufferInput.s;
  210.   Uint32 samples_len=frames>>(!ovoice->stereoInput);
  211.  
  212.   //do the mixing
  213.   for(Uint32 vi=0; vi<ivoices_len; ++vi){
  214.     _kit_kmixerVoice* ivoice=&ivoices[vi];
  215.     _stereo_samples_f32* isamples=ivoice->bufferOutput.s;
  216.     float volL=ivoice->volL, volR=ivoice->volR;
  217.  
  218.     volL=_MN(volL,1.0f); volR=_MN(volR, 1.0f);
  219.     if(!ivoice->stereoOutput) volR=volL;
  220.  
  221.     if(volL==0 && volR==0) continue; //if volume is effectively muted, then skip the voice
  222.     else if(volL==1.0f && volR==1.0f) goto _do_not_apply_volume;
  223.     else if((volL>=0)&&ivoice->applyVolume){
  224.       if(volR<0) volR=volL;
  225.       for(Uint32 i=0; i<samples_len; ++i){
  226.         osamples[i].l += isamples[i].l*volL;
  227.         osamples[i].r += isamples[i].r*volR;
  228.       }
  229.     } else { _do_not_apply_volume:
  230.       for(Uint32 i=0; i<samples_len; ++i){
  231.         osamples[i].l += isamples[i].l;
  232.         osamples[i].r += isamples[i].r;
  233.       }
  234.     }
  235.   }
  236.  
  237.   //hard clip output samples to between -1.0f and 1.0f
  238.   for(Uint32 i=0; i<samples_len; ++i){
  239.     float sampleL=osamples[i].l;
  240.     osamples[i].l=_CLMP(sampleL, -1.0f,1.0f);
  241.     float sampleR=osamples[i].r;
  242.     osamples[i].r=_CLMP(sampleR, -1.0f,1.0f);
  243.   }
  244. }
  245. void _kit_kmixerVoiceMix(_kit_kmixerVoice* ovoice,
  246.                          _kit_kmixerVoice* ivoices, Uint32 ivoices_len)
  247. {
  248.   _kit_kmixerVoiceMixFallback(ovoice, ivoices,ivoices_len);
  249. }
  250.  
  251.  
  252.  
  253.  
  254. #ifdef _KIT_KMIXER_DEBUG
  255. extern int printf(const char*,...);
  256. void _kit_kmixerVoiceTestCallback(void* userdata, void* _stream, int size, SDL_bool hasInput){
  257. }
  258. #define _F32_EQUAL(a,b) ( (a)>((b)-0.000001) && (a)<((b)+0.000001) )
  259. int kit_kmixerVoiceTest(){
  260.   float bufferInputA[16], bufferTypeA[16], bufferChannelA[16], bufferUserA[16], bufferOutputA[16];
  261.   float bufferInputB[16], bufferTypeB[16], bufferChannelB[16], bufferUserB[16], bufferOutputB[16];
  262.   float bufferInputC[16], bufferTypeC[16], bufferChannelC[16], bufferUserC[16], bufferOutputC[16];
  263.  
  264.   _kit_kmixerVoice voiceA={
  265.     .bufferInput   = { .v=bufferInputA },
  266.     .bufferType    = { .v=bufferTypeA },
  267.     .bufferChannel = { .v=bufferChannelA },
  268.     .bufferUser    = { .v=bufferUserA },
  269.     .bufferOutput  = { .v=bufferOutputA },
  270.  
  271.     .lock     = NULL,
  272.     .callback = _kit_kmixerVoiceTestCallback,
  273.     .userdata = NULL,
  274.     .inputs   = NULL,
  275.  
  276.     .index           = 0,
  277.     .sampleRate      = 44100,
  278.     .bufferUser_size = 16*sizeof(float),
  279.  
  280.     .volL = 1.0f,
  281.     .volR = 1.0f,
  282.  
  283.     .applyVolume  = SDL_TRUE,
  284.     .stereoInput  = SDL_FALSE,
  285.     .stereoUser   = SDL_FALSE,
  286.     .stereoOutput = SDL_FALSE,
  287.  
  288.     .sampleFrames = 16,
  289.     .formatInput  = AUDIO_F32,
  290.     .formatUser   = AUDIO_F32,
  291.     .formatOutput = AUDIO_F32
  292.   };
  293.  
  294.   _kit_kmixerVoice voiceB={
  295.     .bufferInput   = { .v=bufferInputB },
  296.     .bufferType    = { .v=bufferTypeB },
  297.     .bufferChannel = { .v=bufferChannelB },
  298.     .bufferUser    = { .v=bufferUserB },
  299.     .bufferOutput  = { .v=bufferOutputB },
  300.  
  301.     .lock     = NULL,
  302.     .callback = _kit_kmixerVoiceTestCallback,
  303.     .userdata = NULL,
  304.     .inputs   = NULL,
  305.  
  306.     .index           = 0,
  307.     .sampleRate      = 44100,
  308.     .bufferUser_size = 16*sizeof(float),
  309.  
  310.     .volL = 1.0f,
  311.     .volR = 1.0f,
  312.  
  313.     .applyVolume  = SDL_TRUE,
  314.     .stereoInput  = SDL_FALSE,
  315.     .stereoUser   = SDL_FALSE,
  316.     .stereoOutput = SDL_FALSE,
  317.  
  318.     .sampleFrames = 16,
  319.     .formatInput  = AUDIO_F32,
  320.     .formatUser   = AUDIO_F32,
  321.     .formatOutput = AUDIO_F32
  322.   };
  323.  
  324.   _kit_kmixerVoice voiceC={
  325.     .bufferInput   = { .v=bufferInputC },
  326.     .bufferType    = { .v=bufferTypeC },
  327.     .bufferChannel = { .v=bufferChannelC },
  328.     .bufferUser    = { .v=bufferUserC },
  329.     .bufferOutput  = { .v=bufferOutputC },
  330.  
  331.     .lock     = NULL,
  332.     .callback = _kit_kmixerVoiceTestCallback,
  333.     .userdata = NULL,
  334.     .inputs   = NULL,
  335.  
  336.     .index           = 2,
  337.     .sampleRate      = 44100,
  338.     .bufferUser_size = 16*sizeof(float),
  339.  
  340.     .volL = 1.0f,
  341.     .volR = 1.0f,
  342.  
  343.     .applyVolume  = SDL_TRUE,
  344.     .stereoInput  = SDL_FALSE,
  345.     .stereoUser   = SDL_FALSE,
  346.     .stereoOutput = SDL_FALSE,
  347.  
  348.     .sampleFrames = 16,
  349.     .formatInput  = AUDIO_F32,
  350.     .formatUser   = AUDIO_F32,
  351.     .formatOutput = AUDIO_F32
  352.   };
  353.  
  354.   //example streams
  355.   Uint8  u_8_A[16]={0x00,0x3F,0x10,0x80,0xFF,0x4E,0x24,0x6D,0x21,0xFE,0xED,0x86,0x3A,0xAB,0xDA,0x4C};
  356.   Sint16 i16_A[16]={-32768,13106,-16384,6553,32767,2553,-26214,25937,22337,-13102,9553,-32467,-9830,0,-19661,-22938};
  357.   Sint32 i32_A[16]={-2147483648,2147483647,2,547760950,-978102134,-1901782676,973752665,-2054956051,-1793070550,2100284199,1386177656,-70287364,-799099289,-594127329,1025429360,-570645197};
  358.   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};
  359.   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};
  360.  
  361.   //test to and from type conversion
  362.    //u_8
  363.   SDL_memcpy(voiceA.bufferUser.m.u_8, u_8_A, 16*sizeof(Uint8));
  364.   _kit_kmixerVoiceProcFromType(voiceA.bufferUser.m.u_8,voiceA.bufferType.m, 16,AUDIO_U8,SDL_FALSE);
  365.   _kit_kmixerVoiceProcToType(voiceA.bufferType.m,voiceA.bufferUser.m.u_8, 16,AUDIO_U8,SDL_FALSE);
  366.   for(Uint32 i=0; i<16; ++i){
  367.     if(voiceA.bufferUser.m.u_8[i] != _MX(u_8_A[i],1)){
  368.       SDL_SetError("u_8 type conversion failed (%u: %X != %X)",
  369.         i, voiceA.bufferUser.m.u_8[i], _MX(u_8_A[i],1) ); return -999;
  370.     }
  371.   }
  372.    //i16
  373.   SDL_memcpy(voiceA.bufferUser.m.i16, i16_A, 16*sizeof(Sint16));
  374.   _kit_kmixerVoiceProcFromType(voiceA.bufferUser.m.i16,voiceA.bufferType.m, 16,AUDIO_S16,SDL_FALSE);
  375.   _kit_kmixerVoiceProcToType(voiceA.bufferType.m,voiceA.bufferUser.m.i16, 16,AUDIO_S16,SDL_FALSE);
  376.   for(Uint32 i=0; i<16; ++i){
  377.     if(voiceA.bufferUser.m.i16[i] != _MX(i16_A[i],-32767)){
  378.       SDL_SetError("i16 type conversion failed (%u: %i != %i)",
  379.         i, voiceA.bufferUser.m.i16[i], _MX(i16_A[i],-32767) ); return -999;
  380.     }
  381.   }
  382.    //i32 (products of conversion are actually approximations with a max error of 64)
  383.   SDL_memcpy(voiceA.bufferUser.m.i32, i32_A, 16*sizeof(Sint32));
  384.   _kit_kmixerVoiceProcFromType(voiceA.bufferUser.m.i32,voiceA.bufferType.m, 16,AUDIO_S32,SDL_FALSE);
  385.   _kit_kmixerVoiceProcToType(voiceA.bufferType.m,voiceA.bufferUser.m.i32, 16,AUDIO_S32,SDL_FALSE);
  386.   for(Uint32 i=0; i<16; ++i){
  387.     if((voiceA.bufferUser.m.i32[i] < (_MX(i32_A[i],-2147483647)-64)) &&
  388.        (voiceA.bufferUser.m.i32[i] > (_MX(i32_A[i],-2147483647)+64)))
  389.     {
  390.       SDL_SetError("i32 type conversion failed (%u: %i != %i)",
  391.         i, voiceA.bufferUser.m.i32[i], _MX(i32_A[i],-2147483647) ); return -999;
  392.     }
  393.   }
  394.    //f32
  395.   SDL_memcpy(voiceA.bufferUser.m.f32, f32_A, 16*sizeof(float));
  396.   _kit_kmixerVoiceProcFromType(voiceA.bufferUser.m.f32,voiceA.bufferType.m, 16,AUDIO_F32,SDL_FALSE);
  397.   _kit_kmixerVoiceProcToType(voiceA.bufferType.m,voiceA.bufferUser.m.f32, 16,AUDIO_F32,SDL_FALSE);
  398.   for(Uint32 i=0; i<16; ++i){
  399.     if(voiceA.bufferUser.m.f32[i] != _CLMP(f32_A[i], -1.0f,1.0f)){
  400.       SDL_SetError("f32 type conversion failed (%u: %f != %f)",
  401.         i, voiceA.bufferUser.m.f32[i], _CLMP(f32_A[i], -1.0f,1.0f) ); return -999;
  402.     }
  403.   }
  404.  
  405.   //test channel conversion
  406.    //  mono-stereo
  407.   _kit_kmixerVoiceProcChannels(f32_A, voiceA.bufferChannel.s, 8,_M_to_S);
  408.   for(Uint32 i=0; i<16; i+=2){
  409.     //printf("%2u: %9f, %9f\n",i, voiceA.bufferChannel.m[i], voiceA.bufferChannel.m[i+1]);
  410.     if(voiceA.bufferChannel.m[i] != voiceA.bufferChannel.m[i+1]){
  411.       SDL_SetError("mono->stereo channel conversion failed (%u: %f != %f)",
  412.         i, voiceA.bufferChannel.m[i], voiceA.bufferChannel.m[i+1] ); return -999;
  413.     }
  414.   }
  415.    //stereo-mono
  416.   _kit_kmixerVoiceProcChannels(f32_A, voiceA.bufferChannel.m,  8,_S_to_M);
  417.   for(Uint32 i=0; i<16; i+=2){
  418.     //printf("%2u: %9f,%9f -> %9f\n",i, f32_A[i],f32_A[i+1], voiceA.bufferChannel.m[i>>1]);
  419.     if(voiceA.bufferChannel.m[i>>1] != (f32_A[i]+f32_A[i+1])*.5f){
  420.       SDL_SetError("stereo->mono channel conversion failed (%u: %f != %f)",
  421.         i, voiceA.bufferChannel.m[i>>1], (f32_A[i]+f32_A[i+1])*.5f ); return -999;
  422.     }
  423.   }
  424.    //stereo-stereo
  425.   _kit_kmixerVoiceProcChannels(f32_A, voiceA.bufferChannel.s,  8,_S_to_S);
  426.   for(Uint32 i=0; i<16; ++i){
  427.     //printf("%2u: %9f\n",i, voiceA.bufferChannel.m[i]);
  428.     if(voiceA.bufferChannel.m[i] != f32_A[i]){
  429.       SDL_SetError("stereo->stereo channel conversion failed (%u: %f != %f)",
  430.         i, voiceA.bufferChannel.m[i], f32_A[i] ); return -999;
  431.     }
  432.   }
  433.    //  mono-mono
  434.   _kit_kmixerVoiceProcChannels(f32_A, voiceA.bufferChannel.m, 16,_M_to_M);
  435.   for(Uint32 i=0; i<16; ++i){
  436.     //printf("%2u: %9f\n",i, voiceA.bufferChannel.m[i]);
  437.     if(voiceA.bufferChannel.m[i] != f32_A[i]){
  438.       SDL_SetError("mono->mono channel conversion failed (%u: %f != %f)",
  439.         i, voiceA.bufferChannel.m[i], f32_A[i] ); return -999;
  440.     }
  441.   }
  442.  
  443.   //test f32 buffer copying
  444.   _kit_kmixerVoiceProcCopy(f32_A, voiceA.bufferOutput.m, 16,0);
  445.   for(Uint32 i=0; i<16; ++i){
  446.     if(voiceA.bufferOutput.m[i] != f32_A[i]){
  447.       SDL_SetError("f32 buffer copying failed (%u: %f != %f)",
  448.         i, voiceA.bufferOutput.m[i], f32_A[i] ); return -999;
  449.     }
  450.   }
  451.  
  452.   //todo: test VoiceProc itself here
  453.  
  454.   //test mixing (might want to add in other volume settings at some point)
  455.   SDL_memcpy(voiceA.bufferOutput.m, f32_A, 16*sizeof(float));
  456.   SDL_memcpy(voiceB.bufferOutput.m, f32_B, 16*sizeof(float));
  457.   _kit_kmixerVoice ivoices[2]={voiceA,voiceB};
  458.    //mono, 1.0,1.0
  459.   _kit_kmixerVoiceMix(&voiceC, ivoices,2);
  460.   for(Uint32 i=0; i<16; ++i){
  461.     float mixed=voiceC.bufferInput.m[i];
  462.     float real=_CLMP(voiceA.bufferOutput.m[i]+voiceB.bufferOutput.m[i], -1.0f,1.0f);
  463.     if(mixed != real){ SDL_SetError("mono, 100%%L,100%%R mixing failed (%u: %.1f != %.1f)",
  464.                          i, mixed, real ); return -999;
  465.     }
  466.   }
  467.    //stereo, 1.0,1.0
  468.   voiceA.stereoOutput=SDL_TRUE;
  469.   voiceB.stereoOutput=SDL_TRUE;
  470.   voiceC.stereoInput =SDL_TRUE;
  471.   voiceA.sampleFrames=8;
  472.   voiceB.sampleFrames=8;
  473.   voiceC.sampleFrames=8;
  474.   _kit_kmixerVoiceMix(&voiceC, ivoices,2);
  475.   for(Uint32 i=0; i<16; ++i){
  476.     float mixed=voiceC.bufferInput.m[i];
  477.     float real=_CLMP(voiceA.bufferOutput.m[i]+voiceB.bufferOutput.m[i], -1.0f,1.0f);
  478.     if(mixed != real){ SDL_SetError("stereo, 100%%L,100%%R mixing failed (%u: %.1f != %.1f)",
  479.                          i, mixed, real ); return -999;
  480.     }
  481.   }
  482.  
  483.   return 0;
  484. }
  485. #else
  486. int kit_kmixerVoiceTest(){
  487.   SDL_SetError("\"_KIT_KMIXER_DEBUG\" was not defined during compilation of kmixer");
  488.   return 999;
  489. }
  490. #endif
  491.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement