carb/audio/IAudioPlayback.h

File members: carb/audio/IAudioPlayback.h

// Copyright (c) 2018-2023, NVIDIA CORPORATION. All rights reserved.
//
// NVIDIA CORPORATION and its licensors retain all intellectual property
// and proprietary rights in and to this software, related documentation
// and any modifications thereto. Any use, reproduction, disclosure or
// distribution of this software and related documentation without an express
// license agreement from NVIDIA CORPORATION is strictly prohibited.
//
#pragma once

#ifndef DOXYGEN_SHOULD_SKIP_THIS
#    define _USE_MATH_DEFINES
#endif

#include "../Interface.h"
#include "AudioTypes.h"
#include "IAudioData.h"

#include <math.h>

namespace carb
{

namespace audio
{

/******************************** typedefs, enums, & macros **************************************/
struct SpeakerDirection
{
    float leftRight = 0.0f;

    float frontBack = 0.0f;

    float topBottom = 0.0f;
};

typedef uint32_t SpeakerDirectionFlags;

struct SpeakerDirectionDesc
{
    SpeakerDirectionFlags flags = 0;

    SpeakerMode speakerMode;

    SpeakerDirection directions[kMaxChannels];

    void* ext = nullptr;
};

enum class StreamState
{
    eNormal,

    eCritical,

    eMore,

    eLess,

    eMuchLess,
};

struct Streamer
{
    void(CARB_ABI* acquireReference)(Streamer* self);

    void(CARB_ABI* releaseReference)(Streamer* self);

    bool(CARB_ABI* openStream)(Streamer* self, SoundFormat* format);

    StreamState(CARB_ABI* writeStreamData)(Streamer* self, const void* data, size_t bytes);

    void(CARB_ABI* closeStream)(Streamer* self);
};

typedef uint32_t OutputFlags;

constexpr OutputFlags fOutputFlagDevice = 0x00000001;

constexpr OutputFlags fOutputFlagStreamer = 0x00000002;

constexpr OutputFlags fOutputFlagAllowNoStreamers = 0x00000004;

constexpr OutputFlags fOutputFlagAvailableMask = 0xffffffff;

struct OutputDesc
{
    OutputFlags flags = 0;

    size_t deviceIndex = 0;

    SpeakerMode speakerMode = kSpeakerModeDefault;

    size_t frameRate = 0;

    size_t streamerCount = 0;

    Streamer** streamer = nullptr;

    void* ext = nullptr;
};

enum class ContextCallbackEvent
{
    eDeviceChange,

    eCycleStart,

    eCycleEnd,
};

typedef void(CARB_ABI* ContextCallback)(Context* context, ContextCallbackEvent event, void* data, void* userData);

typedef uint32_t PlaybackContextFlags;

constexpr PlaybackContextFlags fContextFlagCycleCallbacks = 0x00000001;

constexpr PlaybackContextFlags fContextFlagBaking = 0x00000002;

constexpr PlaybackContextFlags fContextFlagManualStop = 0x00000004;

constexpr PlaybackContextFlags fContextFlagDeviceChangeCallbacks = 0x00000008;

struct PlaybackContextDesc
{
    PlaybackContextFlags flags = 0;

    ContextCallback callback = nullptr;

    void* callbackContext = nullptr;

    size_t maxBuses = 0;

    OutputDesc output = {};

    const char* outputDisplayName = nullptr;

    void* ext = nullptr;
};

struct ContextCaps
{
    size_t maxBuses;

    SpeakerDirectionDesc speakerDirections;

    DeviceCaps selectedDevice;

    OutputDesc output;

    void* ext;
};

typedef uint32_t EntityAttributeFlags;

constexpr EntityAttributeFlags fEntityFlagPosition = 0x00000001;

constexpr EntityAttributeFlags fEntityFlagVelocity = 0x00000002;

constexpr EntityAttributeFlags fEntityFlagForward = 0x00000004;

constexpr EntityAttributeFlags fEntityFlagUp = 0x00000008;

constexpr EntityAttributeFlags fEntityFlagCone = 0x00000010;

constexpr EntityAttributeFlags fEntityFlagRolloff = 0x00000020;

constexpr EntityAttributeFlags fEntityFlagAll = fEntityFlagPosition | fEntityFlagVelocity | fEntityFlagForward |
                                                fEntityFlagUp | fEntityFlagCone | fEntityFlagRolloff;

constexpr EntityAttributeFlags fEntityFlagMakePerp = 0x80000000;

constexpr EntityAttributeFlags fEntityFlagNormalize = 0x40000000;
enum class RolloffType
{
    eInverse,

