mirror of https://github.com/AxioDL/amuse.git
Make audio overload types float-only, initial boo2 switchover
This commit is contained in:
parent
5112228abd
commit
6da262355a
|
@ -77,12 +77,8 @@ add_library(amuse
|
|||
include/amuse/VolumeTable.hpp
|
||||
)
|
||||
|
||||
target_atdna(amuse atdna_AudioGroupPool.cpp include/amuse/AudioGroupPool.hpp)
|
||||
target_atdna(amuse atdna_AudioGroupProject.cpp include/amuse/AudioGroupProject.hpp)
|
||||
target_atdna(amuse atdna_AudioGroupSampleDirectory.cpp include/amuse/AudioGroupSampleDirectory.hpp)
|
||||
|
||||
target_include_directories(amuse PUBLIC include)
|
||||
target_link_libraries(amuse
|
||||
target_link_libraries(amuse PUBLIC
|
||||
athena-core
|
||||
lzokay
|
||||
${ZLIB_LIBRARIES}
|
||||
|
@ -92,11 +88,15 @@ if(NX)
|
|||
target_sources(amuse PRIVATE include/switch_math.hpp)
|
||||
endif()
|
||||
|
||||
if(TARGET boo)
|
||||
if(TARGET boo2)
|
||||
target_sources(amuse PRIVATE lib/BooBackend.cpp include/amuse/BooBackend.hpp)
|
||||
target_link_libraries(amuse boo)
|
||||
target_link_libraries(amuse PUBLIC boo2)
|
||||
endif()
|
||||
|
||||
target_atdna(amuse atdna_AudioGroupPool.cpp include/amuse/AudioGroupPool.hpp)
|
||||
target_atdna(amuse atdna_AudioGroupProject.cpp include/amuse/AudioGroupProject.hpp)
|
||||
target_atdna(amuse atdna_AudioGroupSampleDirectory.cpp include/amuse/AudioGroupSampleDirectory.hpp)
|
||||
|
||||
if (MSVC)
|
||||
target_compile_options(amuse PRIVATE
|
||||
# Enforce various standards compliant behavior.
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace amuse {
|
|||
class Engine;
|
||||
}
|
||||
|
||||
namespace boo {
|
||||
namespace boo2 {
|
||||
struct IAudioVoiceEngine;
|
||||
}
|
||||
|
||||
|
|
|
@ -854,7 +854,7 @@ void EventCallback::specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods,
|
|||
m_app.m_engine->setVolume(m_app.m_volume);
|
||||
m_app.m_updateDisp = true;
|
||||
break;
|
||||
case boo::ESpecialKey::Esc:
|
||||
case boo2::Keycode::ESC:
|
||||
m_app.m_breakout = true;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -13,10 +13,10 @@
|
|||
#include "amuse/IBackendSubmix.hpp"
|
||||
#include "amuse/IBackendVoiceAllocator.hpp"
|
||||
|
||||
#include <boo/audiodev/IAudioSubmix.hpp>
|
||||
#include <boo/audiodev/IAudioVoiceEngine.hpp>
|
||||
#include <boo/audiodev/IMIDIReader.hpp>
|
||||
#include <boo/audiodev/MIDIDecoder.hpp>
|
||||
#include "boo2/audiodev/IAudioSubmix.hpp"
|
||||
#include "boo2/audiodev/IAudioVoiceEngine.hpp"
|
||||
#include "boo2/audiodev/IMIDIReader.hpp"
|
||||
#include "boo2/audiodev/MIDIDecoder.hpp"
|
||||
|
||||
namespace amuse {
|
||||
|
||||
|
@ -24,19 +24,19 @@ namespace amuse {
|
|||
class BooBackendVoice : public IBackendVoice {
|
||||
friend class BooBackendVoiceAllocator;
|
||||
Voice& m_clientVox;
|
||||
struct VoiceCallback : boo::IAudioVoiceCallback {
|
||||
struct VoiceCallback : boo2::IAudioVoiceCallback {
|
||||
BooBackendVoice& m_parent;
|
||||
void preSupplyAudio(boo::IAudioVoice& voice, double dt) override;
|
||||
size_t supplyAudio(boo::IAudioVoice& voice, size_t frames, int16_t* data) override;
|
||||
void preSupplyAudio(boo2::IAudioVoice& voice, double dt) override;
|
||||
size_t supplyAudio(boo2::IAudioVoice& voice, size_t frames, int16_t* data) override;
|
||||
void routeAudio(size_t frames, size_t channels, double dt, int busId, int16_t* in, int16_t* out) override;
|
||||
void routeAudio(size_t frames, size_t channels, double dt, int busId, int32_t* in, int32_t* out) override;
|
||||
void routeAudio(size_t frames, size_t channels, double dt, int busId, float* in, float* out) override;
|
||||
VoiceCallback(BooBackendVoice& parent) : m_parent(parent) {}
|
||||
} m_cb;
|
||||
boo::ObjToken<boo::IAudioVoice> m_booVoice;
|
||||
boo2::ObjToken<boo2::IAudioVoice> m_booVoice;
|
||||
|
||||
public:
|
||||
BooBackendVoice(boo::IAudioVoiceEngine& engine, Voice& clientVox, double sampleRate, bool dynamicPitch);
|
||||
BooBackendVoice(boo2::IAudioVoiceEngine& engine, Voice& clientVox, double sampleRate, bool dynamicPitch);
|
||||
void resetSampleRate(double sampleRate) override;
|
||||
|
||||
void resetChannelLevels() override;
|
||||
|
@ -51,35 +51,30 @@ class BooBackendSubmix : public IBackendSubmix {
|
|||
friend class BooBackendVoiceAllocator;
|
||||
friend class BooBackendVoice;
|
||||
Submix& m_clientSmx;
|
||||
struct SubmixCallback : boo::IAudioSubmixCallback {
|
||||
struct SubmixCallback : boo2::IAudioSubmixCallback {
|
||||
BooBackendSubmix& m_parent;
|
||||
bool canApplyEffect() const override;
|
||||
void applyEffect(int16_t* audio, size_t frameCount, const boo::ChannelMap& chanMap,
|
||||
double sampleRate) const override;
|
||||
void applyEffect(int32_t* audio, size_t frameCount, const boo::ChannelMap& chanMap,
|
||||
double sampleRate) const override;
|
||||
void applyEffect(float* audio, size_t frameCount, const boo::ChannelMap& chanMap, double sampleRate) const override;
|
||||
void applyEffect(float* audio, size_t frameCount, const boo2::ChannelMap& chanMap, double sampleRate) const override;
|
||||
void resetOutputSampleRate(double sampleRate) override;
|
||||
SubmixCallback(BooBackendSubmix& parent) : m_parent(parent) {}
|
||||
} m_cb;
|
||||
boo::ObjToken<boo::IAudioSubmix> m_booSubmix;
|
||||
boo2::ObjToken<boo2::IAudioSubmix> m_booSubmix;
|
||||
|
||||
public:
|
||||
BooBackendSubmix(boo::IAudioVoiceEngine& engine, Submix& clientSmx, bool mainOut, int busId);
|
||||
BooBackendSubmix(boo2::IAudioVoiceEngine& engine, Submix& clientSmx, bool mainOut, int busId);
|
||||
void setSendLevel(IBackendSubmix* submix, float level, bool slew) override;
|
||||
double getSampleRate() const override;
|
||||
SubmixFormat getSampleFormat() const override;
|
||||
};
|
||||
|
||||
/** Backend MIDI event reader for controlling sequencer with external hardware / software */
|
||||
class BooBackendMIDIReader : public IMIDIReader, public boo::IMIDIReader {
|
||||
class BooBackendMIDIReader : public IMIDIReader, public boo2::IMIDIReader {
|
||||
friend class BooBackendVoiceAllocator;
|
||||
|
||||
protected:
|
||||
Engine& m_engine;
|
||||
std::unordered_map<std::string, std::unique_ptr<boo::IMIDIIn>> m_midiIns;
|
||||
std::unique_ptr<boo::IMIDIIn> m_virtualIn;
|
||||
boo::MIDIDecoder m_decoder;
|
||||
std::unordered_map<std::string, std::unique_ptr<boo2::IMIDIIn>> m_midiIns;
|
||||
std::unique_ptr<boo2::IMIDIIn> m_virtualIn;
|
||||
boo2::MIDIDecoder m_decoder;
|
||||
|
||||
bool m_useLock;
|
||||
std::list<std::pair<double, std::vector<uint8_t>>> m_queue;
|
||||
|
@ -127,15 +122,15 @@ public:
|
|||
};
|
||||
|
||||
/** Backend voice allocator implementation for boo mixer */
|
||||
class BooBackendVoiceAllocator : public IBackendVoiceAllocator, public boo::IAudioVoiceEngineCallback {
|
||||
class BooBackendVoiceAllocator : public IBackendVoiceAllocator, public boo2::IAudioVoiceEngineCallback {
|
||||
friend class BooBackendMIDIReader;
|
||||
|
||||
protected:
|
||||
boo::IAudioVoiceEngine& m_booEngine;
|
||||
boo2::IAudioVoiceEngine& m_booEngine;
|
||||
Engine* m_cbInterface = nullptr;
|
||||
|
||||
public:
|
||||
BooBackendVoiceAllocator(boo::IAudioVoiceEngine& booEngine);
|
||||
BooBackendVoiceAllocator(boo2::IAudioVoiceEngine& booEngine);
|
||||
std::unique_ptr<IBackendVoice> allocateVoice(Voice& clientVox, double sampleRate, bool dynamicPitch) override;
|
||||
std::unique_ptr<IBackendSubmix> allocateSubmix(Submix& clientSmx, bool mainOut, int busId) override;
|
||||
std::vector<std::pair<std::string, std::string>> enumerateMIDIDevices() override;
|
||||
|
@ -143,7 +138,7 @@ public:
|
|||
void setCallbackInterface(Engine* engine) override;
|
||||
AudioChannelSet getAvailableSet() override;
|
||||
void setVolume(float vol) override;
|
||||
void on5MsInterval(boo::IAudioVoiceEngine& engine, double dt) override;
|
||||
void onPumpCycleComplete(boo::IAudioVoiceEngine& engine) override;
|
||||
void on5MsInterval(boo2::IAudioVoiceEngine& engine, double dt) override;
|
||||
void onPumpCycleComplete(boo2::IAudioVoiceEngine& engine) override;
|
||||
};
|
||||
} // namespace amuse
|
||||
|
|
|
@ -368,23 +368,6 @@ inline int CompareCaseInsensitive(const SystemChar* a, const SystemChar* b) {
|
|||
#endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr T ClampFull(float in) noexcept {
|
||||
if (std::is_floating_point<T>()) {
|
||||
return in;
|
||||
} else {
|
||||
constexpr T MAX = std::numeric_limits<T>::max();
|
||||
constexpr T MIN = std::numeric_limits<T>::min();
|
||||
|
||||
if (in < MIN)
|
||||
return MIN;
|
||||
else if (in > MAX)
|
||||
return MAX;
|
||||
else
|
||||
return in;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef M_PIF
|
||||
#define M_PIF 3.14159265358979323846f /* pi */
|
||||
#endif
|
||||
|
|
|
@ -5,16 +5,11 @@ struct ChannelMap;
|
|||
|
||||
enum class EffectType { Invalid, ReverbStd, ReverbHi, Delay, Chorus, EffectTypeMAX };
|
||||
|
||||
class EffectBaseTypeless {
|
||||
class EffectBase {
|
||||
public:
|
||||
virtual ~EffectBaseTypeless() = default;
|
||||
virtual ~EffectBase() = default;
|
||||
virtual void resetOutputSampleRate(double sampleRate) = 0;
|
||||
virtual EffectType Isa() const = 0;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class EffectBase : public EffectBaseTypeless {
|
||||
public:
|
||||
virtual void applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap) = 0;
|
||||
virtual void applyEffect(float* audio, size_t frameCount, const ChannelMap& chanMap) = 0;
|
||||
};
|
||||
} // namespace amuse
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#include "amuse/IBackendVoice.hpp"
|
||||
|
||||
namespace amuse {
|
||||
template <typename T>
|
||||
class EffectChorusImp;
|
||||
|
||||
#define AMUSE_CHORUS_NUM_BLOCKS 3
|
||||
|
@ -31,13 +30,11 @@ class EffectChorus {
|
|||
uint32_t x98_period; /**< [500, 10000] time (in ms) of one delay-shift cycle */
|
||||
bool m_dirty = true; /**< needs update of internal parameter data */
|
||||
|
||||
template <typename T>
|
||||
friend class EffectChorusImp;
|
||||
EffectChorus(uint32_t baseDelay, uint32_t variation, uint32_t period);
|
||||
|
||||
public:
|
||||
template <typename T>
|
||||
using ImpType = EffectChorusImp<T>;
|
||||
using ImpType = EffectChorusImp;
|
||||
|
||||
void setBaseDelay(uint32_t baseDelay) {
|
||||
baseDelay = std::clamp(baseDelay, 5u, 15u);
|
||||
|
@ -68,13 +65,12 @@ public:
|
|||
};
|
||||
|
||||
/** Type-specific implementation of chorus effect */
|
||||
template <typename T>
|
||||
class EffectChorusImp : public EffectBase<T>, public EffectChorus {
|
||||
class EffectChorusImp : public EffectBase, public EffectChorus {
|
||||
/** Evenly-allocated pointer-table for each channel's delay */
|
||||
std::array<std::array<T*, AMUSE_CHORUS_NUM_BLOCKS>, NumChannels> x0_lastChans{};
|
||||
std::array<std::array<float*, AMUSE_CHORUS_NUM_BLOCKS>, NumChannels> x0_lastChans{};
|
||||
|
||||
uint8_t x24_currentLast = 1; /**< Last 5ms block-idx to be processed */
|
||||
std::array<std::array<T, 4>, NumChannels> x28_oldChans{}; /**< Unprocessed history of previous 4 samples */
|
||||
std::array<std::array<float, 4>, NumChannels> x28_oldChans{}; /**< Unprocessed history of previous 4 samples */
|
||||
|
||||
uint32_t x58_currentPosLo = 0; /**< 16.7 fixed-point low-part of sample index */
|
||||
uint32_t x5c_currentPosHi = 0; /**< 16.7 fixed-point high-part of sample index */
|
||||
|
@ -84,9 +80,9 @@ class EffectChorusImp : public EffectBase<T>, public EffectChorus {
|
|||
uint32_t x68_pitchOffsetPeriod; /**< intermediate block window quantity for calculating SRC state */
|
||||
|
||||
struct SrcInfo {
|
||||
T* x6c_dest; /**< selected channel's live buffer */
|
||||
T* x70_smpBase; /**< selected channel's delay buffer */
|
||||
T* x74_old; /**< selected channel's 4-sample history buffer */
|
||||
float* x6c_dest; /**< selected channel's live buffer */
|
||||
float* x70_smpBase; /**< selected channel's delay buffer */
|
||||
float* x74_old; /**< selected channel's 4-sample history buffer */
|
||||
uint32_t x78_posLo; /**< 16.7 fixed-point low-part of sample index */
|
||||
uint32_t x7c_posHi; /**< 16.7 fixed-point high-part of sample index */
|
||||
uint32_t x80_pitchLo; /**< 16.7 fixed-point low-part of sample-rate conversion differential */
|
||||
|
@ -111,7 +107,7 @@ public:
|
|||
EffectChorusImp(const EffectChorusInfo& info, double sampleRate)
|
||||
: EffectChorusImp(info.baseDelay, info.variation, info.period, sampleRate) {}
|
||||
|
||||
void applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap) override;
|
||||
void applyEffect(float* audio, size_t frameCount, const ChannelMap& chanMap) override;
|
||||
void resetOutputSampleRate(double sampleRate) override { _setup(sampleRate); }
|
||||
|
||||
EffectType Isa() const override { return EffectType::Chorus; }
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include "amuse/IBackendVoice.hpp"
|
||||
|
||||
namespace amuse {
|
||||
template <typename T>
|
||||
class EffectDelayImp;
|
||||
|
||||
/** Parameters needed to create EffectDelay */
|
||||
|
@ -50,8 +49,7 @@ protected:
|
|||
bool m_dirty = true; /**< needs update of internal parameter data */
|
||||
|
||||
public:
|
||||
template <typename T>
|
||||
using ImpType = EffectDelayImp<T>;
|
||||
using ImpType = EffectDelayImp;
|
||||
|
||||
void setDelay(uint32_t delay) {
|
||||
delay = std::clamp(delay, 10u, 5000u);
|
||||
|
@ -102,14 +100,13 @@ public:
|
|||
};
|
||||
|
||||
/** Type-specific implementation of delay effect */
|
||||
template <typename T>
|
||||
class EffectDelayImp : public EffectBase<T>, public EffectDelay {
|
||||
class EffectDelayImp : public EffectBase, public EffectDelay {
|
||||
std::array<uint32_t, NumChannels> x0_currentSize; /**< per-channel delay-line buffer sizes */
|
||||
std::array<uint32_t, NumChannels> xc_currentPos; /**< per-channel block-index */
|
||||
std::array<uint32_t, NumChannels> x18_currentFeedback; /**< [0, 128] feedback attenuator */
|
||||
std::array<uint32_t, NumChannels> x24_currentOutput; /**< [0, 128] total attenuator */
|
||||
|
||||
std::array<std::unique_ptr<T[]>, NumChannels> x30_chanLines; /**< delay-line buffers for each channel */
|
||||
std::array<std::unique_ptr<float[]>, NumChannels> x30_chanLines; /**< delay-line buffers for each channel */
|
||||
|
||||
uint32_t m_sampsPerMs; /**< canonical count of samples per ms for the current backend */
|
||||
uint32_t m_blockSamples; /**< count of samples in a 5ms block */
|
||||
|
@ -120,7 +117,7 @@ public:
|
|||
EffectDelayImp(uint32_t initDelay, uint32_t initFeedback, uint32_t initOutput, double sampleRate);
|
||||
EffectDelayImp(const EffectDelayInfo& info, double sampleRate);
|
||||
|
||||
void applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap) override;
|
||||
void applyEffect(float* audio, size_t frameCount, const ChannelMap& chanMap) override;
|
||||
void resetOutputSampleRate(double sampleRate) override { _setup(sampleRate); }
|
||||
|
||||
EffectType Isa() const override { return EffectType::Delay; }
|
||||
|
|
|
@ -49,10 +49,7 @@ struct ReverbDelayLine {
|
|||
void setdelay(int32_t delay);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class EffectReverbStdImp;
|
||||
|
||||
template <typename T>
|
||||
class EffectReverbHiImp;
|
||||
|
||||
/** Reverb effect with configurable reflection filtering */
|
||||
|
@ -66,15 +63,12 @@ protected:
|
|||
float x150_x1d8_preDelay; /**< [0.0, 0.1] time in seconds before initial reflection heard */
|
||||
bool m_dirty = true; /**< needs update of internal parameter data */
|
||||
|
||||
template <typename T>
|
||||
friend class EffectReverbStdImp;
|
||||
template <typename T>
|
||||
friend class EffectReverbHiImp;
|
||||
EffectReverbStd(float coloration, float mix, float time, float damping, float preDelay);
|
||||
|
||||
public:
|
||||
template <typename T>
|
||||
using ImpType = EffectReverbStdImp<T>;
|
||||
using ImpType = EffectReverbStdImp;
|
||||
|
||||
void setColoration(float coloration) {
|
||||
x140_x1c8_coloration = std::clamp(coloration, 0.f, 1.f);
|
||||
|
@ -119,13 +113,11 @@ public:
|
|||
class EffectReverbHi : public EffectReverbStd {
|
||||
float x1dc_crosstalk; /**< [0.0, 1.0] factor defining how much reflections are allowed to bleed to other channels */
|
||||
|
||||
template <typename T>
|
||||
friend class EffectReverbHiImp;
|
||||
EffectReverbHi(float coloration, float mix, float time, float damping, float preDelay, float crosstalk);
|
||||
|
||||
public:
|
||||
template <typename T>
|
||||
using ImpType = EffectReverbHiImp<T>;
|
||||
using ImpType = EffectReverbHiImp;
|
||||
|
||||
void setCrosstalk(float crosstalk) {
|
||||
x1dc_crosstalk = std::clamp(crosstalk, 0.f, 1.f);
|
||||
|
@ -144,8 +136,7 @@ public:
|
|||
};
|
||||
|
||||
/** Standard-quality 2-stage reverb */
|
||||
template <typename T>
|
||||
class EffectReverbStdImp : public EffectBase<T>, public EffectReverbStd {
|
||||
class EffectReverbStdImp : public EffectBase, public EffectReverbStd {
|
||||
using CombCoeffArray = std::array<std::array<float, 2>, NumChannels>;
|
||||
using ReverbDelayArray = std::array<std::array<ReverbDelayLine, 2>, NumChannels>;
|
||||
using PreDelayArray = std::array<std::unique_ptr<float[]>, NumChannels>;
|
||||
|
@ -170,15 +161,14 @@ public:
|
|||
EffectReverbStdImp(const EffectReverbStdInfo& info, double sampleRate)
|
||||
: EffectReverbStdImp(info.coloration, info.mix, info.time, info.damping, info.preDelay, sampleRate) {}
|
||||
|
||||
void applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap) override;
|
||||
void applyEffect(float* audio, size_t frameCount, const ChannelMap& chanMap) override;
|
||||
void resetOutputSampleRate(double sampleRate) override { _setup(sampleRate); }
|
||||
|
||||
EffectType Isa() const override { return EffectType::ReverbStd; }
|
||||
};
|
||||
|
||||
/** High-quality 3-stage reverb with per-channel low-pass and crosstalk */
|
||||
template <typename T>
|
||||
class EffectReverbHiImp : public EffectBase<T>, public EffectReverbHi {
|
||||
class EffectReverbHiImp : public EffectBase, public EffectReverbHi {
|
||||
using AllPassDelayLines = std::array<std::array<ReverbDelayLine, 2>, NumChannels>;
|
||||
using CombCoefficients = std::array<std::array<float, 3>, NumChannels>;
|
||||
using CombDelayLines = std::array<std::array<ReverbDelayLine, 3>, NumChannels>;
|
||||
|
@ -201,8 +191,8 @@ class EffectReverbHiImp : public EffectBase<T>, public EffectReverbHi {
|
|||
double m_sampleRate; /**< copy of sample rate */
|
||||
void _setup(double sampleRate);
|
||||
void _update();
|
||||
void _handleReverb(T* audio, int chanIdx, int chanCount, int sampleCount);
|
||||
void _doCrosstalk(T* audio, float wet, float dry, int chanCount, int sampleCount);
|
||||
void _handleReverb(float* audio, int chanIdx, int chanCount, int sampleCount);
|
||||
void _doCrosstalk(float* audio, float wet, float dry, int chanCount, int sampleCount);
|
||||
|
||||
public:
|
||||
EffectReverbHiImp(float coloration, float mix, float time, float damping, float preDelay, float crosstalk,
|
||||
|
@ -210,7 +200,7 @@ public:
|
|||
EffectReverbHiImp(const EffectReverbHiInfo& info, double sampleRate)
|
||||
: EffectReverbHiImp(info.coloration, info.mix, info.time, info.damping, info.preDelay, info.crosstalk, sampleRate) {}
|
||||
|
||||
void applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap) override;
|
||||
void applyEffect(float* audio, size_t frameCount, const ChannelMap& chanMap) override;
|
||||
void resetOutputSampleRate(double sampleRate) override { _setup(sampleRate); }
|
||||
|
||||
EffectType Isa() const override { return EffectType::ReverbHi; }
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
namespace amuse {
|
||||
|
||||
enum class SubmixFormat { Int16, Int32, Float };
|
||||
|
||||
/** Client-implemented submix instance */
|
||||
class IBackendSubmix {
|
||||
public:
|
||||
|
@ -14,8 +12,5 @@ public:
|
|||
|
||||
/** Amuse gets fixed sample rate of submix this way */
|
||||
virtual double getSampleRate() const = 0;
|
||||
|
||||
/** Amuse gets fixed sample format of submix this way */
|
||||
virtual SubmixFormat getSampleFormat() const = 0;
|
||||
};
|
||||
} // namespace amuse
|
||||
|
|
|
@ -23,36 +23,23 @@ class Submix {
|
|||
friend class Sequencer;
|
||||
Engine& m_root;
|
||||
std::unique_ptr<IBackendSubmix> m_backendSubmix; /**< Handle to client-implemented backend submix */
|
||||
std::vector<std::unique_ptr<EffectBaseTypeless>> m_effectStack; /**< Ordered list of effects to apply to submix */
|
||||
std::vector<std::unique_ptr<EffectBase>> m_effectStack; /**< Ordered list of effects to apply to submix */
|
||||
|
||||
public:
|
||||
Submix(Engine& engine);
|
||||
|
||||
/** Construct new effect */
|
||||
template <class T, class... Args>
|
||||
std::unique_ptr<EffectBaseTypeless> _makeEffect(Args... args) {
|
||||
switch (m_backendSubmix->getSampleFormat()) {
|
||||
case SubmixFormat::Int16: {
|
||||
using ImpType = typename T::template ImpType<int16_t>;
|
||||
return std::make_unique<ImpType>(args..., m_backendSubmix->getSampleRate());
|
||||
}
|
||||
case SubmixFormat::Int32:
|
||||
default: {
|
||||
using ImpType = typename T::template ImpType<int32_t>;
|
||||
return std::make_unique<ImpType>(args..., m_backendSubmix->getSampleRate());
|
||||
}
|
||||
case SubmixFormat::Float: {
|
||||
using ImpType = typename T::template ImpType<float>;
|
||||
return std::make_unique<ImpType>(args..., m_backendSubmix->getSampleRate());
|
||||
}
|
||||
}
|
||||
std::unique_ptr<EffectBase> _makeEffect(Args... args) {
|
||||
using ImpType = typename T::ImpType;
|
||||
return std::make_unique<ImpType>(args..., m_backendSubmix->getSampleRate());
|
||||
}
|
||||
|
||||
/** Add new effect to effect stack and assume ownership */
|
||||
template <class T, class... Args>
|
||||
T& makeEffect(Args... args) {
|
||||
m_effectStack.push_back(_makeEffect<T>(args...));
|
||||
return static_cast<typename T::template ImpType<float>&>(*m_effectStack.back());
|
||||
return static_cast<typename T::ImpType&>(*m_effectStack.back());
|
||||
}
|
||||
|
||||
/** Add new chorus effect to effect stack and assume ownership */
|
||||
|
@ -85,12 +72,6 @@ public:
|
|||
/** Returns true when an effect callback is bound */
|
||||
bool canApplyEffect() const { return m_effectStack.size() != 0; }
|
||||
|
||||
/** in/out transformation entry for audio effect */
|
||||
void applyEffect(int16_t* audio, size_t frameCount, const ChannelMap& chanMap) const;
|
||||
|
||||
/** in/out transformation entry for audio effect */
|
||||
void applyEffect(int32_t* audio, size_t frameCount, const ChannelMap& chanMap) const;
|
||||
|
||||
/** in/out transformation entry for audio effect */
|
||||
void applyEffect(float* audio, size_t frameCount, const ChannelMap& chanMap) const;
|
||||
|
||||
|
@ -99,6 +80,6 @@ public:
|
|||
|
||||
Engine& getEngine() { return m_root; }
|
||||
|
||||
std::vector<std::unique_ptr<EffectBaseTypeless>>& getEffectStack() { return m_effectStack; }
|
||||
std::vector<std::unique_ptr<EffectBase>>& getEffectStack() { return m_effectStack; }
|
||||
};
|
||||
} // namespace amuse
|
||||
|
|
|
@ -6,11 +6,11 @@
|
|||
|
||||
namespace amuse {
|
||||
|
||||
void BooBackendVoice::VoiceCallback::preSupplyAudio(boo::IAudioVoice&, double dt) {
|
||||
void BooBackendVoice::VoiceCallback::preSupplyAudio(boo2::IAudioVoice&, double dt) {
|
||||
m_parent.m_clientVox.preSupplyAudio(dt);
|
||||
}
|
||||
|
||||
size_t BooBackendVoice::VoiceCallback::supplyAudio(boo::IAudioVoice&, size_t frames, int16_t* data) {
|
||||
size_t BooBackendVoice::VoiceCallback::supplyAudio(boo2::IAudioVoice&, size_t frames, int16_t* data) {
|
||||
return m_parent.m_clientVox.supplyAudio(frames, data);
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ void BooBackendVoice::VoiceCallback::routeAudio(size_t frames, size_t channels,
|
|||
m_parent.m_clientVox.routeAudio(frames, dt, busId, in, out);
|
||||
}
|
||||
|
||||
BooBackendVoice::BooBackendVoice(boo::IAudioVoiceEngine& engine, Voice& clientVox, double sampleRate, bool dynamicPitch)
|
||||
BooBackendVoice::BooBackendVoice(boo2::IAudioVoiceEngine& engine, Voice& clientVox, double sampleRate, bool dynamicPitch)
|
||||
: m_clientVox(clientVox), m_cb(*this), m_booVoice(engine.allocateNewMonoVoice(sampleRate, &m_cb, dynamicPitch)) {}
|
||||
|
||||
void BooBackendVoice::resetSampleRate(double sampleRate) { m_booVoice->resetSampleRate(sampleRate); }
|
||||
|
@ -49,17 +49,7 @@ void BooBackendVoice::stop() { m_booVoice->stop(); }
|
|||
|
||||
bool BooBackendSubmix::SubmixCallback::canApplyEffect() const { return m_parent.m_clientSmx.canApplyEffect(); }
|
||||
|
||||
void BooBackendSubmix::SubmixCallback::applyEffect(int16_t* audio, size_t frameCount, const boo::ChannelMap& chanMap,
|
||||
double) const {
|
||||
return m_parent.m_clientSmx.applyEffect(audio, frameCount, reinterpret_cast<const ChannelMap&>(chanMap));
|
||||
}
|
||||
|
||||
void BooBackendSubmix::SubmixCallback::applyEffect(int32_t* audio, size_t frameCount, const boo::ChannelMap& chanMap,
|
||||
double) const {
|
||||
return m_parent.m_clientSmx.applyEffect(audio, frameCount, reinterpret_cast<const ChannelMap&>(chanMap));
|
||||
}
|
||||
|
||||
void BooBackendSubmix::SubmixCallback::applyEffect(float* audio, size_t frameCount, const boo::ChannelMap& chanMap,
|
||||
void BooBackendSubmix::SubmixCallback::applyEffect(float* audio, size_t frameCount, const boo2::ChannelMap& chanMap,
|
||||
double) const {
|
||||
return m_parent.m_clientSmx.applyEffect(audio, frameCount, reinterpret_cast<const ChannelMap&>(chanMap));
|
||||
}
|
||||
|
@ -68,7 +58,7 @@ void BooBackendSubmix::SubmixCallback::resetOutputSampleRate(double sampleRate)
|
|||
m_parent.m_clientSmx.resetOutputSampleRate(sampleRate);
|
||||
}
|
||||
|
||||
BooBackendSubmix::BooBackendSubmix(boo::IAudioVoiceEngine& engine, Submix& clientSmx, bool mainOut, int busId)
|
||||
BooBackendSubmix::BooBackendSubmix(boo2::IAudioVoiceEngine& engine, Submix& clientSmx, bool mainOut, int busId)
|
||||
: m_clientSmx(clientSmx), m_cb(*this), m_booSubmix(engine.allocateNewSubmix(mainOut, &m_cb, busId)) {}
|
||||
|
||||
void BooBackendSubmix::setSendLevel(IBackendSubmix* submix, float level, bool slew) {
|
||||
|
@ -78,8 +68,6 @@ void BooBackendSubmix::setSendLevel(IBackendSubmix* submix, float level, bool sl
|
|||
|
||||
double BooBackendSubmix::getSampleRate() const { return m_booSubmix->getSampleRate(); }
|
||||
|
||||
SubmixFormat BooBackendSubmix::getSampleFormat() const { return SubmixFormat(m_booSubmix->getSampleFormat()); }
|
||||
|
||||
BooBackendMIDIReader::~BooBackendMIDIReader() {}
|
||||
|
||||
BooBackendMIDIReader::BooBackendMIDIReader(Engine& engine, bool useLock)
|
||||
|
@ -247,7 +235,7 @@ void BooBackendMIDIReader::stopSeq() {}
|
|||
|
||||
void BooBackendMIDIReader::reset() {}
|
||||
|
||||
BooBackendVoiceAllocator::BooBackendVoiceAllocator(boo::IAudioVoiceEngine& booEngine) : m_booEngine(booEngine) {
|
||||
BooBackendVoiceAllocator::BooBackendVoiceAllocator(boo2::IAudioVoiceEngine& booEngine) : m_booEngine(booEngine) {
|
||||
booEngine.setCallbackInterface(this);
|
||||
}
|
||||
|
||||
|
@ -274,12 +262,12 @@ AudioChannelSet BooBackendVoiceAllocator::getAvailableSet() { return AudioChanne
|
|||
|
||||
void BooBackendVoiceAllocator::setVolume(float vol) { m_booEngine.setVolume(vol); }
|
||||
|
||||
void BooBackendVoiceAllocator::on5MsInterval(boo::IAudioVoiceEngine& engine, double dt) {
|
||||
void BooBackendVoiceAllocator::on5MsInterval(boo2::IAudioVoiceEngine& engine, double dt) {
|
||||
if (m_cbInterface)
|
||||
m_cbInterface->_on5MsInterval(*this, dt);
|
||||
}
|
||||
|
||||
void BooBackendVoiceAllocator::onPumpCycleComplete(boo::IAudioVoiceEngine& engine) {
|
||||
void BooBackendVoiceAllocator::onPumpCycleComplete(boo2::IAudioVoiceEngine& engine) {
|
||||
if (m_cbInterface)
|
||||
m_cbInterface->_onPumpCycleComplete(*this);
|
||||
}
|
||||
|
|
|
@ -145,21 +145,19 @@ EffectChorus::EffectChorus(uint32_t baseDelay, uint32_t variation, uint32_t peri
|
|||
, x94_variation(std::clamp(variation, 0u, 5u))
|
||||
, x98_period(std::clamp(period, 500u, 10000u)) {}
|
||||
|
||||
template <typename T>
|
||||
EffectChorusImp<T>::EffectChorusImp(uint32_t baseDelay, uint32_t variation, uint32_t period, double sampleRate)
|
||||
EffectChorusImp::EffectChorusImp(uint32_t baseDelay, uint32_t variation, uint32_t period, double sampleRate)
|
||||
: EffectChorus(baseDelay, variation, period) {
|
||||
_setup(sampleRate);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void EffectChorusImp<T>::_setup(double sampleRate) {
|
||||
void EffectChorusImp::_setup(double sampleRate) {
|
||||
m_sampsPerMs = std::ceil(sampleRate / 1000.0);
|
||||
m_blockSamples = m_sampsPerMs * 5;
|
||||
|
||||
delete[] x0_lastChans[0][0];
|
||||
|
||||
const size_t chanPitch = m_blockSamples * AMUSE_CHORUS_NUM_BLOCKS;
|
||||
T* buf = new T[chanPitch * NumChannels]();
|
||||
auto* buf = new float[chanPitch * NumChannels]();
|
||||
|
||||
for (size_t c = 0; c < NumChannels; ++c) {
|
||||
for (size_t i = 0; i < AMUSE_CHORUS_NUM_BLOCKS; ++i) {
|
||||
|
@ -172,8 +170,7 @@ void EffectChorusImp<T>::_setup(double sampleRate) {
|
|||
m_dirty = true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void EffectChorusImp<T>::_update() {
|
||||
void EffectChorusImp::_update() {
|
||||
size_t chanPitch = m_blockSamples * AMUSE_CHORUS_NUM_BLOCKS;
|
||||
size_t fifteenSamps = 15 * m_sampsPerMs;
|
||||
|
||||
|
@ -189,19 +186,17 @@ void EffectChorusImp<T>::_update() {
|
|||
m_dirty = false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
EffectChorusImp<T>::~EffectChorusImp() {
|
||||
EffectChorusImp::~EffectChorusImp() {
|
||||
delete[] x0_lastChans[0][0];
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void EffectChorusImp<T>::SrcInfo::doSrc1(size_t blockSamples, size_t chanCount) {
|
||||
void EffectChorusImp::SrcInfo::doSrc1(size_t blockSamples, size_t chanCount) {
|
||||
float old1 = x74_old[0];
|
||||
float old2 = x74_old[1];
|
||||
float old3 = x74_old[2];
|
||||
float cur = x70_smpBase[x7c_posHi];
|
||||
|
||||
T* dest = x6c_dest;
|
||||
auto* dest = x6c_dest;
|
||||
for (size_t i = 0; i < blockSamples; ++i) {
|
||||
const float* selTab = &rsmpTab12khz[x78_posLo >> 23 & 0x1fc];
|
||||
|
||||
|
@ -212,7 +207,7 @@ void EffectChorusImp<T>::SrcInfo::doSrc1(size_t blockSamples, size_t chanCount)
|
|||
++x7c_posHi;
|
||||
if (x7c_posHi == x88_trigger)
|
||||
x7c_posHi = x8c_target;
|
||||
*dest = ClampFull<T>(selTab[0] * old1 + selTab[1] * old2 + selTab[2] * old3 + selTab[3] * cur);
|
||||
*dest = selTab[0] * old1 + selTab[1] * old2 + selTab[2] * old3 + selTab[3] * cur;
|
||||
dest += chanCount;
|
||||
old1 = old2;
|
||||
old2 = old3;
|
||||
|
@ -220,7 +215,7 @@ void EffectChorusImp<T>::SrcInfo::doSrc1(size_t blockSamples, size_t chanCount)
|
|||
cur = x70_smpBase[x7c_posHi];
|
||||
} else {
|
||||
x78_posLo = ovrTest;
|
||||
*dest = ClampFull<T>(selTab[0] * old1 + selTab[1] * old2 + selTab[2] * old3 + selTab[3] * cur);
|
||||
*dest = selTab[0] * old1 + selTab[1] * old2 + selTab[2] * old3 + selTab[3] * cur;
|
||||
dest += chanCount;
|
||||
}
|
||||
}
|
||||
|
@ -230,14 +225,13 @@ void EffectChorusImp<T>::SrcInfo::doSrc1(size_t blockSamples, size_t chanCount)
|
|||
x74_old[2] = old3;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void EffectChorusImp<T>::SrcInfo::doSrc2(size_t blockSamples, size_t chanCount) {
|
||||
void EffectChorusImp::SrcInfo::doSrc2(size_t blockSamples, size_t chanCount) {
|
||||
float old1 = x74_old[0];
|
||||
float old2 = x74_old[1];
|
||||
float old3 = x74_old[2];
|
||||
float cur = x70_smpBase[x7c_posHi];
|
||||
|
||||
T* dest = x6c_dest;
|
||||
auto* dest = x6c_dest;
|
||||
for (size_t i = 0; i < blockSamples; ++i) {
|
||||
const float* selTab = &rsmpTab12khz[x78_posLo >> 23 & 0x1fc];
|
||||
++x7c_posHi;
|
||||
|
@ -258,14 +252,14 @@ void EffectChorusImp<T>::SrcInfo::doSrc2(size_t blockSamples, size_t chanCount)
|
|||
if (x7c_posHi == x88_trigger)
|
||||
x7c_posHi = x8c_target;
|
||||
|
||||
*dest = ClampFull<T>(selTab[0] * old1 + selTab[1] * old2 + selTab[2] * old3 + selTab[3] * cur);
|
||||
*dest = selTab[0] * old1 + selTab[1] * old2 + selTab[2] * old3 + selTab[3] * cur;
|
||||
dest += chanCount;
|
||||
|
||||
cur = x70_smpBase[x7c_posHi];
|
||||
} else {
|
||||
x78_posLo = ovrTest;
|
||||
|
||||
*dest = ClampFull<T>(selTab[0] * old1 + selTab[1] * old2 + selTab[2] * old3 + selTab[3] * cur);
|
||||
*dest = selTab[0] * old1 + selTab[1] * old2 + selTab[2] * old3 + selTab[3] * cur;
|
||||
dest += chanCount;
|
||||
|
||||
old1 = old2;
|
||||
|
@ -284,8 +278,7 @@ void EffectChorusImp<T>::SrcInfo::doSrc2(size_t blockSamples, size_t chanCount)
|
|||
x74_old[2] = old3;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void EffectChorusImp<T>::applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap) {
|
||||
void EffectChorusImp::applyEffect(float* audio, size_t frameCount, const ChannelMap& chanMap) {
|
||||
if (m_dirty)
|
||||
_update();
|
||||
|
||||
|
@ -293,12 +286,12 @@ void EffectChorusImp<T>::applyEffect(T* audio, size_t frameCount, const ChannelM
|
|||
for (size_t f = 0; f < frameCount;) {
|
||||
uint8_t next = x24_currentLast + 1;
|
||||
uint8_t buf = next % 3;
|
||||
std::array<T*, 8> bufs{
|
||||
std::array<float*, 8> bufs{
|
||||
x0_lastChans[0][buf], x0_lastChans[1][buf], x0_lastChans[2][buf], x0_lastChans[3][buf],
|
||||
x0_lastChans[4][buf], x0_lastChans[5][buf], x0_lastChans[6][buf], x0_lastChans[7][buf],
|
||||
};
|
||||
|
||||
T* inBuf = audio;
|
||||
auto* inBuf = audio;
|
||||
for (size_t s = 0; f < frameCount && s < m_blockSamples; ++s, ++f) {
|
||||
for (size_t c = 0; c < chanMap.m_channelCount && c < NumChannels; ++c) {
|
||||
*bufs[c]++ = *inBuf++;
|
||||
|
@ -314,7 +307,7 @@ void EffectChorusImp<T>::applyEffect(T* audio, size_t frameCount, const ChannelM
|
|||
x60_pitchOffset = -x60_pitchOffset;
|
||||
}
|
||||
|
||||
T* outBuf = audio;
|
||||
auto* outBuf = audio;
|
||||
size_t bs = std::min(remFrames, size_t(m_blockSamples));
|
||||
for (size_t c = 0; c < chanMap.m_channelCount && c < NumChannels; ++c) {
|
||||
x6c_src.x7c_posHi = x5c_currentPosHi;
|
||||
|
@ -348,7 +341,4 @@ void EffectChorusImp<T>::applyEffect(T* audio, size_t frameCount, const ChannelM
|
|||
}
|
||||
}
|
||||
|
||||
template class EffectChorusImp<int16_t>;
|
||||
template class EffectChorusImp<int32_t>;
|
||||
template class EffectChorusImp<float>;
|
||||
} // namespace amuse
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
|
||||
namespace amuse {
|
||||
|
||||
template <typename T>
|
||||
EffectDelayImp<T>::EffectDelayImp(uint32_t initDelay, uint32_t initFeedback, uint32_t initOutput, double sampleRate) {
|
||||
EffectDelayImp::EffectDelayImp(uint32_t initDelay, uint32_t initFeedback, uint32_t initOutput, double sampleRate) {
|
||||
initDelay = std::clamp(initDelay, 10u, 5000u);
|
||||
initFeedback = std::clamp(initFeedback, 0u, 100u);
|
||||
initOutput = std::clamp(initOutput, 0u, 100u);
|
||||
|
@ -20,8 +19,7 @@ EffectDelayImp<T>::EffectDelayImp(uint32_t initDelay, uint32_t initFeedback, uin
|
|||
_setup(sampleRate);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
EffectDelayImp<T>::EffectDelayImp(const EffectDelayInfo& info, double sampleRate) {
|
||||
EffectDelayImp::EffectDelayImp(const EffectDelayInfo& info, double sampleRate) {
|
||||
for (size_t i = 0; i < NumChannels; ++i) {
|
||||
x3c_delay[i] = std::clamp(info.delay[i], 10u, 5000u);
|
||||
x48_feedback[i] = std::clamp(info.feedback[i], 0u, 100u);
|
||||
|
@ -31,40 +29,37 @@ EffectDelayImp<T>::EffectDelayImp(const EffectDelayInfo& info, double sampleRate
|
|||
_setup(sampleRate);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void EffectDelayImp<T>::_setup(double sampleRate) {
|
||||
void EffectDelayImp::_setup(double sampleRate) {
|
||||
m_sampsPerMs = std::ceil(sampleRate / 1000.0);
|
||||
m_blockSamples = m_sampsPerMs * 5;
|
||||
|
||||
_update();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void EffectDelayImp<T>::_update() {
|
||||
void EffectDelayImp::_update() {
|
||||
for (size_t i = 0; i < NumChannels; ++i) {
|
||||
x0_currentSize[i] = ((x3c_delay[i] - 5) * m_sampsPerMs + 159) / 160;
|
||||
xc_currentPos[i] = 0;
|
||||
x18_currentFeedback[i] = x48_feedback[i] * 128 / 100;
|
||||
x24_currentOutput[i] = x54_output[i] * 128 / 100;
|
||||
|
||||
x30_chanLines[i] = std::make_unique<T[]>(m_blockSamples * x0_currentSize[i]);
|
||||
x30_chanLines[i] = std::make_unique<float[]>(m_blockSamples * x0_currentSize[i]);
|
||||
}
|
||||
|
||||
m_dirty = false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void EffectDelayImp<T>::applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap) {
|
||||
void EffectDelayImp::applyEffect(float* audio, size_t frameCount, const ChannelMap& chanMap) {
|
||||
if (m_dirty)
|
||||
_update();
|
||||
|
||||
for (size_t f = 0; f < frameCount;) {
|
||||
for (unsigned c = 0; c < chanMap.m_channelCount; ++c) {
|
||||
T* chanAud = audio + c;
|
||||
auto* chanAud = audio + c;
|
||||
for (unsigned i = 0; i < m_blockSamples && f < frameCount; ++i, ++f) {
|
||||
T& liveSamp = chanAud[chanMap.m_channelCount * i];
|
||||
T& samp = x30_chanLines[c][xc_currentPos[c] * m_blockSamples + i];
|
||||
samp = ClampFull<T>(samp * x18_currentFeedback[c] / 128 + liveSamp);
|
||||
auto& liveSamp = chanAud[chanMap.m_channelCount * i];
|
||||
auto& samp = x30_chanLines[c][xc_currentPos[c] * m_blockSamples + i];
|
||||
samp = samp * x18_currentFeedback[c] / 128 + liveSamp;
|
||||
liveSamp = samp * x24_currentOutput[c] / 128;
|
||||
}
|
||||
xc_currentPos[c] = (xc_currentPos[c] + 1) % x0_currentSize[c];
|
||||
|
@ -73,7 +68,4 @@ void EffectDelayImp<T>::applyEffect(T* audio, size_t frameCount, const ChannelMa
|
|||
}
|
||||
}
|
||||
|
||||
template class EffectDelayImp<int16_t>;
|
||||
template class EffectDelayImp<int32_t>;
|
||||
template class EffectDelayImp<float>;
|
||||
} // namespace amuse
|
||||
|
|
|
@ -62,21 +62,18 @@ EffectReverbStd::EffectReverbStd(float coloration, float mix, float time, float
|
|||
EffectReverbHi::EffectReverbHi(float coloration, float mix, float time, float damping, float preDelay, float crosstalk)
|
||||
: EffectReverbStd(coloration, mix, time, damping, preDelay), x1dc_crosstalk(std::clamp(crosstalk, 0.f, 1.0f)) {}
|
||||
|
||||
template <typename T>
|
||||
EffectReverbStdImp<T>::EffectReverbStdImp(float coloration, float mix, float time, float damping, float preDelay,
|
||||
EffectReverbStdImp::EffectReverbStdImp(float coloration, float mix, float time, float damping, float preDelay,
|
||||
double sampleRate)
|
||||
: EffectReverbStd(coloration, mix, time, damping, preDelay) {
|
||||
_setup(sampleRate);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void EffectReverbStdImp<T>::_setup(double sampleRate) {
|
||||
void EffectReverbStdImp::_setup(double sampleRate) {
|
||||
m_sampleRate = sampleRate;
|
||||
_update();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void EffectReverbStdImp<T>::_update() {
|
||||
void EffectReverbStdImp::_update() {
|
||||
float timeSamples = x148_x1d0_time * m_sampleRate;
|
||||
double rateRatio = m_sampleRate / NativeSampleRate;
|
||||
for (size_t c = 0; c < NumChannels; ++c) {
|
||||
|
@ -122,8 +119,7 @@ void EffectReverbStdImp<T>::_update() {
|
|||
m_dirty = false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void EffectReverbStdImp<T>::applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap) {
|
||||
void EffectReverbStdImp::applyEffect(float* audio, size_t frameCount, const ChannelMap& chanMap) {
|
||||
if (m_dirty)
|
||||
_update();
|
||||
|
||||
|
@ -212,7 +208,7 @@ void EffectReverbStdImp<T>::applyEffect(T* audio, size_t frameCount, const Chann
|
|||
linesAP[1].x4_outPoint = 0;
|
||||
|
||||
/* Mix out */
|
||||
audio[s * chanMap.m_channelCount + c] = ClampFull<T>(dampWet * allPass + dampDry * sample);
|
||||
audio[s * chanMap.m_channelCount + c] = dampWet * allPass + dampDry * sample;
|
||||
}
|
||||
x130_preDelayPtr[c] = preDelayPtr;
|
||||
}
|
||||
|
@ -220,21 +216,18 @@ void EffectReverbStdImp<T>::applyEffect(T* audio, size_t frameCount, const Chann
|
|||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
EffectReverbHiImp<T>::EffectReverbHiImp(float coloration, float mix, float time, float damping, float preDelay,
|
||||
EffectReverbHiImp::EffectReverbHiImp(float coloration, float mix, float time, float damping, float preDelay,
|
||||
float crosstalk, double sampleRate)
|
||||
: EffectReverbHi(coloration, mix, time, damping, preDelay, crosstalk) {
|
||||
_setup(sampleRate);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void EffectReverbHiImp<T>::_setup(double sampleRate) {
|
||||
void EffectReverbHiImp::_setup(double sampleRate) {
|
||||
m_sampleRate = sampleRate;
|
||||
_update();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void EffectReverbHiImp<T>::_update() {
|
||||
void EffectReverbHiImp::_update() {
|
||||
const float timeSamples = x148_x1d0_time * m_sampleRate;
|
||||
const double rateRatio = m_sampleRate / NativeSampleRate;
|
||||
|
||||
|
@ -287,8 +280,7 @@ void EffectReverbHiImp<T>::_update() {
|
|||
m_dirty = false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void EffectReverbHiImp<T>::_handleReverb(T* audio, int c, int chanCount, int sampleCount) {
|
||||
void EffectReverbHiImp::_handleReverb(float* audio, int c, int chanCount, int sampleCount) {
|
||||
const float dampWet = x19c_level * 0.6f;
|
||||
const float dampDry = 0.6f - dampWet;
|
||||
|
||||
|
@ -401,28 +393,26 @@ void EffectReverbHiImp<T>::_handleReverb(T* audio, int c, int chanCount, int sam
|
|||
lineLP.x4_outPoint = 0;
|
||||
|
||||
/* Mix out */
|
||||
audio[s * chanCount + c] = ClampFull<T>(dampWet * allPass + dampDry * sample);
|
||||
audio[s * chanCount + c] = dampWet * allPass + dampDry * sample;
|
||||
}
|
||||
|
||||
x1b8_preDelayPtr[c] = preDelayPtr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void EffectReverbHiImp<T>::_doCrosstalk(T* audio, float wet, float dry, int chanCount, int sampleCount) {
|
||||
void EffectReverbHiImp::_doCrosstalk(float* audio, float wet, float dry, int chanCount, int sampleCount) {
|
||||
for (int i = 0; i < sampleCount; ++i) {
|
||||
T* base = &audio[chanCount * i];
|
||||
auto* base = &audio[chanCount * i];
|
||||
float allWet = 0;
|
||||
for (int c = 0; c < chanCount; ++c) {
|
||||
allWet += base[c] * wet;
|
||||
base[c] *= dry;
|
||||
}
|
||||
for (int c = 0; c < chanCount; ++c)
|
||||
base[c] = ClampFull<T>(base[c] + allWet);
|
||||
base[c] = base[c] + allWet;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void EffectReverbHiImp<T>::applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap) {
|
||||
void EffectReverbHiImp::applyEffect(float* audio, size_t frameCount, const ChannelMap& chanMap) {
|
||||
if (m_dirty)
|
||||
_update();
|
||||
|
||||
|
@ -439,11 +429,4 @@ void EffectReverbHiImp<T>::applyEffect(T* audio, size_t frameCount, const Channe
|
|||
}
|
||||
}
|
||||
|
||||
template class EffectReverbStdImp<int16_t>;
|
||||
template class EffectReverbStdImp<int32_t>;
|
||||
template class EffectReverbStdImp<float>;
|
||||
|
||||
template class EffectReverbHiImp<int16_t>;
|
||||
template class EffectReverbHiImp<int32_t>;
|
||||
template class EffectReverbHiImp<float>;
|
||||
} // namespace amuse
|
||||
|
|
|
@ -29,23 +29,13 @@ EffectReverbHi& Submix::makeReverbHi(float coloration, float mix, float time, fl
|
|||
|
||||
EffectReverbHi& Submix::makeReverbHi(const EffectReverbHiInfo& info) { return makeEffect<EffectReverbHi>(info); }
|
||||
|
||||
void Submix::applyEffect(int16_t* audio, size_t frameCount, const ChannelMap& chanMap) const {
|
||||
for (const std::unique_ptr<EffectBaseTypeless>& effect : m_effectStack)
|
||||
((EffectBase<int16_t>&)*effect).applyEffect(audio, frameCount, chanMap);
|
||||
}
|
||||
|
||||
void Submix::applyEffect(int32_t* audio, size_t frameCount, const ChannelMap& chanMap) const {
|
||||
for (const std::unique_ptr<EffectBaseTypeless>& effect : m_effectStack)
|
||||
((EffectBase<int32_t>&)*effect).applyEffect(audio, frameCount, chanMap);
|
||||
}
|
||||
|
||||
void Submix::applyEffect(float* audio, size_t frameCount, const ChannelMap& chanMap) const {
|
||||
for (const std::unique_ptr<EffectBaseTypeless>& effect : m_effectStack)
|
||||
((EffectBase<float>&)*effect).applyEffect(audio, frameCount, chanMap);
|
||||
for (const std::unique_ptr<EffectBase>& effect : m_effectStack)
|
||||
effect->applyEffect(audio, frameCount, chanMap);
|
||||
}
|
||||
|
||||
void Submix::resetOutputSampleRate(double sampleRate) {
|
||||
for (const std::unique_ptr<EffectBaseTypeless>& effect : m_effectStack)
|
||||
for (const std::unique_ptr<EffectBase>& effect : m_effectStack)
|
||||
effect->resetOutputSampleRate(sampleRate);
|
||||
}
|
||||
} // namespace amuse
|
||||
|
|
Loading…
Reference in New Issue