1e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org/* 2e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 3e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org * 4e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org * Use of this source code is governed by a BSD-style license 5e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org * that can be found in the LICENSE file in the root of the source 6e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org * tree. An additional intellectual property rights grant can be found 7e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org * in the file PATENTS. All contributing project authors may 8e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org */ 10e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org 11e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org#include "webrtc/test/fake_audio_device.h" 12e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org 13e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org#include <algorithm> 14e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org 15e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org#include "testing/gtest/include/gtest/gtest.h" 16e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org#include "webrtc/modules/media_file/source/media_file_utility.h" 17e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org#include "webrtc/system_wrappers/interface/clock.h" 18e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" 19e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org#include "webrtc/system_wrappers/interface/event_wrapper.h" 20e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org#include "webrtc/system_wrappers/interface/file_wrapper.h" 21e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org#include "webrtc/system_wrappers/interface/thread_wrapper.h" 22e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org 23e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.orgnamespace webrtc { 24e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.orgnamespace test { 25e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org 26e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.orgFakeAudioDevice::FakeAudioDevice(Clock* clock, const std::string& filename) 27e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org : audio_callback_(NULL), 28e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org capturing_(false), 29e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org captured_audio_(), 30e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org playout_buffer_(), 31e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org last_playout_ms_(-1), 32e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org clock_(clock), 33e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org tick_(EventWrapper::Create()), 34e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org lock_(CriticalSectionWrapper::CreateCriticalSection()), 35e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org file_utility_(new ModuleFileUtility(0)), 36e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org input_stream_(FileWrapper::Create()) { 37e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org memset(captured_audio_, 0, sizeof(captured_audio_)); 38e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org memset(playout_buffer_, 0, sizeof(playout_buffer_)); 39e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org // Open audio input file as read-only and looping. 40e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org EXPECT_EQ(0, input_stream_->OpenFile(filename.c_str(), true, true)) 41e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org << filename; 42e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org} 43e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org 44e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.orgFakeAudioDevice::~FakeAudioDevice() { 45e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org Stop(); 46e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org 47e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org if (thread_.get() != NULL) 48e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org thread_->Stop(); 49e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org} 50e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org 51e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.orgint32_t FakeAudioDevice::Init() { 52e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org CriticalSectionScoped cs(lock_.get()); 53e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org if (file_utility_->InitPCMReading(*input_stream_.get()) != 0) 54e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org return -1; 55e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org 56e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org if (!tick_->StartTimer(true, 10)) 57e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org return -1; 58e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org thread_.reset(ThreadWrapper::CreateThread( 59e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org FakeAudioDevice::Run, this, webrtc::kHighPriority, "FakeAudioDevice")); 60e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org if (thread_.get() == NULL) 61e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org return -1; 62e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org unsigned int thread_id; 63e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org if (!thread_->Start(thread_id)) { 64e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org thread_.reset(); 65e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org return -1; 66e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org } 67e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org return 0; 68e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org} 69e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org 70e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.orgint32_t FakeAudioDevice::RegisterAudioCallback(AudioTransport* callback) { 71e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org CriticalSectionScoped cs(lock_.get()); 72e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org audio_callback_ = callback; 73e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org return 0; 74e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org} 75e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org 76e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.orgbool FakeAudioDevice::Playing() const { 77e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org CriticalSectionScoped cs(lock_.get()); 78e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org return capturing_; 79e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org} 80e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org 81e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.orgint32_t FakeAudioDevice::PlayoutDelay(uint16_t* delay_ms) const { 82e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org *delay_ms = 0; 83e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org return 0; 84e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org} 85e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org 86e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.orgbool FakeAudioDevice::Recording() const { 87e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org CriticalSectionScoped cs(lock_.get()); 88e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org return capturing_; 89e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org} 90e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org 91e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.orgbool FakeAudioDevice::Run(void* obj) { 92e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org static_cast<FakeAudioDevice*>(obj)->CaptureAudio(); 93e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org return true; 94e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org} 95e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org 96e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.orgvoid FakeAudioDevice::CaptureAudio() { 97e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org { 98e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org CriticalSectionScoped cs(lock_.get()); 99e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org if (capturing_) { 100e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org int bytes_read = file_utility_->ReadPCMData( 101e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org *input_stream_.get(), captured_audio_, kBufferSizeBytes); 102e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org if (bytes_read <= 0) 103e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org return; 104e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org int num_samples = bytes_read / 2; // 2 bytes per sample. 105e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org uint32_t new_mic_level; 106e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org EXPECT_EQ(0, 107e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org audio_callback_->RecordedDataIsAvailable(captured_audio_, 108e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org num_samples, 109e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org 2, 110e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org 1, 111e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org kFrequencyHz, 112e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org 0, 113e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org 0, 114e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org 0, 115e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org false, 116e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org new_mic_level)); 117e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org uint32_t samples_needed = kFrequencyHz / 100; 118e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org int64_t now_ms = clock_->TimeInMilliseconds(); 119e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org uint32_t time_since_last_playout_ms = now_ms - last_playout_ms_; 120e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org if (last_playout_ms_ > 0 && time_since_last_playout_ms > 0) 121e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org samples_needed = std::min(kFrequencyHz / time_since_last_playout_ms, 122e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org kBufferSizeBytes / 2); 123e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org uint32_t samples_out = 0; 12481f8df9af96c6b4bf43234f2a0162146a5da6112wu@webrtc.org int64_t elapsed_time_ms = -1; 12581f8df9af96c6b4bf43234f2a0162146a5da6112wu@webrtc.org int64_t ntp_time_ms = -1; 126e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org EXPECT_EQ(0, 127e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org audio_callback_->NeedMorePlayData(samples_needed, 128e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org 2, 129e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org 1, 130e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org kFrequencyHz, 131e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org playout_buffer_, 13222f69bd27abc89979460df6d01de8685cb058aabwu@webrtc.org samples_out, 13381f8df9af96c6b4bf43234f2a0162146a5da6112wu@webrtc.org &elapsed_time_ms, 13422f69bd27abc89979460df6d01de8685cb058aabwu@webrtc.org &ntp_time_ms)); 135e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org } 136e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org } 137e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org tick_->Wait(WEBRTC_EVENT_INFINITE); 138e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org} 139e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org 140e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.orgvoid FakeAudioDevice::Start() { 141e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org CriticalSectionScoped cs(lock_.get()); 142e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org capturing_ = true; 143e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org} 144e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org 145e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.orgvoid FakeAudioDevice::Stop() { 146e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org CriticalSectionScoped cs(lock_.get()); 147e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org capturing_ = false; 148e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org} 149e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org} // namespace test 150e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org} // namespace webrtc 151