Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #ifndef _KIT_KMIXERDEVICEPRIVATE_H
- #define _KIT_KMIXERDEVICEPRIVATE_H
- #include "../../include/kit_sdl2/kit_kmixer.h"
- #include "_kit_privmacro.h"
- #include "_kit_kmixerVoicePrivate.h"
- #ifdef __cplusplus
- extern "C" {
- #endif
- #define _DEV_MAGIC_NUM (0x0076654472786D6B) //="kmxrDev\x00"
- #define _DEVICE_VALIDITY_CHECK(_nullDeviceAllowed) { \
- if(_nullDeviceAllowed){ _IF_GOTO(device==NULL,_noerr_,;) } \
- else { _IF_SDLERR(device==NULL,;,"device cannot be NULL") } \
- _IF_SDLERR(device->_magic.num!=_DEV_MAGIC_NUM,;,"invalid device struct") }
- extern void _kit_kmixerDeviceDoTasks(SDL_ThreadFunction task, kit_coreVector* threads_v,
- kit_coreVector* threadData_v);
- extern int _kit_kmixerDevicePauseThread(void* data);
- extern void _kit_kmixerDeviceCallback(void* userdata, Uint8* _stream, int len);
- static inline void _kit_kmixerDeviceMixThreads(kit_kmixerDevice* device,
- _kit_kmixerVoice** voiceRefs,
- Uint32 stageVoiceLen)
- {
- kit_coreVector* threadData_v = device->_threadData;
- void** threadData = threadData_v->data;
- Uint32 threadData_len = 0; //incremented as data is added
- for(Uint32 vi=0; vi<stageVoiceLen; ++vi){
- _kit_kmixerVoice* voice = voiceRefs[vi];
- if(voice==NULL || voice->lock==NULL) continue; //skip if voice is completely invalid
- //only add the voice to the data queue if it actually has inputs
- if(voice->inputs != NULL) threadData[threadData_len++] = voice;
- }
- VECTOR_LENS_A(threadData_v, 0,0) = threadData_len; //update length to new value
- _kit_kmixerDeviceDoTasks(_kit_kmixerVoiceMix, device->_threads, threadData_v);
- }
- static inline void _kit_kmixerDeviceProcThreads(kit_kmixerDevice* device,
- _kit_kmixerVoice** voiceRefs,
- Uint32 stageVoiceLen)
- {
- kit_coreVector* threadData_v = device->_threadData;
- void** threadData = threadData_v->data;
- Uint32 threadData_len = 0; //incremented as data is added
- for(Uint32 vi=0; vi<stageVoiceLen; ++vi){
- _kit_kmixerVoice* voice = voiceRefs[vi];
- if(voice==NULL || voice->lock==NULL) continue; //skip if voice is completely invalid
- //only add the voice to the data queue if it's not voice 0
- if(voice->output != U32_MAX) threadData[threadData_len++] = voice;
- }
- VECTOR_LENS_A(threadData_v, 0,0) = threadData_len; //update length to new value
- _kit_kmixerDeviceDoTasks(_kit_kmixerVoiceProc, device->_threads, threadData_v);
- }
- //assumes device is already locked
- static inline void _kit_kmixerDeviceStereoFade(kit_kmixerDevice* device,
- kit_acodecPCM_F32S* stream,
- int len)
- {
- //get values from device itself
- float fadeDelta = device->_fadeDelta;
- float fadeVolume = device->_fadeVolume;
- Uint32 fadeInDelay = device->_fadeInDelay;
- Uint32 i = 0; //this index is shared, as the loops can jump to others at will
- //FADING OUT
- if(device->_fadeOut){
- _do_fade_out:
- for(; i<len; ++i){
- if(!device->_fadeOut) goto _do_fade_in;
- stream[i].l *= fadeVolume;
- stream[i].r *= fadeVolume;
- fadeVolume = MAX(fadeVolume-fadeDelta,0);
- }
- //trigger pause thread if fade out is complete
- if(fadeVolume <= 0.0f){
- SDL_Thread* pauseThread = SDL_CreateThread(_kit_kmixerDevicePauseThread,"_PauseTh", device);
- //setting _fadeInDelay to -1 will cause further calls to the device callback
- //to simply memset 0 until kit_kmixerDevicePlay is called again
- if(pauseThread == NULL) device->_fadeInDelay = -1; //0xffffffff
- else SDL_DetachThread(pauseThread); //make sure thread cleans up when finished
- }
- //FADING IN
- } else if(fadeVolume < 1.0f){
- //let device warm up before fading in
- for(; (fadeInDelay)&&(i<len); ++i){ //write 0s for fadeInDelaySeconds
- stream[i].l=stream[i].r = 0; --fadeInDelay;
- }
- _do_fade_in:
- for(; i<len; ++i){
- if(device->_fadeOut) goto _do_fade_out;
- else if(fadeVolume >= 1.0f){ fadeVolume = 1.0f; break; }
- stream[i].l *= fadeVolume;
- stream[i].r *= fadeVolume;
- fadeVolume += fadeDelta;
- }
- }
- //update device struct to any relevant new values
- device->_fadeVolume = fadeVolume; //update fade volume
- device->_fadeInDelay = fadeInDelay; //update fade in delay
- }
- //also assumes device is already locked
- static inline void _kit_kmixerDeviceMonoFade(kit_kmixerDevice* device,
- float* stream, int len)
- {
- //get values from device itself
- float fadeDelta = device->_fadeDelta;
- float fadeVolume = device->_fadeVolume;
- Uint32 fadeInDelay = device->_fadeInDelay;
- Uint32 i = 0; //this index is shared, as the loops can jump to others at will
- //FADING OUT
- if(device->_fadeOut){
- _do_fade_out:
- for(; i<len; ++i){
- if(!device->_fadeOut) goto _do_fade_in;
- stream[i] *= fadeVolume;
- fadeVolume = MAX(fadeVolume-fadeDelta,0);
- }
- //trigger pause thread if fade out is complete
- if(fadeVolume <= 0.0f){
- SDL_Thread* pauseThread = SDL_CreateThread(_kit_kmixerDevicePauseThread,"_PauseTh", device);
- //setting _fadeInDelay to -1 will cause further calls to the device callback
- //to simply memset 0 until kit_kmixerDevicePlay is called again
- if(pauseThread == NULL) device->_fadeInDelay = -1; //0xffffffff
- else SDL_DetachThread(pauseThread); //make sure thread cleans up when finished
- }
- //FADING IN
- } else if(fadeVolume < 1.0f){
- //let device warm up before fading in
- for(; (fadeInDelay)&&(i<len); ++i){ //write 0s for fadeInDelaySeconds
- stream[i] = 0; --fadeInDelay;
- }
- _do_fade_in:
- for(; i<len; ++i){
- if(device->_fadeOut) goto _do_fade_out;
- else if(fadeVolume >= 1.0f){ fadeVolume = 1.0f; break; }
- stream[i] *= fadeVolume;
- fadeVolume += fadeDelta;
- }
- }
- //update device struct to any relevant new values
- device->_fadeVolume = fadeVolume; //update fade volume
- device->_fadeInDelay = fadeInDelay; //update fade in delay
- }
- static inline SDL_AudioSpec _kit_kmixerDeviceVoiceToAudioSpec(kit_kmixerDevice* device,
- const kit_kmixerVoiceSpec* vspec)
- {
- SDL_AudioSpec aspec;
- SDL_bool success = SDL_FALSE;
- aspec.freq = vspec->freq;
- aspec.format = AUDIO_F32;
- aspec.channels = 1+(vspec->stereo&1);
- aspec.samples = vspec->samples;
- aspec.callback = _kit_kmixerDeviceCallback;
- aspec.userdata = device;
- //assuming 44.1kHz, <=16 sample frames would be well under 1ms lol
- //(even at 8kHz, it would still only be 2ms)
- _IF_SDLERR(aspec.samples<32,;,"samples < 32")
- _IF_SDLERR(count_bits(aspec.samples)>1,;,"samples not a power of 2")
- success = SDL_TRUE;
- _error_:
- if(!success) aspec.format = 0; //used to check for failure inside DeviceOpen
- return aspec;
- }
- static inline int _kit_kmixerDeviceFillVoice0(kit_kmixerDevice* device,
- kit_kmixerVoiceSpec* vspec)
- {
- _kit_kmixerVoice* raw = device->_raw->data;
- SDL_bool stereo = vspec->stereo&1;
- Uint32 bufferSize = (sizeof(float)*vspec->samples)<<stereo;
- raw->lock=SDL_CreateMutex();
- _IF_GOTO_ERROR(raw->lock==NULL,;)
- raw->inputs = NULL; //created when a voice gets added
- raw->device = device; //lol
- raw->output = U32_MAX; //unused for voice 0
- raw->timeStamp = SDL_GetTicks();
- //(voice 0's bufferInput is copied to device callback's _stream)
- raw->bufferInput.data = SDL_malloc(bufferSize);
- raw->bufferUser.data = NULL; //unused for voice 0
- raw->bufferConvert.data = NULL; //unused for voice 0
- raw->bufferOutput.data = NULL; //unused for voice 0
- _IF_SDLERR(raw->bufferInput.data==NULL,;,"!voice 0 bufferInput")
- //copy voice spec info
- raw->spec = *vspec;
- //(these two members are exceptions)
- raw->spec._size = bufferSize;
- raw->spec.format = AUDIO_F32;
- raw->chainStage = 0;
- raw->index = 0;
- raw->volL = 1.0f;
- raw->volR = (stereo) ? 1.0f : -1.0f;
- raw->stereoOutput = stereo;
- /*!err*/ return 0;
- _error_: return -1;
- }
- #ifdef __cplusplus
- }
- #endif
- #endif /* _KIT_KMIXERDEVICEPRIVATE_H */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement