boo/lib/audiodev/AudioSubmix.hpp

105 lines
2.9 KiB
C++
Raw Normal View History

2016-05-07 04:28:32 +00:00
#ifndef BOO_AUDIOSUBMIX_HPP
#define BOO_AUDIOSUBMIX_HPP
#include "boo/audiodev/IAudioSubmix.hpp"
#include <list>
2016-05-07 22:11:45 +00:00
#include <vector>
2016-07-14 19:17:04 +00:00
#include <array>
#include <unordered_map>
#if __SSE__
#include <xmmintrin.h>
#endif
2016-05-07 04:28:32 +00:00
2016-06-08 04:37:21 +00:00
struct AudioUnitVoiceEngine;
struct VSTVoiceEngine;
struct WAVOutVoiceEngine;
2016-06-08 04:37:21 +00:00
2016-05-07 04:28:32 +00:00
namespace boo
{
class BaseAudioVoiceEngine;
class AudioVoice;
struct AudioVoiceEngineMixInfo;
/* Output gains for each mix-send/channel */
2016-05-07 04:28:32 +00:00
class AudioSubmix : public IAudioSubmix
2016-05-07 04:28:32 +00:00
{
friend class BaseAudioVoiceEngine;
friend class AudioVoiceMono;
friend class AudioVoiceStereo;
friend struct WASAPIAudioVoiceEngine;
2016-06-08 04:37:21 +00:00
friend struct ::AudioUnitVoiceEngine;
friend struct ::VSTVoiceEngine;
friend struct ::WAVOutVoiceEngine;
2016-05-07 04:28:32 +00:00
/* Mixer-engine relationships */
2016-05-07 22:11:45 +00:00
BaseAudioVoiceEngine& m_root;
2016-07-14 04:59:41 +00:00
int m_busId;
2016-05-07 04:28:32 +00:00
std::list<AudioSubmix*>::iterator m_parentIt;
bool m_mainOut;
2016-05-07 04:28:32 +00:00
bool m_bound = false;
void bindSubmix(std::list<AudioSubmix*>::iterator pIt)
{
m_bound = true;
m_parentIt = pIt;
}
/* Callback (effect source, optional) */
IAudioSubmixCallback* m_cb;
/* Slew state for output gains */
size_t m_slewFrames = 0;
size_t m_curSlewFrame = 0;
2016-05-07 04:28:32 +00:00
/* Output gains for each mix-send/channel */
std::unordered_map<IAudioSubmix*, std::array<float, 2>> m_sendGains;
2016-05-07 04:28:32 +00:00
2016-05-07 22:11:45 +00:00
/* Temporary scratch buffers for accumulating submix audio */
std::vector<int16_t> m_scratch16;
std::vector<int32_t> m_scratch32;
std::vector<float> m_scratchFlt;
/* Override scratch buffers with alternate destination */
int16_t* m_redirect16 = nullptr;
int32_t* m_redirect32 = nullptr;
float* m_redirectFlt = nullptr;
/* C3-linearization support (to mitigate a potential diamond problem on 'clever' submix routes) */
bool _isDirectDependencyOf(AudioSubmix* send);
std::list<AudioSubmix*> _linearizeC3();
static bool _mergeC3(std::list<AudioSubmix*>& output,
std::vector<std::list<AudioSubmix*>>& lists);
/* Fill scratch buffers with silence for new mix cycle */
void _zeroFill16();
void _zeroFill32();
void _zeroFillFlt();
2016-05-07 04:28:32 +00:00
/* Receive audio from a single voice / submix */
int16_t* _getMergeBuf16(size_t frames);
int32_t* _getMergeBuf32(size_t frames);
float* _getMergeBufFlt(size_t frames);
/* Mix scratch buffers into sends */
size_t _pumpAndMix16(size_t frames);
size_t _pumpAndMix32(size_t frames);
size_t _pumpAndMixFlt(size_t frames);
2016-05-07 04:28:32 +00:00
void _resetOutputSampleRate();
2016-05-07 04:28:32 +00:00
public:
~AudioSubmix();
2016-07-14 04:59:41 +00:00
AudioSubmix(BaseAudioVoiceEngine& root, IAudioSubmixCallback* cb, int busId, bool mainOut);
2016-05-07 04:28:32 +00:00
void resetSendLevels();
void setSendLevel(IAudioSubmix* submix, float level, bool slew);
2016-05-07 04:28:32 +00:00
void unbindSubmix();
const AudioVoiceEngineMixInfo& mixInfo() const;
double getSampleRate() const;
SubmixFormat getSampleFormat() const;
2016-05-07 04:28:32 +00:00
};
}
#endif // BOO_AUDIOSUBMIX_HPP