1 | /* |
2 | Copyright 2018 Google Inc. All Rights Reserved. |
3 | |
4 | Licensed under the Apache License, Version 2.0 (the "License"); |
5 | you may not use this file except in compliance with the License. |
6 | You may obtain a copy of the License at |
7 | |
8 | http://www.apache.org/licenses/LICENSE-2.0 |
9 | |
10 | Unless required by applicable law or agreed to in writing, software |
11 | distributed under the License is distributed on an "AS-IS" BASIS, |
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | See the License for the specific language governing permissions and |
14 | limitations under the License. |
15 | */ |
16 | |
17 | #ifndef RESONANCE_AUDIO_GRAPH_GRAPH_MANAGER_H_ |
18 | #define RESONANCE_AUDIO_GRAPH_GRAPH_MANAGER_H_ |
19 | |
20 | #include <memory> |
21 | #include <string> |
22 | #include <unordered_map> |
23 | |
24 | #include "ambisonics/ambisonic_lookup_table.h" |
25 | #include "base/audio_buffer.h" |
26 | #include "base/constants_and_types.h" |
27 | #include "config/global_config.h" |
28 | #include "dsp/fft_manager.h" |
29 | #include "dsp/resampler.h" |
30 | #include "graph/ambisonic_binaural_decoder_node.h" |
31 | #include "graph/ambisonic_mixing_encoder_node.h" |
32 | #include "graph/buffered_source_node.h" |
33 | #include "graph/gain_mixer_node.h" |
34 | #include "graph/mixer_node.h" |
35 | #include "graph/reflections_node.h" |
36 | #include "graph/reverb_node.h" |
37 | #include "graph/stereo_mixing_panner_node.h" |
38 | #include "graph/system_settings.h" |
39 | #include "node/sink_node.h" |
40 | |
41 | namespace vraudio { |
42 | |
43 | // The GraphManager class manages the construction and lifetime of the audio |
44 | // processing graph. It owns the output node that connects the audio processing |
45 | // graph to the audio hardware. |
46 | class GraphManager { |
47 | public: |
48 | // Initializes GraphManager class. |
49 | // |
50 | // @param system_settings Global system configuration. |
51 | explicit GraphManager(const SystemSettings& system_settings); |
52 | |
53 | // Returns the sink node the audio graph is connected to. |
54 | // |
55 | // @return Shared pointer of the sink node. |
56 | std::shared_ptr<SinkNode> GetSinkNode(); |
57 | |
58 | // Triggers processing of the audio graph for all the connected nodes. |
59 | void Process(); |
60 | |
61 | // Returns a mutable pointer to the |AudioBuffer| of an audio source with |
62 | // given |source_id|. Calls to this method must be synchronized with the audio |
63 | // graph processing. |
64 | // |
65 | // @param source_id Source id. |
66 | // @return Mutable audio buffer pointer. Nullptr if source_id not found. |
67 | AudioBuffer* GetMutableAudioBuffer(SourceId source_id); |
68 | |
69 | // Creates an ambisonic panner source with given |sound_object_source_id|. |
70 | // |
71 | // Processing graph: |
72 | // |
73 | // +-------------------+ |
74 | // | | |
75 | // +------------+ SoundObjectSource +----------+ |
76 | // | | | | |
77 | // | +---------+---------+ | |
78 | // | | |
79 | // +-----------v-----------+ +---------v----------+ |
80 | // | | | | |
81 | // | AmbisonicMixingPanner | | StereoMixingPanner | |
82 | // | | | | |
83 | // +-----------+-----------+ +---------+----------+ |
84 | // | | |
85 | // +-----------v-----------+ +---------v----------+ |
86 | // | | | | |
87 | // | AmbisonicMixer | | StereoMixer | |
88 | // | | | | |
89 | // +-----------+-----------+ +--------------------+ |
90 | // |
91 | // |
92 | // @param sound_object_source_id Id of sound object source. |
93 | // @param enable_hrtf Flag to enable HRTF-based spatialization. |
94 | void CreateAmbisonicPannerSource(SourceId sound_object_source_id, |
95 | bool enable_hrtf); |
96 | |
97 | // Creates a new stereo non-spatialized source with given |stereo_source_id|. |
98 | // |
99 | // Processing graph: |
100 | // |
101 | // +--------------+ |
102 | // | | |
103 | // | StereoSource | |
104 | // | | |
105 | // +-------+------+ |
106 | // | |
107 | // +-------v------+ |
108 | // | | |
109 | // | Gain | |
110 | // | | |
111 | // +-------+------+ |
112 | // | |
113 | // +-------V------+ |
114 | // | | |
115 | // | StereoMixer | |
116 | // | | |
117 | // +--------------+ |
118 | // |
119 | // @param stereo_source_id Id of new stereo source. |
120 | void CreateStereoSource(SourceId stereo_source_id); |
121 | |
122 | // Destroys source with given |source_id|. Note that this call only sets a |
123 | // flag to indicate that this source can be removed. The actual disconnect |
124 | // happens from the audio processing thread the next time the processing graph |
125 | // is triggered. |
126 | // |
127 | // @param source_id Id of source to be destroyed. |
128 | void DestroySource(SourceId source_id); |
129 | |
130 | // Creates a new ambisonic source subgraph with given |ambisonic_source_id|. |
131 | // Note: Ambisonic source subgraph is only created if the rendering mode is |
132 | // HRTF. |
133 | // |
134 | // Processing graph (all the graphs created using http://asciiflow.com/): |
135 | // |
136 | // +-----------------+ |
137 | // | | |
138 | // +-------+ AmbisonicSource +-------+ |
139 | // | | | | |
140 | // | +-----------------+ | |
141 | // | | |
142 | // +----v---+ +----------v---------+ |
143 | // | | | | |
144 | // | Gain | +--+ MonoFromSoundfield +--+ |
145 | // | | | | | | |
146 | // +----+---+ | +--------------------+ | |
147 | // | | | |
148 | // | | | |
149 | // +--------v-------+ +--------v---------+ +------v------+ |
150 | // | | | | | | |
151 | // | Foa/HoaRotator | | ReflectionsMixer | | ReverbMixer | |
152 | // | | | | | | |
153 | // +--------+-------+ +--------+---------+ +------+------+ |
154 | // | |
155 | // +--------v-------+ |
156 | // | | |
157 | // | AmbisonicMixer | |
158 | // | | |
159 | // +--------+-------+ |
160 | // |
161 | // @param ambisonic_source_id Id of new ambisonic source. |
162 | // @param num_channels Number of input channels of ambisonic source node. |
163 | void CreateAmbisonicSource(SourceId ambisonic_source_id, size_t num_channels); |
164 | |
165 | // Creates a new sound object source with given |sound_object_source_id|. |
166 | // |
167 | // Processing graph: |
168 | // |
169 | // +-------------------+ |
170 | // | | |
171 | // +-------------+ SoundObjectSource +----------+ |
172 | // | | | | |
173 | // | +---------+---------+ | |
174 | // | | | |
175 | // +----------v-----------+ +---------v---------+ +--------v--------+ |
176 | // | | | | | | |
177 | // | ReflectionsGainMixer | | DirectAttenuation | | ReverbGainMixer | |
178 | // | | | | | | |
179 | // +----------+-----------+ +---------+---------+ +--------+--------+ |
180 | // | |
181 | // +---------v---------+ |
182 | // HRTF | | Stereo Panning |
183 | // +------------+ Occlusion +----------+ |
184 | // | | | | |
185 | // | +---------+---------+ | |
186 | // | | | |
187 | // +-----------v-----------+ +--------v--------+ +---------v----------+ |
188 | // | | | | | | |
189 | // | AmbisonicMixingPanner | | NearFieldEffect | | StereoMixingPanner | |
190 | // | | | | | | |
191 | // +-----------+-----------+ +--------+--------+ +---------+----------+ |
192 | // | | | |
193 | // +-----------v-----------+ +--------v--------+ | |
194 | // | | | | | |
195 | // | AmbisonicMixer | | StereoMixer <-----------+ |
196 | // | | | | |
197 | // +-----------+-----------+ +-----------------+ |
198 | // |
199 | // |
200 | // @param sound_object_source_id Id of sound object source. |
201 | // @param ambisonic_order Ambisonic order to encode the sound object source. |
202 | // @param enable_hrtf Flag to enable HRTF-based rendering. |
203 | // @param enable_direct_rendering Flag to enable direct source rendering. |
204 | void CreateSoundObjectSource(SourceId sound_object_source_id, |
205 | int ambisonic_order, bool enable_hrtf, |
206 | bool enable_direct_rendering); |
207 | |
208 | // Mutes on/off the room effects mixers. |
209 | // |
210 | // @param Whether to enable room effects. |
211 | void EnableRoomEffects(bool enable); |
212 | |
213 | // Returns the last processed output audio buffer of the ambisonic mix with |
214 | // the highest possible ambisonic channel configuration. Note that, this |
215 | // method will *not* trigger the processing of the audio graph. |
216 | // |GraphManager::Process| must be called prior to this method call to ensure |
217 | // that the output buffer is up-to-date. |
218 | // |
219 | // @return Output audio buffer of the ambisonic mix, or nullptr if no output. |
220 | const AudioBuffer* GetAmbisonicBuffer() const; |
221 | |
222 | // Returns the last processed output audio buffer of the stereo (binaural) |
223 | // mix. Note that, this method will *not* trigger the processing of the audio |
224 | // graph. |GraphManager::Process| must be called prior to this method call to |
225 | // ensure that the output buffer is up-to-date. |
226 | // |
227 | // @return Output audio buffer of the stereo mix, or nullptr if no output. |
228 | const AudioBuffer* GetStereoBuffer() const; |
229 | |
230 | // Returns the last processed buffer containing the reverb data for the room. |
231 | // The buffer contains stereo data. |
232 | // Note that, this method will *not* trigger the processing of the audio |
233 | // graph. |GraphManager::Process| must be called prior to this method call to |
234 | // ensure that the buffer is up-to-date. |
235 | // |
236 | // @return Room reverb audio buffer, or nullptr if no output. |
237 | const AudioBuffer* GetReverbBuffer() const; |
238 | |
239 | // Returns the maximum allowed number of ambisonic channels. |
240 | // |
241 | // @return Number of channels based on Ambisonic order in the global config. |
242 | size_t GetNumMaxAmbisonicChannels() const; |
243 | |
244 | // Returns whether the room effects graph is enabled. |
245 | // |
246 | // @return True if room effects are enabled. |
247 | bool GetRoomEffectsEnabled() const; |
248 | |
249 | // Updates the room reflections with the current properties for room effects |
250 | // processing. |
251 | void UpdateRoomReflections(); |
252 | |
253 | // Updates the room reverb. |
254 | void UpdateRoomReverb(); |
255 | |
256 | private: |
257 | // Initializes the Ambisonic renderer subgraph for the speficied Ambisonic |
258 | // order and connects it to the |StereoMixerNode|. |
259 | // |
260 | // Processing graph: |
261 | // |
262 | // +------------------+ |
263 | // | | |
264 | // | AmbisonicMixer | |
265 | // | | |
266 | // +--------+---------+ |
267 | // | |
268 | // | |
269 | // +------------v-------------+ |
270 | // | | |
271 | // | AmbisonicBinauralDecoder | |
272 | // | | |
273 | // +------------+-------------+ |
274 | // | |
275 | // | |
276 | // +-----------v------------+ |
277 | // | | |
278 | // | StereoMixer | |
279 | // | | |
280 | // +------------------------+ |
281 | // |
282 | // @param ambisonic_order Ambisonic order. |
283 | // @param sh_hrir_filename Filename to load the HRIR data from. |
284 | void InitializeAmbisonicRendererGraph(int ambisonic_order, |
285 | const std::string& sh_hrir_filename); |
286 | |
287 | // Helper method to lookup a source node with given |source_id|. |
288 | // |
289 | // @param source_id Source id. |
290 | // @returns Shared pointer to source node instance, nullptr if not found. |
291 | std::shared_ptr<BufferedSourceNode> LookupSourceNode(SourceId source_id); |
292 | |
293 | // Creates an audio subgraph that renders early reflections based on a room |
294 | // model on a single mix. |
295 | // |
296 | // Processing graph: |
297 | // |
298 | // +---------------------------+ |
299 | // | | |
300 | // | ReflectionsGainMixer | |
301 | // | | |
302 | // +-------------+-------------+ |
303 | // | |
304 | // +----------v----------+ |
305 | // | | |
306 | // | Reflections | |
307 | // | | |
308 | // +----------+----------+ |
309 | // | |
310 | // +----------v----------+ |
311 | // | | |
312 | // | AmbisonicMixer | |
313 | // | | |
314 | // +----------+----------+ |
315 | // |
316 | void InitializeReflectionsGraph(); |
317 | |
318 | // Creates an audio subgraph that renders a reverb from a mono mix of all the |
319 | // sound objects based on a room model. |
320 | // |
321 | // Processing graph: |
322 | // |
323 | // +-----------------+ |
324 | // | | |
325 | // | ReverbGainMixer | |
326 | // | | |
327 | // +--------+--------+ |
328 | // | |
329 | // +--------v--------+ |
330 | // | | |
331 | // | Reverb | |
332 | // | | |
333 | // +--------+--------+ |
334 | // | |
335 | // +--------v--------+ |
336 | // | | |
337 | // | StereoMixer | |
338 | // | | |
339 | // +-----------------+ |
340 | // |
341 | void InitializeReverbGraph(); |
342 | |
343 | // Flag indicating if room effects are enabled. |
344 | bool room_effects_enabled_; |
345 | |
346 | // Mono mixer to accumulate all reverb sources. |
347 | std::shared_ptr<GainMixerNode> reverb_gain_mixer_node_; |
348 | |
349 | // Reflections node. |
350 | std::shared_ptr<ReflectionsNode> reflections_node_; |
351 | |
352 | // Mono mixer node to accumulate the early reflection sources. |
353 | std::shared_ptr<GainMixerNode> reflections_gain_mixer_node_; |
354 | |
355 | // Reverb node. |
356 | std::shared_ptr<ReverbNode> reverb_node_; |
357 | |
358 | // Ambisonic output mixer to accumulate incoming ambisonic inputs into a |
359 | // single ambisonic output buffer. |
360 | std::unique_ptr<Mixer> ambisonic_output_mixer_; |
361 | |
362 | // Global config passed in during construction. |
363 | const GraphManagerConfig config_; |
364 | |
365 | // Manages system wide settings. |
366 | const SystemSettings& system_settings_; |
367 | |
368 | // Provides Ambisonic encoding coefficients. |
369 | std::unique_ptr<AmbisonicLookupTable> lookup_table_; |
370 | |
371 | // |FftManager| to be used in nodes that require FFT transformations. |
372 | FftManager fft_manager_; |
373 | |
374 | // |Resampler| to be used to convert HRIRs to the system sample rate. |
375 | Resampler resampler_; |
376 | |
377 | // Ambisonic mixer nodes per each ambisonic order to accumulate the |
378 | // ambisonic sources for the corresponding binaural Ambisonic decoders. |
379 | std::unordered_map<int, std::shared_ptr<MixerNode>> ambisonic_mixer_nodes_; |
380 | |
381 | // Stereo mixer to combine all the stereo and binaural output. |
382 | std::shared_ptr<MixerNode> stereo_mixer_node_; |
383 | |
384 | // Ambisonic mixing encoder node to apply encoding coefficients and accumulate |
385 | // the Ambisonic buffers. |
386 | std::unordered_map<int, std::shared_ptr<AmbisonicMixingEncoderNode>> |
387 | ambisonic_mixing_encoder_nodes_; |
388 | |
389 | // Stereo mixing panner node to apply stereo panning gains and accumulate the |
390 | // buffers. |
391 | std::shared_ptr<StereoMixingPannerNode> stereo_mixing_panner_node_; |
392 | |
393 | // Output node that enables audio playback of a single audio stream. |
394 | std::shared_ptr<SinkNode> output_node_; |
395 | |
396 | // Holds all registered source nodes (independently of their type) and |
397 | // allows look up by id. |
398 | std::unordered_map<SourceId, std::shared_ptr<BufferedSourceNode>> |
399 | source_nodes_; |
400 | }; |
401 | |
402 | } // namespace vraudio |
403 | |
404 | #endif // RESONANCE_AUDIO_GRAPH_GRAPH_MANAGER_H_ |
405 | |