Reproducing the Shimmer instability

pull/495/head
abscisys 2 years ago
parent 0cec94f491
commit 55feb0f794
  1. 16
      src/debug.hpp
  2. 11
      src/fx_delay.cpp
  3. 2
      src/fx_delay.h
  4. 8
      src/mixing_console.hpp
  5. 23
      src/test/Makefile
  6. 229
      src/test/beta.cpp
  7. 2
      src/test/test_cpp.cpp
  8. 12
      src/test/test_cpp_performance.cpp
  9. 3
      src/test/test_framework.cpp
  10. 18
      src/test/test_fx_components.cpp
  11. 46
      src/test/test_fx_helper.cpp
  12. 13
      src/test/test_fx_helper.h
  13. 598
      src/test/test_fx_mixing_console.cpp
  14. 136
      src/test/test_fx_plate_reverb.cpp
  15. 18
      src/test/test_fx_rack.cpp
  16. 182
      src/test/test_fx_shimmer_reverb.cpp
  17. 4
      src/test/wave.h
  18. 11
      src/test/wavein.cpp
  19. 2
      src/test/waveout.cpp

@ -81,6 +81,11 @@ public:\
code\
}
#define DUMP(clazz, out) clazz->dump(out, true, "")
#define DUMP2(clazz, out, tag) clazz->dump(out, true, tag)
#define FAST_DUMP(clazz, out, tag) clazz->dump(out, false, "")
#define FAST_DUMP2(clazz, out, tag) clazz->dump(out, false, tag)
#define IMPLEMENT_INSPECT(code) \
public:\
virtual size_t inspect(ValueInpector inspector, bool deepInspection = true, const std::string& tag = "") const override\
@ -89,7 +94,9 @@ public:\
}
#define INSPECT(obj, inspector) obj->inspect(inspector, true)
#define INSPECT2(obj, inspector, deepInspection) obj->inpect(inspector, deepInspection)
#define INSPECT2(obj, inspector, deepInspection) obj->inspect(inspector, deepInspection)
#define FULL_INSPECT(obj, deepInspection) obj->inspect(fullInspector, deepInspection)
#define FULL_INSPECT2(obj, deepInspection, tag) obj->inspect(fullInspector, deepInspection, tag)
#else
@ -97,7 +104,14 @@ public:\
#define IMPLEMENT_DUMP(code)
#define IMPLEMENT_INSPECT(code)
#define DUMP(clazz, out)
#define DUMP2(clazz, out, tag)
#define FAST_DUMP(clazz, out, tag)
#define FAST_DUMP2(clazz, out, tag)
#define INSPECT(obj, inspector)
#define INSPECT2(obj, inspector, deepInspection)
#define FULL_INSPECT(obj, deepInspection)
#define FULL_INSPECT2(obj, deepInspection, tag)
#endif

