| 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 |  |