1c55a96383497a772a307b346368133960b02ad03Eric Laurent/*
2c55a96383497a772a307b346368133960b02ad03Eric Laurent *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3c55a96383497a772a307b346368133960b02ad03Eric Laurent *
4c55a96383497a772a307b346368133960b02ad03Eric Laurent *  Use of this source code is governed by a BSD-style license
5c55a96383497a772a307b346368133960b02ad03Eric Laurent *  that can be found in the LICENSE file in the root of the source
6c55a96383497a772a307b346368133960b02ad03Eric Laurent *  tree. An additional intellectual property rights grant can be found
7c55a96383497a772a307b346368133960b02ad03Eric Laurent *  in the file PATENTS.  All contributing project authors may
8c55a96383497a772a307b346368133960b02ad03Eric Laurent *  be found in the AUTHORS file in the root of the source tree.
9c55a96383497a772a307b346368133960b02ad03Eric Laurent */
10c55a96383497a772a307b346368133960b02ad03Eric Laurent
11c55a96383497a772a307b346368133960b02ad03Eric Laurent#include <stddef.h>  // size_t
12c55a96383497a772a307b346368133960b02ad03Eric Laurent#include <stdlib.h>
13c55a96383497a772a307b346368133960b02ad03Eric Laurent
14c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "gtest/gtest.h"
15c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "typedefs.h"
16c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "webrtc_vad.h"
17c55a96383497a772a307b346368133960b02ad03Eric Laurent
18c55a96383497a772a307b346368133960b02ad03Eric Laurent// TODO(bjornv): Move the internal unit tests to separate files.
19c55a96383497a772a307b346368133960b02ad03Eric Laurentextern "C" {
20c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "vad_core.h"
21c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "vad_gmm.h"
22c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "vad_sp.h"
23c55a96383497a772a307b346368133960b02ad03Eric Laurent}
24c55a96383497a772a307b346368133960b02ad03Eric Laurent
25c55a96383497a772a307b346368133960b02ad03Eric Laurentnamespace webrtc {
26c55a96383497a772a307b346368133960b02ad03Eric Laurentnamespace {
27c55a96383497a772a307b346368133960b02ad03Eric Laurentconst int16_t kModes[] = { 0, 1, 2, 3 };
28c55a96383497a772a307b346368133960b02ad03Eric Laurentconst size_t kModesSize = sizeof(kModes) / sizeof(*kModes);
29c55a96383497a772a307b346368133960b02ad03Eric Laurent
30c55a96383497a772a307b346368133960b02ad03Eric Laurent// Rates we support.
31c55a96383497a772a307b346368133960b02ad03Eric Laurentconst int16_t kRates[] = { 8000, 12000, 16000, 24000, 32000 };
32c55a96383497a772a307b346368133960b02ad03Eric Laurentconst size_t kRatesSize = sizeof(kRates) / sizeof(*kRates);
33c55a96383497a772a307b346368133960b02ad03Eric Laurent// Frame lengths we support.
34c55a96383497a772a307b346368133960b02ad03Eric Laurentconst int16_t kMaxFrameLength = 960;
35c55a96383497a772a307b346368133960b02ad03Eric Laurentconst int16_t kFrameLengths[] = { 80, 120, 160, 240, 320, 480, 640,
36c55a96383497a772a307b346368133960b02ad03Eric Laurent    kMaxFrameLength };
37c55a96383497a772a307b346368133960b02ad03Eric Laurentconst size_t kFrameLengthsSize = sizeof(kFrameLengths) / sizeof(*kFrameLengths);
38c55a96383497a772a307b346368133960b02ad03Eric Laurent
39c55a96383497a772a307b346368133960b02ad03Eric Laurent// Returns true if the rate and frame length combination is valid.
40c55a96383497a772a307b346368133960b02ad03Eric Laurentbool ValidRatesAndFrameLengths(int16_t rate, int16_t frame_length) {
41c55a96383497a772a307b346368133960b02ad03Eric Laurent  if (rate == 8000) {
42c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (frame_length == 80 || frame_length == 160 || frame_length == 240) {
43c55a96383497a772a307b346368133960b02ad03Eric Laurent      return true;
44c55a96383497a772a307b346368133960b02ad03Eric Laurent    }
45c55a96383497a772a307b346368133960b02ad03Eric Laurent    return false;
46c55a96383497a772a307b346368133960b02ad03Eric Laurent  } else if (rate == 16000) {
47c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (frame_length == 160 || frame_length == 320 || frame_length == 480) {
48c55a96383497a772a307b346368133960b02ad03Eric Laurent      return true;
49c55a96383497a772a307b346368133960b02ad03Eric Laurent    }
50c55a96383497a772a307b346368133960b02ad03Eric Laurent    return false;
51c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
52c55a96383497a772a307b346368133960b02ad03Eric Laurent  if (rate == 32000) {
53c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (frame_length == 320 || frame_length == 640 || frame_length == 960) {
54c55a96383497a772a307b346368133960b02ad03Eric Laurent      return true;
55c55a96383497a772a307b346368133960b02ad03Eric Laurent    }
56c55a96383497a772a307b346368133960b02ad03Eric Laurent    return false;
57c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
58c55a96383497a772a307b346368133960b02ad03Eric Laurent
59c55a96383497a772a307b346368133960b02ad03Eric Laurent  return false;
60c55a96383497a772a307b346368133960b02ad03Eric Laurent}
61c55a96383497a772a307b346368133960b02ad03Eric Laurent
62c55a96383497a772a307b346368133960b02ad03Eric Laurentclass VadTest : public ::testing::Test {
63c55a96383497a772a307b346368133960b02ad03Eric Laurent protected:
64c55a96383497a772a307b346368133960b02ad03Eric Laurent  VadTest();
65c55a96383497a772a307b346368133960b02ad03Eric Laurent  virtual void SetUp();
66c55a96383497a772a307b346368133960b02ad03Eric Laurent  virtual void TearDown();
67c55a96383497a772a307b346368133960b02ad03Eric Laurent};
68c55a96383497a772a307b346368133960b02ad03Eric Laurent
69c55a96383497a772a307b346368133960b02ad03Eric LaurentVadTest::VadTest() {
70c55a96383497a772a307b346368133960b02ad03Eric Laurent}
71c55a96383497a772a307b346368133960b02ad03Eric Laurent
72c55a96383497a772a307b346368133960b02ad03Eric Laurentvoid VadTest::SetUp() {
73c55a96383497a772a307b346368133960b02ad03Eric Laurent}
74c55a96383497a772a307b346368133960b02ad03Eric Laurent
75c55a96383497a772a307b346368133960b02ad03Eric Laurentvoid VadTest::TearDown() {
76c55a96383497a772a307b346368133960b02ad03Eric Laurent}
77c55a96383497a772a307b346368133960b02ad03Eric Laurent
78c55a96383497a772a307b346368133960b02ad03Eric LaurentTEST_F(VadTest, ApiTest) {
79c55a96383497a772a307b346368133960b02ad03Eric Laurent  // This API test runs through the APIs for all possible valid and invalid
80c55a96383497a772a307b346368133960b02ad03Eric Laurent  // combinations.
81c55a96383497a772a307b346368133960b02ad03Eric Laurent
82c55a96383497a772a307b346368133960b02ad03Eric Laurent  VadInst* handle = NULL;
83c55a96383497a772a307b346368133960b02ad03Eric Laurent  int16_t zeros[kMaxFrameLength] = { 0 };
84c55a96383497a772a307b346368133960b02ad03Eric Laurent
85c55a96383497a772a307b346368133960b02ad03Eric Laurent  // Construct a speech signal that will trigger the VAD in all modes. It is
86c55a96383497a772a307b346368133960b02ad03Eric Laurent  // known that (i * i) will wrap around, but that doesn't matter in this case.
87c55a96383497a772a307b346368133960b02ad03Eric Laurent  int16_t speech[kMaxFrameLength];
88c55a96383497a772a307b346368133960b02ad03Eric Laurent  for (int16_t i = 0; i < kMaxFrameLength; i++) {
89c55a96383497a772a307b346368133960b02ad03Eric Laurent    speech[i] = (i * i);
90c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
91c55a96383497a772a307b346368133960b02ad03Eric Laurent
92c55a96383497a772a307b346368133960b02ad03Eric Laurent  // WebRtcVad_get_version() tests
93c55a96383497a772a307b346368133960b02ad03Eric Laurent  char version[32];
94c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(-1, WebRtcVad_get_version(NULL, sizeof(version)));
95c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(-1, WebRtcVad_get_version(version, 1));
96c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(0, WebRtcVad_get_version(version, sizeof(version)));
97c55a96383497a772a307b346368133960b02ad03Eric Laurent
98c55a96383497a772a307b346368133960b02ad03Eric Laurent  // Null instance tests
99c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(-1, WebRtcVad_Create(NULL));
100c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(-1, WebRtcVad_Init(NULL));
101c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(-1, WebRtcVad_Assign(NULL, NULL));
102c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(-1, WebRtcVad_Free(NULL));
103c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(-1, WebRtcVad_set_mode(NULL, kModes[0]));
104c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(-1, WebRtcVad_Process(NULL, kRates[0], speech, kFrameLengths[0]));
105c55a96383497a772a307b346368133960b02ad03Eric Laurent
106c55a96383497a772a307b346368133960b02ad03Eric Laurent  // WebRtcVad_AssignSize tests
107c55a96383497a772a307b346368133960b02ad03Eric Laurent  int handle_size_bytes = 0;
108c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(0, WebRtcVad_AssignSize(&handle_size_bytes));
109c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(576, handle_size_bytes);
110c55a96383497a772a307b346368133960b02ad03Eric Laurent
111c55a96383497a772a307b346368133960b02ad03Eric Laurent  // WebRtcVad_Assign tests
112c55a96383497a772a307b346368133960b02ad03Eric Laurent  void* tmp_handle = malloc(handle_size_bytes);
113c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(-1, WebRtcVad_Assign(&handle, NULL));
114c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(0, WebRtcVad_Assign(&handle, tmp_handle));
115c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(handle, tmp_handle);
116c55a96383497a772a307b346368133960b02ad03Eric Laurent  free(tmp_handle);
117c55a96383497a772a307b346368133960b02ad03Eric Laurent
118c55a96383497a772a307b346368133960b02ad03Eric Laurent  // WebRtcVad_Create()
119c55a96383497a772a307b346368133960b02ad03Eric Laurent  ASSERT_EQ(0, WebRtcVad_Create(&handle));
120c55a96383497a772a307b346368133960b02ad03Eric Laurent
121c55a96383497a772a307b346368133960b02ad03Eric Laurent  // Not initialized tests
122c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(-1, WebRtcVad_Process(handle, kRates[0], speech, kFrameLengths[0]));
123c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(-1, WebRtcVad_set_mode(handle, kModes[0]));
124c55a96383497a772a307b346368133960b02ad03Eric Laurent
125c55a96383497a772a307b346368133960b02ad03Eric Laurent  // WebRtcVad_Init() test
126c55a96383497a772a307b346368133960b02ad03Eric Laurent  ASSERT_EQ(0, WebRtcVad_Init(handle));
127c55a96383497a772a307b346368133960b02ad03Eric Laurent
128c55a96383497a772a307b346368133960b02ad03Eric Laurent  // WebRtcVad_set_mode() invalid modes tests
129c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(-1, WebRtcVad_set_mode(handle, kModes[0] - 1));
130c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(-1, WebRtcVad_set_mode(handle, kModes[kModesSize - 1] + 1));
131c55a96383497a772a307b346368133960b02ad03Eric Laurent
132c55a96383497a772a307b346368133960b02ad03Eric Laurent  // WebRtcVad_Process() tests
133c55a96383497a772a307b346368133960b02ad03Eric Laurent  // NULL speech pointer
134c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(-1, WebRtcVad_Process(handle, kRates[0], NULL, kFrameLengths[0]));
135c55a96383497a772a307b346368133960b02ad03Eric Laurent  // Invalid sampling rate
136c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(-1, WebRtcVad_Process(handle, 9999, speech, kFrameLengths[0]));
137c55a96383497a772a307b346368133960b02ad03Eric Laurent  // All zeros as input should work
138c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(0, WebRtcVad_Process(handle, kRates[0], zeros, kFrameLengths[0]));
139c55a96383497a772a307b346368133960b02ad03Eric Laurent  for (size_t k = 0; k < kModesSize; k++) {
140c55a96383497a772a307b346368133960b02ad03Eric Laurent    // Test valid modes
141c55a96383497a772a307b346368133960b02ad03Eric Laurent    EXPECT_EQ(0, WebRtcVad_set_mode(handle, kModes[k]));
142c55a96383497a772a307b346368133960b02ad03Eric Laurent    // Loop through sampling rate and frame length combinations
143c55a96383497a772a307b346368133960b02ad03Eric Laurent    for (size_t i = 0; i < kRatesSize; i++) {
144c55a96383497a772a307b346368133960b02ad03Eric Laurent      for (size_t j = 0; j < kFrameLengthsSize; j++) {
145c55a96383497a772a307b346368133960b02ad03Eric Laurent        if (ValidRatesAndFrameLengths(kRates[i], kFrameLengths[j])) {
146c55a96383497a772a307b346368133960b02ad03Eric Laurent          EXPECT_EQ(1, WebRtcVad_Process(handle,
147c55a96383497a772a307b346368133960b02ad03Eric Laurent                                         kRates[i],
148c55a96383497a772a307b346368133960b02ad03Eric Laurent                                         speech,
149c55a96383497a772a307b346368133960b02ad03Eric Laurent                                         kFrameLengths[j]));
150c55a96383497a772a307b346368133960b02ad03Eric Laurent        } else {
151c55a96383497a772a307b346368133960b02ad03Eric Laurent          EXPECT_EQ(-1, WebRtcVad_Process(handle,
152c55a96383497a772a307b346368133960b02ad03Eric Laurent                                          kRates[i],
153c55a96383497a772a307b346368133960b02ad03Eric Laurent                                          speech,
154c55a96383497a772a307b346368133960b02ad03Eric Laurent                                          kFrameLengths[j]));
155c55a96383497a772a307b346368133960b02ad03Eric Laurent        }
156c55a96383497a772a307b346368133960b02ad03Eric Laurent      }
157c55a96383497a772a307b346368133960b02ad03Eric Laurent    }
158c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
159c55a96383497a772a307b346368133960b02ad03Eric Laurent
160c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(0, WebRtcVad_Free(handle));
161c55a96383497a772a307b346368133960b02ad03Eric Laurent}
162c55a96383497a772a307b346368133960b02ad03Eric Laurent
163c55a96383497a772a307b346368133960b02ad03Eric LaurentTEST_F(VadTest, GMMTests) {
164c55a96383497a772a307b346368133960b02ad03Eric Laurent  int16_t delta = 0;
165c55a96383497a772a307b346368133960b02ad03Eric Laurent  // Input value at mean.
166c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(1048576, WebRtcVad_GaussianProbability(0, 0, 128, &delta));
167c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(0, delta);
168c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(1048576, WebRtcVad_GaussianProbability(16, 128, 128, &delta));
169c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(0, delta);
170c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(1048576, WebRtcVad_GaussianProbability(-16, -128, 128, &delta));
171c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(0, delta);
172c55a96383497a772a307b346368133960b02ad03Eric Laurent
173c55a96383497a772a307b346368133960b02ad03Eric Laurent  // Largest possible input to give non-zero probability.
174c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(1024, WebRtcVad_GaussianProbability(59, 0, 128, &delta));
175c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(7552, delta);
176c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(1024, WebRtcVad_GaussianProbability(75, 128, 128, &delta));
177c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(7552, delta);
178c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(1024, WebRtcVad_GaussianProbability(-75, -128, 128, &delta));
179c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(-7552, delta);
180c55a96383497a772a307b346368133960b02ad03Eric Laurent
181c55a96383497a772a307b346368133960b02ad03Eric Laurent  // Too large input, should give zero probability.
182c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(0, WebRtcVad_GaussianProbability(105, 0, 128, &delta));
183c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(13440, delta);
184c55a96383497a772a307b346368133960b02ad03Eric Laurent}
185c55a96383497a772a307b346368133960b02ad03Eric Laurent
186c55a96383497a772a307b346368133960b02ad03Eric LaurentTEST_F(VadTest, SPTests) {
187c55a96383497a772a307b346368133960b02ad03Eric Laurent  VadInstT* handle = (VadInstT*) malloc(sizeof(VadInstT));
188c55a96383497a772a307b346368133960b02ad03Eric Laurent  int16_t zeros[kMaxFrameLength] = { 0 };
189c55a96383497a772a307b346368133960b02ad03Eric Laurent  int32_t state[2] = { 0 };
190c55a96383497a772a307b346368133960b02ad03Eric Laurent  int16_t data_in[kMaxFrameLength];
191c55a96383497a772a307b346368133960b02ad03Eric Laurent  int16_t data_out[kMaxFrameLength];
192c55a96383497a772a307b346368133960b02ad03Eric Laurent
193c55a96383497a772a307b346368133960b02ad03Eric Laurent  const int16_t kReferenceMin[32] = {
194c55a96383497a772a307b346368133960b02ad03Eric Laurent      1600, 720, 509, 512, 532, 552, 570, 588,
195c55a96383497a772a307b346368133960b02ad03Eric Laurent      606, 624, 642, 659, 675, 691, 707, 723,
196c55a96383497a772a307b346368133960b02ad03Eric Laurent      1600, 544, 502, 522, 542, 561, 579, 597,
197c55a96383497a772a307b346368133960b02ad03Eric Laurent      615, 633, 651, 667, 683, 699, 715, 731
198c55a96383497a772a307b346368133960b02ad03Eric Laurent  };
199c55a96383497a772a307b346368133960b02ad03Eric Laurent
200c55a96383497a772a307b346368133960b02ad03Eric Laurent  // Construct a speech signal that will trigger the VAD in all modes. It is
201c55a96383497a772a307b346368133960b02ad03Eric Laurent  // known that (i * i) will wrap around, but that doesn't matter in this case.
202c55a96383497a772a307b346368133960b02ad03Eric Laurent  for (int16_t i = 0; i < kMaxFrameLength; ++i) {
203c55a96383497a772a307b346368133960b02ad03Eric Laurent    data_in[i] = (i * i);
204c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
205c55a96383497a772a307b346368133960b02ad03Eric Laurent  // Input values all zeros, expect all zeros out.
206c55a96383497a772a307b346368133960b02ad03Eric Laurent  WebRtcVad_Downsampling(zeros, data_out, state, (int) kMaxFrameLength);
207c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(0, state[0]);
208c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(0, state[1]);
209c55a96383497a772a307b346368133960b02ad03Eric Laurent  for (int16_t i = 0; i < kMaxFrameLength / 2; ++i) {
210c55a96383497a772a307b346368133960b02ad03Eric Laurent    EXPECT_EQ(0, data_out[i]);
211c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
212c55a96383497a772a307b346368133960b02ad03Eric Laurent  // Make a simple non-zero data test.
213c55a96383497a772a307b346368133960b02ad03Eric Laurent  WebRtcVad_Downsampling(data_in, data_out, state, (int) kMaxFrameLength);
214c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(207, state[0]);
215c55a96383497a772a307b346368133960b02ad03Eric Laurent  EXPECT_EQ(2270, state[1]);
216c55a96383497a772a307b346368133960b02ad03Eric Laurent
217c55a96383497a772a307b346368133960b02ad03Eric Laurent  ASSERT_EQ(0, WebRtcVad_InitCore(handle, 0));
218c55a96383497a772a307b346368133960b02ad03Eric Laurent  for (int16_t i = 0; i < 16; ++i) {
219c55a96383497a772a307b346368133960b02ad03Eric Laurent    int16_t value = 500 * (i + 1);
220c55a96383497a772a307b346368133960b02ad03Eric Laurent    for (int j = 0; j < NUM_CHANNELS; ++j) {
221c55a96383497a772a307b346368133960b02ad03Eric Laurent      // Use values both above and below initialized value.
222c55a96383497a772a307b346368133960b02ad03Eric Laurent      EXPECT_EQ(kReferenceMin[i], WebRtcVad_FindMinimum(handle, value, j));
223c55a96383497a772a307b346368133960b02ad03Eric Laurent      EXPECT_EQ(kReferenceMin[i + 16], WebRtcVad_FindMinimum(handle, 12000, j));
224c55a96383497a772a307b346368133960b02ad03Eric Laurent    }
225c55a96383497a772a307b346368133960b02ad03Eric Laurent    handle->frame_counter++;
226c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
227c55a96383497a772a307b346368133960b02ad03Eric Laurent
228c55a96383497a772a307b346368133960b02ad03Eric Laurent  free(handle);
229c55a96383497a772a307b346368133960b02ad03Eric Laurent}
230c55a96383497a772a307b346368133960b02ad03Eric Laurent
231c55a96383497a772a307b346368133960b02ad03Eric Laurent// TODO(bjornv): Add a process test, run on file.
232c55a96383497a772a307b346368133960b02ad03Eric Laurent
233c55a96383497a772a307b346368133960b02ad03Eric Laurent}  // namespace
234c55a96383497a772a307b346368133960b02ad03Eric Laurent}  // namespace webrtc
235