@ -88,12 +88,15 @@ void Delay::reset()
void Delay::processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR)
{
static const float32_t max_delay_time = MAX_DELAY_TIME * this->getSamplingRate();
float32_t jitter_ratio = this->jitter_generator_.process();
float32_t jitter_delay_time = 0.0f;
if(jitter_ratio != 0.0f)
if(this->jitter_amount_ != 0.0f)
{
jitter_ratio *= this->jitter_amount_;
jitter_delay_time = MAX_FLUTTER_DELAY_TIME * jitter_ratio * this->getSamplingRate();
float32_t jitter_ratio = this->jitter_generator_.process();
if(jitter_ratio != 0.0f)
{
jitter_ratio *= this->jitter_amount_;
jitter_delay_time = MAX_FLUTTER_DELAY_TIME * jitter_ratio * this->getSamplingRate();
}
}
// this->filter_.setCutoffChangeRatio(jitter_ratio);

@ -22,8 +22,6 @@
#include "fx_components.h"
#include "fx_svf.h"
#include <random>
class Delay : public FXElement
{
DISALLOW_COPY_AND_ASSIGN(Delay);

@ -383,7 +383,7 @@ template<size_t nb_inputs>
void MixingConsole<nb_inputs>::setSendLevel(size_t in, MixerOutput fx, float32_t lvl)
{
assert(in < nb_inputs);
assert(fx < kFXCount);
assert(fx < MixerOutput::kFXCount);
this->setLevel(in, fx, lvl);
}
@ -440,8 +440,8 @@ void MixingConsole<nb_inputs>::setInputSampleBuffer(size_t in, float32_t* sample
template<size_t nb_inputs>
void MixingConsole<nb_inputs>::setReturnLevel(MixerOutput ret, MixerOutput dest, float32_t lvl)
{
assert(ret < (kFXCount - 1));
assert(dest < kFXCount);
assert(ret < (MixerOutput::kFXCount - 1));
assert(dest < MixerOutput::kFXCount);
if(ret == dest)
{
@ -455,7 +455,7 @@ void MixingConsole<nb_inputs>::setReturnLevel(MixerOutput ret, MixerOutput dest,
template<size_t nb_inputs>
void MixingConsole<nb_inputs>::setReturnSample(MixerOutput ret, float32_t sampleL, float32_t sampleR)
{
assert(ret < (kFXCount - 1));
assert(ret < (MixerOutput::kFXCount - 1));
this->setSample(nb_inputs + ret, sampleL, sampleR);
}

@ -16,7 +16,6 @@ INCLUDES = -I../../CMSIS_5/CMSIS/DSP/Include/ \
LD := g++
LIBS := -lm -lstdc++ -lgtest -lpthread
TST_SRCS := $(filter-out waveplay.cpp, $(filter-out beta.cpp, $(wildcard *.cpp)))
FX__SRCS := ../fx.cpp
FX__SRCS += ../fx_components.cpp
FX__SRCS += ../fx_svf.cpp
@ -31,17 +30,28 @@ FX__SRCS += ../fx_shimmer_reverb.cpp
FX__SRCS += ../fx_dry.cpp
FX__SRCS += ../fx_rack.cpp
TST_OBJS = $(TST_SRCS:%.cpp=$(OBJDIR)/%.o)
TST_SRCS := $(filter-out waveplay.cpp, $(filter-out beta.cpp, $(wildcard *.cpp)))
BETASRCS := beta.cpp
BETASRCS += arm_functions.cpp
BETASRCS += wavein.cpp
BETASRCS += waveout.cpp
BETASRCS += test_fx_helper.cpp
FX__OBJS = $(patsubst ../%, $(OBJDIR)/%, $(FX__SRCS:.cpp=.o))
TST_OBJS = $(TST_SRCS:%.cpp=$(OBJDIR)/%.o)
BETAOBJS = $(BETASRCS:%.cpp=$(OBJDIR)/%.o)
all: $(EXE) test
bin: $(EXE)
test: $(EXE) $(OUTPUT_FOLDER)
rm -f $(OUTPUT_FOLDER)/*
rm -rf $(OUTPUT_FOLDER)/*
./$(EXE)
test-debug: $(EXE) $(OUTPUT_FOLDER)
rm -f $(OUTPUT_FOLDER)/*
rm -rf $(OUTPUT_FOLDER)/*
valgrind --leak-check=full --leak-resolution=high --show-leak-kinds=all --xtree-leak=yes --show-mismatched-frees=yes --error-limit=no --log-file=$(OUTPUT_FOLDER)/valgrind-analysis-results.txt ./$(EXE)
$(OBJDIR):
@ -59,9 +69,8 @@ $(OBJDIR)/%.o: ../%.cpp $(OBJDIR)
$(EXE): $(TST_OBJS) $(FX__OBJS)
$(LD) $(CXXFLAGS) $(call wildcard,$(TST_OBJS)) $(call wildcard,$(FX__OBJS)) -o $@ $(LIBS)
$(BETA): $(FX__OBJS) beta.cpp
$(CXX) $(CXXFLAGS) $(DEFINES) $(INCLUDES) -c beta.cpp -o $(OBJDIR)/beta.o
$(LD) $(CXXFLAGS) $(call wildcard,$(OBJDIR)/beta.o) $(call wildcard,$(OBJDIR)/arm_functions.o) $(call wildcard,$(FX__OBJS)) -o $@ $(LIBS)
$(BETA): $(BETAOBJS) beta.cpp
$(LD) $(CXXFLAGS) $(BETAOBJS) $(call wildcard,$(FX__OBJS)) -o $@ $(LIBS)
clean:
rm -rf *.o $(OBJDIR) $(EXE) $(OUTPUT_FOLDER)

@ -1,55 +1,216 @@
#include "../mixing_console_constants.h"
#include <gtest/gtest.h>
#include <cmath>
#include <iostream>
#include "test_fx_helper.h"
#include "../mixing_console.hpp"
#include <iostream>
TEST(BetaTest, WavefileSamplesBoundariesTest)
{
const testing::TestInfo* test_info = testing::UnitTest::GetInstance()->current_test_info();
std::string full_test_name = test_info->test_case_name();
full_test_name += ".";
full_test_name += test_info->name();
using namespace std;
size_t size;
float32_t** samples = readWaveFile(AUDIO_SOURCE_FILE, size);
typedef MixingConsole<8> Mixer;
size_t nb_errors = 0;
for(size_t i = 0; i < size; ++i)
{
nb_errors += fullInspector(full_test_name + ".rawWaveSampleTest", samples[0][i], -1.0f, 1.0f, true);
nb_errors += fullInspector(full_test_name + ".rawWaveSampleTest", samples[1][i], -1.0f, 1.0f, true);
}
EXPECT_EQ(0, nb_errors) << full_test_name << ".rawWaveSampleTest";
int main()
delete[] samples[0];
delete[] samples[1];
delete[] samples;
}
typedef MixingConsole<1> Mixer;
TEST(BetaTest, MixingConsoleShortBuffer)
{
Mixer* mixer = new Mixer(44100.0f, 4);
// DUMP2(mixer, cout, "Post creation");
static const float32_t SINPI_4 = std::sqrt(2.0f) / 2.0f;
mixer->reset();
DUMP2(mixer, cout, "Post creation");
const testing::TestInfo* test_info = testing::UnitTest::GetInstance()->current_test_info();
std::string full_test_name = test_info->test_case_name();
full_test_name += ".";
full_test_name += test_info->name();
const size_t size = 10;
Mixer* mixer = new Mixer(SAMPLING_FREQUENCY, size);
mixer->setChannelLevel(0, 1.0f);
// DUMP2(mixer, cout, "Post setChannelLevel");
mixer->setPan(0, 0.5f);
mixer->setSendLevel(0, MixerOutput::MainOutput, 1.0f);
float32_t inSamples[size];
for(size_t s = 0; s < size; ++s) inSamples[s] = getRandomValue();
float32_t outSamples[2][size];
memset(outSamples[0], 0, size * sizeof(float32_t));
memset(outSamples[1], 0, size * sizeof(float32_t));
mixer->setInputSampleBuffer(0, inSamples);
EXPECT_EQ(0, FULL_INSPECT(mixer, true));
mixer->process(outSamples[0], outSamples[1]);
EXPECT_EQ(0, FULL_INSPECT(mixer, true));
for(size_t s = 0; s < size; ++s)
{
EXPECT_EQ(outSamples[0][s], outSamples[1][s]);
EXPECT_EQ(outSamples[0][s], inSamples[s] * SINPI_4);
}
delete mixer;
}
TEST(BetaTest, MixingConsoleShimmerShortBuffer)
{
const testing::TestInfo* test_info = testing::UnitTest::GetInstance()->current_test_info();
std::string full_test_name = test_info->test_case_name();
full_test_name += ".";
full_test_name += test_info->name();
const size_t size = 10;
Mixer* mixer = new Mixer(SAMPLING_FREQUENCY, size);
mixer->setChannelLevel(0, 1.0f);
mixer->setPan(0, 0.5f);
// DUMP2(mixer, cout, "Post setPan");
float32_t samples[] = {0.0f, 0.0f, 0.0f, 0.0f};
mixer->setInputSampleBuffer(0, samples);
// DUMP2(mixer, cout, "Post setInputSampleBuffer");
mixer->getShimmerReverb()->setInputGain(0.35f);
mixer->getShimmerReverb()->setTime(0.69f);
mixer->getShimmerReverb()->setDiffusion(0.7f);
mixer->getShimmerReverb()->setLP(0.8f);
mixer->setSendLevel(0, MixerOutput::MainOutput, 0.4f);
mixer->setSendLevel(0, MixerOutput::FX_ShimmerReverb, 1.0f);
mixer->setReturnLevel(MixerOutput::FX_ShimmerReverb, MixerOutput::MainOutput, 0.6f);
float32_t inSamples[size];
for(size_t s = 0; s < size; ++s) inSamples[s] = getRandomValue();
float32_t outSamples[2][size];
memset(outSamples[0], 0, size * sizeof(float32_t));
memset(outSamples[1], 0, size * sizeof(float32_t));
mixer->setInputSampleBuffer(0, inSamples);
EXPECT_EQ(0, FULL_INSPECT(mixer, true));
// FAST_DUMP(mixer, std::cerr, full_test_name + ".setInputSampleBuffer");
mixer->process(outSamples[0], outSamples[1]);
EXPECT_EQ(0, FULL_INSPECT(mixer, true));
// FAST_DUMP(mixer, std::cerr, full_test_name + ".process");
delete mixer;
}
TEST(BetaTest, MixingConsoleDrySamplesBoundariesTest)
{
const testing::TestInfo* test_info = testing::UnitTest::GetInstance()->current_test_info();
std::string full_test_name = test_info->test_case_name();
full_test_name += ".";
full_test_name += test_info->name();
size_t size;
float32_t** inSamples =readWaveFile(AUDIO_SOURCE_FILE, size);
Mixer* mixer = new Mixer(SAMPLING_FREQUENCY, size);
mixer->reset();
FULL_INSPECT2(mixer, true, "Mixer.reset");
mixer->setChannelLevel(0, 1.0f);
mixer->setPan(0, 0.5f);
mixer->setSendLevel(0, MixerOutput::MainOutput, 1.0f);
// DUMP2(mixer, cout, "Post setSendLevel - full dry");
float32_t outL[4];
float32_t outR[4];
mixer->process(outL, outR);
DUMP2(mixer, cout, "Post process");
cout.precision(5);
cout << std::fixed;
cout << "+ outL: " << outL[0] << " - " << outL[1] << endl;
cout << "+ outR: " << outR[0] << " - " << outR[1] << endl;
mixer->setInputSampleBuffer(0, inSamples[0]);
float32_t** outSamples = new float32_t*[2];
outSamples[0] = new float32_t[size];
outSamples[1] = new float32_t[size];
memset(outSamples[0], 0, size * sizeof(float32_t));
memset(outSamples[1], 0, size * sizeof(float32_t));
mixer->process(outSamples[0], outSamples[1]);
size_t nb_errors = 0;
for(size_t i = 0; i < size; ++i)
{
nb_errors += fullInspector(full_test_name + ".outputSampleTest", inSamples[0][i], -1.0f, 1.0f, true);
nb_errors += fullInspector(full_test_name + ".outputSampleTest", inSamples[1][i], -1.0f, 1.0f, true);
}
EXPECT_EQ(0, nb_errors) << full_test_name << ".outputSampleTest";
delete[] inSamples[0];
delete[] inSamples[1];
delete[] inSamples;
delete[] outSamples[0];
delete[] outSamples[1];
delete[] outSamples;
delete mixer;
}
TEST(BetaTest, MixingConsoleShimmerSamplesBoundariesTest)
{
const testing::TestInfo* test_info = testing::UnitTest::GetInstance()->current_test_info();
std::string full_test_name = test_info->test_case_name();
full_test_name += ".";
full_test_name += test_info->name();
size_t size;
float32_t** inSamples =readWaveFile(AUDIO_SOURCE_FILE, size);
mixer->setSendLevel(0, MixerOutput::FX_Tube, 1.0f);
mixer->setSendLevel(0, MixerOutput::FX_Delay, 1.0f);
mixer->setSendLevel(0, MixerOutput::FX_PlateReverb, 1.0f);
float32_t** outSamples = new float32_t*[2];
outSamples[0] = new float32_t[size];
outSamples[1] = new float32_t[size];
memset(outSamples[0], 0, size * sizeof(float32_t));
memset(outSamples[1], 0, size * sizeof(float32_t));
mixer->setReturnLevel(MixerOutput::FX_Tube, MixerOutput::FX_Orbitone, 1.0f);
mixer->setReturnLevel(MixerOutput::FX_Orbitone, MixerOutput::MainOutput, 0.5f);
mixer->setReturnLevel(MixerOutput::FX_Orbitone, MixerOutput::FX_PlateReverb, 1.0f);
mixer->setReturnLevel(MixerOutput::FX_Delay, MixerOutput::MainOutput, 0.5f);
mixer->setReturnLevel(MixerOutput::FX_PlateReverb, MixerOutput::MainOutput, 0.5f);
// DUMP2(mixer, cout, "Post setSendLevel & setReturnLevel");
Mixer* mixer = new Mixer(SAMPLING_FREQUENCY, size);
mixer->reset();
mixer->setChannelLevel(0, 1.0f);
mixer->setPan(0, 0.5f);
mixer->setSendLevel(0, MixerOutput::MainOutput, 0.4f);
mixer->setSendLevel(0, MixerOutput::FX_ShimmerReverb, 1.0f);
mixer->setReturnLevel(MixerOutput::FX_ShimmerReverb, MixerOutput::MainOutput, 0.6f);
mixer->getShimmerReverb()->setMute(false);
mixer->getShimmerReverb()->setInputGain(0.35);
mixer->getShimmerReverb()->setTime(0.65);
mixer->getShimmerReverb()->setDiffusion(0.8);
mixer->getShimmerReverb()->setLP(0.7f);
mixer->setInputSampleBuffer(0, inSamples[0]);
mixer->process(outSamples[0], outSamples[1]);
FAST_DUMP(mixer, std::cerr, full_test_name);
//EXPECT_EQ(0, FULL_INSPECT2(mixer, true, full_test_name + "Mixer.process")) << full_test_name << "Mixer.process";
saveWaveFile(getResultFile(full_test_name + ".wav", true), outSamples[0], outSamples[1], size, static_cast<unsigned>(SAMPLING_FREQUENCY), 16);
size_t nb_errors = 0;
for(size_t i = 0; i < size; ++i)
{
nb_errors += fullInspector(full_test_name + ".outputSampleTest", inSamples[0][i], -1.0f, 1.0f, true);
nb_errors += fullInspector(full_test_name + ".outputSampleTest", inSamples[1][i], -1.0f, 1.0f, true);
}
EXPECT_EQ(0, nb_errors) << full_test_name << ".outputSampleTest";
delete[] inSamples[0];
delete[] inSamples[1];
delete[] inSamples;
delete[] outSamples[0];
delete[] outSamples[1];
delete[] outSamples;
delete mixer;
}
return 0;
}
int main(int argc, char **argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

@ -1,8 +1,6 @@
#include <gtest/gtest.h>
#include "../fx_components.h"
#include <chrono>
#include <fstream>
int nb = 0;

@ -61,9 +61,13 @@ TEST(CppPerformance, LFOPerformance_ComplexLFO_FastLFO)
TEST(CppPerformance, FastLFOTuning)
{
float32_t freq = 5.0f;
const testing::TestInfo* test_info = testing::UnitTest::GetInstance()->current_test_info();
std::string full_test_name = test_info->test_case_name();
full_test_name += ".";
full_test_name += test_info->name();
size_t NB = static_cast<size_t>(1.0f * SAMPLING_FREQUENCY);
float32_t freq = 5.0f;
FastLFO lfo1(SAMPLING_FREQUENCY, freq, 440.0f);
lfo1.setFrequency(freq);
@ -71,8 +75,8 @@ TEST(CppPerformance, FastLFOTuning)
ComplexLFO lfo2(SAMPLING_FREQUENCY, freq, 440.0f);
lfo2.setFrequency(freq);
std::ofstream out(getResultFile("CppPerformance.FastLFOTuning-data.csv"));
setupOuputStreamFocCSV(out);
std::ofstream out(getResultFile(full_test_name + ".FastLFOTuning-data.csv", true));
setupOuputStreamForCSV(out);
out << "index;FastLFO;ComplexLFO" << std::endl;
for(size_t i = 0; i < NB; ++i)
{

@ -1,14 +1,13 @@
#include <gtest/gtest.h>
#include "test_fx_helper.h"
#include "wave.h"
#include "../debug.hpp"
#include "../fx_base.h"
TEST(Framework, TestWaveIn)
{
unsigned size;
size_t size;
float32_t** samples = readWaveFile(AUDIO_SOURCE_FILE, size);
size_t nb_errors = 0;

@ -2,13 +2,6 @@
#include <iomanip>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <locale>
#include <ctime>
#include <cmath>
#include <random>
#include "wave.h"
#include "test_fx_helper.h"
@ -21,6 +14,11 @@
TEST(FXComponent, LFO)
{
const testing::TestInfo* test_info = testing::UnitTest::GetInstance()->current_test_info();
std::string full_test_name = test_info->test_case_name();
full_test_name += ".";
full_test_name += test_info->name();
const float32_t freq = 10.0f;
LFO lfo(SAMPLING_FREQUENCY, 0.0f, freq);
@ -28,9 +26,9 @@ TEST(FXComponent, LFO)
float32_t rate = 0.0f;
float32_t rate_increment = freq / 2.0f / SAMPLING_FREQUENCY;
std::ofstream out(getResultFile("FXComponent.LFO.csv"));
setupOuputStreamFocCSV(out);
out << fixed << showpoint;
std::ofstream out(getResultFile(full_test_name + ".FXComponent.LFO.csv", true));
setupOuputStreamForCSV(out);
out << std::fixed << std::showpoint;
out << "index;LFO" << std::endl;
for(unsigned i = 0; i < size; ++i)

@ -1,5 +1,8 @@
#include "test_fx_helper.h"
#include <iostream>
#include <filesystem>
std::string getScenarioName(int scenario)
{
std::stringstream ss;
@ -78,27 +81,52 @@ std::string getScenarioName(int scenario)
}
void setupOuputStreamFocCSV(std::ostream& out)
void setupOuputStreamForCSV(std::ostream& out)
{
struct comma_separator : numpunct<char>
struct comma_separator : std::numpunct<char>
{
virtual char do_decimal_point() const override { return ','; }
};
out.imbue(locale(out.getloc(), new comma_separator));
out << fixed << showpoint;
out.imbue(std::locale(out.getloc(), new comma_separator));
out << std::fixed << std::showpoint;
}
bool createFolderStructure(std::string& path)
{
try
{
std::filesystem::path file_path(path);
if(!std::filesystem::exists(file_path.parent_path()))
{
std::filesystem::create_directories(file_path.parent_path());
}
return true;
}
catch(const std::exception& e)
{
std::cerr << e.what() << '\n';
return false;
}
}
std::string getResultFile(const std::string& filename)
std::string getResultFile(const std::string& filename, bool createPath)
{
return std::string(OUTPUT_FOLDER) + "/" + filename;
std::string f = std::string(OUTPUT_FOLDER) + "/" + filename;
if(createPath)
{
createFolderStructure(f);
}
return f;
}
float32_t getRandomValue()
{
static random_device rd;
static mt19937 gen(rd());
static uniform_real_distribution<float32_t> dist(-1.0f, 1.0f);
static std::random_device rd;
static std::mt19937 gen(rd());
static std::uniform_real_distribution<float32_t> dist(-1.0f, 1.0f);
return dist(gen);
}

@ -4,10 +4,10 @@
#include <string>
#include <gtest/gtest.h>
#include "wave.h"
#include "../fx.h"
#include "../mixing_console_constants.h"
#define AUDIO_SOURCE_FILE "test2.wav"
#define AUDIO_SOURCE_FILE "test.wav"
#define SAMPLING_FREQUENCY 44100.0f
@ -24,12 +24,15 @@ enum FXSwitch
FX__Phaser,
FX__Delay,
FX__ShimmerReverb,
FX__PlateReverb
FX__PlateReverb,
__kFXCount
};
void setupOuputStreamFocCSV(std::ostream& out);
void setupOuputStreamForCSV(std::ostream& out);
std::string getResultFile(const string& filename);
bool createFolderStructure(std::string& path);
std::string getResultFile(const std::string& filename, bool createPath);
float32_t getRandomValue();

@ -1,245 +1,353 @@
#include <gtest/gtest.h>
#include <cmath>
#include "test_fx_helper.h"
#include "wave.h"
#include "../mixing_console.hpp"
class MixingConsoleScenarioTest : public testing::TestWithParam<MixerOutput> {};
TEST_P(MixingConsoleScenarioTest, MixerOutputTest)
{
MixerOutput v = this->GetParam();
std::string str = toString(v);
MixerOutput mo = toIndex(str.c_str());
EXPECT_EQ(v, mo);
}
INSTANTIATE_TEST_SUITE_P(MixerOutputTest, MixingConsoleScenarioTest, testing::Range(MixerOutput::OutputStart, MixerOutput::kFXCount));
typedef MixingConsole<8> Mixer;
void setupMixingConsoleFX(Mixer* mixer)
{
mixer->getTube()->setMute(false);
mixer->getTube()->setOverdrive(0.25f);
mixer->getChorus()->setMute(false);
mixer->getChorus()->setRate(0.4f);
mixer->getChorus()->setDepth(0.5f);
mixer->getFlanger()->setMute(false);
mixer->getFlanger()->setRate(0.03f);
mixer->getFlanger()->setDepth(0.75f);
mixer->getFlanger()->setFeedback(0.5f);
mixer->getOrbitone()->setMute(false);
mixer->getOrbitone()->setRate(0.4f);
mixer->getOrbitone()->setDepth(0.5f);
mixer->getPhaser()->setMute(false);
mixer->getPhaser()->setRate(0.1f);
mixer->getPhaser()->setDepth(1.0f);
mixer->getPhaser()->setFeedback(0.5f);
mixer->getPhaser()->setNbStages(12);
mixer->getDelay()->setMute(false);
mixer->getDelay()->setLeftDelayTime(0.5f);
mixer->getDelay()->setLeftDelayTime(0.7f);
mixer->getDelay()->setFeedback(0.7f);
mixer->getDelay()->setFlutterRate(0.7f);
mixer->getDelay()->setFlutterAmount(0.7f);
mixer->getPlateReverb()->setMute(false);
mixer->getPlateReverb()->set_bypass(false);
mixer->getPlateReverb()->size(0.7f);
mixer->getPlateReverb()->hidamp(0.5f);
mixer->getPlateReverb()->lodamp(0.5f);
mixer->getPlateReverb()->lowpass(0.3f);
mixer->getPlateReverb()->diffusion(0.65f);
mixer->getPlateReverb()->level(1.0f);
mixer->getShimmerReverb()->setMute(false);
mixer->getShimmerReverb()->setInputGain(0.65f);
mixer->getShimmerReverb()->setTime(0.89f);
mixer->getShimmerReverb()->setDiffusion(0.75f);
mixer->getShimmerReverb()->setLP(0.8f);
}
TEST(MixingConsole, DryProcessing)
{
const float32_t epsilon = 1e-7;
const size_t length = 2;
Mixer* mixer = new Mixer(SAMPLING_FREQUENCY, length);
mixer->reset();
mixer->setSendLevel(0, MixerOutput::FX_Tube, 0.0f);
mixer->setSendLevel(0, MixerOutput::FX_Chorus, 0.0f);
mixer->setSendLevel(0, MixerOutput::FX_Flanger, 0.0f);
mixer->setSendLevel(0, MixerOutput::FX_Orbitone, 0.0f);
mixer->setSendLevel(0, MixerOutput::FX_Phaser, 0.0f);
mixer->setSendLevel(0, MixerOutput::FX_Delay, 0.0f);
mixer->setSendLevel(0, MixerOutput::FX_PlateReverb, 0.0f);
mixer->setSendLevel(0, MixerOutput::FX_ShimmerReverb, 0.0f);
for(unsigned i = MixerOutput::OutputStart; i < (MixerOutput::kFXCount - 1); ++i)
{
mixer->setReturnLevel(static_cast<MixerOutput>(i), MixerOutput::MainOutput, 0.0f);
}
mixer->setChannelLevel(0, 1.0f);
mixer->setPan(0, 0.5f);
mixer->setSendLevel(0, MixerOutput::MainOutput, 1.0f);
EXPECT_EQ(0, INSPECT(mixer, fullInspector));
float32_t in[length] = {0.1, 0.2};
float32_t out[StereoChannels::kNumChannels][length];
for(size_t i = 0; i < StereoChannels::kNumChannels; ++i) memset(out[i], 0, length * sizeof(float32_t));
mixer->setInputSampleBuffer(0, in);
EXPECT_EQ(0, INSPECT(mixer, fullInspector));
mixer->process(
out[StereoChannels::Left ],
out[StereoChannels::Right]
);
EXPECT_EQ(0, INSPECT(mixer, fullInspector));
EXPECT_EQ(out[StereoChannels::Left ][0], out[StereoChannels::Right][0]);
EXPECT_EQ(out[StereoChannels::Left ][1], out[StereoChannels::Right][1]);
EXPECT_LT(std::abs(out[StereoChannels::Left ][0] - (sqrt(2.0f) / 20.0f)), epsilon);
EXPECT_LT(std::abs(out[StereoChannels::Left ][1] - (sqrt(2.0f) / 10.0f)), epsilon);
delete mixer;
}
TEST(MixingConsole, ShimmerProcessing)
{
const float32_t epsilon = 1e-7;
const size_t length = 2;
Mixer* mixer = new Mixer(SAMPLING_FREQUENCY, length);
mixer->reset();
mixer->setSendLevel(0, MixerOutput::MainOutput, 0.0f);
mixer->setSendLevel(0, MixerOutput::FX_ShimmerReverb, 1.0f);
mixer->setReturnLevel(MixerOutput::FX_ShimmerReverb, MixerOutput::MainOutput, 1.0f);
mixer->setChannelLevel(0, 1.0f);
mixer->setPan(0, 0.5f);
EXPECT_EQ(0, INSPECT(mixer, fullInspector));
float32_t in[length] = {0.1, 0.2};
float32_t out1[StereoChannels::kNumChannels][length];
for(size_t i = 0; i < StereoChannels::kNumChannels; ++i) memset(out1[i], 0, length * sizeof(float32_t));
mixer->setInputSampleBuffer(0, in);
EXPECT_EQ(0, INSPECT(mixer, fullInspector));
mixer->process(
out1[StereoChannels::Left ],
out1[StereoChannels::Right]
);
EXPECT_EQ(0, INSPECT(mixer, fullInspector));
mixer->reset();
EXPECT_EQ(0, INSPECT(mixer, fullInspector));
float32_t out2[StereoChannels::kNumChannels][length];
mixer->setInputSampleBuffer(0, in);
EXPECT_EQ(0, INSPECT(mixer, fullInspector));
mixer->process(
out2[StereoChannels::Left ],
out2[StereoChannels::Right]
);
EXPECT_EQ(0, INSPECT(mixer, fullInspector));
EXPECT_EQ(out1[StereoChannels::Left ][0], out2[StereoChannels::Left ][0]);
EXPECT_EQ(out1[StereoChannels::Right][0], out2[StereoChannels::Right][0]);
EXPECT_EQ(out1[StereoChannels::Left ][1], out2[StereoChannels::Left ][1]);
EXPECT_EQ(out1[StereoChannels::Right][1], out2[StereoChannels::Right][1]);
delete mixer;
}
TEST(MixingConsole, ShimmerNoiseProcessing)
{
const size_t length = 1024;
Mixer* mixer = new Mixer(SAMPLING_FREQUENCY, length);
mixer->reset();
mixer->setSendLevel(0, MixerOutput::MainOutput, 0.0f);
mixer->setSendLevel(0, MixerOutput::FX_ShimmerReverb, 1.0f);
mixer->setReturnLevel(MixerOutput::FX_ShimmerReverb, MixerOutput::MainOutput, 1.0f);
mixer->setChannelLevel(0, 1.0f);
mixer->setPan(0, 0.5f);
EXPECT_EQ(0, INSPECT(mixer, fullInspector));
float32_t in[length];
for(size_t i = 0; i < length; ++i) in[i] = getRandomValue();
float32_t out[StereoChannels::kNumChannels][length];
for(size_t i = 0; i < StereoChannels::kNumChannels; ++i) memset(out[i], 0, length * sizeof(float32_t));
mixer->setInputSampleBuffer(0, in);
EXPECT_EQ(0, INSPECT(mixer, fullInspector));
mixer->process(
out[StereoChannels::Left ],
out[StereoChannels::Right]
);
EXPECT_EQ(0, INSPECT(mixer, fullInspector));
delete mixer;
}
TEST(MixingConsole, SimpleProcessing)
{
const unsigned nbRepeats = 2;
unsigned size;
float32_t** samples = readWaveFile(AUDIO_SOURCE_FILE, size);
float32_t* sampleOutL = new float32_t[size * nbRepeats];
float32_t* sampleOutR = new float32_t[size * nbRepeats];
memset(sampleOutL, 0, size * nbRepeats * sizeof(float32_t));
memset(sampleOutR, 0, size * nbRepeats * sizeof(float32_t));
Mixer* mixer = new Mixer(SAMPLING_FREQUENCY, size);
setupMixingConsoleFX(mixer);
mixer->getTube()->setOverdrive(0.15f);
mixer->setSendLevel(0, MixerOutput::FX_Tube, 1.0f);
mixer->setSendLevel(0, MixerOutput::FX_Phaser, 1.0f);
// mixer->setReturnLevel(MixerOutput::FX_Tube, MixerOutput::MainOutput, 1.0f);
// mixer->setSendLevel(0, MixerOutput::FX_Chorus, 1.0f);
// mixer->setSendLevel(0, MixerOutput::FX_ShimmerReverb, 1.0f);
mixer->setReturnLevel(MixerOutput::FX_Tube, MixerOutput::FX_Chorus, 1.0f);
mixer->setReturnLevel(MixerOutput::FX_Chorus, MixerOutput::FX_ShimmerReverb, 1.0f);
mixer->setReturnLevel(MixerOutput::FX_Phaser, MixerOutput::FX_Delay, 1.0f);
mixer->setSendLevel(0, MixerOutput::MainOutput, 0.25f);
mixer->setReturnLevel(MixerOutput::FX_Tube, MixerOutput::MainOutput, 0.1f);
mixer->setReturnLevel(MixerOutput::FX_Chorus, MixerOutput::MainOutput, 0.15f);
mixer->setReturnLevel(MixerOutput::FX_ShimmerReverb, MixerOutput::MainOutput, 0.3f);
mixer->setReturnLevel(MixerOutput::FX_Delay, MixerOutput::MainOutput, 0.3f);
for(unsigned j = 0; j < nbRepeats; ++j)
{
mixer->setInputSampleBuffer(0, samples[0], samples[1]);
mixer->process(sampleOutL + j * size, sampleOutR + j * size);
EXPECT_EQ(0, INSPECT(mixer, fullInspector));
}
saveWaveFile(getResultFile("result-mixing-console.wav"), sampleOutL, sampleOutR, nbRepeats * size, static_cast<unsigned>(SAMPLING_FREQUENCY), 16);
delete mixer;
delete[] samples[0];
delete[] samples[1];
delete[] samples;
delete[] sampleOutL;
delete[] sampleOutR;
}
#include <gtest/gtest.h>
#include <cmath>
#include "test_fx_helper.h"
#include "wave.h"
#include "../mixing_console.hpp"
class MixingConsoleScenarioTest : public testing::TestWithParam<MixerOutput> {};
TEST_P(MixingConsoleScenarioTest, MixerOutputTest)
{
MixerOutput v = this->GetParam();
std::string str = toString(v);
MixerOutput mo = toIndex(str.c_str());
EXPECT_EQ(v, mo);
}
INSTANTIATE_TEST_SUITE_P(MixerOutputTest, MixingConsoleScenarioTest, testing::Range(MixerOutput::OutputStart, MixerOutput::kFXCount));
typedef MixingConsole<8> Mixer;
void setupMixingConsoleFX(Mixer* mixer)
{
mixer->getTube()->setMute(false);
mixer->getTube()->setOverdrive(0.25f);
mixer->getChorus()->setMute(false);
mixer->getChorus()->setRate(0.4f);
mixer->getChorus()->setDepth(0.5f);
mixer->getFlanger()->setMute(false);
mixer->getFlanger()->setRate(0.03f);
mixer->getFlanger()->setDepth(0.75f);
mixer->getFlanger()->setFeedback(0.5f);
mixer->getOrbitone()->setMute(false);
mixer->getOrbitone()->setRate(0.4f);
mixer->getOrbitone()->setDepth(0.5f);
mixer->getPhaser()->setMute(false);
mixer->getPhaser()->setRate(0.1f);
mixer->getPhaser()->setDepth(1.0f);
mixer->getPhaser()->setFeedback(0.5f);
mixer->getPhaser()->setNbStages(12);
mixer->getDelay()->setMute(false);
mixer->getDelay()->setLeftDelayTime(0.5f);
mixer->getDelay()->setLeftDelayTime(0.7f);
mixer->getDelay()->setFeedback(0.7f);
mixer->getDelay()->setFlutterRate(0.7f);
mixer->getDelay()->setFlutterAmount(0.7f);
mixer->getPlateReverb()->setMute(false);
mixer->getPlateReverb()->set_bypass(false);
mixer->getPlateReverb()->size(0.7f);
mixer->getPlateReverb()->hidamp(0.5f);
mixer->getPlateReverb()->lodamp(0.5f);
mixer->getPlateReverb()->lowpass(0.3f);
mixer->getPlateReverb()->diffusion(0.65f);
mixer->getPlateReverb()->level(1.0f);
mixer->getShimmerReverb()->setMute(false);
mixer->getShimmerReverb()->setInputGain(0.65f);
mixer->getShimmerReverb()->setTime(0.89f);
mixer->getShimmerReverb()->setDiffusion(0.75f);
mixer->getShimmerReverb()->setLP(0.8f);
}
#define ACTIVE_FX(scenarioId, fx) const bool b ## fx = ((scenarioId & MixerOutput::fx) == MixerOutput::fx)
void setupMixingConsoleFX(Mixer* mixer, int scenarioId)
{
ACTIVE_FX(scenarioId, FX_Tube);
ACTIVE_FX(scenarioId, FX_Chorus);
ACTIVE_FX(scenarioId, FX_Flanger);
ACTIVE_FX(scenarioId, FX_Orbitone);
ACTIVE_FX(scenarioId, FX_Phaser);
ACTIVE_FX(scenarioId, FX_Delay);
ACTIVE_FX(scenarioId, FX_PlateReverb);
ACTIVE_FX(scenarioId, FX_ShimmerReverb);
mixer->setChannelLevel(0, 1.0f);
mixer->setPan(0, 0.5f);
}
TEST(MixingConsole, ZeroSamplesTest)
{
const size_t length = 4;
Mixer* mixer = new Mixer(SAMPLING_FREQUENCY, length);
EXPECT_EQ(0, FULL_INSPECT(mixer, true));
mixer->reset();
EXPECT_EQ(0, FULL_INSPECT(mixer, true));
setupMixingConsoleFX(mixer);
EXPECT_EQ(0, FULL_INSPECT(mixer, true));
mixer->setChannelLevel(0, 1.0f);
EXPECT_EQ(0, FULL_INSPECT(mixer, true));
mixer->setPan(0, 0.5f);
EXPECT_EQ(0, FULL_INSPECT(mixer, true));
float32_t samples[] = {0.0f, 0.0f, 0.0f, 0.0f};
mixer->setInputSampleBuffer(0, samples);
EXPECT_EQ(0, FULL_INSPECT(mixer, true));
mixer->setSendLevel(0, MixerOutput::MainOutput, 1.0f);
EXPECT_EQ(0, FULL_INSPECT(mixer, true));
float32_t outL[4];
float32_t outR[4];
mixer->process(outL, outR);
EXPECT_EQ(0, FULL_INSPECT(mixer, true));
mixer->setSendLevel(0, MixerOutput::FX_Tube, 1.0f);
mixer->setSendLevel(0, MixerOutput::FX_Delay, 1.0f);
mixer->setSendLevel(0, MixerOutput::FX_PlateReverb, 1.0f);
mixer->setReturnLevel(MixerOutput::FX_Tube, MixerOutput::FX_Orbitone, 1.0f);
mixer->setReturnLevel(MixerOutput::FX_Orbitone, MixerOutput::MainOutput, 0.5f);
mixer->setReturnLevel(MixerOutput::FX_Orbitone, MixerOutput::FX_PlateReverb, 1.0f);
mixer->setReturnLevel(MixerOutput::FX_Delay, MixerOutput::MainOutput, 0.5f);
mixer->setReturnLevel(MixerOutput::FX_PlateReverb, MixerOutput::MainOutput, 0.5f);
EXPECT_EQ(0, FULL_INSPECT(mixer, true));
delete mixer;
}
TEST(MixingConsole, DryProcessing)
{
const float32_t epsilon = 1e-7;
const size_t length = 2;
Mixer* mixer = new Mixer(SAMPLING_FREQUENCY, length);
mixer->reset();
mixer->setSendLevel(0, MixerOutput::FX_Tube, 0.0f);
mixer->setSendLevel(0, MixerOutput::FX_Chorus, 0.0f);
mixer->setSendLevel(0, MixerOutput::FX_Flanger, 0.0f);
mixer->setSendLevel(0, MixerOutput::FX_Orbitone, 0.0f);
mixer->setSendLevel(0, MixerOutput::FX_Phaser, 0.0f);
mixer->setSendLevel(0, MixerOutput::FX_Delay, 0.0f);
mixer->setSendLevel(0, MixerOutput::FX_PlateReverb, 0.0f);
mixer->setSendLevel(0, MixerOutput::FX_ShimmerReverb, 0.0f);
for(unsigned i = MixerOutput::OutputStart; i < (MixerOutput::kFXCount - 1); ++i)
{
mixer->setReturnLevel(static_cast<MixerOutput>(i), MixerOutput::MainOutput, 0.0f);
}
mixer->setChannelLevel(0, 1.0f);
mixer->setPan(0, 0.5f);
mixer->setSendLevel(0, MixerOutput::MainOutput, 1.0f);
EXPECT_EQ(0, INSPECT(mixer, fullInspector));
float32_t in[length] = {0.1, 0.2};
float32_t out[StereoChannels::kNumChannels][length];
for(size_t i = 0; i < StereoChannels::kNumChannels; ++i) memset(out[i], 0, length * sizeof(float32_t));
mixer->setInputSampleBuffer(0, in);
EXPECT_EQ(0, INSPECT(mixer, fullInspector));
mixer->process(
out[StereoChannels::Left ],
out[StereoChannels::Right]
);
EXPECT_EQ(0, INSPECT(mixer, fullInspector));
EXPECT_EQ(out[StereoChannels::Left ][0], out[StereoChannels::Right][0]);
EXPECT_EQ(out[StereoChannels::Left ][1], out[StereoChannels::Right][1]);
EXPECT_LT(std::abs(out[StereoChannels::Left ][0] - (sqrt(2.0f) / 20.0f)), epsilon);
EXPECT_LT(std::abs(out[StereoChannels::Left ][1] - (sqrt(2.0f) / 10.0f)), epsilon);
delete mixer;
}
TEST(MixingConsole, ShimmerProcessing)
{
const float32_t epsilon = 1e-7;
const size_t length = 2;
Mixer* mixer = new Mixer(SAMPLING_FREQUENCY, length);
mixer->reset();
mixer->setSendLevel(0, MixerOutput::MainOutput, 0.0f);
mixer->setSendLevel(0, MixerOutput::FX_ShimmerReverb, 1.0f);
mixer->setReturnLevel(MixerOutput::FX_ShimmerReverb, MixerOutput::MainOutput, 1.0f);
mixer->setChannelLevel(0, 1.0f);
mixer->setPan(0, 0.5f);
EXPECT_EQ(0, INSPECT(mixer, fullInspector));
float32_t in[length] = {0.1, 0.2};
float32_t out1[StereoChannels::kNumChannels][length];
for(size_t i = 0; i < StereoChannels::kNumChannels; ++i) memset(out1[i], 0, length * sizeof(float32_t));
mixer->setInputSampleBuffer(0, in);
EXPECT_EQ(0, INSPECT(mixer, fullInspector));
mixer->process(
out1[StereoChannels::Left ],
out1[StereoChannels::Right]
);
EXPECT_EQ(0, INSPECT(mixer, fullInspector));
mixer->reset();
EXPECT_EQ(0, INSPECT(mixer, fullInspector));
float32_t out2[StereoChannels::kNumChannels][length];
mixer->setInputSampleBuffer(0, in);
EXPECT_EQ(0, INSPECT(mixer, fullInspector));
mixer->process(
out2[StereoChannels::Left ],
out2[StereoChannels::Right]
);
EXPECT_EQ(0, INSPECT(mixer, fullInspector));
EXPECT_EQ(out1[StereoChannels::Left ][0], out2[StereoChannels::Left ][0]);
EXPECT_EQ(out1[StereoChannels::Right][0], out2[StereoChannels::Right][0]);
EXPECT_EQ(out1[StereoChannels::Left ][1], out2[StereoChannels::Left ][1]);
EXPECT_EQ(out1[StereoChannels::Right][1], out2[StereoChannels::Right][1]);
delete mixer;
}
TEST(MixingConsole, ShimmerNoiseProcessing)
{
const size_t length = 1024;
Mixer* mixer = new Mixer(SAMPLING_FREQUENCY, length);
mixer->reset();
mixer->setSendLevel(0, MixerOutput::MainOutput, 0.0f);
mixer->setSendLevel(0, MixerOutput::FX_ShimmerReverb, 1.0f);
mixer->setReturnLevel(MixerOutput::FX_ShimmerReverb, MixerOutput::MainOutput, 1.0f);
mixer->setChannelLevel(0, 1.0f);
mixer->setPan(0, 0.5f);
EXPECT_EQ(0, INSPECT(mixer, fullInspector));
float32_t in[length];
for(size_t i = 0; i < length; ++i) in[i] = getRandomValue();
float32_t out[StereoChannels::kNumChannels][length];
for(size_t i = 0; i < StereoChannels::kNumChannels; ++i) memset(out[i], 0, length * sizeof(float32_t));
mixer->setInputSampleBuffer(0, in);
EXPECT_EQ(0, INSPECT(mixer, fullInspector));
mixer->process(
out[StereoChannels::Left ],
out[StereoChannels::Right]
);
EXPECT_EQ(0, INSPECT(mixer, fullInspector));
delete mixer;
}
TEST(MixingConsole, StandardUsageProcessing)
{
const testing::TestInfo* test_info = testing::UnitTest::GetInstance()->current_test_info();
std::string full_test_name = test_info->test_case_name();
full_test_name += ".";
full_test_name += test_info->name();
const unsigned nbRepeats = 2;
size_t size;
float32_t** samples = readWaveFile(AUDIO_SOURCE_FILE, size);
float32_t* sampleOutL = new float32_t[size * nbRepeats];
float32_t* sampleOutR = new float32_t[size * nbRepeats];
memset(sampleOutL, 0, size * nbRepeats * sizeof(float32_t));
memset(sampleOutR, 0, size * nbRepeats * sizeof(float32_t));
Mixer* mixer = new Mixer(SAMPLING_FREQUENCY, size);
setupMixingConsoleFX(mixer);
mixer->getTube()->setOverdrive(0.15f);
mixer->setSendLevel(0, MixerOutput::FX_Tube, 1.0f);
mixer->setSendLevel(0, MixerOutput::FX_Phaser, 1.0f);
// mixer->setReturnLevel(MixerOutput::FX_Tube, MixerOutput::MainOutput, 1.0f);
// mixer->setSendLevel(0, MixerOutput::FX_Chorus, 1.0f);
// mixer->setSendLevel(0, MixerOutput::FX_ShimmerReverb, 1.0f);
mixer->setReturnLevel(MixerOutput::FX_Tube, MixerOutput::FX_Chorus, 1.0f);
mixer->setReturnLevel(MixerOutput::FX_Chorus, MixerOutput::FX_ShimmerReverb, 1.0f);
mixer->setReturnLevel(MixerOutput::FX_Phaser, MixerOutput::FX_Delay, 1.0f);
mixer->setSendLevel(0, MixerOutput::MainOutput, 0.25f);
mixer->setReturnLevel(MixerOutput::FX_Tube, MixerOutput::MainOutput, 0.1f);
mixer->setReturnLevel(MixerOutput::FX_Chorus, MixerOutput::MainOutput, 0.15f);
mixer->setReturnLevel(MixerOutput::FX_ShimmerReverb, MixerOutput::MainOutput, 0.3f);
mixer->setReturnLevel(MixerOutput::FX_Delay, MixerOutput::MainOutput, 0.3f);
for(unsigned j = 0; j < nbRepeats; ++j)
{
mixer->setInputSampleBuffer(0, samples[0], samples[1]);
mixer->process(sampleOutL + j * size, sampleOutR + j * size);
EXPECT_EQ(0, INSPECT(mixer, fullInspector));
}
saveWaveFile(getResultFile(full_test_name + ".wav", true), sampleOutL, sampleOutR, nbRepeats * size, static_cast<unsigned>(SAMPLING_FREQUENCY), 16);
delete mixer;
delete[] samples[0];
delete[] samples[1];
delete[] samples;
delete[] sampleOutL;
delete[] sampleOutR;
}
// TEST_P(FXScenarioTest, FXProcessingScenario)
// {
// const testing::TestInfo* test_info = testing::UnitTest::GetInstance()->current_test_info();
// std::string full_test_name = test_info->test_case_name();
// full_test_name += ".";
// full_test_name += test_info->name();
// const unsigned nbRepeats = 2;
// size_t size;
// float32_t** samples = readWaveFile(AUDIO_SOURCE_FILE, size);
// float32_t* sampleOutL = new float32_t[size * nbRepeats];
// float32_t* sampleOutR = new float32_t[size * nbRepeats];
// memset(sampleOutL, 0, size * nbRepeats * sizeof(float32_t));
// memset(sampleOutR, 0, size * nbRepeats * sizeof(float32_t));
// Mixer* mixer = new Mixer(SAMPLING_FREQUENCY, size);
// setupMixingConsoleFX(mixer);
// int scenarioId = this->GetParam();
// setupMixingConsoleFXForScenario(mixer, scenarioId);
// for(unsigned j = 0; j < nbRepeats; ++j)
// {
// mixer->setInputSampleBuffer(0, samples[0], samples[1]);
// mixer->process(sampleOutL + j * size, sampleOutR + j * size);
// EXPECT_EQ(0, INSPECT(mixer, fullInspector));
// }
// saveWaveFile(getResultFile(full_test_name + ".wav"), sampleOutL, sampleOutR, nbRepeats * size, static_cast<unsigned>(SAMPLING_FREQUENCY), 16);
// delete mixer;
// delete[] samples[0];
// delete[] samples[1];
// delete[] samples;
// delete[] sampleOutL;
// delete[] sampleOutR;
// }
// INSTANTIATE_TEST_SUITE_P(MixingConsole, FXScenarioTest, testing::Range(0, 1 << (MixerOutput::kFXCount - 1)));

@ -1,66 +1,70 @@
#include <gtest/gtest.h>
#include "test_fx_helper.h"
#include "wave.h"
#include "../effect_platervbstereo.h"
TEST(FXElement, PlateReverbMigration)
{
const unsigned nbRepeats = 4;
AudioEffectPlateReverb* reverb = new AudioEffectPlateReverb(SAMPLING_FREQUENCY);
reverb->set_bypass(false);
reverb->size(0.7f);
reverb->hidamp(0.5f);
reverb->lodamp(0.5f);
reverb->lowpass(0.3f);
reverb->diffusion(0.65f);
reverb->level(1.0f);
unsigned size;
float32_t** samples = readWaveFile(AUDIO_SOURCE_FILE, size);
float32_t* sampleOutL = new float32_t[size * nbRepeats];
float32_t* sampleOutR = new float32_t[size * nbRepeats];
memset(sampleOutL, 0, size * nbRepeats * sizeof(float32_t));
memset(sampleOutR, 0, size * nbRepeats * sizeof(float32_t));
unsigned index = 0;
for(unsigned i = 0; i < nbRepeats; ++i)
{
for(unsigned j = 0; j < size; ++j)
{
reverb->processSample(samples[0][j], samples[1][j], sampleOutL[index], sampleOutR[index]);
++index;
}
}
saveWaveFile(getResultFile("result-PlateReverb-new.wav"), sampleOutL, sampleOutR, nbRepeats * size, static_cast<unsigned>(SAMPLING_FREQUENCY), 16);
unsigned indexOut = 0;
for (unsigned i = 0; i < nbRepeats; ++i)
{
unsigned len = size;
unsigned indexIn = 0;
while(len > 0)
{
unsigned grainSize = (len < 1024 ? len : 1024);
reverb->doReverb(samples[0] + indexIn, samples[1] + indexIn, sampleOutL + indexOut, sampleOutR + indexOut, grainSize);
indexIn += grainSize;
indexOut += grainSize;
len -= grainSize;
}
}
saveWaveFile(getResultFile("result-PlateReverb-legacy.wav"), sampleOutL, sampleOutR, nbRepeats * size, static_cast<unsigned>(SAMPLING_FREQUENCY), 16);
delete[] sampleOutL;
delete[] sampleOutR;
delete[] samples[0];
delete[] samples[1];
delete[] samples;
delete reverb;
}
#include <gtest/gtest.h>
#include "test_fx_helper.h"
#include "../effect_platervbstereo.h"
TEST(FXPlateReverb, Migration)
{
const testing::TestInfo* test_info = testing::UnitTest::GetInstance()->current_test_info();
std::string full_test_name = test_info->test_case_name();
full_test_name += ".";
full_test_name += test_info->name();
const unsigned nbRepeats = 4;
AudioEffectPlateReverb* reverb = new AudioEffectPlateReverb(SAMPLING_FREQUENCY);
reverb->set_bypass(false);
reverb->size(0.7f);
reverb->hidamp(0.5f);
reverb->lodamp(0.5f);
reverb->lowpass(0.3f);
reverb->diffusion(0.65f);
reverb->level(1.0f);
size_t size;
float32_t** samples = readWaveFile(AUDIO_SOURCE_FILE, size);
float32_t* sampleOutL = new float32_t[size * nbRepeats];
float32_t* sampleOutR = new float32_t[size * nbRepeats];
memset(sampleOutL, 0, size * nbRepeats * sizeof(float32_t));
memset(sampleOutR, 0, size * nbRepeats * sizeof(float32_t));
unsigned index = 0;
for(unsigned i = 0; i < nbRepeats; ++i)
{
for(unsigned j = 0; j < size; ++j)
{
reverb->processSample(samples[0][j], samples[1][j], sampleOutL[index], sampleOutR[index]);
++index;
}
}
saveWaveFile(getResultFile(full_test_name + ".PlateReverb-new.wav", true), sampleOutL, sampleOutR, nbRepeats * size, static_cast<unsigned>(SAMPLING_FREQUENCY), 16);
unsigned indexOut = 0;
for (unsigned i = 0; i < nbRepeats; ++i)
{
unsigned len = size;
unsigned indexIn = 0;
while(len > 0)
{
unsigned grainSize = (len < 1024 ? len : 1024);
reverb->doReverb(samples[0] + indexIn, samples[1] + indexIn, sampleOutL + indexOut, sampleOutR + indexOut, grainSize);
indexIn += grainSize;
indexOut += grainSize;
len -= grainSize;
}
}
saveWaveFile(getResultFile(full_test_name + ".PlateReverb-legacy.wav", true), sampleOutL, sampleOutR, nbRepeats * size, static_cast<unsigned>(SAMPLING_FREQUENCY), 16);
delete[] sampleOutL;
delete[] sampleOutR;
delete[] samples[0];
delete[] samples[1];
delete[] samples;
delete reverb;
}

@ -2,10 +2,8 @@
#include <cmath>
#include "test_fx_helper.h"
#include "wave.h"
#include "../fx_rack.h"
#include "../effect_platervbstereo.h"
using namespace std;
@ -73,8 +71,13 @@ TEST_P(FXScenarioTest, FXRackResetAllScenarios)
TEST_P(FXScenarioTest, ScenarioProcessing)
{
const testing::TestInfo* test_info = testing::UnitTest::GetInstance()->current_test_info();
std::string full_test_name = test_info->test_case_name();
full_test_name += ".";
full_test_name += test_info->name();
const unsigned nbRepeats = 1;
unsigned size;
size_t size;
float32_t** samples = readWaveFile(AUDIO_SOURCE_FILE, size);
float32_t* sampleOutL = new float32_t[size * nbRepeats];
float32_t* sampleOutR = new float32_t[size * nbRepeats];
@ -96,16 +99,17 @@ TEST_P(FXScenarioTest, ScenarioProcessing)
}
stringstream ss;
ss << "result-fx-rack" << name << ".wav";
saveWaveFile(getResultFile(ss.str()), sampleOutL, sampleOutR, nbRepeats * size, static_cast<unsigned>(SAMPLING_FREQUENCY), 16);
delete rack;
ss << full_test_name << "-fx-rack" << name << ".wav";
saveWaveFile(getResultFile(ss.str(), true), sampleOutL, sampleOutR, nbRepeats * size, static_cast<unsigned>(SAMPLING_FREQUENCY), 16);
delete[] samples[0];
delete[] samples[1];
delete[] samples;
delete[] sampleOutL;
delete[] sampleOutR;
delete rack;
}
INSTANTIATE_TEST_SUITE_P(FXRack, FXScenarioTest, testing::Range(0, 1 << (FXSwitch::FX__ShimmerReverb + 1)));

@ -0,0 +1,182 @@
#include <gtest/gtest.h>
#include "test_fx_helper.h"
#include "../fx_shimmer_reverb.h"
TEST(FXShimmerReverb, TransientSilence)
{
const testing::TestInfo* test_info = testing::UnitTest::GetInstance()->current_test_info();
std::string full_test_name = test_info->test_case_name();
full_test_name += ".";
full_test_name += test_info->name();
const size_t size = static_cast<size_t>(SAMPLING_FREQUENCY);
float32_t* inSamples = new float32_t[size];
memset(inSamples, 0, size * sizeof(float32_t));
float32_t* outSamplesL = new float32_t[size];
float32_t* outSamplesR = new float32_t[size];
memset(outSamplesL, 0, size * sizeof(float32_t));
memset(outSamplesR, 0, size * sizeof(float32_t));
ShimmerReverb* shimmer = new ShimmerReverb(SAMPLING_FREQUENCY);
shimmer->setInputGain(0.55f);
shimmer->setTime(0.75f);
shimmer->setDiffusion(0.8f);
shimmer->setLP(0.7f);
shimmer->reset();
for(size_t i = 0; i < size; ++i)
{
shimmer->processSample(
inSamples[i],
inSamples[i],
outSamplesL[i],
outSamplesR[i]
);
}
saveWaveFile(getResultFile(full_test_name + ".wav", true), outSamplesL, outSamplesR, size, SAMPLING_FREQUENCY, 16);
delete shimmer;
delete[] inSamples;
delete[] outSamplesL;
delete[] outSamplesR;
}
TEST(FXShimmerReverb, TransientSilenceWithDirac)
{
const testing::TestInfo* test_info = testing::UnitTest::GetInstance()->current_test_info();
std::string full_test_name = test_info->test_case_name();
full_test_name += ".";
full_test_name += test_info->name();
const size_t size = 4 * static_cast<size_t>(SAMPLING_FREQUENCY);
float32_t* inSamples = new float32_t[size];
memset(inSamples, 0, size * sizeof(float32_t));
inSamples[0] = 1.0f;
float32_t* outSamplesL = new float32_t[size];
float32_t* outSamplesR = new float32_t[size];
memset(outSamplesL, 0, size * sizeof(float32_t));
memset(outSamplesR, 0, size * sizeof(float32_t));
ShimmerReverb* shimmer = new ShimmerReverb(SAMPLING_FREQUENCY);
shimmer->setInputGain(0.55f);
shimmer->setTime(0.75f);
shimmer->setDiffusion(0.8f);
shimmer->setLP(0.7f);
shimmer->reset();
for(size_t i = 0; i < size; ++i)
{
shimmer->processSample(
inSamples[i],
inSamples[i],
outSamplesL[i],
outSamplesR[i]
);
}
saveWaveFile(getResultFile(full_test_name + ".wav", true), outSamplesL, outSamplesR, size, SAMPLING_FREQUENCY, 16);
delete shimmer;
delete[] inSamples;
delete[] outSamplesL;
delete[] outSamplesR;
}
TEST(FXShimmerReverb, TransientNoise)
{
const testing::TestInfo* test_info = testing::UnitTest::GetInstance()->current_test_info();
std::string full_test_name = test_info->test_case_name();
full_test_name += ".";
full_test_name += test_info->name();
const size_t size = static_cast<size_t>(SAMPLING_FREQUENCY);
float32_t* inSamples = new float32_t[size];
for(size_t i = 0; i < size; ++i) inSamples[i] = getRandomValue();
float32_t* outSamplesL = new float32_t[size];
float32_t* outSamplesR = new float32_t[size];
memset(outSamplesL, 0, size * sizeof(float32_t));
memset(outSamplesR, 0, size * sizeof(float32_t));
ShimmerReverb* shimmer = new ShimmerReverb(SAMPLING_FREQUENCY);
shimmer->setInputGain(0.55f);
shimmer->setTime(0.75f);
shimmer->setDiffusion(0.8f);
shimmer->setLP(0.7f);
shimmer->reset();
for(size_t i = 0; i < size; ++i)
{
shimmer->processSample(
inSamples[i],
inSamples[i],
outSamplesL[i],
outSamplesR[i]
);
}
saveWaveFile(getResultFile(full_test_name + ".wav", true), outSamplesL, outSamplesR, size, SAMPLING_FREQUENCY, 16);
delete shimmer;
delete[] inSamples;
delete[] outSamplesL;
delete[] outSamplesR;
}
TEST(FXShimmerReverb, TransientMusic)
{
const testing::TestInfo* test_info = testing::UnitTest::GetInstance()->current_test_info();
std::string full_test_name = test_info->test_case_name();
full_test_name += ".";
full_test_name += test_info->name();
size_t size;
float32_t** inSamples = readWaveFile(AUDIO_SOURCE_FILE, size);
float32_t* outSamplesL = new float32_t[size];
float32_t* outSamplesR = new float32_t[size];
memset(outSamplesL, 0, size * sizeof(float32_t));
memset(outSamplesR, 0, size * sizeof(float32_t));
ShimmerReverb* shimmer = new ShimmerReverb(SAMPLING_FREQUENCY);
shimmer->setInputGain(0.55f);
shimmer->setTime(0.75f);
shimmer->setDiffusion(0.8f);
shimmer->setLP(0.7f);
shimmer->reset();
for(size_t i = 0; i < size; ++i)
{
shimmer->processSample(
inSamples[0][i],
inSamples[1][i],
outSamplesL[i],
outSamplesR[i]
);
}
saveWaveFile(getResultFile(full_test_name + ".wav", true), outSamplesL, outSamplesR, size, SAMPLING_FREQUENCY, 16);
delete shimmer;
delete[] inSamples[0];
delete[] inSamples[1];
delete[] inSamples;
delete[] outSamplesL;
delete[] outSamplesR;
}

@ -61,12 +61,12 @@ struct WaveHeaderDATA {
uint32_t subchunk2Size;
};
float32_t** readWaveFile(const std::string& fileName, unsigned& size);
float32_t** readWaveFile(const std::string& fileName, size_t& size);
void saveWaveFile(const std::string& fileName,
float32_t* LChannel,
float32_t* RChannel,
unsigned size,
size_t size,
int sampleRate,
int bitsPerSample);

@ -4,6 +4,12 @@
#include <iostream>
#include <cassert>
#if defined(DEBUG)
#define ASSERT_NORMALIZED(x) assert(x <= 1.0f && x >= -1.0f)
#else
#define ASSERT_NORMALIZED(x)
#endif
template<typename T>
bool readChunk(std::ifstream& in, uint32_t id, T& chunk)
{
@ -27,7 +33,7 @@ bool readChunk(std::ifstream& in, uint32_t id, T& chunk)
return false;
}
float32_t** readWaveFile(const std::string& fileName, unsigned& size)
float32_t** readWaveFile(const std::string& fileName, size_t& size)
{
std::ifstream file(fileName, std::ios::binary);
if(!file)
@ -147,6 +153,9 @@ float32_t** readWaveFile(const std::string& fileName, unsigned& size)
return nullptr;
}
// ASSERT_NORMALIZED(LChannel[i]);
// ASSERT_NORMALIZED(RChannel[i]);
i += increment;
}
assert(i == size);

@ -7,7 +7,7 @@
void saveWaveFile(const std::string& fileName,
float32_t* LChannel,
float32_t* RChannel,
unsigned size,
size_t size,
int sampleRate,
int bitsPerSample)
{

Loading…
Cancel
Save