-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathaec.c
More file actions
70 lines (55 loc) · 1.7 KB
/
aec.c
File metadata and controls
70 lines (55 loc) · 1.7 KB
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
#include "aec.h"
#include <stdlib.h>
#define INT16_TO_FLOAT(x) ((x) / 32768.0f)
#define FLOAT_TO_INT16(x) ((int16_t)((x) * 32768.0f))
aec_t* aec_init(int filter_len, float mu) {
aec_t *aec = (aec_t*)malloc(sizeof(aec_t));
if (!aec) return NULL;
aec->filter_len = filter_len;
aec->mu = mu;
aec->pos = 0;
aec->w = (float*)calloc(filter_len, sizeof(float));
aec->x = (float*)calloc(filter_len, sizeof(float));
if (!aec->w || !aec->x) {
free(aec->w);
free(aec->x);
free(aec);
return NULL;
}
return aec;
}
int16_t aec_process(aec_t *aec, int16_t ref, int16_t mic) {
float ref_f = INT16_TO_FLOAT(ref);
float mic_f = INT16_TO_FLOAT(mic);
// Update reference signal buffer
aec->x[aec->pos] = ref_f;
// Estimate echo signal
float y = 0.0f;
for (int i = 0; i < aec->filter_len; i++) {
int idx = (aec->pos - i + aec->filter_len) % aec->filter_len;
y += aec->w[i] * aec->x[idx];
}
// Calculate error signal
float e = mic_f - y;
// Calculate reference signal power
float power = 1e-6f;
for (int i = 0; i < aec->filter_len; i++) {
power += aec->x[i] * aec->x[i];
}
// Update filter coefficients (NLMS algorithm)
float step = aec->mu / power;
for (int i = 0; i < aec->filter_len; i++) {
int idx = (aec->pos - i + aec->filter_len) % aec->filter_len;
aec->w[i] += step * e * aec->x[idx];
}
// Update position
aec->pos = (aec->pos + 1) % aec->filter_len;
return FLOAT_TO_INT16(e);
}
void aec_destroy(aec_t *aec) {
if (aec) {
free(aec->w);
free(aec->x);
free(aec);
}
}