Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "../include/kit_sdl2/kit_kmixer.h"
- #include "../_private/include/_kit_privmacro.h"
- #include "../_private/include/_kit_kmixerAllPrivate.h"
- /* example of simd stereo to mono without sse3's hadd
- static inline void _sse1_s_to_m(float* dst, __m128 vector){
- __m128 shuffled = _mm_shuffle_ps(vector,vector, _MM_SHUFFLE(2,3,0,1));
- __m128 sum = _mm_add_ps(vector,shuffled);
- __m128 result = _mm_shuffle_ps(sum,sum, _MM_SHUFFLE(3,1,2,0));
- _mm_storel_pi((__m64*)dst,result);
- }
- */
- //for visual clarity during ProcChannels
- //(this could also just be an enum probably, but w/e)
- #define _M_to_M (0) // mono->mono
- #define _M_to_S (1) // mono->stereo
- #define _S_to_M (2) //stereo->mono
- #define _S_to_S (3) //stereo->stereo
- /* i think i need to fix this
- #define _MM256_SHUFFLE(c7,c6,c5,c4,c3,c2,c1,c0) \
- ((_MM_SHUFFLE(c7,c6,c5,c4)<<8)|_MM_SHUFFLE(c3,c2,c1,c0)) */
- //converts u8, i16, and i32 samples to f32 samples
- //(will basically just copy input to output if input is also f32)
- static inline void _kit_kmixerVoiceProcFromTypeFallback(void* _dataIn, float* dataOut,
- Uint32 numSamples, SDL_AudioFormat typeIn)
- { //if nothing else works
- _mono_samples dataIn = { .ptr = _dataIn };
- float rawSample; //used for max(original_sample,-1) basically
- switch(typeIn){
- case AUDIO_U8 : for(Uint32 i=0; i<numSamples; ++i){ rawSample = (float)(dataIn.u_8[i]-0x80)*invi_8;
- dataOut[i] = (rawSample>=-1.0f)?rawSample:-1.0f; } break;
- case AUDIO_S16: for(Uint32 i=0; i<numSamples; ++i){ rawSample = (float) dataIn.i16[i] *invi16;
- dataOut[i] = (rawSample>=-1.0f)?rawSample:-1.0f; } break;
- case AUDIO_S32: for(Uint32 i=0; i<numSamples; ++i){ rawSample = (float) dataIn.i32[i] *invi32;
- dataOut[i] = (rawSample>=-1.0f)?rawSample:-1.0f; } }
- //('from f32' is skipped inside VoiceProc, thus this code would never run)
- //case AUDIO_F32: for(Uint32 i=0; i<numSamples; ++i){ dataOut[i] = dataIn.f32[i]; } }
- }
- void _kit_kmixerVoiceProcFromType(void* dataIn, void* dataOut,
- Uint32 sampleFrames, SDL_AudioFormat typeIn, SDL_bool isStereo)
- {
- Uint32 numSamples = sampleFrames<<isStereo;
- _kit_kmixerVoiceProcFromTypeFallback(dataIn,dataOut,numSamples,typeIn);
- }
- //converts f32 samples to u8, i16, and i32 samples
- static inline void _kmixerVoiceProcToTypeFallback(float* dataIn, void* _dataOut,
- Uint32 numSamples, SDL_AudioFormat typeOut)
- { //if nothing else works
- _mono_samples dataOut = { .ptr = _dataOut };
- float rawSample, rawSampleB;
- switch(typeOut){
- case AUDIO_U8 : for(Uint32 i=0; i<numSamples; ++i){ rawSample = dataIn[i];
- rawSampleB = (rawSample>=-1.0f)?rawSample:-1.0f;
- dataOut.u_8[i] = (rawSampleB<=1.0f)?rawSampleB*I_8_MAX+0x80:I_8_MAX; } break;
- case AUDIO_S16: for(Uint32 i=0; i<numSamples; ++i){ rawSample = dataIn[i];
- rawSampleB = (rawSample>=-1.0f)?rawSample:-1.0f;
- dataOut.i16[i] = (rawSampleB<=1.0f)?rawSampleB*I16_MAX:I16_MAX; } break;
- case AUDIO_S32: for(Uint32 i=0; i<numSamples; ++i){ rawSample = dataIn[i];
- rawSampleB = (rawSample>=-1.0f)?rawSample:-1.0f;
- dataOut.i32[i] = (rawSampleB<=1.0f)?rawSampleB*I32_MAX:I32_MAX; } break;
- case AUDIO_F32: for(Uint32 i=0; i<numSamples; ++i){ rawSample = dataIn[i];
- rawSampleB = (rawSample>=-1.0f)?rawSample:-1.0f;
- dataOut.f32[i] = (rawSampleB<=1.0f)?rawSampleB:1.0f; } }
- }
- void _kit_kmixerVoiceProcToType(void* dataIn, void* dataOut,
- Uint32 sampleFrames, SDL_AudioFormat typeOut, SDL_bool isStereo)
- {
- Uint32 numSamples = sampleFrames<<isStereo;
- _kmixerVoiceProcToTypeFallback(dataIn,dataOut,numSamples,typeOut);
- }
- //assumes samples are f32
- static inline void _kit_kmixerVoiceProcChannelsFallback(float* dataInM, float* dataOutM,
- Uint32 sampleFrames, int channelInfo)
- { //if nothing else works
- _stereo_samples_f32* dataInS = (void*)dataInM;
- _stereo_samples_f32* dataOutS = (void*)dataOutM;
- switch(channelInfo){
- case _M_to_S: for(Uint32 i=0; i<sampleFrames; ++i){ dataOutS[i].l=dataOutS[i].r = dataInM[i]; } break;
- case _S_to_M: for(Uint32 i=0; i<sampleFrames; ++i){ dataOutM[i] = (dataInS[i].l+dataInS[i].r)*.5f; } break;
- case _S_to_S: sampleFrames<<=1; SDL_FALLTHROUGH; //multiply mono by 2 to make length of stereo
- case _M_to_M: for(Uint32 i=0; i<sampleFrames; ++i){ dataOutM[i] = dataInM[i]; }
- }
- }
- void _kit_kmixerVoiceProcChannels(void* dataIn, void* dataOut, Uint32 sampleFrames, int channelInfo){
- _kit_kmixerVoiceProcChannelsFallback(dataIn,dataOut, sampleFrames,channelInfo);
- }
- #define _CH_INFO(a,b) (((a)<<1)|(b))
- //assumes input AND output samples are f32 (intermediate type is determined by the given voice)
- int _kit_kmixerVoiceProc(void* data){ //(this is an SDL_ThreadFunction)
- _kit_kmixerVoice* voice = data;
- if(voice->lock == NULL) return -1;
- SDL_LockMutex(voice->lock);
- void *ibuffer = voice->bufferInput.v, *obuffer = voice->bufferOutput.v;
- void *ubuffer = voice->bufferUser.v, *cbuffer = voice->bufferConvert.v;
- void *userdata = voice->spec.userdata, *_stream = ubuffer;
- ///
- SDL_bool hasInput = voice->inputs!=NULL;
- SDL_bool ustereo = voice->spec.stereo;
- SDL_bool ostereo = voice->stereoOutput;
- ///
- SDL_AudioFormat uformat = voice->spec.format;
- Uint32 frames = voice->spec.samples, ubuffer_size = voice->spec._size;
- //convert (if necessary) input type (format) from f32
- int userTypeIsF32 = uformat==AUDIO_F32;
- if(userTypeIsF32) _stream = ibuffer; //input and user are identical; just reroute
- else _kit_kmixerVoiceProcToType(ibuffer, ubuffer, frames,uformat,ustereo);
- //the actual user callback
- voice->spec.callback(userdata, _stream, ubuffer_size, hasInput);
- //convert (if necessary) to f32 and channels, sending result to output
- int sameChannels = ustereo==ostereo;
- if(sameChannels){
- //convert type (or just copy contents if _stream is f32)
- _kit_kmixerVoiceProcFromType(_stream,obuffer, frames,uformat,ustereo);
- } else if(userTypeIsF32){ //convert channels
- _kit_kmixerVoiceProcChannels(_stream,obuffer, frames,_CH_INFO(ustereo,ostereo));
- } else { //convert type and channels
- _kit_kmixerVoiceProcFromType(_stream,cbuffer, frames,uformat,ustereo);
- _kit_kmixerVoiceProcChannels(cbuffer,obuffer, frames,_CH_INFO(ustereo,ostereo));
- }
- SDL_UnlockMutex(voice->lock);
- return 0;
- }
- //assumes all samples are f32
- //if nothing else works
- static inline void _kit_kmixerVoiceMixFallback(_kit_kmixerVoice* voiceO){
- if(voiceO->lock == NULL) return; //skip in case voice was removed
- SDL_LockMutex(voiceO->lock);
- Uint32 frames = voiceO->spec.samples;
- //bad things would happen if input buffer is NULL
- memset(voiceO->bufferInput.v, 0, (frames*sizeof(float))<<voiceO->spec.stereo);
- _stereo_samples_f32* osamples = voiceO->bufferInput.s;
- Uint32 samples_len = frames>>(!voiceO->spec.stereo); //so stereo volume can apply to mono
- //do the mixing
- kit_coreVector* inputRefs = voiceO->inputRefs;
- _kit_kmixerVoice** refs = inputRefs->data;
- Uint32 refs_len = inputRefs->x;
- for(Uint32 vi=0; vi<refs_len; ++vi){
- _kit_kmixerVoice* ivoice = refs[vi];
- if(ivoice->lock == NULL) continue; //skip in case voice was removed
- SDL_LockMutex(ivoice->lock);
- _stereo_samples_f32* isamples = ivoice->bufferOutput.s;
- float volL = ivoice->volL, volR = ivoice->volR;
- volL = MIN(volL,1.0f); volR = MIN(volR, 1.0f);
- if(!ivoice->stereoOutput) volR = volL;
- if(volL==0 && volR==0) continue; //if volume is effectively muted, then skip the voice
- else if(volL==1.0f && volR==1.0f) goto _do_not_apply_volume; //because sample*1=sample
- else if((volL>=0) && ivoice->applyVolume){
- if(volR<0) volR = volL;
- for(Uint32 i=0; i<samples_len; ++i){
- osamples[i].l += isamples[i].l*volL;
- osamples[i].r += isamples[i].r*volR;
- }
- } else { _do_not_apply_volume:
- for(Uint32 i=0; i<samples_len; ++i){
- osamples[i].l += isamples[i].l;
- osamples[i].r += isamples[i].r;
- }
- }
- SDL_UnlockMutex(ivoice->lock);
- }
- //hard clip output samples to between -1.0f and 1.0f
- for(Uint32 i=0; i<samples_len; ++i){
- float sampleL = osamples[i].l;
- float sampleR = osamples[i].r;
- osamples[i].l = CLAMP(sampleL, -1.0f,1.0f);
- osamples[i].r = CLAMP(sampleR, -1.0f,1.0f);
- }
- SDL_UnlockMutex(voiceO->lock);
- }
- void _kit_kmixerVoiceMix(_kit_kmixerVoice* voiceO){
- _kit_kmixerVoiceMixFallback(voiceO);
- }
- //used to check whether an element in the raw voice list is valid or not
- SDL_bool _kit_kmixerDeviceRawUnitCallback(void* unit, Uint32 size){
- _kit_kmixerVoice* voice = unit;
- return voice->lock == NULL;
- }
- //same thing, but with ord instead of raw
- SDL_bool _kit_kmixerDeviceOrdUnitCallback(void* unit, Uint32 size){
- _kit_kmixerVoice** voice_p = unit;
- if(*voice_p == NULL) return SDL_TRUE;
- return (*voice_p)->lock == NULL;
- }
- int kit_kmixerVoiceRemove(kit_kmixerDevice* device, Uint32 voiceID){
- _IF_SDLERR(device==NULL,;,"device cannot be NULL")
- _IF_SDLERR(device->_magic.num!=_DEV_MAGIC_NUM,;,"invalid device struct")
- //only allow voice 0 to be removed when device->_closing is set
- _IF_SDLERR(!voiceID && !device->_closing,;,"cannot remove voice 0")
- //if bit 31 is set, call is assumed to be the result of recursion
- SDL_bool rootCall = (!(voiceID&U32_MSb)) ? SDL_TRUE : SDL_FALSE;
- voiceID &= I32_MAX; //unset bit 31 now that rootCall is set
- kit_coreVector** raw_p = &device->_voices.raw;
- _kit_kmixerVoice* voiceI = &VECTOR_INDEX_C(_kit_kmixerVoice, *raw_p, voiceID);
- _IF_GOTO(voiceI->lock==NULL,_noerr_,;) //return normally if voice already removed
- _IF_GOTO_ERROR(SDL_LockMutex(voiceI->lock),;)
- //loop through and remove any inputs the voice might have (recursive)
- if(voiceI->inputs != NULL){
- Uint32* inputs = voiceI->inputs->data;
- Uint32 inputs_len = voiceI->inputs->x;
- _kit_kmixerVoice* raw = (*raw_p)->data;
- for(Uint32 i=0; i<inputs_len; ++i){
- Uint32 index = inputs[i];
- if(!index) continue; //an index of 0 indicates a voice that was already removed
- if(raw[index].lock != NULL) //(bit 31 is set to indicate recursion)
- _IF_GOTO_ERROR(kit_kmixerVoiceRemove(device,U32_MSb|index),;)
- }
- //(kit_coreVectorDestroy automatically sets pointer to NULL)
- _IF_GOTO_ERROR(kit_coreVectorDestroy(&voiceI->inputs),;)
- _IF_GOTO_ERROR(kit_coreVectorDestroy(&voiceI->inputRefs),;)
- }
- //free buffers
- SAFE_FREE(voiceI->bufferInput.v);
- SAFE_FREE(voiceI->bufferUser.v);
- SAFE_FREE(voiceI->bufferConvert.v);
- SAFE_FREE(voiceI->bufferOutput.v);
- //call the user's 'userdata removal' callback
- if(voiceI->spec.remove != NULL) voiceI->spec.remove(voiceI->spec.userdata);
- _IF_GOTO_ERROR(SDL_UnlockMutex(voiceI->lock),;)
- SDL_DestroyMutex(voiceI->lock);
- voiceI->lock = NULL; //a mutex of NULL indicates a removed voice
- //remove reference from ord
- _kit_kmixerVoiceRemoveFromOrd(device, voiceI); //this can't error (yay!)
- if(rootCall){ //if this call is not the result of recursion
- //trim raw and ord
- _IF_GOTO_ERROR(kit_coreVectorTrim(&device->_voices.raw,'x',_kit_kmixerDeviceRawUnitCallback),;)
- _IF_GOTO_ERROR(kit_coreVectorTrim(&device->_voices.ord,0,_kit_kmixerDeviceOrdUnitCallback),;)
- //trim inputs of output voice, potentially destroying inputs if none are left
- voiceI = &VECTOR_INDEX_C(_kit_kmixerVoice, *raw_p, voiceID);
- _kit_kmixerVoice* voiceO = voiceI->output;
- _IF_GOTO(voiceO==NULL,_noerr_,;) //voice 0 doesn't have an output, for example
- _IF_GOTO_ERROR(_kit_kmixerVoiceRemoveInput(voiceO,voiceI->index),;)
- }
- _noerr_: return 0; // 0 on success
- _error_: return -1; //-1 on failure
- }
- Uint32 kit_kmixerVoiceAdd(kit_kmixerDevice* device, kit_kmixerVoiceSpec* spec,
- Uint32 outputVoiceID)
- {
- Sint32 newIndex = 0; //0 for error by default
- _kit_kmixerVoice voice = { .lock = NULL }; //voice struct to be copied to raw
- _kit_kmixerVoice* voiceI = NULL; //reference to voice inside raw
- SDL_bool inRaw = SDL_FALSE; //set to true if successfully inserted into raw
- SDL_bool success = SDL_FALSE;
- _IF_SDLERR(device==NULL,;,"device cannot be NULL")
- _IF_SDLERR(device->_magic.num!=_DEV_MAGIC_NUM,;,"invalid device struct")
- _IF_GOTO_ERROR(kit_kmixerDeviceLock(device,SDL_TRUE),;)
- //get reference to output voice
- kit_coreVector** raw_p = &device->_voices.raw;
- Uint32 raw_len = (*raw_p)->x;
- _IF_SDLERR(outputVoiceID>=raw_len,;,"outputVoiceID > voice list size")
- _kit_kmixerVoice* voiceO = &VECTOR_INDEX_C(_kit_kmixerVoice, *raw_p, outputVoiceID);
- _IF_SDLERR(voiceO->lock==NULL,;,"output voice is nonexistent")
- //fill in info for voice spec and the voice struct itself
- _IF_GOTO_ERROR(_kit_kmixerVoiceAddFillSpec(device, spec),;)
- _IF_GOTO_ERROR(_kit_kmixerVoiceAddFillVoice(spec, voiceO, &voice),;)
- //add voice to raw
- newIndex = kit_coreVectorInsert(raw_p, &voice, 0,0, _kit_kmixerDeviceRawUnitCallback);
- _IF_GOTO_ERROR(newIndex<0,;)
- voiceI = &VECTOR_INDEX_C(_kit_kmixerVoice, *raw_p, newIndex);
- voiceI->index = newIndex;
- inRaw = SDL_TRUE;
- //add voice's reference to ord
- _IF_GOTO_ERROR(_kit_kmixerVoiceAddToOrd(device, voiceI),;)
- //add voice to output's input list
- voiceO = &VECTOR_INDEX_C(_kit_kmixerVoice, *raw_p, outputVoiceID);
- _IF_GOTO_ERROR(_kit_kmixerVoiceAddInput(voiceO, voiceI),;)
- success = SDL_TRUE;
- _error_:
- if(!success){
- if(inRaw){
- if(voiceI->lock != NULL) SDL_DestroyMutex(voiceI->lock);
- kit_coreVectorDestroy(&voiceI->inputs);
- kit_coreVectorDestroy(&voiceI->inputRefs);
- SAFE_FREE(voiceI->bufferInput.v);
- SAFE_FREE(voiceI->bufferUser.v);
- SAFE_FREE(voiceI->bufferConvert.v);
- SAFE_FREE(voiceI->bufferOutput.v);
- voiceI->lock = NULL;
- } else { //only remove the stack version of voice
- if(voice.lock != NULL) SDL_DestroyMutex(voice.lock);
- kit_coreVectorDestroy(&voice.inputs);
- kit_coreVectorDestroy(&voice.inputRefs);
- SAFE_FREE(voice.bufferInput.v);
- SAFE_FREE(voice.bufferUser.v);
- SAFE_FREE(voice.bufferConvert.v);
- SAFE_FREE(voice.bufferOutput.v);
- }
- newIndex = 0;
- }
- kit_kmixerDeviceLock(device, SDL_FALSE);
- return newIndex;
- }
- int kit_kmixerVoiceRedirect(kit_kmixerDevice* device,
- Uint32 inputVoiceID, Uint32 outputVoiceID)
- {
- int returnStatus = 0;
- _IF_SDLERR(device==NULL,;,"device cannot be NULL")
- _IF_SDLERR(device->_magic.num!=_DEV_MAGIC_NUM,;,"invalid device struct")
- _IF_GOTO_ERROR(kit_kmixerDeviceLock(device,SDL_TRUE),;)
- kit_coreVector** raw_p = &device->_voices.raw;
- Uint32 raw_len = (*raw_p)->x;
- _IF_SDLERR(outputVoiceID>=raw_len,;,"outputVoiceID > voice list size")
- _kit_kmixerVoice* voiceI = &VECTOR_INDEX_C(_kit_kmixerVoice, *raw_p, inputVoiceID);
- _kit_kmixerVoice* voiceO = &VECTOR_INDEX_C(_kit_kmixerVoice, *raw_p, outputVoiceID);
- _kit_kmixerVoice* voiceO_old = voiceI->output;
- _IF_SDLERR(voiceO->lock==NULL,;,"output voice is nonexistent")
- _IF_GOTO_ERROR(_kit_kmixerVoiceRemoveInput(voiceO_old, inputVoiceID),;)
- _IF_GOTO_ERROR(_kit_kmixerVoiceAddInput(voiceO, voiceI),;)
- _kit_kmixerVoiceRemoveFromOrd(device, voiceI);
- voiceI->output = voiceO;
- voiceI->chainStage = voiceO->chainStage+1;
- voiceI->stereoOutput = voiceO->spec.stereo;
- _IF_GOTO_ERROR(_kit_kmixerVoiceAddToOrd(device, voiceI),;)
- /*!err*/ ++returnStatus;
- _error_: --returnStatus;
- kit_kmixerDeviceLock(device,SDL_FALSE);
- return returnStatus;
- }
- #if defined(_KIT_KMIXER_DEBUG) || defined(_KIT_ALL_DEBUG)
- void _kit_kmixerVoice_TestCallback(void* userdata, void* _stream, int size, SDL_bool hasInput){
- }
- /*
- because kmixer compiles with -O3, i get this error if i attempt to compile the test:
- "warning: may be used uninitialized in this function [-Wmaybe-uninitialized]|"
- i have very little doubt that this is a bug, so i can't do much about it other than
- turn down optimization for this specific function
- */
- //(for some reason, it started working again after i added some seemingly
- //unrelated stuff, so i'll comment this out for now)
- //__attribute__((optimize("-O0")))
- int kit_kmixerVoice_Test(){
- float bufferInputA[16], bufferUserA[16], bufferConvertA[16], bufferOutputA[16];
- float bufferInputB[16], bufferUserB[16], bufferConvertB[16], bufferOutputB[16];
- float bufferInputC[16], bufferUserC[16], bufferConvertC[16], bufferOutputC[16];
- _kit_kmixerVoice voiceA={
- .spec={
- .callback = _kit_kmixerVoice_TestCallback,
- .userdata = NULL,
- .freq = 44100,
- ._size = 16*sizeof(float),
- .stereo = SDL_FALSE,
- .samples = 16,
- .format = AUDIO_F32
- },
- .bufferInput = { .v=bufferInputA },
- .bufferUser = { .v=bufferUserA },
- .bufferConvert = { .v=bufferConvertA },
- .bufferOutput = { .v=bufferOutputA },
- .inputs = NULL,
- .lock = NULL,
- .chainStage = 2,
- .index = 3,
- .volL = 1.0f,
- .volR = 1.0f,
- .applyVolume = SDL_TRUE,
- .stereoOutput = SDL_FALSE,
- };
- _kit_kmixerVoice voiceB={
- .spec={
- .callback = _kit_kmixerVoice_TestCallback,
- .userdata = NULL,
- .freq = 44100,
- ._size = 16*sizeof(float),
- .stereo = SDL_FALSE,
- .samples = 16,
- .format = AUDIO_F32
- },
- .bufferInput = { .v=bufferInputB },
- .bufferUser = { .v=bufferUserB },
- .bufferConvert = { .v=bufferConvertB },
- .bufferOutput = { .v=bufferOutputB },
- .inputs = NULL,
- .lock = NULL,
- .chainStage = 2,
- .index = 2,
- .volL = 1.0f,
- .volR = 1.0f,
- .applyVolume = SDL_TRUE,
- .stereoOutput = SDL_FALSE,
- };
- _kit_kmixerVoice voiceC={
- .spec={
- .callback = _kit_kmixerVoice_TestCallback,
- .userdata = NULL,
- .freq = 44100,
- ._size = 16*sizeof(float),
- .stereo = SDL_FALSE,
- .samples = 16,
- .format = AUDIO_F32
- },
- .bufferInput = { .v=bufferInputC },
- .bufferUser = { .v=bufferUserC },
- .bufferConvert = { .v=bufferConvertC },
- .bufferOutput = { .v=bufferOutputC },
- .inputs = NULL,
- .lock = NULL,
- .chainStage = 1,
- .index = 1,
- .volL = 1.0f,
- .volR = 1.0f,
- .applyVolume = SDL_TRUE,
- .stereoOutput = SDL_FALSE,
- };
- //example streams
- Uint8 u_8_A[16]={0x00,0x3F,0x10,0x80,0xFF,0x4E,0x24,0x6D,0x21,0xFE,0xED,0x86,0x3A,0xAB,0xDA,0x4C};
- Sint16 i16_A[16]={-32768,13106,-16384,6553,32767,2553,-26214,25937,22337,-13102,9553,-32467,-9830,0,-19661,-22938};
- Sint32 i32_A[16]={-2147483648,2147483647,2,547760950,-978102134,-1901782676,973752665,-2054956051,-1793070550,2100284199,1386177656,-70287364,-799099289,-594127329,1025429360,-570645197};
- 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};
- 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};
- //test to and from type conversion
- //u_8
- SDL_memcpy(voiceA.bufferUser.m.u_8, u_8_A, 16*sizeof(Uint8));
- _kit_kmixerVoiceProcFromType(voiceA.bufferUser.m.u_8,voiceA.bufferConvert.m, 16,AUDIO_U8,SDL_FALSE);
- _kit_kmixerVoiceProcToType(voiceA.bufferConvert.m,voiceA.bufferUser.m.u_8, 16,AUDIO_U8,SDL_FALSE);
- for(Uint32 i=0; i<16; ++i){
- if(voiceA.bufferUser.m.u_8[i] != MAX(u_8_A[i],1)){
- SDL_SetError("u_8 type conv. (%u:%X!=%X)",
- i, voiceA.bufferUser.m.u_8[i], MAX(u_8_A[i],1) ); return -999;
- }
- }
- //i16
- SDL_memcpy(voiceA.bufferUser.m.i16, i16_A, 16*sizeof(Sint16));
- _kit_kmixerVoiceProcFromType(voiceA.bufferUser.m.i16,voiceA.bufferConvert.m, 16,AUDIO_S16,SDL_FALSE);
- _kit_kmixerVoiceProcToType(voiceA.bufferConvert.m,voiceA.bufferUser.m.i16, 16,AUDIO_S16,SDL_FALSE);
- for(Uint32 i=0; i<16; ++i){
- if(voiceA.bufferUser.m.i16[i] != MAX(i16_A[i],-32767)){
- SDL_SetError("i16 type conv. (%u:%i!=%i)",
- i, voiceA.bufferUser.m.i16[i], MAX(i16_A[i],-32767) ); return -999;
- }
- }
- //i32 (products of conversion are actually approximations with a max error of 64)
- SDL_memcpy(voiceA.bufferUser.m.i32, i32_A, 16*sizeof(Sint32));
- _kit_kmixerVoiceProcFromType(voiceA.bufferUser.m.i32,voiceA.bufferConvert.m, 16,AUDIO_S32,SDL_FALSE);
- _kit_kmixerVoiceProcToType(voiceA.bufferConvert.m,voiceA.bufferUser.m.i32, 16,AUDIO_S32,SDL_FALSE);
- for(Uint32 i=0; i<16; ++i){
- if((voiceA.bufferUser.m.i32[i] < (MAX(i32_A[i],-2147483647)-64)) &&
- (voiceA.bufferUser.m.i32[i] > (MAX(i32_A[i],-2147483647)+64)))
- {
- SDL_SetError("i32 type conv. (%u:%i!=%i)",
- i, voiceA.bufferUser.m.i32[i], MAX(i32_A[i],-2147483647) ); return -999;
- }
- }
- //f32
- SDL_memcpy(voiceA.bufferUser.m.f32, f32_A, 16*sizeof(float));
- _kit_kmixerVoiceProcFromType(voiceA.bufferUser.m.f32,voiceA.bufferConvert.m, 16,AUDIO_F32,SDL_FALSE);
- _kit_kmixerVoiceProcToType(voiceA.bufferConvert.m,voiceA.bufferUser.m.f32, 16,AUDIO_F32,SDL_FALSE);
- for(Uint32 i=0; i<16; ++i){
- if(voiceA.bufferUser.m.f32[i] != CLAMP(f32_A[i], -1.0f,1.0f)){
- SDL_SetError("f32 type conv. (%u:%.1f!=%.1f)",
- i, voiceA.bufferUser.m.f32[i], CLAMP(f32_A[i], -1.0f,1.0f) ); return -999;
- }
- }
- //test channel conversion
- // mono-stereo
- _kit_kmixerVoiceProcChannels(f32_A, voiceA.bufferConvert.s, 8,_M_to_S);
- for(Uint32 i=0; i<16; i+=2){
- //SDL_Log("%2u: %9f, %9f",i, voiceA.bufferConvert.m[i], voiceA.bufferConvert.m[i+1]);
- if(voiceA.bufferConvert.m[i] != voiceA.bufferConvert.m[i+1]){
- SDL_SetError("mn.->st. convert (%u:%.1f!=%.1f)",
- i, voiceA.bufferConvert.m[i], voiceA.bufferConvert.m[i+1] ); return -999;
- }
- }
- //stereo-mono
- _kit_kmixerVoiceProcChannels(f32_A, voiceA.bufferConvert.m, 8,_S_to_M);
- for(Uint32 i=0; i<16; i+=2){
- //SDL_Log("%2u: %9f,%9f -> %9f",i, f32_A[i],f32_A[i+1], voiceA.bufferConvert.m[i>>1]);
- if(voiceA.bufferConvert.m[i>>1] != (f32_A[i]+f32_A[i+1])*.5f){
- SDL_SetError("st.->mn. convert (%u:%.1f!=%.1f)",
- i, voiceA.bufferConvert.m[i>>1], (f32_A[i]+f32_A[i+1])*.5f ); return -999;
- }
- }
- //stereo-stereo
- _kit_kmixerVoiceProcChannels(f32_A, voiceA.bufferConvert.s, 8,_S_to_S);
- for(Uint32 i=0; i<16; ++i){
- //SDL_Log("%2u: %9f",i, voiceA.bufferConvert.m[i]);
- if(voiceA.bufferConvert.m[i] != f32_A[i]){
- SDL_SetError("st.->st. convert (%u:%.1f!=%.1f)",
- i, voiceA.bufferConvert.m[i], f32_A[i] ); return -999;
- }
- }
- // mono-mono
- _kit_kmixerVoiceProcChannels(f32_A, voiceA.bufferConvert.m, 16,_M_to_M);
- for(Uint32 i=0; i<16; ++i){
- //SDL_Log("%2u: %9f",i, voiceA.bufferConvert.m[i]);
- if(voiceA.bufferConvert.m[i] != f32_A[i]){
- SDL_SetError("mn.->mn. convert (%u:%.1f!=%.1f)",
- i, voiceA.bufferConvert.m[i], f32_A[i] ); return -999;
- }
- }
- //test VoiceProc itself here
- //test mixing (might want to add in other volume settings at some point)
- voiceA.lock=SDL_CreateMutex();
- voiceB.lock=SDL_CreateMutex();
- voiceC.lock=SDL_CreateMutex();
- kit_coreVector* ivoices=kit_coreVectorCreate(2,0,0, sizeof(_kit_kmixerVoice),0);
- if(voiceA.lock==NULL || voiceB.lock==NULL || voiceC.lock==NULL || ivoices==NULL){
- if(voiceA.lock != NULL) SDL_DestroyMutex(voiceA.lock);
- if(voiceB.lock != NULL) SDL_DestroyMutex(voiceB.lock);
- if(voiceC.lock != NULL) SDL_DestroyMutex(voiceC.lock);
- if(ivoices != NULL) kit_coreVectorDestroy(&ivoices);
- }
- SDL_memcpy(voiceA.bufferOutput.m, f32_A, 16*sizeof(float));
- SDL_memcpy(voiceB.bufferOutput.m, f32_B, 16*sizeof(float));
- _kit_kmixerVoice _ivoices[2]={voiceA,voiceB};
- memcpy(ivoices->data, _ivoices, sizeof(_kit_kmixerVoice)*2);
- //mono, 1.0,1.0
- _kit_kmixerVoiceMix(&voiceC);
- for(Uint32 i=0; i<16; ++i){
- float mixed=voiceC.bufferInput.m[i];
- float real=CLAMP(voiceA.bufferOutput.m[i]+voiceB.bufferOutput.m[i], -1.0f,1.0f);
- if(mixed != real){ SDL_SetError("mn. mixing (%u:%.1f!=%.1f)",
- i, mixed, real ); return -999;
- }
- }
- //stereo, 1.0,1.0
- voiceA.stereoOutput=SDL_TRUE;
- voiceB.stereoOutput=SDL_TRUE;
- voiceA.spec.samples=8;
- voiceB.spec.samples=8;
- voiceC.spec.samples=8;
- _kit_kmixerVoiceMix(&voiceC);
- for(Uint32 i=0; i<16; ++i){
- float mixed=voiceC.bufferInput.m[i];
- float real=CLAMP(voiceA.bufferOutput.m[i]+voiceB.bufferOutput.m[i], -1.0f,1.0f);
- if(mixed != real){ SDL_SetError("st. mixing (%u:%.1f!=%.1f)",
- i, mixed, real ); return -999;
- }
- }
- if(voiceA.lock != NULL) SDL_DestroyMutex(voiceA.lock);
- if(voiceB.lock != NULL) SDL_DestroyMutex(voiceB.lock);
- if(voiceC.lock != NULL) SDL_DestroyMutex(voiceC.lock);
- if(ivoices != NULL) kit_coreVectorDestroy(&ivoices);
- //test adding and removing possibly
- //kit_coreLog("sizeof(_kit_kmixerVoice)=%u",(unsigned int)sizeof(_kit_kmixerVoice));
- return 0;
- }
- void kit_kmixerVoicePrintRawOrd(kit_kmixerDevice* device){
- kit_coreVector** raw_p = &device->_voices.raw;
- kit_coreVector** ord_p = &device->_voices.ord;
- Uint32 rawLen = (*raw_p)->x;
- Uint32 ordLen = (*ord_p)->x;
- Uint32 maxStage = (*ord_p)->y-1;
- _kit_kmixerVoice* raw = (*raw_p)->data;
- _kit_kmixerVoice** ord = (*ord_p)->data;
- printf("\n~~~ RAW ~~~\n");
- for(Uint32 v=0; v<rawLen; ++v){
- _kit_kmixerVoice* voice = &raw[v];
- Uint32 numInputs = 0;
- Uint32* inputs = NULL;
- _kit_kmixerVoice** inputRefs = NULL;
- if(voice->inputs != NULL){
- numInputs = voice->inputs->x;
- inputs = voice->inputs->data;
- inputRefs = voice->inputRefs->data;
- }
- printf("--- %02u/%02u (%p) ---\n", v, rawLen-1, voice);
- printf(" voice%u->inputs = %p: ",v, voice->inputs);
- if(inputs != NULL){
- printf("{\n ");
- for(Uint32 i=0; i<numInputs; ++i){
- printf("%02u, ",inputs[i]);
- if((i+1)==numInputs) printf("\n");
- else if((i%5)==4) printf("\n ");
- }
- printf(" }\n");
- } else printf("(NULL)\n");
- printf(" voice%u->inputRefs = %p: ",v, voice->inputRefs);
- if(inputRefs != NULL){
- printf("{\n ");
- for(Uint32 i=0; i<numInputs; ++i){
- printf("%p, ",inputRefs[i]);
- if((i+1)==numInputs) printf("\n");
- else if((i%5)==4) printf("\n ");
- }
- printf(" }\n");
- } else printf("(NULL)\n");
- printf(" voice%u->output = %p\n",v, voice->output);
- printf(" voice%u->chainStage = %u\n",v, voice->chainStage);
- printf(" voice%u->index = %u\n",v, voice->index);
- printf("\n");
- }
- printf("\n~~~ ORD ~~~\n");
- for(Uint32 yi=maxStage; yi!=U32_MAX; --yi){
- printf("stage %02u: ", yi);
- for(Uint32 xi=0; xi<ordLen; ++xi){
- _kit_kmixerVoice* voice = ord[xi + yi*ordLen];
- if(voice == NULL) printf("NL, ");
- else if(voice->lock == NULL) printf("RM, ");
- else printf("%p, ",voice);
- //else printf("%02u, ",voice->index);
- }
- printf("\n");
- }
- printf("\n");
- }
- #else
- int kit_kmixerVoice_Test(){
- SDL_SetError("!defined(_KIT_KMIXER_DEBUG)");
- return 999;
- }
- void kit_kmixerVoicePrintRawOrd(kit_kmixerDevice* device){}
- #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement