1 // Copyright 2014 Olivier Gillet.
2 //
3 // Author: Olivier Gillet (ol.gillet@gmail.com)
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to deal
7 // in the Software without restriction, including without limitation the rights
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 // THE SOFTWARE.
22 //
23 // See http://creativecommons.org/licenses/MIT/ for more information.
24 //
25 // -----------------------------------------------------------------------------
26 //
27 // Main processing class.
28 
29 #ifndef CLOUDS_DSP_GRANULAR_PROCESSOR_H_
30 #define CLOUDS_DSP_GRANULAR_PROCESSOR_H_
31 
32 #include "stmlib/stmlib.h"
33 #include "stmlib/dsp/filter.h"
34 
35 #include "clouds/dsp/correlator.h"
36 #include "clouds/dsp/frame.h"
37 #include "clouds/dsp/fx/diffuser.h"
38 #include "clouds/dsp/fx/pitch_shifter.h"
39 #include "clouds/dsp/fx/reverb.h"
40 #include "clouds/dsp/resonestor.h"
41 #include "clouds/dsp/fx/oliverb.h"
42 #include "clouds/dsp/granular_processor.h"
43 #include "clouds/dsp/granular_sample_player.h"
44 #include "clouds/dsp/looping_sample_player.h"
45 #include "clouds/dsp/pvoc/phase_vocoder.h"
46 #include "clouds/dsp/sample_rate_converter.h"
47 #include "clouds/dsp/wsola_sample_player.h"
48 
49 namespace clouds {
50 
51 const int32_t kDownsamplingFactor = 2;
52 
53 enum PlaybackMode {
54   PLAYBACK_MODE_GRANULAR,
55   PLAYBACK_MODE_STRETCH,
56   PLAYBACK_MODE_LOOPING_DELAY,
57   PLAYBACK_MODE_SPECTRAL,
58   PLAYBACK_MODE_OLIVERB,
59   PLAYBACK_MODE_RESONESTOR,
60   PLAYBACK_MODE_LAST
61 };
62 
63 // State of the recording buffer as saved in one of the 4 sample memories.
64 struct PersistentState {
65   int32_t write_head[2];
66   uint8_t quality;
67   uint8_t spectral;
68 };
69 
70 // Data block as saved in one of the 4 sample memories.
71 struct PersistentBlock {
72   uint32_t tag;
73   uint32_t size;
74   void* data;
75 };
76 
77 class GranularProcessor {
78  public:
GranularProcessor()79   GranularProcessor() { }
~GranularProcessor()80   ~GranularProcessor() { }
81 
82   void Init(
83       void* large_buffer,
84       size_t large_buffer_size,
85       void* small_buffer,
86       size_t small_buffer_size);
87 
88   void Process(ShortFrame* input, ShortFrame* output, size_t size);
89   void Prepare();
90 
mutable_parameters()91   inline Parameters* mutable_parameters() {
92     return &parameters_;
93   }
94 
parameters()95   inline const Parameters& parameters() const {
96     return parameters_;
97   }
98 
ToggleFreeze()99   inline void ToggleFreeze() {
100     parameters_.freeze = !parameters_.freeze;
101   }
ToggleReverse()102   inline void ToggleReverse() {
103     parameters_.granular.reverse = !parameters_.granular.reverse;
104   }
105 
frozen()106   inline bool frozen() const {
107     return parameters_.freeze;
108   }
109 
reversed()110   inline bool reversed() const {
111     return parameters_.granular.reverse;
112   }
113 
set_silence(bool silence)114   inline void set_silence(bool silence) {
115     silence_ = silence;
116   }
117 
set_bypass(bool bypass)118   inline void set_bypass(bool bypass) {
119     bypass_ = bypass;
120   }
121 
bypass()122   inline bool bypass() const {
123     return bypass_;
124   }
125 
set_playback_mode(PlaybackMode playback_mode)126   inline void set_playback_mode(PlaybackMode playback_mode) {
127     playback_mode_ = playback_mode;
128   }
129 
playback_mode()130   inline PlaybackMode playback_mode() const { return playback_mode_; }
131 
set_quality(int32_t quality)132   inline void set_quality(int32_t quality) {
133     set_num_channels(quality & 1 ? 1 : 2);
134     set_low_fidelity(quality >> 1 ? true : false);
135   }
136 
set_num_channels(int32_t num_channels)137   inline void set_num_channels(int32_t num_channels) {
138     reset_buffers_ = reset_buffers_ || num_channels_ != num_channels;
139     num_channels_ = num_channels;
140   }
141 
set_low_fidelity(bool low_fidelity)142   inline void set_low_fidelity(bool low_fidelity) {
143     reset_buffers_ = reset_buffers_ || low_fidelity != low_fidelity_;
144     low_fidelity_ = low_fidelity;
145   }
146 
quality()147   inline int32_t quality() const {
148     int32_t quality = 0;
149     if (num_channels_ == 1) quality |= 1;
150     if (low_fidelity_) quality |= 2;
151     return quality;
152   }
153 
154   void GetPersistentData(PersistentBlock* block, size_t *num_blocks);
155   bool LoadPersistentData(const uint32_t* data);
156   void PreparePersistentData();
157 
158  private:
resolution()159   inline int32_t resolution() const {
160     return low_fidelity_ ? 8 : 16;
161   }
162 
sample_rate()163   inline float sample_rate() const {
164     return 48000.0f / \
165         (low_fidelity_ ? kDownsamplingFactor : 1);
166   }
167 
168   void ResetFilters();
169   void ProcessGranular(FloatFrame* input, FloatFrame* output, size_t size);
170 
171   PlaybackMode playback_mode_;
172   PlaybackMode previous_playback_mode_;
173   int32_t num_channels_;
174   bool low_fidelity_;
175 
176   bool silence_;
177   bool bypass_;
178   bool reset_buffers_;
179   float freeze_lp_;
180   float dry_wet_;
181 
182   void* buffer_[2];
183   size_t buffer_size_[2];
184 
185   Correlator correlator_;
186 
187   GranularSamplePlayer player_;
188   WSOLASamplePlayer ws_player_;
189   LoopingSamplePlayer looper_;
190   PhaseVocoder phase_vocoder_;
191 
192   Diffuser diffuser_;
193   Reverb reverb_;
194   Oliverb oliverb_;
195   Resonestor resonestor_;
196   PitchShifter pitch_shifter_;
197   stmlib::Svf fb_filter_[2];
198   stmlib::Svf hp_filter_[2];
199   stmlib::Svf lp_filter_[2];
200 
201   AudioBuffer<RESOLUTION_8_BIT_MU_LAW> buffer_8_[2];
202   AudioBuffer<RESOLUTION_16_BIT> buffer_16_[2];
203 
204   FloatFrame in_[kMaxBlockSize];
205   FloatFrame in_downsampled_[kMaxBlockSize / kDownsamplingFactor];
206   FloatFrame out_downsampled_[kMaxBlockSize / kDownsamplingFactor];
207   FloatFrame out_[kMaxBlockSize];
208   FloatFrame fb_[kMaxBlockSize];
209 
210   int16_t tail_buffer_[2][256];
211 
212   Parameters parameters_;
213 
214   SampleRateConverter<-kDownsamplingFactor, 45, src_filter_1x_2_45> src_down_;
215   SampleRateConverter<+kDownsamplingFactor, 45, src_filter_1x_2_45> src_up_;
216 
217   PersistentState persistent_state_;
218 
219   DISALLOW_COPY_AND_ASSIGN(GranularProcessor);
220 };
221 
222 }  // namespace clouds
223 
224 #endif  // CLOUDS_DSP_GRANULAR_PROCESSOR_H_
225