Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
247 changes: 136 additions & 111 deletions Source/PluginProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@
#include "PluginProcessor.h"
#include "PluginEditor.h"

#define STEREO_OUTPUT
//#define MUTE_OVER_0DBFS

const float ScatteringDelayReverbAudioProcessor::ROOM_HEIGHT = 3.f;
const float ScatteringDelayReverbAudioProcessor::MAX_ROOM_SIZE = 100.f;

//==============================================================================
ScatteringDelayReverbAudioProcessor::ScatteringDelayReverbAudioProcessor()
#ifndef JucePlugin_PreferredChannelConfigurations
Expand All @@ -23,43 +29,50 @@ ScatteringDelayReverbAudioProcessor::ScatteringDelayReverbAudioProcessor()
#endif
)
#endif
,
roomSizeLast(8.0f)
{

addParameter (roomSize = new AudioParameterFloat ("roomSize", // parameter ID
"Room size", // parameter name
NormalisableRange<float> (0.0f, 100.0f),
8.0f)); // default value


addParameter (absorption = new AudioParameterFloat ("absorption", // parameter ID
"Wall Reflectivity", // parameter name
NormalisableRange<float> (0.0f, 1.0),
0.5f)); // default value

addParameter (dryWet = new AudioParameterFloat ("dryWet", // parameter ID
"Dry/Wet", // parameter name
NormalisableRange<float> (0.0f, 1.0f),
0.5f)); // default value

addParameter (sourceXPosition = new AudioParameterFloat ("sourceXPosition", // parameter ID
"Source X Position", // parameter name
NormalisableRange<float> (0.0f, roomSize->get()),
roomSize->get()/2.0)); // default value

addParameter (sourceYPosition = new AudioParameterFloat ("sourceYPosition", // parameter ID
"Source Y Position", // parameter name
NormalisableRange<float> (0.0f, roomSize->get()),
6.0)); // default value

addParameter (micXPosition = new AudioParameterFloat ("micXPosition", // parameter ID
"Mic X Position", // parameter name
NormalisableRange<float> (0.0f, roomSize->get()),
2.0)); // default value

addParameter (micYPosition = new AudioParameterFloat ("micYPosition", // parameter ID
"Mic Y Position", // parameter name
NormalisableRange<float> (0.0f, roomSize->get()),
roomSize->get()/2.0)); // default value
network = new SDN::Network(44100); // placeholder network - to be reset before playback

const float initSrcPosX = roomSizeLast / 2;
const float initSrcPosY = roomSizeLast / 2;
const float initMicPosX = roomSizeLast / 4;
const float initMicPosY = roomSizeLast / 2;

addParameter(roomSize = new AudioParameterFloat("roomSize", // parameter ID
"Room size", // parameter name
NormalisableRange<float>(0.0f, MAX_ROOM_SIZE),
roomSizeLast)); // default value

addParameter(absorption = new AudioParameterFloat("absorption", // parameter ID
"Wall Reflectivity", // parameter name
NormalisableRange<float>(0.0f, 1.0),
0.5f)); // default value

addParameter(dryWet = new AudioParameterFloat("dryWet", // parameter ID
"Source X Position", // parameter name
NormalisableRange<float>(0.0f, 1.0f),
0.5f)); // default value

addParameter(sourceXPosition = new AudioParameterFloat("sourceXPosition", // parameter ID
"Source X Position", // parameter name
NormalisableRange<float>(0.0f, MAX_ROOM_SIZE),
initSrcPosX)); // default value

addParameter(sourceYPosition = new AudioParameterFloat("sourceYPosition", // parameter ID
"Source Y Position", // parameter name
NormalisableRange<float>(0.0f, MAX_ROOM_SIZE),
initSrcPosY)); // default value

addParameter(micXPosition = new AudioParameterFloat("micXPosition", // parameter ID
"Mic X Position", // parameter name
NormalisableRange<float>(0.0f, MAX_ROOM_SIZE),
initMicPosX)); // default value

addParameter(micYPosition = new AudioParameterFloat("micYPosition", // parameter ID
"Mic Y Position", // parameter name
NormalisableRange<float>(0.0f, MAX_ROOM_SIZE),
initMicPosY)); // default value
}

