#pragma once #include "boo/audiodev/IAudioVoiceEngine.hpp" #include "LtRtProcessing.hpp" #include "Common.hpp" #include "AudioVoice.hpp" #include "AudioSubmix.hpp" #include #include namespace boo { /** Base class for managing mixing and sample-rate-conversion amongst active voices */ class BaseAudioVoiceEngine : public IAudioVoiceEngine { protected: friend class AudioVoice; friend class AudioSubmix; friend class AudioVoiceMono; friend class AudioVoiceStereo; float m_totalVol = 1.f; AudioVoiceEngineMixInfo m_mixInfo; std::recursive_mutex m_dataMutex; AudioVoice* m_voiceHead = nullptr; AudioSubmix* m_submixHead = nullptr; size_t m_5msFrames = 0; IAudioVoiceEngineCallback* m_engineCallback = nullptr; /* Shared scratch buffers for accumulating audio data for resampling */ std::vector m_scratchIn; std::vector m_scratch16Pre; std::vector m_scratch32Pre; std::vector m_scratchFltPre; template std::vector& _getScratchPre(); std::vector m_scratch16Post; std::vector m_scratch32Post; std::vector m_scratchFltPost; template std::vector& _getScratchPost(); /* LtRt processing if enabled */ std::unique_ptr m_ltRtProcessing; std::vector m_ltRtIn16; std::vector m_ltRtIn32; std::vector m_ltRtInFlt; template std::vector& _getLtRtIn(); std::unique_ptr m_mainSubmix; std::list m_linearizedSubmixes; bool m_submixesDirty = true; template void _pumpAndMixVoices(size_t frames, T* dataOut); void _resetSampleRate(); public: BaseAudioVoiceEngine() : m_mainSubmix(std::make_unique(*this, nullptr, -1, false)) {} ~BaseAudioVoiceEngine(); ObjToken allocateNewMonoVoice(double sampleRate, IAudioVoiceCallback* cb, bool dynamicPitch = false); ObjToken allocateNewStereoVoice(double sampleRate, IAudioVoiceCallback* cb, bool dynamicPitch = false); ObjToken allocateNewSubmix(bool mainOut, IAudioSubmixCallback* cb, int busId); void setCallbackInterface(IAudioVoiceEngineCallback* cb); void setVolume(float vol); bool enableLtRt(bool enable); const AudioVoiceEngineMixInfo& mixInfo() const; const AudioVoiceEngineMixInfo& clientMixInfo() const; AudioChannelSet getAvailableSet() { return clientMixInfo().m_channels; } void pumpAndMixVoices() {} size_t get5MsFrames() const { return m_5msFrames; } }; template <> inline std::vector& BaseAudioVoiceEngine::_getScratchPre() { return m_scratch16Pre; } template <> inline std::vector& BaseAudioVoiceEngine::_getScratchPre() { return m_scratch32Pre; } template <> inline std::vector& BaseAudioVoiceEngine::_getScratchPre() { return m_scratchFltPre; } template <> inline std::vector& BaseAudioVoiceEngine::_getScratchPost() { return m_scratch16Post; } template <> inline std::vector& BaseAudioVoiceEngine::_getScratchPost() { return m_scratch32Post; } template <> inline std::vector& BaseAudioVoiceEngine::_getScratchPost() { return m_scratchFltPost; } template <> inline std::vector& BaseAudioVoiceEngine::_getLtRtIn() { return m_ltRtIn16; } template <> inline std::vector& BaseAudioVoiceEngine::_getLtRtIn() { return m_ltRtIn32; } template <> inline std::vector& BaseAudioVoiceEngine::_getLtRtIn() { return m_ltRtInFlt; } } // namespace boo