Skip to content

Commit

Permalink
Report current time in samples to plugins.
Browse files Browse the repository at this point in the history
  • Loading branch information
psobot committed Mar 7, 2024
1 parent 1bac563 commit d3e7c00
Showing 1 changed file with 41 additions and 1 deletion.
42 changes: 41 additions & 1 deletion pedalboard/ExternalPlugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ class AbstractExternalPlugin : public Plugin {
};

template <typename ExternalPluginType>
class ExternalPlugin : public AbstractExternalPlugin {
class ExternalPlugin : public AbstractExternalPlugin, juce::AudioPlayHead {
public:
ExternalPlugin(
std::string &_pathToPluginFile,
Expand Down Expand Up @@ -599,6 +599,10 @@ class ExternalPlugin : public AbstractExternalPlugin {
~ExternalPlugin() {
{
std::lock_guard<std::mutex> lock(EXTERNAL_PLUGIN_MUTEX);
if (pluginInstance) {
pluginInstance->setPlayHead(nullptr);
}

pluginInstance.reset();
NUM_ACTIVE_EXTERNAL_PLUGINS--;

Expand Down Expand Up @@ -664,6 +668,9 @@ class ExternalPlugin : public AbstractExternalPlugin {
{
std::lock_guard<std::mutex> lock(EXTERNAL_PLUGIN_MUTEX);
// Delete the plugin instance itself:
if (pluginInstance) {
pluginInstance->setPlayHead(nullptr);
}
pluginInstance.reset();
NUM_ACTIVE_EXTERNAL_PLUGINS--;
}
Expand All @@ -683,6 +690,7 @@ class ExternalPlugin : public AbstractExternalPlugin {
loadError.toStdString());
}

pluginInstance->setPlayHead(this);
pluginInstance->enableAllBuses();

auto mainInputBus = pluginInstance->getBus(true, 0);
Expand All @@ -692,6 +700,9 @@ class ExternalPlugin : public AbstractExternalPlugin {
auto exception = std::invalid_argument(
"Plugin '" + pluginInstance->getName().toStdString() +
"' does not produce audio output.");
if (pluginInstance) {
pluginInstance->setPlayHead(nullptr);
}
pluginInstance.reset();
throw exception;
}
Expand All @@ -710,6 +721,7 @@ class ExternalPlugin : public AbstractExternalPlugin {
pathToPluginFile.toStdString() + ": " +
loadError.toStdString());
}
pluginInstance->setPlayHead(this);
}
}

Expand Down Expand Up @@ -881,7 +893,10 @@ class ExternalPlugin : public AbstractExternalPlugin {
juce::AudioBuffer<float> audioBuffer(numOutputChannels, bufferSize);
audioBuffer.clear();

currentPositionInfo.isPlaying = true;
pluginInstance->processBlock(audioBuffer, emptyNoteBuffer);
currentPositionInfo.isPlaying = false;
currentPositionInfo.timeInSamples += bufferSize;
auto noiseFloor = audioBuffer.getMagnitude(0, bufferSize);

audioBuffer.clear();
Expand All @@ -891,7 +906,10 @@ class ExternalPlugin : public AbstractExternalPlugin {
// the messages in a MidiBuffer get erased every time we call processBlock!
{
juce::MidiBuffer noteOnBuffer(noteOn);
currentPositionInfo.isPlaying = true;
pluginInstance->processBlock(audioBuffer, noteOnBuffer);
currentPositionInfo.isPlaying = false;
currentPositionInfo.timeInSamples += bufferSize;
}

// Then keep pumping the message thread until we get some louder output:
Expand All @@ -914,8 +932,11 @@ class ExternalPlugin : public AbstractExternalPlugin {

audioBuffer.clear();
{
currentPositionInfo.isPlaying = true;
juce::MidiBuffer noteOnBuffer(noteOn);
pluginInstance->processBlock(audioBuffer, noteOnBuffer);
currentPositionInfo.isPlaying = false;
currentPositionInfo.timeInSamples += bufferSize;
}

if (juce::Time::currentTimeMillis() >= endTime)
Expand All @@ -927,8 +948,12 @@ class ExternalPlugin : public AbstractExternalPlugin {
audioBuffer.clear();
{
juce::MidiBuffer allNotesOffBuffer(allNotesOff);
currentPositionInfo.isPlaying = true;
pluginInstance->processBlock(audioBuffer, allNotesOffBuffer);
currentPositionInfo.isPlaying = false;
currentPositionInfo.timeInSamples += bufferSize;
}
currentPositionInfo.timeInSamples = 0;
pluginInstance->reset();
pluginInstance->releaseResources();

Expand Down Expand Up @@ -1046,6 +1071,7 @@ class ExternalPlugin : public AbstractExternalPlugin {
// Force prepare() to be called again later by invalidating lastSpec:
lastSpec.maximumBlockSize = 0;
samplesProvided = 0;
currentPositionInfo.timeInSamples = 0;
}
}

Expand All @@ -1071,6 +1097,8 @@ class ExternalPlugin : public AbstractExternalPlugin {

pluginInstance->setNonRealtime(true);
pluginInstance->prepareToPlay(spec.sampleRate, spec.maximumBlockSize);
currentPositionInfo.timeInSamples = 0;
currentPositionInfo.isPlaying = false;

lastSpec = spec;
}
Expand Down Expand Up @@ -1142,8 +1170,11 @@ class ExternalPlugin : public AbstractExternalPlugin {
channelPointers.size(),
outputBlock.getNumSamples());

currentPositionInfo.isPlaying = true;
pluginInstance->processBlock(audioBuffer, emptyMidiBuffer);
currentPositionInfo.isPlaying = false;
samplesProvided += outputBlock.getNumSamples();
currentPositionInfo.timeInSamples += outputBlock.getNumSamples();

// To compensate for any latency added by the plugin,
// only tell Pedalboard to use the last _n_ samples.
Expand Down Expand Up @@ -1238,7 +1269,10 @@ class ExternalPlugin : public AbstractExternalPlugin {
juce::MidiBuffer midiChunk;
midiChunk.addEvents(midiInputBuffer, i, chunkSampleCount, -i);

currentPositionInfo.isPlaying = true;
pluginInstance->processBlock(audioChunk, midiChunk);
currentPositionInfo.isPlaying = false;
currentPositionInfo.timeInSamples += chunkSampleCount;
}
}

Expand Down Expand Up @@ -1302,13 +1336,19 @@ class ExternalPlugin : public AbstractExternalPlugin {

ExternalPluginReloadType reloadType = ExternalPluginReloadType::Unknown;

bool getCurrentPosition(CurrentPositionInfo &result) override {
result = currentPositionInfo;
return true;
}

private:
constexpr static int ExternalLoadSampleRate = 44100,
ExternalLoadMaximumBlockSize = 8192;
juce::String pathToPluginFile;
juce::PluginDescription foundPluginDescription;
juce::AudioPluginFormatManager pluginFormatManager;
std::unique_ptr<juce::AudioPluginInstance> pluginInstance;
juce::AudioPlayHead::CurrentPositionInfo currentPositionInfo;

long samplesProvided = 0;
float initializationTimeout = DEFAULT_INITIALIZATION_TIMEOUT_SECONDS;
Expand Down

0 comments on commit d3e7c00

Please sign in to comment.