blob: 62d1961396310cbae21824e5ea0c5e528b6f92b4 [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"
12#include "webrtc/modules/audio_device/audio_device_config.h"
13#include "webrtc/modules/audio_device/audio_device_utility.h"
14#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
andrew@webrtc.org8f940132013-09-11 22:35:00 +000015#include "webrtc/system_wrappers/interface/logging.h"
pbos@webrtc.org811269d2013-07-11 13:24:38 +000016#include "webrtc/system_wrappers/interface/trace.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000017
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000018#include <assert.h>
niklase@google.com470e71d2011-07-07 08:21:25 +000019#include <stdlib.h>
20#include <string.h>
niklase@google.com470e71d2011-07-07 08:21:25 +000021
pbos@webrtc.org811269d2013-07-11 13:24:38 +000022#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000023
24namespace webrtc {
25
andrew@webrtc.org8f940132013-09-11 22:35:00 +000026static const int kHighDelayThresholdMs = 300;
27static const int kLogHighDelayIntervalFrames = 500; // 5 seconds.
28
niklase@google.com470e71d2011-07-07 08:21:25 +000029// ----------------------------------------------------------------------------
30// ctor
31// ----------------------------------------------------------------------------
32
33AudioDeviceBuffer::AudioDeviceBuffer() :
34 _id(-1),
35 _critSect(*CriticalSectionWrapper::CreateCriticalSection()),
36 _critSectCb(*CriticalSectionWrapper::CreateCriticalSection()),
37 _ptrCbAudioTransport(NULL),
38 _recSampleRate(0),
39 _playSampleRate(0),
40 _recChannels(0),
41 _playChannels(0),
42 _recChannel(AudioDeviceModule::kChannelBoth),
43 _recBytesPerSample(0),
44 _playBytesPerSample(0),
45 _recSamples(0),
niklase@google.com470e71d2011-07-07 08:21:25 +000046 _recSize(0),
xians@google.com88bd4402011-08-04 15:33:30 +000047 _playSamples(0),
niklase@google.com470e71d2011-07-07 08:21:25 +000048 _playSize(0),
49 _recFile(*FileWrapper::Create()),
50 _playFile(*FileWrapper::Create()),
niklase@google.com470e71d2011-07-07 08:21:25 +000051 _currentMicLevel(0),
xians@google.com88bd4402011-08-04 15:33:30 +000052 _newMicLevel(0),
niklas.enbom@webrtc.org3be565b2013-05-07 21:04:24 +000053 _typingStatus(false),
niklase@google.com470e71d2011-07-07 08:21:25 +000054 _playDelayMS(0),
55 _recDelayMS(0),
andrew@webrtc.org8f940132013-09-11 22:35:00 +000056 _clockDrift(0),
57 // Set to the interval in order to log on the first occurrence.
58 high_delay_counter_(kLogHighDelayIntervalFrames) {
niklase@google.com470e71d2011-07-07 08:21:25 +000059 // valid ID will be set later by SetId, use -1 for now
60 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s created", __FUNCTION__);
xians@webrtc.orgeff3c892011-12-06 10:02:56 +000061 memset(_recBuffer, 0, kMaxBufferSizeBytes);
62 memset(_playBuffer, 0, kMaxBufferSizeBytes);
niklase@google.com470e71d2011-07-07 08:21:25 +000063}
64
65// ----------------------------------------------------------------------------
66// dtor
67// ----------------------------------------------------------------------------
68
69AudioDeviceBuffer::~AudioDeviceBuffer()
70{
71 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s destroyed", __FUNCTION__);
72 {
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +000073 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +000074
75 _recFile.Flush();
76 _recFile.CloseFile();
77 delete &_recFile;
78
79 _playFile.Flush();
80 _playFile.CloseFile();
81 delete &_playFile;
niklase@google.com470e71d2011-07-07 08:21:25 +000082 }
83
84 delete &_critSect;
85 delete &_critSectCb;
86}
87
88// ----------------------------------------------------------------------------
89// SetId
90// ----------------------------------------------------------------------------
91
pbos@webrtc.org25509882013-04-09 10:30:35 +000092void AudioDeviceBuffer::SetId(uint32_t id)
niklase@google.com470e71d2011-07-07 08:21:25 +000093{
94 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, id, "AudioDeviceBuffer::SetId(id=%d)", id);
95 _id = id;
96}
97
98// ----------------------------------------------------------------------------
99// RegisterAudioCallback
100// ----------------------------------------------------------------------------
101
pbos@webrtc.org25509882013-04-09 10:30:35 +0000102int32_t AudioDeviceBuffer::RegisterAudioCallback(AudioTransport* audioCallback)
niklase@google.com470e71d2011-07-07 08:21:25 +0000103{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000104 CriticalSectionScoped lock(&_critSectCb);
niklase@google.com470e71d2011-07-07 08:21:25 +0000105 _ptrCbAudioTransport = audioCallback;
106
107 return 0;
108}
109
110// ----------------------------------------------------------------------------
111// InitPlayout
112// ----------------------------------------------------------------------------
113
pbos@webrtc.org25509882013-04-09 10:30:35 +0000114int32_t AudioDeviceBuffer::InitPlayout()
niklase@google.com470e71d2011-07-07 08:21:25 +0000115{
116 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +0000117 return 0;
118}
119
120// ----------------------------------------------------------------------------
121// InitRecording
122// ----------------------------------------------------------------------------
123
pbos@webrtc.org25509882013-04-09 10:30:35 +0000124int32_t AudioDeviceBuffer::InitRecording()
niklase@google.com470e71d2011-07-07 08:21:25 +0000125{
126 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +0000127 return 0;
128}
129
130// ----------------------------------------------------------------------------
131// SetRecordingSampleRate
132// ----------------------------------------------------------------------------
133
pbos@webrtc.org25509882013-04-09 10:30:35 +0000134int32_t AudioDeviceBuffer::SetRecordingSampleRate(uint32_t fsHz)
niklase@google.com470e71d2011-07-07 08:21:25 +0000135{
136 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "AudioDeviceBuffer::SetRecordingSampleRate(fsHz=%u)", fsHz);
137
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000138 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000139 _recSampleRate = fsHz;
140 return 0;
141}
142
143// ----------------------------------------------------------------------------
144// SetPlayoutSampleRate
145// ----------------------------------------------------------------------------
146
pbos@webrtc.org25509882013-04-09 10:30:35 +0000147int32_t AudioDeviceBuffer::SetPlayoutSampleRate(uint32_t fsHz)
niklase@google.com470e71d2011-07-07 08:21:25 +0000148{
149 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "AudioDeviceBuffer::SetPlayoutSampleRate(fsHz=%u)", fsHz);
150
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000151 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000152 _playSampleRate = fsHz;
153 return 0;
154}
155
156// ----------------------------------------------------------------------------
157// RecordingSampleRate
158// ----------------------------------------------------------------------------
159
pbos@webrtc.org25509882013-04-09 10:30:35 +0000160int32_t AudioDeviceBuffer::RecordingSampleRate() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000161{
162 return _recSampleRate;
163}
164
165// ----------------------------------------------------------------------------
166// PlayoutSampleRate
167// ----------------------------------------------------------------------------
168
pbos@webrtc.org25509882013-04-09 10:30:35 +0000169int32_t AudioDeviceBuffer::PlayoutSampleRate() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000170{
171 return _playSampleRate;
172}
173
174// ----------------------------------------------------------------------------
175// SetRecordingChannels
176// ----------------------------------------------------------------------------
177
pbos@webrtc.org25509882013-04-09 10:30:35 +0000178int32_t AudioDeviceBuffer::SetRecordingChannels(uint8_t channels)
niklase@google.com470e71d2011-07-07 08:21:25 +0000179{
180 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "AudioDeviceBuffer::SetRecordingChannels(channels=%u)", channels);
181
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000182 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000183 _recChannels = channels;
184 _recBytesPerSample = 2*channels; // 16 bits per sample in mono, 32 bits in stereo
185 return 0;
186}
187
188// ----------------------------------------------------------------------------
189// SetPlayoutChannels
190// ----------------------------------------------------------------------------
191
pbos@webrtc.org25509882013-04-09 10:30:35 +0000192int32_t AudioDeviceBuffer::SetPlayoutChannels(uint8_t channels)
niklase@google.com470e71d2011-07-07 08:21:25 +0000193{
194 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "AudioDeviceBuffer::SetPlayoutChannels(channels=%u)", channels);
195
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000196 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000197 _playChannels = channels;
198 // 16 bits per sample in mono, 32 bits in stereo
199 _playBytesPerSample = 2*channels;
200 return 0;
201}
202
203// ----------------------------------------------------------------------------
204// SetRecordingChannel
205//
206// Select which channel to use while recording.
207// This API requires that stereo is enabled.
208//
209// Note that, the nChannel parameter in RecordedDataIsAvailable will be
210// set to 2 even for kChannelLeft and kChannelRight. However, nBytesPerSample
211// will be 2 instead of 4 four these cases.
212// ----------------------------------------------------------------------------
213
pbos@webrtc.org25509882013-04-09 10:30:35 +0000214int32_t AudioDeviceBuffer::SetRecordingChannel(const AudioDeviceModule::ChannelType channel)
niklase@google.com470e71d2011-07-07 08:21:25 +0000215{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000216 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000217
218 if (_recChannels == 1)
219 {
220 return -1;
221 }
222
223 if (channel == AudioDeviceModule::kChannelBoth)
224 {
225 // two bytes per channel
226 _recBytesPerSample = 4;
227 }
228 else
229 {
230 // only utilize one out of two possible channels (left or right)
231 _recBytesPerSample = 2;
232 }
233 _recChannel = channel;
234
235 return 0;
236}
237
238// ----------------------------------------------------------------------------
239// RecordingChannel
240// ----------------------------------------------------------------------------
241
pbos@webrtc.org25509882013-04-09 10:30:35 +0000242int32_t AudioDeviceBuffer::RecordingChannel(AudioDeviceModule::ChannelType& channel) const
niklase@google.com470e71d2011-07-07 08:21:25 +0000243{
244 channel = _recChannel;
245 return 0;
246}
247
248// ----------------------------------------------------------------------------
249// RecordingChannels
250// ----------------------------------------------------------------------------
251
pbos@webrtc.org25509882013-04-09 10:30:35 +0000252uint8_t AudioDeviceBuffer::RecordingChannels() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000253{
254 return _recChannels;
255}
256
257// ----------------------------------------------------------------------------
258// PlayoutChannels
259// ----------------------------------------------------------------------------
260
pbos@webrtc.org25509882013-04-09 10:30:35 +0000261uint8_t AudioDeviceBuffer::PlayoutChannels() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000262{
263 return _playChannels;
264}
265
266// ----------------------------------------------------------------------------
267// SetCurrentMicLevel
268// ----------------------------------------------------------------------------
269
pbos@webrtc.org25509882013-04-09 10:30:35 +0000270int32_t AudioDeviceBuffer::SetCurrentMicLevel(uint32_t level)
niklase@google.com470e71d2011-07-07 08:21:25 +0000271{
272 _currentMicLevel = level;
273 return 0;
274}
275
niklas.enbom@webrtc.org3be565b2013-05-07 21:04:24 +0000276int32_t AudioDeviceBuffer::SetTypingStatus(bool typingStatus)
277{
278 _typingStatus = typingStatus;
279 return 0;
280}
281
niklase@google.com470e71d2011-07-07 08:21:25 +0000282// ----------------------------------------------------------------------------
283// NewMicLevel
284// ----------------------------------------------------------------------------
285
pbos@webrtc.org25509882013-04-09 10:30:35 +0000286uint32_t AudioDeviceBuffer::NewMicLevel() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000287{
288 return _newMicLevel;
289}
290
291// ----------------------------------------------------------------------------
292// SetVQEData
293// ----------------------------------------------------------------------------
294
andrew@webrtc.org5eb997a2013-09-12 01:01:42 +0000295void AudioDeviceBuffer::SetVQEData(int playDelayMs, int recDelayMs,
296 int clockDrift) {
andrew@webrtc.org8f940132013-09-11 22:35:00 +0000297 if (high_delay_counter_ < kLogHighDelayIntervalFrames) {
298 ++high_delay_counter_;
299 } else {
300 if (playDelayMs + recDelayMs > kHighDelayThresholdMs) {
301 high_delay_counter_ = 0;
302 LOG(LS_WARNING) << "High audio device delay reported (render="
303 << playDelayMs << " ms, capture=" << recDelayMs << " ms)";
niklase@google.com470e71d2011-07-07 08:21:25 +0000304 }
andrew@webrtc.org8f940132013-09-11 22:35:00 +0000305 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000306
andrew@webrtc.org8f940132013-09-11 22:35:00 +0000307 _playDelayMS = playDelayMs;
308 _recDelayMS = recDelayMs;
309 _clockDrift = clockDrift;
niklase@google.com470e71d2011-07-07 08:21:25 +0000310}
311
312// ----------------------------------------------------------------------------
313// StartInputFileRecording
314// ----------------------------------------------------------------------------
315
pbos@webrtc.org25509882013-04-09 10:30:35 +0000316int32_t AudioDeviceBuffer::StartInputFileRecording(
leozwang@webrtc.org28f39132012-03-01 18:01:48 +0000317 const char fileName[kAdmMaxFileNameSize])
niklase@google.com470e71d2011-07-07 08:21:25 +0000318{
319 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
320
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000321 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000322
323 _recFile.Flush();
324 _recFile.CloseFile();
325
326 return (_recFile.OpenFile(fileName, false, false, false));
327}
328
329// ----------------------------------------------------------------------------
330// StopInputFileRecording
331// ----------------------------------------------------------------------------
332
pbos@webrtc.org25509882013-04-09 10:30:35 +0000333int32_t AudioDeviceBuffer::StopInputFileRecording()
niklase@google.com470e71d2011-07-07 08:21:25 +0000334{
335 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
336
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000337 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000338
339 _recFile.Flush();
340 _recFile.CloseFile();
341
342 return 0;
343}
344
345// ----------------------------------------------------------------------------
346// StartOutputFileRecording
347// ----------------------------------------------------------------------------
348
pbos@webrtc.org25509882013-04-09 10:30:35 +0000349int32_t AudioDeviceBuffer::StartOutputFileRecording(
leozwang@webrtc.org28f39132012-03-01 18:01:48 +0000350 const char fileName[kAdmMaxFileNameSize])
niklase@google.com470e71d2011-07-07 08:21:25 +0000351{
352 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
353
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000354 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000355
356 _playFile.Flush();
357 _playFile.CloseFile();
358
359 return (_playFile.OpenFile(fileName, false, false, false));
360}
361
362// ----------------------------------------------------------------------------
363// StopOutputFileRecording
364// ----------------------------------------------------------------------------
365
pbos@webrtc.org25509882013-04-09 10:30:35 +0000366int32_t AudioDeviceBuffer::StopOutputFileRecording()
niklase@google.com470e71d2011-07-07 08:21:25 +0000367{
368 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
369
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000370 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000371
372 _playFile.Flush();
373 _playFile.CloseFile();
374
375 return 0;
376}
377
378// ----------------------------------------------------------------------------
379// SetRecordedBuffer
380//
381// Store recorded audio buffer in local memory ready for the actual
382// "delivery" using a callback.
383//
384// This method can also parse out left or right channel from a stereo
385// input signal, i.e., emulate mono.
386//
387// Examples:
388//
389// 16-bit,48kHz mono, 10ms => nSamples=480 => _recSize=2*480=960 bytes
braveyao@webrtc.org0a185222011-11-25 02:45:39 +0000390// 16-bit,48kHz stereo,10ms => nSamples=480 => _recSize=4*480=1920 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000391// ----------------------------------------------------------------------------
392
pbos@webrtc.org25509882013-04-09 10:30:35 +0000393int32_t AudioDeviceBuffer::SetRecordedBuffer(const void* audioBuffer,
394 uint32_t nSamples)
niklase@google.com470e71d2011-07-07 08:21:25 +0000395{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000396 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000397
398 if (_recBytesPerSample == 0)
399 {
400 assert(false);
401 return -1;
402 }
403
404 _recSamples = nSamples;
405 _recSize = _recBytesPerSample*nSamples; // {2,4}*nSamples
braveyao@webrtc.org0a185222011-11-25 02:45:39 +0000406 if (_recSize > kMaxBufferSizeBytes)
niklase@google.com470e71d2011-07-07 08:21:25 +0000407 {
408 assert(false);
409 return -1;
410 }
411
412 if (nSamples != _recSamples)
413 {
414 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "invalid number of recorded samples (%d)", nSamples);
415 return -1;
416 }
417
418 if (_recChannel == AudioDeviceModule::kChannelBoth)
419 {
420 // (default) copy the complete input buffer to the local buffer
421 memcpy(&_recBuffer[0], audioBuffer, _recSize);
422 }
423 else
424 {
pbos@webrtc.org25509882013-04-09 10:30:35 +0000425 int16_t* ptr16In = (int16_t*)audioBuffer;
426 int16_t* ptr16Out = (int16_t*)&_recBuffer[0];
niklase@google.com470e71d2011-07-07 08:21:25 +0000427
428 if (AudioDeviceModule::kChannelRight == _recChannel)
429 {
430 ptr16In++;
431 }
432
433 // exctract left or right channel from input buffer to the local buffer
pbos@webrtc.org25509882013-04-09 10:30:35 +0000434 for (uint32_t i = 0; i < _recSamples; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +0000435 {
436 *ptr16Out = *ptr16In;
437 ptr16Out++;
438 ptr16In++;
439 ptr16In++;
440 }
441 }
442
443 if (_recFile.Open())
444 {
445 // write to binary file in mono or stereo (interleaved)
446 _recFile.Write(&_recBuffer[0], _recSize);
447 }
448
449 return 0;
450}
451
452// ----------------------------------------------------------------------------
453// DeliverRecordedData
454// ----------------------------------------------------------------------------
455
pbos@webrtc.org25509882013-04-09 10:30:35 +0000456int32_t AudioDeviceBuffer::DeliverRecordedData()
niklase@google.com470e71d2011-07-07 08:21:25 +0000457{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000458 CriticalSectionScoped lock(&_critSectCb);
niklase@google.com470e71d2011-07-07 08:21:25 +0000459
460 // Ensure that user has initialized all essential members
461 if ((_recSampleRate == 0) ||
462 (_recSamples == 0) ||
463 (_recBytesPerSample == 0) ||
464 (_recChannels == 0))
465 {
466 assert(false);
467 return -1;
468 }
469
470 if (_ptrCbAudioTransport == NULL)
471 {
472 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "failed to deliver recorded data (AudioTransport does not exist)");
473 return 0;
474 }
475
pbos@webrtc.org25509882013-04-09 10:30:35 +0000476 int32_t res(0);
477 uint32_t newMicLevel(0);
478 uint32_t totalDelayMS = _playDelayMS +_recDelayMS;
niklase@google.com470e71d2011-07-07 08:21:25 +0000479
niklase@google.com470e71d2011-07-07 08:21:25 +0000480 res = _ptrCbAudioTransport->RecordedDataIsAvailable(&_recBuffer[0],
481 _recSamples,
482 _recBytesPerSample,
483 _recChannels,
484 _recSampleRate,
485 totalDelayMS,
486 _clockDrift,
487 _currentMicLevel,
niklas.enbom@webrtc.org3be565b2013-05-07 21:04:24 +0000488 _typingStatus,
niklase@google.com470e71d2011-07-07 08:21:25 +0000489 newMicLevel);
490 if (res != -1)
491 {
492 _newMicLevel = newMicLevel;
493 }
494
495 return 0;
496}
497
498// ----------------------------------------------------------------------------
499// RequestPlayoutData
500// ----------------------------------------------------------------------------
501
pbos@webrtc.org25509882013-04-09 10:30:35 +0000502int32_t AudioDeviceBuffer::RequestPlayoutData(uint32_t nSamples)
niklase@google.com470e71d2011-07-07 08:21:25 +0000503{
pbos@webrtc.org25509882013-04-09 10:30:35 +0000504 uint32_t playSampleRate = 0;
505 uint8_t playBytesPerSample = 0;
506 uint8_t playChannels = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000507 {
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000508 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000509
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000510 // Store copies under lock and use copies hereafter to avoid race with
511 // setter methods.
512 playSampleRate = _playSampleRate;
513 playBytesPerSample = _playBytesPerSample;
514 playChannels = _playChannels;
515
niklase@google.com470e71d2011-07-07 08:21:25 +0000516 // Ensure that user has initialized all essential members
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000517 if ((playBytesPerSample == 0) ||
518 (playChannels == 0) ||
519 (playSampleRate == 0))
niklase@google.com470e71d2011-07-07 08:21:25 +0000520 {
521 assert(false);
522 return -1;
523 }
524
525 _playSamples = nSamples;
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000526 _playSize = playBytesPerSample * nSamples; // {2,4}*nSamples
braveyao@webrtc.org0a185222011-11-25 02:45:39 +0000527 if (_playSize > kMaxBufferSizeBytes)
niklase@google.com470e71d2011-07-07 08:21:25 +0000528 {
529 assert(false);
530 return -1;
531 }
532
533 if (nSamples != _playSamples)
534 {
535 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "invalid number of samples to be played out (%d)", nSamples);
536 return -1;
537 }
538 }
539
pbos@webrtc.org25509882013-04-09 10:30:35 +0000540 uint32_t nSamplesOut(0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000541
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000542 CriticalSectionScoped lock(&_critSectCb);
niklase@google.com470e71d2011-07-07 08:21:25 +0000543
544 if (_ptrCbAudioTransport == NULL)
545 {
546 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "failed to feed data to playout (AudioTransport does not exist)");
547 return 0;
548 }
549
550 if (_ptrCbAudioTransport)
551 {
pbos@webrtc.org25509882013-04-09 10:30:35 +0000552 uint32_t res(0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000553
554 res = _ptrCbAudioTransport->NeedMorePlayData(_playSamples,
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000555 playBytesPerSample,
556 playChannels,
557 playSampleRate,
niklase@google.com470e71d2011-07-07 08:21:25 +0000558 &_playBuffer[0],
559 nSamplesOut);
560 if (res != 0)
561 {
562 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "NeedMorePlayData() failed");
563 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000564 }
565
566 return nSamplesOut;
567}
568
569// ----------------------------------------------------------------------------
570// GetPlayoutData
571// ----------------------------------------------------------------------------
572
pbos@webrtc.org25509882013-04-09 10:30:35 +0000573int32_t AudioDeviceBuffer::GetPlayoutData(void* audioBuffer)
niklase@google.com470e71d2011-07-07 08:21:25 +0000574{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000575 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000576
punyabrata@webrtc.orgc9801462011-11-29 18:49:54 +0000577 if (_playSize > kMaxBufferSizeBytes)
578 {
579 WEBRTC_TRACE(kTraceError, kTraceUtility, _id, "_playSize %i exceeds "
580 "kMaxBufferSizeBytes in AudioDeviceBuffer::GetPlayoutData", _playSize);
581 assert(false);
leozwang@webrtc.org28f39132012-03-01 18:01:48 +0000582 return -1;
583 }
punyabrata@webrtc.orgc9801462011-11-29 18:49:54 +0000584
niklase@google.com470e71d2011-07-07 08:21:25 +0000585 memcpy(audioBuffer, &_playBuffer[0], _playSize);
586
587 if (_playFile.Open())
588 {
589 // write to binary file in mono or stereo (interleaved)
590 _playFile.Write(&_playBuffer[0], _playSize);
591 }
592
593 return _playSamples;
594}
595
niklase@google.com470e71d2011-07-07 08:21:25 +0000596} // namespace webrtc