Advertisement
Kitomas

kit_kmixer.h as of 2023-10-05

Oct 6th, 2023
1,022
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 11.57 KB | None | 0 0
  1. /**
  2.  * \file kit_kmixer.h
  3.  * \brief Header file for KIT SDL2's KMixer module
  4.  */
  5. #ifndef _KIT_KMIXER_H
  6. #define _KIT_KMIXER_H
  7. #ifndef _KIT_SDL2_KMIXER_H
  8. #define _KIT_SDL2_KMIXER_H
  9. //todo: make thing for rerouting output of voices
  10.  
  11.  
  12. #include "./kit_core.h" //includes SDL2/SDL.h
  13.  
  14. #ifdef __cplusplus
  15. extern "C" {
  16. #endif
  17.  
  18.  
  19.  
  20.  
  21. /* +kit_kmixerDevice struct/union typedefs+ */
  22. typedef struct kit_kmixerDevice kit_kmixerDevice;
  23. /* -kit_kmixerDevice struct/union typedefs- */
  24.  
  25. /* +kit_kmixerVoice struct/union typedefs+ */
  26. typedef struct kit_kmixerVoiceSpec kit_kmixerVoiceSpec;
  27. /* -kit_kmixerVoice struct/union typedefs- */
  28.  
  29.  
  30.  
  31.  
  32. /* ++++++++++++ */
  33. /* +kit_kmixer+ */
  34. /* ++++++++++++ */
  35.  
  36. extern const SDL_bool kit_kmixerIsDebug;
  37.  
  38.  
  39.  
  40. extern int kit_kmixerInit(int deviceThreadPoolSize);
  41.  
  42. extern int kit_kmixerQuit();
  43.  
  44. /* ------------ */
  45. /* -kit_kmixer- */
  46. /* ------------ */
  47.  
  48.  
  49.  
  50.  
  51. /* ++++++++++++++++++ */
  52. /* +kit_kmixerDevice+ */
  53. /* ++++++++++++++++++ */
  54.  
  55. /**
  56.  * \brief This struct contains all info needed for a kmixer device and its voice chains
  57.  * \remark Every member of this struct has the "_" prefix,
  58.  *         which means they should be treated as read-only
  59.  */
  60. struct kit_kmixerDevice { //136B
  61.   union {
  62.     char           str[8]; ///< \brief String portion of struct ID ("kmxrDev\x00")
  63.     Uint64            num; ///< \brief Integer portion of struct ID (0x0076654472786D6B)
  64.   } /* ---------- */ _magic; ///< \brief Struct ID number; union of Uint64 and char[8]
  65.   SDL_AudioSpec       _spec; ///< \brief Audio specification of the device
  66.   SDL_mutex*          _lock; ///< \brief Mutex for device access (lock unnecessary for accessing some members)
  67.   struct {
  68.     SDL_cond*        cond; ///< \brief Used for signalling when a free spot is available in the pool
  69.     kit_coreVector* queue; ///< \brief Circular buffer that contains currently queued voice tasks
  70.     kit_coreVector*  pool; ///< \brief The thread pool for voice tasks
  71.     Uint32  qread, qwrite; ///< \brief Read/write headers for the queue buffer
  72.   } /* --------- */ _thread; ///< \brief The device's thread pool voice task queue
  73.   struct { //(the highest current voice chain stage is basically just ord.y)
  74.     kit_coreVector*   raw; ///< \brief 1D array of all registered voice structs
  75.     kit_coreVector*   ord; ///< \brief 2D array of voice references (of .raw), ordered by input chain stage
  76.   } /* --------- */ _voices; ///< \brief The device's registered voices
  77.   float     _fadeMultiplier; ///< \brief the number to *= by when applying fade
  78.   float         _fadeVolume; ///< \brief Volume used for fade ins/outs
  79.   Uint32       _fadeInDelay; ///< \brief How many samples to write 0 to before fading in
  80.   Uint32         _lockCount; ///< \brief The number of threads currently locking the device
  81.   SDL_AudioDeviceID  _devID; ///< \brief The device ID number that SDL uses
  82.   SDL_bool         _playing; ///< \brief A boolean of whether the device is currently active
  83.   SDL_bool         _closing; ///< \brief Should only be set inside a call to kit_kmixerDeviceClose
  84.   SDL_bool         _fadeOut; ///< \brief Used internally for fade ins/outs
  85. };
  86.  
  87.  
  88.  
  89. /**
  90.  * Lock or unlock the mutex of a kit_kmixerAudioDevice
  91.  * \param[in] device The device to lock
  92.  * \param[in] lockState A boolean of whether to lock the device or unlock it
  93.  * \return 0 on success, 1 if device already unlocked,
  94.  *         or a negative error code (call SDL_GetError() for more info).
  95.  *
  96.  * \remark Only lock a device as long as necessary, as locking the device's mutex
  97.  *         prevents kmixer from interacting with the device at all. \n
  98.  *         Also, locks are counted by reference, so every lock needs to be
  99.  *         paired with an unlock until the device can be fully unlocked.
  100.  */
  101. extern int kit_kmixerDeviceLock(kit_kmixerDevice* device, SDL_bool lockState);
  102.  
  103.  
  104. /**
  105.  * Play or pause a kit_kmixerAudioDevice
  106.  * \param[in] device The device to play or pause
  107.  * \param[in] playState A boolean of whether to play or pause the device
  108.  * \return 0 on success, or a negative error code (call SDL_GetError() for more info)
  109.  */
  110. extern int kit_kmixerDevicePlay(kit_kmixerDevice* device, SDL_bool playState);
  111.  
  112.  
  113. /**
  114.  * Close a kit_kmixerAudioDevice
  115.  * \param[in] device_p A pointer to the device to close
  116.  * \return 0 on success, or a negative error code (call SDL_GetError() for more info)
  117.  *
  118.  * \remark Do note that this will call the kit_kmixerVoiceRemoveCallback
  119.  *         of any voices destroyed during this operation.
  120.  * \sa kit_kmixerDeviceOpen
  121.  */
  122. extern int kit_kmixerDeviceClose(kit_kmixerDevice** device_p);
  123.  
  124. /**
  125.  * Open a kit_kmixerAudioDevice
  126.  * \param[in] deviceName A string given by SDL_GetAudioDeviceName
  127.  *            (NULL for most reasonable default device)
  128.  * \param[in] allowedChanges Any combination of
  129.  *            SDL_AUDIO_ALLOW_<FREQUENCY,FORMAT,CHANNELS,SAMPLES,ANY>_CHANGE, OR'd together
  130.  * \param[in] voiceSpecDesired The requested specification of the device and initial voice
  131.  * \param[out] voiceSpecObtained The real specification of the device/initial voice,
  132.  *             altered depending on allowedChange's flags
  133.  *
  134.  * \remark If the ".format" member of voiceSpecDesired is set to 0,
  135.  *         voice 1 will not be created (useful in some scenarios). \n
  136.  * \remark (Devices will start in a paused state!)
  137.  * \sa kit_kmixerDeviceClose
  138.  * \sa kit_kmixerDevicePlay
  139.  */
  140. extern kit_kmixerDevice* kit_kmixerDeviceOpen(const char* deviceName, int allowedChanges,
  141.                                               const kit_kmixerVoiceSpec* voiceSpecDesired,
  142.                                               kit_kmixerVoiceSpec* voiceSpecObtained);
  143.  
  144.  
  145. extern int kit_kmixerDevice_Test(); // debug
  146.  
  147. /* ------------------ */
  148. /* -kit_kmixerDevice- */
  149. /* ------------------ */
  150.  
  151.  
  152.  
  153.  
  154. /* +++++++++++++++++ */
  155. /* +kit_kmixerVoice+ */
  156. /* +++++++++++++++++ */
  157.  
  158. /**
  159.  * \name Print a kit_kmixerVoiceSpec
  160.  */
  161. /** @{ */
  162. #define PRINT_VOICE_SPEC(_pref, _vspec) {                 \
  163.   SDL_Log(_pref".remove  =%p",(_vspec).remove);           \
  164.   SDL_Log(_pref".callback=%p",(_vspec).callback);         \
  165.   SDL_Log(_pref".userdata=%p",(_vspec).userdata);         \
  166.   SDL_Log(_pref".freq    =%i",(_vspec).freq);             \
  167.   SDL_Log(_pref"._size   =%u",(_vspec)._size);            \
  168.   SDL_Log(_pref".stereo  =%s",kit_coreBoolStr[(_vspec).stereo]); \
  169.   SDL_Log(_pref".samples =%u",(_vspec).samples);          \
  170.   SDL_Log(_pref".format  =%X",(_vspec).format);           }
  171.  
  172. #define PRINT_VOICE_SPEC_P(_pref, _vspec_pointer) {                 \
  173.   SDL_Log(_pref"->remove  =%p",(_vspec_pointer)->remove);           \
  174.   SDL_Log(_pref"->callback=%p",(_vspec_pointer)->callback);         \
  175.   SDL_Log(_pref"->userdata=%p",(_vspec_pointer)->userdata);         \
  176.   SDL_Log(_pref"->freq    =%i",(_vspec_pointer)->freq);             \
  177.   SDL_Log(_pref"->_size   =%u",(_vspec_pointer)->_size);            \
  178.   SDL_Log(_pref"->stereo  =%s",kit_coreBoolStr[(_vspec_pointer)->stereo]); \
  179.   SDL_Log(_pref"->samples =%u",(_vspec_pointer)->samples);          \
  180.   SDL_Log(_pref"->format  =%X",(_vspec_pointer)->format);           }
  181. /** @} */
  182.  
  183.  
  184.  
  185. /**
  186.  * PCM Audio Voice Callback
  187.  * This type of function is called when added as a voice to a KMixer audio device
  188.  * While each voice's callback is given its own threadpool task (and should be thread-safe),
  189.  * the overall speed is determined by device's slowest voice chain (processing-wise)
  190.  * The given audio buffer must be completely filled before returning
  191.  * \param[in] userdata A user-defined pointer passed to the voice callback
  192.  * \param[in] _stream  A pointer to the audio data buffer
  193.  * \param[in] size     The size of that buffer, in bytes
  194.  * \param[in] hasInput A boolean of whether _stream already contains input PCM data (useful for applying DSP effects)
  195.  *
  196.  * \remark The audio data buffer is not guaranteed to be zeroed out, even if hasInput is SDL_FALSE
  197.  */
  198. typedef void (*kit_kmixerVoiceCallback) (void* userdata, void* _stream, int size, SDL_bool hasInput);
  199.  
  200.  
  201. /**
  202.  * Voice Destructor Callback
  203.  * This type of function is called when removing a voice, so userdata can be properly handled by the user.
  204.  * \param[in] userdata The user defined pointer to operate on.
  205.  *
  206.  * \remark Warning: unless kit_kmixerVoiceSpec.remove was set to NULL,
  207.  *         this will still be called, whether or not userdata is also NULL.
  208.  */
  209. typedef void (*kit_kmixerVoiceRemoveCallback) (void* userdata);
  210.  
  211.  
  212.  
  213. /**
  214.  * \brief The struct used when opening a kmixerDevice, as well as adding a voice to that device.
  215.  * \details When adding a voice, ".freq", and ".samples" are ignored, as that is tied to the device itself.
  216.  */
  217. struct kit_kmixerVoiceSpec { //40B
  218.   kit_kmixerVoiceRemoveCallback remove; ///< \brief A callback that should handle userdata in the event of voice removal
  219.   kit_kmixerVoiceCallback callback; ///< \brief A callback that should either fill or modify its input stream (NULL to use kmixer's built-in asynchronous mixer)
  220.   void*                   userdata; ///< \brief A user-defined pointer, passed to the callback (can be NULL)
  221.   Sint32                      freq; ///< \brief The PCM audio's sample rate, in Hz
  222.   Uint32                     _size; ///< \brief (internal; automatically calculated) The size of the audio buffer, in bytes
  223.   SDL_bool                  stereo; ///< \brief Stereo if SDL_TRUE, mono if SDL_FALSE
  224.   Uint16                   samples; ///< \brief The Audio buffer's length in sample FRAMES (total samples divided by channel count)
  225.   SDL_AudioFormat           format; ///< \brief Format can be one of AUDIO_<U8,S16,S32,F32>
  226. };
  227.  
  228.  
  229.  
  230. /**
  231.  * Remove a kmixer device's voice, as well as any input voices, recursively
  232.  * \param[in] device The device to remove a voice from
  233.  * \param[in] voiceID The ID number of the voice to remove
  234.  * \return 0 on success, -1 on error (call SDL_GetError() for more info)
  235.  *
  236.  * \remark The selected voice's kit_kmixerVoiceRemoveCallback will trigger
  237.  *         after the voice itself is mostly done being removed (if it isn't NULL) \n
  238.  * \remark Also, bit 31 of voiceID is reserved for detecting recursion, so don't set it.
  239.  * \sa kit_kmixerVoiceRemoveCallback
  240.  * \sa kit_kmixerVoiceAdd
  241.  * \sa kit_kmixerVoiceRedirect
  242.  */
  243. extern int kit_kmixerVoiceRemove(kit_kmixerDevice* device, Uint32 voiceID);
  244.  
  245. /**
  246.  * Add a voice to output to either a kmixer device or one of the device's voices
  247.  * \param[in] device The device to add a voice to
  248.  * \param[in] spec The specification for the voice
  249.  * \param[in] outputVoiceID The ID number of the output voice (0 for the device itself)
  250.  * \return The ID number of the newly-created voice, or 0 on error (call SDL_GetError() for more info)
  251.  *
  252.  * \sa kit_kmixerVoiceRemove
  253.  * \sa kit_kmixerVoiceRedirect
  254.  */
  255. extern Uint32 kit_kmixerVoiceAdd(kit_kmixerDevice* device, kit_kmixerVoiceSpec* spec,
  256.                                  Uint32 outputVoiceID);
  257.  
  258. /**
  259.  * Redirect the output of a voice
  260.  * \param[in] device The device to alter the voices of
  261.  * \param[in] inputVoiceID The voice to be redirected
  262.  * \param[in] outputVoiceID The new voice to output to
  263.  * \return 0 on success, -1 on error (call SDL_GetError() for more info)
  264.  *
  265.  * \sa kit_kmixerVoiceRemove
  266.  * \sa kit_kmixerVoiceAdd
  267.  */
  268. extern int kit_kmixerVoiceRedirect(kit_kmixerDevice* device,
  269.                                    Uint32 inputVoiceID, Uint32 outputVoiceID);
  270.  
  271.  
  272. extern int kit_kmixerVoice_Test(); //debug
  273.  
  274. extern void kit_kmixerVoicePrintRawOrd(kit_kmixerDevice* device); //debug
  275.  
  276. /* ----------------- */
  277. /* -kit_kmixerVoice- */
  278. /* ----------------- */
  279.  
  280.  
  281.  
  282.  
  283. #ifdef __cplusplus
  284. }
  285. #endif
  286.  
  287. #endif /* _KIT_SDL2_KMIXER_H */
  288. #endif /* _KIT_KMIXER_H */
  289.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement