| OLD | NEW | 
|---|
| 1 /* | 1 /* | 
| 2  *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | 2  *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | 
| 3  * | 3  * | 
| 4  *  Use of this source code is governed by a BSD-style license | 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 | 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 | 6  *  tree. An additional intellectual property rights grant can be found | 
| 7  *  in the file PATENTS.  All contributing project authors may | 7  *  in the file PATENTS.  All contributing project authors may | 
| 8  *  be found in the AUTHORS file in the root of the source tree. | 8  *  be found in the AUTHORS file in the root of the source tree. | 
| 9  */ | 9  */ | 
| 10 | 10 | 
| 11 #include <algorithm> | 11 #include <algorithm> | 
| 12 #include <limits> | 12 #include <limits> | 
| 13 #include <list> | 13 #include <list> | 
| 14 #include <memory> | 14 #include <memory> | 
| 15 #include <numeric> | 15 #include <numeric> | 
| 16 #include <string> | 16 #include <string> | 
| 17 #include <vector> | 17 #include <vector> | 
| 18 | 18 | 
| 19 #include "webrtc/base/arraysize.h" | 19 #include "webrtc/base/arraysize.h" | 
| 20 #include "webrtc/base/criticalsection.h" | 20 #include "webrtc/base/criticalsection.h" | 
| 21 #include "webrtc/base/format_macros.h" | 21 #include "webrtc/base/format_macros.h" | 
| 22 #include "webrtc/base/logging.h" | 22 #include "webrtc/base/logging.h" | 
| 23 #include "webrtc/base/scoped_ref_ptr.h" | 23 #include "webrtc/base/scoped_ref_ptr.h" | 
|  | 24 #include "webrtc/base/timeutils.h" | 
| 24 #include "webrtc/modules/audio_device/audio_device_impl.h" | 25 #include "webrtc/modules/audio_device/audio_device_impl.h" | 
| 25 #include "webrtc/modules/audio_device/include/audio_device.h" | 26 #include "webrtc/modules/audio_device/include/audio_device.h" | 
| 26 #include "webrtc/modules/audio_device/include/mock_audio_transport.h" | 27 #include "webrtc/modules/audio_device/include/mock_audio_transport.h" | 
| 27 #include "webrtc/modules/audio_device/ios/audio_device_ios.h" | 28 #include "webrtc/modules/audio_device/ios/audio_device_ios.h" | 
| 28 #include "webrtc/system_wrappers/include/clock.h" |  | 
| 29 #include "webrtc/system_wrappers/include/event_wrapper.h" | 29 #include "webrtc/system_wrappers/include/event_wrapper.h" | 
| 30 #include "webrtc/system_wrappers/include/sleep.h" | 30 #include "webrtc/system_wrappers/include/sleep.h" | 
| 31 #include "webrtc/test/gmock.h" | 31 #include "webrtc/test/gmock.h" | 
| 32 #include "webrtc/test/gtest.h" | 32 #include "webrtc/test/gtest.h" | 
| 33 #include "webrtc/test/testsupport/fileutils.h" | 33 #include "webrtc/test/testsupport/fileutils.h" | 
| 34 | 34 | 
| 35 using std::cout; | 35 using std::cout; | 
| 36 using std::endl; | 36 using std::endl; | 
| 37 using ::testing::_; | 37 using ::testing::_; | 
| 38 using ::testing::AtLeast; | 38 using ::testing::AtLeast; | 
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 240   size_t write_count_; | 240   size_t write_count_; | 
| 241 }; | 241 }; | 
| 242 | 242 | 
| 243 // Inserts periodic impulses and measures the latency between the time of | 243 // Inserts periodic impulses and measures the latency between the time of | 
| 244 // transmission and time of receiving the same impulse. | 244 // transmission and time of receiving the same impulse. | 
| 245 // Usage requires a special hardware called Audio Loopback Dongle. | 245 // Usage requires a special hardware called Audio Loopback Dongle. | 
| 246 // See http://source.android.com/devices/audio/loopback.html for details. | 246 // See http://source.android.com/devices/audio/loopback.html for details. | 
| 247 class LatencyMeasuringAudioStream : public AudioStreamInterface { | 247 class LatencyMeasuringAudioStream : public AudioStreamInterface { | 
| 248  public: | 248  public: | 
| 249   explicit LatencyMeasuringAudioStream(size_t frames_per_buffer) | 249   explicit LatencyMeasuringAudioStream(size_t frames_per_buffer) | 
| 250       : clock_(Clock::GetRealTimeClock()), | 250       : frames_per_buffer_(frames_per_buffer), | 
| 251         frames_per_buffer_(frames_per_buffer), |  | 
| 252         bytes_per_buffer_(frames_per_buffer_ * sizeof(int16_t)), | 251         bytes_per_buffer_(frames_per_buffer_ * sizeof(int16_t)), | 
| 253         play_count_(0), | 252         play_count_(0), | 
| 254         rec_count_(0), | 253         rec_count_(0), | 
| 255         pulse_time_(0) {} | 254         pulse_time_(0) {} | 
| 256 | 255 | 
| 257   // Insert periodic impulses in first two samples of |destination|. | 256   // Insert periodic impulses in first two samples of |destination|. | 
| 258   void Read(void* destination, size_t num_frames) override { | 257   void Read(void* destination, size_t num_frames) override { | 
| 259     ASSERT_EQ(num_frames, frames_per_buffer_); | 258     ASSERT_EQ(num_frames, frames_per_buffer_); | 
| 260     if (play_count_ == 0) { | 259     if (play_count_ == 0) { | 
| 261       PRINT("["); | 260       PRINT("["); | 
| 262     } | 261     } | 
| 263     play_count_++; | 262     play_count_++; | 
| 264     memset(destination, 0, bytes_per_buffer_); | 263     memset(destination, 0, bytes_per_buffer_); | 
| 265     if (play_count_ % (kNumCallbacksPerSecond / kImpulseFrequencyInHz) == 0) { | 264     if (play_count_ % (kNumCallbacksPerSecond / kImpulseFrequencyInHz) == 0) { | 
| 266       if (pulse_time_ == 0) { | 265       if (pulse_time_ == 0) { | 
| 267         pulse_time_ = clock_->TimeInMilliseconds(); | 266         pulse_time_ = rtc::TimeMillis(); | 
| 268       } | 267       } | 
| 269       PRINT("."); | 268       PRINT("."); | 
| 270       const int16_t impulse = std::numeric_limits<int16_t>::max(); | 269       const int16_t impulse = std::numeric_limits<int16_t>::max(); | 
| 271       int16_t* ptr16 = static_cast<int16_t*>(destination); | 270       int16_t* ptr16 = static_cast<int16_t*>(destination); | 
| 272       for (size_t i = 0; i < 2; ++i) { | 271       for (size_t i = 0; i < 2; ++i) { | 
| 273         ptr16[i] = impulse; | 272         ptr16[i] = impulse; | 
| 274       } | 273       } | 
| 275     } | 274     } | 
| 276   } | 275   } | 
| 277 | 276 | 
| 278   // Detect received impulses in |source|, derive time between transmission and | 277   // Detect received impulses in |source|, derive time between transmission and | 
| 279   // detection and add the calculated delay to list of latencies. | 278   // detection and add the calculated delay to list of latencies. | 
| 280   void Write(const void* source, size_t num_frames) override { | 279   void Write(const void* source, size_t num_frames) override { | 
| 281     ASSERT_EQ(num_frames, frames_per_buffer_); | 280     ASSERT_EQ(num_frames, frames_per_buffer_); | 
| 282     rec_count_++; | 281     rec_count_++; | 
| 283     if (pulse_time_ == 0) { | 282     if (pulse_time_ == 0) { | 
| 284       // Avoid detection of new impulse response until a new impulse has | 283       // Avoid detection of new impulse response until a new impulse has | 
| 285       // been transmitted (sets |pulse_time_| to value larger than zero). | 284       // been transmitted (sets |pulse_time_| to value larger than zero). | 
| 286       return; | 285       return; | 
| 287     } | 286     } | 
| 288     const int16_t* ptr16 = static_cast<const int16_t*>(source); | 287     const int16_t* ptr16 = static_cast<const int16_t*>(source); | 
| 289     std::vector<int16_t> vec(ptr16, ptr16 + num_frames); | 288     std::vector<int16_t> vec(ptr16, ptr16 + num_frames); | 
| 290     // Find max value in the audio buffer. | 289     // Find max value in the audio buffer. | 
| 291     int max = *std::max_element(vec.begin(), vec.end()); | 290     int max = *std::max_element(vec.begin(), vec.end()); | 
| 292     // Find index (element position in vector) of the max element. | 291     // Find index (element position in vector) of the max element. | 
| 293     int index_of_max = | 292     int index_of_max = | 
| 294         std::distance(vec.begin(), std::find(vec.begin(), vec.end(), max)); | 293         std::distance(vec.begin(), std::find(vec.begin(), vec.end(), max)); | 
| 295     if (max > kImpulseThreshold) { | 294     if (max > kImpulseThreshold) { | 
| 296       PRINTD("(%d,%d)", max, index_of_max); | 295       PRINTD("(%d,%d)", max, index_of_max); | 
| 297       int64_t now_time = clock_->TimeInMilliseconds(); | 296       int64_t now_time = rtc::TimeMillis(); | 
| 298       int extra_delay = IndexToMilliseconds(static_cast<double>(index_of_max)); | 297       int extra_delay = IndexToMilliseconds(static_cast<double>(index_of_max)); | 
| 299       PRINTD("[%d]", static_cast<int>(now_time - pulse_time_)); | 298       PRINTD("[%d]", static_cast<int>(now_time - pulse_time_)); | 
| 300       PRINTD("[%d]", extra_delay); | 299       PRINTD("[%d]", extra_delay); | 
| 301       // Total latency is the difference between transmit time and detection | 300       // Total latency is the difference between transmit time and detection | 
| 302       // tome plus the extra delay within the buffer in which we detected the | 301       // tome plus the extra delay within the buffer in which we detected the | 
| 303       // received impulse. It is transmitted at sample 0 but can be received | 302       // received impulse. It is transmitted at sample 0 but can be received | 
| 304       // at sample N where N > 0. The term |extra_delay| accounts for N and it | 303       // at sample N where N > 0. The term |extra_delay| accounts for N and it | 
| 305       // is a value between 0 and 10ms. | 304       // is a value between 0 and 10ms. | 
| 306       latencies_.push_back(now_time - pulse_time_ + extra_delay); | 305       latencies_.push_back(now_time - pulse_time_ + extra_delay); | 
| 307       pulse_time_ = 0; | 306       pulse_time_ = 0; | 
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 341     PRINT("\n"); | 340     PRINT("\n"); | 
| 342     PRINT("%s[min, max, avg]=[%d, %d, %d] ms\n", kTag, min_latency(), | 341     PRINT("%s[min, max, avg]=[%d, %d, %d] ms\n", kTag, min_latency(), | 
| 343           max_latency(), average_latency()); | 342           max_latency(), average_latency()); | 
| 344   } | 343   } | 
| 345 | 344 | 
| 346   int IndexToMilliseconds(double index) const { | 345   int IndexToMilliseconds(double index) const { | 
| 347     return 10.0 * (index / frames_per_buffer_) + 0.5; | 346     return 10.0 * (index / frames_per_buffer_) + 0.5; | 
| 348   } | 347   } | 
| 349 | 348 | 
| 350  private: | 349  private: | 
| 351   Clock* clock_; |  | 
| 352   const size_t frames_per_buffer_; | 350   const size_t frames_per_buffer_; | 
| 353   const size_t bytes_per_buffer_; | 351   const size_t bytes_per_buffer_; | 
| 354   size_t play_count_; | 352   size_t play_count_; | 
| 355   size_t rec_count_; | 353   size_t rec_count_; | 
| 356   int64_t pulse_time_; | 354   int64_t pulse_time_; | 
| 357   std::vector<int> latencies_; | 355   std::vector<int> latencies_; | 
| 358 }; | 356 }; | 
| 359 // Mocks the AudioTransport object and proxies actions for the two callbacks | 357 // Mocks the AudioTransport object and proxies actions for the two callbacks | 
| 360 // (RecordedDataIsAvailable and NeedMorePlayData) to different implementations | 358 // (RecordedDataIsAvailable and NeedMorePlayData) to different implementations | 
| 361 // of AudioStreamInterface. | 359 // of AudioStreamInterface. | 
| (...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 815   StopPlayout(); | 813   StopPlayout(); | 
| 816   StopRecording(); | 814   StopRecording(); | 
| 817   // Verify that the correct number of transmitted impulses are detected. | 815   // Verify that the correct number of transmitted impulses are detected. | 
| 818   EXPECT_EQ(latency_audio_stream->num_latency_values(), | 816   EXPECT_EQ(latency_audio_stream->num_latency_values(), | 
| 819             static_cast<size_t>( | 817             static_cast<size_t>( | 
| 820                 kImpulseFrequencyInHz * kMeasureLatencyTimeInSec - 1)); | 818                 kImpulseFrequencyInHz * kMeasureLatencyTimeInSec - 1)); | 
| 821   latency_audio_stream->PrintResults(); | 819   latency_audio_stream->PrintResults(); | 
| 822 } | 820 } | 
| 823 | 821 | 
| 824 }  // namespace webrtc | 822 }  // namespace webrtc | 
| OLD | NEW | 
|---|