1/*
2 *  Copyright (c) 2013 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 "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
12
13#include <assert.h>
14#include <math.h>
15
16#include <iostream>
17
18#include "testing/gtest/include/gtest/gtest.h"
19#include "webrtc/common_types.h"
20#include "webrtc/engine_configurations.h"
21#include "webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h"
22#include "webrtc/modules/audio_coding/main/test/Channel.h"
23#include "webrtc/modules/audio_coding/main/test/PCMFile.h"
24#include "webrtc/modules/audio_coding/main/test/utility.h"
25#include "webrtc/system_wrappers/interface/event_wrapper.h"
26#include "webrtc/system_wrappers/interface/scoped_ptr.h"
27#include "webrtc/test/testsupport/fileutils.h"
28#include "webrtc/test/testsupport/gtest_disable.h"
29
30namespace webrtc {
31
32namespace {
33
34double FrameRms(AudioFrame& frame) {
35  int samples = frame.num_channels_ * frame.samples_per_channel_;
36  double rms = 0;
37  for (int n = 0; n < samples; ++n)
38    rms += frame.data_[n] * frame.data_[n];
39  rms /= samples;
40  rms = sqrt(rms);
41  return rms;
42}
43
44}
45
46class InitialPlayoutDelayTest : public ::testing::Test {
47 protected:
48  InitialPlayoutDelayTest()
49      : acm_a_(AudioCodingModule::Create(0)),
50        acm_b_(AudioCodingModule::Create(1)),
51        channel_a2b_(NULL) {}
52
53  ~InitialPlayoutDelayTest() {
54    if (channel_a2b_ != NULL) {
55      delete channel_a2b_;
56      channel_a2b_ = NULL;
57    }
58  }
59
60  void SetUp() {
61    ASSERT_TRUE(acm_a_.get() != NULL);
62    ASSERT_TRUE(acm_b_.get() != NULL);
63
64    EXPECT_EQ(0, acm_b_->InitializeReceiver());
65    EXPECT_EQ(0, acm_a_->InitializeReceiver());
66
67    // Register all L16 codecs in receiver.
68    CodecInst codec;
69    const int kFsHz[3] = { 8000, 16000, 32000 };
70    const int kChannels[2] = { 1, 2 };
71    for (int n = 0; n < 3; ++n) {
72      for (int k = 0; k < 2; ++k) {
73        AudioCodingModule::Codec("L16", &codec, kFsHz[n], kChannels[k]);
74        acm_b_->RegisterReceiveCodec(codec);
75      }
76    }
77
78    // Create and connect the channel
79    channel_a2b_ = new Channel;
80    acm_a_->RegisterTransportCallback(channel_a2b_);
81    channel_a2b_->RegisterReceiverACM(acm_b_.get());
82  }
83
84  void NbMono() {
85    CodecInst codec;
86    AudioCodingModule::Codec("L16", &codec, 8000, 1);
87    codec.pacsize = codec.plfreq * 30 / 1000;  // 30 ms packets.
88    Run(codec, 1000);
89  }
90
91  void WbMono() {
92    CodecInst codec;
93    AudioCodingModule::Codec("L16", &codec, 16000, 1);
94    codec.pacsize = codec.plfreq * 30 / 1000;  // 30 ms packets.
95    Run(codec, 1000);
96  }
97
98  void SwbMono() {
99    CodecInst codec;
100    AudioCodingModule::Codec("L16", &codec, 32000, 1);
101    codec.pacsize = codec.plfreq * 10 / 1000;  // 10 ms packets.
102    Run(codec, 400);  // Memory constraints limit the buffer at <500 ms.
103  }
104
105  void NbStereo() {
106    CodecInst codec;
107    AudioCodingModule::Codec("L16", &codec, 8000, 2);
108    codec.pacsize = codec.plfreq * 30 / 1000;  // 30 ms packets.
109    Run(codec, 1000);
110  }
111
112  void WbStereo() {
113    CodecInst codec;
114    AudioCodingModule::Codec("L16", &codec, 16000, 2);
115    codec.pacsize = codec.plfreq * 30 / 1000;  // 30 ms packets.
116    Run(codec, 1000);
117  }
118
119  void SwbStereo() {
120    CodecInst codec;
121    AudioCodingModule::Codec("L16", &codec, 32000, 2);
122    codec.pacsize = codec.plfreq * 10 / 1000;  // 10 ms packets.
123    Run(codec, 400);  // Memory constraints limit the buffer at <500 ms.
124  }
125
126 private:
127  void Run(CodecInst codec, int initial_delay_ms) {
128    AudioFrame in_audio_frame;
129    AudioFrame out_audio_frame;
130    int num_frames = 0;
131    const int kAmp = 10000;
132    in_audio_frame.sample_rate_hz_ = codec.plfreq;
133    in_audio_frame.num_channels_ = codec.channels;
134    in_audio_frame.samples_per_channel_ = codec.plfreq / 100;  // 10 ms.
135    int samples = in_audio_frame.num_channels_ *
136        in_audio_frame.samples_per_channel_;
137    for (int n = 0; n < samples; ++n) {
138      in_audio_frame.data_[n] = kAmp;
139    }
140
141    uint32_t timestamp = 0;
142    double rms = 0;
143    ASSERT_EQ(0, acm_a_->RegisterSendCodec(codec));
144    acm_b_->SetInitialPlayoutDelay(initial_delay_ms);
145    while (rms < kAmp / 2) {
146      in_audio_frame.timestamp_ = timestamp;
147      timestamp += in_audio_frame.samples_per_channel_;
148      ASSERT_EQ(0, acm_a_->Add10MsData(in_audio_frame));
149      ASSERT_LE(0, acm_a_->Process());
150      ASSERT_EQ(0, acm_b_->PlayoutData10Ms(codec.plfreq, &out_audio_frame));
151      rms = FrameRms(out_audio_frame);
152      ++num_frames;
153    }
154
155    ASSERT_GE(num_frames * 10, initial_delay_ms);
156    ASSERT_LE(num_frames * 10, initial_delay_ms + 100);
157  }
158
159  scoped_ptr<AudioCodingModule> acm_a_;
160  scoped_ptr<AudioCodingModule> acm_b_;
161  Channel* channel_a2b_;
162};
163
164TEST_F(InitialPlayoutDelayTest, NbMono) { NbMono(); }
165
166TEST_F(InitialPlayoutDelayTest, WbMono) { WbMono(); }
167
168TEST_F(InitialPlayoutDelayTest, SwbMono) { SwbMono(); }
169
170TEST_F(InitialPlayoutDelayTest, NbStereo) { NbStereo(); }
171
172TEST_F(InitialPlayoutDelayTest, WbStereo) { WbStereo(); }
173
174TEST_F(InitialPlayoutDelayTest, SwbStereo) { SwbStereo(); }
175
176}  // namespace webrtc
177