Allocate submixes and voices using boo::ObjToken

This commit is contained in:
Jack Andersen 2017-12-03 16:50:33 -10:00
parent 135f504899
commit 489e7e671b
15 changed files with 47 additions and 42 deletions

View File

@ -13,7 +13,7 @@ class IObj
protected: protected:
virtual ~IObj() = default; virtual ~IObj() = default;
public: public:
virtual std::unique_lock<std::recursive_mutex> destructorLock() { return {}; } virtual std::unique_lock<std::recursive_mutex> destructorLock()=0;
void increment() { m_refCount++; } void increment() { m_refCount++; }
void decrement() void decrement()
{ {

View File

@ -241,7 +241,7 @@ struct DeferredWindowEvents : public IWindowCallback
m_cmds.back().m_mods = mod; m_cmds.back().m_mods = mod;
} }
ITextInputCallback* getTextInputCallback() {return m_rec.getTextInputCallback();} ITextInputCallback* getTextInputCallback() { return m_rec.getTextInputCallback(); }
void dispatchEvents() void dispatchEvents()
{ {

View File

@ -27,7 +27,7 @@ class IApplication
friend class WindowWin32; friend class WindowWin32;
virtual void _deletedWindow(IWindow* window)=0; virtual void _deletedWindow(IWindow* window)=0;
public: public:
virtual ~IApplication() {} virtual ~IApplication() = default;
enum class EPlatformType enum class EPlatformType
{ {

View File

@ -4,6 +4,7 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <memory> #include <memory>
#include "boo/BooObject.hpp"
namespace boo namespace boo
{ {
@ -19,10 +20,8 @@ enum class SubmixFormat
Float Float
}; };
struct IAudioSubmix struct IAudioSubmix : IObj
{ {
virtual ~IAudioSubmix() = default;
/** Reset channel-levels to silence; unbind all submixes */ /** Reset channel-levels to silence; unbind all submixes */
virtual void resetSendLevels()=0; virtual void resetSendLevels()=0;

View File

@ -4,6 +4,7 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include "boo/BooObject.hpp"
namespace boo namespace boo
{ {
@ -54,10 +55,8 @@ static inline unsigned ChannelCount(AudioChannelSet layout)
return 0; return 0;
} }
struct IAudioVoice struct IAudioVoice : IObj
{ {
virtual ~IAudioVoice() = default;
/** Set sample rate into voice (may result in audio discontinuities) */ /** Set sample rate into voice (may result in audio discontinuities) */
virtual void resetSampleRate(double sampleRate)=0; virtual void resetSampleRate(double sampleRate)=0;

View File

@ -4,6 +4,7 @@
#include "IAudioVoice.hpp" #include "IAudioVoice.hpp"
#include "IAudioSubmix.hpp" #include "IAudioSubmix.hpp"
#include "IMIDIPort.hpp" #include "IMIDIPort.hpp"
#include "boo/BooObject.hpp"
#include <memory> #include <memory>
#include <vector> #include <vector>
@ -36,17 +37,17 @@ struct IAudioVoiceEngine
* Client must be prepared to supply audio frames via the callback when this is called; * Client must be prepared to supply audio frames via the callback when this is called;
* the backing audio-buffers are primed with initial data for low-latency playback start * the backing audio-buffers are primed with initial data for low-latency playback start
*/ */
virtual std::unique_ptr<IAudioVoice> allocateNewMonoVoice(double sampleRate, virtual ObjToken<IAudioVoice> allocateNewMonoVoice(double sampleRate,
IAudioVoiceCallback* cb, IAudioVoiceCallback* cb,
bool dynamicPitch=false)=0; bool dynamicPitch=false)=0;
/** Same as allocateNewMonoVoice, but source audio is stereo-interleaved */ /** Same as allocateNewMonoVoice, but source audio is stereo-interleaved */
virtual std::unique_ptr<IAudioVoice> allocateNewStereoVoice(double sampleRate, virtual ObjToken<IAudioVoice> allocateNewStereoVoice(double sampleRate,
IAudioVoiceCallback* cb, IAudioVoiceCallback* cb,
bool dynamicPitch=false)=0; bool dynamicPitch=false)=0;
/** Client calls this to allocate a Submix for gathering audio together for effects processing */ /** Client calls this to allocate a Submix for gathering audio together for effects processing */
virtual std::unique_ptr<IAudioSubmix> allocateNewSubmix(bool mainOut, IAudioSubmixCallback* cb, int busId)=0; virtual ObjToken<IAudioSubmix> allocateNewSubmix(bool mainOut, IAudioSubmixCallback* cb, int busId)=0;
/** Client can register for key callback events from the mixing engine this way */ /** Client can register for key callback events from the mixing engine this way */
virtual void setCallbackInterface(IAudioVoiceEngineCallback* cb)=0; virtual void setCallbackInterface(IAudioVoiceEngineCallback* cb)=0;

View File

@ -7,27 +7,27 @@
namespace boo namespace boo
{ {
/** Linked-list iterator shareable by data container types */ /** Linked-list iterator shareable by ListNode types. */
template<class T> template <class T>
class DataIterator : public std::iterator<std::bidirectional_iterator_tag, T> class ListIterator : public std::iterator<std::bidirectional_iterator_tag, T>
{ {
T* m_node; T* m_node;
public: public:
explicit DataIterator(T* node) : m_node(node) {} explicit ListIterator(T* node) : m_node(node) {}
T& operator*() const { return *m_node; } T& operator*() const { return *m_node; }
bool operator!=(const DataIterator& other) const { return m_node != other.m_node; } bool operator!=(const ListIterator& other) const { return m_node != other.m_node; }
DataIterator& operator++() { m_node = m_node->m_next; return *this; } ListIterator& operator++() { m_node = m_node->m_next; return *this; }
DataIterator& operator--() { m_node = m_node->m_prev; return *this; } ListIterator& operator--() { m_node = m_node->m_prev; return *this; }
}; };
/** Linked-list IObj node made part of objects participating in list /** Linked-list IObj node made part of objects participating in list.
* Subclasses must implement static methods _getHeadPtr() and _getHeadLock() * Subclasses must implement static methods _getHeadPtr() and _getHeadLock()
* to support the common list-management functionality. * to support the common list-management functionality.
*/ */
template <class N, class H, class P = IObj> template <class N, class H, class P = IObj>
struct ListNode : P struct ListNode : P
{ {
using iterator = DataIterator<N>; using iterator = ListIterator<N>;
iterator begin() { return iterator(static_cast<N*>(this)); } iterator begin() { return iterator(static_cast<N*>(this)); }
iterator end() { return iterator(nullptr); } iterator end() { return iterator(nullptr); }

View File

@ -25,6 +25,8 @@ AudioSubmix::~AudioSubmix()
AudioSubmix*& AudioSubmix::_getHeadPtr(BaseAudioVoiceEngine* head) { return head->m_submixHead; } AudioSubmix*& AudioSubmix::_getHeadPtr(BaseAudioVoiceEngine* head) { return head->m_submixHead; }
std::unique_lock<std::recursive_mutex> AudioSubmix::_getHeadLock(BaseAudioVoiceEngine* head) std::unique_lock<std::recursive_mutex> AudioSubmix::_getHeadLock(BaseAudioVoiceEngine* head)
{ return std::unique_lock<std::recursive_mutex>{head->m_dataMutex}; } { return std::unique_lock<std::recursive_mutex>{head->m_dataMutex}; }
std::unique_lock<std::recursive_mutex> AudioSubmix::destructorLock()
{ return std::unique_lock<std::recursive_mutex>{m_head->m_dataMutex}; }
bool AudioSubmix::_isDirectDependencyOf(AudioSubmix* send) bool AudioSubmix::_isDirectDependencyOf(AudioSubmix* send)
{ {

View File

@ -79,6 +79,7 @@ class AudioSubmix : public ListNode<AudioSubmix, BaseAudioVoiceEngine*, IAudioSu
public: public:
static AudioSubmix*& _getHeadPtr(BaseAudioVoiceEngine* head); static AudioSubmix*& _getHeadPtr(BaseAudioVoiceEngine* head);
static std::unique_lock<std::recursive_mutex> _getHeadLock(BaseAudioVoiceEngine* head); static std::unique_lock<std::recursive_mutex> _getHeadLock(BaseAudioVoiceEngine* head);
std::unique_lock<std::recursive_mutex> destructorLock();
AudioSubmix(BaseAudioVoiceEngine& root, IAudioSubmixCallback* cb, int busId, bool mainOut); AudioSubmix(BaseAudioVoiceEngine& root, IAudioSubmixCallback* cb, int busId, bool mainOut);
~AudioSubmix(); ~AudioSubmix();

View File

@ -22,6 +22,8 @@ AudioVoice::~AudioVoice()
AudioVoice*& AudioVoice::_getHeadPtr(BaseAudioVoiceEngine* head) { return head->m_voiceHead; } AudioVoice*& AudioVoice::_getHeadPtr(BaseAudioVoiceEngine* head) { return head->m_voiceHead; }
std::unique_lock<std::recursive_mutex> AudioVoice::_getHeadLock(BaseAudioVoiceEngine* head) std::unique_lock<std::recursive_mutex> AudioVoice::_getHeadLock(BaseAudioVoiceEngine* head)
{ return std::unique_lock<std::recursive_mutex>{head->m_dataMutex}; } { return std::unique_lock<std::recursive_mutex>{head->m_dataMutex}; }
std::unique_lock<std::recursive_mutex> AudioVoice::destructorLock()
{ return std::unique_lock<std::recursive_mutex>{m_head->m_dataMutex}; }
void AudioVoice::_setPitchRatio(double ratio, bool slew) void AudioVoice::_setPitchRatio(double ratio, bool slew)
{ {

View File

@ -65,6 +65,7 @@ protected:
public: public:
static AudioVoice*& _getHeadPtr(BaseAudioVoiceEngine* head); static AudioVoice*& _getHeadPtr(BaseAudioVoiceEngine* head);
static std::unique_lock<std::recursive_mutex> _getHeadLock(BaseAudioVoiceEngine* head); static std::unique_lock<std::recursive_mutex> _getHeadLock(BaseAudioVoiceEngine* head);
std::unique_lock<std::recursive_mutex> destructorLock();
~AudioVoice(); ~AudioVoice();
void resetSampleRate(double sampleRate); void resetSampleRate(double sampleRate);

View File

@ -86,26 +86,26 @@ template void BaseAudioVoiceEngine::_pumpAndMixVoices<int16_t>(size_t frames, in
template void BaseAudioVoiceEngine::_pumpAndMixVoices<int32_t>(size_t frames, int32_t* dataOut); template void BaseAudioVoiceEngine::_pumpAndMixVoices<int32_t>(size_t frames, int32_t* dataOut);
template void BaseAudioVoiceEngine::_pumpAndMixVoices<float>(size_t frames, float* dataOut); template void BaseAudioVoiceEngine::_pumpAndMixVoices<float>(size_t frames, float* dataOut);
std::unique_ptr<IAudioVoice> ObjToken<IAudioVoice>
BaseAudioVoiceEngine::allocateNewMonoVoice(double sampleRate, BaseAudioVoiceEngine::allocateNewMonoVoice(double sampleRate,
IAudioVoiceCallback* cb, IAudioVoiceCallback* cb,
bool dynamicPitch) bool dynamicPitch)
{ {
return std::make_unique<AudioVoiceMono>(*this, cb, sampleRate, dynamicPitch); return {new AudioVoiceMono(*this, cb, sampleRate, dynamicPitch)};
} }
std::unique_ptr<IAudioVoice> ObjToken<IAudioVoice>
BaseAudioVoiceEngine::allocateNewStereoVoice(double sampleRate, BaseAudioVoiceEngine::allocateNewStereoVoice(double sampleRate,
IAudioVoiceCallback* cb, IAudioVoiceCallback* cb,
bool dynamicPitch) bool dynamicPitch)
{ {
return std::make_unique<AudioVoiceStereo>(*this, cb, sampleRate, dynamicPitch); return {new AudioVoiceStereo(*this, cb, sampleRate, dynamicPitch)};
} }
std::unique_ptr<IAudioSubmix> ObjToken<IAudioSubmix>
BaseAudioVoiceEngine::allocateNewSubmix(bool mainOut, IAudioSubmixCallback* cb, int busId) BaseAudioVoiceEngine::allocateNewSubmix(bool mainOut, IAudioSubmixCallback* cb, int busId)
{ {
return std::make_unique<AudioSubmix>(*this, cb, busId, mainOut); return {new AudioSubmix(*this, cb, busId, mainOut)};
} }
void BaseAudioVoiceEngine::setCallbackInterface(IAudioVoiceEngineCallback* cb) void BaseAudioVoiceEngine::setCallbackInterface(IAudioVoiceEngineCallback* cb)

View File

@ -56,15 +56,15 @@ protected:
public: public:
BaseAudioVoiceEngine() : m_mainSubmix(std::make_unique<AudioSubmix>(*this, nullptr, -1, false)) {} BaseAudioVoiceEngine() : m_mainSubmix(std::make_unique<AudioSubmix>(*this, nullptr, -1, false)) {}
~BaseAudioVoiceEngine(); ~BaseAudioVoiceEngine();
std::unique_ptr<IAudioVoice> allocateNewMonoVoice(double sampleRate, ObjToken<IAudioVoice> allocateNewMonoVoice(double sampleRate,
IAudioVoiceCallback* cb, IAudioVoiceCallback* cb,
bool dynamicPitch=false); bool dynamicPitch=false);
std::unique_ptr<IAudioVoice> allocateNewStereoVoice(double sampleRate, ObjToken<IAudioVoice> allocateNewStereoVoice(double sampleRate,
IAudioVoiceCallback* cb, IAudioVoiceCallback* cb,
bool dynamicPitch=false); bool dynamicPitch=false);
std::unique_ptr<IAudioSubmix> allocateNewSubmix(bool mainOut, IAudioSubmixCallback* cb, int busId); ObjToken<IAudioSubmix> allocateNewSubmix(bool mainOut, IAudioSubmixCallback* cb, int busId);
void setCallbackInterface(IAudioVoiceEngineCallback* cb); void setCallbackInterface(IAudioVoiceEngineCallback* cb);

View File

@ -108,9 +108,9 @@ WindowedHilbert::~WindowedHilbert()
{ {
ippFree(m_spec); ippFree(m_spec);
ippFree(m_buffer); ippFree(m_buffer);
ippFree(m_inputBuf); ippsFree(m_inputBuf);
ippFree(m_outputBuf); ippsFree(m_outputBuf);
ippFree(m_hammingTable); ippsFree(m_hammingTable);
} }
void WindowedHilbert::_AddWindow() void WindowedHilbert::_AddWindow()

View File

@ -1,5 +1,5 @@
#ifndef APPLICATION_UNIX_CPP #ifndef APPLICATION_UNIX_CPP
#error This file may only be included from CApplicationUnix.cpp #error This file may only be included from ApplicationUnix.cpp
#endif #endif
#include "boo/IApplication.hpp" #include "boo/IApplication.hpp"