-
Notifications
You must be signed in to change notification settings - Fork 101
Expand file tree
/
Copy pathaudio_graph_executor.h
More file actions
118 lines (94 loc) · 4.06 KB
/
Copy pathaudio_graph_executor.h
File metadata and controls
118 lines (94 loc) · 4.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#pragma once
#include <cstring>
#include <memory>
#include <unordered_map>
#include <vector>
#include "audio/effects/core/effect.h"
#include "audio/engine/audio_graph.h"
namespace Amplitron {
class INodeProcessor {
public:
virtual ~INodeProcessor() = default;
virtual void process(const float* input, float* output, int num_samples) = 0;
};
class StandardEffectProcessor : public INodeProcessor {
public:
explicit StandardEffectProcessor(std::shared_ptr<Effect> pedal) : pedal_(std::move(pedal)) {}
void process(const float* input, float* output, int num_samples) override {
std::memcpy(output, input, static_cast<size_t>(num_samples) * sizeof(float));
if (pedal_) {
pedal_->process(output, num_samples);
}
}
private:
std::shared_ptr<Effect> pedal_;
};
class PassthroughProcessor : public INodeProcessor {
public:
void process(const float* input, float* output, int num_samples) override {
std::memcpy(output, input, static_cast<size_t>(num_samples) * sizeof(float));
}
};
class AnalyzerCapture;
class AudioGraphExecutor {
public:
friend class AudioEngine;
// ── Public nested types ────────────────────────────────────────────────
// Kept public so that white-box tests (and AudioEngine friend code) can
// inspect the execution plan without requiring #define private public.
struct InputSource {
int buffer_index; // The pool index to read from
float gain = 1.0f;
int pin_index = 0;
};
struct NodeExecutionStep {
int node_id;
int buffer_index; // The pool index this node writes to
NodeRoutingType type;
std::shared_ptr<Effect> pedal;
std::vector<InputSource> input_sources; // Which buffers to sum together for the input
std::unique_ptr<INodeProcessor> processor; // Polymorphic node executor
bool is_graph_input = false;
bool is_graph_output = false;
bool is_sink = false;
};
// ── End public nested types ────────────────────────────────────────────
AudioGraphExecutor();
~AudioGraphExecutor() = default;
// Allocate the memory pool ahead of time (Call this during engine initialization)
void prepare(int sample_rate, int max_block_size, int max_nodes = 32);
// Translates the AudioGraph into a flat, allocation-free execution array
// Call this from the UI thread whenever connections change!
void compile(const AudioGraph& graph);
// Broadcast tempo/BPM down to all active nodes in the execution plan
void update_transport_state(float bpm);
// Hot-path processing (Strictly allocation-free and lock-free)
// Adjust the pedal->process signature if your pedals process strictly in-place
void process(const float* input, float* output, int num_samples,
AnalyzerCapture* capture = nullptr);
void update_mixer_gain(int node_id, int pin_index, float gain);
std::shared_ptr<Effect> get_effect_by_node_id(int node_id) const {
for (const auto& step : execution_plan_) {
if (step.node_id == node_id) {
return step.pedal;
}
}
return nullptr;
}
#ifdef AMPLITRON_TESTS
/** @brief Direct read-only access to the execution plan for white-box testing. */
const std::vector<NodeExecutionStep>& test_execution_plan() const { return execution_plan_; }
#endif
private:
int sample_rate_ = 48000;
int max_block_size_ = 512;
int max_nodes_ = 32;
std::vector<NodeExecutionStep> execution_plan_;
bool any_explicit_input_ = false;
int fallback_input_node_id_ = -1;
// Pre-allocated memory for routing parallel signal streams: [node_capacity][max_block_size]
std::vector<std::vector<float>> buffer_pool_;
// A dedicated temporary buffer for summing multiple incoming signals
std::vector<float> sum_buffer_;
};
} // namespace Amplitron