1 /* 2 * Copyright (C) 2020 Linux Studio Plugins Project <https://lsp-plug.in/> 3 * (C) 2020 Vladimir Sadovnikov <sadko4u@gmail.com> 4 * 5 * This file is part of lsp-plugins 6 * Created on: 25 апр. 2019 г. 7 * 8 * lsp-plugins is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU Lesser General Public License as published by 10 * the Free Software Foundation, either version 3 of the License, or 11 * any later version. 12 * 13 * lsp-plugins is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public License 19 * along with lsp-plugins. If not, see <https://www.gnu.org/licenses/>. 20 */ 21 22 #ifndef PLUGINS_ROOM_BUILDER_H_ 23 #define PLUGINS_ROOM_BUILDER_H_ 24 25 #include <core/plugin.h> 26 #include <core/util/Bypass.h> 27 #include <core/util/Delay.h> 28 #include <core/util/Convolver.h> 29 #include <core/3d/Scene3D.h> 30 #include <core/3d/RayTrace3D.h> 31 #include <core/sampling/SamplePlayer.h> 32 #include <core/filters/Equalizer.h> 33 #include <data/cstorage.h> 34 35 36 #include <metadata/plugins.h> 37 38 namespace lsp 39 { 40 class room_builder_base: public plugin_t 41 { 42 public: 43 typedef struct obj_props_t 44 { 45 const char *sName; // UTF-8 object name 46 bool bEnabled; // Enabled flag 47 point3d_t sCenter; // Object center 48 vector3d_t sMove; // Object move 49 float fYaw; // Yaw 50 float fPitch; // Pitch 51 float fRoll; // Roll 52 vector3d_t sScale; // Scaling of object 53 float fHue; // Hue color 54 float fAbsorption[2]; 55 float lnkAbsorption; 56 float fDispersion[2]; 57 float lnkDispersion; 58 float fDiffusion[2]; 59 float lnkDiffusion; 60 float fTransparency[2]; 61 float lnkTransparency; 62 float fSndSpeed; 63 } obj_props_t; 64 65 protected: 66 enum sync_t 67 { 68 SYNC_TOGGLE_RENDER = 1 << 0 69 }; 70 71 protected: 72 73 typedef struct convolver_t 74 { 75 Delay sDelay; // Delay line 76 77 Convolver *pCurr; // Currently used convolver 78 Convolver *pSwap; // Swap 79 80 size_t nSampleID; // Sample identifier 81 size_t nTrackID; // Track identifier 82 83 float *vBuffer; // Buffer for convolution 84 float fPanIn[2]; // Input panning of convolver 85 float fPanOut[2]; // Output panning of convolver 86 87 IPort *pMakeup; // Makeup gain of convolver 88 IPort *pPanIn; // Input panning of convolver 89 IPort *pPanOut; // Output panning of convolver 90 IPort *pSample; // Convolver source sample 91 IPort *pTrack; // Convolver source sample track 92 IPort *pPredelay; // Pre-delay 93 IPort *pMute; // Mute button 94 IPort *pActivity; // Activity indicator 95 } convolver_t; 96 97 typedef struct channel_t 98 { 99 Bypass sBypass; 100 SamplePlayer sPlayer; 101 Equalizer sEqualizer; // Wet signal equalizer 102 103 float *vOut; 104 float *vBuffer; // Rendering buffer 105 float fDryPan[2]; // Dry panorama 106 107 IPort *pOut; 108 109 IPort *pWetEq; // Wet equalization flag 110 IPort *pLowCut; // Low-cut flag 111 IPort *pLowFreq; // Low-cut frequency 112 IPort *pHighCut; // High-cut flag 113 IPort *pHighFreq; // Low-cut frequency 114 IPort *pFreqGain[room_builder_base_metadata::EQ_BANDS]; // Gain for each band of the Equalizer 115 } channel_t; 116 117 typedef struct input_t 118 { 119 float *vIn; // Input data 120 IPort *pIn; // Input port 121 IPort *pPan; // Panning 122 } input_t; 123 124 typedef struct source_t: public room_source_config_t 125 { 126 bool bEnabled; 127 128 IPort *pEnabled; 129 IPort *pType; 130 IPort *pPhase; 131 IPort *pPosX; 132 IPort *pPosY; 133 IPort *pPosZ; 134 IPort *pYaw; 135 IPort *pPitch; 136 IPort *pRoll; 137 IPort *pSize; 138 IPort *pHeight; 139 IPort *pAngle; 140 IPort *pCurvature; 141 } source_t; 142 143 typedef struct capture_t: public room_capture_config_t 144 { 145 bool bEnabled; // Enabled flag 146 ssize_t nRMin; // Minimum reflection order 147 ssize_t nRMax; // Maximum reflection order 148 149 float fHeadCut; 150 float fTailCut; 151 float fFadeIn; 152 float fFadeOut; 153 bool bReverse; 154 float fMakeup; // Makeup gain 155 size_t nLength; // Output: length of captured response in samples 156 status_t nStatus; // Output: status of sample rendering 157 float fCurrLen; 158 float fMaxLen; 159 160 volatile uatomic_t nChangeReq; // Reconfiguration request 161 uatomic_t nChangeResp; // Reconfiguration response 162 bool bCommit; // Commit reconfiguration 163 bool bSync; // Sync with UI 164 bool bExport; // Export flag 165 166 Sample *pCurr; // Current sample for playback (rendered) 167 Sample *pSwap; // Swap sample (garbage or pending) 168 169 float *vThumbs[room_builder_base_metadata::TRACKS_MAX]; 170 171 // Capture functions 172 IPort *pEnabled; 173 IPort *pRMin; 174 IPort *pRMax; 175 IPort *pPosX; 176 IPort *pPosY; 177 IPort *pPosZ; 178 IPort *pYaw; 179 IPort *pPitch; 180 IPort *pRoll; 181 IPort *pCapsule; 182 IPort *pConfig; 183 IPort *pAngle; 184 IPort *pDistance; 185 IPort *pDirection; 186 IPort *pSide; 187 188 // Sample editor functions 189 IPort *pHeadCut; 190 IPort *pTailCut; 191 IPort *pFadeIn; 192 IPort *pFadeOut; 193 IPort *pListen; 194 IPort *pReverse; // Reverse 195 IPort *pMakeup; // Makeup gain 196 IPort *pStatus; // Status of rendering 197 IPort *pLength; // Length of sample 198 IPort *pCurrLen; // Current duration 199 IPort *pMaxLen; // Max duration 200 IPort *pThumbs; // Thumbnails of sample 201 202 IPort *pOutFile; // Output file name 203 IPort *pSaveCmd; // Save command 204 IPort *pSaveStatus; // Save status 205 IPort *pSaveProgress; // Save progress points 206 } capture_t; 207 208 typedef struct sample_t 209 { 210 Sample sSample; 211 size_t nID; 212 rt_capture_config_t enConfig; 213 } sample_t; 214 215 typedef struct reconfig_t 216 { 217 bool bReconfigure[room_builder_base_metadata::CAPTURES]; 218 uatomic_t nChangeResp[room_builder_base_metadata::CAPTURES]; 219 size_t nSampleID[room_builder_base_metadata::CONVOLVERS]; 220 size_t nTrack[room_builder_base_metadata::CONVOLVERS]; 221 size_t nRank[room_builder_base_metadata::CONVOLVERS]; 222 } reconfig_t; 223 224 protected: 225 class SceneLoader: public ipc::ITask 226 { 227 public: 228 size_t nFlags; 229 char sPath[PATH_MAX+1]; 230 room_builder_base *pCore; 231 Scene3D sScene; 232 233 public: SceneLoader()234 inline SceneLoader() 235 { 236 nFlags = 0; 237 pCore = NULL; 238 } 239 240 virtual ~SceneLoader(); 241 242 void init(room_builder_base *base); 243 void destroy(); 244 245 public: 246 virtual status_t run(); 247 }; 248 249 class RenderLauncher: public ipc::ITask 250 { 251 public: 252 room_builder_base *pBuilder; 253 254 public: RenderLauncher(room_builder_base * builder)255 inline RenderLauncher(room_builder_base *builder): pBuilder(builder) {} 256 257 public: 258 virtual status_t run(); 259 }; 260 261 class Renderer: public ipc::Thread 262 { 263 protected: 264 room_builder_base *pBuilder; 265 RayTrace3D *pRT; 266 size_t nThreads; 267 cvector<sample_t> vSamples; 268 ipc::Mutex lkTerminate; 269 270 public: Renderer(room_builder_base * bld,RayTrace3D * rt,size_t threads,cvector<sample_t> & samples)271 inline Renderer(room_builder_base *bld, RayTrace3D *rt, size_t threads, cvector<sample_t> &samples): 272 pBuilder(bld), pRT(rt), nThreads(threads) 273 { 274 vSamples.swap_data(&samples); 275 } 276 277 virtual status_t run(); 278 279 void terminate(); 280 }; 281 282 class Configurator: public ipc::ITask 283 { 284 public: 285 room_builder_base *pBuilder; 286 volatile uatomic_t nChangeReq; 287 uatomic_t nChangeResp; 288 reconfig_t sConfig; 289 290 public: Configurator(room_builder_base * bld)291 inline Configurator(room_builder_base *bld): 292 pBuilder(bld) 293 { 294 nChangeReq = 0; 295 nChangeResp = 0; 296 } 297 298 virtual status_t run(); 299 need_launch()300 inline bool need_launch() const { return nChangeReq != nChangeResp; } 301 queue_launch()302 inline void queue_launch() { atomic_add(&nChangeReq, 1); } 303 launched()304 inline void launched() { nChangeResp = nChangeReq; } 305 }; 306 307 class SampleSaver: public ipc::ITask 308 { 309 public: 310 room_builder_base *pBuilder; 311 char sPath[PATH_MAX+1]; 312 size_t nSampleID; 313 314 public: SampleSaver(room_builder_base * builder)315 inline SampleSaver(room_builder_base *builder) 316 { 317 pBuilder = builder; 318 sPath[0] = '\0'; 319 nSampleID = 0; 320 } 321 322 void bind(size_t sample_id, capture_t *capture); 323 324 public: 325 virtual status_t run(); 326 }; 327 328 protected: 329 size_t nInputs; 330 size_t nReconfigReq; 331 size_t nReconfigResp; 332 ssize_t nRenderThreads; 333 float fRenderQuality; 334 bool bRenderNormalize; 335 status_t enRenderStatus; 336 float fRenderProgress; 337 float fRenderCmd; 338 size_t nFftRank; 339 340 input_t vInputs[2]; 341 channel_t vChannels[2]; 342 convolver_t vConvolvers[room_builder_base_metadata::CONVOLVERS]; 343 capture_t vCaptures[room_builder_base_metadata::CAPTURES]; 344 source_t vSources[room_builder_base_metadata::SOURCES]; 345 346 Scene3D sScene; 347 vector3d_t sScale; 348 Renderer *pRenderer; 349 350 status_t nSceneStatus; 351 float fSceneProgress; 352 size_t nSync; 353 354 SceneLoader s3DLoader; 355 RenderLauncher s3DLauncher; 356 Configurator sConfigurator; 357 SampleSaver sSaver; 358 359 IPort *pBypass; 360 IPort *pRank; 361 IPort *pDry; 362 IPort *pWet; 363 IPort *pRenderThreads; 364 IPort *pRenderQuality; 365 IPort *pRenderStatus; 366 IPort *pRenderProgress; 367 IPort *pRenderNormalize; 368 IPort *pRenderCmd; 369 IPort *pOutGain; 370 IPort *pPredelay; 371 IPort *p3DFile; 372 IPort *p3DProgress; 373 IPort *p3DStatus; 374 IPort *p3DOrientation; 375 IPort *pScaleX; 376 IPort *pScaleY; 377 IPort *pScaleZ; 378 379 void *pData; // Allocated data 380 ipc::IExecutor *pExecutor; 381 382 protected: 383 static size_t get_fft_rank(size_t rank); 384 void sync_offline_tasks(); 385 status_t start_rendering(); 386 status_t run_rendring(void *arg); 387 status_t bind_sources(RayTrace3D *rt); 388 status_t bind_captures(cvector<sample_t> &samples, RayTrace3D *rt); 389 status_t bind_scene(KVTStorage *kvt, RayTrace3D *rt); 390 status_t commit_samples(cvector<sample_t> &samples); 391 status_t reconfigure(const reconfig_t *cfg); 392 status_t save_sample(const char *path, size_t sample_id); 393 static void destroy_samples(cvector<sample_t> &samples); 394 static status_t progress_callback(float progress, void *ptr); 395 static status_t fetch_kvt_sample(KVTStorage *kvt, size_t sample_id, sample_header_t *hdr, const float **samples); 396 397 public: 398 explicit room_builder_base(const plugin_metadata_t &metadata, size_t inputs); 399 virtual ~room_builder_base(); 400 401 public: 402 virtual void init(IWrapper *wrapper); 403 virtual void destroy(); 404 405 virtual void update_settings(); 406 virtual void update_sample_rate(long sr); 407 408 virtual void process(size_t samples); 409 410 virtual void state_loaded(); 411 virtual void ui_activated(); 412 413 public: 414 static rt_capture_config_t decode_config(float value); 415 static rt_audio_capture_t decode_direction(float value); 416 static rt_audio_capture_t decode_side_direction(float value); 417 static rt_audio_source_t decode_source_type(float value); 418 419 static void kvt_cleanup_objects(KVTStorage *kvt, size_t objects); 420 static void read_object_properties(obj_props_t *props, const char *base, KVTStorage *kvt); 421 static void build_object_matrix(matrix3d_t *m, const obj_props_t *props, const matrix3d_t *world); 422 }; 423 424 class room_builder_mono: public room_builder_base, public room_builder_mono_metadata 425 { 426 public: 427 explicit room_builder_mono(); 428 virtual ~room_builder_mono(); 429 }; 430 431 class room_builder_stereo: public room_builder_base, public room_builder_stereo_metadata 432 { 433 public: 434 explicit room_builder_stereo(); 435 virtual ~room_builder_stereo(); 436 }; 437 438 } 439 440 441 #endif /* PLUGINS_ROOM_BUILDER_H_ */ 442