stereo reverb
This commit is contained in:
parent
91a44e9c5e
commit
45e2867877
@ -8,8 +8,8 @@ namespace audio {
|
|||||||
constexpr int channels = 2;
|
constexpr int channels = 2;
|
||||||
|
|
||||||
struct DelayFilter {
|
struct DelayFilter {
|
||||||
float * buffer;
|
float * buffers[channels];
|
||||||
int index;
|
int indexes[channels];
|
||||||
|
|
||||||
const int maxDelay;
|
const int maxDelay;
|
||||||
int delay;
|
int delay;
|
||||||
@ -18,23 +18,23 @@ namespace audio {
|
|||||||
DelayFilter(int maxDelay, int delay, float gain);
|
DelayFilter(int maxDelay, int delay, float gain);
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
virtual float feed(float value) = 0;
|
virtual float feed(int channel, float value) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FeedbackCombFilter : DelayFilter {
|
struct FeedbackCombFilter : DelayFilter {
|
||||||
FeedbackCombFilter(int maxDelay, int delay, float gain);
|
FeedbackCombFilter(int maxDelay, int delay, float gain);
|
||||||
float feed(float value) override;
|
float feed(int channel, float value) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FeedforwardCombFilter : DelayFilter {
|
struct FeedforwardCombFilter : DelayFilter {
|
||||||
public:
|
public:
|
||||||
FeedforwardCombFilter(int maxDelay, int delay, float gain);
|
FeedforwardCombFilter(int maxDelay, int delay, float gain);
|
||||||
float feed(float value) override;
|
float feed(int channel, float value) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AllpassFilter : DelayFilter {
|
struct AllpassFilter : DelayFilter {
|
||||||
AllpassFilter(int maxDelay, int delay, float gain);
|
AllpassFilter(int maxDelay, int delay, float gain);
|
||||||
float feed(float x) override;
|
float feed(int channel, float x) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
using FBCF = FeedbackCombFilter;
|
using FBCF = FeedbackCombFilter;
|
||||||
@ -52,11 +52,11 @@ namespace audio {
|
|||||||
|
|
||||||
Reverb(DelayFilter * cf, DelayFilter * ap);
|
Reverb(DelayFilter * cf, DelayFilter * ap);
|
||||||
void reset();
|
void reset();
|
||||||
lr feed(float x);
|
lr feed(int channel, float x);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int reverbIndex;
|
extern int reverbIndex;
|
||||||
extern Reverb * reverbs[];
|
extern Reverb reverbs[];
|
||||||
extern int const reverbsCount;
|
extern int const reverbsCount;
|
||||||
|
|
||||||
extern float wetGain;
|
extern float wetGain;
|
||||||
|
|||||||
@ -34,16 +34,20 @@ namespace audio {
|
|||||||
|
|
||||||
void DelayFilter::reset()
|
void DelayFilter::reset()
|
||||||
{
|
{
|
||||||
memset(buffer, 0, maxDelay * (sizeof (float)));
|
for (int i = 0; i < channels; i++) {
|
||||||
|
memset(buffers[i], 0, maxDelay * (sizeof (float)));
|
||||||
|
indexes[i] = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DelayFilter::DelayFilter(int maxDelay, int delay, float gain)
|
DelayFilter::DelayFilter(int maxDelay, int delay, float gain)
|
||||||
: index(0)
|
: maxDelay(maxDelay)
|
||||||
, maxDelay(maxDelay)
|
|
||||||
, delay(delay)
|
, delay(delay)
|
||||||
, gain(gain)
|
, gain(gain)
|
||||||
{
|
{
|
||||||
buffer = (float *)malloc(maxDelay * (sizeof (float)));
|
for (int i = 0; i < channels; i++) {
|
||||||
|
buffers[i] = (float *)malloc(maxDelay * (sizeof (float)));
|
||||||
|
}
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,8 +59,11 @@ namespace audio {
|
|||||||
: DelayFilter(maxDelay, delay, gain)
|
: DelayFilter(maxDelay, delay, gain)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
float FeedbackCombFilter::feed(float value)
|
float FeedbackCombFilter::feed(int channel, float value)
|
||||||
{
|
{
|
||||||
|
int & index = indexes[channel];
|
||||||
|
float * buffer = buffers[channel];
|
||||||
|
|
||||||
float y = gain * value + gain * buffer[index];
|
float y = gain * value + gain * buffer[index];
|
||||||
buffer[index] = y;
|
buffer[index] = y;
|
||||||
index = (index + 1) % delay;
|
index = (index + 1) % delay;
|
||||||
@ -71,8 +78,11 @@ namespace audio {
|
|||||||
: DelayFilter(maxDelay, delay, gain)
|
: DelayFilter(maxDelay, delay, gain)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
float FeedforwardCombFilter::feed(float value)
|
float FeedforwardCombFilter::feed(int channel, float value)
|
||||||
{
|
{
|
||||||
|
int & index = indexes[channel];
|
||||||
|
float * buffer = buffers[channel];
|
||||||
|
|
||||||
float y = gain * value + gain * buffer[index];
|
float y = gain * value + gain * buffer[index];
|
||||||
buffer[index] = value;
|
buffer[index] = value;
|
||||||
index = (index + 1) % delay;
|
index = (index + 1) % delay;
|
||||||
@ -87,8 +97,11 @@ namespace audio {
|
|||||||
: DelayFilter(maxDelay, delay, gain)
|
: DelayFilter(maxDelay, delay, gain)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
float AllpassFilter::feed(float x)
|
float AllpassFilter::feed(int channel, float x)
|
||||||
{
|
{
|
||||||
|
int & index = indexes[channel];
|
||||||
|
float * buffer = buffers[channel];
|
||||||
|
|
||||||
float v = x + -gain * buffer[index];
|
float v = x + -gain * buffer[index];
|
||||||
float y = buffer[index] + gain * v;
|
float y = buffer[index] + gain * v;
|
||||||
buffer[index] = v;
|
buffer[index] = v;
|
||||||
@ -108,16 +121,16 @@ namespace audio {
|
|||||||
ap[i].reset();
|
ap[i].reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
lr Reverb::feed(float x)
|
lr Reverb::feed(int channel, float x)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < apCount; i++) {
|
for (int i = 0; i < apCount; i++) {
|
||||||
x = ap[i].feed(x);
|
x = ap[i].feed(channel, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
float x0 = cf[0].feed(x);
|
float x0 = cf[0].feed(channel, x);
|
||||||
float x1 = cf[1].feed(x);
|
float x1 = cf[1].feed(channel, x);
|
||||||
float x2 = cf[2].feed(x);
|
float x2 = cf[2].feed(channel, x);
|
||||||
float x3 = cf[3].feed(x);
|
float x3 = cf[3].feed(channel, x);
|
||||||
|
|
||||||
float s0 = x0 + x2;
|
float s0 = x0 + x2;
|
||||||
float s1 = x1 + x3;
|
float s1 = x1 + x3;
|
||||||
@ -139,7 +152,6 @@ namespace audio {
|
|||||||
static AP forwardAP[3]{AP{2500, 2017, 0.7f},
|
static AP forwardAP[3]{AP{2500, 2017, 0.7f},
|
||||||
AP{2500, 647, 0.7f},
|
AP{2500, 647, 0.7f},
|
||||||
AP{2500, 137, 0.7f}};
|
AP{2500, 137, 0.7f}};
|
||||||
Reverb forwardReverb(forwardCF, forwardAP);
|
|
||||||
|
|
||||||
static FBCF backCF[4]{FBCF{10000, 3229, 0.733f}, // 1687
|
static FBCF backCF[4]{FBCF{10000, 3229, 0.733f}, // 1687
|
||||||
FBCF{10000, 3079, 0.802f}, // 1601
|
FBCF{10000, 3079, 0.802f}, // 1601
|
||||||
@ -148,12 +160,11 @@ namespace audio {
|
|||||||
static AP backAP[3]{AP{1500, 661, 0.7f}, // 347
|
static AP backAP[3]{AP{1500, 661, 0.7f}, // 347
|
||||||
AP{1500, 257, 0.7f}, // 113
|
AP{1500, 257, 0.7f}, // 113
|
||||||
AP{1500, 71, 0.7f}};
|
AP{1500, 71, 0.7f}};
|
||||||
Reverb backReverb(backCF, backAP);
|
|
||||||
|
|
||||||
int reverbIndex = 0;
|
int reverbIndex = 0;
|
||||||
Reverb * reverbs[] = {
|
Reverb reverbs[] = {
|
||||||
&backReverb,
|
{backCF, backAP},
|
||||||
&forwardReverb,
|
{forwardCF, forwardAP},
|
||||||
};
|
};
|
||||||
int const reverbsCount = (sizeof (reverbs)) / (sizeof (reverbs[0]));
|
int const reverbsCount = (sizeof (reverbs)) / (sizeof (reverbs[0]));
|
||||||
|
|
||||||
@ -198,7 +209,7 @@ namespace audio {
|
|||||||
|
|
||||||
audio_instances_count = 0;
|
audio_instances_count = 0;
|
||||||
for (int i = 0; i < reverbsCount; i++)
|
for (int i = 0; i < reverbsCount; i++)
|
||||||
reverbs[i]->reset();
|
reverbs[i].reset();
|
||||||
|
|
||||||
for (int i = 0; i < mixChannelCount; i++) {
|
for (int i = 0; i < mixChannelCount; i++) {
|
||||||
mixChannelGain[i] = 1.0f;
|
mixChannelGain[i] = 1.0f;
|
||||||
@ -539,15 +550,21 @@ namespace audio {
|
|||||||
// audio configuration "B"
|
// audio configuration "B"
|
||||||
// mono reverberation
|
// mono reverberation
|
||||||
for (int i = 0; i < half_period_samples; i++) {
|
for (int i = 0; i < half_period_samples; i++) {
|
||||||
float value = channel_buffer[mix_channel::voice][i * channels + 0];
|
float mix[2] = { 0, 0 };
|
||||||
|
for (int ch = 0; ch < channels; ch++) {
|
||||||
|
float value = channel_buffer[mix_channel::voice][i * channels + ch];
|
||||||
|
|
||||||
lr wet;
|
|
||||||
assert(reverbIndex >= 0 && reverbIndex < reverbsCount);
|
assert(reverbIndex >= 0 && reverbIndex < reverbsCount);
|
||||||
wet = reverbs[reverbIndex]->feed(value);
|
lr wet = reverbs[reverbIndex].feed(ch, value);
|
||||||
|
|
||||||
float left = value * dryGain + wet.l * wetGain;
|
float left = value * dryGain + wet.l * wetGain;
|
||||||
float right = value * dryGain + wet.r * wetGain;
|
float right = value * dryGain + wet.r * wetGain;
|
||||||
channel_buffer[mix_channel::voice][i * channels + 0] = left;
|
mix[0 ^ ch] += left;
|
||||||
channel_buffer[mix_channel::voice][i * channels + 1] = right;
|
mix[1 ^ ch] += right;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int ch = 0; ch < channels; ch++)
|
||||||
|
channel_buffer[mix_channel::voice][i * channels + ch] = mix[ch];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < half_period_samples; i++) {
|
for (int i = 0; i < half_period_samples; i++) {
|
||||||
|
|||||||
@ -74,15 +74,15 @@ namespace ui
|
|||||||
reverberatorSliders[i].ap[j] =
|
reverberatorSliders[i].ap[j] =
|
||||||
widget::DelayGainSlider(allpassLabels[j],
|
widget::DelayGainSlider(allpassLabels[j],
|
||||||
allpassLeft, top + ySpace * j,
|
allpassLeft, top + ySpace * j,
|
||||||
1, audio::reverbs[i]->ap[j].maxDelay, &audio::reverbs[i]->ap[j].delay,
|
1, audio::reverbs[i].ap[j].maxDelay, &audio::reverbs[i].ap[j].delay,
|
||||||
0.0, 1.0, &audio::reverbs[i]->ap[j].gain);
|
0.0, 1.0, &audio::reverbs[i].ap[j].gain);
|
||||||
}
|
}
|
||||||
for (int j = 0; j < 4; j++) {
|
for (int j = 0; j < 4; j++) {
|
||||||
reverberatorSliders[i].comb[j] =
|
reverberatorSliders[i].comb[j] =
|
||||||
widget::DelayGainSlider(combLabels[j],
|
widget::DelayGainSlider(combLabels[j],
|
||||||
combLeft, top + ySpace * j,
|
combLeft, top + ySpace * j,
|
||||||
100, audio::reverbs[i]->cf[j].maxDelay, &audio::reverbs[i]->cf[j].delay,
|
100, audio::reverbs[i].cf[j].maxDelay, &audio::reverbs[i].cf[j].delay,
|
||||||
0.0, 1.0, &audio::reverbs[i]->cf[j].gain);
|
0.0, 1.0, &audio::reverbs[i].cf[j].gain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user