Skip to content

Commit

Permalink
first tests on filter buffer passing
Browse files Browse the repository at this point in the history
  • Loading branch information
olbotta committed Jun 2, 2024
1 parent 261ad0b commit c52e98e
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 69 deletions.
15 changes: 8 additions & 7 deletions source/DryWet.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#pragma once
#include <juce_audio_basics/juce_audio_basics.h>
#include <juce_core/juce_core.h>
//#include <juce_SmoothedValue.h>

#include "Parameters.h"
#include <cmath>

Expand Down Expand Up @@ -41,17 +41,18 @@ class DryWet
smoothedDryLevel.applyGain (drySignal, numSamples); //v3 oss: scrive numSamples! non drySignal.getNumSamples()

for (int ch = wetBuffer.getNumChannels(); --ch >= 0;) //ciclo strano di presti che scorre i canali al contrario
{ //add stored dry buffer to wet buffer
wetBuffer.addFrom (ch, 0, drySignal, ch, 0, numSamples); //v1,v3
// wetBuffer.addFrom(ch, 0, drySignal, ch, 0, numSamples, dryLevel); //v2, più compatta e ottimizzata
{
wetBuffer.addFrom (ch, 0, drySignal, ch, 0, numSamples);
}
}

void setDryWetRatio (const float newValue)
{
dryWetRatio = newValue;
smoothedWetLevel.setTargetValue (sqrt (1 - dryWetRatio));
smoothedDryLevel.setTargetValue (sqrt (dryWetRatio));
smoothedWetLevel.setCurrentAndTargetValue (sqrt (1 - dryWetRatio));
smoothedDryLevel.setCurrentAndTargetValue (sqrt (dryWetRatio));
//smoothedWetLevel.setTargetValue (sqrt (1 - dryWetRatio));
//smoothedDryLevel.setTargetValue (sqrt (dryWetRatio));
}

private:
Expand All @@ -61,5 +62,5 @@ class DryWet

juce::AudioBuffer<float> drySignal;

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(DryWet);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(DryWet)
};
5 changes: 3 additions & 2 deletions source/Parameters.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#pragma once

//#include <juce_audio_processors/juce_audio_processors.h>
#include <juce_audio_processors/juce_audio_processors.h>
#include <juce_audio_utils/juce_audio_utils.h>

#define SMOOTHING_TIME 0.04
//#define SMOOTHING_TIME 0.0f
#define SMOOTHING_TIME 0.04f

// Actual parameters
#define NAME_DW "dw"
Expand Down
6 changes: 2 additions & 4 deletions source/PluginProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,15 @@ FilterAudioProcessor::FilterAudioProcessor()
: parameters (*this, nullptr, "Filter Parameters", Parameters::createParameterLayout())
{
parameters.addParameterListener (NAME_DW, this);
parameters.addParameterListener (NAME_CUTOFF, static_cast<Listener*> (this));
parameters.addParameterListener (NAME_CUTOFF, this);
drywetter.setDryWetRatio (DEFAULT_DW);
cutoff = 1000.0f;

tptFilter.setType(juce::dsp::StateVariableTPTFilterType::highpass);
}

//==============================================================================
void FilterAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
{
this->fs = sampleRate;
drywetter.prepareToPlay (sampleRate, samplesPerBlock);

juce::dsp::ProcessSpec spec { sampleRate, static_cast<juce::uint32> (samplesPerBlock), 2 };
Expand All @@ -34,7 +33,6 @@ void FilterAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, juce:
juce::dsp::ProcessContextReplacing<float> context (block);
tptFilter.process(context);

// Miscelo il segnale pulito salvato in drywetter con quello processato da delay
drywetter.merge (buffer);
}

Expand Down
6 changes: 1 addition & 5 deletions source/PluginProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@
#include "DryWet.h"
#include "Parameters.h"
#include <juce_dsp/juce_dsp.h>
//#include <juce_audio_processors/juce_audio_processors.h>
//#include <juce_data_structures/juce_data_structures.h>

#include <juce_audio_processors/juce_audio_processors.h>

