blob: fb82b91ea105a4daa235ed8420e162aa431a7000 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
xians@webrtc.org20aabbb2012-02-20 09:17:41 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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
pbos@webrtc.org811269d2013-07-11 13:24:38 +000011#include "webrtc/modules/audio_device/audio_device_buffer.h"
andrew@webrtc.org25534502013-09-13 00:02:13 +000012
henrika3f33e2a2016-07-06 00:33:57 -070013#include "webrtc/base/checks.h"
14#include "webrtc/base/logging.h"
Peter Kastingdce40cf2015-08-24 14:52:23 -070015#include "webrtc/base/format_macros.h"
pbos@webrtc.org811269d2013-07-11 13:24:38 +000016#include "webrtc/modules/audio_device/audio_device_config.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010017#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000018
niklase@google.com470e71d2011-07-07 08:21:25 +000019namespace webrtc {
20
andrew@webrtc.org8f940132013-09-11 22:35:00 +000021static const int kHighDelayThresholdMs = 300;
22static const int kLogHighDelayIntervalFrames = 500; // 5 seconds.
23
henrika0fd68012016-07-04 13:01:19 +020024AudioDeviceBuffer::AudioDeviceBuffer()
henrika3f33e2a2016-07-06 00:33:57 -070025 : _critSect(*CriticalSectionWrapper::CreateCriticalSection()),
henrika0fd68012016-07-04 13:01:19 +020026 _critSectCb(*CriticalSectionWrapper::CreateCriticalSection()),
henrika3f33e2a2016-07-06 00:33:57 -070027 _ptrCbAudioTransport(nullptr),
henrika0fd68012016-07-04 13:01:19 +020028 _recSampleRate(0),
29 _playSampleRate(0),
30 _recChannels(0),
31 _playChannels(0),
32 _recChannel(AudioDeviceModule::kChannelBoth),
33 _recBytesPerSample(0),
34 _playBytesPerSample(0),
35 _recSamples(0),
36 _recSize(0),
37 _playSamples(0),
38 _playSize(0),
39 _recFile(*FileWrapper::Create()),
40 _playFile(*FileWrapper::Create()),
41 _currentMicLevel(0),
42 _newMicLevel(0),
43 _typingStatus(false),
44 _playDelayMS(0),
45 _recDelayMS(0),
46 _clockDrift(0),
47 // Set to the interval in order to log on the first occurrence.
48 high_delay_counter_(kLogHighDelayIntervalFrames) {
henrika3f33e2a2016-07-06 00:33:57 -070049 LOG(INFO) << "AudioDeviceBuffer::ctor";
henrika0fd68012016-07-04 13:01:19 +020050 memset(_recBuffer, 0, kMaxBufferSizeBytes);
51 memset(_playBuffer, 0, kMaxBufferSizeBytes);
niklase@google.com470e71d2011-07-07 08:21:25 +000052}
53
henrika0fd68012016-07-04 13:01:19 +020054AudioDeviceBuffer::~AudioDeviceBuffer() {
henrika3f33e2a2016-07-06 00:33:57 -070055 LOG(INFO) << "AudioDeviceBuffer::~dtor";
henrika0fd68012016-07-04 13:01:19 +020056 {
57 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +000058
henrika0fd68012016-07-04 13:01:19 +020059 _recFile.Flush();
60 _recFile.CloseFile();
61 delete &_recFile;
niklase@google.com470e71d2011-07-07 08:21:25 +000062
henrika0fd68012016-07-04 13:01:19 +020063 _playFile.Flush();
64 _playFile.CloseFile();
65 delete &_playFile;
66 }
niklase@google.com470e71d2011-07-07 08:21:25 +000067
henrika0fd68012016-07-04 13:01:19 +020068 delete &_critSect;
69 delete &_critSectCb;
niklase@google.com470e71d2011-07-07 08:21:25 +000070}
71
henrika0fd68012016-07-04 13:01:19 +020072int32_t AudioDeviceBuffer::RegisterAudioCallback(
73 AudioTransport* audioCallback) {
henrika3f33e2a2016-07-06 00:33:57 -070074 LOG(INFO) << __FUNCTION__;
henrika0fd68012016-07-04 13:01:19 +020075 CriticalSectionScoped lock(&_critSectCb);
76 _ptrCbAudioTransport = audioCallback;
henrika0fd68012016-07-04 13:01:19 +020077 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +000078}
79
henrika0fd68012016-07-04 13:01:19 +020080int32_t AudioDeviceBuffer::InitPlayout() {
henrika3f33e2a2016-07-06 00:33:57 -070081 LOG(INFO) << __FUNCTION__;
henrika0fd68012016-07-04 13:01:19 +020082 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +000083}
84
henrika0fd68012016-07-04 13:01:19 +020085int32_t AudioDeviceBuffer::InitRecording() {
henrika3f33e2a2016-07-06 00:33:57 -070086 LOG(INFO) << __FUNCTION__;
henrika0fd68012016-07-04 13:01:19 +020087 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +000088}
89
henrika0fd68012016-07-04 13:01:19 +020090int32_t AudioDeviceBuffer::SetRecordingSampleRate(uint32_t fsHz) {
henrika3f33e2a2016-07-06 00:33:57 -070091 LOG(INFO) << "SetRecordingSampleRate(" << fsHz << ")";
henrika0fd68012016-07-04 13:01:19 +020092 CriticalSectionScoped lock(&_critSect);
93 _recSampleRate = fsHz;
94 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +000095}
96
henrika0fd68012016-07-04 13:01:19 +020097int32_t AudioDeviceBuffer::SetPlayoutSampleRate(uint32_t fsHz) {
henrika3f33e2a2016-07-06 00:33:57 -070098 LOG(INFO) << "SetPlayoutSampleRate(" << fsHz << ")";
henrika0fd68012016-07-04 13:01:19 +020099 CriticalSectionScoped lock(&_critSect);
100 _playSampleRate = fsHz;
101 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000102}
103
henrika0fd68012016-07-04 13:01:19 +0200104int32_t AudioDeviceBuffer::RecordingSampleRate() const {
105 return _recSampleRate;
niklase@google.com470e71d2011-07-07 08:21:25 +0000106}
107
henrika0fd68012016-07-04 13:01:19 +0200108int32_t AudioDeviceBuffer::PlayoutSampleRate() const {
109 return _playSampleRate;
niklase@google.com470e71d2011-07-07 08:21:25 +0000110}
111
henrika0fd68012016-07-04 13:01:19 +0200112int32_t AudioDeviceBuffer::SetRecordingChannels(size_t channels) {
113 CriticalSectionScoped lock(&_critSect);
114 _recChannels = channels;
115 _recBytesPerSample =
116 2 * channels; // 16 bits per sample in mono, 32 bits in stereo
117 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000118}
119
henrika0fd68012016-07-04 13:01:19 +0200120int32_t AudioDeviceBuffer::SetPlayoutChannels(size_t channels) {
121 CriticalSectionScoped lock(&_critSect);
122 _playChannels = channels;
123 // 16 bits per sample in mono, 32 bits in stereo
124 _playBytesPerSample = 2 * channels;
125 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000126}
127
henrika0fd68012016-07-04 13:01:19 +0200128int32_t AudioDeviceBuffer::SetRecordingChannel(
129 const AudioDeviceModule::ChannelType channel) {
130 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000131
henrika0fd68012016-07-04 13:01:19 +0200132 if (_recChannels == 1) {
133 return -1;
134 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000135
henrika0fd68012016-07-04 13:01:19 +0200136 if (channel == AudioDeviceModule::kChannelBoth) {
137 // two bytes per channel
138 _recBytesPerSample = 4;
139 } else {
140 // only utilize one out of two possible channels (left or right)
141 _recBytesPerSample = 2;
142 }
143 _recChannel = channel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000144
henrika0fd68012016-07-04 13:01:19 +0200145 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000146}
147
henrika0fd68012016-07-04 13:01:19 +0200148int32_t AudioDeviceBuffer::RecordingChannel(
149 AudioDeviceModule::ChannelType& channel) const {
150 channel = _recChannel;
151 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000152}
153
henrika0fd68012016-07-04 13:01:19 +0200154size_t AudioDeviceBuffer::RecordingChannels() const {
155 return _recChannels;
niklase@google.com470e71d2011-07-07 08:21:25 +0000156}
157
henrika0fd68012016-07-04 13:01:19 +0200158size_t AudioDeviceBuffer::PlayoutChannels() const {
159 return _playChannels;
niklase@google.com470e71d2011-07-07 08:21:25 +0000160}
161
henrika0fd68012016-07-04 13:01:19 +0200162int32_t AudioDeviceBuffer::SetCurrentMicLevel(uint32_t level) {
163 _currentMicLevel = level;
164 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000165}
166
henrika0fd68012016-07-04 13:01:19 +0200167int32_t AudioDeviceBuffer::SetTypingStatus(bool typingStatus) {
168 _typingStatus = typingStatus;
169 return 0;
niklas.enbom@webrtc.org3be565b2013-05-07 21:04:24 +0000170}
171
henrika0fd68012016-07-04 13:01:19 +0200172uint32_t AudioDeviceBuffer::NewMicLevel() const {
173 return _newMicLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000174}
175
henrika0fd68012016-07-04 13:01:19 +0200176void AudioDeviceBuffer::SetVQEData(int playDelayMs,
177 int recDelayMs,
andrew@webrtc.org5eb997a2013-09-12 01:01:42 +0000178 int clockDrift) {
andrew@webrtc.org8f940132013-09-11 22:35:00 +0000179 if (high_delay_counter_ < kLogHighDelayIntervalFrames) {
180 ++high_delay_counter_;
181 } else {
182 if (playDelayMs + recDelayMs > kHighDelayThresholdMs) {
183 high_delay_counter_ = 0;
184 LOG(LS_WARNING) << "High audio device delay reported (render="
185 << playDelayMs << " ms, capture=" << recDelayMs << " ms)";
niklase@google.com470e71d2011-07-07 08:21:25 +0000186 }
andrew@webrtc.org8f940132013-09-11 22:35:00 +0000187 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000188
andrew@webrtc.org8f940132013-09-11 22:35:00 +0000189 _playDelayMS = playDelayMs;
190 _recDelayMS = recDelayMs;
191 _clockDrift = clockDrift;
niklase@google.com470e71d2011-07-07 08:21:25 +0000192}
193
pbos@webrtc.org25509882013-04-09 10:30:35 +0000194int32_t AudioDeviceBuffer::StartInputFileRecording(
henrika0fd68012016-07-04 13:01:19 +0200195 const char fileName[kAdmMaxFileNameSize]) {
henrika0fd68012016-07-04 13:01:19 +0200196 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000197
henrika0fd68012016-07-04 13:01:19 +0200198 _recFile.Flush();
199 _recFile.CloseFile();
niklase@google.com470e71d2011-07-07 08:21:25 +0000200
henrika0fd68012016-07-04 13:01:19 +0200201 return _recFile.OpenFile(fileName, false) ? 0 : -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000202}
203
henrika0fd68012016-07-04 13:01:19 +0200204int32_t AudioDeviceBuffer::StopInputFileRecording() {
henrika0fd68012016-07-04 13:01:19 +0200205 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000206
henrika0fd68012016-07-04 13:01:19 +0200207 _recFile.Flush();
208 _recFile.CloseFile();
niklase@google.com470e71d2011-07-07 08:21:25 +0000209
henrika0fd68012016-07-04 13:01:19 +0200210 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000211}
212
pbos@webrtc.org25509882013-04-09 10:30:35 +0000213int32_t AudioDeviceBuffer::StartOutputFileRecording(
henrika0fd68012016-07-04 13:01:19 +0200214 const char fileName[kAdmMaxFileNameSize]) {
henrika0fd68012016-07-04 13:01:19 +0200215 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000216
henrika0fd68012016-07-04 13:01:19 +0200217 _playFile.Flush();
218 _playFile.CloseFile();
niklase@google.com470e71d2011-07-07 08:21:25 +0000219
henrika0fd68012016-07-04 13:01:19 +0200220 return _playFile.OpenFile(fileName, false) ? 0 : -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000221}
222
henrika0fd68012016-07-04 13:01:19 +0200223int32_t AudioDeviceBuffer::StopOutputFileRecording() {
henrika0fd68012016-07-04 13:01:19 +0200224 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000225
henrika0fd68012016-07-04 13:01:19 +0200226 _playFile.Flush();
227 _playFile.CloseFile();
niklase@google.com470e71d2011-07-07 08:21:25 +0000228
henrika0fd68012016-07-04 13:01:19 +0200229 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000230}
231
pbos@webrtc.org25509882013-04-09 10:30:35 +0000232int32_t AudioDeviceBuffer::SetRecordedBuffer(const void* audioBuffer,
henrika0fd68012016-07-04 13:01:19 +0200233 size_t nSamples) {
234 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000235
henrika0fd68012016-07-04 13:01:19 +0200236 if (_recBytesPerSample == 0) {
237 assert(false);
238 return -1;
239 }
240
241 _recSamples = nSamples;
242 _recSize = _recBytesPerSample * nSamples; // {2,4}*nSamples
243 if (_recSize > kMaxBufferSizeBytes) {
244 assert(false);
245 return -1;
246 }
247
248 if (_recChannel == AudioDeviceModule::kChannelBoth) {
249 // (default) copy the complete input buffer to the local buffer
250 memcpy(&_recBuffer[0], audioBuffer, _recSize);
251 } else {
252 int16_t* ptr16In = (int16_t*)audioBuffer;
253 int16_t* ptr16Out = (int16_t*)&_recBuffer[0];
254
255 if (AudioDeviceModule::kChannelRight == _recChannel) {
256 ptr16In++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000257 }
258
henrika0fd68012016-07-04 13:01:19 +0200259 // exctract left or right channel from input buffer to the local buffer
260 for (size_t i = 0; i < _recSamples; i++) {
261 *ptr16Out = *ptr16In;
262 ptr16Out++;
263 ptr16In++;
264 ptr16In++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000265 }
henrika0fd68012016-07-04 13:01:19 +0200266 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000267
henrika0fd68012016-07-04 13:01:19 +0200268 if (_recFile.is_open()) {
269 // write to binary file in mono or stereo (interleaved)
270 _recFile.Write(&_recBuffer[0], _recSize);
271 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000272
henrika0fd68012016-07-04 13:01:19 +0200273 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000274}
275
henrika0fd68012016-07-04 13:01:19 +0200276int32_t AudioDeviceBuffer::DeliverRecordedData() {
277 CriticalSectionScoped lock(&_critSectCb);
henrika0fd68012016-07-04 13:01:19 +0200278 // Ensure that user has initialized all essential members
279 if ((_recSampleRate == 0) || (_recSamples == 0) ||
280 (_recBytesPerSample == 0) || (_recChannels == 0)) {
henrika3f33e2a2016-07-06 00:33:57 -0700281 RTC_NOTREACHED();
henrika0fd68012016-07-04 13:01:19 +0200282 return -1;
283 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000284
henrika3f33e2a2016-07-06 00:33:57 -0700285 if (!_ptrCbAudioTransport) {
286 LOG(LS_WARNING) << "Invalid audio transport";
niklase@google.com470e71d2011-07-07 08:21:25 +0000287 return 0;
henrika0fd68012016-07-04 13:01:19 +0200288 }
289
290 int32_t res(0);
291 uint32_t newMicLevel(0);
292 uint32_t totalDelayMS = _playDelayMS + _recDelayMS;
henrika0fd68012016-07-04 13:01:19 +0200293 res = _ptrCbAudioTransport->RecordedDataIsAvailable(
294 &_recBuffer[0], _recSamples, _recBytesPerSample, _recChannels,
295 _recSampleRate, totalDelayMS, _clockDrift, _currentMicLevel,
296 _typingStatus, newMicLevel);
297 if (res != -1) {
298 _newMicLevel = newMicLevel;
299 }
300
301 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000302}
303
henrika0fd68012016-07-04 13:01:19 +0200304int32_t AudioDeviceBuffer::RequestPlayoutData(size_t nSamples) {
305 uint32_t playSampleRate = 0;
306 size_t playBytesPerSample = 0;
307 size_t playChannels = 0;
henrika3f33e2a2016-07-06 00:33:57 -0700308
309 // TOOD(henrika): improve bad locking model and make it more clear that only
310 // 10ms buffer sizes is supported in WebRTC.
henrika0fd68012016-07-04 13:01:19 +0200311 {
312 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000313
henrika0fd68012016-07-04 13:01:19 +0200314 // Store copies under lock and use copies hereafter to avoid race with
315 // setter methods.
316 playSampleRate = _playSampleRate;
317 playBytesPerSample = _playBytesPerSample;
318 playChannels = _playChannels;
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000319
henrika0fd68012016-07-04 13:01:19 +0200320 // Ensure that user has initialized all essential members
321 if ((playBytesPerSample == 0) || (playChannels == 0) ||
322 (playSampleRate == 0)) {
henrika3f33e2a2016-07-06 00:33:57 -0700323 RTC_NOTREACHED();
henrika0fd68012016-07-04 13:01:19 +0200324 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000325 }
326
henrika0fd68012016-07-04 13:01:19 +0200327 _playSamples = nSamples;
328 _playSize = playBytesPerSample * nSamples; // {2,4}*nSamples
henrika3f33e2a2016-07-06 00:33:57 -0700329 RTC_CHECK_LE(_playSize, kMaxBufferSizeBytes);
330 RTC_CHECK_EQ(nSamples, _playSamples);
henrika0fd68012016-07-04 13:01:19 +0200331 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000332
henrika0fd68012016-07-04 13:01:19 +0200333 size_t nSamplesOut(0);
334
335 CriticalSectionScoped lock(&_critSectCb);
336
henrika3f33e2a2016-07-06 00:33:57 -0700337 // It is currently supported to start playout without a valid audio
338 // transport object. Leads to warning and silence.
339 if (!_ptrCbAudioTransport) {
340 LOG(LS_WARNING) << "Invalid audio transport";
henrika0fd68012016-07-04 13:01:19 +0200341 return 0;
342 }
343
henrika3f33e2a2016-07-06 00:33:57 -0700344 uint32_t res(0);
345 int64_t elapsed_time_ms = -1;
346 int64_t ntp_time_ms = -1;
347 res = _ptrCbAudioTransport->NeedMorePlayData(
348 _playSamples, playBytesPerSample, playChannels, playSampleRate,
349 &_playBuffer[0], nSamplesOut, &elapsed_time_ms, &ntp_time_ms);
350 if (res != 0) {
351 LOG(LS_ERROR) << "NeedMorePlayData() failed";
henrika0fd68012016-07-04 13:01:19 +0200352 }
353
354 return static_cast<int32_t>(nSamplesOut);
niklase@google.com470e71d2011-07-07 08:21:25 +0000355}
356
henrika0fd68012016-07-04 13:01:19 +0200357int32_t AudioDeviceBuffer::GetPlayoutData(void* audioBuffer) {
358 CriticalSectionScoped lock(&_critSect);
henrika3f33e2a2016-07-06 00:33:57 -0700359 RTC_CHECK_LE(_playSize, kMaxBufferSizeBytes);
punyabrata@webrtc.orgc9801462011-11-29 18:49:54 +0000360
henrika0fd68012016-07-04 13:01:19 +0200361 memcpy(audioBuffer, &_playBuffer[0], _playSize);
niklase@google.com470e71d2011-07-07 08:21:25 +0000362
henrika0fd68012016-07-04 13:01:19 +0200363 if (_playFile.is_open()) {
364 // write to binary file in mono or stereo (interleaved)
365 _playFile.Write(&_playBuffer[0], _playSize);
366 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000367
henrika0fd68012016-07-04 13:01:19 +0200368 return static_cast<int32_t>(_playSamples);
niklase@google.com470e71d2011-07-07 08:21:25 +0000369}
370
niklase@google.com470e71d2011-07-07 08:21:25 +0000371} // namespace webrtc