Mozzi  version v2.0
sound synthesis library for Arduino
AudioDelay.h
1 /*
2  * AudioDelay.h
3  *
4  * This file is part of Mozzi.
5  *
6  * Copyright 2012-2024 Tim Barrass and the Mozzi Team
7  *
8  * Mozzi is licensed under the GNU Lesser General Public Licence (LGPL) Version 2.1 or later.
9  *
10  */
11 
12 #ifndef AUDIODELAY_H_
13 #define AUDIODELAY_H_
14 
15 
16 /** Audio delay line for comb filter, flange, chorus and short echo effects.
17 @tparam NUM_BUFFER_SAMPLES is the length of the delay buffer in samples. This should
18 be a power of two. The largest delay you'll fit in an atmega328 will be 512
19 cells, which at 16384 Hz sample rate is 31 milliseconds. More of a flanger or a
20 doubler than an echo. The amount of memory available for delays on other chips will vary.
21 AudioDelay() doesn't have feedback. If you want feedback, use AudioDelayFeedback().
22 @tparam the type of numbers to use for the signal in the delay. The default is int8_t, but int could be useful
23 when adding manual feedback. When using int, the input should be limited to 15 bits width, ie. -16384 to 16383.
24 */
25 
26 template <unsigned int NUM_BUFFER_SAMPLES, class T = int8_t>
28 {
29 
30 private:
31 
32  T delay_array[NUM_BUFFER_SAMPLES];
33  unsigned int _write_pos;
34  unsigned int _delaytime_cells;
35 
36 public:
37 
38  /** Constructor.
39  */
40  AudioDelay(): _write_pos(0)
41  {}
42 
43 
44  /** Constructor.
45  @param delaytime_cells delay time expressed in cells.
46  For example, 128 cells delay at MOZZI_AUDIO_RATE would produce a time delay of 128/16384 = 0.0078125 s = 7.8 ms
47  Put another way, num_cells = delay_seconds * MOZZI_AUDIO_RATE.
48  */
49  AudioDelay(unsigned int delaytime_cells): _write_pos(0), _delaytime_cells(delaytime_cells)
50  {}
51 
52 
53 
54  /** Input a value to the delay and retrieve the signal in the delay line at the position delaytime_cells.
55  @param in_value the signal input.
56  @param delaytime_cells sets the delay time in terms of cells in the delay buffer.
57  */
58  inline
59  T next(T in_value, unsigned int delaytime_cells)
60  {
61  ++_write_pos &= (NUM_BUFFER_SAMPLES - 1);
62  unsigned int read_pos = (_write_pos - delaytime_cells) & (NUM_BUFFER_SAMPLES - 1);
63 
64  // why does delay jump if I read it before writing?
65  delay_array[_write_pos] = in_value; // write to buffer
66  int8_t delay_sig = delay_array[read_pos] ; // read the delay buffer
67 
68  return (T)delay_sig;
69  }
70 
71 
72 
73  /** Input a value to the delay and retrieve the signal in the delay line at the position delaytime_cells.
74  @param in_value the signal input.
75  */
76  inline
77  T next(T in_value)
78  {
79  ++_write_pos &= (NUM_BUFFER_SAMPLES - 1);
80  unsigned int read_pos = (_write_pos - _delaytime_cells) & (NUM_BUFFER_SAMPLES - 1);
81 
82  // why does delay jump if I read it before writing?
83  delay_array[_write_pos] = in_value; // write to buffer
84  T delay_sig = delay_array[read_pos] ; // read the delay buffer
85 
86  return delay_sig;
87  }
88 
89 
90  /** Set the delay time, measured in cells.
91  @param delaytime_cells how many cells to delay the input signal by.
92  */
93  inline
94  void set(unsigned int delaytime_cells){
95  _delaytime_cells = delaytime_cells;
96  }
97 
98 
99  /** Retrieve the signal in the delay line at the position delaytime_cells.
100  It doesn't change the stored internal value of _delaytime_cells.
101  @param delaytime_cells indicates the delay time in terms of cells in the delay buffer.
102  */
103  inline
104  T read(unsigned int delaytime_cells)
105  {
106  unsigned int read_pos = (_write_pos - delaytime_cells) & (NUM_BUFFER_SAMPLES - 1);
107  return delay_array[read_pos];
108  }
109 
110 
111  // /** Input a value to the delay but don't advance the write position, change the delay time or retrieve the output signal.
112  // This can be useful for manually adding feedback to the delay line, "behind" the advancing write head.
113  // @param input the signal input.
114  // */
115  // inline
116  // void writeFeedback(T input)
117  // {
118  // delay_array[_write_pos] = input;
119  // }
120 
121 };
122 
123 /**
124 @example 09.Delays/AudioDelay/AudioDelay.ino
125 This is an example of how to use the AudioDelay class.
126 */
127 
128 #endif // #ifndef AUDIODELAY_H_