class FilterAudioProcessor : public juce::AudioProcessor, public juce::AudioProcessorValueTreeState::Listener
{
Expand Down Expand Up @@ -49,10 +47,8 @@ class FilterAudioProcessor : public juce::AudioProcessor, public juce::AudioPro

juce::AudioProcessorValueTreeState parameters;
DryWet drywetter;
float cutoff;
juce::dsp::StateVariableTPTFilter<float> tptFilter;
juce::dsp::ProcessorDuplicator<juce::dsp::StateVariableTPTFilter<float>, juce::dsp::IIR::Coefficients <float>> filter;
double fs;

//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FilterAudioProcessor)
Expand Down
4 changes: 2 additions & 2 deletions tests/Helpers.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#include "Helpers.h"

juce::AudioBuffer<float>* Helpers::noiseGenerator(int channels, int samples)
std::unique_ptr<juce::AudioBuffer<float>> Helpers::noiseGenerator(int channels, int samples)
{
juce::AudioBuffer<float> *buffer = new juce::AudioBuffer<float>(channels, samples);
auto buffer = std::make_unique<juce::AudioBuffer<float>>(channels, samples);

//Fill with random values ranging from -1 to 1
for (int i = 0; i < channels; i++) {
Expand Down
2 changes: 1 addition & 1 deletion tests/Helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

class Helpers {
public:
static juce::AudioBuffer<float>* noiseGenerator(int channels = 2, int samples = 4096);
static std::unique_ptr<juce::AudioBuffer<float>> noiseGenerator(int channels = 2, int samples = 4096);
static juce::AudioBuffer<float>* generateIncreasingAudioSampleBuffer(int channels = 2, int samples = 4096);
static juce::MemoryMappedAudioFormatReader* readSineSweep();
static void writeBufferToFile(juce::AudioBuffer<float>* buffer, juce::String path);
Expand Down
67 changes: 32 additions & 35 deletions tests/Matchers.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
#include "Settings.h"
#include <juce_dsp/juce_dsp.h>
#include <juce_audio_processors/juce_audio_processors.h>
#include <catch2/catch_test_macros.hpp>
#include <catch2/matchers/catch_matchers_templated.hpp>
#include <utility>

//TODO: tipizzare con type
juce::Array<float> getBinEnergies (const juce::dsp::FFT* forwardFFT, juce::AudioBuffer<float> in)
{
auto* inRead = in.getArrayOfReadPointers();
Expand Down Expand Up @@ -36,29 +40,25 @@ juce::Array<float> getBinEnergies (const juce::dsp::FFT* forwardFFT, juce::Audio
return binEnergies;
}

class AudioBufferMatcher : public Catch::Matchers::MatcherBase<juce::AudioBuffer<float>>
template<typename Type>
struct AudioBufferMatcher : Catch::Matchers::MatcherGenericBase
{
juce::AudioBuffer<float> otherBuffer;

public:
AudioBufferMatcher (juce::AudioBuffer<float> const& other) : otherBuffer (other) {}
AudioBufferMatcher (juce::AudioBuffer<Type> const& buffer) : buffer (buffer) {}

bool match (juce::AudioBuffer<float> const& in) const override
bool match (juce::AudioBuffer<Type> const& other) const
{
//return in >= m_begin && in <= m_end;
auto* inRead = in.getArrayOfReadPointers();
auto* othRead = otherBuffer.getArrayOfReadPointers();

if (in.getNumChannels() != otherBuffer.getNumChannels() || in.getNumSamples() != otherBuffer.getNumSamples())
{
if (buffer.getNumChannels() != other.getNumChannels() || buffer.getNumSamples() != other.getNumSamples())
return false;
}

for (int ch = 0; ch < in.getNumChannels(); ++ch)
auto* inRead = buffer.getArrayOfReadPointers();
auto* othRead = other.getArrayOfReadPointers();

for (int ch = 0; ch < buffer.getNumChannels(); ++ch)
{
for (int sam = 0; sam < in.getNumSamples(); ++sam)
for (int sam = 0; sam < buffer.getNumSamples(); ++sam)
{
if (std::fabs (inRead[ch][sam] - othRead[ch][sam]) > std::numeric_limits<float>::epsilon())
if (std::fabs (inRead[ch][sam] - othRead[ch][sam]) > std::numeric_limits<Type>::epsilon())
{
return false;
}
Expand All @@ -70,23 +70,28 @@ class AudioBufferMatcher : public Catch::Matchers::MatcherBase<juce::AudioBuffer

std::string describe() const override
{
std::ostringstream ss;
ss << "AudioBuffers are the same ";
return ss.str();
return "AudioBuffers have the same values and lenght";
}

private:
juce::AudioBuffer<Type> buffer;
};

AudioBufferMatcher AudioBuffersMatch (juce::AudioBuffer<float> other)
{
return { other };
template<typename Type>
auto AudioBuffersMatch (juce::AudioBuffer<Type> buffer) -> AudioBufferMatcher<Type>{
return AudioBufferMatcher<Type>{buffer};
}

class AudioBufferEnergyMatcher : public Catch::Matchers::MatcherBase<juce::AudioBuffer<float>>
{
juce::AudioBuffer<float> otherBuffer;

public:
AudioBufferEnergyMatcher (juce::AudioBuffer<float> other) : otherBuffer (other), forwardFFT (fft_order), window { fft_size, juce::dsp::WindowingFunction<float>::WindowingMethod::hann } {}
AudioBufferEnergyMatcher (juce::AudioBuffer<float> other) :
otherBuffer (std::move(other)),
forwardFFT (fft_order)
//window { fft_size, juce::dsp::WindowingFunction<float>::WindowingMethod::hann }
{}

bool match (juce::AudioBuffer<float> const& in) const override
{
Expand All @@ -107,31 +112,23 @@ class AudioBufferEnergyMatcher : public Catch::Matchers::MatcherBase<juce::Audio
othPower += othEnergies[i];
}

if (inPower < othPower)
{
return true;
}
else
{
return false;
}
return inPower < othPower;

}

std::string describe() const override
{
std::ostringstream ss;
ss << "Other buffer has higher total energy";
return ss.str();
return "Other buffer has higher total energy";
}

private:
juce::dsp::FFT forwardFFT;
juce::dsp::WindowingFunction<float> window;
//juce::dsp::WindowingFunction<float> window;
};

AudioBufferEnergyMatcher AudioBufferHigherEnergy (juce::AudioBuffer<float> other)
{
return { other };
return AudioBufferEnergyMatcher(other);
}

class AudioBufferMaxEnergyMatcher : public Catch::Matchers::MatcherBase<juce::AudioBuffer<float>>
Expand Down
28 changes: 15 additions & 13 deletions tests/PluginBasics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,48 +9,50 @@ TEST_CASE ("one is equal to one", "[dummy]")
REQUIRE (1 == 1);
}

TEST_CASE ("Wet Parameter", "[parameters]")
TEST_CASE ("Wet Parameter influence on buffer", "[parameters]")
{
auto testPluginProcessor = std::make_unique<FilterAudioProcessor>();

juce::AudioBuffer<float>* buffer = Helpers::noiseGenerator();
juce::AudioBuffer<float> originalBuffer (*buffer);
auto buffer = Helpers::noiseGenerator();
auto originalBuffer (*buffer);

juce::MidiBuffer midiBuffer;

testPluginProcessor->prepareToPlay (44100, 4096);

auto const* parameters = testPluginProcessor->getParameters();
juce::RangedAudioParameter* pParam = parameters->getParameter ("WET");
juce::RangedAudioParameter* pParam = parameters->getParameter (NAME_DW);

SECTION ("wet=0 implies no change to the signal")
SECTION ("dry/wet ratio = 1.0f implies no change to the signal")
{
pParam->setValueNotifyingHost (0.0f);
pParam->setValueNotifyingHost (1.0f);
testPluginProcessor->processBlock (*buffer, midiBuffer);

CHECK_THAT (*buffer, AudioBuffersMatch (originalBuffer));
}

SECTION ("wet!=0 implies change to the signal")
SECTION ("dry/wet ratio < 1.0f implies change to the signal")
{
auto value = GENERATE (0.1f, 0.5f, 1.0f);
auto value = GENERATE (0.1f, 0.5f, 0.0f);

pParam->setValueNotifyingHost (value);
testPluginProcessor->processBlock (*buffer, midiBuffer);

CHECK_THAT (*buffer, !AudioBuffersMatch (originalBuffer));
}

// TEARDOWN
testPluginProcessor->releaseResources();
}

TEST_CASE ("Big Buffer Wet Parameter", "[parameters]")
/*TEST_CASE ("Big Buffer Wet Parameter", "[parameters]")
{
int blockCount = GENERATE (1, 256); //1 corresponds to previous case
auto testPluginProcessor = std::make_unique<FilterAudioProcessor>();
juce::AudioBuffer<float>* buffer = Helpers::noiseGenerator (2, 4096 * blockCount);
juce::AudioBuffer<float> originalBuffer (*buffer);
//ImageProcessing::drawAudioBufferImage(buffer, "RandomWet");
auto buffer = Helpers::noiseGenerator (2, 4096 * blockCount);
auto originalBuffer (*buffer);
juce::MidiBuffer midiBuffer;
Expand Down Expand Up @@ -140,4 +142,4 @@ TEST_CASE ("Filter", "[functionality]")
// // CHECK_THAT (originalBuffer, !AudioBufferHigherEnergy (*buffer));
// // //CHECK_THAT (*buffer, AudioBufferCheckMaxEnergy (maxEnergies));
// }
}
}*/

0 comments on commit c52e98e

Please sign in to comment.