I’m trying to render audio in a separate thread, in order to avoid blocking the message thread. So I can show a progress bar, reporting the export status.
But strangely the function call hangs when calling renderer->processBlock (buffer,midiBuffer);
. it looks to me like a deadlock. you can see the call stacks when the hanging happens. And the rendering function is down below.
How can I correctly rendering audio in separate thread? Or what’s the right way to render the audio without completely blocking the gui thread. Thanks in advance!
void run() override
{
outputFile.deleteFile(); // Make sure there aren't any old versions of the file left over
OutputStream* outStream (outputFile.createOutputStream().release());
outStream->setPosition (0);
double sampleRate = 44100.0;
unsigned int numChannels = 2;
int bitDepth = 16;
StringPairArray metadata (true);
metadata.set("title", String (outputFile.getFileName()));
metadata.set("samplerate", String (sampleRate));
metadata.set("bitdepth", String (bitDepth));
metadata.set("numChannels", String (numChannels));
std::unique_ptr<AiffAudioFormat> aiffAudioFormat = std::make_unique<AiffAudioFormat> ();
std::unique_ptr<AudioFormatWriter> writer {aiffAudioFormat->createWriterFor (outStream, sampleRate,n umChannels, bitDepth, metadata, 0)};
std::shared_ptr<AudioProcessorGraph> renderer = project->getGraph();
const ScopedLock sl (renderer->getCallbackLock());
const int numSamples = 1024;
renderer->prepareToPlay (sampleRate, numSamples);
renderer->setNonRealtime (true);
int numOutputChannels = (int) numChannels;
AudioBuffer<float> buffer {numOutputChannels, numSamples};
MidiBuffer midiBuffer;
int64 totalSamples = project->getTotalSamples();
int64 playheadPosition = 0;
project->transport->setExporting (true);
int thingsToDo = (int) (totalSamples / numSamples);
for (int i = 0; i < thingsToDo; ++i)
{
renderer->processBlock (buffer,midiBuffer);
writer->writeFromAudioSampleBuffer (buffer, 0, numSamples);
project->transport->process (project->transport->getTransportState(), buffer, midiBuffer);
auto transport = project->transport;
if (auto transportPtr = transport)
renderer->setPlayHead (transportPtr.get());
playheadPosition += numSamples;
}
project->transport->setExporting (false);
}