arduino-audio-tools
Loading...
Searching...
No Matches
LMSEchoCancellationStream.h
1#pragma once
2
3#include "AudioTools/CoreAudio/AudioStreams.h"
4#include "AudioTools/CoreAudio/Buffers.h"
5
6namespace audio_tools {
15template <typename T = int16_t>
17 public:
25 LMSEchoCancellationStream(Stream& in, size_t lag_samples = 0, size_t buffer_size = 512,
26 size_t filter_len = 32, float mu = 0.001f)
27 : lag(lag_samples),
28 buffer_size(buffer_size),
29 filter_len(filter_len),
30 adaptation_rate(mu) {
31 p_io = &in;
32 filter.resize(filter_len, 0.0f);
33 reset();
34 }
35
42 size_t write(const uint8_t* buf, size_t len) override {
43 // Store output signal in queue for echo estimation
44 return ring_buffer.writeArray((T*)buf, len / sizeof(T)) *
45 sizeof(T);
46 }
47
54 size_t readBytes(uint8_t* buf, size_t len) override {
55 size_t read = p_io->readBytes(buf, len);
56 size_t actual_samples = read / sizeof(T);
57 T* data = (T*)buf;
58
59 // Create a temporary buffer for playback samples (zeros since we don't have them here)
60 Vector<T> play_buf(actual_samples, 0);
61
62 // Use cancel() to process the samples
63 cancel(data, play_buf.data(), data, actual_samples);
64
65 return read;
66 }
67
72 void setLag(size_t lag_samples) { lag = lag_samples; }
73
78 void setMu(float mu) { adaptation_rate = mu; }
79
84 void setFilterLen(size_t len) {
85 filter_len = len;
86 filter.resize(filter_len, 0.0f);
87 }
88
92 void reset() {
93 ring_buffer.resize(buffer_size + lag);
94 for (size_t j = 0; j < lag; j++) {
95 ring_buffer.write(0);
96 }
97 filter.assign(filter_len, 0.0f);
98 }
99
107 void cancel(const T* rec, const T* play, T* out, size_t len) {
108 for (size_t i = 0; i < len; ++i) {
109 // Store playback signal in ring buffer for echo estimation
110 ring_buffer.write(play[i]);
111
112 // Build the reference vector for the adaptive filter
113 Vector<T> ref_vec(filter_len, 0);
114 ring_buffer.peekArray(ref_vec.data(), filter_len);
115
116 float echo_est = 0.0f;
117 for (size_t k = 0; k < filter_len; ++k) {
118 echo_est += filter[k] * (float)ref_vec[k];
119 }
120
121 float mic = (float)rec[i];
122 float error = mic - echo_est;
123 out[i] = (T)error;
124
125 // LMS update
126 for (size_t k = 0; k < filter_len; ++k) {
127 filter[k] += adaptation_rate * error * (float)ref_vec[k];
128 }
129 }
130 }
131
132 protected:
133 Stream* p_io = nullptr;
134 RingBuffer<T> ring_buffer{0};
135 size_t buffer_size;
136 size_t lag; // lag in samples
137 // Adaptive filter
138 size_t filter_len;
139 float adaptation_rate = 0.01f;
140 Vector<float> filter;
141};
142
143} // namespace audio_tools
Base class for all Audio Streams. It support the boolean operator to test if the object is ready with...
Definition BaseStream.h:122
virtual int writeArray(const T data[], int len)
Fills the buffer data.
Definition Buffers.h:55
Definition LMSEchoCancellationStream.h:16
void cancel(const T *rec, const T *play, T *out, size_t len)
Process echo cancellation on arrays of samples.
Definition LMSEchoCancellationStream.h:107
void setFilterLen(size_t len)
Set the filter length for the adaptive filter.
Definition LMSEchoCancellationStream.h:84
void setLag(size_t lag_samples)
Set the lag (delay) in samples for echo cancellation.
Definition LMSEchoCancellationStream.h:72
size_t readBytes(uint8_t *buf, size_t len) override
Read input and remove echo (subtract output signal with lag)
Definition LMSEchoCancellationStream.h:54
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:25
void reset()
Reset the internal buffer and lag state.
Definition LMSEchoCancellationStream.h:92
size_t write(const uint8_t *buf, size_t len) override
Store the output signal (sent to speaker)
Definition LMSEchoCancellationStream.h:42
void setMu(float mu)
Set the adaptation rate (mu) for the LMS algorithm.
Definition LMSEchoCancellationStream.h:78
Implements a typed Ringbuffer.
Definition Buffers.h:341
virtual bool write(T data) override
write add an entry to the buffer
Definition Buffers.h:391
virtual bool resize(int len)
Resizes the buffer if supported: returns false if not supported.
Definition Buffers.h:418
Definition NoArduino.h:142
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10