Skip to content

Commit e688aaf

Browse files
committed
Report current time in samples to plugins.
1 parent a00c02d commit e688aaf

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
@@ -516,7 +516,7 @@ class AbstractExternalPlugin : public Plugin {
516516
};
517517

518518
template <typename ExternalPluginType>
519-
class ExternalPlugin : public AbstractExternalPlugin {
519+
class ExternalPlugin : public AbstractExternalPlugin, juce::AudioPlayHead {
520520
public:
521521
ExternalPlugin(
522522
std::string &_pathToPluginFile,
@@ -630,6 +630,10 @@ class ExternalPlugin : public AbstractExternalPlugin {
630630
~ExternalPlugin() {
631631
{
632632
std::lock_guard<std::mutex> lock(EXTERNAL_PLUGIN_MUTEX);
633+
if (pluginInstance) {
634+
pluginInstance->setPlayHead(nullptr);
635+
}
636+
633637
pluginInstance.reset();
634638
NUM_ACTIVE_EXTERNAL_PLUGINS--;
635639

@@ -695,6 +699,9 @@ class ExternalPlugin : public AbstractExternalPlugin {
695699
{
696700
std::lock_guard<std::mutex> lock(EXTERNAL_PLUGIN_MUTEX);
697701
// Delete the plugin instance itself:
702+
if (pluginInstance) {
703+
pluginInstance->setPlayHead(nullptr);
704+
}
698705
pluginInstance.reset();
699706
NUM_ACTIVE_EXTERNAL_PLUGINS--;
700707
}
@@ -714,6 +721,7 @@ class ExternalPlugin : public AbstractExternalPlugin {
714721
loadError.toStdString());
715722
}
716723

724+
pluginInstance->setPlayHead(this);
717725
pluginInstance->enableAllBuses();
718726

719727
auto mainInputBus = pluginInstance->getBus(true, 0);
@@ -723,6 +731,9 @@ class ExternalPlugin : public AbstractExternalPlugin {
723731
auto exception = std::invalid_argument(
724732
"Plugin '" + pluginInstance->getName().toStdString() +
725733
"' does not produce audio output.");
734+
if (pluginInstance) {
735+
pluginInstance->setPlayHead(nullptr);
736+
}
726737
pluginInstance.reset();
727738
throw exception;
728739
}
@@ -741,6 +752,7 @@ class ExternalPlugin : public AbstractExternalPlugin {
741752
pathToPluginFile.toStdString() + ": " +
742753
loadError.toStdString());
743754
}
755+
pluginInstance->setPlayHead(this);
744756
}
745757
}
746758

@@ -912,7 +924,10 @@ class ExternalPlugin : public AbstractExternalPlugin {
912924
juce::AudioBuffer<float> audioBuffer(numOutputChannels, bufferSize);
913925
audioBuffer.clear();
914926

927+
currentPositionInfo.isPlaying = true;
915928
pluginInstance->processBlock(audioBuffer, emptyNoteBuffer);
929+
currentPositionInfo.isPlaying = false;
930+
currentPositionInfo.timeInSamples += bufferSize;
916931
auto noiseFloor = audioBuffer.getMagnitude(0, bufferSize);
917932

918933
audioBuffer.clear();
@@ -922,7 +937,10 @@ class ExternalPlugin : public AbstractExternalPlugin {
922937
// the messages in a MidiBuffer get erased every time we call processBlock!
923938
{
924939
juce::MidiBuffer noteOnBuffer(noteOn);
940+
currentPositionInfo.isPlaying = true;
925941
pluginInstance->processBlock(audioBuffer, noteOnBuffer);
942+
currentPositionInfo.isPlaying = false;
943+
currentPositionInfo.timeInSamples += bufferSize;
926944
}
927945

928946
// Then keep pumping the message thread until we get some louder output:
@@ -945,8 +963,11 @@ class ExternalPlugin : public AbstractExternalPlugin {
945963

946964
audioBuffer.clear();
947965
{
966+
currentPositionInfo.isPlaying = true;
948967
juce::MidiBuffer noteOnBuffer(noteOn);
949968
pluginInstance->processBlock(audioBuffer, noteOnBuffer);
969+
currentPositionInfo.isPlaying = false;
970+
currentPositionInfo.timeInSamples += bufferSize;
950971
}
951972

952973
if (juce::Time::currentTimeMillis() >= endTime)
@@ -958,8 +979,12 @@ class ExternalPlugin : public AbstractExternalPlugin {
958979
audioBuffer.clear();
959980
{
960981
juce::MidiBuffer allNotesOffBuffer(allNotesOff);
982+
currentPositionInfo.isPlaying = true;
961983
pluginInstance->processBlock(audioBuffer, allNotesOffBuffer);
984+
currentPositionInfo.isPlaying = false;
985+
currentPositionInfo.timeInSamples += bufferSize;
962986
}
987+
currentPositionInfo.timeInSamples = 0;
963988
pluginInstance->reset();
964989
pluginInstance->releaseResources();
965990

@@ -1077,6 +1102,7 @@ class ExternalPlugin : public AbstractExternalPlugin {
10771102
// Force prepare() to be called again later by invalidating lastSpec:
10781103
lastSpec.maximumBlockSize = 0;
10791104
samplesProvided = 0;
1105+
currentPositionInfo.timeInSamples = 0;
10801106
}
10811107
}
10821108

@@ -1102,6 +1128,8 @@ class ExternalPlugin : public AbstractExternalPlugin {
11021128

11031129
pluginInstance->setNonRealtime(true);
11041130
pluginInstance->prepareToPlay(spec.sampleRate, spec.maximumBlockSize);
1131+
currentPositionInfo.timeInSamples = 0;
1132+
currentPositionInfo.isPlaying = false;
11051133

11061134
lastSpec = spec;
11071135
}
@@ -1173,8 +1201,11 @@ class ExternalPlugin : public AbstractExternalPlugin {
11731201
channelPointers.size(),
11741202
outputBlock.getNumSamples());
11751203

1204+
currentPositionInfo.isPlaying = true;
11761205
pluginInstance->processBlock(audioBuffer, emptyMidiBuffer);
1206+
currentPositionInfo.isPlaying = false;
11771207
samplesProvided += outputBlock.getNumSamples();
1208+
currentPositionInfo.timeInSamples += outputBlock.getNumSamples();
11781209

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

1303+
currentPositionInfo.isPlaying = true;
12721304
pluginInstance->processBlock(audioChunk, midiChunk);
1305+
currentPositionInfo.isPlaying = false;
1306+
currentPositionInfo.timeInSamples += chunkSampleCount;
12731307
}
12741308
}
12751309

@@ -1337,6 +1371,11 @@ class ExternalPlugin : public AbstractExternalPlugin {
13371371
ExternalPluginReloadType reloadType = ExternalPluginReloadType::Unknown;
13381372
juce::PluginDescription foundPluginDescription;
13391373

1374+
bool getCurrentPosition(CurrentPositionInfo &result) override {
1375+
result = currentPositionInfo;
1376+
return true;
1377+
}
1378+
13401379
private:
13411380
std::unique_ptr<juce::AudioPluginInstance>
13421381
createPluginInstance(const juce::PluginDescription &foundPluginDescription,
@@ -1371,6 +1410,7 @@ class ExternalPlugin : public AbstractExternalPlugin {
13711410
juce::String pathToPluginFile;
13721411
juce::AudioPluginFormatManager pluginFormatManager;
13731412
std::unique_ptr<juce::AudioPluginInstance> pluginInstance;
1413+
juce::AudioPlayHead::CurrentPositionInfo currentPositionInfo;
13741414

13751415
long samplesProvided = 0;
13761416
float initializationTimeout = DEFAULT_INITIALIZATION_TIMEOUT_SECONDS;

0 commit comments

Comments
 (0)