arduino-audio-tools
Loading...
Searching...
No Matches
LMSEchoCancellationStream.h
Go to the documentation of this file.
1#pragma once
2
5
6namespace audio_tools {
46template <typename T = int16_t>
48 public:
56 LMSEchoCancellationStream(Stream& in, size_t lag_samples = 0, size_t buffer_size = 512,
57 size_t filter_len = 32, float mu = 0.001f)
58 : lag(lag_samples),
61 adaptation_rate(mu) {
62 p_io = &in;
64 reset();
65 }
66
75 size_t write(const uint8_t* buf, size_t len) override {
76 const T* data = (const T*)buf;
77 size_t samples = len / sizeof(T);
78 for (size_t i = 0; i < samples; ++i) pushPlayback(data[i]);
79 return samples * sizeof(T);
80 }
81
89 size_t readBytes(uint8_t* buf, size_t len) override {
90 size_t read = p_io->readBytes(buf, len);
91 size_t actual_samples = read / sizeof(T);
92 T* data = (T*)buf;
93
94 for (size_t i = 0; i < actual_samples; ++i) {
95 data[i] = filterSample(data[i]);
96 }
97
98 return read;
99 }
100
105 void setLag(size_t lag_samples) { lag = lag_samples; }
106
111 void setMu(float mu) { adaptation_rate = mu; }
112
117 void setFilterLen(size_t len) {
118 filter_len = len;
119 filter.resize(filter_len, 0.0f);
120 ref_vec.resize(filter_len, 0);
121 }
122
126 void reset() {
129 for (size_t j = 0; j < lag; j++) {
131 }
132 filter.assign(filter_len, 0.0f);
133 ref_vec.resize(filter_len, 0);
134 }
135
146 void cancel(const T* rec, const T* play, T* out, size_t len) {
147 for (size_t i = 0; i < len; ++i) {
148 pushPlayback(play[i]);
149 out[i] = filterSample(rec[i]);
150 }
151 }
152
153 protected:
154 Stream* p_io = nullptr;
157 size_t lag; // lag in samples
158 // Adaptive filter
160 float adaptation_rate = 0.01f;
163
169 void pushPlayback(T sample) {
170 ring_buffer.write(sample);
171 T dummy;
172 while ((size_t)ring_buffer.available() > filter_len + lag) {
173 ring_buffer.read(dummy);
174 }
175 }
176
183 T filterSample(T mic_sample) {
184 if ((size_t)ring_buffer.available() < filter_len + lag) {
185 // Not enough playback history buffered yet: pass through unmodified.
186 return mic_sample;
187 }
188
190
191 float echo_est = 0.0f;
192 for (size_t k = 0; k < filter_len; ++k) {
193 echo_est += filter[k] * (float)ref_vec[k];
194 }
195
196 float mic = (float)mic_sample;
197 float error = mic - echo_est;
198
199 // LMS update
200 for (size_t k = 0; k < filter_len; ++k) {
201 filter[k] += adaptation_rate * error * (float)ref_vec[k];
202 }
203
204 return (T)error;
205 }
206};
207
208} // namespace audio_tools
void play(maxi_float_t *channels)
Definition Arduino.h:136
virtual size_t readBytes(uint8_t *data, size_t len)
Definition Arduino.h:140
Base class for all Audio Streams. It support the boolean operator to test if the object is ready with...
Definition BaseStream.h:120
Echo cancellation with adaptive LMS filtering for microcontrollers.
Definition LMSEchoCancellationStream.h:47
Vector< T > ref_vec
Definition LMSEchoCancellationStream.h:162
T filterSample(T mic_sample)
Estimate and subtract the echo for a single microphone sample, using the oldest filter_len samples cu...
Definition LMSEchoCancellationStream.h:183
size_t lag
Definition LMSEchoCancellationStream.h:157
void cancel(const T *rec, const T *play, T *out, size_t len)
Process echo cancellation on arrays of samples. Self-contained: feeds the playback reference and the ...
Definition LMSEchoCancellationStream.h:146
void pushPlayback(T sample)
Push a playback (speaker) sample into the delay line, evicting the oldest sample once the window exce...
Definition LMSEchoCancellationStream.h:169
void setFilterLen(size_t len)
Set the filter length for the adaptive filter.
Definition LMSEchoCancellationStream.h:117
void setLag(size_t lag_samples)
Set the lag (delay) in samples for echo cancellation.
Definition LMSEchoCancellationStream.h:105
size_t buffer_size
Definition LMSEchoCancellationStream.h:156
float adaptation_rate
Definition LMSEchoCancellationStream.h:160
RingBuffer< T > ring_buffer
Definition LMSEchoCancellationStream.h:155
size_t readBytes(uint8_t *buf, size_t len) override
Read input and remove echo, using the playback signal previously buffered via write() as the referenc...
Definition LMSEchoCancellationStream.h:89
LMSEchoCancellationStream(Stream &in, size_t lag_samples=0, size_t buffer_size=512, size_t filter_len=32, float mu=0.001f)
Constructor.
Definition LMSEchoCancellationStream.h:56
size_t filter_len
Definition LMSEchoCancellationStream.h:159
void reset()
Reset the internal buffer and lag state.
Definition LMSEchoCancellationStream.h:126
size_t write(const uint8_t *buf, size_t len) override
Store the output signal (sent to speaker). The samples are pushed into the internal delay line so tha...
Definition LMSEchoCancellationStream.h:75
void setMu(float mu)
Set the adaptation rate (mu) for the LMS algorithm.
Definition LMSEchoCancellationStream.h:111
Vector< float > filter
Definition LMSEchoCancellationStream.h:161
Stream * p_io
Definition LMSEchoCancellationStream.h:154
Implements a typed Ringbuffer.
Definition Buffers.h:353
virtual int peekArray(T *data, int n)
Definition Buffers.h:382
bool read(T &result) override
reads a single value
Definition Buffers.h:360
virtual bool write(T data) override
write add an entry to the buffer
Definition Buffers.h:403
virtual void reset() override
clears the buffer
Definition Buffers.h:415
virtual bool resize(size_t len)
Resizes the buffer if supported: returns false if not supported.
Definition Buffers.h:430
virtual int available() override
provides the number of entries that are available to read
Definition Buffers.h:422
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
void assign(iterator v1, iterator v2)
Definition Vector.h:222
bool resize(size_t newSize, T value)
Definition Vector.h:266
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition LMSEchoCancellationStream.h:6