    eLinear,

    eLinearSquare,
};

struct RolloffCurve
{
    size_t pointCount;

    Float2* points;
};

struct RolloffDesc
{
    RolloffType type;

    float nearDistance;

    float farDistance;

    RolloffCurve* volume;

    RolloffCurve* lowFrequency;

    RolloffCurve* lowPassDirect;

    RolloffCurve* lowPassReverb;

    RolloffCurve* reverb;

    void* ext = nullptr;
};

struct DspValuePair
{
    float inner;

    float outer;
};

constexpr float kConeAngleOmnidirectional = (float)(2.0 * M_PI);

struct EntityCone
{
    float insideAngle;

    float outsideAngle;

    DspValuePair volume;

    DspValuePair lowPassFilter;

    DspValuePair reverb;

    void* ext = nullptr;
};

struct EntityAttributes
{
    EntityAttributeFlags flags;

    Float3 position;

    Float3 velocity;

    Float3 forward;

    Float3 up;

    EntityCone cone;
};

struct ListenerAttributes : EntityAttributes
{
    void* ext = nullptr;
};

struct EmitterAttributes : EntityAttributes
{
    RolloffDesc rolloff;

    void* ext = nullptr;
};

enum class VoiceCallbackType
{
    eSoundEnded,

    eEventPoint,

    eLoopPoint,
};

typedef AudioResult(CARB_ABI* VoiceCallback)(
    Voice* voice, VoiceCallbackType callbackType, SoundData* sound, void* data, void* context);

typedef uint32_t PlaybackModeFlags;

constexpr PlaybackModeFlags fPlaybackModeSpatial = 0x00000001;

constexpr PlaybackModeFlags fPlaybackModeListenerRelative = 0x00000002;

constexpr PlaybackModeFlags fPlaybackModeDistanceDelay = 0x00000004;

constexpr PlaybackModeFlags fPlaybackModeInterauralDelay = 0x00000008;

constexpr PlaybackModeFlags fPlaybackModeUseDoppler = 0x00000010;

constexpr PlaybackModeFlags fPlaybackModeUseReverb = 0x00000020;

constexpr PlaybackModeFlags fPlaybackModeUseFilters = 0x00000040;

constexpr PlaybackModeFlags fPlaybackModeMuted = 0x00000080;

constexpr PlaybackModeFlags fPlaybackModePaused = 0x00000100;

constexpr PlaybackModeFlags fPlaybackModeFadeIn = 0x00000200;

constexpr PlaybackModeFlags fPlaybackModeSimulatePosition = 0x00000400;

constexpr PlaybackModeFlags fPlaybackModeNoPositionSimulation = 0x00000800;

constexpr PlaybackModeFlags fPlaybackModeSpatialMixLevelMatrix = 0x00001000;

constexpr PlaybackModeFlags fPlaybackModeNoSpatialLowFrequencyEffect = 0x00002000;

constexpr PlaybackModeFlags fPlaybackModeStopOnSimulation = 0x00004000;

constexpr PlaybackModeFlags fPlaybackModeAvailableMask = 0x7fffffff;

constexpr PlaybackModeFlags fPlaybackModeDefaultUseDoppler = 0x40000000;

constexpr PlaybackModeFlags fPlaybackModeDefaultDistanceDelay = 0x20000000;

constexpr PlaybackModeFlags fPlaybackModeDefaultInterauralDelay = 0x10000000;

constexpr PlaybackModeFlags fPlaybackModeDefaultUseReverb = 0x08000000;

constexpr PlaybackModeFlags fPlaybackModeDefaultUseFilters = 0x04000000;

constexpr PlaybackModeFlags fPlaybackModeDefaultMask =
    fPlaybackModeDefaultUseDoppler | fPlaybackModeDefaultDistanceDelay | fPlaybackModeDefaultInterauralDelay |
    fPlaybackModeDefaultUseReverb | fPlaybackModeDefaultUseFilters;

constexpr size_t kPlaybackModeDefaultFlagCount = 10;

// FIXME: exhale can't handle this
#ifndef DOXYGEN_SHOULD_SKIP_THIS
constexpr PlaybackModeFlags getForceOffPlaybackModeFlags(PlaybackModeFlags flags)
{
    return (flags & fPlaybackModeDefaultMask) >> kPlaybackModeDefaultFlagCount;
}

constexpr PlaybackModeFlags getForceOnPlaybackModeFlags(PlaybackModeFlags flags)
{
    return (flags & fPlaybackModeDefaultMask) >> (kPlaybackModeDefaultFlagCount * 2);
}
#endif
typedef uint32_t VoiceParamFlags;

constexpr VoiceParamFlags fVoiceParamAll = static_cast<VoiceParamFlags>(~0);

constexpr VoiceParamFlags fVoiceParamPlaybackMode = 0x00000001;

constexpr VoiceParamFlags fVoiceParamVolume = 0x00000002;

constexpr VoiceParamFlags fVoiceParamMute = 0x00000004;

constexpr VoiceParamFlags fVoiceParamBalance = 0x00000008;

constexpr VoiceParamFlags fVoiceParamFrequencyRatio = 0x00000010;

constexpr VoiceParamFlags fVoiceParamPriority = 0x00000020;

constexpr VoiceParamFlags fVoiceParamPause = 0x00000040;

constexpr VoiceParamFlags fVoiceParamSpatialMixLevel = 0x00000080;

constexpr VoiceParamFlags fVoiceParamDopplerScale = 0x00000100;

constexpr VoiceParamFlags fVoiceParamOcclusionFactor = 0x00000200;

constexpr VoiceParamFlags fVoiceParamEmitter = 0x00000400;

constexpr VoiceParamFlags fVoiceParamMatrix = 0x00000800;
struct VoiceParams
{
    PlaybackModeFlags playbackMode;

