Advertisement
Kitomas

kit_kmixer.h as of 2023-8-31

Sep 1st, 2023
879
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 10.88 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. /* add these things at some point:
  10. kmixerFileLoadQOA
  11. kmixerFileLoadWAV
  12. kmixerFileLoadMUA
  13. (also, include save functions, and functions that just convert streams)
  14.  */
  15.  
  16.  
  17.  
  18. #include "./kit_core.h" //includes SDL2/SDL.h
  19.  
  20.  
  21.  
  22.  
  23. /* +kit_kmixerDevice struct/union typedefs+ */
  24. typedef struct kit_kmixerDevice kit_kmixerDevice;
  25. /* -kit_kmixerDevice struct/union typedefs- */
  26.  
  27. /* +kit_kmixerVoice struct/union typedefs+ */
  28. typedef struct kit_kmixerVoiceSpec kit_kmixerVoiceSpec;
  29. /* -kit_kmixerVoice struct/union typedefs- */
  30.  
  31.  
  32.  
  33.  
  34. /* ++++++++++++ */
  35. /* +kit_kmixer+ */
  36. /* ++++++++++++ */
  37.  
  38.  
  39. extern int kit_kmixerInit(int deviceThreadPoolSize);
  40.  
  41. extern int kit_kmixerQuit();
  42.  
  43. /* ------------ */
  44. /* -kit_kmixer- */
  45. /* ------------ */
  46.  
  47.  
  48.  
  49.  
  50. /* ++++++++++++++++++ */
  51. /* +kit_kmixerDevice+ */
  52. /* ++++++++++++++++++ */
  53.  
  54. /**
  55.  * \brief This struct contains all info needed for a kmixer device and its voice chains
  56.  * \remark Every member of this struct has the "_" prefix,
  57.  *         which means they should be treated as read-only
  58.  */
  59. struct kit_kmixerDevice { //136B
  60.   union {
  61.     char           str[8]; ///< \brief String portion of struct ID ("kmxrDev\x00")
  62.     Uint64            num; ///< \brief Integer portion of struct ID (0x0076654472786D6B)
  63.   } /* ---------- */ _magic; ///< \brief Struct ID number; union of Uint64 and char[8]
  64.   SDL_AudioSpec       _spec; ///< \brief Audio specification of the device
  65.   SDL_mutex*          _lock; ///< \brief Mutex for device access (lock unnecessary for accessing some members)
  66.   struct {
  67.     SDL_cond*        cond; ///< \brief Used for signalling when a free spot is available in the pool
  68.     kit_coreVector* queue; ///< \brief Circular buffer that contains currently queued voice tasks
  69.     kit_coreVector*  pool; ///< \brief The thread pool for voice tasks
  70.     Uint32  qread, qwrite; ///< \brief Read/write headers for the queue buffer
  71.   } /* --------- */ _thread; ///< \brief The device's thread pool voice task queue
  72.   struct { //(the highest current voice chain stage is basically just ord.x)
  73.     kit_coreVector*   raw; ///< \brief 1D array of all registered voice structs
  74.     kit_coreVector*   ord; ///< \brief 2D array of voice references (of .raw), ordered by input chain stage
  75.     kit_coreVector* chain; ///< \brief 1D array of the amount of voices on a given chain stage (.ord's y axis)
  76.   } /* --------- */ _voices; ///< \brief The device's registered voices
  77.   float      _fadeMuliplier; ///< \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
  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_kmixerDeviceTest(); // 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(_vspec) {         \
  163.   SDL_Log(".remove  =%p",_vspec.remove);   \
  164.   SDL_Log(".callback=%p",_vspec.callback); \
  165.   SDL_Log(".userdata=%p",_vspec.userdata); \
  166.   SDL_Log(".freq    =%i",_vspec.freq);     \
  167.   SDL_Log("._size   =%u",_vspec._size);    \
  168.   SDL_Log(".stereo  =%u",_vspec.stereo);   \
  169.   SDL_Log(".samples =%u",_vspec.samples);  \
  170.   SDL_Log(".format  =%X",_vspec.format);   }
  171.  
  172. #define PRINT_VOICE_SPEC_P(_vspec_pointer) {         \
  173.   SDL_Log("->remove  =%p",_vspec_pointer->remove);   \
  174.   SDL_Log("->callback=%p",_vspec_pointer->callback); \
  175.   SDL_Log("->userdata=%p",_vspec_pointer->userdata); \
  176.   SDL_Log("->freq    =%i",_vspec_pointer->freq);     \
  177.   SDL_Log("->_size   =%u",_vspec_pointer->_size);    \
  178.   SDL_Log("->stereo  =%u",_vspec_pointer->stereo);   \
  179.   SDL_Log("->samples =%u",_vspec_pointer->samples);  \
  180.   SDL_Log("->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] len      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 len, 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 opening a device, the ".format" member is ignored, as samples are always floats internally. \n
  216.  *          Conversely, when adding a voice, ".freq", and ".samples" are ignored, \n
  217.  *          as that is tied to the device itself.
  218.  */
  219. struct kit_kmixerVoiceSpec { //40B
  220.   kit_kmixerVoiceRemoveCallback remove; ///< \brief A callback that should handle userdata in the event of voice removal
  221.   kit_kmixerVoiceCallback callback; ///< \brief A callback that should either fill or modify its input stream (NULL to use kmixer's built-in asynchronous mixer)
  222.   void*                   userdata; ///< \brief A user-defined pointer, passed to the callback (can be NULL)
  223.   Sint32                      freq; ///< \brief The PCM audio's sample rate, in Hz
  224.   Uint32                     _size; ///< \brief (internal; automatically calculated) The size of the audio buffer, in bytes
  225.   SDL_bool                  stereo; ///< \brief Stereo if SDL_TRUE, mono if SDL_FALSE
  226.   Uint16                   samples; ///< \brief The Audio buffer's length in sample FRAMES (total samples divided by channel count)
  227.   SDL_AudioFormat           format; ///< \brief Format can be one of AUDIO_<U8,S16,S32,F32>
  228. };
  229.  
  230.  
  231.  
  232. /**
  233.  * Remove a kmixer device's voice, as well as any input voices, recursively
  234.  * \param[in] device The device to remove a voice from
  235.  * \param[in] voiceID The ID number of the voice to remove
  236.  *
  237.  * \return 0 on success, -1 on error (call SDL_GetError() for more info)
  238.  * \remark The selected voice's kit_kmixerVoiceRemoveCallback will trigger
  239.  *         after the voice itself is mostly done being removed (if it isn't NULL) \n
  240.  * \remark Also, bit 31 of voiceID is reserved for detecting recursion, so don't set it.
  241.  * \sa kit_kmixerVoiceAdd
  242.  * \sa kit_kmixerVoiceRemoveCallback
  243.  */
  244. extern int kit_kmixerVoiceRemove(kit_kmixerDevice* device, Uint32 voiceID);
  245.  
  246. /**
  247.  * Add a voice to output to either a kmixer device or one of the device's voices
  248.  * \param[in] device The device to add a voice to
  249.  * \param[in] spec The specification for the voice
  250.  * \param[in] outputVoiceID The ID number of the output voice (0 for the device itself)
  251.  *
  252.  * \return The ID number of the newly-created voice, or 0 on error (call SDL_GetError() for more info)
  253.  * \sa kit_kmixerVoiceAdd
  254.  */
  255. extern Uint32 kit_kmixerVoiceAdd(kit_kmixerDevice* device, kit_kmixerVoiceSpec* spec,
  256.                                  Uint32 outputVoiceID);
  257.  
  258.  
  259. extern int kit_kmixerVoiceTest(); //debug
  260.  
  261. /* ----------------- */
  262. /* -kit_kmixerVoice- */
  263. /* ----------------- */
  264.  
  265.  
  266.  
  267.  
  268. #endif /* _KIT_SDL2_KMIXER_H */
  269. #endif /* _KIT_KMIXER_H */
  270.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement