Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * \file kit_kmixer.h
- * \brief Header file for KIT SDL2's KMixer module
- */
- #ifndef _KIT_KMIXER_H
- #define _KIT_KMIXER_H
- #ifndef _KIT_SDL2_KMIXER_H
- #define _KIT_SDL2_KMIXER_H
- //todo: make kmixerAsync
- #include "./kit_core.h" //includes SDL2/SDL.h
- #include "./_kit_acodecPCM.h" //contains PCM data stuff
- #ifdef __cplusplus
- extern "C" {
- #endif
- /* +kit_kmixerDevice struct/union typedefs+ */
- typedef struct kit_kmixerDevice kit_kmixerDevice;
- /* -kit_kmixerDevice struct/union typedefs- */
- /* +kit_kmixerVoice struct/union typedefs+ */
- typedef struct kit_kmixerVoiceSpec kit_kmixerVoiceSpec;
- /* -kit_kmixerVoice struct/union typedefs- */
- /* ++++++++++++ */
- /* +kit_kmixer+ */
- /* ++++++++++++ */
- extern const SDL_bool kit_kmixerIsDebug;
- /**
- * Initialize kmixer
- * \param[in] numDeviceThreads The maximum number of active threads a device can have. \n
- Negative values will use fractions of total core count (-2 for half, -3 for a third, etc.)
- * \return 0 on success, >0 on warning, or <0 on error (call SDL_GetError() for more info)
- *
- * \remark Setting numDeviceThreads to 0 is treated the same as setting it to -1 (as many threads as there are CPU cores).
- * \sa kit_kmixerQuit
- */
- extern int kit_kmixerInit(int numDeviceThreads);
- /**
- * Shut down kmixer
- * \return 0 on success, >0 on warning, <0 on error (call SDL_GetError() for more info)
- *
- * \sa kit_kmixerInit
- */
- extern int kit_kmixerQuit();
- /* ------------ */
- /* -kit_kmixer- */
- /* ------------ */
- /* ++++++++++++++++++ */
- /* +kit_kmixerDevice+ */
- /* ++++++++++++++++++ */
- /**
- * \brief This struct contains all info needed for a kmixer device and its voice chains
- * \remark Every member of this struct has the "_" prefix,
- * which means they should be treated as read-only
- */
- struct kit_kmixerDevice { //112B
- union {
- char str[8]; ///< \brief String portion of struct ID ("kmxrDev\x00")
- Uint64 num; ///< \brief Integer portion of struct ID (0x0076654472786D6B)
- } /* ------------ */ _magic; ///< \brief Struct ID number; union of Uint64 and char[8]
- SDL_AudioSpec _spec; ///< \brief Audio specification of the device
- SDL_mutex* _lock; ///< \brief Mutex for device access (lock unnecessary for accessing some members)
- kit_coreVector* _threads; ///< \brief The device's thread list for voice processing
- kit_coreVector* _threadData; ///< \brief List of data to be fed into the device threads
- kit_coreVector* _raw; ///< \brief 1D array of all registered voice structs
- kit_coreVector* _ord; ///< \brief 2D array of voice references (of raw), ordered by input chain stage
- float _fadeDelta; ///< \brief the number to apply to _fadeVolume when applying fade ins/outs
- float _fadeVolume; ///< \brief Volume used for fade ins/outs
- Uint32 _fadeInDelay; ///< \brief How many samples to write 0 to before fading in
- Uint32 _lockCount; ///< \brief The number of threads currently locking the device
- SDL_AudioDeviceID _devID; ///< \brief The device ID number that SDL uses
- SDL_bool _playing; ///< \brief A boolean of whether the device is currently active
- SDL_bool _closing; ///< \brief Should only be set inside a call to kit_kmixerDeviceClose
- SDL_bool _fadeOut; ///< \brief Used internally for fade ins/outs
- };
- /**
- * Lock or unlock the mutex of a kit_kmixerAudioDevice
- * \param[in] device The device to lock
- * \param[in] lockState A boolean of whether to lock the device or unlock it
- * \return 0 on success, 1 if device already unlocked, or <0 on error (call SDL_GetError() for more info).
- *
- * \remark Only lock a device as long as necessary, as locking the device's mutex
- * prevents kmixer from interacting with the device at all. \n
- * Also, locks are counted by reference, so every lock needs to be
- * paired with an unlock until the device can be fully unlocked.
- */
- extern int kit_kmixerDeviceLock(kit_kmixerDevice* device, SDL_bool lockState);
- /**
- * Play or pause a kit_kmixerAudioDevice
- * \param[in] device The device to play or pause
- * \param[in] playState A boolean of whether to play or pause the device
- * \return 0 on success, or <0 on error (call SDL_GetError() for more info)
- *
- * \remark When unpausing a paused device, there is 490ms of silence, followed by 10ms of fade-in. \n
- * \remark Conversely, when pausing a currently unpaused device, there's 10ms of fade-out.
- * \sa kit_kmixerDeviceUnpauseAndWait
- * \sa kit_kmixerDevicePauseAndWait
- */
- extern int kit_kmixerDevicePlay(kit_kmixerDevice* device, SDL_bool playState);
- /**
- * Close a kit_kmixerAudioDevice
- * \param[in] device_p A pointer to the device to close
- * \return 0 on success, or <0 on error (call SDL_GetError() for more info)
- *
- * \remark Do note that this will call the kit_kmixerVoiceRemoveCallback
- * of any voices destroyed during this operation.
- * \sa kit_kmixerDeviceOpen
- */
- extern int kit_kmixerDeviceClose(kit_kmixerDevice** device_p);
- /**
- * Open a kit_kmixerAudioDevice
- * \param[in] deviceName A string given by SDL_GetAudioDeviceName
- * (NULL for most reasonable default device)
- * \param[in] allowedChanges Any combination of
- * SDL_AUDIO_ALLOW_<FREQUENCY,FORMAT,CHANNELS,SAMPLES,ANY>_CHANGE, OR'd together
- * \param[in] voiceSpecDesired The requested specification of the device and initial voice
- * \param[out] voiceSpecObtained The real specification of the device/initial voice,
- * altered depending on allowedChange's flags
- *
- * \remark If the ".format" member of voiceSpecDesired is set to 0,
- * voice 1 will not be created (useful in some scenarios). \n
- * \remark (Devices will start in a paused state!)
- * \sa kit_kmixerDeviceClose
- * \sa kit_kmixerDevicePlay
- */
- extern kit_kmixerDevice* kit_kmixerDeviceOpen(const char* deviceName, int allowedChanges,
- const kit_kmixerVoiceSpec* voiceSpecDesired,
- kit_kmixerVoiceSpec* voiceSpecObtained);
- /**
- * Unpause a device, halting the calling thread until device fade-in completes
- * \param[in] device The device to unpause
- * \return 0 on success, or <0 on error (call SDL_GetError() for more info)
- *
- * \sa kit_kmixerDevicePlay
- * \sa kit_kmixerDevicePauseAndWait
- */
- extern int kit_kmixerDeviceUnpauseAndWait(kit_kmixerDevice* device);
- /**
- * Pause a device, halting the calling thread until device fade-out completes
- * \param[in] device The device to unpause
- * \return 0 on success, or <0 on error (call SDL_GetError() for more info)
- *
- * \sa kit_kmixerDevicePlay
- * \sa kit_kmixerDeviceUnpauseAndWait
- */
- extern int kit_kmixerDevicePauseAndWait(kit_kmixerDevice* device);
- extern int kit_kmixerDevice_Test(); // debug
- /* ------------------ */
- /* -kit_kmixerDevice- */
- /* ------------------ */
- /* +++++++++++++++++ */
- /* +kit_kmixerVoice+ */
- /* +++++++++++++++++ */
- /**
- * \name Print a kit_kmixerVoiceSpec (These should probably become inlines at some point)
- */
- /** @{ */
- #define PRINT_VOICE_SPEC(_pref, _vspec) { \
- kit_coreLog(_pref".remove = %p",(_vspec).remove); \
- kit_coreLog(_pref".callback = %p",(_vspec).callback); \
- kit_coreLog(_pref".userdata = %p",(_vspec).userdata); \
- kit_coreLog(_pref".freq = %i",(_vspec).freq); \
- kit_coreLog(_pref"._size = %u",(_vspec)._size); \
- kit_coreLog(_pref".stereo = %s",boolstr[(_vspec).stereo]); \
- kit_coreLog(_pref".samples = %u",(_vspec).samples); \
- kit_coreLog(_pref".format = 0x%04X",(_vspec).format); }
- #define PRINT_VOICE_SPEC_P(_pref, _vspec_pointer) { \
- kit_coreLog(_pref"->remove = %p",(_vspec_pointer)->remove); \
- kit_coreLog(_pref"->callback = %p",(_vspec_pointer)->callback); \
- kit_coreLog(_pref"->userdata = %p",(_vspec_pointer)->userdata); \
- kit_coreLog(_pref"->freq = %i",(_vspec_pointer)->freq); \
- kit_coreLog(_pref"->_size = %u",(_vspec_pointer)->_size); \
- kit_coreLog(_pref"->stereo = %s",boolstr[(_vspec_pointer)->stereo]); \
- kit_coreLog(_pref"->samples = %u",(_vspec_pointer)->samples); \
- kit_coreLog(_pref"->format = 0x%04X",(_vspec_pointer)->format); }
- /** @} */
- /**
- * PCM Audio Voice Callback
- * This type of function is called when added as a voice to a KMixer audio device
- * While each voice's callback is given its own threadpool task (and should be thread-safe),
- * the overall speed is determined by device's slowest voice chain (processing-wise)
- * The given audio buffer must be completely filled before returning
- * \param[in] userdata A user-defined pointer passed to the voice callback
- * \param[in] _stream A pointer to the audio data buffer
- * \param[in] size The size of that buffer, in bytes
- * \param[in] hasInput A boolean of whether _stream already contains input PCM data (useful for applying DSP effects)
- *
- * \remark The audio data buffer is not guaranteed to be zeroed out, even if hasInput is SDL_FALSE
- */
- typedef void (*kit_kmixerVoiceCallback) (void* userdata, void* _stream, int size, SDL_bool hasInput);
- /**
- * Voice Destructor Callback
- * This type of function is called when removing a voice, so userdata can be properly handled by the user.
- * \param[in] userdata The user defined pointer to operate on.
- *
- * \remark Warning: unless kit_kmixerVoiceSpec.remove was set to NULL,
- * this will still be called, whether or not userdata is also NULL.
- */
- typedef void (*kit_kmixerVoiceRemoveCallback) (void* userdata);
- /**
- * \brief The struct used when opening a kmixerDevice, as well as adding a voice to that device.
- * \details When adding a voice, ".freq", and ".samples" are ignored, as that is tied to the device itself.
- */
- struct kit_kmixerVoiceSpec { //40B
- kit_kmixerVoiceRemoveCallback remove; ///< \brief A callback that should handle userdata in the event of voice removal (can be NULL)
- kit_kmixerVoiceCallback callback; ///< \brief A callback that should either fill or modify its input stream
- void* userdata; ///< \brief A user-defined pointer, passed to the callback (can be NULL)
- Sint32 freq; ///< \brief The PCM audio's sample rate, in Hz
- Uint32 _size; ///< \brief (internal; automatically calculated) The size of the audio buffer, in bytes
- SDL_bool stereo; ///< \brief Stereo if SDL_TRUE, mono if SDL_FALSE
- Uint16 samples; ///< \brief The Audio buffer's length in sample FRAMES (total samples divided by channel count)
- SDL_AudioFormat format; ///< \brief Format can be one of AUDIO_<U8,S16,S32,F32>
- };
- /**
- * Remove a kmixer device's voice, as well as any input voices, recursively
- * \param[in] device The device to remove a voice from
- * \param[in] voiceID The ID number of the voice to remove
- * \return 0 on success, -1 on error (call SDL_GetError() for more info)
- *
- * \remark The selected voice's kit_kmixerVoiceRemoveCallback will trigger
- * after the voice itself is mostly done being removed (if it isn't NULL) \n
- * \remark Also, bit 31 of voiceID is reserved for detecting recursion, so don't set it.
- * \sa kit_kmixerVoiceRemoveCallback
- * \sa kit_kmixerVoiceAdd
- * \sa kit_kmixerVoiceRedirect
- */
- extern int kit_kmixerVoiceRemove(kit_kmixerDevice* device, Uint32 voiceID);
- /**
- * Add a voice to output to either a kmixer device or one of the device's voices
- * \param[in] device The device to add a voice to
- * \param[in] spec The specification for the voice
- * \param[in] outputVoiceID The ID number of the output voice (0 for the device itself)
- * \return The ID number of the newly-created voice, or 0 on error (call SDL_GetError() for more info)
- *
- * \sa kit_kmixerVoiceRemove
- * \sa kit_kmixerVoiceRedirect
- */
- extern Uint32 kit_kmixerVoiceAdd(kit_kmixerDevice* device, kit_kmixerVoiceSpec* spec,
- Uint32 outputVoiceID);
- /**
- * Redirect the output of a voice
- * \param[in] device The device to alter the voices of
- * \param[in] inputVoiceID The voice to be redirected
- * \param[in] outputVoiceID The new voice to output to (0 for the device itself)
- * \return 0 on success, -1 on error (call SDL_GetError() for more info)
- *
- * \sa kit_kmixerVoiceRemove
- * \sa kit_kmixerVoiceAdd
- */
- extern int kit_kmixerVoiceRedirect(kit_kmixerDevice* device,
- Uint32 inputVoiceID, Uint32 outputVoiceID);
- /**
- * Get the number of inputs of a given voice
- * \param[in] device The device access the voices of
- * \param[in] voiceID The specific voice to query (0 for the device itself)
- * \return The total number of inputs, or -1 on error (call SDL_GetError() for more info)
- *
- * \sa kit_kmixerVoiceGetInputs
- * \sa kit_kmixerVoiceGetOutput
- */
- extern Uint32 kit_kmixerVoiceGetNumInputs(kit_kmixerDevice* device, Uint32 voiceID);
- /**
- * Create a deep copy of a voice's input list
- * \param[in] device The device access the voices of
- * \param[in] voiceID The specific voice to query (0 for the device itself)
- * \return A deep copy of voice's input list, or NULL on error (call SDL_GetError() for more info)
- *
- * \remark (Make sure to call kit_coreVectorDestroy after the returned vector is no longer used!)
- * \sa kit_kmixerVoiceGetNumInputs
- * \sa kit_kmixerVoiceGetOutput
- */
- extern kit_coreVector* kit_kmixerVoiceGetInputs(kit_kmixerDevice* device, Uint32 voiceID);
- /**
- * Get the output voice ID of a given input voice
- * \param[in] device The device access the voices of
- * \param[in] voiceID The specific voice to query
- * \return The output voice ID, or -1 on error (call SDL_GetError() for more info)
- *
- * \sa kit_kmixerVoiceGetNumInputs
- * \sa kit_kmixerVoiceGetInputs
- */
- extern Uint32 kit_kmixerVoiceGetOutput(kit_kmixerDevice* device, Uint32 voiceID);
- /**
- * Get the time stamp of a voice at its point of creation
- * \param[in] device The device access the voices of
- * \param[in] voiceID The specific voice to query (0 for the device itself)
- * \return The time stamp, in milliseconds, or -1 on error (call SDL_GetError() for more info)
- *
- * \remark Specifically, the value SDL_GetTicks() returned when the voice was created.
- */
- extern Uint32 kit_kmixerVoiceGetTimeStamp(kit_kmixerDevice* device, Uint32 voiceID);
- /**
- * Get the voice processing stage of a given voice
- * \param[in] device The device access the voices of
- * \param[in] voiceID The specific voice to query (0 for the device itself)
- * \return The voice's chain stage, or -1 on error (call SDL_GetError() for more info)
- *
- * \remark Voices are processed by order of highest stage to lowest. \n
- * For example, voice 0 is always on stage 0, whereas a voice that outputs to it will be on stage 1.
- */
- extern Uint32 kit_kmixerVoiceGetChainStage(kit_kmixerDevice* device, Uint32 voiceID);
- /**
- * Get the specification of a given voice
- * \param[in] device The device access the voices of
- * \param[in] voiceID The specific voice to query (0 for the device itself)
- * \return The voice's specification struct. ".format" will be 0 on error (call SDL_GetError() for more info)
- *
- * \sa kit_kmixerVoiceSetSpecRemove
- * \sa kit_kmixerVoiceSetSpecCallback
- * \sa kit_kmixerVoiceSetSpecUserdata
- */
- extern kit_kmixerVoiceSpec kit_kmixerVoiceGetSpec(kit_kmixerDevice* device, Uint32 voiceID);
- /**
- * Set the kit_kmixerVoiceRemoveCallback of a given voice
- * \param[in] device The device access the voices of
- * \param[in] voiceID The specific voice to query
- * \param[in] remove The new kit_kmixerVoiceRemoveCallback the voice should use (can be NULL)
- * \return 0 on success, or <0 on error (call SDL_GetError() for more info)
- *
- * \sa kit_kmixerVoiceGetSpec
- * \sa kit_kmixerVoiceSetSpecCallback
- * \sa kit_kmixerVoiceSetSpecUserdata
- */
- extern int kit_kmixerVoiceSetSpecRemove(kit_kmixerDevice* device, Uint32 voiceID,
- kit_kmixerVoiceRemoveCallback remove);
- /**
- * Set the kit_kmixerVoiceCallback of a given voice
- * \param[in] device The device access the voices of
- * \param[in] voiceID The specific voice to query
- * \param[in] callback The new kit_kmixerVoiceCallback the voice should use
- * \return 0 on success, or <0 on error (call SDL_GetError() for more info)
- *
- * \sa kit_kmixerVoiceGetSpec
- * \sa kit_kmixerVoiceSetSpecRemove
- * \sa kit_kmixerVoiceSetSpecUserdata
- */
- extern int kit_kmixerVoiceSetSpecCallback(kit_kmixerDevice* device, Uint32 voiceID,
- kit_kmixerVoiceCallback callback);
- /**
- * Set the userdata pointer of a given voice
- * \param[in] device The device access the voices of
- * \param[in] voiceID The specific voice to query
- * \param[in] userdata The new userdata pointer the voice should use (can be NULL)
- * \return 0 on success, or <0 on error (call SDL_GetError() for more info)
- *
- * \sa kit_kmixerVoiceGetSpec
- * \sa kit_kmixerVoiceSetSpecRemove
- * \sa kit_kmixerVoiceSetSpecCallback
- */
- extern int kit_kmixerVoiceSetSpecUserdata(kit_kmixerDevice* device, Uint32 voiceID, void* userdata);
- /**
- * Get the left channel volume of a given voice (or total volume if voice is mono)
- * \param[in] device The device access the voices of
- * \param[in] voiceID The specific voice to query (0 for the device itself)
- * \return The voice's volume, or NAN on error (call SDL_GetError() for more info)
- *
- * \sa kit_kmixerVoiceGetVolR
- * \sa kit_kmixerVoiceSetVolL
- * \sa kit_kmixerVoiceSetVolR
- * \sa kit_kmixerVoiceSetVolume
- */
- extern float kit_kmixerVoiceGetVolL(kit_kmixerDevice* device, Uint32 voiceID);
- /**
- * Get the right channel volume of a given voice (or total volume if voice is mono)
- * \param[in] device The device access the voices of
- * \param[in] voiceID The specific voice to query (0 for the device itself)
- * \return The voice's volume, or NAN on error (call SDL_GetError() for more info)
- *
- * \sa kit_kmixerVoiceGetVolL
- * \sa kit_kmixerVoiceSetVolL
- * \sa kit_kmixerVoiceSetVolR
- * \sa kit_kmixerVoiceSetVolume
- */
- extern float kit_kmixerVoiceGetVolR(kit_kmixerDevice* device, Uint32 voiceID);
- /**
- * Set the left channel volume of a given voice (or total volume if voice is mono)
- * \param[in] device The device access the voices of
- * \param[in] voiceID The specific voice to query (0 for the device itself)
- * \param[in] volL The new volume to set the voice to
- * \return 0 on success, or <0 on error (call SDL_GetError() for more info)
- *
- * \remark If volL <0, volL will be MAX()'d to 0
- * \sa kit_kmixerVoiceGetVolL
- * \sa kit_kmixerVoiceGetVolR
- * \sa kit_kmixerVoiceSetVolR
- * \sa kit_kmixerVoiceSetVolume
- */
- extern int kit_kmixerVoiceSetVolL(kit_kmixerDevice* device, Uint32 voiceID, float volL);
- /**
- * Set the right channel volume of a given voice (ignored if voice is mono)
- * \param[in] device The device access the voices of
- * \param[in] voiceID The specific voice to query (0 for the device itself)
- * \param[in] volR The new volume to set the voice to
- * \return 0 on success, or <0 on error (call SDL_GetError() for more info)
- *
- * \remark If the voice is stereo, but volR <0, volR will be set to volL
- * \sa kit_kmixerVoiceGetVolL
- * \sa kit_kmixerVoiceGetVolR
- * \sa kit_kmixerVoiceSetVolL
- * \sa kit_kmixerVoiceSetVolume
- */
- extern int kit_kmixerVoiceSetVolR(kit_kmixerDevice* device, Uint32 voiceID, float volR);
- /**
- * Set both the left and right channel volumes of a given voice
- * \param[in] device The device access the voices of
- * \param[in] voiceID The specific voice to query (0 for the device itself)
- * \param[in] volL The new volume for the left channel
- * \param[in] volR The new volume for the right channel
- * \return 0 on success, or <0 on error (call SDL_GetError() for more info)
- *
- * \remark The same rules that apply to kit_kmixerVoiceSetVolL and kit_kmixerVoiceSetVolR apply here too.
- * \sa kit_kmixerVoiceGetVolL
- * \sa kit_kmixerVoiceGetVolR
- * \sa kit_kmixerVoiceSetVolL
- * \sa kit_kmixerVoiceSetVolR
- */
- extern int kit_kmixerVoiceSetVolume(kit_kmixerDevice* device, Uint32 voiceID, float volL, float volR);
- extern int kit_kmixerVoice_Test(); //debug
- extern void kit_kmixerVoicePrintRawOrd(kit_kmixerDevice* device); //debug
- /* ----------------- */
- /* -kit_kmixerVoice- */
- /* ----------------- */
- /* +++++++++++++++++ */
- /* +kit_kmixerAsync+ */
- /* +++++++++++++++++ */
- /**
- * Add an asyncronous mixer voice (useful for playing sound effects)
- * \param[in] device The device to add the voice to
- * \param[in] vspec The specification for the new voice
- * \param[in] outputVoiceID The voice to output to (0 for the device itself)
- * \param[in] numTracks The maximum number of tracks that can play at once
- * \return The index of the newly-created voice, or 0 on error (call SDL_GetError() for more info)
- *
- * \remark There is no AsyncRemove function, as VoiceRemove handles everything automatically. \n
- * \remark Also, only the stereo and format members of vspec are important. Everything else should be ignored
- */
- extern Uint32 kit_kmixerAsyncAdd(kit_kmixerDevice* device, kit_kmixerVoiceSpec* vspec,
- Uint32 outputVoiceID, Uint32 numTracks);
- /* +++++++++++++++++ */
- /* +kit_kmixerAsync+ */
- /* +++++++++++++++++ */
- #ifdef __cplusplus
- }
- #endif
- #endif /* _KIT_SDL2_KMIXER_H */
- #endif /* _KIT_KMIXER_H */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement