-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathdelayline_2tap.h
150 lines (130 loc) · 5.09 KB
/
delayline_2tap.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#pragma once
#ifndef DELAYLINE_2TAP_H
#define DELAYLINE_2TAP_H
#include <stdlib.h>
#include <stdint.h>
template <typename T, size_t max_size>
class DelayLine2Tap
{
public:
DelayLine2Tap() {}
~DelayLine2Tap() {}
/** initializes the delay line by clearing the values within, and setting delay to 1 sample.
*/
void Init() { Reset(); }
/** clears buffer, sets write ptr to 0, and delay to 1 sample.
*/
void Reset()
{
for(size_t i = 0; i < max_size; i++)
{
line_[i] = T(0);
}
write_ptr_ = 0;
delay_ = 1;
delay_secondTap = 1;
delay_float = 1.0;
secondTapFraction = 0.0;
}
// Sets the fractional length of the 2nd tap
// 2/3 (0.66667) = Triplett
// 3/4 (0.75) = Dotted Eighth
inline void set2ndTapFraction(float tapFraction)
{
secondTapFraction = tapFraction;
// For secondTap (if this changes we want to recalculate the second tap based on current delay setting)
int32_t int_delay_secondTap = static_cast<int32_t>(delay_float * secondTapFraction);
frac_secondTap = delay_float * secondTapFraction - static_cast<float>(int_delay_secondTap);
delay_secondTap = static_cast<size_t>(int_delay_secondTap) < max_size ? int_delay_secondTap
: max_size - 1;
}
/** sets the delay time in samples
If a float is passed in, a fractional component will be calculated for interpolating the delay line.
*/
inline void SetDelay(size_t delay)
{
frac_ = 0.0f;
delay_ = delay < max_size ? delay : max_size - 1;
}
/** sets the delay time in samples
If a float is passed in, a fractional component will be calculated for interpolating the delay line.
*/
inline void SetDelay(float delay)
{
int32_t int_delay = static_cast<int32_t>(delay);
frac_ = delay - static_cast<float>(int_delay);
delay_ = static_cast<size_t>(int_delay) < max_size ? int_delay
: max_size - 1;
// For secondTap
delay_float = delay;
int32_t int_delay_secondTap = static_cast<int32_t>(delay_float * secondTapFraction);
frac_secondTap = delay_float * secondTapFraction - static_cast<float>(int_delay_secondTap);
delay_secondTap = static_cast<size_t>(int_delay_secondTap) < max_size ? int_delay_secondTap
: max_size - 1;
}
/** writes the sample of type T to the delay line, and advances the write ptr
*/
inline void Write(const T sample)
{
line_[write_ptr_] = sample;
write_ptr_ = (write_ptr_ - 1 + max_size) % max_size;
}
/** returns the next sample of type T in the delay line, interpolated if necessary.
*/
inline const T Read() const
{
T a = line_[(write_ptr_ + delay_) % max_size];
T b = line_[(write_ptr_ + delay_ + 1) % max_size];
return a + (b - a) * frac_;
}
inline const T ReadSecondTap() const
{
T c = line_[(write_ptr_ + delay_ + delay_secondTap) % max_size];
T d = line_[(write_ptr_ + delay_ + delay_secondTap + 1) % max_size];
return c + (d - c) * frac_secondTap;
}
/** Read from a set location */
inline const T Read(float delay) const
{
int32_t delay_integral = static_cast<int32_t>(delay);
float delay_fractional = delay - static_cast<float>(delay_integral);
const T a = line_[(write_ptr_ + delay_integral) % max_size];
const T b = line_[(write_ptr_ + delay_integral + 1) % max_size];
return a + (b - a) * delay_fractional;
}
inline const T ReadHermite(float delay) const
{
int32_t delay_integral = static_cast<int32_t>(delay);
float delay_fractional = delay - static_cast<float>(delay_integral);
int32_t t = (write_ptr_ + delay_integral + max_size);
const T xm1 = line_[(t - 1) % max_size];
const T x0 = line_[(t) % max_size];
const T x1 = line_[(t + 1) % max_size];
const T x2 = line_[(t + 2) % max_size];
const float c = (x1 - xm1) * 0.5f;
const float v = x0 - x1;
const float w = c + v;
const float a = w + v + (x2 - x0) * 0.5f;
const float b_neg = w + a;
const float f = delay_fractional;
return (((a * f) - b_neg) * f + c) * f + x0;
}
inline const T Allpass(const T sample, size_t delay, const T coefficient)
{
T read = line_[(write_ptr_ + delay) % max_size];
T write = sample + coefficient * read;
Write(write);
return -write * coefficient + read;
}
private:
float frac_;
size_t write_ptr_;
size_t delay_;
T line_[max_size];
float frac_secondTap;
size_t delay_secondTap;
float delay_float; // Saves the last delay float setting for recalculating the second tap if needed
float secondTapFraction;
};
//} // namespace daisysp
#endif