From f0cd480540c8496c46b02363485ca2ad5cd9bbc0 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Tue, 24 Dec 2019 14:02:07 +1100 Subject: [PATCH] finished audio effects support in audio renderer Working structure implemented in previous commit into the audio renderer is complete in this commit. --- app/node/audio/pan/pan.cpp | 14 +++++++--- app/node/audio/pan/pan.h | 6 +++-- app/node/audio/volume/volume.cpp | 19 +++++++++++--- app/node/audio/volume/volume.h | 8 ++++-- app/node/node.cpp | 6 ++--- app/node/node.h | 4 +-- app/render/backend/audio/audioworker.cpp | 32 +++++++++++++++++++++++ app/render/backend/audio/audioworker.h | 2 ++ app/render/backend/audiorenderworker.cpp | 5 ++++ app/render/backend/audiorenderworker.h | 2 ++ app/render/backend/renderworker.cpp | 6 ----- app/render/backend/renderworker.h | 2 -- app/widget/timelinewidget/tool/import.cpp | 8 +++++- 13 files changed, 88 insertions(+), 26 deletions(-) diff --git a/app/node/audio/pan/pan.cpp b/app/node/audio/pan/pan.cpp index a289eb8c8..f09077296 100644 --- a/app/node/audio/pan/pan.cpp +++ b/app/node/audio/pan/pan.cpp @@ -39,19 +39,19 @@ QString PanNode::Description() const return tr("Adjust the stereo panning of an audio source."); } -bool PanNode::ProcessesSamples() const +NodeInput *PanNode::ProcessesSamplesFrom() const { - return true; + return samples_input_; } -void PanNode::ProcessSamples(const NodeValueDatabase &values, const AudioRenderingParams ¶ms, const float *input, float *output, int index) const +void PanNode::ProcessSamples(const NodeValueDatabase *values, const AudioRenderingParams ¶ms, const float *input, float *output, int index) const { if (params.channel_count() != 2) { // This node currently only works for stereo audio return; } - float pan_val = values[panning_input_].Get(NodeParam::kFloat).toFloat(); + float pan_val = (*values)[panning_input_].Get(NodeParam::kFloat).toFloat(); if (index%2 == 0) { // Sample is left channel @@ -65,3 +65,9 @@ void PanNode::ProcessSamples(const NodeValueDatabase &values, const AudioRenderi } } } + +void PanNode::Retranslate() +{ + samples_input_->set_name(tr("Samples")); + panning_input_->set_name(tr("Pan")); +} diff --git a/app/node/audio/pan/pan.h b/app/node/audio/pan/pan.h index a999cdf16..3b4a011e3 100644 --- a/app/node/audio/pan/pan.h +++ b/app/node/audio/pan/pan.h @@ -15,8 +15,10 @@ public: virtual QString Category() const override; virtual QString Description() const override; - virtual bool ProcessesSamples() const override; - virtual void ProcessSamples(const NodeValueDatabase& values, const AudioRenderingParams& params, const float* input, float* output, int index) const override; + virtual NodeInput* ProcessesSamplesFrom() const override; + virtual void ProcessSamples(const NodeValueDatabase* values, const AudioRenderingParams& params, const float* input, float* output, int index) const override; + + virtual void Retranslate() override; private: NodeInput* samples_input_; diff --git a/app/node/audio/volume/volume.cpp b/app/node/audio/volume/volume.cpp index 87c4c23f3..b2d19899b 100644 --- a/app/node/audio/volume/volume.cpp +++ b/app/node/audio/volume/volume.cpp @@ -39,14 +39,25 @@ QString VolumeNode::Description() const return tr("Adjusts the volume of an audio source."); } -bool VolumeNode::ProcessesSamples() const +NodeInput *VolumeNode::ProcessesSamplesFrom() const { - return true; + return samples_input_; } -void VolumeNode::ProcessSamples(const NodeValueDatabase& values, const AudioRenderingParams& params, const float* input, float* output, int index) const +void VolumeNode::ProcessSamples(const NodeValueDatabase *values, const AudioRenderingParams& params, const float* input, float* output, int index) const { - float volume_val = values[volume_input_].Get(NodeParam::kFloat).toFloat(); + float volume_val = (*values)[volume_input_].Get(NodeParam::kFloat).toFloat(); output[index] = input[index] * volume_val; } + +void VolumeNode::Retranslate() +{ + samples_input_->set_name(tr("Samples")); + volume_input_->set_name(tr("Volume")); +} + +NodeInput *VolumeNode::samples_input() const +{ + return samples_input_; +} diff --git a/app/node/audio/volume/volume.h b/app/node/audio/volume/volume.h index c7c1f2cf6..133924e0c 100644 --- a/app/node/audio/volume/volume.h +++ b/app/node/audio/volume/volume.h @@ -15,8 +15,12 @@ public: virtual QString Category() const override; virtual QString Description() const override; - virtual bool ProcessesSamples() const override; - virtual void ProcessSamples(const NodeValueDatabase& values, const AudioRenderingParams& params, const float* input, float* output, int index) const override; + virtual NodeInput* ProcessesSamplesFrom() const override; + virtual void ProcessSamples(const NodeValueDatabase* values, const AudioRenderingParams& params, const float* input, float* output, int index) const override; + + virtual void Retranslate() override; + + NodeInput* samples_input() const; private: NodeInput* samples_input_; diff --git a/app/node/node.cpp b/app/node/node.cpp index 1ce66da7b..5736ff5b4 100644 --- a/app/node/node.cpp +++ b/app/node/node.cpp @@ -390,12 +390,12 @@ NodeInput *Node::AcceleratedCodeIterativeInput() const return nullptr; } -bool Node::ProcessesSamples() const +NodeInput* Node::ProcessesSamplesFrom() const { - return false; + return nullptr; } -void Node::ProcessSamples(const NodeValueDatabase &values, const AudioRenderingParams ¶ms, const float *input, float *output, int index) const +void Node::ProcessSamples(const NodeValueDatabase *values, const AudioRenderingParams ¶ms, const float *input, float *output, int index) const { Q_UNUSED(values) Q_UNUSED(params) diff --git a/app/node/node.h b/app/node/node.h index b9fa15cde..c89c11e1f 100644 --- a/app/node/node.h +++ b/app/node/node.h @@ -160,12 +160,12 @@ public: /** * @brief Return whether this node processes samples or not */ - virtual bool ProcessesSamples() const; + virtual NodeInput* ProcessesSamplesFrom() const; /** * @brief If ProcessesSamples() is true, this is the function that will process them. */ - virtual void ProcessSamples(const NodeValueDatabase& values, const AudioRenderingParams& params, const float* input, float* output, int index) const; + virtual void ProcessSamples(const NodeValueDatabase *values, const AudioRenderingParams& params, const float* input, float* output, int index) const; /** * @brief Returns the parameter with the specified ID (or nullptr if it doesn't exist) diff --git a/app/render/backend/audio/audioworker.cpp b/app/render/backend/audio/audioworker.cpp index c012976af..09d8effad 100644 --- a/app/render/backend/audio/audioworker.cpp +++ b/app/render/backend/audio/audioworker.cpp @@ -11,3 +11,35 @@ void AudioWorker::FrameToValue(StreamPtr stream, FramePtr frame, NodeValueTable table->Push(NodeParam::kSamples, frame->ToByteArray()); } + +void AudioWorker::RunNodeAccelerated(const Node *node, const TimeRange &range, const NodeValueDatabase *input_params, NodeValueTable *output_params) +{ + // Check if node processes samples + if (!node->ProcessesSamplesFrom()) { + return; + } + + // Try to find the sample buffer in the table + QVariant samples_var = (*input_params)[node->ProcessesSamplesFrom()].Get(NodeParam::kSamples); + + // If there isn't one, there's nothing to do + if (samples_var.isNull()) { + return; + } + + QByteArray input_buffer = samples_var.toByteArray(); + QByteArray output_buffer(input_buffer.size(), 0); + + int sample_count = input_buffer.size() / audio_params().bytes_per_sample_per_channel(); + + // FIXME: Hardcoded float sample format + for (int i=0;iProcessSamples(input_params, + audio_params(), + reinterpret_cast(input_buffer.constData()), + reinterpret_cast(output_buffer.data()), + i); + } + + output_params->Push(NodeParam::kSamples, output_buffer); +} diff --git a/app/render/backend/audio/audioworker.h b/app/render/backend/audio/audioworker.h index 3fdcb02ce..5e81bccf9 100644 --- a/app/render/backend/audio/audioworker.h +++ b/app/render/backend/audio/audioworker.h @@ -11,6 +11,8 @@ public: protected: virtual void FrameToValue(StreamPtr stream, FramePtr frame, NodeValueTable* table) override; + virtual void RunNodeAccelerated(const Node *node, const TimeRange& range, const NodeValueDatabase *input_params, NodeValueTable* output_params) override; + private: }; diff --git a/app/render/backend/audiorenderworker.cpp b/app/render/backend/audiorenderworker.cpp index 6e4f645ef..b3f999acf 100644 --- a/app/render/backend/audiorenderworker.cpp +++ b/app/render/backend/audiorenderworker.cpp @@ -90,3 +90,8 @@ NodeValueTable AudioRenderWorker::RenderBlock(const TrackOutput *track, const Ti return merged_table; } + +const AudioRenderingParams &AudioRenderWorker::audio_params() const +{ + return audio_params_; +} diff --git a/app/render/backend/audiorenderworker.h b/app/render/backend/audiorenderworker.h index d6f7aaa01..67e345ac2 100644 --- a/app/render/backend/audiorenderworker.h +++ b/app/render/backend/audiorenderworker.h @@ -20,6 +20,8 @@ protected: virtual NodeValueTable RenderBlock(const TrackOutput *track, const TimeRange& range) override; + const AudioRenderingParams& audio_params() const; + private: AudioRenderingParams audio_params_; diff --git a/app/render/backend/renderworker.cpp b/app/render/backend/renderworker.cpp index f2a65a7fc..21cf82c5e 100644 --- a/app/render/backend/renderworker.cpp +++ b/app/render/backend/renderworker.cpp @@ -42,12 +42,6 @@ NodeValueTable RenderWorker::RenderInternal(const NodeDependency &path) return ProcessNode(path); } -bool RenderWorker::OutputIsAccelerated(Node *output) -{ - Q_UNUSED(output) - return false; -} - void RenderWorker::RunNodeAccelerated(const Node *node, const TimeRange &range, const NodeValueDatabase *input_params, NodeValueTable* output_params) { Q_UNUSED(node) diff --git a/app/render/backend/renderworker.h b/app/render/backend/renderworker.h index 2668a4ce9..659aa7557 100644 --- a/app/render/backend/renderworker.h +++ b/app/render/backend/renderworker.h @@ -35,8 +35,6 @@ protected: virtual NodeValueTable RenderInternal(const NodeDependency& path); - virtual bool OutputIsAccelerated(Node *output); - virtual void RunNodeAccelerated(const Node *node, const TimeRange& range, const NodeValueDatabase *input_params, NodeValueTable* output_params); StreamPtr ResolveStreamFromInput(NodeInput* input); diff --git a/app/widget/timelinewidget/tool/import.cpp b/app/widget/timelinewidget/tool/import.cpp index 42ed21e82..128f3ba80 100644 --- a/app/widget/timelinewidget/tool/import.cpp +++ b/app/widget/timelinewidget/tool/import.cpp @@ -26,6 +26,7 @@ #include "config/config.h" #include "common/qtversionabstraction.h" #include "core.h" +#include "node/audio/volume/volume.h" #include "node/distort/transform/transform.h" #include "node/input/media/audio/audio.h" #include "node/input/media/video/video.h" @@ -254,7 +255,12 @@ void TimelineWidget::ImportTool::DragDrop(TimelineViewMouseEvent *event) AudioInput* audio_input = new AudioInput(); audio_input->SetFootage(footage_stream); new NodeAddCommand(dst_graph, audio_input, command); - new NodeEdgeAddCommand(audio_input->output(), clip->texture_input(), command); + + VolumeNode* volume_node = new VolumeNode(); + new NodeAddCommand(dst_graph, volume_node, command); + + new NodeEdgeAddCommand(audio_input->output(), volume_node->samples_input(), command); + new NodeEdgeAddCommand(volume_node->output(), clip->texture_input(), command); break; } default: