File: dtmf_buffer_unittest.cc

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (297 lines) | stat: -rw-r--r-- 10,380 bytes parent folder | download | duplicates (5)
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "modules/audio_coding/neteq/dtmf_buffer.h"

#include <cstdint>

#ifdef WIN32
#include <winsock2.h>  // ntohl()
#else
#endif

#include "rtc_base/ip_address.h"
#include "test/gtest.h"

// Modify the tests so that they pass with the modifications done to DtmfBuffer
// for backwards bit-exactness. Once bit-exactness is no longer required, this
// #define should be removed (and the code that it enables).
#define LEGACY_BITEXACT

namespace webrtc {

static int sample_rate_hz = 8000;

static uint32_t MakeDtmfPayload(int event, bool end, int volume, int duration) {
  uint32_t payload = 0;
  //  0                   1                   2                   3
  //  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  // |     event     |E|R| volume    |          duration             |
  // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  payload |= (event & 0x00FF) << 24;
  payload |= (end ? 0x00800000 : 0x00000000);
  payload |= (volume & 0x003F) << 16;
  payload |= (duration & 0xFFFF);
  payload = ntohl(payload);
  return payload;
}

static bool EqualEvents(const DtmfEvent& a, const DtmfEvent& b) {
  return (a.duration == b.duration && a.end_bit == b.end_bit &&
          a.event_no == b.event_no && a.timestamp == b.timestamp &&
          a.volume == b.volume);
}

TEST(DtmfBuffer, CreateAndDestroy) {
  DtmfBuffer* buffer = new DtmfBuffer(sample_rate_hz);
  delete buffer;
}

// Test the event parser.
TEST(DtmfBuffer, ParseEvent) {
  int event_no = 7;
  bool end_bit = true;
  int volume = 17;
  int duration = 4711;
  uint32_t timestamp = 0x12345678;
  uint32_t payload = MakeDtmfPayload(event_no, end_bit, volume, duration);
  uint8_t* payload_ptr = reinterpret_cast<uint8_t*>(&payload);
  DtmfEvent event;
  EXPECT_EQ(DtmfBuffer::kOK, DtmfBuffer::ParseEvent(timestamp, payload_ptr,
                                                    sizeof(payload), &event));
  EXPECT_EQ(duration, event.duration);
  EXPECT_EQ(end_bit, event.end_bit);
  EXPECT_EQ(event_no, event.event_no);
  EXPECT_EQ(timestamp, event.timestamp);
  EXPECT_EQ(volume, event.volume);

  EXPECT_EQ(DtmfBuffer::kPayloadTooShort,
            DtmfBuffer::ParseEvent(timestamp, payload_ptr, 3, &event));
}

TEST(DtmfBuffer, SimpleInsertAndGet) {
  int event_no = 7;
  bool end_bit = true;
  int volume = 17;
  int duration = 4711;
  uint32_t timestamp = 0x12345678;
  DtmfEvent event(timestamp, event_no, volume, duration, end_bit);
  DtmfBuffer buffer(sample_rate_hz);
  EXPECT_EQ(DtmfBuffer::kOK, buffer.InsertEvent(event));
  EXPECT_EQ(1u, buffer.Length());
  EXPECT_FALSE(buffer.Empty());
  DtmfEvent out_event;
  // Too early to get event.
  EXPECT_FALSE(buffer.GetEvent(timestamp - 10, &out_event));
  EXPECT_EQ(1u, buffer.Length());
  EXPECT_FALSE(buffer.Empty());
  // Get the event at its starting timestamp.
  EXPECT_TRUE(buffer.GetEvent(timestamp, &out_event));
  EXPECT_TRUE(EqualEvents(event, out_event));
  EXPECT_EQ(1u, buffer.Length());
  EXPECT_FALSE(buffer.Empty());
  // Get the event some time into the event.
  EXPECT_TRUE(buffer.GetEvent(timestamp + duration / 2, &out_event));
  EXPECT_TRUE(EqualEvents(event, out_event));
  EXPECT_EQ(1u, buffer.Length());
  EXPECT_FALSE(buffer.Empty());
// Give a "current" timestamp after the event has ended.
#ifdef LEGACY_BITEXACT
  EXPECT_TRUE(buffer.GetEvent(timestamp + duration + 10, &out_event));
#endif
  EXPECT_FALSE(buffer.GetEvent(timestamp + duration + 10, &out_event));
  EXPECT_EQ(0u, buffer.Length());
  EXPECT_TRUE(buffer.Empty());
}

TEST(DtmfBuffer, MergingPackets) {
  int event_no = 0;
  bool end_bit = false;
  int volume = 17;
  int duration = 80;
  uint32_t timestamp = 0x12345678;
  DtmfEvent event(timestamp, event_no, volume, duration, end_bit);
  DtmfBuffer buffer(sample_rate_hz);
  EXPECT_EQ(DtmfBuffer::kOK, buffer.InsertEvent(event));

  event.duration += 80;
  EXPECT_EQ(DtmfBuffer::kOK, buffer.InsertEvent(event));

  event.duration += 80;
  event.end_bit = true;
  EXPECT_EQ(DtmfBuffer::kOK, buffer.InsertEvent(event));

  EXPECT_EQ(1u, buffer.Length());

  DtmfEvent out_event;
  EXPECT_TRUE(buffer.GetEvent(timestamp, &out_event));
  EXPECT_TRUE(EqualEvents(event, out_event));
}

// This test case inserts one shorter event completely overlapped by one longer
// event. The expected outcome is that only the longer event is played.
TEST(DtmfBuffer, OverlappingEvents) {
  int event_no = 0;
  bool end_bit = true;
  int volume = 1;
  int duration = 80;
  uint32_t timestamp = 0x12345678 + 80;
  DtmfEvent short_event(timestamp, event_no, volume, duration, end_bit);
  DtmfBuffer buffer(sample_rate_hz);
  EXPECT_EQ(DtmfBuffer::kOK, buffer.InsertEvent(short_event));

  event_no = 10;
  end_bit = false;
  timestamp = 0x12345678;
  DtmfEvent long_event(timestamp, event_no, volume, duration, end_bit);
  EXPECT_EQ(DtmfBuffer::kOK, buffer.InsertEvent(long_event));

  long_event.duration += 80;
  EXPECT_EQ(DtmfBuffer::kOK, buffer.InsertEvent(long_event));

  long_event.duration += 80;
  long_event.end_bit = true;
  EXPECT_EQ(DtmfBuffer::kOK, buffer.InsertEvent(long_event));

  EXPECT_EQ(2u, buffer.Length());

  DtmfEvent out_event;
  // Expect to get the long event.
  EXPECT_TRUE(buffer.GetEvent(timestamp, &out_event));
  EXPECT_TRUE(EqualEvents(long_event, out_event));
// Expect no more events.
#ifdef LEGACY_BITEXACT
  EXPECT_TRUE(
      buffer.GetEvent(timestamp + long_event.duration + 10, &out_event));
  EXPECT_TRUE(EqualEvents(long_event, out_event));
  EXPECT_TRUE(
      buffer.GetEvent(timestamp + long_event.duration + 10, &out_event));
  EXPECT_TRUE(EqualEvents(short_event, out_event));
#else
  EXPECT_FALSE(
      buffer.GetEvent(timestamp + long_event.duration + 10, &out_event));
#endif
  EXPECT_TRUE(buffer.Empty());
}

TEST(DtmfBuffer, ExtrapolationTime) {
  int event_no = 0;
  bool end_bit = false;
  int volume = 1;
  int duration = 80;
  uint32_t timestamp = 0x12345678;
  DtmfEvent event1(timestamp, event_no, volume, duration, end_bit);
  DtmfBuffer buffer(sample_rate_hz);
  EXPECT_EQ(DtmfBuffer::kOK, buffer.InsertEvent(event1));
  EXPECT_EQ(1u, buffer.Length());

  DtmfEvent out_event;
  // Get the event at the start.
  EXPECT_TRUE(buffer.GetEvent(timestamp, &out_event));
  EXPECT_TRUE(EqualEvents(event1, out_event));
  // Also get the event 100 samples after the end of the event (since we're
  // missing the end bit).
  uint32_t timestamp_now = timestamp + duration + 100;
  EXPECT_TRUE(buffer.GetEvent(timestamp_now, &out_event));
  EXPECT_TRUE(EqualEvents(event1, out_event));
  // Insert another event starting back-to-back with the previous event.
  timestamp += duration;
  event_no = 1;
  DtmfEvent event2(timestamp, event_no, volume, duration, end_bit);
  EXPECT_EQ(DtmfBuffer::kOK, buffer.InsertEvent(event2));
  EXPECT_EQ(2u, buffer.Length());
  // Now we expect to get the new event when supplying `timestamp_now`.
  EXPECT_TRUE(buffer.GetEvent(timestamp_now, &out_event));
  EXPECT_TRUE(EqualEvents(event2, out_event));
  // Expect the the first event to be erased now.
  EXPECT_EQ(1u, buffer.Length());
  // Move `timestamp_now` to more than 560 samples after the end of the second
  // event. Expect that event to be erased.
  timestamp_now = timestamp + duration + 600;
#ifdef LEGACY_BITEXACT
  EXPECT_TRUE(buffer.GetEvent(timestamp_now, &out_event));
#endif
  EXPECT_FALSE(buffer.GetEvent(timestamp_now, &out_event));
  EXPECT_TRUE(buffer.Empty());
}

TEST(DtmfBuffer, TimestampWraparound) {
  int event_no = 0;
  bool end_bit = true;
  int volume = 1;
  int duration = 80;
  uint32_t timestamp1 = 0xFFFFFFFF - duration;
  DtmfEvent event1(timestamp1, event_no, volume, duration, end_bit);
  uint32_t timestamp2 = 0;
  DtmfEvent event2(timestamp2, event_no, volume, duration, end_bit);
  DtmfBuffer buffer(sample_rate_hz);
  EXPECT_EQ(DtmfBuffer::kOK, buffer.InsertEvent(event1));
  EXPECT_EQ(DtmfBuffer::kOK, buffer.InsertEvent(event2));
  EXPECT_EQ(2u, buffer.Length());
  DtmfEvent out_event;
  EXPECT_TRUE(buffer.GetEvent(timestamp1, &out_event));
  EXPECT_TRUE(EqualEvents(event1, out_event));
#ifdef LEGACY_BITEXACT
  EXPECT_EQ(1u, buffer.Length());
#else
  EXPECT_EQ(2u, buffer.Length());
#endif

  buffer.Flush();
  // Reverse the insert order. Expect same results.
  EXPECT_EQ(DtmfBuffer::kOK, buffer.InsertEvent(event2));
  EXPECT_EQ(DtmfBuffer::kOK, buffer.InsertEvent(event1));
  EXPECT_EQ(2u, buffer.Length());
  EXPECT_TRUE(buffer.GetEvent(timestamp1, &out_event));
  EXPECT_TRUE(EqualEvents(event1, out_event));
#ifdef LEGACY_BITEXACT
  EXPECT_EQ(1u, buffer.Length());
#else
  EXPECT_EQ(2u, buffer.Length());
#endif
}

TEST(DtmfBuffer, InvalidEvents) {
  int event_no = 0;
  bool end_bit = true;
  int volume = 1;
  int duration = 80;
  uint32_t timestamp = 0x12345678;
  DtmfEvent event(timestamp, event_no, volume, duration, end_bit);
  DtmfBuffer buffer(sample_rate_hz);

  // Invalid event number.
  event.event_no = -1;
  EXPECT_EQ(DtmfBuffer::kInvalidEventParameters, buffer.InsertEvent(event));
  event.event_no = 16;
  EXPECT_EQ(DtmfBuffer::kInvalidEventParameters, buffer.InsertEvent(event));
  event.event_no = 0;  // Valid value;

  // Invalid volume.
  event.volume = -1;
  EXPECT_EQ(DtmfBuffer::kInvalidEventParameters, buffer.InsertEvent(event));
  event.volume = 64;
  EXPECT_EQ(DtmfBuffer::kInvalidEventParameters, buffer.InsertEvent(event));
  event.volume = 0;  // Valid value;

  // Invalid duration.
  event.duration = -1;
  EXPECT_EQ(DtmfBuffer::kInvalidEventParameters, buffer.InsertEvent(event));
  event.duration = 0;
  EXPECT_EQ(DtmfBuffer::kInvalidEventParameters, buffer.InsertEvent(event));
  event.duration = 0xFFFF + 1;
  EXPECT_EQ(DtmfBuffer::kInvalidEventParameters, buffer.InsertEvent(event));
  event.duration = 1;  // Valid value;

  // Finish with a valid event, just to verify that all is ok.
  EXPECT_EQ(DtmfBuffer::kOK, buffer.InsertEvent(event));
}
}  // namespace webrtc