OLD | NEW |
| (Empty) |
1 /* | |
2 * libjingle | |
3 * Copyright 2004 Google Inc. | |
4 * | |
5 * Redistribution and use in source and binary forms, with or without | |
6 * modification, are permitted provided that the following conditions are met: | |
7 * | |
8 * 1. Redistributions of source code must retain the above copyright notice, | |
9 * this list of conditions and the following disclaimer. | |
10 * 2. Redistributions in binary form must reproduce the above copyright notice, | |
11 * this list of conditions and the following disclaimer in the documentation | |
12 * and/or other materials provided with the distribution. | |
13 * 3. The name of the author may not be used to endorse or promote products | |
14 * derived from this software without specific prior written permission. | |
15 * | |
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED | |
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO | |
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
26 */ | |
27 | |
28 #include "talk/session/media/audiomonitor.h" | |
29 #include "talk/session/media/currentspeakermonitor.h" | |
30 #include "webrtc/base/gunit.h" | |
31 #include "webrtc/base/thread.h" | |
32 | |
33 namespace cricket { | |
34 | |
35 static const uint32_t kSsrc1 = 1001; | |
36 static const uint32_t kSsrc2 = 1002; | |
37 static const uint32_t kMinTimeBetweenSwitches = 10; | |
38 // Due to limited system clock resolution, the CurrentSpeakerMonitor may | |
39 // actually require more or less time between switches than that specified | |
40 // in the call to set_min_time_between_switches. To be safe, we sleep for | |
41 // 90 ms more than the min time between switches before checking for a switch. | |
42 // I am assuming system clocks do not have a coarser resolution than 90 ms. | |
43 static const uint32_t kSleepTimeBetweenSwitches = 100; | |
44 | |
45 class CurrentSpeakerMonitorTest : public testing::Test, | |
46 public sigslot::has_slots<> { | |
47 public: | |
48 CurrentSpeakerMonitorTest() { | |
49 monitor_ = new CurrentSpeakerMonitor(&source_); | |
50 // Shrink the minimum time betweeen switches to 10 ms so we don't have to | |
51 // slow down our tests. | |
52 monitor_->set_min_time_between_switches(kMinTimeBetweenSwitches); | |
53 monitor_->SignalUpdate.connect(this, &CurrentSpeakerMonitorTest::OnUpdate); | |
54 current_speaker_ = 0; | |
55 num_changes_ = 0; | |
56 monitor_->Start(); | |
57 } | |
58 | |
59 ~CurrentSpeakerMonitorTest() { | |
60 delete monitor_; | |
61 } | |
62 | |
63 void SignalAudioMonitor(const AudioInfo& info) { | |
64 source_.SignalAudioMonitor(&source_, info); | |
65 } | |
66 | |
67 protected: | |
68 AudioSourceContext source_; | |
69 CurrentSpeakerMonitor* monitor_; | |
70 int num_changes_; | |
71 uint32_t current_speaker_; | |
72 | |
73 void OnUpdate(CurrentSpeakerMonitor* monitor, uint32_t current_speaker) { | |
74 current_speaker_ = current_speaker; | |
75 num_changes_++; | |
76 } | |
77 }; | |
78 | |
79 static void InitAudioInfo(AudioInfo* info, int input_level, int output_level) { | |
80 info->input_level = input_level; | |
81 info->output_level = output_level; | |
82 } | |
83 | |
84 TEST_F(CurrentSpeakerMonitorTest, NoActiveStreams) { | |
85 AudioInfo info; | |
86 InitAudioInfo(&info, 0, 0); | |
87 SignalAudioMonitor(info); | |
88 | |
89 EXPECT_EQ(current_speaker_, 0U); | |
90 EXPECT_EQ(num_changes_, 0); | |
91 } | |
92 | |
93 TEST_F(CurrentSpeakerMonitorTest, MultipleActiveStreams) { | |
94 AudioInfo info; | |
95 InitAudioInfo(&info, 0, 0); | |
96 | |
97 info.active_streams.push_back(std::make_pair(kSsrc1, 3)); | |
98 info.active_streams.push_back(std::make_pair(kSsrc2, 7)); | |
99 SignalAudioMonitor(info); | |
100 | |
101 // No speaker recognized because the initial sample is treated as possibly | |
102 // just noise and disregarded. | |
103 EXPECT_EQ(current_speaker_, 0U); | |
104 EXPECT_EQ(num_changes_, 0); | |
105 | |
106 info.active_streams.push_back(std::make_pair(kSsrc1, 3)); | |
107 info.active_streams.push_back(std::make_pair(kSsrc2, 7)); | |
108 SignalAudioMonitor(info); | |
109 | |
110 EXPECT_EQ(current_speaker_, kSsrc2); | |
111 EXPECT_EQ(num_changes_, 1); | |
112 } | |
113 | |
114 // See: https://code.google.com/p/webrtc/issues/detail?id=2409 | |
115 TEST_F(CurrentSpeakerMonitorTest, DISABLED_RapidSpeakerChange) { | |
116 AudioInfo info; | |
117 InitAudioInfo(&info, 0, 0); | |
118 | |
119 info.active_streams.push_back(std::make_pair(kSsrc1, 3)); | |
120 info.active_streams.push_back(std::make_pair(kSsrc2, 7)); | |
121 SignalAudioMonitor(info); | |
122 | |
123 EXPECT_EQ(current_speaker_, 0U); | |
124 EXPECT_EQ(num_changes_, 0); | |
125 | |
126 info.active_streams.push_back(std::make_pair(kSsrc1, 3)); | |
127 info.active_streams.push_back(std::make_pair(kSsrc2, 7)); | |
128 SignalAudioMonitor(info); | |
129 | |
130 EXPECT_EQ(current_speaker_, kSsrc2); | |
131 EXPECT_EQ(num_changes_, 1); | |
132 | |
133 info.active_streams.push_back(std::make_pair(kSsrc1, 9)); | |
134 info.active_streams.push_back(std::make_pair(kSsrc2, 1)); | |
135 SignalAudioMonitor(info); | |
136 | |
137 // We expect no speaker change because of the rapid change. | |
138 EXPECT_EQ(current_speaker_, kSsrc2); | |
139 EXPECT_EQ(num_changes_, 1); | |
140 } | |
141 | |
142 TEST_F(CurrentSpeakerMonitorTest, SpeakerChange) { | |
143 AudioInfo info; | |
144 InitAudioInfo(&info, 0, 0); | |
145 | |
146 info.active_streams.push_back(std::make_pair(kSsrc1, 3)); | |
147 info.active_streams.push_back(std::make_pair(kSsrc2, 7)); | |
148 SignalAudioMonitor(info); | |
149 | |
150 EXPECT_EQ(current_speaker_, 0U); | |
151 EXPECT_EQ(num_changes_, 0); | |
152 | |
153 info.active_streams.push_back(std::make_pair(kSsrc1, 3)); | |
154 info.active_streams.push_back(std::make_pair(kSsrc2, 7)); | |
155 SignalAudioMonitor(info); | |
156 | |
157 EXPECT_EQ(current_speaker_, kSsrc2); | |
158 EXPECT_EQ(num_changes_, 1); | |
159 | |
160 // Wait so the changes don't come so rapidly. | |
161 rtc::Thread::SleepMs(kSleepTimeBetweenSwitches); | |
162 | |
163 info.active_streams.push_back(std::make_pair(kSsrc1, 9)); | |
164 info.active_streams.push_back(std::make_pair(kSsrc2, 1)); | |
165 SignalAudioMonitor(info); | |
166 | |
167 EXPECT_EQ(current_speaker_, kSsrc1); | |
168 EXPECT_EQ(num_changes_, 2); | |
169 } | |
170 | |
171 TEST_F(CurrentSpeakerMonitorTest, InterwordSilence) { | |
172 AudioInfo info; | |
173 InitAudioInfo(&info, 0, 0); | |
174 | |
175 info.active_streams.push_back(std::make_pair(kSsrc1, 3)); | |
176 info.active_streams.push_back(std::make_pair(kSsrc2, 7)); | |
177 SignalAudioMonitor(info); | |
178 | |
179 EXPECT_EQ(current_speaker_, 0U); | |
180 EXPECT_EQ(num_changes_, 0); | |
181 | |
182 info.active_streams.push_back(std::make_pair(kSsrc1, 3)); | |
183 info.active_streams.push_back(std::make_pair(kSsrc2, 7)); | |
184 SignalAudioMonitor(info); | |
185 | |
186 EXPECT_EQ(current_speaker_, kSsrc2); | |
187 EXPECT_EQ(num_changes_, 1); | |
188 | |
189 info.active_streams.push_back(std::make_pair(kSsrc1, 3)); | |
190 info.active_streams.push_back(std::make_pair(kSsrc2, 7)); | |
191 SignalAudioMonitor(info); | |
192 | |
193 EXPECT_EQ(current_speaker_, kSsrc2); | |
194 EXPECT_EQ(num_changes_, 1); | |
195 | |
196 // Wait so the changes don't come so rapidly. | |
197 rtc::Thread::SleepMs(kSleepTimeBetweenSwitches); | |
198 | |
199 info.active_streams.push_back(std::make_pair(kSsrc1, 3)); | |
200 info.active_streams.push_back(std::make_pair(kSsrc2, 0)); | |
201 SignalAudioMonitor(info); | |
202 | |
203 // Current speaker shouldn't have changed because we treat this as an inter- | |
204 // word silence. | |
205 EXPECT_EQ(current_speaker_, kSsrc2); | |
206 EXPECT_EQ(num_changes_, 1); | |
207 | |
208 info.active_streams.push_back(std::make_pair(kSsrc1, 3)); | |
209 info.active_streams.push_back(std::make_pair(kSsrc2, 0)); | |
210 SignalAudioMonitor(info); | |
211 | |
212 // Current speaker shouldn't have changed because we treat this as an inter- | |
213 // word silence. | |
214 EXPECT_EQ(current_speaker_, kSsrc2); | |
215 EXPECT_EQ(num_changes_, 1); | |
216 | |
217 info.active_streams.push_back(std::make_pair(kSsrc1, 3)); | |
218 info.active_streams.push_back(std::make_pair(kSsrc2, 0)); | |
219 SignalAudioMonitor(info); | |
220 | |
221 // At this point, we should have concluded that SSRC2 stopped speaking. | |
222 EXPECT_EQ(current_speaker_, kSsrc1); | |
223 EXPECT_EQ(num_changes_, 2); | |
224 } | |
225 | |
226 } // namespace cricket | |
OLD | NEW |