diff --git a/include/sndcore2/core.h b/include/sndcore2/core.h new file mode 100644 index 0000000..c9b61ab --- /dev/null +++ b/include/sndcore2/core.h @@ -0,0 +1,87 @@ +#pragma once +#include +#include "result.h" + +/** + * \defgroup sndcore2_core Core + * \ingroup sndcore2 + * + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct AXProfile AXProfile; +typedef struct AXInitParams AXInitParams; + +typedef void(*AXFrameCallback)(void); + +//! A value from enum AX_INIT_RENDERER. +typedef uint32_t AXInitRenderer; + +//! A value from enum AX_INIT_PIPELINE. +typedef uint32_t AXInitPipeline; + +enum AX_INIT_RENDERER +{ + AX_INIT_RENDERER_32KHZ = 0, + AX_INIT_RENDERER_48KHZ = 1, +}; + +enum AX_INIT_PIPELINE +{ + AX_INIT_PIPELINE_SINGLE = 0, + AX_INIT_PIPELINE_FOUR_STAGE = 1, +}; + +struct AXProfile +{ + // Unknown +}; + +struct AXInitParams +{ + AXInitRenderer renderer; + UNKNOWN(4); + AXInitPipeline pipeline; +}; +CHECK_OFFSET(AXInitParams, 0x00, renderer); +CHECK_OFFSET(AXInitParams, 0x08, pipeline); +CHECK_SIZE(AXInitParams, 0x0C); + +void +AXInit(); + +void +AXInitWithParams(AXInitParams *params); + +BOOL +AXIsInit(); + +void +AXInitProfile(AXProfile *profile, + uint32_t count); + +uint32_t +AXGetSwapProfile(AXProfile *profile, + uint32_t count); + +AXResult +AXSetDefaultMixerSelect(uint32_t unk0); + +AXResult +AXRegisterAppFrameCallback(AXFrameCallback callback); + +uint32_t +AXGetInputSamplesPerFrame(); + +uint32_t +AXGetInputSamplesPerSec(); + +#ifdef __cplusplus +} +#endif + +/** @} */ diff --git a/include/sndcore2/device.h b/include/sndcore2/device.h new file mode 100644 index 0000000..14817d9 --- /dev/null +++ b/include/sndcore2/device.h @@ -0,0 +1,86 @@ +#pragma once +#include +#include "result.h" + +/** + * \defgroup sndcore2_device Device + * \ingroup sndcore2 + * + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void(*AXDeviceFinalMixCallback)(void*); +typedef void(*AXAuxCallback)(void*, void*); + +//! A value from enum AX_DEVICE_MODE. +typedef uint32_t AXDeviceMode; + +//! A value from enum AX_DEVICE_TYPE. +typedef uint32_t AXDeviceType; + +enum AX_DEVICE_MODE +{ + // Unknown + AX_DEVICE_MODE_UNKNOWN +}; + +enum AX_DEVICE_TYPE +{ + AX_DEVICE_TYPE_TV = 0, + AX_DEVICE_TYPE_DRC = 1, + AX_DEVICE_TYPE_CONTROLLER = 2, +}; + +AXResult +AXGetDeviceMode(AXDeviceType type, + AXDeviceMode *mode); + +AXResult +AXGetDeviceFinalMixCallback(AXDeviceType type, + AXDeviceFinalMixCallback *func); + +AXResult +AXRegisterDeviceFinalMixCallback(AXDeviceType type, + AXDeviceFinalMixCallback func); + +AXResult +AXGetAuxCallback(AXDeviceType type, + uint32_t unk0, + uint32_t unk1, + AXAuxCallback *callback, + void **userData); + +AXResult +AXRegisterAuxCallback(AXDeviceType type, + uint32_t unk0, + uint32_t unk1, + AXAuxCallback callback, + void *userData); + +AXResult +AXSetDeviceLinearUpsampler(AXDeviceType type, + uint32_t unk0, + uint32_t unk1); + +AXResult +AXSetDeviceCompressor(AXDeviceType type, + uint32_t unk0); + +AXResult +AXSetDeviceUpsampleStage(AXDeviceType type, + BOOL postFinalMix); + +AXResult +AXSetDeviceVolume(AXDeviceType type, + uint32_t id, + uint16_t volume); + +#ifdef __cplusplus +} +#endif + +/** @} */ diff --git a/include/sndcore2/drcvs.h b/include/sndcore2/drcvs.h new file mode 100644 index 0000000..8577e54 --- /dev/null +++ b/include/sndcore2/drcvs.h @@ -0,0 +1,99 @@ +#pragma once +#include +#include "result.h" + +/** + * \defgroup sndcore2_drcvs DRC VS + * \ingroup sndcore2 + * + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +//! A value from enum AX_DRC_VS_MODE. +typedef uint32_t AXDRCVSMode; + +//! A value from enum AX_DRC_VS_OUTPUT. +typedef uint32_t AXDRCVSOutput; + +//! A value from enum AX_DRC_VS_LC. +typedef uint32_t AXDRCVSLC; + +//! A value from enum AX_DRC_VS_SPEAKER_POS. +typedef uint32_t AXDRCVSSpeakerPosition; + +//! A value from enum AX_DRC_VS_SURROUND_GAIN. +typedef uint32_t AXDRCVSSurroundLevelGain; + +enum AX_DRC_VS_MODE +{ + // Unknown + AX_DRC_VS_MODE_UNKNOWN +}; + +enum AX_DRC_VS_OUTPUT +{ + // Unknown + AX_DRC_VS_OUTPUT_UNKNOWN +}; + +enum AX_DRC_VS_LC +{ + // Unknown + AX_DRC_VS_LC_UNKNOWN +}; + +enum AX_DRC_VS_SPEAKER_POS +{ + // Unknown + AX_DRC_VS_SPEAKER_POS_UNKNOWN +}; + +enum AX_DRC_VS_SURROUND_GAIN +{ + // Unknown + AX_DRC_VS_SURROUND_GAIN_UNKNOWN +}; + +AXResult +AXGetDRCVSMode(AXDRCVSMode *mode); + +AXResult +AXSetDRCVSMode(AXDRCVSMode mode); + +AXResult +AXSetDRCVSDownmixBalance(AXDRCVSOutput output, + float balance); + +AXResult +AXSetDRCVSLC(AXDRCVSLC lc); + +AXResult +AXSetDRCVSLimiter(BOOL limit); + +AXResult +AXSetDRCVSLimiterThreshold(float threshold); + +AXResult +AXSetDRCVSOutputGain(AXDRCVSOutput output, + float gain); + +AXResult +AXSetDRCVSSpeakerPosition(AXDRCVSOutput output, + AXDRCVSSpeakerPosition pos); + +AXResult +AXSetDRCVSSurroundDepth(AXDRCVSOutput output, + float depth); + +AXResult +AXSetDRCVSSurroundLevelGain(AXDRCVSSurroundLevelGain gain); + +#ifdef __cplusplus +} +#endif + +/** @} */ diff --git a/include/sndcore2/result.h b/include/sndcore2/result.h new file mode 100644 index 0000000..ea9873f --- /dev/null +++ b/include/sndcore2/result.h @@ -0,0 +1,31 @@ +#pragma once +#include + +/** + * \defgroup sndcore2_result Result + * \ingroup sndcore2 + * + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +//! A value from enum AX_RESULT. +typedef int32_t AXResult; + +enum AX_RESULT +{ + AX_RESULT_SUCCESS = 0, + AX_RESULT_INVALID_DEVICE_TYPE = -1, + AX_RESULT_INVALID_DRC_VS_MODE = -13, + AX_RESULT_VOICE_IS_RUNNING = -18, + AX_RESULT_DELAY_TOO_BIG = -19, +}; + +#ifdef __cplusplus +} +#endif + +/** @} */ diff --git a/include/sndcore2/voice.h b/include/sndcore2/voice.h new file mode 100644 index 0000000..4eb0def --- /dev/null +++ b/include/sndcore2/voice.h @@ -0,0 +1,378 @@ +#pragma once +#include +#include "device.h" +#include "result.h" + +/** + * \defgroup sndcore2_voice Voice + * \ingroup sndcore2 + * + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct AXVoice AXVoice; +typedef struct AXVoiceAdpcmLoopData AXVoiceAdpcmLoopData; +typedef struct AXVoiceAdpcm AXVoiceAdpcm; +typedef struct AXVoiceDeviceBusMixData AXVoiceDeviceBusMixData; +typedef struct AXVoiceDeviceMixData AXVoiceDeviceMixData; +typedef struct AXVoiceLink AXVoiceLink; +typedef struct AXVoiceOffsets AXVoiceOffsets; +typedef struct AXVoiceSrc AXVoiceSrc; +typedef struct AXVoiceVeData AXVoiceVeData; + +//! A value from enum AX_VOICE_FORMAT. +typedef uint16_t AXVoiceFormat; + +//! A value from enum AX_VOICE_LOOP. +typedef uint16_t AXVoiceLoop; + +//! A value from enum AX_VOICE_SRC_TYPE. +typedef uint32_t AXVoiceSrcType; + +//! A value from enum AX_VOICE_STATE. +typedef uint32_t AXVoiceState; + +//! A value from enum AX_VOICE_RENDERER. +typedef uint32_t AXVoiceRenderer; + +//! A value from enum AX_VOICE_RATIO_RESULT. +typedef int32_t AXVoiceSrcRatioResult; + +//! A value from enum AX_VOICE_TYPE. +typedef uint32_t AXVoiceType; + +typedef void(*AXVoiceCallbackFn)(void *); +typedef void(*AXVoiceCallbackExFn)(void *, uint32_t, uint32_t); + +enum AX_VOICE_FORMAT +{ + AX_VOICE_FORMAT_ADPCM = 0, + AX_VOICE_FORMAT_LPCM16 = 10, + AX_VOICE_FORMAT_LPCM8 = 25, +}; + +enum AX_VOICE_LOOP +{ + AX_VOICE_LOOP_DISABLED = 0, + AX_VOICE_LOOP_ENABLED = 1, +}; + +enum AX_VOICE_RENDERER +{ + AX_VOICE_RENDERER_DSP = 0, + AX_VOICE_RENDERER_CPU = 1, + AX_VOICE_RENDERER_AUTO = 2, +}; + +enum AX_VOICE_RATIO_RESULT +{ + AX_VOICE_RATIO_RESULT_SUCCESS = 0, + AX_VOICE_RATIO_RESULT_LESS_THAN_ZERO = -1, + AX_VOICE_RATIO_RESULT_GREATER_THAN_SOMETHING = -2, +}; + +enum AX_VOICE_SRC_TYPE +{ + AX_VOICE_SRC_TYPE_NONE = 0, + AX_VOICE_SRC_TYPE_LINEAR = 1, + AX_VOICE_SRC_TYPE_UNK0 = 2, + AX_VOICE_SRC_TYPE_UNK1 = 3, + AX_VOICE_SRC_TYPE_UNK2 = 4, +}; + +enum AX_VOICE_STATE +{ + AX_VOICE_STATE_STOPPED = 0, + AX_VOICE_STATE_PLAYING = 1, +}; + +enum AX_VOICE_TYPE +{ + // Unknown + AX_VOICE_TYPE_UNKNOWN +}; + +struct AXVoiceLink +{ + AXVoice *next; + AXVoice *prev; +}; +CHECK_OFFSET(AXVoiceLink, 0x0, next); +CHECK_OFFSET(AXVoiceLink, 0x4, prev); +CHECK_SIZE(AXVoiceLink, 0x8); + +struct AXVoiceOffsets +{ + AXVoiceFormat dataType; + AXVoiceLoop loopingEnabled; + uint32_t loopOffset; + uint32_t endOffset; + uint32_t currentOffset; + const void *data; +}; +CHECK_OFFSET(AXVoiceOffsets, 0x0, dataType); +CHECK_OFFSET(AXVoiceOffsets, 0x2, loopingEnabled); +CHECK_OFFSET(AXVoiceOffsets, 0x4, loopOffset); +CHECK_OFFSET(AXVoiceOffsets, 0x8, endOffset); +CHECK_OFFSET(AXVoiceOffsets, 0xc, currentOffset); +CHECK_OFFSET(AXVoiceOffsets, 0x10, data); +CHECK_SIZE(AXVoiceOffsets, 0x14); + +struct AXVoice +{ + //! The index of this voice out of the total voices + uint32_t index; + + //! Current play state of this voice + AXVoiceState state; + + //! Current volume of this voice + uint32_t volume; + + //! The renderer to use for this voice + AXVoiceRenderer renderer; + + //! this is a link used in the stack, we do this in host-memory currently + AXVoiceLink link; + + //! A link to the next callback to invoke + AXVoice *cbNext; + + //! The priority of this voice used for force-acquiring a voice + uint32_t priority; + + //! The callback to call if this is force-free'd by another acquire + AXVoiceCallbackFn callback; + + //! The user context to send to the callbacks + void *userContext; + + //! A bitfield representing different things needing to be synced. + uint32_t syncBits; + + UNKNOWN(0x8); + + //! The current offset data! + AXVoiceOffsets offsets; + + //! An extended version of the callback above + AXVoiceCallbackExFn callbackEx; + + //! The reason for the callback being invoked + uint32_t callbackReason; + + float unk0; + float unk1; +}; +CHECK_OFFSET(AXVoice, 0x0, index); +CHECK_OFFSET(AXVoice, 0x4, state); +CHECK_OFFSET(AXVoice, 0x8, volume); +CHECK_OFFSET(AXVoice, 0xc, renderer); +CHECK_OFFSET(AXVoice, 0x10, link); +CHECK_OFFSET(AXVoice, 0x18, cbNext); +CHECK_OFFSET(AXVoice, 0x1c, priority); +CHECK_OFFSET(AXVoice, 0x20, callback); +CHECK_OFFSET(AXVoice, 0x24, userContext); +CHECK_OFFSET(AXVoice, 0x28, syncBits); +CHECK_OFFSET(AXVoice, 0x34, offsets); +CHECK_OFFSET(AXVoice, 0x48, callbackEx); +CHECK_OFFSET(AXVoice, 0x4c, callbackReason); +CHECK_OFFSET(AXVoice, 0x50, unk0); +CHECK_OFFSET(AXVoice, 0x54, unk1); +CHECK_SIZE(AXVoice, 0x58); + +struct AXVoiceDeviceBusMixData +{ + uint16_t volume; + int16_t delta; +}; +CHECK_OFFSET(AXVoiceDeviceBusMixData, 0x0, volume); +CHECK_OFFSET(AXVoiceDeviceBusMixData, 0x2, delta); +CHECK_SIZE(AXVoiceDeviceBusMixData, 0x4); + +struct AXVoiceDeviceMixData +{ + AXVoiceDeviceBusMixData bus[4]; +}; +CHECK_OFFSET(AXVoiceDeviceMixData, 0x0, bus); +CHECK_SIZE(AXVoiceDeviceMixData, 0x10); + +struct AXVoiceVeData +{ + uint16_t volume; + int16_t delta; +}; +CHECK_OFFSET(AXVoiceVeData, 0x0, volume); +CHECK_OFFSET(AXVoiceVeData, 0x2, delta); +CHECK_SIZE(AXVoiceVeData, 0x4); + +struct AXVoiceAdpcmLoopData +{ + uint16_t predScale; + int16_t prevSample[2]; +}; +CHECK_OFFSET(AXVoiceAdpcmLoopData, 0x0, predScale); +CHECK_OFFSET(AXVoiceAdpcmLoopData, 0x2, prevSample); +CHECK_SIZE(AXVoiceAdpcmLoopData, 0x6); + +struct AXVoiceAdpcm +{ + int16_t coefficients[16]; + uint16_t gain; + uint16_t predScale; + int16_t prevSample[2]; +}; +CHECK_OFFSET(AXVoiceAdpcm, 0x0, coefficients); +CHECK_OFFSET(AXVoiceAdpcm, 0x20, gain); +CHECK_OFFSET(AXVoiceAdpcm, 0x22, predScale); +CHECK_OFFSET(AXVoiceAdpcm, 0x24, prevSample); +CHECK_SIZE(AXVoiceAdpcm, 0x28); + +#pragma pack(push, 1) + +/** + * AXVoice Sample Rate Converter + */ +struct AXVoiceSrc +{ + //! Playback rate, fixed 16.16 + uint32_t ratio; + + //! Used by the resampler, fixed 0.16 + uint16_t currentOffsetFrac; + int16_t lastSample[4]; +}; +CHECK_OFFSET(AXVoiceSrc, 0x0, ratio); +CHECK_OFFSET(AXVoiceSrc, 0x4, currentOffsetFrac); +CHECK_OFFSET(AXVoiceSrc, 0x6, lastSample); +CHECK_SIZE(AXVoiceSrc, 0xe); + +#pragma pack(pop) + +AXVoice * +AXAcquireVoice(uint32_t priority, + AXVoiceCallbackFn callback, + void *userContext); + +AXVoice * +AXAcquireVoiceEx(uint32_t priority, + AXVoiceCallbackExFn callback, + void *userContext); + +BOOL +AXCheckVoiceOffsets(AXVoiceOffsets *offsets); + +void +AXFreeVoice(AXVoice *voice); + +uint32_t +AXGetMaxVoices(); + +uint32_t +AXGetVoiceCurrentOffsetEx(AXVoice *voice, + const void *samples); + +uint32_t +AXGetVoiceLoopCount(AXVoice *voice); + +void +AXGetVoiceOffsets(AXVoice *voice, + AXVoiceOffsets *offsets); + +BOOL +AXIsVoiceRunning(AXVoice *voice); + +void +AXSetVoiceAdpcm(AXVoice *voice, + AXVoiceAdpcm *adpcm); + +void +AXSetVoiceAdpcmLoop(AXVoice *voice, + AXVoiceAdpcmLoopData *loopData); + +void +AXSetVoiceCurrentOffset(AXVoice *voice, + uint32_t offset); + +AXResult +AXSetVoiceDeviceMix(AXVoice *voice, + AXDeviceType type, + uint32_t id, + AXVoiceDeviceMixData *mixData); + +void +AXSetVoiceEndOffset(AXVoice *voice, + uint32_t offset); + +void +AXSetVoiceEndOffsetEx(AXVoice *voice, + uint32_t offset, + const void *samples); + +AXResult +AXSetVoiceInitialTimeDelay(AXVoice *voice, + uint16_t delay); + +void +AXSetVoiceLoopOffset(AXVoice *voice, + uint32_t offset); + +void +AXSetVoiceLoopOffsetEx(AXVoice *voice, + uint32_t offset, + const void *samples); + +void +AXSetVoiceLoop(AXVoice *voice, + AXVoiceLoop loop); + +void +AXSetVoiceOffsets(AXVoice *voice, + AXVoiceOffsets *offsets); + +void +AXSetVoicePriority(AXVoice *voice, + uint32_t priority); + +void +AXSetVoiceRmtIIRCoefs(AXVoice *voice, + uint16_t filter, + ...); + +void +AXSetVoiceSrc(AXVoice *voice, + AXVoiceSrc *src); + +AXVoiceSrcRatioResult +AXSetVoiceSrcRatio(AXVoice *voice, + float ratio); + +void +AXSetVoiceSrcType(AXVoice *voice, + AXVoiceSrcType type); + +void +AXSetVoiceState(AXVoice *voice, + AXVoiceState state); + +void +AXSetVoiceType(AXVoice *voice, + AXVoiceType type); + +void +AXSetVoiceVe(AXVoice *voice, + AXVoiceVeData *veData); + +void +AXSetVoiceVeDelta(AXVoice *voice, + int16_t delta); + +#ifdef __cplusplus +} +#endif + +/** @} */ diff --git a/rpl/Makefile b/rpl/Makefile index b5c9c62..e347ea8 100644 --- a/rpl/Makefile +++ b/rpl/Makefile @@ -1,4 +1,4 @@ -TARGETS := libcoreinit libgx2 libnsysnet libvpad libsysapp libproc_ui +TARGETS := libcoreinit libgx2 libnsysnet libvpad libproc_ui libsndcore2 libsysapp all: @for dir in $(TARGETS); do \ diff --git a/rpl/libsndcore2/Makefile b/rpl/libsndcore2/Makefile new file mode 100644 index 0000000..0db6a68 --- /dev/null +++ b/rpl/libsndcore2/Makefile @@ -0,0 +1,2 @@ +-include ../common/rules.mk +-include ../../common/rules.mk diff --git a/rpl/libsndcore2/config.h b/rpl/libsndcore2/config.h new file mode 100644 index 0000000..815c97d --- /dev/null +++ b/rpl/libsndcore2/config.h @@ -0,0 +1 @@ +#define LIBRARY_NAME "sndcore2" diff --git a/rpl/libsndcore2/exports.h b/rpl/libsndcore2/exports.h new file mode 100644 index 0000000..a607459 --- /dev/null +++ b/rpl/libsndcore2/exports.h @@ -0,0 +1,64 @@ +// sndcore2/core.h +EXPORT(AXInit); +EXPORT(AXInitWithParams); +EXPORT(AXIsInit); +EXPORT(AXInitProfile); +EXPORT(AXGetSwapProfile); +EXPORT(AXSetDefaultMixerSelect); +EXPORT(AXRegisterAppFrameCallback); +EXPORT(AXGetInputSamplesPerFrame); +EXPORT(AXGetInputSamplesPerSec); + +// sndcore2/device.h +EXPORT(AXGetDeviceMode); +EXPORT(AXGetDeviceFinalMixCallback); +EXPORT(AXRegisterDeviceFinalMixCallback); +EXPORT(AXGetAuxCallback); +EXPORT(AXRegisterAuxCallback); +EXPORT(AXSetDeviceLinearUpsampler); +EXPORT(AXSetDeviceCompressor); +EXPORT(AXSetDeviceUpsampleStage); +EXPORT(AXSetDeviceVolume); + +// sndcore2/drcvs.h +EXPORT(AXGetDRCVSMode); +EXPORT(AXSetDRCVSMode); +EXPORT(AXSetDRCVSDownmixBalance); +EXPORT(AXSetDRCVSLC); +EXPORT(AXSetDRCVSLimiter); +EXPORT(AXSetDRCVSLimiterThreshold); +EXPORT(AXSetDRCVSOutputGain); +EXPORT(AXSetDRCVSSpeakerPosition); +EXPORT(AXSetDRCVSSurroundDepth); +EXPORT(AXSetDRCVSSurroundLevelGain); + +// sndcore2/voice.h +EXPORT(AXAcquireVoice); +EXPORT(AXAcquireVoiceEx); +EXPORT(AXCheckVoiceOffsets); +EXPORT(AXFreeVoice); +EXPORT(AXGetMaxVoices); +EXPORT(AXGetVoiceCurrentOffsetEx); +EXPORT(AXGetVoiceLoopCount); +EXPORT(AXGetVoiceOffsets); +EXPORT(AXIsVoiceRunning); +EXPORT(AXSetVoiceAdpcm); +EXPORT(AXSetVoiceAdpcmLoop); +EXPORT(AXSetVoiceCurrentOffset); +EXPORT(AXSetVoiceDeviceMix); +EXPORT(AXSetVoiceEndOffset); +EXPORT(AXSetVoiceEndOffsetEx); +EXPORT(AXSetVoiceInitialTimeDelay); +EXPORT(AXSetVoiceLoopOffset); +EXPORT(AXSetVoiceLoopOffsetEx); +EXPORT(AXSetVoiceLoop); +EXPORT(AXSetVoiceOffsets); +EXPORT(AXSetVoicePriority); +EXPORT(AXSetVoiceRmtIIRCoefs); +EXPORT(AXSetVoiceSrc); +EXPORT(AXSetVoiceSrcRatio); +EXPORT(AXSetVoiceSrcType); +EXPORT(AXSetVoiceState); +EXPORT(AXSetVoiceType); +EXPORT(AXSetVoiceVe); +EXPORT(AXSetVoiceVeDelta);