    float volume;

    struct VoiceParamBalance
    {
        float pan;

        float fade;
    } balance;

    float frequencyRatio;

    int32_t priority;

    float spatialMixLevel;

    float dopplerScale;

    struct VoiceParamOcclusion
    {
        float direct;

        float reverb;
    } occlusion;

    EmitterAttributes emitter;

    const float* matrix;

    void* ext = nullptr;
};

using ContextParamFlags = uint32_t;

constexpr ContextParamFlags fContextParamAll = ~0u;

constexpr ContextParamFlags fContextParamSpeedOfSound = 0x00000001;

constexpr ContextParamFlags fContextParamWorldUnitScale = 0x00000002;

constexpr ContextParamFlags fContextParamListener = 0x00000004;

constexpr ContextParamFlags fContextParamDopplerScale = 0x00000008;

constexpr ContextParamFlags fContextParamVirtualizationThreshold = 0x00000010;

constexpr ContextParamFlags fContextParamSpatialFrequencyRatio = 0x00000020;

constexpr ContextParamFlags fContextParamNonSpatialFrequencyRatio = 0x00000040;

constexpr ContextParamFlags fContextParamMasterVolume = 0x00000080;

constexpr ContextParamFlags fContextParamSpatialVolume = 0x00000100;

constexpr ContextParamFlags fContextParamNonSpatialVolume = 0x00000200;

constexpr ContextParamFlags fContextParamDopplerLimit = 0x00000400;

constexpr ContextParamFlags fContextParamDefaultPlaybackMode = 0x00000800;

constexpr ContextParamFlags fContextParamFlags = 0x00001000;

constexpr ContextParamFlags fContextParamVideoLatency = 0x00002000;

constexpr ContextParamFlags fContextParamFlagValidateVoiceTable = 0x10000000;
constexpr float kDefaultSpeedOfSound = 340.f;

struct ContextParams
{
    float speedOfSound;

    float unitsPerMeter;

    float dopplerScale;

