mirror of https://github.com/AxioDL/amuse.git
Work on Chorus effect
This commit is contained in:
parent
3cce975977
commit
7aad87ea8c
|
@ -42,9 +42,12 @@ class BooBackendSubmix : public IBackendSubmix
|
|||
{
|
||||
BooBackendSubmix& m_parent;
|
||||
bool canApplyEffect() const;
|
||||
void applyEffect(int16_t* audio, const boo::ChannelMap& chanMap, double sampleRate) const;
|
||||
void applyEffect(int32_t* audio, const boo::ChannelMap& chanMap, double sampleRate) const;
|
||||
void applyEffect(float* audio, const boo::ChannelMap& chanMap, double sampleRate) const;
|
||||
void applyEffect(int16_t* audio, size_t frameCount,
|
||||
const boo::ChannelMap& chanMap, double sampleRate) const;
|
||||
void applyEffect(int32_t* audio, size_t frameCount,
|
||||
const boo::ChannelMap& chanMap, double sampleRate) const;
|
||||
void applyEffect(float* audio, size_t frameCount,
|
||||
const boo::ChannelMap& chanMap, double sampleRate) const;
|
||||
SubmixCallback(BooBackendSubmix& parent) : m_parent(parent) {}
|
||||
} m_cb;
|
||||
std::unique_ptr<boo::IAudioSubmix> m_booSubmix;
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
#ifndef __AMUSE_COMMON_HPP__
|
||||
#define __AMUSE_COMMON_HPP__
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace amuse
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
static inline T clamp(T a, T val, T b) {return std::max<T>(a, std::min<T>(b, val));}
|
||||
|
||||
#ifndef M_PIF
|
||||
#define M_PIF 3.14159265358979323846f /* pi */
|
||||
#endif
|
||||
|
|
|
@ -1,11 +1,22 @@
|
|||
#ifndef __AMUSE_EFFECTBASE_HPP__
|
||||
#define __AMUSE_EFFECTBASE_HPP__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace amuse
|
||||
{
|
||||
class ChannelMap;
|
||||
|
||||
class EffectBase
|
||||
{
|
||||
public:
|
||||
virtual void applyEffect(int16_t* audio, size_t frameCount,
|
||||
const ChannelMap& chanMap, double sampleRate)=0;
|
||||
virtual void applyEffect(int32_t* audio, size_t frameCount,
|
||||
const ChannelMap& chanMap, double sampleRate)=0;
|
||||
virtual void applyEffect(float* audio, size_t frameCount,
|
||||
const ChannelMap& chanMap, double sampleRate)=0;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -7,12 +7,66 @@
|
|||
namespace amuse
|
||||
{
|
||||
|
||||
#define AMUSE_CHORUS_NUM_BLOCKS 3
|
||||
|
||||
/** Mixes the audio back into itself after continuously-varying delay */
|
||||
class EffectChorus : public EffectBase
|
||||
{
|
||||
uint32_t m_baseDelay; /**< [5, 15] minimum value (in ms) for computed delay */
|
||||
uint32_t m_variation; /**< [0, 5] time error (in ms) to set delay within */
|
||||
uint32_t m_period; /**< [500, 10000] time (in ms) of one delay-shift cycle */
|
||||
int32_t* x0_lastLeft[AMUSE_CHORUS_NUM_BLOCKS];
|
||||
int32_t* xc_lastRight[AMUSE_CHORUS_NUM_BLOCKS];
|
||||
int32_t* x18_lastRearLeft[AMUSE_CHORUS_NUM_BLOCKS];
|
||||
int32_t* x18_lastRearRight[AMUSE_CHORUS_NUM_BLOCKS];
|
||||
int32_t* x18_lastCenter[AMUSE_CHORUS_NUM_BLOCKS];
|
||||
int32_t* x18_lastLFE[AMUSE_CHORUS_NUM_BLOCKS];
|
||||
int32_t* x18_lastSideLeft[AMUSE_CHORUS_NUM_BLOCKS];
|
||||
int32_t* x18_lastSideRight[AMUSE_CHORUS_NUM_BLOCKS];
|
||||
|
||||
uint8_t x24_currentLast = 1;
|
||||
int32_t x28_oldLeft[4] = {};
|
||||
int32_t x38_oldRight[4] = {};
|
||||
int32_t x48_oldRearLeft[4] = {};
|
||||
int32_t x48_oldRearRight[4] = {};
|
||||
int32_t x48_oldCenter[4] = {};
|
||||
int32_t x48_oldLFE[4] = {};
|
||||
int32_t x48_oldSideLeft[4] = {};
|
||||
int32_t x48_oldSideRight[4] = {};
|
||||
|
||||
uint32_t x58_currentPosLo = 0;
|
||||
uint32_t x5c_currentPosHi = 0;
|
||||
|
||||
int32_t x60_pitchOffset;
|
||||
uint32_t x64_pitchOffsetPeriodCount;
|
||||
uint32_t x68_pitchOffsetPeriod;
|
||||
|
||||
struct SrcInfo
|
||||
{
|
||||
int32_t* x6c_dest;
|
||||
int32_t* x70_smpBase;
|
||||
int32_t* x74_old;
|
||||
uint32_t x78_posLo;
|
||||
uint32_t x7c_posHi;
|
||||
uint32_t x80_pitchLo;
|
||||
uint32_t x84_pitchHi;
|
||||
uint32_t x88_trigger;
|
||||
uint32_t x8c_target = 0;
|
||||
} x6c_src;
|
||||
|
||||
uint32_t x90_baseDelay; /**< [5, 15] minimum value (in ms) for computed delay */
|
||||
uint32_t x94_variation; /**< [0, 5] time error (in ms) to set delay within */
|
||||
uint32_t x98_period; /**< [500, 10000] time (in ms) of one delay-shift cycle */
|
||||
|
||||
double m_sampleRate;
|
||||
uint32_t m_blockSamples;
|
||||
|
||||
public:
|
||||
~EffectChorus();
|
||||
EffectChorus(uint32_t baseDelay, uint32_t variation, uint32_t period, double sampleRate);
|
||||
void applyEffect(int16_t* audio, size_t frameCount,
|
||||
const ChannelMap& chanMap, double sampleRate);
|
||||
void applyEffect(int32_t* audio, size_t frameCount,
|
||||
const ChannelMap& chanMap, double sampleRate);
|
||||
void applyEffect(float* audio, size_t frameCount,
|
||||
const ChannelMap& chanMap, double sampleRate);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -13,6 +13,14 @@ class EffectDelay : public EffectBase
|
|||
uint32_t m_delay[8]; /**< [10, 5000] time in ms of each channel's delay */
|
||||
uint32_t m_feedback[8]; /**< [0, 100] percent to mix delayed signal with input signal */
|
||||
uint32_t m_output[8]; /**< [0, 100] total output percent */
|
||||
public:
|
||||
EffectDelay(uint32_t initDelay, uint32_t initFeedback, uint32_t initOutput);
|
||||
void applyEffect(int16_t* audio, size_t frameCount,
|
||||
const ChannelMap& chanMap, double sampleRate);
|
||||
void applyEffect(int32_t* audio, size_t frameCount,
|
||||
const ChannelMap& chanMap, double sampleRate);
|
||||
void applyEffect(float* audio, size_t frameCount,
|
||||
const ChannelMap& chanMap, double sampleRate);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -15,6 +15,15 @@ class EffectReverbHi : public EffectBase
|
|||
float m_damping; /**< [0.0, 1.0] damping factor influencing low-pass filter of reflections */
|
||||
float m_preDelay; /**< [0.0, 0.1] time in seconds before initial reflection heard */
|
||||
float m_crosstalk; /**< [0.0, 100.0] factor defining how much reflections are allowed to bleed to other channels */
|
||||
public:
|
||||
EffectReverbHi(float coloration, float mix, float time,
|
||||
float damping, float preDelay, float crosstalk);
|
||||
void applyEffect(int16_t* audio, size_t frameCount,
|
||||
const ChannelMap& chanMap, double sampleRate);
|
||||
void applyEffect(int32_t* audio, size_t frameCount,
|
||||
const ChannelMap& chanMap, double sampleRate);
|
||||
void applyEffect(float* audio, size_t frameCount,
|
||||
const ChannelMap& chanMap, double sampleRate);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -14,6 +14,15 @@ class EffectReverbStd : public EffectBase
|
|||
float m_time; /**< [0.01, 10.0] time in seconds for reflection decay */
|
||||
float m_damping; /**< [0.0, 1.0] damping factor influencing low-pass filter of reflections */
|
||||
float m_preDelay; /**< [0.0, 0.1] time in seconds before initial reflection heard */
|
||||
public:
|
||||
EffectReverbStd(float coloration, float mix, float time,
|
||||
float damping, float preDelay);
|
||||
void applyEffect(int16_t* audio, size_t frameCount,
|
||||
const ChannelMap& chanMap, double sampleRate);
|
||||
void applyEffect(int32_t* audio, size_t frameCount,
|
||||
const ChannelMap& chanMap, double sampleRate);
|
||||
void applyEffect(float* audio, size_t frameCount,
|
||||
const ChannelMap& chanMap, double sampleRate);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -48,20 +48,20 @@ bool BooBackendSubmix::SubmixCallback::canApplyEffect() const
|
|||
return m_parent.m_clientSmx.canApplyEffect();
|
||||
}
|
||||
|
||||
void BooBackendSubmix::SubmixCallback::applyEffect(int16_t* audio, const boo::ChannelMap& chanMap,
|
||||
double sampleRate) const
|
||||
void BooBackendSubmix::SubmixCallback::applyEffect(int16_t* audio, size_t frameCount,
|
||||
const boo::ChannelMap& chanMap, double sampleRate) const
|
||||
{
|
||||
return m_parent.m_clientSmx.applyEffect(audio, reinterpret_cast<const ChannelMap&>(chanMap), sampleRate);
|
||||
}
|
||||
|
||||
void BooBackendSubmix::SubmixCallback::applyEffect(int32_t* audio, const boo::ChannelMap& chanMap,
|
||||
double sampleRate) const
|
||||
void BooBackendSubmix::SubmixCallback::applyEffect(int32_t* audio, size_t frameCount,
|
||||
const boo::ChannelMap& chanMap, double sampleRate) const
|
||||
{
|
||||
return m_parent.m_clientSmx.applyEffect(audio, reinterpret_cast<const ChannelMap&>(chanMap), sampleRate);
|
||||
}
|
||||
|
||||
void BooBackendSubmix::SubmixCallback::applyEffect(float* audio, const boo::ChannelMap& chanMap,
|
||||
double sampleRate) const
|
||||
void BooBackendSubmix::SubmixCallback::applyEffect(float* audio, size_t frameCount,
|
||||
const boo::ChannelMap& chanMap, double sampleRate) const
|
||||
{
|
||||
return m_parent.m_clientSmx.applyEffect(audio, reinterpret_cast<const ChannelMap&>(chanMap), sampleRate);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
#include "amuse/EffectChorus.hpp"
|
||||
#include "amuse/Common.hpp"
|
||||
#include <string.h>
|
||||
|
||||
namespace amuse
|
||||
{
|
||||
|
||||
EffectChorus::EffectChorus(uint32_t baseDelay, uint32_t variation,
|
||||
uint32_t period, double sampleRate)
|
||||
: x90_baseDelay(clamp(5u, baseDelay, 15u)),
|
||||
x94_variation(clamp(0u, variation, 5u)),
|
||||
x98_period(clamp(500u, period, 10000u)),
|
||||
m_sampleRate(sampleRate),
|
||||
m_blockSamples(sampleRate * 160.0 / 32000.0)
|
||||
{
|
||||
int32_t* buf = new int32_t[m_blockSamples * AMUSE_CHORUS_NUM_BLOCKS * 8];
|
||||
memset(buf, 0, m_blockSamples * AMUSE_CHORUS_NUM_BLOCKS * 8 * sizeof(int32_t));
|
||||
size_t chanPitch = m_blockSamples * AMUSE_CHORUS_NUM_BLOCKS;
|
||||
|
||||
x0_lastLeft[0] = buf;
|
||||
x0_lastLeft[1] = x0_lastLeft[0] + m_blockSamples;
|
||||
x0_lastLeft[2] = x0_lastLeft[0] + m_blockSamples * 2;
|
||||
|
||||
xc_lastRight[0] = buf + chanPitch;
|
||||
xc_lastRight[1] = xc_lastRight[0] + m_blockSamples;
|
||||
xc_lastRight[2] = xc_lastRight[0] + m_blockSamples * 2;
|
||||
|
||||
x18_lastRearLeft[0] = buf + chanPitch * 2;
|
||||
x18_lastRearLeft[1] = x18_lastRearLeft[0] + m_blockSamples;
|
||||
x18_lastRearLeft[2] = x18_lastRearLeft[0] + m_blockSamples * 2;
|
||||
|
||||
x18_lastRearRight[0] = buf + chanPitch * 3;
|
||||
x18_lastRearRight[1] = x18_lastRearRight[0] + m_blockSamples;
|
||||
x18_lastRearRight[2] = x18_lastRearRight[0] + m_blockSamples * 2;
|
||||
|
||||
x18_lastCenter[0] = buf + chanPitch * 4;
|
||||
x18_lastCenter[1] = x18_lastCenter[0] + m_blockSamples;
|
||||
x18_lastCenter[2] = x18_lastCenter[0] + m_blockSamples * 2;
|
||||
|
||||
x18_lastLFE[0] = buf + chanPitch * 5;
|
||||
x18_lastLFE[1] = x18_lastLFE[0] + m_blockSamples;
|
||||
x18_lastLFE[2] = x18_lastLFE[0] + m_blockSamples * 2;
|
||||
|
||||
x18_lastSideLeft[0] = buf + chanPitch * 6;
|
||||
x18_lastSideLeft[1] = x18_lastSideLeft[0] + m_blockSamples;
|
||||
x18_lastSideLeft[2] = x18_lastSideLeft[0] + m_blockSamples * 2;
|
||||
|
||||
x18_lastSideRight[0] = buf + chanPitch * 7;
|
||||
x18_lastSideRight[1] = x18_lastSideRight[0] + m_blockSamples;
|
||||
x18_lastSideRight[2] = x18_lastSideRight[0] + m_blockSamples * 2;
|
||||
|
||||
x6c_src.x88_trigger = chanPitch;
|
||||
|
||||
x5c_currentPosHi = m_blockSamples * 2 - ((x90_baseDelay - 5) * m_sampleRate / 1000.f);
|
||||
uint32_t temp = (x5c_currentPosHi + (x24_currentLast - 1) * m_blockSamples);
|
||||
x5c_currentPosHi = temp - ((temp * 8 / 15) >> 8) * chanPitch;
|
||||
|
||||
x68_pitchOffsetPeriod = (x98_period * 2 / 10 + 1) & ~1;
|
||||
x60_pitchOffset = x94_variation * 2048 / x68_pitchOffsetPeriod;
|
||||
}
|
||||
|
||||
EffectChorus::~EffectChorus()
|
||||
{
|
||||
delete[] x0_lastLeft[0];
|
||||
}
|
||||
|
||||
void EffectChorus::applyEffect(int16_t* audio, size_t frameCount,
|
||||
const ChannelMap& chanMap, double sampleRate)
|
||||
{
|
||||
}
|
||||
|
||||
void EffectChorus::applyEffect(int32_t* audio, size_t frameCount,
|
||||
const ChannelMap& chanMap, double sampleRate)
|
||||
{
|
||||
}
|
||||
|
||||
void EffectChorus::applyEffect(float* audio, size_t frameCount,
|
||||
const ChannelMap& chanMap, double sampleRate)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue