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: 19 нояб. 2016 г.
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 CORE_UTIL_OVERSAMPLER_H_
23 #define CORE_UTIL_OVERSAMPLER_H_
24 
25 #include <core/IStateDumper.h>
26 #include <core/filters/Filter.h>
27 
28 namespace lsp
29 {
30     /** Callback to perform processing of oversampled signal
31      *
32      */
33     class IOversamplerCallback
34     {
35         public:
36             /** Virtual destructor
37              *
38              */
39             virtual ~IOversamplerCallback();
40 
41             /** Processing routine
42              *
43              * @param out output buffer of samples size
44              * @param in input buffer of samples size
45              * @param samples number of samples to process
46              */
47             virtual void process(float *out, const float *in, size_t samples);
48     };
49 
50     enum over_mode_t
51     {
52         OM_NONE,
53 
54         OM_LANCZOS_2X2,
55         OM_LANCZOS_2X3,
56         OM_LANCZOS_2X4,
57 
58         OM_LANCZOS_3X2,
59         OM_LANCZOS_3X3,
60         OM_LANCZOS_3X4,
61 
62         OM_LANCZOS_4X2,
63         OM_LANCZOS_4X3,
64         OM_LANCZOS_4X4,
65 
66         OM_LANCZOS_6X2,
67         OM_LANCZOS_6X3,
68         OM_LANCZOS_6X4,
69 
70         OM_LANCZOS_8X2,
71         OM_LANCZOS_8X3,
72         OM_LANCZOS_8X4
73     };
74 
75     /** Oversampler class
76      *
77      */
78     class Oversampler
79     {
80         private:
81             Oversampler & operator = (const Oversampler &);
82 
83         protected:
84             enum update_t
85             {
86                 UP_MODE         = 1 << 0,
87                 UP_SAMPLE_RATE  = 1 << 2,
88                 UP_OTHER        = 1 << 3,
89 
90                 UP_ALL          = UP_MODE | UP_OTHER | UP_SAMPLE_RATE
91             };
92 
93         protected:
94             IOversamplerCallback   *pCallback;
95             float                  *fUpBuffer;
96             float                  *fDownBuffer;
97             size_t                  nUpHead;
98             size_t                  nMode;
99             size_t                  nSampleRate;
100             size_t                  nUpdate;
101             Filter                  sFilter;
102             uint8_t                *bData;
103             bool                    bFilter;
104 
105         public:
106             explicit Oversampler();
107             virtual ~Oversampler();
108 
109             void construct();
110 
111         public:
112             /** Initialize oversampler
113              *
114              */
115             bool init();
116 
117             /** Destroy oversampler
118              *
119              */
120             void destroy();
121 
122             /** Set sample rate
123              *
124              * @param sr sample rate
125              */
126             void set_sample_rate(size_t sr);
127 
128             /** Set oversampling callback
129              *
130              * @param callback calback to call on process()
131              */
set_callback(IOversamplerCallback * callback)132             inline void set_callback(IOversamplerCallback *callback)
133             {
134                 pCallback       = callback;
135             }
136 
137             /** Set oversampling ratio
138              *
139              * @param mode oversampling mode
140              */
set_mode(over_mode_t mode)141             inline void set_mode(over_mode_t mode)
142             {
143                 if (mode < OM_NONE)
144                     mode = OM_NONE;
145                 else if (mode > OM_LANCZOS_8X4)
146                     mode = OM_LANCZOS_8X4;
147                 if (nMode == mode)
148                     return;
149                 nMode      = mode;
150                 nUpdate   |= UP_MODE;
151             }
152 
153             /** Enable/disable low-pass filter when performing downsampling
154              *
155              * @param filter enables/diables low-pass filter
156              */
set_filtering(bool filter)157             inline void set_filtering(bool filter)
158             {
159                 if (bFilter == filter)
160                     return;
161                 bFilter     = filter;
162                 nUpdate   |= UP_MODE;
163             }
164 
165             /** Check that module needs re-configuration
166              *
167              * @return true if needs reconfiguration
168              */
modified()169             inline bool modified() const
170             {
171                 return nUpdate;
172             }
173 
174             /** Get current oversampling multiplier
175              *
176              * @return current oversampling multiplier
177              */
178             size_t get_oversampling() const;
179 
180             /** Update settings
181              *
182              */
183             void update_settings();
184 
185             /** Perform upsampling of the signal
186              *
187              * @param dst destination buffer of samples*ratio size
188              * @param src source buffer of samples size
189              * @param samples number of samples that should be processed in src buffer
190              */
191             void upsample(float *dst, const float *src, size_t samples);
192 
193             /** Perform downsampling of the signal
194              *
195              * @param dst destination buffer of samples size
196              * @param src source buffer of samples*ratio size
197              * @param samples number of samples that should be produced into the dst buffer
198              */
199             void downsample(float *dst, const float *src, size_t samples);
200 
201             /** Perform processing of the signal
202              *
203              * @param dst destination buffer of samples size
204              * @param src source buffer of samples size
205              * @param samples number of samples to process
206              * @param callback callback to handle buffer
207              */
208             void process(float *dst, const float *src, size_t samples, IOversamplerCallback *callback);
209 
210             /** Perform processing of the signal
211              *
212              * @param dst destination buffer of samples size
213              * @param src source buffer of samples size
214              * @param samples number of samples to process
215              */
process(float * dst,const float * src,size_t samples)216             inline void process(float *dst, const float *src, size_t samples)
217             {
218                 process(dst, src, samples, pCallback);
219             }
220 
221             /**
222              * Get oversampler latency
223              * @return oversampler latency in normal (non-oversampled) samples
224              */
225             size_t latency() const;
226 
227             /**
228              * Get maximum possible latency
229              * @return maximum possible latency
230              */
max_latency()231             inline size_t max_latency() const       { return 8; }
232 
233             /**
234              * Dump the state
235              * @param dumper dumper
236              */
237             void dump(IStateDumper *v) const;
238     };
239 
240 } /* namespace lsp */
241 
242 #endif /* CORE_UTIL_OVERSAMPLER_H_ */
243