Skip to content

Commit

Permalink
PlayheadHelpers Added to Manage the AudioPlayHead Object
Browse files Browse the repository at this point in the history
  • Loading branch information
RachelMaryamLocke committed Nov 1, 2023
1 parent e13032c commit 00bd58c
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 34 deletions.
7 changes: 6 additions & 1 deletion src/BYOD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@ BYOD::BYOD() : chowdsp::PluginBase<BYOD> (&undoManager),

pluginSettings->initialise (settingsFilePath);
procs = std::make_unique<ProcessorChain> (procStore, vts, presetManager, paramForwarder, [&] (int l)
{ updateSampleLatency (l); });
{ updateSampleLatency (l); }); //make unique
paramForwarder = std::make_unique<ParamForwardManager> (vts, *procs);
presetManager = std::make_unique<PresetManager> (procs.get(), vts);
stateManager = std::make_unique<StateManager> (vts, *procs, *presetManager);
// playheadHelper = std::make_unique<PlayheadHelpers> ();

#if JUCE_IOS
LookAndFeel::setDefaultLookAndFeel (lnfAllocator->getLookAndFeel<chowdsp::ChowLNF>());
Expand Down Expand Up @@ -66,6 +67,10 @@ void BYOD::processBlock (AudioBuffer<float>& buffer, MidiBuffer& midi)
const juce::ScopedNoDenormals noDenormals {};
AudioProcessLoadMeasurer::ScopedTimer loadTimer { loadMeasurer, buffer.getNumSamples() };

//get playhead
playheadHelper.process(getPlayHead(), buffer.getNumSamples());
procs->setPlayheadHelpersReference(playheadHelper);

// push samples into bypass delay
bypassScratchBuffer.makeCopyOf (buffer, true);
processBypassDelay (bypassScratchBuffer);
Expand Down
5 changes: 4 additions & 1 deletion src/BYOD.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "processors/ProcessorStore.h"
#include "processors/chain/ProcessorChain.h"
#include "processors/PlayheadHelpers.h"
#include "state/ParamForwardManager.h"
#include "state/StateManager.h"

Expand Down Expand Up @@ -54,7 +55,7 @@ class BYOD : public chowdsp::PluginBase<BYOD>
[[maybe_unused]] chowdsp::SharedLNFAllocator lnfAllocator; // keep alive!

ProcessorStore procStore;
std::unique_ptr<ProcessorChain> procs;
std::unique_ptr<ProcessorChain> procs; //ptrs to processor chain
[[maybe_unused]] std::unique_ptr<ParamForwardManager> paramForwarder;

AudioBuffer<float> bypassScratchBuffer;
Expand All @@ -68,6 +69,8 @@ class BYOD : public chowdsp::PluginBase<BYOD>

std::unique_ptr<chowdsp::OpenGLHelper> openGLHelper = nullptr;

PlayheadHelpers playheadHelper;

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BYOD)
};

Expand Down
8 changes: 8 additions & 0 deletions src/processors/BaseProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,14 @@ void BaseProcessor::processAudioBlock (AudioBuffer<float>& buffer)
processAudio (buffer);
}

void BaseProcessor::setPlayheadHelpersReference(PlayheadHelpers& helpers) {
playheadHelpersReference = &helpers;
}

PlayheadHelpers& BaseProcessor::getPlayheadHelpersReference() {
return *playheadHelpersReference;
}

