1 /*
2 * Copyright (C) 2015-2020 Alibaba Group Holding Limited
3 *
4 */
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <stdint.h>
9 #include <string.h>
10 #include <stdarg.h>
11 #include <signal.h>
12
13 #include "uvoice_types.h"
14 #include "uvoice_os.h"
15
16 #include "uvoice_common.h"
17 #include "uvoice_audio.h"
18
19 #include "audio_common.h"
20 #include "audio_stream.h"
21 #include "audio_aec.h"
22
23
24 #define AEC_REFER_DELAY_MS 10
25
26
audio_aec_refer_conserve(struct aec_handler * aec,uint8_t * buffer,int nbytes)27 int audio_aec_refer_conserve(struct aec_handler *aec, uint8_t *buffer, int nbytes)
28 {
29 if (!aec) {
30 snd_err("aec handler null !\n");
31 return -1;
32 }
33
34 os_mutex_lock(aec->lock, OS_WAIT_FOREVER);
35
36 if (uvoice_ringbuff_freesize(&aec->rb) >= nbytes)
37 uvoice_ringbuff_fill(&aec->rb, buffer, nbytes);
38
39 os_mutex_unlock(aec->lock);
40
41 __exit:
42 return 0;
43 }
44
audio_aec_process(struct aec_handler * aec,uint8_t * buffer,int nbytes)45 int audio_aec_process(struct aec_handler *aec, uint8_t *buffer, int nbytes)
46 {
47 if (!aec) {
48 snd_err("aec handler null !\n");
49 return -1;
50 }
51
52 os_mutex_lock(aec->lock, OS_WAIT_FOREVER);
53 if (!aec->start)
54 goto __exit;
55
56 if (uvoice_ringbuff_dirtysize(&aec->rb) >= nbytes) {
57 uvoice_ringbuff_read(&aec->rb, aec->echo_buffer, nbytes);
58
59 if (echo_cancellation_process(aec, buffer, aec->echo_buffer, nbytes)) {
60 snd_err("aec process failed !\n");
61 os_mutex_unlock(aec->lock);
62 return -1;
63 }
64 }
65
66 __exit:
67 os_mutex_unlock(aec->lock);
68 return 0;
69 }
70
audio_aec_init(struct in_stream * in)71 int audio_aec_init(struct in_stream *in)
72 {
73 struct aec_handler *aec;
74 struct pcm_config *config;
75 int bits;
76
77 if (!in) {
78 snd_err("in stream null !\n");
79 return -1;
80 }
81
82 config = &in->pcm.config;
83 bits = pcm_format_to_bits(config->format);
84
85 aec = snd_zalloc(sizeof(struct aec_handler), AFM_EXTN);
86 if (!aec) {
87 snd_err("alloc echo cancellation struct failed !\n");
88 return -1;
89 }
90
91 aec->echo_buffer_size = period_samples_to_bytes(&in->pcm.config);
92 aec->echo_buffer = snd_zalloc(aec->echo_buffer_size, AFM_MAIN);
93 if (!aec->echo_buffer) {
94 snd_err("alloc echo buffer failed !\n");
95 snd_free(aec);
96 return -1;
97 }
98
99 aec->refer_pool_size = aec->echo_buffer_size;
100 aec->refer_pool = snd_zalloc(aec->refer_pool_size, AFM_EXTN);
101 if (!aec->refer_pool) {
102 snd_err("alloc refer pool failed !\n");
103 snd_free(aec->echo_buffer);
104 snd_free(aec);
105 return -1;
106 }
107
108 if (echo_cancellation_create(aec,
109 config->rate, bits, config->period_size)) {
110 snd_err("create aec failed !\n");
111 snd_free(aec->refer_pool);
112 snd_free(aec->echo_buffer);
113 snd_free(aec);
114 return -1;
115 }
116
117 uvoice_ringbuff_init(&aec->rb, aec->refer_pool, aec->refer_pool_size);
118 aec->lock = os_mutex_new();
119 aec->rd_sem = os_sem_new(0);
120 aec->wr_sem = os_sem_new(0);
121
122 in->aec = aec;
123 snd_debug("aec init\n");
124 return 0;
125 }
126
audio_aec_deinit(struct in_stream * in)127 int audio_aec_deinit(struct in_stream *in)
128 {
129 struct aec_handler *aec;
130
131 aec = in->aec;
132 if (!aec) {
133 snd_err("aec handler null !\n");
134 return -1;
135 }
136
137 echo_cancellation_release(aec);
138 os_sem_free(aec->wr_sem);
139 os_sem_free(aec->rd_sem);
140 os_mutex_free(aec->lock);
141 snd_free(aec->refer_pool);
142 snd_free(aec->echo_buffer);
143 snd_free(aec);
144 in->aec = NULL;
145
146 snd_debug("aec free\n");
147 return 0;
148 }
149
150