    float dopplerLimit;

    float virtualizationThreshold;

    float spatialFrequencyRatio;

    float nonSpatialFrequencyRatio;

    float masterVolume;

    float spatialVolume;

    float nonSpatialVolume;

    ListenerAttributes listener;

    PlaybackModeFlags defaultPlaybackMode;

    ContextParamFlags flags;

    void* ext = nullptr;
};

struct ContextParams2
{
    int64_t videoLatency = 0;

    int64_t videoLatencyTrim = 0;

    void* padding[32] = {};

    void* ext = nullptr;
};

constexpr size_t kLoopDescNoLoop = ~0ull;

struct LoopPointDesc
{
    const EventPoint* loopPoint = nullptr;

    size_t loopPointIndex = kLoopDescNoLoop;

    void* ext = nullptr;
};

typedef uint32_t PlayFlags;

constexpr PlayFlags fPlayFlagUseEventPoints = 0x00000001;

constexpr PlayFlags fPlayFlagRealtimeCallbacks = 0x00000002;

constexpr PlayFlags fPlayFlagMaxInstancesSimulate = 0x00000004;

constexpr PlayFlags fPlayFlagAvailableMask = 0x01ffffff;
struct PlaySoundDesc
{
    PlayFlags flags = 0;

    SoundData* sound;

    VoiceParamFlags validParams = 0;

    VoiceParams* params = nullptr;

    LoopPointDesc loopPoint = {};

    VoiceCallback callback = nullptr;

    void* callbackContext = nullptr;

    size_t playStart = 0;

    size_t playLength = 0;

    UnitType playUnits = UnitType::eFrames;

    void* ext = nullptr;
};

struct PlaySoundDesc2
{
    int64_t delayTime = 0;

    void* padding[32] = {};

    void* ext = nullptr;
};

/********************************** IAudioPlayback Interface **********************************/
struct IAudioPlayback
{
    CARB_PLUGIN_INTERFACE("carb::audio::IAudioPlayback", 1, 1)

    /************************ context and device management functions ****************************/
    size_t(CARB_ABI* getDeviceCount)();

    AudioResult(CARB_ABI* getDeviceCaps)(size_t deviceIndex, DeviceCaps* caps);

    Context*(CARB_ABI* createContext)(const PlaybackContextDesc* desc);

    AudioResult(CARB_ABI* destroyContext)(Context* context);

    const ContextCaps*(CARB_ABI* getContextCaps)(Context* context);

    void(CARB_ABI* setContextParameters)(Context* context, ContextParamFlags paramsToSet, const ContextParams* params);

    void(CARB_ABI* getContextParameters)(Context* context, ContextParamFlags paramsToGet, ContextParams* params);

    bool(CARB_ABI* setBusCount)(Context* ctx, size_t count);

    bool(CARB_ABI* setSpeakerDirections)(Context* context, const SpeakerDirectionDesc* desc);

    AudioResult(CARB_ABI* setOutput)(Context* context, const OutputDesc* desc);

    AudioResult(CARB_ABI* update)(Context* context);

    void(CARB_ABI* startProcessing)(Context* context);

    void(CARB_ABI* stopProcessing)(Context* context);

    /********************************** sound management functions *******************************/
    Voice*(CARB_ABI* playSound)(Context* context, const PlaySoundDesc* desc);

    void(CARB_ABI* stopVoice)(Voice* voice);

    /********************************** voice management functions *******************************/
    SoundData*(CARB_ABI* getPlayingSound)(Voice* voice);

    bool(CARB_ABI* isPlaying)(Voice* voice);

    bool(CARB_ABI* setLoopPoint)(Voice* voice, const LoopPointDesc* desc);

    size_t(CARB_ABI* getPlayCursor)(Voice* voice, UnitType type);

    void(CARB_ABI* setVoiceParameters)(Voice* voice, VoiceParamFlags paramsToSet, const VoiceParams* params);

    void(CARB_ABI* getVoiceParameters)(Voice* voice, VoiceParamFlags paramsToGet, VoiceParams* params);

    void(CARB_ABI* stopAllVoices)(Context* context);
};

} // namespace audio
} // namespace carb