Skip to content

Commit d3e7c00

Browse files
committed
Report current time in samples to plugins.
1 parent 1bac563 commit d3e7c00

File tree

1 file changed

+41
-1
lines changed

1 file changed

+41
-1
lines changed

pedalboard/ExternalPlugin.h

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ class AbstractExternalPlugin : public Plugin {
471471
};
472472

473473
template <typename ExternalPluginType>
474-
class ExternalPlugin : public AbstractExternalPlugin {
474+
class ExternalPlugin : public AbstractExternalPlugin, juce::AudioPlayHead {
475475
public:
476476
ExternalPlugin(
477477
std::string &_pathToPluginFile,
@@ -599,6 +599,10 @@ class ExternalPlugin : public AbstractExternalPlugin {
599599
~ExternalPlugin() {
600600
{
601601
std::lock_guard<std::mutex> lock(EXTERNAL_PLUGIN_MUTEX);
602+
if (pluginInstance) {
603+
pluginInstance->setPlayHead(nullptr);
604+
}
605+
602606
pluginInstance.reset();
603607
NUM_ACTIVE_EXTERNAL_PLUGINS--;
604608

@@ -664,6 +668,9 @@ class ExternalPlugin : public AbstractExternalPlugin {
664668
{
665669
std::lock_guard<std::mutex> lock(EXTERNAL_PLUGIN_MUTEX);
666670
// Delete the plugin instance itself:
671+
if (pluginInstance) {
672+
pluginInstance->setPlayHead(nullptr);
673+
}
667674
pluginInstance.reset();
668675
NUM_ACTIVE_EXTERNAL_PLUGINS--;
669676
}
@@ -683,6 +690,7 @@ class ExternalPlugin : public AbstractExternalPlugin {
683690
loadError.toStdString());
684691
}
685692

693+
pluginInstance->setPlayHead(this);
686694
pluginInstance->enableAllBuses();
687695

688696
auto mainInputBus = pluginInstance->getBus(true, 0);
@@ -692,6 +700,9 @@ class ExternalPlugin : public AbstractExternalPlugin {
692700
auto exception = std::invalid_argument(
693701
"Plugin '" + pluginInstance->getName().toStdString() +
694702
"' does not produce audio output.");
703+
if (pluginInstance) {
704+
pluginInstance->setPlayHead(nullptr);
705+
}
695706
pluginInstance.reset();
696707
throw exception;
697708
}
@@ -710,6 +721,7 @@ class ExternalPlugin : public AbstractExternalPlugin {
710721
pathToPluginFile.toStdString() + ": " +
711722
loadError.toStdString());
712723
}
724+
pluginInstance->setPlayHead(this);
713725
}
714726
}
715727

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

896+
currentPositionInfo.isPlaying = true;
884897
pluginInstance->processBlock(audioBuffer, emptyNoteBuffer);
898+
currentPositionInfo.isPlaying = false;
899+
currentPositionInfo.timeInSamples += bufferSize;
885900
auto noiseFloor = audioBuffer.getMagnitude(0, bufferSize);
886901

887902
audioBuffer.clear();
@@ -891,7 +906,10 @@ class ExternalPlugin : public AbstractExternalPlugin {
891906
// the messages in a MidiBuffer get erased every time we call processBlock!
892907
{
893908
juce::MidiBuffer noteOnBuffer(noteOn);
909+
currentPositionInfo.isPlaying = true;
894910
pluginInstance->processBlock(audioBuffer, noteOnBuffer);
911+
currentPositionInfo.isPlaying = false;
912+
currentPositionInfo.timeInSamples += bufferSize;
895913
}
896914

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

915933
audioBuffer.clear();
916934
{
935+
currentPositionInfo.isPlaying = true;
917936
juce::MidiBuffer noteOnBuffer(noteOn);
918937
pluginInstance->processBlock(audioBuffer, noteOnBuffer);
938+
currentPositionInfo.isPlaying = false;
939+
currentPositionInfo.timeInSamples += bufferSize;
919940
}
920941

921942
if (juce::Time::currentTimeMillis() >= endTime)
@@ -927,8 +948,12 @@ class ExternalPlugin : public AbstractExternalPlugin {
927948
audioBuffer.clear();
928949
{
929950
juce::MidiBuffer allNotesOffBuffer(allNotesOff);
951+
currentPositionInfo.isPlaying = true;
930952
pluginInstance->processBlock(audioBuffer, allNotesOffBuffer);
953+
currentPositionInfo.isPlaying = false;
954+
currentPositionInfo.timeInSamples += bufferSize;
931955
}
956+
currentPositionInfo.timeInSamples = 0;
932957
pluginInstance->reset();
933958
pluginInstance->releaseResources();
934959

@@ -1046,6 +1071,7 @@ class ExternalPlugin : public AbstractExternalPlugin {
10461071
// Force prepare() to be called again later by invalidating lastSpec:
10471072
lastSpec.maximumBlockSize = 0;
10481073
samplesProvided = 0;
1074+
currentPositionInfo.timeInSamples = 0;
10491075
}
10501076
}
10511077

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

10721098
pluginInstance->setNonRealtime(true);
10731099
pluginInstance->prepareToPlay(spec.sampleRate, spec.maximumBlockSize);
1100+
currentPositionInfo.timeInSamples = 0;
1101+
currentPositionInfo.isPlaying = false;
10741102

10751103
lastSpec = spec;
10761104
}
@@ -1142,8 +1170,11 @@ class ExternalPlugin : public AbstractExternalPlugin {
11421170
channelPointers.size(),
11431171
outputBlock.getNumSamples());
11441172

1173+
currentPositionInfo.isPlaying = true;
11451174
pluginInstance->processBlock(audioBuffer, emptyMidiBuffer);
1175+
currentPositionInfo.isPlaying = false;
11461176
samplesProvided += outputBlock.getNumSamples();
1177+
currentPositionInfo.timeInSamples += outputBlock.getNumSamples();
11471178

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

1272+
currentPositionInfo.isPlaying = true;
12411273
pluginInstance->processBlock(audioChunk, midiChunk);
1274+
currentPositionInfo.isPlaying = false;
1275+
currentPositionInfo.timeInSamples += chunkSampleCount;
12421276
}
12431277
}
12441278

@@ -1302,13 +1336,19 @@ class ExternalPlugin : public AbstractExternalPlugin {
13021336

13031337
ExternalPluginReloadType reloadType = ExternalPluginReloadType::Unknown;
13041338

1339+
bool getCurrentPosition(CurrentPositionInfo &result) override {
1340+
result = currentPositionInfo;
1341+
return true;
1342+
}
1343+
13051344
private:
13061345
constexpr static int ExternalLoadSampleRate = 44100,
13071346
ExternalLoadMaximumBlockSize = 8192;
13081347
juce::String pathToPluginFile;
13091348
juce::PluginDescription foundPluginDescription;
13101349
juce::AudioPluginFormatManager pluginFormatManager;
13111350
std::unique_ptr<juce::AudioPluginInstance> pluginInstance;
1351+
juce::AudioPlayHead::CurrentPositionInfo currentPositionInfo;
13121352

13131353
long samplesProvided = 0;
13141354
float initializationTimeout = DEFAULT_INITIALIZATION_TIMEOUT_SECONDS;

0 commit comments

Comments
 (0)