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 "utility.h"
12
13#include <assert.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
17
18#include "testing/gtest/include/gtest/gtest.h"
19#include "webrtc/common.h"
20#include "webrtc/common_types.h"
21#include "webrtc/modules/audio_coding/include/audio_coding_module.h"
22#include "webrtc/modules/audio_coding/acm2/acm_common_defs.h"
23
24#define NUM_CODECS_WITH_FIXED_PAYLOAD_TYPE 13
25
26namespace webrtc {
27
28ACMTestTimer::ACMTestTimer()
29    : _msec(0),
30      _sec(0),
31      _min(0),
32      _hour(0) {
33  return;
34}
35
36ACMTestTimer::~ACMTestTimer() {
37  return;
38}
39
40void ACMTestTimer::Reset() {
41  _msec = 0;
42  _sec = 0;
43  _min = 0;
44  _hour = 0;
45  return;
46}
47void ACMTestTimer::Tick10ms() {
48  _msec += 10;
49  Adjust();
50  return;
51}
52
53void ACMTestTimer::Tick1ms() {
54  _msec++;
55  Adjust();
56  return;
57}
58
59void ACMTestTimer::Tick100ms() {
60  _msec += 100;
61  Adjust();
62  return;
63}
64
65void ACMTestTimer::Tick1sec() {
66  _sec++;
67  Adjust();
68  return;
69}
70
71void ACMTestTimer::CurrentTimeHMS(char* currTime) {
72  sprintf(currTime, "%4lu:%02u:%06.3f", _hour, _min,
73          (double) _sec + (double) _msec / 1000.);
74  return;
75}
76
77void ACMTestTimer::CurrentTime(unsigned long& h, unsigned char& m,
78                               unsigned char& s, unsigned short& ms) {
79  h = _hour;
80  m = _min;
81  s = _sec;
82  ms = _msec;
83  return;
84}
85
86void ACMTestTimer::Adjust() {
87  unsigned int n;
88  if (_msec >= 1000) {
89    n = _msec / 1000;
90    _msec -= (1000 * n);
91    _sec += n;
92  }
93  if (_sec >= 60) {
94    n = _sec / 60;
95    _sec -= (n * 60);
96    _min += n;
97  }
98  if (_min >= 60) {
99    n = _min / 60;
100    _min -= (n * 60);
101    _hour += n;
102  }
103}
104
105int16_t ChooseCodec(CodecInst& codecInst) {
106
107  PrintCodecs();
108  //AudioCodingModule* tmpACM = AudioCodingModule::Create(0);
109  uint8_t noCodec = AudioCodingModule::NumberOfCodecs();
110  int8_t codecID;
111  bool outOfRange = false;
112  char myStr[15] = "";
113  do {
114    printf("\nChoose a codec [0]: ");
115    EXPECT_TRUE(fgets(myStr, 10, stdin) != NULL);
116    codecID = atoi(myStr);
117    if ((codecID < 0) || (codecID >= noCodec)) {
118      printf("\nOut of range.\n");
119      outOfRange = true;
120    }
121  } while (outOfRange);
122
123  CHECK_ERROR(AudioCodingModule::Codec((uint8_t )codecID, &codecInst));
124  return 0;
125}
126
127void PrintCodecs() {
128  uint8_t noCodec = AudioCodingModule::NumberOfCodecs();
129
130  CodecInst codecInst;
131  printf("No  Name                [Hz]    [bps]\n");
132  for (uint8_t codecCntr = 0; codecCntr < noCodec; codecCntr++) {
133    AudioCodingModule::Codec(codecCntr, &codecInst);
134    printf("%2d- %-18s %5d   %6d\n", codecCntr, codecInst.plname,
135           codecInst.plfreq, codecInst.rate);
136  }
137
138}
139
140CircularBuffer::CircularBuffer(uint32_t len)
141    : _buff(NULL),
142      _idx(0),
143      _buffIsFull(false),
144      _calcAvg(false),
145      _calcVar(false),
146      _sum(0),
147      _sumSqr(0) {
148  _buff = new double[len];
149  if (_buff == NULL) {
150    _buffLen = 0;
151  } else {
152    for (uint32_t n = 0; n < len; n++) {
153      _buff[n] = 0;
154    }
155    _buffLen = len;
156  }
157}
158
159CircularBuffer::~CircularBuffer() {
160  if (_buff != NULL) {
161    delete[] _buff;
162    _buff = NULL;
163  }
164}
165
166void CircularBuffer::Update(const double newVal) {
167  assert(_buffLen > 0);
168
169  // store the value that is going to be overwritten
170  double oldVal = _buff[_idx];
171  // record the new value
172  _buff[_idx] = newVal;
173  // increment the index, to point to where we would
174  // write next
175  _idx++;
176  // it is a circular buffer, if we are at the end
177  // we have to cycle to the beginning
178  if (_idx >= _buffLen) {
179    // flag that the buffer is filled up.
180    _buffIsFull = true;
181    _idx = 0;
182  }
183
184  // Update
185
186  if (_calcAvg) {
187    // for the average we have to update
188    // the sum
189    _sum += (newVal - oldVal);
190  }
191
192  if (_calcVar) {
193    // to calculate variance we have to update
194    // the sum of squares
195    _sumSqr += (double) (newVal - oldVal) * (double) (newVal + oldVal);
196  }
197}
198
199void CircularBuffer::SetArithMean(bool enable) {
200  assert(_buffLen > 0);
201
202  if (enable && !_calcAvg) {
203    uint32_t lim;
204    if (_buffIsFull) {
205      lim = _buffLen;
206    } else {
207      lim = _idx;
208    }
209    _sum = 0;
210    for (uint32_t n = 0; n < lim; n++) {
211      _sum += _buff[n];
212    }
213  }
214  _calcAvg = enable;
215}
216
217void CircularBuffer::SetVariance(bool enable) {
218  assert(_buffLen > 0);
219
220  if (enable && !_calcVar) {
221    uint32_t lim;
222    if (_buffIsFull) {
223      lim = _buffLen;
224    } else {
225      lim = _idx;
226    }
227    _sumSqr = 0;
228    for (uint32_t n = 0; n < lim; n++) {
229      _sumSqr += _buff[n] * _buff[n];
230    }
231  }
232  _calcAvg = enable;
233}
234
235int16_t CircularBuffer::ArithMean(double& mean) {
236  assert(_buffLen > 0);
237
238  if (_buffIsFull) {
239
240    mean = _sum / (double) _buffLen;
241    return 0;
242  } else {
243    if (_idx > 0) {
244      mean = _sum / (double) _idx;
245      return 0;
246    } else {
247      return -1;
248    }
249
250  }
251}
252
253int16_t CircularBuffer::Variance(double& var) {
254  assert(_buffLen > 0);
255
256  if (_buffIsFull) {
257    var = _sumSqr / (double) _buffLen;
258    return 0;
259  } else {
260    if (_idx > 0) {
261      var = _sumSqr / (double) _idx;
262      return 0;
263    } else {
264      return -1;
265    }
266  }
267}
268
269bool FixedPayloadTypeCodec(const char* payloadName) {
270  char fixPayloadTypeCodecs[NUM_CODECS_WITH_FIXED_PAYLOAD_TYPE][32] = { "PCMU",
271      "PCMA", "GSM", "G723", "DVI4", "LPC", "PCMA", "G722", "QCELP", "CN",
272      "MPA", "G728", "G729" };
273
274  for (int n = 0; n < NUM_CODECS_WITH_FIXED_PAYLOAD_TYPE; n++) {
275    if (!STR_CASE_CMP(payloadName, fixPayloadTypeCodecs[n])) {
276      return true;
277    }
278  }
279  return false;
280}
281
282void VADCallback::Reset() {
283  memset(_numFrameTypes, 0, sizeof(_numFrameTypes));
284}
285
286VADCallback::VADCallback() {
287  memset(_numFrameTypes, 0, sizeof(_numFrameTypes));
288}
289
290void VADCallback::PrintFrameTypes() {
291  printf("kEmptyFrame......... %d\n", _numFrameTypes[kEmptyFrame]);
292  printf("kAudioFrameSpeech... %d\n", _numFrameTypes[kAudioFrameSpeech]);
293  printf("kAudioFrameCN....... %d\n", _numFrameTypes[kAudioFrameCN]);
294  printf("kVideoFrameKey...... %d\n", _numFrameTypes[kVideoFrameKey]);
295  printf("kVideoFrameDelta.... %d\n", _numFrameTypes[kVideoFrameDelta]);
296}
297
298int32_t VADCallback::InFrameType(FrameType frame_type) {
299  _numFrameTypes[frame_type]++;
300  return 0;
301}
302
303}  // namespace webrtc
304