1 // Copyright 2014 Emilie Gillet.
2 //
3 // Author: Emilie Gillet (emilie.o.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/granular_processor.h"
41 #include "clouds/dsp/granular_sample_player.h"
42 #include "clouds/dsp/looping_sample_player.h"
43 #include "clouds/dsp/pvoc/phase_vocoder.h"
44 #include "clouds/dsp/sample_rate_converter.h"
45 #include "clouds/dsp/wsola_sample_player.h"
46 
47 namespace clouds {
48 
49 const int32_t kDownsamplingFactor = 2;
50 
51 enum PlaybackMode {
52   PLAYBACK_MODE_GRANULAR,
53   PLAYBACK_MODE_STRETCH,
54   PLAYBACK_MODE_LOOPING_DELAY,
55   PLAYBACK_MODE_SPECTRAL,
56   PLAYBACK_MODE_LAST
57 };
58 
59 // State of the recording buffer as saved in one of the 4 sample memories.
60 struct PersistentState {
61   int32_t write_head[2];
62   uint8_t quality;
63   uint8_t spectral;
64 };
65 
66 // Data block as saved in one of the 4 sample memories.
67 struct PersistentBlock {
68   uint32_t tag;
69   uint32_t size;
70   void* data;
71 };
72 
73 class GranularProcessor {
74  public:
GranularProcessor()75   GranularProcessor() { }
~GranularProcessor()76   ~GranularProcessor() { }
77 
78   void Init(
79       void* large_buffer,
80       size_t large_buffer_size,
81       void* small_buffer,
82       size_t small_buffer_size);
83 
84   void Process(ShortFrame* input, ShortFrame* output, size_t size);
85   void Prepare();
86 
mutable_parameters()87   inline Parameters* mutable_parameters() {
88     return &parameters_;
89   }
90 
parameters()91   inline const Parameters& parameters() const {
92     return parameters_;
93   }
94 
ToggleFreeze()95   inline void ToggleFreeze() {
96     parameters_.freeze = !parameters_.freeze;
97   }
98 
set_freeze(bool freeze)99   inline void set_freeze(bool freeze) {
100     parameters_.freeze = freeze;
101   }
102 
frozen()103   inline bool frozen() const {
104     return parameters_.freeze;
105   }
106 
set_silence(bool silence)107   inline void set_silence(bool silence) {
108     silence_ = silence;
109   }
110 
set_bypass(bool bypass)111   inline void set_bypass(bool bypass) {
112     bypass_ = bypass;
113   }
114 
bypass()115   inline bool bypass() const {
116     return bypass_;
117   }
118 
set_playback_mode(PlaybackMode playback_mode)119   inline void set_playback_mode(PlaybackMode playback_mode) {
120     playback_mode_ = playback_mode;
121   }
122 
playback_mode()123   inline PlaybackMode playback_mode() const { return playback_mode_; }
124 
set_quality(int32_t quality)125   inline void set_quality(int32_t quality) {
126     set_num_channels(quality & 1 ? 1 : 2);
127     set_low_fidelity(quality >> 1 ? true : false);
128   }
129 
set_num_channels(int32_t num_channels)130   inline void set_num_channels(int32_t num_channels) {
131     reset_buffers_ = reset_buffers_ || num_channels_ != num_channels;
132     num_channels_ = num_channels;
133   }
134 
set_low_fidelity(bool low_fidelity)135   inline void set_low_fidelity(bool low_fidelity) {
136     reset_buffers_ = reset_buffers_ || low_fidelity != low_fidelity_;
137     low_fidelity_ = low_fidelity;
138   }
139 
quality()140   inline int32_t quality() const {
141     int32_t quality = 0;
142     if (num_channels_ == 1) quality |= 1;
143     if (low_fidelity_) quality |= 2;
144     return quality;
145   }
146 
147   void GetPersistentData(PersistentBlock* block, size_t *num_blocks);
148   bool LoadPersistentData(const uint32_t* data);
149   void PreparePersistentData();
150 
151  private:
resolution()152   inline int32_t resolution() const {
153     return low_fidelity_ ? 8 : 16;
154   }
155 
sample_rate()156   inline float sample_rate() const {
157     return 32000.0f / \
158         (low_fidelity_ ? kDownsamplingFactor : 1);
159   }
160 
161   void ResetFilters();
162   void ProcessGranular(FloatFrame* input, FloatFrame* output, size_t size);
163 
164   PlaybackMode playback_mode_;
165   PlaybackMode previous_playback_mode_;
166   int32_t num_channels_;
167   bool low_fidelity_;
168 
169   bool silence_;
170   bool bypass_;
171   bool reset_buffers_;
172   float freeze_lp_;
173   float dry_wet_;
174 
175   void* buffer_[2];
176   size_t buffer_size_[2];
177 
178   Correlator correlator_;
179 
180   GranularSamplePlayer player_;
181   WSOLASamplePlayer ws_player_;
182   LoopingSamplePlayer looper_;
183   PhaseVocoder phase_vocoder_;
184 
185   Diffuser diffuser_;
186   Reverb reverb_;
187   PitchShifter pitch_shifter_;
188   stmlib::Svf fb_filter_[2];
189   stmlib::Svf hp_filter_[2];
190   stmlib::Svf lp_filter_[2];
191 
192   AudioBuffer<RESOLUTION_8_BIT_MU_LAW> buffer_8_[2];
193   AudioBuffer<RESOLUTION_16_BIT> buffer_16_[2];
194 
195   FloatFrame in_[kMaxBlockSize];
196   FloatFrame in_downsampled_[kMaxBlockSize / kDownsamplingFactor];
197   FloatFrame out_downsampled_[kMaxBlockSize / kDownsamplingFactor];
198   FloatFrame out_[kMaxBlockSize];
199   FloatFrame fb_[kMaxBlockSize];
200 
201   int16_t tail_buffer_[2][256];
202 
203   Parameters parameters_;
204 
205   SampleRateConverter<-kDownsamplingFactor, 45, src_filter_1x_2_45> src_down_;
206   SampleRateConverter<+kDownsamplingFactor, 45, src_filter_1x_2_45> src_up_;
207 
208   PersistentState persistent_state_;
209 
210   DISALLOW_COPY_AND_ASSIGN(GranularProcessor);
211 };
212 
213 }  // namespace clouds
214 
215 #endif  // CLOUDS_DSP_GRANULAR_PROCESSOR_H_
216