1/*
2 *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "delay_estimator_wrapper.h"
12
13#include <assert.h>
14#include <stdlib.h>
15#include <string.h>
16
17#include "delay_estimator.h"
18
19typedef union {
20  float float_;
21  int32_t int32_;
22} SpectrumType;
23
24typedef struct {
25  // Pointers to mean values of spectrum.
26  SpectrumType* mean_far_spectrum;
27  SpectrumType* mean_near_spectrum;
28  // |mean_*_spectrum| initialization indicator.
29  int far_spectrum_initialized;
30  int near_spectrum_initialized;
31
32  int spectrum_size;
33
34  // Binary spectrum based delay estimator
35  BinaryDelayEstimator* binary_handle;
36} DelayEstimator;
37
38// Only bit |kBandFirst| through bit |kBandLast| are processed and
39// |kBandFirst| - |kBandLast| must be < 32.
40static const int kBandFirst = 12;
41static const int kBandLast = 43;
42
43static __inline uint32_t SetBit(uint32_t in, int pos) {
44  uint32_t mask = (1 << pos);
45  uint32_t out = (in | mask);
46
47  return out;
48}
49
50// Calculates the mean recursively. Same version as WebRtc_MeanEstimatorFix(),
51// but for float.
52//
53// Inputs:
54//    - new_value             : New additional value.
55//    - scale                 : Scale for smoothing (should be less than 1.0).
56//
57// Input/Output:
58//    - mean_value            : Pointer to the mean value for updating.
59//
60static void MeanEstimatorFloat(float new_value,
61                               float scale,
62                               float* mean_value) {
63  assert(scale < 1.0f);
64  *mean_value += (new_value - *mean_value) * scale;
65}
66
67// Computes the binary spectrum by comparing the input |spectrum| with a
68// |threshold_spectrum|. Float and fixed point versions.
69//
70// Inputs:
71//      - spectrum            : Spectrum of which the binary spectrum should be
72//                              calculated.
73//      - threshold_spectrum  : Threshold spectrum with which the input
74//                              spectrum is compared.
75// Return:
76//      - out                 : Binary spectrum.
77//
78static uint32_t BinarySpectrumFix(uint16_t* spectrum,
79                                  SpectrumType* threshold_spectrum,
80                                  int q_domain,
81                                  int* threshold_initialized) {
82  int i = kBandFirst;
83  uint32_t out = 0;
84
85  assert(q_domain < 16);
86
87  if (!(*threshold_initialized)) {
88    // Set the |threshold_spectrum| to half the input |spectrum| as starting
89    // value. This speeds up the convergence.
90    for (i = kBandFirst; i <= kBandLast; i++) {
91      if (spectrum[i] > 0) {
92        // Convert input spectrum from Q(|q_domain|) to Q15.
93        int32_t spectrum_q15 = ((int32_t) spectrum[i]) << (15 - q_domain);
94        threshold_spectrum[i].int32_ = (spectrum_q15 >> 1);
95        *threshold_initialized = 1;
96      }
97    }
98  }
99  for (i = kBandFirst; i <= kBandLast; i++) {
100    // Convert input spectrum from Q(|q_domain|) to Q15.
101    int32_t spectrum_q15 = ((int32_t) spectrum[i]) << (15 - q_domain);
102    // Update the |threshold_spectrum|.
103    WebRtc_MeanEstimatorFix(spectrum_q15, 6, &(threshold_spectrum[i].int32_));
104    // Convert |spectrum| at current frequency bin to a binary value.
105    if (spectrum_q15 > threshold_spectrum[i].int32_) {
106      out = SetBit(out, i - kBandFirst);
107    }
108  }
109
110  return out;
111}
112
113static uint32_t BinarySpectrumFloat(float* spectrum,
114                                    SpectrumType* threshold_spectrum,
115                                    int* threshold_initialized) {
116  int i = kBandFirst;
117  uint32_t out = 0;
118  const float kScale = 1 / 64.0;
119
120  if (!(*threshold_initialized)) {
121    // Set the |threshold_spectrum| to half the input |spectrum| as starting
122    // value. This speeds up the convergence.
123    for (i = kBandFirst; i <= kBandLast; i++) {
124      if (spectrum[i] > 0.0f) {
125        threshold_spectrum[i].float_ = (spectrum[i] / 2);
126        *threshold_initialized = 1;
127      }
128    }
129  }
130
131  for (i = kBandFirst; i <= kBandLast; i++) {
132    // Update the |threshold_spectrum|.
133    MeanEstimatorFloat(spectrum[i], kScale, &(threshold_spectrum[i].float_));
134    // Convert |spectrum| at current frequency bin to a binary value.
135    if (spectrum[i] > threshold_spectrum[i].float_) {
136      out = SetBit(out, i - kBandFirst);
137    }
138  }
139
140  return out;
141}
142
143int WebRtc_FreeDelayEstimator(void* handle) {
144  DelayEstimator* self = (DelayEstimator*) handle;
145
146  if (self == NULL) {
147    return -1;
148  }
149
150  if (self->mean_far_spectrum != NULL) {
151    free(self->mean_far_spectrum);
152    self->mean_far_spectrum = NULL;
153  }
154  if (self->mean_near_spectrum != NULL) {
155    free(self->mean_near_spectrum);
156    self->mean_near_spectrum = NULL;
157  }
158
159  WebRtc_FreeBinaryDelayEstimator(self->binary_handle);
160
161  free(self);
162
163  return 0;
164}
165
166int WebRtc_CreateDelayEstimator(void** handle,
167                                int spectrum_size,
168                                int max_delay,
169                                int lookahead) {
170  DelayEstimator* self = NULL;
171
172  // Check if the sub band used in the delay estimation is small enough to fit
173  // the binary spectra in a uint32_t.
174  assert(kBandLast - kBandFirst < 32);
175
176  if (handle == NULL) {
177    return -1;
178  }
179  if (spectrum_size < kBandLast) {
180    return -1;
181  }
182
183  self = malloc(sizeof(DelayEstimator));
184  *handle = self;
185  if (self == NULL) {
186    return -1;
187  }
188
189  self->mean_far_spectrum = NULL;
190  self->mean_near_spectrum = NULL;
191
192  // Create binary delay estimator.
193  if (WebRtc_CreateBinaryDelayEstimator(&self->binary_handle,
194                                        max_delay,
195                                        lookahead) != 0) {
196    WebRtc_FreeDelayEstimator(self);
197    self = NULL;
198    return -1;
199  }
200  // Allocate memory for spectrum buffers.
201  self->mean_far_spectrum = malloc(spectrum_size * sizeof(SpectrumType));
202  if (self->mean_far_spectrum == NULL) {
203    WebRtc_FreeDelayEstimator(self);
204    self = NULL;
205    return -1;
206  }
207  self->mean_near_spectrum = malloc(spectrum_size * sizeof(SpectrumType));
208  if (self->mean_near_spectrum == NULL) {
209    WebRtc_FreeDelayEstimator(self);
210    self = NULL;
211    return -1;
212  }
213
214  self->spectrum_size = spectrum_size;
215
216  return 0;
217}
218
219int WebRtc_InitDelayEstimator(void* handle) {
220  DelayEstimator* self = (DelayEstimator*) handle;
221
222  if (self == NULL) {
223    return -1;
224  }
225
226  // Initialize binary delay estimator.
227  if (WebRtc_InitBinaryDelayEstimator(self->binary_handle) != 0) {
228    return -1;
229  }
230  // Set averaged far and near end spectra to zero.
231  memset(self->mean_far_spectrum, 0,
232         sizeof(SpectrumType) * self->spectrum_size);
233  memset(self->mean_near_spectrum, 0,
234         sizeof(SpectrumType) * self->spectrum_size);
235  // Reset initialization indicators.
236  self->far_spectrum_initialized = 0;
237  self->near_spectrum_initialized = 0;
238
239  return 0;
240}
241
242int WebRtc_DelayEstimatorProcessFix(void* handle,
243                                    uint16_t* far_spectrum,
244                                    uint16_t* near_spectrum,
245                                    int spectrum_size,
246                                    int far_q,
247                                    int near_q) {
248  DelayEstimator* self = (DelayEstimator*) handle;
249  uint32_t binary_far_spectrum = 0;
250  uint32_t binary_near_spectrum = 0;
251
252  if (self == NULL) {
253    return -1;
254  }
255  if (far_spectrum == NULL) {
256    // Empty far end spectrum.
257    return -1;
258  }
259  if (near_spectrum == NULL) {
260    // Empty near end spectrum.
261    return -1;
262  }
263  if (spectrum_size != self->spectrum_size) {
264    // Data sizes don't match.
265    return -1;
266  }
267  if (far_q > 15) {
268    // If |far_q| is larger than 15 we cannot guarantee no wrap around.
269    return -1;
270  }
271  if (near_q > 15) {
272    // If |near_q| is larger than 15 we cannot guarantee no wrap around.
273    return -1;
274  }
275
276  // Get binary spectra.
277  binary_far_spectrum = BinarySpectrumFix(far_spectrum,
278                                          self->mean_far_spectrum,
279                                          far_q,
280                                          &(self->far_spectrum_initialized));
281  binary_near_spectrum = BinarySpectrumFix(near_spectrum,
282                                           self->mean_near_spectrum,
283                                           near_q,
284                                           &(self->near_spectrum_initialized));
285
286  return WebRtc_ProcessBinarySpectrum(self->binary_handle,
287                                      binary_far_spectrum,
288                                      binary_near_spectrum);
289}
290
291int WebRtc_DelayEstimatorProcessFloat(void* handle,
292                                      float* far_spectrum,
293                                      float* near_spectrum,
294                                      int spectrum_size) {
295  DelayEstimator* self = (DelayEstimator*) handle;
296  uint32_t binary_far_spectrum = 0;
297  uint32_t binary_near_spectrum = 0;
298
299  if (self == NULL) {
300    return -1;
301  }
302  if (far_spectrum == NULL) {
303    // Empty far end spectrum.
304    return -1;
305  }
306  if (near_spectrum == NULL) {
307    // Empty near end spectrum.
308    return -1;
309  }
310  if (spectrum_size != self->spectrum_size) {
311    // Data sizes don't match.
312    return -1;
313  }
314
315  // Get binary spectra.
316  binary_far_spectrum = BinarySpectrumFloat(far_spectrum,
317                                            self->mean_far_spectrum,
318                                            &(self->far_spectrum_initialized));
319  binary_near_spectrum = BinarySpectrumFloat(near_spectrum,
320                                             self->mean_near_spectrum,
321                                             &(self->near_spectrum_initialized));
322
323  return WebRtc_ProcessBinarySpectrum(self->binary_handle,
324                                      binary_far_spectrum,
325                                      binary_near_spectrum);
326}
327
328int WebRtc_last_delay(void* handle) {
329  DelayEstimator* self = (DelayEstimator*) handle;
330
331  if (self == NULL) {
332    return -1;
333  }
334
335  return WebRtc_binary_last_delay(self->binary_handle);
336}
337