If the nodes are now stateless, there's nothing stopping the renderer from rendering multiple frames at once. Earlier since the nodes held some of their input/output data (and that data could change per frame), it was not possible to render multiple frames at once without conflicts. Now that the node state is held in render threads, they can do whatever they want at any time.
101 lines
2.2 KiB
C++
101 lines
2.2 KiB
C++
#include "audiobackend.h"
|
|
|
|
#include "audioworker.h"
|
|
|
|
AudioBackend::AudioBackend(QObject *parent) :
|
|
AudioRenderBackend(parent)
|
|
{
|
|
}
|
|
|
|
AudioBackend::~AudioBackend()
|
|
{
|
|
Close();
|
|
}
|
|
|
|
QIODevice *AudioBackend::GetAudioPullDevice()
|
|
{
|
|
pull_device_.setFileName(CachePathName());
|
|
|
|
return &pull_device_;
|
|
}
|
|
|
|
void AudioBackend::InvalidateCache(const rational &start_range, const rational &end_range)
|
|
{
|
|
/*
|
|
// Truncate to length if necessary
|
|
int max_length_in_bytes = params().time_to_bytes(viewer_node()->Length());
|
|
if (pcm_data_.size() > max_length_in_bytes) {
|
|
pcm_data_.resize(max_length_in_bytes);
|
|
}
|
|
*/
|
|
|
|
AudioRenderBackend::InvalidateCache(start_range, end_range);
|
|
}
|
|
|
|
bool AudioBackend::InitInternal()
|
|
{
|
|
// Initiate one thread per CPU core
|
|
for (int i=0;i<threads().size();i++) {
|
|
// Create one processor object for each thread
|
|
AudioWorker* processor = new AudioWorker();
|
|
processor->SetParameters(params());
|
|
processors_.append(processor);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void AudioBackend::CloseInternal()
|
|
{
|
|
}
|
|
|
|
bool AudioBackend::CompileInternal()
|
|
{
|
|
// This backend doesn't compile anything yet
|
|
return true;
|
|
}
|
|
|
|
void AudioBackend::DecompileInternal()
|
|
{
|
|
// This backend doesn't compile anything yet
|
|
}
|
|
|
|
void AudioBackend::ConnectWorkerToThis(RenderWorker *worker)
|
|
{
|
|
connect(worker, SIGNAL(CompletedCache(NodeDependency, NodeValueTable)), this, SLOT(ThreadCompletedCache(NodeDependency, NodeValueTable)));
|
|
}
|
|
|
|
void AudioBackend::ThreadCompletedCache(NodeDependency dep, NodeValueTable data)
|
|
{
|
|
QByteArray cached_samples = data.Get(NodeParam::kSamples).toByteArray();
|
|
|
|
int offset = params().time_to_bytes(dep.in());
|
|
int length = params().time_to_bytes(dep.range().length());
|
|
int out_point = offset + length;
|
|
|
|
QFile f(CachePathName());
|
|
if (f.open(QFile::WriteOnly | QFile::Append)) {
|
|
|
|
if (f.size() < out_point) {
|
|
f.resize(out_point);
|
|
}
|
|
|
|
f.seek(offset);
|
|
|
|
// Replace data with this data
|
|
int copy_length = qMin(length, cached_samples.size());
|
|
|
|
f.write(cached_samples.data(), copy_length);
|
|
|
|
if (copy_length < length) {
|
|
// Fill in remainder with silence
|
|
QByteArray empty_space(length - copy_length, 0);
|
|
f.write(empty_space);
|
|
}
|
|
|
|
f.close();
|
|
}
|
|
|
|
CacheNext();
|
|
}
|