Skip to content

Commit

Permalink
updated parameter handling
Browse files Browse the repository at this point in the history
  • Loading branch information
vackva committed May 5, 2024
1 parent 26ade5d commit 25fb854
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 65 deletions.
8 changes: 4 additions & 4 deletions source/PluginParameters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,22 @@ juce::AudioProcessorValueTreeState::ParameterLayout PluginParameters::createPara
params.push_back(std::make_unique<juce::AudioParameterFloat>(AZIM_ID,
AZIM_NAME,
azimRange,
0.f));
defaultAzimParam));

params.push_back(std::make_unique<juce::AudioParameterFloat>(ELEV_ID,
ELEV_NAME,
elevRange,
90.f));
defaultElevParam));

params.push_back(std::make_unique<juce::AudioParameterFloat>(DIST_ID,
DIST_NAME,
distRange,
1.f));
defaultDistParam));

params.push_back( std::make_unique<juce::AudioParameterFloat>(DRY_WET_ID,
DRY_WET_NAME,
dryWetRange,
1.f,
defaultDryWetParam,
percentage_attributes));

for (const auto & param : params) {
Expand Down
5 changes: 5 additions & 0 deletions source/PluginParameters.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ class PluginParameters {
static juce::StringArray getPluginParameterList();
static juce::AudioProcessorValueTreeState::ParameterLayout createParameterLayout();

const inline static float defaultAzimParam { 0.f };
const inline static float defaultElevParam { 90.f };
const inline static float defaultDistParam { 1.f };
const inline static float defaultDryWetParam { 1.f };

private:
inline static juce::StringArray parameterList;
inline static juce::NormalisableRange<float> azimRange {-180.0f, 180.0f, 1.0f},
Expand Down
100 changes: 46 additions & 54 deletions source/PluginProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ AudioPluginAudioProcessor::AudioPluginAudioProcessor()
for (auto & parameterID : PluginParameters::getPluginParameterList()) {
parameters.addParameterListener(parameterID, this);
}

paramAzimuth.store(PluginParameters::defaultAzimParam);
paramElevation.store(PluginParameters::defaultElevParam);
paramDistance.store(PluginParameters::defaultDistParam);
}

AudioPluginAudioProcessor::~AudioPluginAudioProcessor()
Expand Down Expand Up @@ -65,8 +69,7 @@ double AudioPluginAudioProcessor::getTailLengthSeconds() const

int AudioPluginAudioProcessor::getNumPrograms()
{
return 1; // NB: some hosts don't cope very well if you tell them there are 0 programs,
// so this should be at least 1, even if you're not really implementing programs.
return 1;
}

int AudioPluginAudioProcessor::getCurrentProgram()
Expand All @@ -93,19 +96,16 @@ void AudioPluginAudioProcessor::changeProgramName (int index, const juce::String
//==============================================================================
void AudioPluginAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
{
// Use this method as the place to do any pre-playback
// initialisation that you need..
dsp::ProcessSpec processSpec;
processSpec.sampleRate = sampleRate;
processSpec.maximumBlockSize = samplesPerBlock;
processSpec.numChannels = getTotalNumInputChannels();
dsp::ProcessSpec processSpec {sampleRate,
(juce::uint32) samplesPerBlock,
(juce::uint32) getTotalNumInputChannels() };

sofaReader.prepare(sampleRate);

juce::AudioBuffer<float> buffer(2, sofaReader.get_ir_length());
sofaReader.get_hrirs(&buffer, 0, 0, 1);
hrirBuffer.setSize(getTotalNumInputChannels(), sofaReader.get_ir_length());
convolution.prepare(processSpec);
convolution.loadImpulseResponse(std::move(buffer), sampleRate, dsp::Convolution::Stereo::yes, dsp::Convolution::Trim::no, dsp::Convolution::Normalise::no);

std::cout << hrirBuffer.getNumChannels() << std::endl;
updateHRIR();
}

void AudioPluginAudioProcessor::releaseResources()
Expand All @@ -116,52 +116,36 @@ void AudioPluginAudioProcessor::releaseResources()

bool AudioPluginAudioProcessor::isBusesLayoutSupported (const BusesLayout& layouts) const
{
#if JucePlugin_IsMidiEffect
juce::ignoreUnused (layouts);
return true;
#else
// This is the place where you check if the layout is supported.
// In this template code we only support mono or stereo.
// Some plugin hosts, such as certain GarageBand versions, will only
// load plugins that support stereo bus layouts.
if (layouts.getMainOutputChannelSet() != juce::AudioChannelSet::mono()
&& layouts.getMainOutputChannelSet() != juce::AudioChannelSet::stereo())
// Check if both the input and output layouts are stereo.
if (layouts.getMainOutputChannelSet() != juce::AudioChannelSet::stereo() ||
layouts.getMainInputChannelSet() != juce::AudioChannelSet::stereo()) {
return false;

// This checks if the input layout matches the output layout
#if ! JucePlugin_IsSynth
if (layouts.getMainOutputChannelSet() != layouts.getMainInputChannelSet())
return false;
#endif
}

return true;
#endif
}

void AudioPluginAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer,
juce::MidiBuffer& midiMessages)
{
juce::ignoreUnused (midiMessages);

juce::ScopedNoDenormals noDenormals;
auto totalNumInputChannels = getTotalNumInputChannels();
auto totalNumOutputChannels = getTotalNumOutputChannels();

if (hrirChanged.load()) {
updateHRIR();
}

juce::dsp::AudioBlock<float> block(buffer);
juce::dsp::ProcessContextReplacing<float> context(block);

convolution.process(context);

buffer.applyGain(0.5);




}

//==============================================================================
bool AudioPluginAudioProcessor::hasEditor() const
{
return true; // (change this to false if you choose to not supply an editor)
return true;
}

juce::AudioProcessorEditor* AudioPluginAudioProcessor::createEditor()
Expand All @@ -173,32 +157,29 @@ juce::AudioProcessorEditor* AudioPluginAudioProcessor::createEditor()
//==============================================================================
void AudioPluginAudioProcessor::getStateInformation (juce::MemoryBlock& destData)
{
// You should use this method to store your parameters in the memory block.
// You could do that either as raw data, or use the XML or ValueTree classes
// as intermediaries to make it easy to save and load complex data.
juce::ignoreUnused (destData);
auto state = parameters.copyState();
std::unique_ptr<juce::XmlElement> xml (state.createXml());
copyXmlToBinary (*xml, destData);
}

void AudioPluginAudioProcessor::setStateInformation (const void* data, int sizeInBytes)
{
// You should use this method to restore your parameters from this memory block,
// whose contents will have been created by the getStateInformation() call.
juce::ignoreUnused (data, sizeInBytes);
std::unique_ptr<juce::XmlElement> xmlState (getXmlFromBinary (data, sizeInBytes));

if (xmlState.get() != nullptr)
if (xmlState->hasTagName (parameters.state.getType()))
parameters.replaceState (juce::ValueTree::fromXml (*xmlState));
}

void AudioPluginAudioProcessor::parameterChanged(const String &parameterID, float newValue) {
if (parameterID == PluginParameters::AZIM_ID.getParamID()) {
paramAzimuth.store(newValue);
// TODO do this in a better place
// load HRIR for new position
std::cout << "loading new hrirs" << std::endl;
juce::AudioBuffer<float> buffer(2, sofaReader.get_ir_length());
sofaReader.get_hrirs(&buffer, newValue, paramElevation.load(), 1);
convolution.loadImpulseResponse(std::move(buffer), getSampleRate(), dsp::Convolution::Stereo::yes, dsp::Convolution::Trim::no, dsp::Convolution::Normalise::no);

}
else if (parameterID == PluginParameters::ELEV_ID.getParamID()) {
hrirChanged.store(true);
} else if (parameterID == PluginParameters::ELEV_ID.getParamID()) {
paramElevation.store(newValue);
hrirChanged.store(true);
} else if (parameterID == PluginParameters::DIST_ID.getParamID()) {
paramDistance.store(newValue);
}
}

Expand All @@ -218,6 +199,17 @@ juce::AudioProcessorValueTreeState &AudioPluginAudioProcessor::getValueTreeState
return parameters;
}