float BaseProcessor::getInputLevelDB (int portIndex) const noexcept
{
jassert (isPositiveAndBelow (portIndex, numInputs));
Expand Down
5 changes: 5 additions & 0 deletions src/processors/BaseProcessor.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include "JuceProcWrapper.h"
#include "processors/PlayheadHelpers.h"

enum ProcessorType
{
Expand Down Expand Up @@ -110,6 +111,8 @@ class BaseProcessor : private JuceProcWrapper
void prepareProcessing (double sampleRate, int numSamples);
void freeInternalMemory();
void processAudioBlock (AudioBuffer<float>& buffer);
void setPlayheadHelpersReference(PlayheadHelpers& helpers);
PlayheadHelpers& getPlayheadHelpersReference();

// methods for working with port input levels
float getInputLevelDB (int portIndex) const noexcept;
Expand Down Expand Up @@ -302,6 +305,8 @@ class BaseProcessor : private JuceProcWrapper
StringArray popupMenuParameterIDs;
OwnedArray<ParameterAttachment> popupMenuParameterAttachments;

PlayheadHelpers* playheadHelpersReference;

const base_processor_detail::PortTypesVector inputPortTypes;
const base_processor_detail::PortTypesVector outputPortTypes;

Expand Down
25 changes: 25 additions & 0 deletions src/processors/PlayheadHelpers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once

#include <pch.h>

struct PlayheadHelpers
{
static void prepare(double sampleRate, int maxBlockSize)
{
ignoreUnused(sampleRate, maxBlockSize);
}

void process(AudioPlayHead* playHead, int numSamples)
{
ignoreUnused(numSamples);
if (playHead != nullptr)
{
info = *playHead->getPosition();
bpm.store(*info.getBpm());
}
}

std::atomic<double> bpm;
AudioPlayHead::PositionInfo info;
};

8 changes: 8 additions & 0 deletions src/processors/chain/ProcessorChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ void ProcessorChain::createParameters (Parameters& params)
ChainIOProcessor::createParameters (params);
}

void ProcessorChain::setPlayheadHelpersReference(PlayheadHelpers& helpers) {
playheadHelpersReference = &helpers;
}

void ProcessorChain::initializeProcessors()
{
const auto osFactor = ioProcessor.getOversamplingFactor();
Expand All @@ -69,7 +73,11 @@ void ProcessorChain::initializeProcessors()
for (int i = procs.size() - 1; i >= 0; --i)
{
if (auto* proc = procs[i])
{
if (proc->getName() == "Delay")
proc->setPlayheadHelpersReference(*playheadHelpersReference);
proc->prepareProcessing (osSampleRate, osSamplesPerBlock);
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/processors/chain/ProcessorChain.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class ProcessorChain : private AudioProcessorValueTreeState::Listener
auto& getProcessors() { return procs; }
const auto& getProcessors() const { return procs; }
ProcessorStore& getProcStore() { return procStore; }
void setPlayheadHelpersReference(PlayheadHelpers& helpers);

InputProcessor& getInputProcessor() { return inputProcessor; }
OutputProcessor& getOutputProcessor() { return outputProcessor; }
Expand Down Expand Up @@ -78,6 +79,7 @@ class ProcessorChain : private AudioProcessorValueTreeState::Listener
std::unique_ptr<ParamForwardManager>& paramForwardManager;

MidiBuffer internalMidiBuffer;
PlayheadHelpers* playheadHelpersReference = nullptr;

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProcessorChain)
};
81 changes: 49 additions & 32 deletions src/processors/other/Delay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ const String tempoSyncTag = "tempo_sync";
const String tempoSyncAmountTag = "delay_time_type";
} // namespace

DelayModule::DelayModule (UndoManager* um) : BaseProcessor ("Delay", createParameterLayout(), um)
DelayModule::DelayModule (UndoManager* um) : BaseProcessor ("Delay", createParameterLayout(), um),
bpm(getPlayheadHelpersReference().bpm)
{
using namespace ParameterHelpers;
loadParameterPointer (freqParam, vts, freqTag);
Expand Down Expand Up @@ -240,37 +241,49 @@ void DelayModule::processAudio (AudioBuffer<float>& buffer)
std::cout << "Delay Time In Ms..." << std::endl;
delaySmooth.setTargetValue (fs * *delayTimeMsParam * 0.001f); //delay time in samples (if tempo-sync change the calculation here?)
}
else
{
float delayInSamples = fs * 200 * 0.001f; //fallback delay
std::cout << "Delay Time In Notes..." << std::endl;
auto positionInfo = audioPlayHead.getPosition();
// auto hardcodedBpm = 120;
auto bpm = positionInfo->getBpm();
auto noteDivision = (int)*delayTimeTempoSyncParam;
if (noteDivision == 0)
{
delayInSamples = calculateTempoSyncDelayTime(2.0f, *bpm);
std::cout << "1/2 Note Delay..." << std::endl;
}
else if (noteDivision == 1)
{
delayInSamples = calculateTempoSyncDelayTime(1.0f, *bpm);
std::cout << "1/4 Note Delay..." << std::endl;
}
else if (noteDivision == 2)
{
delayInSamples = calculateTempoSyncDelayTime (0.5f, *bpm);
std::cout << "1/8 Note Delay..." << std::endl;
}
else if (noteDivision == 3)
{
delayInSamples = calculateTempoSyncDelayTime (0.75f, *bpm);
std::cout << "1/8 Note Dotted Delay..." << std::endl;
}
delaySmooth.setTargetValue (delayInSamples);
}
freqSmooth.setTargetValue (*freqParam);

// PlayheadHelpers& PlayheadHelpersRef = this->getPlayheadHelpersReference();
// std::cout << playheadHelpersReference.bpmDouble << std::endl;
// double tempo = bpm.load();
// std::cout << "My BPM: " << tempo << std::endl;
// int myIntVal = intRef.load();
// std::cout << "My Int: " << myIntVal << std::endl;


// bpm = PlayheadHelpersRef.bpm.load();

// std::cout << "Playhead Helper BPM: " << bpm << std::endl;
// else
// {
// float delayInSamples = fs * 200 * 0.001f; //fallback delay
// std::cout << "Delay Time In Notes..." << std::endl;
// auto positionInfo = audioPlayHead.getPosition();
//// auto hardcodedBpm = 120;
// auto bpm = positionInfo->getBpm();
// auto noteDivision = (int)*delayTimeTempoSyncParam;
// if (noteDivision == 0)
// {
// delayInSamples = calculateTempoSyncDelayTime(2.0f, *bpm);
// std::cout << "1/2 Note Delay..." << std::endl;
// }
// else if (noteDivision == 1)
// {
// delayInSamples = calculateTempoSyncDelayTime(1.0f, *bpm);
// std::cout << "1/4 Note Delay..." << std::endl;
// }
// else if (noteDivision == 2)
// {
// delayInSamples = calculateTempoSyncDelayTime (0.5f, *bpm);
// std::cout << "1/8 Note Delay..." << std::endl;
// }
// else if (noteDivision == 3)
// {
// delayInSamples = calculateTempoSyncDelayTime (0.75f, *bpm);
// std::cout << "1/8 Note Dotted Delay..." << std::endl;
// }
// delaySmooth.setTargetValue (delayInSamples);
// }
// freqSmooth.setTargetValue (*freqParam);

const auto delayTypeIndex = (int) *delayTypeParam;
if (delayTypeIndex != prevDelayTypeIndex)
Expand Down Expand Up @@ -313,6 +326,10 @@ void DelayModule::processAudioBypassed (AudioBuffer<float>& buffer)
outputBuffers.getReference (0) = &buffer;
}

//void DelayModule::setPlayheadHelpersReference(PlayheadHelpers& helpers) {
// playheadHelpersReference = &helpers;
//}

float DelayModule::calculateTempoSyncDelayTime(const float noteDuration, const double bpm) const
{
//calculate tempo sync delay in samples
Expand Down
3 changes: 3 additions & 0 deletions src/processors/other/Delay.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include "../BaseProcessor.h"
#include "processors/PlayheadHelpers.h"

class DelayModule : public BaseProcessor
{
Expand All @@ -16,6 +17,7 @@ class DelayModule : public BaseProcessor
void processAudio (AudioBuffer<float>& buffer) override;
void processAudioBypassed (AudioBuffer<float>& buffer) override;
float calculateTempoSyncDelayTime(const float noteDuration, const double bpm) const;
// void setPlayheadHelpersReference(PlayheadHelpers& helpers);

private:
template <typename DelayType>
Expand Down Expand Up @@ -82,6 +84,7 @@ class DelayModule : public BaseProcessor
AudioBuffer<float> stereoBuffer;

bool bypassNeedsReset = false;
std::atomic<double>& bpm;

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DelayModule)
};

0 comments on commit 00bd58c

Please sign in to comment.