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