Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #ifndef _KIT_KMIXERASYNCPRIVATE_H
- #define _KIT_KMIXERASYNCPRIVATE_H
- #include "../../include/kit_sdl2/kit_core.h"
- #ifdef __cplusplus
- extern "C" {
- #endif
- typedef enum _udata_types {
- type_UDAT = 0x54414455, // = "UDAT"
- type_TRCK = 0x4B435254, // = "TRCK"
- } _udata_types;
- typedef struct _kit_kmixerAsyncTrack { //88B
- //type, pan, ..., stopOnMute are identical to that of AsyncUserdata,
- //so they can be casted and used interchangably
- _udata_types type; // = "TRCK"
- float pan; //the current pan of the track; -1.0f -> 1.0f (applied AFTER volume)
- kit_acodecPCM_F32S volume; //left and right channel volumes; 0.0f -> 1.0f (.r ignored if mono)
- kit_acodecPCM_F32S delta; //determines the rate at which volume changes each sample (.r ignored if mono)
- SDL_bool stopOnMute; //'deactivate track when volume or speed reaches 0?'
- SDL_bool linear; //use linear interpolation if true, nearest-neighbor if false
- _kit_kmixerVoice* voice; //a reference to the track's voice
- kit_acodecPCM* pcm; //the actual audio data (this should be NULL if the track is inactive)
- Uint64* deviceTimeStamp; //a pointer to the device callback's timeStamp (read-only)
- Uint64 timeStamp; //result of SDL_GetTicks64() called at time of queueing an audio clip
- double position; //sample position, including fraction
- kit_acodecPCM_F32S prevSample; //the value of the previous sample; used for interpolation
- float speed; //what amount to increment position by every sample
- float deltaS; //what number to apply to speed every sample
- Uint32 rawIndex; //the voice's index inside the device's raw voice list
- Uint16 loops; //number of times to loop before deactivating clip (-1 for endless loop)
- Uint16 _padding16;
- } _kit_kmixerAsyncTrack;
- //this should be contiguous with the AsyncTrack(s)
- typedef struct _kit_kmixerAsyncUserdata { //48B
- _udata_types type; // = "UDAT"
- float pan; //the current pan of the main voice; -1.0f -> 1.0f (applied AFTER volume)
- kit_acodecPCM_F32S volume; //left and right channel volumes; 0.0f -> 1.0f (.r ignored if mono)
- kit_acodecPCM_F32S delta; //determines the rate at which volume changes each sample (.r ignored if mono)
- SDL_bool stopOnMute; //'stop all tracks when main voice's volume reaches 0?'
- Uint32 numTracks; //number of total tracks that can play at once
- _kit_kmixerVoice* voice; //a reference to the main voice's actual voice struct
- _kit_kmixerAsyncTrack* tracks; //array of track structs of length numTracks
- } _kit_kmixerAsyncUserdata;
- /* LOOP CHECK */
- #define _mono_0 dst[i] = 0;
- #define _stereo_0 dst[i].l = 0, dst[i].r = 0;
- #define _loop_check(_dst_0) { \
- if(pcm == NULL){ _dst_0; continue; } /*0 for silent sample if inactive*/ \
- if(position >= loopEnd){ /*clip finished loop*/ \
- if(!loops){ pcm = NULL; _dst_0; continue; } /*mark track as inactive*/ \
- if(loops != -1) --loops; /*decrement loops unless infinite*/ \
- position -= (Uint64)position; /*pos %= 1*/ \
- position += loopStart; /*new_pos = loopStart + old_pos%1*/ \
- } else if(position<0){ /*clip has yet to play*/ \
- if(position < -speed){ \
- position += speed; /*step forward position by current speed*/ \
- _dst_0; continue; /*0 for silent sample*/ \
- } else { /*if position >= -speed, the clip should start next sample*/ \
- position = 1; /*make sure the clip starts at 1*/ \
- continue; \
- } \
- } }
- /* SAMPLE */
- static inline float _mono_nearest(float* src, double position, float prevSample){
- Uint64 positionRound = (Uint64)(position+0.5);
- if(positionRound >= position) return src[positionRound];
- else return prevSample;
- }
- static inline kit_acodecPCM_F32S _stereo_nearest(kit_acodecPCM_F32S* src, double position,
- kit_acodecPCM_F32S prevSample)
- {
- Uint64 positionRound = (Uint64)(position+0.5);
- if(positionRound >= position){
- kit_acodecPCM_F32S smp;
- smp.l = src[positionRound].l;
- smp.r = src[positionRound].r;
- return smp;
- } else {
- return prevSample;
- }
- }
- static inline float _mono_linear(float* src, double position, float prevSample){
- Uint64 intPosition = (Uint64)position;
- double modPosition = position - intPosition; // = position % 1
- //modPosition is used as a percentage value for lerp
- float smpOut = LERP2(prevSample, src[++intPosition], modPosition);
- return smpOut;
- }
- static inline kit_acodecPCM_F32S _stereo_linear(kit_acodecPCM_F32S* src, double position,
- kit_acodecPCM_F32S prevSample)
- {
- Uint64 intPosition = (Uint64)position;
- double modPosition = position - intPosition; // = position % 1
- kit_acodecPCM_F32S nextSample = src[++intPosition];
- //modPosition is used as a percentage value for lerp
- kit_acodecPCM_F32S smpOut;
- smpOut.l = LERP2(prevSample.l, nextSample.l, modPosition);
- smpOut.r = LERP2(prevSample.r, nextSample.r, modPosition);
- return smpOut;
- }
- /* VOLUME */
- static inline float _mono_volume(float sample, _kit_kmixerAsyncTrack* track){
- return sample * track->volume.l;
- }
- static inline kit_acodecPCM_F32S _stereo_volume(kit_acodecPCM_F32S sample,
- _kit_kmixerAsyncTrack* track)
- {
- sample.l *= track->volume.l;
- sample.r *= track->volume.r;
- return sample;
- }
- /* CLAMP */
- static inline float _mono_clamp(float sample){
- return CLAMP(sample, -1.0f,1.0f);
- }
- static inline kit_acodecPCM_F32S _stereo_clamp(kit_acodecPCM_F32S sample){
- sample.l = CLAMP(sample.l, -1.0f,1.0f);
- sample.r = CLAMP(sample.r, -1.0f,1.0f);
- return sample;
- }
- /* PAN */
- static inline kit_acodecPCM_F32S _apply_pan(kit_acodecPCM_F32S smp, float pan){
- //(i think this is how audacity does it...)
- pan = CLAMP(pan, -1.0f,1.0f);
- if(pan < 0){
- smp.l += smp.r*(-pan);
- smp.r *= 1.0f+pan;
- } else if(pan > 0){
- smp.r += smp.l*pan;
- smp.l *= 1.0f-pan;
- }
- return smp;
- }
- /* DELTAVOL */
- static inline void _mono_deltaVol(_kit_kmixerAsyncTrack* track){
- track->volume.l += track->delta.l;
- track->volume.l = CLAMP(track->volume.l, 0.0f,1.0f);
- }
- static inline void _stereo_deltaVol(_kit_kmixerAsyncTrack* track){
- _mono_deltaVol(track); //for volume.l and delta.l
- track->volume.r += track->delta.r;
- track->volume.r = CLAMP(track->volume.r, 0.0f,1.0f);
- }
- /* SPEED */ //(using a define for this is unnecessary)
- //#define _apply_speed position += speed;
- /* DELTAS */ //(using a define for this is unnecessary)
- //#define _apply_deltaS speed = MAX(speed+track->deltaS,0);
- /* LOOP FLOW */
- /* loop flow order:
- _loop_check(_<m/s>_0)
- _<m/s>_<nearest,linear>()
- _<m/s>_volume()
- _<m/s>_clamp()
- _apply_pan() (stereo only!)
- prevSample = src[(Uint64)position]
- _<m/s>_deltaVol(track)
- position += speed;
- speed += track->deltaS;
- if(speed < 0) speed = 0;
- (repeat) */
- #define _stereo_iteration(_interpolation_mode) { \
- _loop_check(_stereo_0) \
- kit_acodecPCM_F32S sample = _interpolation_mode(src,position,prevSample); \
- sample = _stereo_clamp(_stereo_volume(sample,track)); \
- dst[i] = _apply_pan(sample,pan); \
- prevSample = src[(Uint64)position]; \
- _stereo_deltaVol(track); \
- position += speed; \
- speed += track->deltaS; \
- if(speed < 0) speed = 0; }
- #define _mono_iteration(_interpolation_mode) { \
- _loop_check(_mono_0) \
- float sample = _interpolation_mode(src,position,prevSample); \
- dst[i] = _mono_clamp(_mono_volume(sample,track)); \
- prevSample = src[(Uint64)position]; \
- _mono_deltaVol(track); \
- position += speed; \
- speed += track->deltaS; \
- if(speed < 0) speed = 0; }
- static inline void _deactivate_track_if(int condition, _kit_kmixerAsyncTrack* track){
- if(condition){
- track->pcm = NULL;
- _kit_kmixerVoice* voice = track->voice;
- if(voice==NULL || voice->lock==NULL) return;
- kit_kmixerVoiceSetActive(voice->device, voice->index, SDL_FALSE);
- }
- }
- #ifdef __cplusplus
- }
- #endif
- #endif /* _KIT_KMIXERASYNCPRIVATE_H */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement