1 // Copyright 2017 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 // Delay line, like the one in stmlib/dsp, but for int16_t, with 28 // built-in quantization and linear interpolation guard. 29 // Too specialized to be in a library... 30 31 #ifndef STAGES_DELAY_LINE_16_BITS_H_ 32 #define STAGES_DELAY_LINE_16_BITS_H_ 33 34 #include "stmlib/stmlib.h" 35 #include "stmlib/dsp/dsp.h" 36 37 #include <algorithm> 38 39 namespace stages { 40 41 template<size_t max_delay> 42 class DelayLine16Bits { 43 public: DelayLine16Bits()44 DelayLine16Bits() { } ~DelayLine16Bits()45 ~DelayLine16Bits() { } 46 Init()47 void Init() { 48 Reset(); 49 } 50 Reset()51 void Reset() { 52 std::fill(&line_[0], &line_[max_delay], 0); 53 write_ptr_ = 0; 54 } 55 Write(const float sample)56 inline void Write(const float sample) { 57 int32_t word = static_cast<int32_t>(sample * 32768.0f); 58 CONSTRAIN(word, -32768, 32767); 59 line_[write_ptr_] = word; 60 if (write_ptr_ == 0) { 61 line_[max_delay] = word; 62 write_ptr_ = max_delay - 1; 63 } else { 64 --write_ptr_; 65 } 66 } 67 Read(float delay)68 inline const float Read(float delay) const { 69 MAKE_INTEGRAL_FRACTIONAL(delay) 70 size_t read_ptr = (write_ptr_ + delay_integral) % max_delay; 71 float a = static_cast<float>(line_[read_ptr]) / 32768.0f; 72 float b = static_cast<float>(line_[read_ptr + 1]) / 32768.0f; 73 return a + (b - a) * delay_fractional; 74 } 75 76 private: 77 size_t write_ptr_; 78 int16_t line_[max_delay + 1]; 79 80 DISALLOW_COPY_AND_ASSIGN(DelayLine16Bits); 81 }; 82 83 } // namespace stages 84 85 #endif // STAGES_DELAY_LINE_16_BITS_H_ 86