ScatteringDelayReverbAudioProcessor::~ScatteringDelayReverbAudioProcessor()
Expand Down Expand Up @@ -131,18 +144,8 @@ void ScatteringDelayReverbAudioProcessor::changeProgramName (int index, const St
//==============================================================================
void ScatteringDelayReverbAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
{
// Use this method as the place to do any pre-playback
// initialisation that you need..
float width, length, height;
width = 8;
length = 8;
height = 8;

network = new SDN::Network(sampleRate, width, length, height);
network->setSourcePosition(6.0, length/2, height/2);
network->setMicPosition(2.0, length/2, height/2);
// network->setAbsorptionAmount(absorption->get());

resetNetwork();

DBG("azimuths");
DBG(network->getSourceAzimuth());
for(int node = 0; node < 6; node++) {
Expand Down Expand Up @@ -192,69 +195,58 @@ void ScatteringDelayReverbAudioProcessor::processBlock (AudioBuffer<float>& buff
auto totalNumInputChannels = getTotalNumInputChannels();
auto totalNumOutputChannels = getTotalNumOutputChannels();
const int numSamples = buffer.getNumSamples(); // How many samples in the buffer


if (roomSize->get() != roomSizeLast)
{
resetNetwork();
roomSizeLast = roomSize->get();
}

for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
buffer.clear (i, 0, numSamples);


// In case we have more outputs than inputs, this code clears any output
// channels that didn't contain input data, (because these aren't
// guaranteed to be empty - they may contain garbage).
// This is here to avoid people getting screaming feedback
// when they first compile a plugin, but obviously you don't need to keep
// this code if your algorithm always overwrites all the output channels.
for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
buffer.clear (i, 0, numSamples);

// This is the place where you'd normally do the guts of your plugin's
// audio processing...
// Make sure to reset the state if your inner loop is processing
// the samples and the outer loop is handling the channels.
// Alternatively, you can process the samples with the channels
// interleaved by keeping the same state.

for (int i = 0; i < numSamples; ++i)
buffer.clear(i, 0, numSamples);

for (int i = 0; i < numSamples; ++i)
{
float in = 0.0;
for (int channel = 0; channel < totalNumInputChannels; ++channel)
{
float in = 0.0;
for (int channel = 0; channel < totalNumInputChannels; ++channel)
{
in += buffer.getReadPointer (channel)[i];
}

in /= totalNumInputChannels; // sum to mono

// auto outDry = network->positionSource(in); // get stereo positioned source output (DRY)
// auto outWet = network->scatterStereo(in); // get stereo reverb output (WET)

// if position changes, get new positions
// get struct of streams
// set source/mic position

auto outMono = network->scatterMono(in/3.0);

buffer.getWritePointer (0)[i] = 0.0;
buffer.getWritePointer (1)[i] = 0.0;

float dryMix = fmin(dryWet->get() * 2, 1.0); // crossfade dry wet amounts (at 0.5 both have gain of 1)
float wetMix = fmin((1 - dryWet->get()) * 2, 1.0);

// float outL = dryMix * outDry.L + wetMix * outWet.L;
// float outR = dryMix * outDry.R + wetMix * outWet.R;

buffer.getWritePointer (0)[i] = outMono;
buffer.getWritePointer (1)[i] = outMono;

// if (outL <= 1 && outR <= 1) {
// buffer.getWritePointer (0)[i] = outL;
// buffer.getWritePointer (1)[i] = outR;
// }
// else {
// DBG("PEAKING"); // TO SAVE YOUR EARS
// }
in += buffer.getReadPointer(channel)[i];
}

// ..do something to the data...
// }
in /= totalNumInputChannels; // sum to mono

SDN::StereoOutput outDry = network->positionSource(in); // get stereo positioned source output (DRY)
SDN::StereoOutput outWet;
float outL, outR;

#ifdef STEREO_OUTPUT
outWet = network->scatterStereo(in); // get stereo reverb output (WET)
#else
outWet.L = outWet.R = network->scatterMono(in / 3.0);
#endif

float dryMix = fmin(dryWet->get() * 2, 1.0); // crossfade dry wet amounts (at 0.5 both have gain of 1)
float wetMix = fmin((1 - dryWet->get()) * 2, 1.0);

outL = dryMix * outDry.L + wetMix * outWet.L;
outR = dryMix * outDry.R + wetMix * outWet.R;

#ifdef MUTE_OVER_0DBFS
if (outL <= 1 && outR <= 1) {
#endif

buffer.getWritePointer(0)[i] = outL;
buffer.getWritePointer(1)[i] = outR;

#ifdef MUTE_OVER_0DBFS
}
else {
buffer.getWritePointer(0)[i] = 0.0f;
buffer.getWritePointer(1)[i] = 0.0f;
DBG("PEAKING"); // TO SAVE YOUR EARS
}
#endif
}
}

//==============================================================================
Expand Down Expand Up @@ -282,12 +274,38 @@ void ScatteringDelayReverbAudioProcessor::setStateInformation (const void* data,
// whose contents will have been created by the getStateInformation() call.
}

void ScatteringDelayReverbAudioProcessor::resetNetwork()
{
delete network;

const float width = roomSize->get();
const float length = roomSize->get();
const float height = ROOM_HEIGHT;

// ensure that source & mic are within room bounds
const float srcX = std::min(length, sourceXPosition->get());
const float srcY = std::min(width, sourceYPosition->get());
const float micX = std::min(length, micXPosition->get());
const float micY = std::min(width, micYPosition->get());

sourceXPosition->setValueNotifyingHost(sourceXPosition->getNormalisableRange().convertTo0to1(srcX));
sourceYPosition->setValueNotifyingHost(sourceYPosition->getNormalisableRange().convertTo0to1(srcY));
micXPosition->setValueNotifyingHost(micXPosition->getNormalisableRange().convertTo0to1(micX));
micYPosition->setValueNotifyingHost(micYPosition->getNormalisableRange().convertTo0to1(micY));

network = new SDN::Network(getSampleRate(), width, length, height);
network->setSourcePosition(srcX, srcY, height / 2);
network->setMicPosition(micX, micY, height / 2);
network->setAbsorptionAmount(absorption->get());
}

// method for updating source position only when slider changes
void ScatteringDelayReverbAudioProcessor::updateSourcePosition(float x, float y, float z)
{
sourceXPosition->setValueNotifyingHost(x);
sourceYPosition->setValueNotifyingHost(y);
// network->setSourcePosition(sourceXPosition->get(), sourceYPosition->get(), roomSize->get()/2);
sourceXPosition->setValueNotifyingHost(sourceXPosition->getNormalisableRange().convertTo0to1(x));
sourceYPosition->setValueNotifyingHost(sourceYPosition->getNormalisableRange().convertTo0to1(y));
network->setSourcePosition(x, y, z);

DBG("azimuths");
DBG(network->getSourceAzimuth());
for(int node = 0; node < 6; node++) {
Expand All @@ -301,9 +319,16 @@ void ScatteringDelayReverbAudioProcessor::updateSourcePosition(float x, float y,
}
}

void ScatteringDelayReverbAudioProcessor::updateMicPosition(float x, float y, float z)
{
micXPosition->setValueNotifyingHost(micXPosition->getNormalisableRange().convertTo0to1(x));
micYPosition->setValueNotifyingHost(micYPosition->getNormalisableRange().convertTo0to1(y));
network->setMicPosition(x, y, z);
}

void ScatteringDelayReverbAudioProcessor::setAbsorption(const float amount) {
absorption->setValueNotifyingHost(amount);
// network->setAbsorptionAmount(amount);
network->setAbsorptionAmount(amount);
}

//==============================================================================
Expand Down
9 changes: 8 additions & 1 deletion Source/PluginProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
#pragma once

#include "../JuceLibraryCode/JuceHeader.h"
#include <Network.h>
#include "Reverb/Network.h"

using namespace juce;

//==============================================================================
/**
Expand Down Expand Up @@ -57,7 +58,9 @@ class ScatteringDelayReverbAudioProcessor : public AudioProcessor
void getStateInformation (MemoryBlock& destData) override;
void setStateInformation (const void* data, int sizeInBytes) override;

void resetNetwork();
void updateSourcePosition(float x, float y, float z);
void updateMicPosition(float x, float y, float z);
void setAbsorption(const float amount);

AudioParameterFloat* sourceXPosition;
Expand All @@ -70,6 +73,10 @@ class ScatteringDelayReverbAudioProcessor : public AudioProcessor
AudioParameterFloat* absorption;
AudioParameterFloat* dryWet;

static const float ROOM_HEIGHT;
static const float MAX_ROOM_SIZE;
float roomSizeLast;

private:
SDN::Network *network;

Expand Down
23 changes: 16 additions & 7 deletions Source/Reverb/Delay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ namespace SDN {
setAirAbsorption();
}

Delay::~Delay()
{
delete[] buffer;
}

Delay* Delay::fromDistance(float sampleRate, float distance, float maxDistance)
{
return new Delay(sampleRate, (sampleRate * distance) / SDN::c, (sampleRate * maxDistance) / SDN::c);
Expand Down Expand Up @@ -91,8 +96,10 @@ namespace SDN {
// reads next sample
float Delay::read() {
float out = 0.0;

const bool isReadPointerFractional = floor(readPointer) != readPointer;

// if(fractional) {
if(isReadPointerFractional) {
// get high sample for linearly interpolation
int highPointer = floor(readPointer + 1.0);
if(highPointer >= bufferLength) highPointer -= bufferLength;
Expand All @@ -107,12 +114,14 @@ namespace SDN {
readPointer += bufferLength;
else if (readPointer >= bufferLength)
readPointer -= bufferLength;
// } else {
// out = buffer[readPointer];
// readPointer++;
//
// readPointer = (readPointer + bufferLength) % bufferLength;
// }
}
else {
out = buffer[(int)readPointer];
incrementReadPointer();

if (readPointer >= bufferLength)
readPointer -= bufferLength;
}

return out;
}
Expand Down
2 changes: 1 addition & 1 deletion Source/Reverb/Delay.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ namespace SDN {
Delay() {};
Delay(float sampleRate, int delayInSamples, int maxBuffer);
// Delay(float sampleRate, float distance);
virtual ~Delay() {}
virtual ~Delay();
};
}

Expand Down
Loading