1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 // clang-format off
18 /*
19  * Typical AEC signal flow:
20  *
21  *                          Microphone Audio
22  *                          Timestamps
23  *                        +--------------------------------------+
24  *                        |                                      |       +---------------+
25  *                        |    Microphone +---------------+      |       |               |
26  *             O|======   |    Audio      | Sample Rate   |      +------->               |
27  *    (from         .  +--+    Samples    | +             |              |               |
28  *     mic          .  +==================> Format        |==============>               |
29  *     codec)       .                     | Conversion    |              |               |   Cleaned
30  *             O|======                   | (if required) |              |   Acoustic    |   Audio
31  *                                        +---------------+              |   Echo        |   Samples
32  *                                                                       |   Canceller   |===================>
33  *                                                                       |   (AEC)       |
34  *                            Reference   +---------------+              |               |
35  *                            Audio       | Sample Rate   |              |               |
36  *                            Samples     | +             |              |               |
37  *                          +=============> Format        |==============>               |
38  *                          |             | Conversion    |              |               |
39  *                          |             | (if required) |      +------->               |
40  *                          |             +---------------+      |       |               |
41  *                          |                                    |       +---------------+
42  *                          |    +-------------------------------+
43  *                          |    |  Reference Audio
44  *                          |    |  Timestamps
45  *                          |    |
46  *                       +--+----+---------+                                                       AUDIO CAPTURE
47  *                       | Speaker         |
48  *          +------------+ Audio/Timestamp +---------------------------------------------------------------------------+
49  *                       | Buffer          |
50  *                       +--^----^---------+                                                       AUDIO PLAYBACK
51  *                          |    |
52  *                          |    |
53  *                          |    |
54  *                          |    |
55  *                |\        |    |
56  *                | +-+     |    |
57  *      (to       | | +-----C----+
58  *       speaker  | | |     |                                                                  Playback
59  *       codec)   | | <=====+================================================================+ Audio
60  *                | +-+                                                                        Samples
61  *                |/
62  *
63  */
64 // clang-format on
65 
66 #define LOG_TAG "audio_hw_aec"
67 // #define LOG_NDEBUG 0
68 
69 #include <audio_utils/primitives.h>
70 #include <stdio.h>
71 #include <inttypes.h>
72 #include <errno.h>
73 #include <malloc.h>
74 #include <sys/time.h>
75 #include <tinyalsa/asoundlib.h>
76 #include <unistd.h>
77 #include <log/log.h>
78 #include "audio_aec.h"
79 
80 #ifdef AEC_HAL
81 #include "audio_aec_process.h"
82 #else
83 #define aec_spk_mic_init(...) ((int)0)
84 #define aec_spk_mic_reset(...) ((void)0)
85 #define aec_spk_mic_process(...) ((int32_t)0)
86 #define aec_spk_mic_release(...) ((void)0)
87 #endif
88 
89 #define MAX_TIMESTAMP_DIFF_USEC 200000
90 
91 #define MAX_READ_WAIT_TIME_MSEC 80
92 
timespec_to_usec(struct timespec ts)93 uint64_t timespec_to_usec(struct timespec ts) {
94     return (ts.tv_sec * 1e6L + ts.tv_nsec/1000);
95 }
96 
get_reference_audio_in_place(struct aec_t * aec,size_t frames)97 void get_reference_audio_in_place(struct aec_t *aec, size_t frames) {
98     if (aec->num_reference_channels == aec->spk_num_channels) {
99         /* Reference count equals speaker channels, nothing to do here. */
100         return;
101     } else if (aec->num_reference_channels != 1) {
102         /* We don't have  a rule for non-mono references, show error on log */
103         ALOGE("Invalid reference count - must be 1 or match number of playback channels!");
104         return;
105     }
106     int16_t *src_Nch = &aec->spk_buf_playback_format[0];
107     int16_t *dst_1ch = &aec->spk_buf_playback_format[0];
108     int32_t num_channels = (int32_t)aec->spk_num_channels;
109     size_t frame, ch;
110     for (frame = 0; frame < frames; frame++) {
111         int32_t acc = 0;
112         for (ch = 0; ch < aec->spk_num_channels; ch++) {
113             acc += src_Nch[ch];
114         }
115         *dst_1ch++ = clamp16(acc/num_channels);
116         src_Nch += aec->spk_num_channels;
117     }
118 }
119 
print_queue_status_to_log(struct aec_t * aec,bool write_side)120 void print_queue_status_to_log(struct aec_t *aec, bool write_side) {
121     ssize_t q1 = fifo_available_to_read(aec->spk_fifo);
122     ssize_t q2 = fifo_available_to_read(aec->ts_fifo);
123 
124     ALOGV("Queue available %s: Spk %zd (count %zd) TS %zd (count %zd)",
125         (write_side) ? "(POST-WRITE)" : "(PRE-READ)",
126         q1, q1/aec->spk_frame_size_bytes/PLAYBACK_PERIOD_SIZE,
127         q2, q2/sizeof(struct aec_info));
128 }
129 
flush_aec_fifos(struct aec_t * aec)130 void flush_aec_fifos(struct aec_t *aec) {
131     if (aec == NULL) {
132         return;
133     }
134     if (aec->spk_fifo != NULL) {
135         ALOGV("Flushing AEC Spk FIFO...");
136         fifo_flush(aec->spk_fifo);
137     }
138     if (aec->ts_fifo != NULL) {
139         ALOGV("Flushing AEC Timestamp FIFO...");
140         fifo_flush(aec->ts_fifo);
141     }
142     /* Reset FIFO read-write offset tracker */
143     aec->read_write_diff_bytes = 0;
144 }
145 
aec_set_spk_running_no_lock(struct aec_t * aec,bool state)146 void aec_set_spk_running_no_lock(struct aec_t* aec, bool state) {
147     aec->spk_running = state;
148 }
149 
aec_get_spk_running_no_lock(struct aec_t * aec)150 bool aec_get_spk_running_no_lock(struct aec_t* aec) {
151     return aec->spk_running;
152 }
153 
destroy_aec_reference_config_no_lock(struct aec_t * aec)154 void destroy_aec_reference_config_no_lock(struct aec_t* aec) {
155     if (!aec->spk_initialized) {
156         return;
157     }
158     aec_set_spk_running_no_lock(aec, false);
159     fifo_release(aec->spk_fifo);
160     fifo_release(aec->ts_fifo);
161     memset(&aec->last_spk_info, 0, sizeof(struct aec_info));
162     aec->spk_initialized = false;
163 }
164 
destroy_aec_mic_config_no_lock(struct aec_t * aec)165 void destroy_aec_mic_config_no_lock(struct aec_t* aec) {
166     if (!aec->mic_initialized) {
167         return;
168     }
169     release_resampler(aec->spk_resampler);
170     free(aec->mic_buf);
171     free(aec->spk_buf);
172     free(aec->spk_buf_playback_format);
173     free(aec->spk_buf_resampler_out);
174     memset(&aec->last_mic_info, 0, sizeof(struct aec_info));
175     aec->mic_initialized = false;
176 }
177 
init_aec_interface()178 struct aec_t *init_aec_interface() {
179     ALOGV("%s enter", __func__);
180     struct aec_t *aec = (struct aec_t *)calloc(1, sizeof(struct aec_t));
181     if (aec == NULL) {
182         ALOGE("Failed to allocate memory for AEC interface!");
183     } else {
184         pthread_mutex_init(&aec->lock, NULL);
185     }
186 
187     ALOGV("%s exit", __func__);
188     return aec;
189 }
190 
release_aec_interface(struct aec_t * aec)191 void release_aec_interface(struct aec_t *aec) {
192     ALOGV("%s enter", __func__);
193     pthread_mutex_lock(&aec->lock);
194     destroy_aec_mic_config_no_lock(aec);
195     destroy_aec_reference_config_no_lock(aec);
196     pthread_mutex_unlock(&aec->lock);
197     free(aec);
198     ALOGV("%s exit", __func__);
199 }
200 
init_aec(int sampling_rate,int num_reference_channels,int num_microphone_channels,struct aec_t ** aec_ptr)201 int init_aec(int sampling_rate, int num_reference_channels,
202                 int num_microphone_channels, struct aec_t **aec_ptr) {
203     ALOGV("%s enter", __func__);
204     int ret = 0;
205     int aec_ret = aec_spk_mic_init(
206                     sampling_rate,
207                     num_reference_channels,
208                     num_microphone_channels);
209     if (aec_ret) {
210         ALOGE("AEC object failed to initialize!");
211         ret = -EINVAL;
212     }
213     struct aec_t *aec = init_aec_interface();
214     if (!ret) {
215         aec->num_reference_channels = num_reference_channels;
216         /* Set defaults, will be overridden by settings in init_aec_(mic|referece_config) */
217         /* Capture uses 2-ch, 32-bit frames */
218         aec->mic_sampling_rate = CAPTURE_CODEC_SAMPLING_RATE;
219         aec->mic_frame_size_bytes = CHANNEL_STEREO * sizeof(int32_t);
220         aec->mic_num_channels = CHANNEL_STEREO;
221 
222         /* Playback uses 2-ch, 16-bit frames */
223         aec->spk_sampling_rate = PLAYBACK_CODEC_SAMPLING_RATE;
224         aec->spk_frame_size_bytes = CHANNEL_STEREO * sizeof(int16_t);
225         aec->spk_num_channels = CHANNEL_STEREO;
226     }
227 
228     (*aec_ptr) = aec;
229     ALOGV("%s exit", __func__);
230     return ret;
231 }
232 
release_aec(struct aec_t * aec)233 void release_aec(struct aec_t *aec) {
234     ALOGV("%s enter", __func__);
235     if (aec == NULL) {
236         return;
237     }
238     release_aec_interface(aec);
239     aec_spk_mic_release();
240     ALOGV("%s exit", __func__);
241 }
242 
init_aec_reference_config(struct aec_t * aec,struct alsa_stream_out * out)243 int init_aec_reference_config(struct aec_t *aec, struct alsa_stream_out *out) {
244     ALOGV("%s enter", __func__);
245     if (!aec) {
246         ALOGE("AEC: No valid interface found!");
247         return -EINVAL;
248     }
249 
250     int ret = 0;
251     pthread_mutex_lock(&aec->lock);
252     if (aec->spk_initialized) {
253         destroy_aec_reference_config_no_lock(aec);
254     }
255 
256     aec->spk_fifo = fifo_init(
257             out->config.period_count * out->config.period_size *
258                 audio_stream_out_frame_size(&out->stream),
259             false /* reader_throttles_writer */);
260     if (aec->spk_fifo == NULL) {
261         ALOGE("AEC: Speaker loopback FIFO Init failed!");
262         ret = -EINVAL;
263         goto exit;
264     }
265     aec->ts_fifo = fifo_init(
266             out->config.period_count * sizeof(struct aec_info),
267             false /* reader_throttles_writer */);
268     if (aec->ts_fifo == NULL) {
269         ALOGE("AEC: Speaker timestamp FIFO Init failed!");
270         ret = -EINVAL;
271         fifo_release(aec->spk_fifo);
272         goto exit;
273     }
274 
275     aec->spk_sampling_rate = out->config.rate;
276     aec->spk_frame_size_bytes = audio_stream_out_frame_size(&out->stream);
277     aec->spk_num_channels = out->config.channels;
278     aec->spk_initialized = true;
279 exit:
280     pthread_mutex_unlock(&aec->lock);
281     ALOGV("%s exit", __func__);
282     return ret;
283 }
284 
destroy_aec_reference_config(struct aec_t * aec)285 void destroy_aec_reference_config(struct aec_t* aec) {
286     ALOGV("%s enter", __func__);
287     if (aec == NULL) {
288         ALOGV("%s exit", __func__);
289         return;
290     }
291     pthread_mutex_lock(&aec->lock);
292     destroy_aec_reference_config_no_lock(aec);
293     pthread_mutex_unlock(&aec->lock);
294     ALOGV("%s exit", __func__);
295 }
296 
write_to_reference_fifo(struct aec_t * aec,void * buffer,struct aec_info * info)297 int write_to_reference_fifo(struct aec_t* aec, void* buffer, struct aec_info* info) {
298     ALOGV("%s enter", __func__);
299     int ret = 0;
300     size_t bytes = info->bytes;
301 
302     /* Write audio samples to FIFO */
303     ssize_t written_bytes = fifo_write(aec->spk_fifo, buffer, bytes);
304     if (written_bytes != bytes) {
305         ALOGE("Could only write %zu of %zu bytes", written_bytes, bytes);
306         ret = -ENOMEM;
307     }
308 
309     /* Write timestamp to FIFO */
310     info->bytes = written_bytes;
311     ALOGV("Speaker timestamp: %ld s, %ld nsec", info->timestamp.tv_sec, info->timestamp.tv_nsec);
312     ssize_t ts_bytes = fifo_write(aec->ts_fifo, info, sizeof(struct aec_info));
313     ALOGV("Wrote TS bytes: %zu", ts_bytes);
314     print_queue_status_to_log(aec, true);
315     ALOGV("%s exit", __func__);
316     return ret;
317 }
318 
get_spk_timestamp(struct aec_t * aec,ssize_t read_bytes,uint64_t * spk_time)319 void get_spk_timestamp(struct aec_t* aec, ssize_t read_bytes, uint64_t* spk_time) {
320     *spk_time = 0;
321     uint64_t spk_time_offset = 0;
322     float usec_per_byte = 1E6 / ((float)(aec->spk_frame_size_bytes * aec->spk_sampling_rate));
323     if (aec->read_write_diff_bytes < 0) {
324         /* We're still reading a previous write packet. (We only need the first sample's timestamp,
325          * so even if we straddle packets we only care about the first one)
326          * So we just use the previous timestamp, with an appropriate offset
327          * based on the number of bytes remaining to be read from that write packet. */
328         spk_time_offset = (aec->last_spk_info.bytes + aec->read_write_diff_bytes) * usec_per_byte;
329         ALOGV("Reusing previous timestamp, calculated offset (usec) %" PRIu64, spk_time_offset);
330     } else {
331         /* If read_write_diff_bytes > 0, there are no new writes, so there won't be timestamps in
332          * the FIFO, and the check below will fail. */
333         if (!fifo_available_to_read(aec->ts_fifo)) {
334             ALOGE("Timestamp error: no new timestamps!");
335             return;
336         }
337         /* We just read valid data, so if we're here, we should have a valid timestamp to use. */
338         ssize_t ts_bytes = fifo_read(aec->ts_fifo, &aec->last_spk_info, sizeof(struct aec_info));
339         ALOGV("Read TS bytes: %zd, expected %zu", ts_bytes, sizeof(struct aec_info));
340         aec->read_write_diff_bytes -= aec->last_spk_info.bytes;
341     }
342 
343     *spk_time = timespec_to_usec(aec->last_spk_info.timestamp) + spk_time_offset;
344 
345     aec->read_write_diff_bytes += read_bytes;
346     struct aec_info spk_info = aec->last_spk_info;
347     while (aec->read_write_diff_bytes > 0) {
348         /* If read_write_diff_bytes > 0, it means that there are more write packet timestamps
349          * in FIFO (since there we read more valid data the size of the current timestamp's
350          * packet). Keep reading timestamps from FIFO to get to the most recent one. */
351         if (!fifo_available_to_read(aec->ts_fifo)) {
352             /* There are no more timestamps, we have the most recent one. */
353             ALOGV("At the end of timestamp FIFO, breaking...");
354             break;
355         }
356         fifo_read(aec->ts_fifo, &spk_info, sizeof(struct aec_info));
357         ALOGV("Fast-forwarded timestamp by %zd bytes, remaining bytes: %zd,"
358               " new timestamp (usec) %" PRIu64,
359               spk_info.bytes, aec->read_write_diff_bytes, timespec_to_usec(spk_info.timestamp));
360         aec->read_write_diff_bytes -= spk_info.bytes;
361     }
362     aec->last_spk_info = spk_info;
363 }
364 
get_reference_samples(struct aec_t * aec,void * buffer,struct aec_info * info)365 int get_reference_samples(struct aec_t* aec, void* buffer, struct aec_info* info) {
366     ALOGV("%s enter", __func__);
367 
368     if (!aec->spk_initialized) {
369         ALOGE("%s called with no reference initialized", __func__);
370         return -EINVAL;
371     }
372 
373     size_t bytes = info->bytes;
374     const size_t frames = bytes / aec->mic_frame_size_bytes;
375     const size_t sample_rate_ratio = aec->spk_sampling_rate / aec->mic_sampling_rate;
376 
377     /* Read audio samples from FIFO */
378     const size_t req_bytes = frames * sample_rate_ratio * aec->spk_frame_size_bytes;
379     ssize_t available_bytes = 0;
380     unsigned int wait_count = MAX_READ_WAIT_TIME_MSEC;
381     while (true) {
382         available_bytes = fifo_available_to_read(aec->spk_fifo);
383         if (available_bytes >= req_bytes) {
384             break;
385         } else if (available_bytes < 0) {
386             ALOGE("fifo_read returned code %zu ", available_bytes);
387             return -ENOMEM;
388         }
389 
390         ALOGV("Sleeping, required bytes: %zu, available bytes: %zd", req_bytes, available_bytes);
391         usleep(1000);
392         if ((wait_count--) == 0) {
393             ALOGE("Timed out waiting for read from reference FIFO");
394             return -ETIMEDOUT;
395         }
396     }
397 
398     const size_t read_bytes = fifo_read(aec->spk_fifo, aec->spk_buf_playback_format, req_bytes);
399 
400     /* Get timestamp*/
401     get_spk_timestamp(aec, read_bytes, &info->timestamp_usec);
402 
403     /* Get reference - could be mono, downmixed from multichannel.
404      * Reference stored at spk_buf_playback_format */
405     const size_t resampler_in_frames = frames * sample_rate_ratio;
406     get_reference_audio_in_place(aec, resampler_in_frames);
407 
408     int16_t* resampler_out_buf;
409     /* Resample to mic sampling rate (16-bit resampler) */
410     if (aec->spk_resampler != NULL) {
411         size_t in_frame_count = resampler_in_frames;
412         size_t out_frame_count = frames;
413         aec->spk_resampler->resample_from_input(aec->spk_resampler, aec->spk_buf_playback_format,
414                                                 &in_frame_count, aec->spk_buf_resampler_out,
415                                                 &out_frame_count);
416         resampler_out_buf = aec->spk_buf_resampler_out;
417     } else {
418         if (sample_rate_ratio != 1) {
419             ALOGE("Speaker sample rate %d, mic sample rate %d but no resampler defined!",
420                   aec->spk_sampling_rate, aec->mic_sampling_rate);
421         }
422         resampler_out_buf = aec->spk_buf_playback_format;
423     }
424 
425     /* Convert to 32 bit */
426     int16_t* src16 = resampler_out_buf;
427     int32_t* dst32 = buffer;
428     size_t frame, ch;
429     for (frame = 0; frame < frames; frame++) {
430         for (ch = 0; ch < aec->num_reference_channels; ch++) {
431             *dst32++ = ((int32_t)*src16++) << 16;
432         }
433     }
434 
435     info->bytes = bytes;
436 
437     ALOGV("%s exit", __func__);
438     return 0;
439 }
440 
init_aec_mic_config(struct aec_t * aec,struct alsa_stream_in * in)441 int init_aec_mic_config(struct aec_t *aec, struct alsa_stream_in *in) {
442     ALOGV("%s enter", __func__);
443 #if DEBUG_AEC
444     remove("/data/local/traces/aec_in.pcm");
445     remove("/data/local/traces/aec_out.pcm");
446     remove("/data/local/traces/aec_ref.pcm");
447     remove("/data/local/traces/aec_timestamps.txt");
448 #endif /* #if DEBUG_AEC */
449 
450     if (!aec) {
451         ALOGE("AEC: No valid interface found!");
452         return -EINVAL;
453     }
454 
455     int ret = 0;
456     pthread_mutex_lock(&aec->lock);
457     if (aec->mic_initialized) {
458         destroy_aec_mic_config_no_lock(aec);
459     }
460     aec->mic_sampling_rate = in->config.rate;
461     aec->mic_frame_size_bytes = audio_stream_in_frame_size(&in->stream);
462     aec->mic_num_channels = in->config.channels;
463 
464     aec->mic_buf_size_bytes = in->config.period_size * audio_stream_in_frame_size(&in->stream);
465     aec->mic_buf = (int32_t *)malloc(aec->mic_buf_size_bytes);
466     if (aec->mic_buf == NULL) {
467         ret = -ENOMEM;
468         goto exit;
469     }
470     memset(aec->mic_buf, 0, aec->mic_buf_size_bytes);
471     /* Reference buffer is the same number of frames as mic,
472      * only with a different number of channels in the frame. */
473     aec->spk_buf_size_bytes = in->config.period_size * aec->spk_frame_size_bytes;
474     aec->spk_buf = (int32_t *)malloc(aec->spk_buf_size_bytes);
475     if (aec->spk_buf == NULL) {
476         ret = -ENOMEM;
477         goto exit_1;
478     }
479     memset(aec->spk_buf, 0, aec->spk_buf_size_bytes);
480 
481     /* Pre-resampler buffer */
482     size_t spk_frame_out_format_bytes = aec->spk_sampling_rate / aec->mic_sampling_rate *
483                                             aec->spk_buf_size_bytes;
484     aec->spk_buf_playback_format = (int16_t *)malloc(spk_frame_out_format_bytes);
485     if (aec->spk_buf_playback_format == NULL) {
486         ret = -ENOMEM;
487         goto exit_2;
488     }
489     /* Resampler is 16-bit */
490     aec->spk_buf_resampler_out = (int16_t *)malloc(aec->spk_buf_size_bytes);
491     if (aec->spk_buf_resampler_out == NULL) {
492         ret = -ENOMEM;
493         goto exit_3;
494     }
495 
496     /* Don't use resampler if it's not required */
497     if (in->config.rate == aec->spk_sampling_rate) {
498         aec->spk_resampler = NULL;
499     } else {
500         int resampler_ret = create_resampler(
501                 aec->spk_sampling_rate, in->config.rate, aec->num_reference_channels,
502                 RESAMPLER_QUALITY_MAX - 1, /* MAX - 1 is the real max */
503                 NULL,                      /* resampler_buffer_provider */
504                 &aec->spk_resampler);
505         if (resampler_ret) {
506             ALOGE("AEC: Resampler initialization failed! Error code %d", resampler_ret);
507             ret = resampler_ret;
508             goto exit_4;
509         }
510     }
511 
512     flush_aec_fifos(aec);
513     aec_spk_mic_reset();
514     aec->mic_initialized = true;
515 
516 exit:
517     pthread_mutex_unlock(&aec->lock);
518     ALOGV("%s exit", __func__);
519     return ret;
520 
521 exit_4:
522     free(aec->spk_buf_resampler_out);
523 exit_3:
524     free(aec->spk_buf_playback_format);
525 exit_2:
526     free(aec->spk_buf);
527 exit_1:
528     free(aec->mic_buf);
529     pthread_mutex_unlock(&aec->lock);
530     ALOGV("%s exit", __func__);
531     return ret;
532 }
533 
aec_set_spk_running(struct aec_t * aec,bool state)534 void aec_set_spk_running(struct aec_t *aec, bool state) {
535     ALOGV("%s enter", __func__);
536     pthread_mutex_lock(&aec->lock);
537     aec_set_spk_running_no_lock(aec, state);
538     pthread_mutex_unlock(&aec->lock);
539     ALOGV("%s exit", __func__);
540 }
541 
aec_get_spk_running(struct aec_t * aec)542 bool aec_get_spk_running(struct aec_t *aec) {
543     ALOGV("%s enter", __func__);
544     pthread_mutex_lock(&aec->lock);
545     bool state = aec_get_spk_running_no_lock(aec);
546     pthread_mutex_unlock(&aec->lock);
547     ALOGV("%s exit", __func__);
548     return state;
549 }
550 
destroy_aec_mic_config(struct aec_t * aec)551 void destroy_aec_mic_config(struct aec_t* aec) {
552     ALOGV("%s enter", __func__);
553     if (aec == NULL) {
554         ALOGV("%s exit", __func__);
555         return;
556     }
557 
558     pthread_mutex_lock(&aec->lock);
559     destroy_aec_mic_config_no_lock(aec);
560     pthread_mutex_unlock(&aec->lock);
561     ALOGV("%s exit", __func__);
562 }
563 
564 #ifdef AEC_HAL
process_aec(struct aec_t * aec,void * buffer,struct aec_info * info)565 int process_aec(struct aec_t *aec, void* buffer, struct aec_info *info) {
566     ALOGV("%s enter", __func__);
567     int ret = 0;
568 
569     if (aec == NULL) {
570         ALOGE("AEC: Interface uninitialized! Cannot process.");
571         return -EINVAL;
572     }
573 
574     if ((!aec->mic_initialized) || (!aec->spk_initialized)) {
575         ALOGE("%s called with initialization: mic: %d, spk: %d", __func__, aec->mic_initialized,
576               aec->spk_initialized);
577         return -EINVAL;
578     }
579 
580     size_t bytes = info->bytes;
581 
582     size_t frame_size = aec->mic_frame_size_bytes;
583     size_t in_frames = bytes / frame_size;
584 
585     /* Copy raw mic samples to AEC input buffer */
586     memcpy(aec->mic_buf, buffer, bytes);
587 
588     uint64_t mic_time = timespec_to_usec(info->timestamp);
589     uint64_t spk_time = 0;
590 
591     /*
592      * Only run AEC if there is speaker playback.
593      * The first time speaker state changes to running, flush FIFOs, so we're not stuck
594      * processing stale reference input.
595      */
596     bool spk_running = aec_get_spk_running(aec);
597 
598     if (!spk_running) {
599         /* No new playback samples, so don't run AEC.
600          * 'buffer' already contains input samples. */
601         ALOGV("Speaker not running, skipping AEC..");
602         goto exit;
603     }
604 
605     if (!aec->prev_spk_running) {
606         flush_aec_fifos(aec);
607     }
608 
609     /* If there's no data in FIFO, exit */
610     if (fifo_available_to_read(aec->spk_fifo) <= 0) {
611         ALOGV("Echo reference buffer empty, zeroing reference....");
612         goto exit;
613     }
614 
615     print_queue_status_to_log(aec, false);
616 
617     /* Get reference, with format and sample rate required by AEC */
618     struct aec_info spk_info;
619     spk_info.bytes = bytes;
620     int ref_ret = get_reference_samples(aec, aec->spk_buf, &spk_info);
621     spk_time = spk_info.timestamp_usec;
622 
623     if (ref_ret) {
624         ALOGE("get_reference_samples returned code %d", ref_ret);
625         ret = -ENOMEM;
626         goto exit;
627     }
628 
629     int64_t time_diff = (mic_time > spk_time) ? (mic_time - spk_time) : (spk_time - mic_time);
630     if ((spk_time == 0) || (mic_time == 0) || (time_diff > MAX_TIMESTAMP_DIFF_USEC)) {
631         ALOGV("Speaker-mic timestamps diverged, skipping AEC");
632         flush_aec_fifos(aec);
633         aec_spk_mic_reset();
634         goto exit;
635     }
636 
637     ALOGV("Mic time: %"PRIu64", spk time: %"PRIu64, mic_time, spk_time);
638 
639     /*
640      * AEC processing call - output stored at 'buffer'
641      */
642     int32_t aec_status = aec_spk_mic_process(
643         aec->spk_buf, spk_time,
644         aec->mic_buf, mic_time,
645         in_frames,
646         buffer);
647 
648     if (!aec_status) {
649         ALOGE("AEC processing failed!");
650         ret = -EINVAL;
651     }
652 
653 exit:
654     aec->prev_spk_running = spk_running;
655     ALOGV("Mic time: %"PRIu64", spk time: %"PRIu64, mic_time, spk_time);
656     if (ret) {
657         /* Best we can do is copy over the raw mic signal */
658         memcpy(buffer, aec->mic_buf, bytes);
659         flush_aec_fifos(aec);
660         aec_spk_mic_reset();
661     }
662 
663 #if DEBUG_AEC
664     /* ref data is 32-bit at this point */
665     size_t ref_bytes = in_frames*aec->num_reference_channels*sizeof(int32_t);
666 
667     FILE *fp_in = fopen("/data/local/traces/aec_in.pcm", "a+");
668     if (fp_in) {
669         fwrite((char *)aec->mic_buf, 1, bytes, fp_in);
670         fclose(fp_in);
671     } else {
672         ALOGE("AEC debug: Could not open file aec_in.pcm!");
673     }
674     FILE *fp_out = fopen("/data/local/traces/aec_out.pcm", "a+");
675     if (fp_out) {
676         fwrite((char *)buffer, 1, bytes, fp_out);
677         fclose(fp_out);
678     } else {
679         ALOGE("AEC debug: Could not open file aec_out.pcm!");
680     }
681     FILE *fp_ref = fopen("/data/local/traces/aec_ref.pcm", "a+");
682     if (fp_ref) {
683         fwrite((char *)aec->spk_buf, 1, ref_bytes, fp_ref);
684         fclose(fp_ref);
685     } else {
686         ALOGE("AEC debug: Could not open file aec_ref.pcm!");
687     }
688     FILE *fp_ts = fopen("/data/local/traces/aec_timestamps.txt", "a+");
689     if (fp_ts) {
690         fprintf(fp_ts, "%"PRIu64",%"PRIu64"\n", mic_time, spk_time);
691         fclose(fp_ts);
692     } else {
693         ALOGE("AEC debug: Could not open file aec_timestamps.txt!");
694     }
695 #endif /* #if DEBUG_AEC */
696     ALOGV("%s exit", __func__);
697     return ret;
698 }
699 
700 #endif /*#ifdef AEC_HAL*/
701