Advertisement
Kitomas

_kit_kmixerAsyncPrivate.h as of 2023-10-27

Oct 27th, 2023
590
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.80 KB | None | 0 0
  1. #ifndef _KIT_KMIXERASYNCPRIVATE_H
  2. #define _KIT_KMIXERASYNCPRIVATE_H
  3.  
  4.  
  5. #include "../../include/kit_sdl2/kit_core.h"
  6.  
  7. #ifdef __cplusplus
  8. extern "C" {
  9. #endif
  10.  
  11.  
  12.  
  13.  
  14. typedef enum _udata_types {
  15.   type_UDAT = 0x54414455, // = "UDAT"
  16.   type_TRCK = 0x4B435254, // = "TRCK"
  17. } _udata_types;
  18.  
  19.  
  20.  
  21.  
  22. typedef struct _kit_kmixerAsyncTrack { //88B
  23.   //type, pan, ..., stopOnMute are identical to that of AsyncUserdata,
  24.    //so they can be casted and used interchangably
  25.   _udata_types         type; // = "TRCK"
  26.   float                 pan; //the current pan of the track; -1.0f -> 1.0f (applied AFTER volume)
  27.   kit_acodecPCM_F32S volume; //left and right channel volumes; 0.0f -> 1.0f (.r ignored if mono)
  28.   kit_acodecPCM_F32S  delta; //determines the rate at which volume changes each sample (.r ignored if mono)
  29.   SDL_bool       stopOnMute; //'deactivate track when volume or speed reaches 0?'
  30.  
  31.   SDL_bool           linear; //use linear interpolation if true, nearest-neighbor if false
  32.   _kit_kmixerVoice*   voice; //a reference to the track's voice
  33.  
  34.   kit_acodecPCM*        pcm; //the actual audio data (this should be NULL if the track is inactive)
  35.   Uint64*   deviceTimeStamp; //a pointer to the device callback's timeStamp (read-only)
  36.   Uint64          timeStamp; //result of SDL_GetTicks64() called at time of queueing an audio clip
  37.   double           position; //sample position, including fraction
  38.  
  39.   double              speed; //what amount to increment position by every sample
  40.   double             deltaS; //what number to apply to speed every sample
  41.  
  42.   Uint32           rawIndex; //the voice's index inside the device's raw voice list
  43.   Uint16              loops; //number of times to loop before deactivating clip (-1 for endless loop)
  44.   Uint16         _padding16;
  45. } _kit_kmixerAsyncTrack;
  46.  
  47.  
  48.  
  49. //this should be contiguous with the AsyncTrack(s)
  50. typedef struct _kit_kmixerAsyncUserdata { //48B
  51.   _udata_types         type; // = "UDAT"
  52.   float                 pan; //the current pan of the main voice; -1.0f -> 1.0f (applied AFTER volume)
  53.   kit_acodecPCM_F32S volume; //left and right channel volumes; 0.0f -> 1.0f (.r ignored if mono)
  54.   kit_acodecPCM_F32S  delta; //determines the rate at which volume changes each sample (.r ignored if mono)
  55.   SDL_bool       stopOnMute; //'stop all tracks when main voice's volume reaches 0?'
  56.  
  57.   Uint32          numTracks; //number of total tracks that can play at once
  58.   _kit_kmixerVoice*   voice; //a reference to the main voice's actual voice struct
  59.  
  60.   _kit_kmixerAsyncTrack* tracks; //array of track structs of length numTracks
  61. } _kit_kmixerAsyncUserdata;
  62.  
  63.  
  64.  
  65.  
  66. /* LOOP CHECK */
  67. #define _mono_0 dst[i] = 0;
  68.  
  69. #define _stereo_0 dst[i].l = 0,  dst[i].r = 0;
  70.  
  71. #define _loop_check(_dst_0) {                                              \
  72.   if(pcm == NULL){ _dst_0; continue; } /*0 for silent sample if inactive*/ \
  73.   if(position >= loopEnd){ /*clip finished loop*/                          \
  74.     if(!loops){ pcm = NULL; _dst_0; continue; } /*mark track as inactive*/ \
  75.     if(loops != -1) --loops; /*decrement loops unless infinite*/           \
  76.     position -= (Uint64)position; /*pos %= 1*/                             \
  77.     position += loopStart; /*new_pos = loopStart + old_pos%1*/             \
  78.   } else if(position<0){ /*clip has yet to play*/                          \
  79.     if(position < -speed){                                                 \
  80.       position += speed; /*step forward position by current speed*/        \
  81.       _dst_0; continue; /*0 for silent sample*/                            \
  82.     } else { /*if position >= -speed, the clip should start next sample*/  \
  83.       position = 0; /*make sure the clip starts at 1*/                     \
  84.     }                                                                      \
  85.   }                                                                        }
  86.  
  87.  
  88.  
  89. /* SAMPLE */
  90. static inline float _mono_nearest(float* src, double position){
  91.   return src[ (Uint64)(position+0.5) ];
  92. }
  93.  
  94. static inline kit_acodecPCM_F32S _stereo_nearest(kit_acodecPCM_F32S* src, double position){
  95.   Uint64 positionRound = (Uint64)(position+0.5);
  96.   kit_acodecPCM_F32S smp;
  97.   smp.l = src[positionRound].l;
  98.   smp.r = src[positionRound].r;
  99.   return smp;
  100. }
  101.  
  102.  
  103. static inline float _mono_linear(float* src, double position){
  104.   Uint64 intPosition = (Uint64)position;
  105.   double modPosition = position - intPosition; // = position % 1
  106.   float smpA = src[  intPosition];
  107.   float smpB = src[++intPosition];
  108.  
  109.   //modPosition is used as a percentage value for lerp
  110.   return LERP2(smpA, smpB, modPosition);
  111. }
  112.  
  113. static inline kit_acodecPCM_F32S _stereo_linear(kit_acodecPCM_F32S* src, double position){
  114.   Uint64 intPosition = (Uint64)position;
  115.   double modPosition = position - intPosition; // = position % 1
  116.   kit_acodecPCM_F32S smpA = src[  intPosition];
  117.   kit_acodecPCM_F32S smpB = src[++intPosition];
  118.  
  119.   //modPosition is used as a percentage value for lerp
  120.   kit_acodecPCM_F32S smpOut;
  121.   smpOut.l = LERP2(smpA.l, smpB.l, modPosition);
  122.   smpOut.r = LERP2(smpA.r, smpB.r, modPosition);
  123.  
  124.   return smpOut;
  125. }
  126.  
  127.  
  128.  
  129. /* VOLUME */
  130. static inline float _mono_volume(float sample, _kit_kmixerAsyncTrack* track){
  131.   return sample * track->volume.l;
  132. }
  133.  
  134. static inline kit_acodecPCM_F32S _stereo_volume(kit_acodecPCM_F32S sample,
  135.                                                 _kit_kmixerAsyncTrack* track)
  136. {
  137.   sample.l *= track->volume.l;
  138.   sample.r *= track->volume.r;
  139.   return sample;
  140. }
  141.  
  142.  
  143.  
  144. /* CLAMP */
  145. static inline float _mono_clamp(float sample){
  146.   return CLAMP(sample, -1.0f,1.0f);
  147. }
  148.  
  149. static inline kit_acodecPCM_F32S _stereo_clamp(kit_acodecPCM_F32S sample){
  150.   sample.l = CLAMP(sample.l, -1.0f,1.0f);
  151.   sample.r = CLAMP(sample.r, -1.0f,1.0f);
  152.   return sample;
  153. }
  154.  
  155.  
  156.  
  157. /* PAN */
  158. static inline kit_acodecPCM_F32S _apply_pan(kit_acodecPCM_F32S smp, float pan){
  159.   //(i think this is how audacity does it...)
  160.   pan = CLAMP(pan, -1.0f,1.0f);
  161.   if(pan < 0){
  162.     smp.l += smp.r*(-pan);
  163.     smp.r *= 1.0f+pan;
  164.   } else if(pan > 0){
  165.     smp.r += smp.l*pan;
  166.     smp.l *= 1.0f-pan;
  167.   }
  168.   return smp;
  169. }
  170.  
  171.  
  172.  
  173. /* DELTAVOL */
  174. static inline void _mono_deltaVol(_kit_kmixerAsyncTrack* track){
  175.   track->volume.l += track->delta.l;
  176.   track->volume.l  = CLAMP(track->volume.l, 0.0f,1.0f);
  177. }
  178.  
  179. static inline void _stereo_deltaVol(_kit_kmixerAsyncTrack* track){
  180.   _mono_deltaVol(track); //for volume.l and delta.l
  181.   track->volume.r += track->delta.r;
  182.   track->volume.r  = CLAMP(track->volume.r, 0.0f,1.0f);
  183. }
  184.  
  185.  
  186.  
  187. /* SPEED */ //(using a define for this is unnecessary)
  188. //#define _apply_speed position += speed;
  189.  
  190.  
  191.  
  192. /* DELTAS */ //(using a define for this is unnecessary)
  193. //#define _apply_deltaS speed = MAX(speed+track->deltaS,0);
  194.  
  195.  
  196.  
  197. /* LOOP FLOW */
  198. /* loop flow order:
  199.     _loop_check(_<m/s>_0)
  200.     _<m/s>_<nearest,linear>()
  201.     _<m/s>_volume()
  202.     _<m/s>_clamp()
  203.     _apply_pan() (stereo only!)
  204.     _<m/s>_deltaVol(track)
  205.     position += speed;
  206.     speed += track->deltaS;
  207.     if(speed < 0) speed = 0;
  208.     (repeat) */
  209.  
  210. #define _stereo_iteration(_interpolation_mode) {                 \
  211.   _loop_check(_stereo_0)                                         \
  212.   kit_acodecPCM_F32S sample = _interpolation_mode(src,position); \
  213.   sample = _stereo_clamp(_stereo_volume(sample,track));          \
  214.   dst[i] = _apply_pan(sample,pan);                               \
  215.   _stereo_deltaVol(track);                                       \
  216.   position += speed;                                             \
  217.   speed += track->deltaS;                                        \
  218.   if(speed <= 0){                                                \
  219.     speed = 0;                                                   \
  220.     track->delta.l = speed0DeltaVol;                             \
  221.     track->delta.r = speed0DeltaVol;                             \
  222.   }                                                              }
  223.  
  224. #define _mono_iteration(_interpolation_mode) {      \
  225.   _loop_check(_mono_0)                              \
  226.   float sample = _interpolation_mode(src,position); \
  227.   dst[i] =            (_mono_volume(sample,track)); \
  228.   _mono_deltaVol(track);                            \
  229.   position += speed;                                \
  230.   speed += track->deltaS;                           \
  231.   if(speed <= 0){                                   \
  232.     speed = 0;                                      \
  233.     track->delta.l = speed0DeltaVol;                \
  234.   }                                                 }
  235.  
  236.  
  237.  
  238.  
  239. static inline void _deactivate_track_if(int condition, _kit_kmixerAsyncTrack* track){
  240.   if(condition){
  241.     track->pcm = NULL;
  242.     _kit_kmixerVoice* voice = track->voice;
  243.     if(voice==NULL || voice->lock==NULL) return;
  244.     kit_kmixerVoiceSetActive(voice->device, voice->index, SDL_FALSE);
  245.   }
  246. }
  247.  
  248.  
  249.  
  250.  
  251. #ifdef __cplusplus
  252. }
  253. #endif
  254.  
  255. #endif /* _KIT_KMIXERASYNCPRIVATE_H */
  256.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement