audio: array of reverberators
This commit is contained in:
parent
057ba291d8
commit
91a44e9c5e
7
Makefile
7
Makefile
@ -23,7 +23,9 @@ CFLAGS += -Wno-format
|
|||||||
CFLAGS += -Wno-error=unused-function
|
CFLAGS += -Wno-error=unused-function
|
||||||
CFLAGS += -Wno-error=array-bounds
|
CFLAGS += -Wno-error=array-bounds
|
||||||
CFLAGS += -Wno-unknown-pragmas
|
CFLAGS += -Wno-unknown-pragmas
|
||||||
|
ifneq '' '$(findstring clang++,$(CXX))'
|
||||||
CFLAGS += -Wno-vla-cxx-extension
|
CFLAGS += -Wno-vla-cxx-extension
|
||||||
|
endif
|
||||||
CFLAGS += -fno-strict-aliasing
|
CFLAGS += -fno-strict-aliasing
|
||||||
CFLAGS += -I./include
|
CFLAGS += -I./include
|
||||||
CFLAGS += -I./data
|
CFLAGS += -I./data
|
||||||
@ -43,7 +45,7 @@ LDFLAGS += -lm
|
|||||||
#LDFLAGS += -Wl,--gc-sections
|
#LDFLAGS += -Wl,--gc-sections
|
||||||
#-Wl,--print-gc-sections
|
#-Wl,--print-gc-sections
|
||||||
ifeq ($(UNAME),Linux)
|
ifeq ($(UNAME),Linux)
|
||||||
#LDFLAGS += -Wl,-z noexecstack
|
LDFLAGS += -z noexecstack
|
||||||
endif
|
endif
|
||||||
ifeq ($(UNAME),Darwin)
|
ifeq ($(UNAME),Darwin)
|
||||||
LDFLAGS += -framework Foundation -framework Cocoa -framework IOKit -framework AVFoundation -framework CoreVideo -framework CoreAudio -framework CoreMedia -framework CoreHaptics -framework AudioToolbox -framework GameController -framework ForceFeedback -framework Carbon -framework Metal -framework QuartzCore -framework UniformTypeIdentifiers
|
LDFLAGS += -framework Foundation -framework Cocoa -framework IOKit -framework AVFoundation -framework CoreVideo -framework CoreAudio -framework CoreMedia -framework CoreHaptics -framework AudioToolbox -framework GameController -framework ForceFeedback -framework Carbon -framework Metal -framework QuartzCore -framework UniformTypeIdentifiers
|
||||||
@ -114,9 +116,6 @@ endif
|
|||||||
|
|
||||||
all: main
|
all: main
|
||||||
|
|
||||||
CC = clang
|
|
||||||
CXX = clang++
|
|
||||||
|
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
$(CC) $(ARCH) $(CSTD) $(CFLAGS) $(FLAGS) $(OPT) $(DEBUG) -c $< -o $@
|
$(CC) $(ARCH) $(CSTD) $(CFLAGS) $(FLAGS) $(OPT) $(DEBUG) -c $< -o $@
|
||||||
|
|
||||||
|
|||||||
@ -7,88 +7,57 @@ namespace audio {
|
|||||||
constexpr int sample_rate = 48000;
|
constexpr int sample_rate = 48000;
|
||||||
constexpr int channels = 2;
|
constexpr int channels = 2;
|
||||||
|
|
||||||
template <int maxDelay>
|
struct DelayFilter {
|
||||||
struct FeedbackCombFilter {
|
float * buffer;
|
||||||
private:
|
|
||||||
//float * buffer;
|
|
||||||
float buffer[maxDelay];
|
|
||||||
int index;
|
|
||||||
public:
|
|
||||||
int delay;
|
|
||||||
float gain0;
|
|
||||||
float gainM;
|
|
||||||
|
|
||||||
FeedbackCombFilter(int delay, float gain0, float gainM);
|
|
||||||
void reset();
|
|
||||||
float feed(float value);
|
|
||||||
};
|
|
||||||
|
|
||||||
template <int maxDelay>
|
|
||||||
struct FeedforwardCombFilter {
|
|
||||||
private:
|
|
||||||
//float * buffer;
|
|
||||||
float buffer[maxDelay];
|
|
||||||
int index;
|
|
||||||
public:
|
|
||||||
int delay;
|
|
||||||
float gain0;
|
|
||||||
float gainM;
|
|
||||||
|
|
||||||
FeedforwardCombFilter(int delay, float gain0, float gainM);
|
|
||||||
void reset();
|
|
||||||
float feed(float value);
|
|
||||||
};
|
|
||||||
|
|
||||||
template <int maxDelay>
|
|
||||||
struct AllpassFilter {
|
|
||||||
private:
|
|
||||||
//float * buffer;
|
|
||||||
float buffer[maxDelay];
|
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
public:
|
const int maxDelay;
|
||||||
int delay;
|
int delay;
|
||||||
float gain0;
|
float gain;
|
||||||
float gainM;
|
|
||||||
|
DelayFilter(int maxDelay, int delay, float gain);
|
||||||
|
|
||||||
AllpassFilter(int delay, float gain0, float gainM);
|
|
||||||
void reset();
|
void reset();
|
||||||
float feed(float x);
|
virtual float feed(float value) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
using FBCF = FeedbackCombFilter<15000>;
|
struct FeedbackCombFilter : DelayFilter {
|
||||||
using FFCF = FeedforwardCombFilter<15000>;
|
FeedbackCombFilter(int maxDelay, int delay, float gain);
|
||||||
using AP = AllpassFilter<2500>;
|
float feed(float value) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FeedforwardCombFilter : DelayFilter {
|
||||||
|
public:
|
||||||
|
FeedforwardCombFilter(int maxDelay, int delay, float gain);
|
||||||
|
float feed(float value) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AllpassFilter : DelayFilter {
|
||||||
|
AllpassFilter(int maxDelay, int delay, float gain);
|
||||||
|
float feed(float x) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
using FBCF = FeedbackCombFilter;
|
||||||
|
using FFCF = FeedforwardCombFilter;
|
||||||
|
using AP = AllpassFilter;
|
||||||
|
|
||||||
struct lr { float l; float r; };
|
struct lr { float l; float r; };
|
||||||
|
|
||||||
struct FBReverb {
|
struct Reverb {
|
||||||
|
static constexpr int apCount = 3;
|
||||||
static constexpr int cfCount = 4;
|
static constexpr int cfCount = 4;
|
||||||
static constexpr int apCount = 3;
|
|
||||||
|
|
||||||
FBCF cf[cfCount];
|
DelayFilter * cf;
|
||||||
AP ap[apCount];
|
DelayFilter * ap;
|
||||||
|
|
||||||
FBReverb();
|
Reverb(DelayFilter * cf, DelayFilter * ap);
|
||||||
void reset();
|
|
||||||
lr feed(float x);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FFReverb {
|
|
||||||
static constexpr int __cfCount = 4;
|
|
||||||
static constexpr int apCount = 3;
|
|
||||||
|
|
||||||
FFCF cf[__cfCount];
|
|
||||||
AP ap[apCount];
|
|
||||||
|
|
||||||
FFReverb();
|
|
||||||
void reset();
|
void reset();
|
||||||
lr feed(float x);
|
lr feed(float x);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int reverbIndex;
|
extern int reverbIndex;
|
||||||
extern FBReverb fbreverb;
|
extern Reverb * reverbs[];
|
||||||
extern FFReverb ffreverb;
|
extern int const reverbsCount;
|
||||||
|
|
||||||
extern float wetGain;
|
extern float wetGain;
|
||||||
extern float dryGain;
|
extern float dryGain;
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
namespace ui
|
namespace ui
|
||||||
{
|
{
|
||||||
|
void init();
|
||||||
void draw(MappedInstanceData<SolidInstance> & data,
|
void draw(MappedInstanceData<SolidInstance> & data,
|
||||||
MappedInstanceData<font::BitmapInstance> & fontData);
|
MappedInstanceData<font::BitmapInstance> & fontData);
|
||||||
void update(float mx, float my, bool mLeft, bool mEdge);
|
void update(float mx, float my, bool mLeft, bool mEdge);
|
||||||
|
|||||||
@ -86,6 +86,9 @@ namespace ui::widget
|
|||||||
T maxExtent;
|
T maxExtent;
|
||||||
T * value;
|
T * value;
|
||||||
|
|
||||||
|
Slider()
|
||||||
|
{}
|
||||||
|
|
||||||
Slider(char const * label,
|
Slider(char const * label,
|
||||||
int left, int top, int width, int height,
|
int left, int top, int width, int height,
|
||||||
T minValue, T maxValue,
|
T minValue, T maxValue,
|
||||||
@ -117,30 +120,27 @@ namespace ui::widget
|
|||||||
char const * label;
|
char const * label;
|
||||||
|
|
||||||
Slider<int, true> delay;
|
Slider<int, true> delay;
|
||||||
Slider<float, true> gain0;
|
Slider<float, true> gain;
|
||||||
Slider<float, true> gainM;
|
|
||||||
|
DelayGainSlider()
|
||||||
|
{}
|
||||||
|
|
||||||
DelayGainSlider(char const * label,
|
DelayGainSlider(char const * label,
|
||||||
int left, int top,
|
int left, int top,
|
||||||
int delayMin, int delayMax, int * delayValue,
|
int delayMin, int delayMax, int * delayValue,
|
||||||
float gainMin, float gainMax,
|
float gainMin, float gainMax,
|
||||||
float * gain0Value, float * gainMValue)
|
float * gainValue)
|
||||||
: label(label)
|
: label(label)
|
||||||
, delay("delay",
|
, delay("delay",
|
||||||
left, top, 150, 14,
|
left, top, 150, 14,
|
||||||
delayMin, delayMax,
|
delayMin, delayMax,
|
||||||
delayMin, delayMax,
|
delayMin, delayMax,
|
||||||
delayValue)
|
delayValue)
|
||||||
, gain0("gain0",
|
, gain("gain",
|
||||||
left, top + 30, 150, 14,
|
left, top + 30, 150, 14,
|
||||||
gainMin, gainMax,
|
gainMin, gainMax,
|
||||||
gainMin, gainMax,
|
gainMin, gainMax,
|
||||||
gain0Value)
|
gainValue)
|
||||||
, gainM("gainM",
|
|
||||||
left, top + 60, 150, 14,
|
|
||||||
gainMin, gainMax,
|
|
||||||
gainMin, gainMax,
|
|
||||||
gainMValue)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void draw(MappedInstanceData<SolidInstance> & data,
|
void draw(MappedInstanceData<SolidInstance> & data,
|
||||||
|
|||||||
208
src/audio.cpp
208
src/audio.cpp
@ -13,14 +13,14 @@
|
|||||||
#include "poem.h"
|
#include "poem.h"
|
||||||
|
|
||||||
namespace audio {
|
namespace audio {
|
||||||
static int const frame_samples = 960; // 20 milliseconds @ 48kHz
|
//static int const frame_samples = 960; // 20 milliseconds @ 48kHz
|
||||||
static int const sample_size = (sizeof (int16_t));
|
static int const sample_size = (sizeof (int16_t));
|
||||||
|
|
||||||
static int const max_frame_size = 960 * 3; // 20ms at 48kHz
|
static int const max_frame_size = 960 * 3; // 20ms at 48kHz
|
||||||
static int const max_packet_size = 1275;
|
//static int const max_packet_size = 1275;
|
||||||
|
|
||||||
static int const half_period_samples = sample_rate / 30;
|
static int const half_period_samples = sample_rate / 30;
|
||||||
static int const half_period_size = half_period_samples * sample_size * channels;
|
//static int const half_period_size = half_period_samples * sample_size * channels;
|
||||||
|
|
||||||
struct AudioBuffer {
|
struct AudioBuffer {
|
||||||
renpy::language::audio const * audio;
|
renpy::language::audio const * audio;
|
||||||
@ -28,111 +28,87 @@ namespace audio {
|
|||||||
uint32_t sample_count;
|
uint32_t sample_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <int maxDelay>
|
//////////////////////////////////////////////////////////////////////
|
||||||
FeedbackCombFilter<maxDelay>::FeedbackCombFilter(int delay, float gain0, float gainM)
|
// DelayFilter
|
||||||
: delay(delay), gain0(gain0), gainM(gainM)
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void DelayFilter::reset()
|
||||||
{
|
{
|
||||||
//buffer = (float *)malloc((sizeof (float)) * maxDelay);
|
memset(buffer, 0, maxDelay * (sizeof (float)));
|
||||||
|
}
|
||||||
|
|
||||||
|
DelayFilter::DelayFilter(int maxDelay, int delay, float gain)
|
||||||
|
: index(0)
|
||||||
|
, maxDelay(maxDelay)
|
||||||
|
, delay(delay)
|
||||||
|
, gain(gain)
|
||||||
|
{
|
||||||
|
buffer = (float *)malloc(maxDelay * (sizeof (float)));
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int maxDelay>
|
//////////////////////////////////////////////////////////////////////
|
||||||
void FeedbackCombFilter<maxDelay>::reset()
|
// FeedbackCombFilter
|
||||||
{
|
//////////////////////////////////////////////////////////////////////
|
||||||
index = 0;
|
|
||||||
memset(buffer, 0, (sizeof (float)) * maxDelay);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <int maxDelay>
|
FeedbackCombFilter::FeedbackCombFilter(int maxDelay, int delay, float gain)
|
||||||
float FeedbackCombFilter<maxDelay>::feed(float value)
|
: DelayFilter(maxDelay, delay, gain)
|
||||||
|
{}
|
||||||
|
|
||||||
|
float FeedbackCombFilter::feed(float value)
|
||||||
{
|
{
|
||||||
float y = gain0 * value + gainM * buffer[index];
|
float y = gain * value + gain * buffer[index];
|
||||||
buffer[index] = y;
|
buffer[index] = y;
|
||||||
index = (index + 1) % delay;
|
index = (index + 1) % delay;
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int maxDelay>
|
//////////////////////////////////////////////////////////////////////
|
||||||
FeedforwardCombFilter<maxDelay>::FeedforwardCombFilter(int delay, float gain0, float gainM)
|
// FeedForwardCombFilter
|
||||||
: delay(delay), gain0(gain0), gainM(gainM)
|
//////////////////////////////////////////////////////////////////////
|
||||||
{
|
|
||||||
//buffer = (float *)malloc((sizeof (float)) * maxDelay);
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <int maxDelay>
|
FeedforwardCombFilter::FeedforwardCombFilter(int maxDelay, int delay, float gain)
|
||||||
void FeedforwardCombFilter<maxDelay>::reset()
|
: DelayFilter(maxDelay, delay, gain)
|
||||||
{
|
{}
|
||||||
index = 0;
|
|
||||||
memset(buffer, 0, (sizeof (float)) * maxDelay);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <int maxDelay>
|
float FeedforwardCombFilter::feed(float value)
|
||||||
float FeedforwardCombFilter<maxDelay>::feed(float value)
|
|
||||||
{
|
{
|
||||||
float y = gain0 * value + gainM * buffer[index];
|
float y = gain * value + gain * buffer[index];
|
||||||
buffer[index] = value;
|
buffer[index] = value;
|
||||||
index = (index + 1) % delay;
|
index = (index + 1) % delay;
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int maxDelay>
|
//////////////////////////////////////////////////////////////////////
|
||||||
AllpassFilter<maxDelay>::AllpassFilter(int delay, float gain0, float gainM)
|
// AllpassFilter
|
||||||
: delay(delay), gain0(gain0), gainM(gainM)
|
//////////////////////////////////////////////////////////////////////
|
||||||
{
|
|
||||||
//buffer = (float *)malloc((sizeof (float)) * maxDelay);
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <int maxDelay>
|
AllpassFilter::AllpassFilter(int maxDelay, int delay, float gain)
|
||||||
void AllpassFilter<maxDelay>::reset()
|
: DelayFilter(maxDelay, delay, gain)
|
||||||
{
|
{}
|
||||||
index = 0;
|
|
||||||
memset(buffer, 0, (sizeof (float)) * maxDelay);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <int maxDelay>
|
float AllpassFilter::feed(float x)
|
||||||
float AllpassFilter<maxDelay>::feed(float x)
|
|
||||||
{
|
{
|
||||||
float v = x + -gainM * buffer[index];
|
float v = x + -gain * buffer[index];
|
||||||
float y = buffer[index] + gain0 * v;
|
float y = buffer[index] + gain * v;
|
||||||
buffer[index] = v;
|
buffer[index] = v;
|
||||||
index = (index + 1) % delay;
|
index = (index + 1) % delay;
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AudioInstance {
|
//////////////////////////////////////////////////////////////////////
|
||||||
int audio_index;
|
// Reverberators
|
||||||
AudioBuffer * audio_buffer;
|
//////////////////////////////////////////////////////////////////////
|
||||||
uint32_t sample_index;
|
|
||||||
uint32_t tail_index;
|
|
||||||
uint32_t fadeout_end;
|
|
||||||
uint32_t fadeout_index;
|
|
||||||
poem::poem const * poem;
|
|
||||||
};
|
|
||||||
|
|
||||||
FBReverb::FBReverb()
|
void Reverb::reset()
|
||||||
: cf{FBCF(3229, 1.0f, 0.733f), // 1687
|
|
||||||
FBCF(3079, 1.0f, 0.802f), // 1601
|
|
||||||
FBCF(3943, 1.0f, 0.753f), // 2053
|
|
||||||
FBCF(4327, 1.0f, 0.733f), // 2251
|
|
||||||
}
|
|
||||||
, ap{AP(661, 0.7f, 0.7f), // 347
|
|
||||||
AP(257, 0.7f, 0.7f), // 113
|
|
||||||
AP(71, 0.7f, 0.7f), // 37
|
|
||||||
}
|
|
||||||
{ }
|
|
||||||
|
|
||||||
void FBReverb::reset()
|
|
||||||
{
|
{
|
||||||
for (int i = 0; i < cfCount; i++)
|
for (int i = 0; i < cfCount; i++)
|
||||||
cf[i].reset();
|
cf[i].reset();
|
||||||
|
|
||||||
for (int i = 0; i < apCount; i++)
|
for (int i = 0; i < apCount; i++)
|
||||||
ap[i].reset();
|
ap[i].reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
lr FBReverb::feed(float x)
|
lr Reverb::feed(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(x);
|
||||||
@ -151,54 +127,54 @@ namespace audio {
|
|||||||
return {a, b};
|
return {a, b};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reverb::Reverb(DelayFilter * cf, DelayFilter * ap)
|
||||||
FFReverb::FFReverb()
|
: cf(cf), ap(ap)
|
||||||
: cf{FFCF{9209, 1.0f, 0.742f},
|
|
||||||
FFCF{9601, 1.0f, 0.733f},
|
|
||||||
FFCF{10369, 1.0f, 0.715f},
|
|
||||||
FFCF{11131, 1.0f, 0.697f},
|
|
||||||
}
|
|
||||||
, ap{AP{2017, 0.7f, 0.7f},
|
|
||||||
AP{647, 0.7f, 0.7f},
|
|
||||||
AP{137, 0.7f, 0.7f},
|
|
||||||
}
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void FFReverb::reset()
|
static FFCF forwardCF[4]{FFCF{15000, 9209, 0.742f},
|
||||||
{
|
FFCF{15000, 9601, 0.733f},
|
||||||
for (int i = 0; i < __cfCount; i++) {
|
FFCF{15000, 10369, 0.715f},
|
||||||
printf("reset cf %d\n", i);
|
FFCF{15000, 11131, 0.697f}};
|
||||||
cf[i].reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < apCount; i++)
|
static AP forwardAP[3]{AP{2500, 2017, 0.7f},
|
||||||
ap[i].reset();
|
AP{2500, 647, 0.7f},
|
||||||
}
|
AP{2500, 137, 0.7f}};
|
||||||
|
Reverb forwardReverb(forwardCF, forwardAP);
|
||||||
|
|
||||||
lr FFReverb::feed(float x)
|
static FBCF backCF[4]{FBCF{10000, 3229, 0.733f}, // 1687
|
||||||
{
|
FBCF{10000, 3079, 0.802f}, // 1601
|
||||||
for (int i = 0; i < apCount; i++) {
|
FBCF{10000, 3943, 0.753f}, // 2053
|
||||||
x = ap[i].feed(x);
|
FBCF{10000, 4327, 0.733f}}; // 2251
|
||||||
}
|
static AP backAP[3]{AP{1500, 661, 0.7f}, // 347
|
||||||
|
AP{1500, 257, 0.7f}, // 113
|
||||||
float x0 = cf[0].feed(x);
|
AP{1500, 71, 0.7f}};
|
||||||
float x1 = cf[1].feed(x);
|
Reverb backReverb(backCF, backAP);
|
||||||
float x2 = cf[2].feed(x);
|
|
||||||
float x3 = cf[3].feed(x);
|
|
||||||
|
|
||||||
float s0 = x0 + x1 + x2 + x3;
|
|
||||||
//float s0 = x0 + x1 + x2;
|
|
||||||
return {s0, s0};
|
|
||||||
}
|
|
||||||
|
|
||||||
int reverbIndex = 0;
|
int reverbIndex = 0;
|
||||||
FBReverb fbreverb;
|
Reverb * reverbs[] = {
|
||||||
FFReverb ffreverb;
|
&backReverb,
|
||||||
|
&forwardReverb,
|
||||||
|
};
|
||||||
|
int const reverbsCount = (sizeof (reverbs)) / (sizeof (reverbs[0]));
|
||||||
|
|
||||||
float dryGain = 1.0;
|
float dryGain = 1.0;
|
||||||
float wetGain = 0.25;
|
float wetGain = 0.25;
|
||||||
float mixChannelGain[mixChannelCount];
|
float mixChannelGain[mixChannelCount];
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// AudioInstance
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
struct AudioInstance {
|
||||||
|
int audio_index;
|
||||||
|
AudioBuffer * audio_buffer;
|
||||||
|
uint32_t sample_index;
|
||||||
|
uint32_t tail_index;
|
||||||
|
uint32_t fadeout_end;
|
||||||
|
uint32_t fadeout_index;
|
||||||
|
poem::poem const * poem;
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
static SDL_AudioStream * audio_stream;
|
static SDL_AudioStream * audio_stream;
|
||||||
@ -221,8 +197,8 @@ namespace audio {
|
|||||||
SDL_ResumeAudioStreamDevice(audio_stream);
|
SDL_ResumeAudioStreamDevice(audio_stream);
|
||||||
|
|
||||||
audio_instances_count = 0;
|
audio_instances_count = 0;
|
||||||
fbreverb.reset();
|
for (int i = 0; i < reverbsCount; i++)
|
||||||
ffreverb.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;
|
||||||
@ -566,12 +542,8 @@ namespace audio {
|
|||||||
float value = channel_buffer[mix_channel::voice][i * channels + 0];
|
float value = channel_buffer[mix_channel::voice][i * channels + 0];
|
||||||
|
|
||||||
lr wet;
|
lr wet;
|
||||||
if (reverbIndex == 0) {
|
assert(reverbIndex >= 0 && reverbIndex < reverbsCount);
|
||||||
wet = fbreverb.feed(value);
|
wet = reverbs[reverbIndex]->feed(value);
|
||||||
}
|
|
||||||
else {
|
|
||||||
wet = ffreverb.feed(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;
|
channel_buffer[mix_channel::voice][i * channels + 0] = left;
|
||||||
|
|||||||
@ -1000,6 +1000,12 @@ int main()
|
|||||||
// 2.17
|
// 2.17
|
||||||
printf("audio_time %f\n", audio_time);
|
printf("audio_time %f\n", audio_time);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// ui
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ui::init();
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// interpreter
|
// interpreter
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
111
src/ui.cpp
111
src/ui.cpp
@ -12,76 +12,13 @@ namespace ui
|
|||||||
constexpr int combLeft = 700;
|
constexpr int combLeft = 700;
|
||||||
constexpr int outputMixLeft = 1000;
|
constexpr int outputMixLeft = 1000;
|
||||||
|
|
||||||
#define BREVERB audio::fbreverb
|
|
||||||
#define FREVERB audio::ffreverb
|
|
||||||
|
|
||||||
widget::DelayGainSlider fap[3] {
|
struct ap_comb {
|
||||||
widget::DelayGainSlider("allpass 0",
|
widget::DelayGainSlider ap[3];
|
||||||
allpassLeft, top + ySpace * 0,
|
widget::DelayGainSlider comb[4];
|
||||||
1, 2500, &FREVERB.ap[0].delay,
|
|
||||||
0.0, 1.0, &FREVERB.ap[0].gain0, &FREVERB.ap[0].gainM),
|
|
||||||
widget::DelayGainSlider("allpass 1",
|
|
||||||
allpassLeft, top + ySpace * 1,
|
|
||||||
1, 2500, &FREVERB.ap[1].delay,
|
|
||||||
0.0, 1.0, &FREVERB.ap[1].gain0, &FREVERB.ap[1].gainM),
|
|
||||||
widget::DelayGainSlider("allpass 2",
|
|
||||||
allpassLeft, top + ySpace * 2,
|
|
||||||
1, 2500, &FREVERB.ap[2].delay,
|
|
||||||
0.0, 1.0, &FREVERB.ap[2].gain0, &FREVERB.ap[2].gainM),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
widget::DelayGainSlider fcomb[4] {
|
ap_comb reverberatorSliders[2];
|
||||||
widget::DelayGainSlider("comb 0",
|
|
||||||
combLeft, top + ySpace * 0,
|
|
||||||
100, 15000, &FREVERB.cf[0].delay,
|
|
||||||
0.0, 1.0, &FREVERB.cf[0].gain0, &FREVERB.cf[0].gainM),
|
|
||||||
widget::DelayGainSlider("comb 1",
|
|
||||||
combLeft, top + ySpace * 1,
|
|
||||||
100, 15000, &FREVERB.cf[1].delay,
|
|
||||||
0.0, 1.0, &FREVERB.cf[1].gain0, &FREVERB.cf[1].gainM),
|
|
||||||
widget::DelayGainSlider("comb 2",
|
|
||||||
combLeft, top + ySpace * 2,
|
|
||||||
100, 15000, &FREVERB.cf[2].delay,
|
|
||||||
0.0, 1.0, &FREVERB.cf[2].gain0, &FREVERB.cf[2].gainM),
|
|
||||||
widget::DelayGainSlider("comb 3",
|
|
||||||
combLeft, top + ySpace * 3,
|
|
||||||
100, 15000, &FREVERB.cf[3].delay,
|
|
||||||
0.0, 1.0, &FREVERB.cf[3].gain0, &FREVERB.cf[3].gainM),
|
|
||||||
};
|
|
||||||
|
|
||||||
widget::DelayGainSlider bap[3] {
|
|
||||||
widget::DelayGainSlider("allpass 0",
|
|
||||||
allpassLeft, top + ySpace * 0,
|
|
||||||
1, 2500, &BREVERB.ap[0].delay,
|
|
||||||
0.0, 1.0, &BREVERB.ap[0].gain0, &BREVERB.ap[0].gainM),
|
|
||||||
widget::DelayGainSlider("allpass 1",
|
|
||||||
allpassLeft, top + ySpace * 1,
|
|
||||||
1, 2500, &BREVERB.ap[1].delay,
|
|
||||||
0.0, 1.0, &BREVERB.ap[1].gain0, &BREVERB.ap[1].gainM),
|
|
||||||
widget::DelayGainSlider("allpass 2",
|
|
||||||
allpassLeft, top + ySpace * 2,
|
|
||||||
1, 2500, &BREVERB.ap[2].delay,
|
|
||||||
0.0, 1.0, &BREVERB.ap[2].gain0, &BREVERB.ap[2].gainM),
|
|
||||||
};
|
|
||||||
|
|
||||||
widget::DelayGainSlider bcomb[4] {
|
|
||||||
widget::DelayGainSlider("comb 0",
|
|
||||||
combLeft, top + ySpace * 0,
|
|
||||||
100, 15000, &BREVERB.cf[0].delay,
|
|
||||||
0.0, 1.0, &BREVERB.cf[0].gain0, &BREVERB.cf[0].gainM),
|
|
||||||
widget::DelayGainSlider("comb 1",
|
|
||||||
combLeft, top + ySpace * 1,
|
|
||||||
100, 15000, &BREVERB.cf[1].delay,
|
|
||||||
0.0, 1.0, &BREVERB.cf[1].gain0, &BREVERB.cf[1].gainM),
|
|
||||||
widget::DelayGainSlider("comb 2",
|
|
||||||
combLeft, top + ySpace * 2,
|
|
||||||
100, 15000, &BREVERB.cf[2].delay,
|
|
||||||
0.0, 1.0, &BREVERB.cf[2].gain0, &BREVERB.cf[2].gainM),
|
|
||||||
widget::DelayGainSlider("comb 3",
|
|
||||||
combLeft, top + ySpace * 3,
|
|
||||||
100, 15000, &BREVERB.cf[3].delay,
|
|
||||||
0.0, 1.0, &BREVERB.cf[3].gain0, &BREVERB.cf[3].gainM),
|
|
||||||
};
|
|
||||||
|
|
||||||
widget::Slider<float, false> dryGain("dry gain",
|
widget::Slider<float, false> dryGain("dry gain",
|
||||||
outputMixLeft, top + yMixSpace * 0, 150, 14,
|
outputMixLeft, top + yMixSpace * 0, 150, 14,
|
||||||
@ -118,6 +55,38 @@ namespace ui
|
|||||||
120, 0,
|
120, 0,
|
||||||
&audio::reverbIndex);
|
&audio::reverbIndex);
|
||||||
|
|
||||||
|
void init()
|
||||||
|
{
|
||||||
|
static const char * allpassLabels[3] = {
|
||||||
|
"allpass 0",
|
||||||
|
"allpass 1",
|
||||||
|
"allpass 2",
|
||||||
|
};
|
||||||
|
static const char * combLabels[4] = {
|
||||||
|
"comb 0",
|
||||||
|
"comb 1",
|
||||||
|
"comb 2",
|
||||||
|
"comb 3",
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
for (int j = 0; j < 3; j++) {
|
||||||
|
reverberatorSliders[i].ap[j] =
|
||||||
|
widget::DelayGainSlider(allpassLabels[j],
|
||||||
|
allpassLeft, top + ySpace * j,
|
||||||
|
1, audio::reverbs[i]->ap[j].maxDelay, &audio::reverbs[i]->ap[j].delay,
|
||||||
|
0.0, 1.0, &audio::reverbs[i]->ap[j].gain);
|
||||||
|
}
|
||||||
|
for (int j = 0; j < 4; j++) {
|
||||||
|
reverberatorSliders[i].comb[j] =
|
||||||
|
widget::DelayGainSlider(combLabels[j],
|
||||||
|
combLeft, top + ySpace * j,
|
||||||
|
100, audio::reverbs[i]->cf[j].maxDelay, &audio::reverbs[i]->cf[j].delay,
|
||||||
|
0.0, 1.0, &audio::reverbs[i]->cf[j].gain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void draw(MappedInstanceData<SolidInstance> & data,
|
void draw(MappedInstanceData<SolidInstance> & data,
|
||||||
MappedInstanceData<font::BitmapInstance> & fontData)
|
MappedInstanceData<font::BitmapInstance> & fontData)
|
||||||
{
|
{
|
||||||
@ -127,8 +96,8 @@ namespace ui
|
|||||||
0x80000000,
|
0x80000000,
|
||||||
});
|
});
|
||||||
|
|
||||||
widget::DelayGainSlider * ap = (audio::reverbIndex == 0) ? bap : fap;
|
widget::DelayGainSlider * ap = reverberatorSliders[audio::reverbIndex].ap;
|
||||||
widget::DelayGainSlider * comb = (audio::reverbIndex == 0) ? bcomb : fcomb;
|
widget::DelayGainSlider * comb = reverberatorSliders[audio::reverbIndex].comb;
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 0; i < 3; i++)
|
||||||
ap[i].draw(data, fontData);
|
ap[i].draw(data, fontData);
|
||||||
@ -148,8 +117,8 @@ namespace ui
|
|||||||
|
|
||||||
void update(float mx, float my, bool mLeft, bool mEdge)
|
void update(float mx, float my, bool mLeft, bool mEdge)
|
||||||
{
|
{
|
||||||
widget::DelayGainSlider * ap = (audio::reverbIndex == 0) ? bap : fap;
|
widget::DelayGainSlider * ap = reverberatorSliders[audio::reverbIndex].ap;
|
||||||
widget::DelayGainSlider * comb = (audio::reverbIndex == 0) ? bcomb : fcomb;
|
widget::DelayGainSlider * comb = reverberatorSliders[audio::reverbIndex].comb;
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 0; i < 3; i++)
|
||||||
ap[i].update(mx, my, mLeft, mEdge);
|
ap[i].update(mx, my, mLeft, mEdge);
|
||||||
|
|||||||
@ -179,15 +179,13 @@ namespace ui::widget
|
|||||||
drawStringCentered(fontData, delay.slider.left + delay.slider.width / 2, delay.slider.top - 16, label);
|
drawStringCentered(fontData, delay.slider.left + delay.slider.width / 2, delay.slider.top - 16, label);
|
||||||
|
|
||||||
delay.draw(data, fontData);
|
delay.draw(data, fontData);
|
||||||
gain0.draw(data, fontData);
|
gain.draw(data, fontData);
|
||||||
gainM.draw(data, fontData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DelayGainSlider::update(float mx, float my, bool mLeft, bool mEdge)
|
void DelayGainSlider::update(float mx, float my, bool mLeft, bool mEdge)
|
||||||
{
|
{
|
||||||
delay.update(mx, my, mLeft, mEdge);
|
delay.update(mx, my, mLeft, mEdge);
|
||||||
gain0.update(mx, my, mLeft, mEdge);
|
gain.update(mx, my, mLeft, mEdge);
|
||||||
gainM.update(mx, my, mLeft, mEdge);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int optionCount>
|
template <int optionCount>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user