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 ¶meters_; 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