void AudioPluginAudioProcessor::updateHRIR() {
if (hrirBuffer.getNumChannels() == 0) {
// since we are moving the buffer to the convolution, we have to resize..
// TODO thread safe solution
hrirBuffer.setSize(2, sofaReader.get_ir_length());
}
hrirChanged.store(false);
sofaReader.get_hrirs(hrirBuffer, paramAzimuth.load(), paramElevation.load(), 1);
convolution.loadImpulseResponse(std::move(hrirBuffer), getSampleRate(), dsp::Convolution::Stereo::yes, dsp::Convolution::Trim::no, dsp::Convolution::Normalise::no);
}

//==============================================================================
// This creates new instances of the plugin..
juce::AudioProcessor* JUCE_CALLTYPE createPluginFilter()
Expand Down
6 changes: 6 additions & 0 deletions source/PluginProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,20 @@ class AudioPluginAudioProcessor final : public juce::AudioProcessor, private juc

private:
void parameterChanged (const juce::String& parameterID, float newValue) override;
void updateHRIR();

private:
juce::AudioProcessorValueTreeState parameters;

SofaReader sofaReader;

juce::AudioBuffer<float> hrirBuffer;
dsp::Convolution convolution;

std::atomic<float> paramAzimuth { 0.0f };
std::atomic<float> paramElevation { 0.0f };
std::atomic<float> paramDistance { 0.0f };
std::atomic<bool> hrirChanged { false };

//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioPluginAudioProcessor)
Expand Down
17 changes: 10 additions & 7 deletions source/dsp/SofaReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ class SofaReader {

~SofaReader() {
mysofa_close(*sofa);
sofa.reset();
}

void prepare(int samplerate){
void prepare(double samplerate){
if (sofa != nullptr){
sofa.reset();
}
Expand All @@ -35,21 +36,23 @@ class SofaReader {
return;
}
}

int get_ir_length(){
return ir_length;
}
void get_hrirs(juce::AudioBuffer<float>* buffer, float azim, float elev, float dist){
float* leftir = buffer->getWritePointer(0);
float* rightir = buffer->getWritePointer(1);
float leftdelay;
float rightdelay;

void get_hrirs(juce::AudioBuffer<float>& buffer, float azim, float elev, float dist){
auto leftIR = buffer.getWritePointer(0);
auto rightIR = buffer.getWritePointer(1);
float leftDelay;
float rightDelay;
// convert coordinates to xyz
coordinate_buffer[0] = azim;
coordinate_buffer[1] = elev;
coordinate_buffer[2] = dist;
mysofa_s2c((float *) &coordinate_buffer);

mysofa_getfilter_float(*sofa, coordinate_buffer[0], coordinate_buffer[1], coordinate_buffer[2], leftir, rightir, &leftdelay, &rightdelay);
mysofa_getfilter_float(*sofa, coordinate_buffer[0], coordinate_buffer[1], coordinate_buffer[2], leftIR, rightIR, &leftDelay, &rightDelay);
}

private:
Expand Down

0 comments on commit 25fb854

Please sign in to comment.