Home | History | Annotate | Download | only in audio_device
      1 /*
      2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
      3  *
      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 
     11 #include "webrtc/modules/audio_device/audio_device_buffer.h"
     12 
     13 #include <assert.h>
     14 #include <string.h>
     15 
     16 #include "webrtc/base/format_macros.h"
     17 #include "webrtc/modules/audio_device/audio_device_config.h"
     18 #include "webrtc/system_wrappers/include/critical_section_wrapper.h"
     19 #include "webrtc/system_wrappers/include/logging.h"
     20 #include "webrtc/system_wrappers/include/trace.h"
     21 
     22 namespace webrtc {
     23 
     24 static const int kHighDelayThresholdMs = 300;
     25 static const int kLogHighDelayIntervalFrames = 500;  // 5 seconds.
     26 
     27 // ----------------------------------------------------------------------------
     28 //  ctor
     29 // ----------------------------------------------------------------------------
     30 
     31 AudioDeviceBuffer::AudioDeviceBuffer() :
     32     _id(-1),
     33     _critSect(*CriticalSectionWrapper::CreateCriticalSection()),
     34     _critSectCb(*CriticalSectionWrapper::CreateCriticalSection()),
     35     _ptrCbAudioTransport(NULL),
     36     _recSampleRate(0),
     37     _playSampleRate(0),
     38     _recChannels(0),
     39     _playChannels(0),
     40     _recChannel(AudioDeviceModule::kChannelBoth),
     41     _recBytesPerSample(0),
     42     _playBytesPerSample(0),
     43     _recSamples(0),
     44     _recSize(0),
     45     _playSamples(0),
     46     _playSize(0),
     47     _recFile(*FileWrapper::Create()),
     48     _playFile(*FileWrapper::Create()),
     49     _currentMicLevel(0),
     50     _newMicLevel(0),
     51     _typingStatus(false),
     52     _playDelayMS(0),
     53     _recDelayMS(0),
     54     _clockDrift(0),
     55     // Set to the interval in order to log on the first occurrence.
     56     high_delay_counter_(kLogHighDelayIntervalFrames) {
     57     // valid ID will be set later by SetId, use -1 for now
     58     WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s created", __FUNCTION__);
     59     memset(_recBuffer, 0, kMaxBufferSizeBytes);
     60     memset(_playBuffer, 0, kMaxBufferSizeBytes);
     61 }
     62 
     63 // ----------------------------------------------------------------------------
     64 //  dtor
     65 // ----------------------------------------------------------------------------
     66 
     67 AudioDeviceBuffer::~AudioDeviceBuffer()
     68 {
     69     WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s destroyed", __FUNCTION__);
     70     {
     71         CriticalSectionScoped lock(&_critSect);
     72 
     73         _recFile.Flush();
     74         _recFile.CloseFile();
     75         delete &_recFile;
     76 
     77         _playFile.Flush();
     78         _playFile.CloseFile();
     79         delete &_playFile;
     80     }
     81 
     82     delete &_critSect;
     83     delete &_critSectCb;
     84 }
     85 
     86 // ----------------------------------------------------------------------------
     87 //  SetId
     88 // ----------------------------------------------------------------------------
     89 
     90 void AudioDeviceBuffer::SetId(uint32_t id)
     91 {
     92     WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, id, "AudioDeviceBuffer::SetId(id=%d)", id);
     93     _id = id;
     94 }
     95 
     96 // ----------------------------------------------------------------------------
     97 //  RegisterAudioCallback
     98 // ----------------------------------------------------------------------------
     99 
    100 int32_t AudioDeviceBuffer::RegisterAudioCallback(AudioTransport* audioCallback)
    101 {
    102     CriticalSectionScoped lock(&_critSectCb);
    103     _ptrCbAudioTransport = audioCallback;
    104 
    105     return 0;
    106 }
    107 
    108 // ----------------------------------------------------------------------------
    109 //  InitPlayout
    110 // ----------------------------------------------------------------------------
    111 
    112 int32_t AudioDeviceBuffer::InitPlayout()
    113 {
    114     WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
    115     return 0;
    116 }
    117 
    118 // ----------------------------------------------------------------------------
    119 //  InitRecording
    120 // ----------------------------------------------------------------------------
    121 
    122 int32_t AudioDeviceBuffer::InitRecording()
    123 {
    124     WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
    125     return 0;
    126 }
    127 
    128 // ----------------------------------------------------------------------------
    129 //  SetRecordingSampleRate
    130 // ----------------------------------------------------------------------------
    131 
    132 int32_t AudioDeviceBuffer::SetRecordingSampleRate(uint32_t fsHz)
    133 {
    134     CriticalSectionScoped lock(&_critSect);
    135     _recSampleRate = fsHz;
    136     return 0;
    137 }
    138 
    139 // ----------------------------------------------------------------------------
    140 //  SetPlayoutSampleRate
    141 // ----------------------------------------------------------------------------
    142 
    143 int32_t AudioDeviceBuffer::SetPlayoutSampleRate(uint32_t fsHz)
    144 {
    145     CriticalSectionScoped lock(&_critSect);
    146     _playSampleRate = fsHz;
    147     return 0;
    148 }
    149 
    150 // ----------------------------------------------------------------------------
    151 //  RecordingSampleRate
    152 // ----------------------------------------------------------------------------
    153 
    154 int32_t AudioDeviceBuffer::RecordingSampleRate() const
    155 {
    156     return _recSampleRate;
    157 }
    158 
    159 // ----------------------------------------------------------------------------
    160 //  PlayoutSampleRate
    161 // ----------------------------------------------------------------------------
    162 
    163 int32_t AudioDeviceBuffer::PlayoutSampleRate() const
    164 {
    165     return _playSampleRate;
    166 }
    167 
    168 // ----------------------------------------------------------------------------
    169 //  SetRecordingChannels
    170 // ----------------------------------------------------------------------------
    171 
    172 int32_t AudioDeviceBuffer::SetRecordingChannels(size_t channels)
    173 {
    174     CriticalSectionScoped lock(&_critSect);
    175     _recChannels = channels;
    176     _recBytesPerSample = 2*channels;  // 16 bits per sample in mono, 32 bits in stereo
    177     return 0;
    178 }
    179 
    180 // ----------------------------------------------------------------------------
    181 //  SetPlayoutChannels
    182 // ----------------------------------------------------------------------------
    183 
    184 int32_t AudioDeviceBuffer::SetPlayoutChannels(size_t channels)
    185 {
    186     CriticalSectionScoped lock(&_critSect);
    187     _playChannels = channels;
    188     // 16 bits per sample in mono, 32 bits in stereo
    189     _playBytesPerSample = 2*channels;
    190     return 0;
    191 }
    192 
    193 // ----------------------------------------------------------------------------
    194 //  SetRecordingChannel
    195 //
    196 //  Select which channel to use while recording.
    197 //  This API requires that stereo is enabled.
    198 //
    199 //  Note that, the nChannel parameter in RecordedDataIsAvailable will be
    200 //  set to 2 even for kChannelLeft and kChannelRight. However, nBytesPerSample
    201 //  will be 2 instead of 4 four these cases.
    202 // ----------------------------------------------------------------------------
    203 
    204 int32_t AudioDeviceBuffer::SetRecordingChannel(const AudioDeviceModule::ChannelType channel)
    205 {
    206     CriticalSectionScoped lock(&_critSect);
    207 
    208     if (_recChannels == 1)
    209     {
    210         return -1;
    211     }
    212 
    213     if (channel == AudioDeviceModule::kChannelBoth)
    214     {
    215         // two bytes per channel
    216         _recBytesPerSample = 4;
    217     }
    218     else
    219     {
    220         // only utilize one out of two possible channels (left or right)
    221         _recBytesPerSample = 2;
    222     }
    223     _recChannel = channel;
    224 
    225     return 0;
    226 }
    227 
    228 // ----------------------------------------------------------------------------
    229 //  RecordingChannel
    230 // ----------------------------------------------------------------------------
    231 
    232 int32_t AudioDeviceBuffer::RecordingChannel(AudioDeviceModule::ChannelType& channel) const
    233 {
    234     channel = _recChannel;
    235     return 0;
    236 }
    237 
    238 // ----------------------------------------------------------------------------
    239 //  RecordingChannels
    240 // ----------------------------------------------------------------------------
    241 
    242 size_t AudioDeviceBuffer::RecordingChannels() const
    243 {
    244     return _recChannels;
    245 }
    246 
    247 // ----------------------------------------------------------------------------
    248 //  PlayoutChannels
    249 // ----------------------------------------------------------------------------
    250 
    251 size_t AudioDeviceBuffer::PlayoutChannels() const
    252 {
    253     return _playChannels;
    254 }
    255 
    256 // ----------------------------------------------------------------------------
    257 //  SetCurrentMicLevel
    258 // ----------------------------------------------------------------------------
    259 
    260 int32_t AudioDeviceBuffer::SetCurrentMicLevel(uint32_t level)
    261 {
    262     _currentMicLevel = level;
    263     return 0;
    264 }
    265 
    266 int32_t AudioDeviceBuffer::SetTypingStatus(bool typingStatus)
    267 {
    268     _typingStatus = typingStatus;
    269     return 0;
    270 }
    271 
    272 // ----------------------------------------------------------------------------
    273 //  NewMicLevel
    274 // ----------------------------------------------------------------------------
    275 
    276 uint32_t AudioDeviceBuffer::NewMicLevel() const
    277 {
    278     return _newMicLevel;
    279 }
    280 
    281 // ----------------------------------------------------------------------------
    282 //  SetVQEData
    283 // ----------------------------------------------------------------------------
    284 
    285 void AudioDeviceBuffer::SetVQEData(int playDelayMs, int recDelayMs,
    286                                    int clockDrift) {
    287   if (high_delay_counter_ < kLogHighDelayIntervalFrames) {
    288     ++high_delay_counter_;
    289   } else {
    290     if (playDelayMs + recDelayMs > kHighDelayThresholdMs) {
    291       high_delay_counter_ = 0;
    292       LOG(LS_WARNING) << "High audio device delay reported (render="
    293                       << playDelayMs << " ms, capture=" << recDelayMs << " ms)";
    294     }
    295   }
    296 
    297   _playDelayMS = playDelayMs;
    298   _recDelayMS = recDelayMs;
    299   _clockDrift = clockDrift;
    300 }
    301 
    302 // ----------------------------------------------------------------------------
    303 //  StartInputFileRecording
    304 // ----------------------------------------------------------------------------
    305 
    306 int32_t AudioDeviceBuffer::StartInputFileRecording(
    307     const char fileName[kAdmMaxFileNameSize])
    308 {
    309     WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
    310 
    311     CriticalSectionScoped lock(&_critSect);
    312 
    313     _recFile.Flush();
    314     _recFile.CloseFile();
    315 
    316     return (_recFile.OpenFile(fileName, false, false, false));
    317 }
    318 
    319 // ----------------------------------------------------------------------------
    320 //  StopInputFileRecording
    321 // ----------------------------------------------------------------------------
    322 
    323 int32_t AudioDeviceBuffer::StopInputFileRecording()
    324 {
    325     WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
    326 
    327     CriticalSectionScoped lock(&_critSect);
    328 
    329     _recFile.Flush();
    330     _recFile.CloseFile();
    331 
    332     return 0;
    333 }
    334 
    335 // ----------------------------------------------------------------------------
    336 //  StartOutputFileRecording
    337 // ----------------------------------------------------------------------------
    338 
    339 int32_t AudioDeviceBuffer::StartOutputFileRecording(
    340     const char fileName[kAdmMaxFileNameSize])
    341 {
    342     WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
    343 
    344     CriticalSectionScoped lock(&_critSect);
    345 
    346     _playFile.Flush();
    347     _playFile.CloseFile();
    348 
    349     return (_playFile.OpenFile(fileName, false, false, false));
    350 }
    351 
    352 // ----------------------------------------------------------------------------
    353 //  StopOutputFileRecording
    354 // ----------------------------------------------------------------------------
    355 
    356 int32_t AudioDeviceBuffer::StopOutputFileRecording()
    357 {
    358     WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
    359 
    360     CriticalSectionScoped lock(&_critSect);
    361 
    362     _playFile.Flush();
    363     _playFile.CloseFile();
    364 
    365     return 0;
    366 }
    367 
    368 // ----------------------------------------------------------------------------
    369 //  SetRecordedBuffer
    370 //
    371 //  Store recorded audio buffer in local memory ready for the actual
    372 //  "delivery" using a callback.
    373 //
    374 //  This method can also parse out left or right channel from a stereo
    375 //  input signal, i.e., emulate mono.
    376 //
    377 //  Examples:
    378 //
    379 //  16-bit,48kHz mono,  10ms => nSamples=480 => _recSize=2*480=960 bytes
    380 //  16-bit,48kHz stereo,10ms => nSamples=480 => _recSize=4*480=1920 bytes
    381 // ----------------------------------------------------------------------------
    382 
    383 int32_t AudioDeviceBuffer::SetRecordedBuffer(const void* audioBuffer,
    384                                              size_t nSamples)
    385 {
    386     CriticalSectionScoped lock(&_critSect);
    387 
    388     if (_recBytesPerSample == 0)
    389     {
    390         assert(false);
    391         return -1;
    392     }
    393 
    394     _recSamples = nSamples;
    395     _recSize = _recBytesPerSample*nSamples; // {2,4}*nSamples
    396     if (_recSize > kMaxBufferSizeBytes)
    397     {
    398         assert(false);
    399         return -1;
    400     }
    401 
    402     if (_recChannel == AudioDeviceModule::kChannelBoth)
    403     {
    404         // (default) copy the complete input buffer to the local buffer
    405         memcpy(&_recBuffer[0], audioBuffer, _recSize);
    406     }
    407     else
    408     {
    409         int16_t* ptr16In = (int16_t*)audioBuffer;
    410         int16_t* ptr16Out = (int16_t*)&_recBuffer[0];
    411 
    412         if (AudioDeviceModule::kChannelRight == _recChannel)
    413         {
    414             ptr16In++;
    415         }
    416 
    417         // exctract left or right channel from input buffer to the local buffer
    418         for (size_t i = 0; i < _recSamples; i++)
    419         {
    420             *ptr16Out = *ptr16In;
    421             ptr16Out++;
    422             ptr16In++;
    423             ptr16In++;
    424         }
    425     }
    426 
    427     if (_recFile.Open())
    428     {
    429         // write to binary file in mono or stereo (interleaved)
    430         _recFile.Write(&_recBuffer[0], _recSize);
    431     }
    432 
    433     return 0;
    434 }
    435 
    436 // ----------------------------------------------------------------------------
    437 //  DeliverRecordedData
    438 // ----------------------------------------------------------------------------
    439 
    440 int32_t AudioDeviceBuffer::DeliverRecordedData()
    441 {
    442     CriticalSectionScoped lock(&_critSectCb);
    443 
    444     // Ensure that user has initialized all essential members
    445     if ((_recSampleRate == 0)     ||
    446         (_recSamples == 0)        ||
    447         (_recBytesPerSample == 0) ||
    448         (_recChannels == 0))
    449     {
    450         assert(false);
    451         return -1;
    452     }
    453 
    454     if (_ptrCbAudioTransport == NULL)
    455     {
    456         WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "failed to deliver recorded data (AudioTransport does not exist)");
    457         return 0;
    458     }
    459 
    460     int32_t res(0);
    461     uint32_t newMicLevel(0);
    462     uint32_t totalDelayMS = _playDelayMS +_recDelayMS;
    463 
    464     res = _ptrCbAudioTransport->RecordedDataIsAvailable(&_recBuffer[0],
    465                                                         _recSamples,
    466                                                         _recBytesPerSample,
    467                                                         _recChannels,
    468                                                         _recSampleRate,
    469                                                         totalDelayMS,
    470                                                         _clockDrift,
    471                                                         _currentMicLevel,
    472                                                         _typingStatus,
    473                                                         newMicLevel);
    474     if (res != -1)
    475     {
    476         _newMicLevel = newMicLevel;
    477     }
    478 
    479     return 0;
    480 }
    481 
    482 // ----------------------------------------------------------------------------
    483 //  RequestPlayoutData
    484 // ----------------------------------------------------------------------------
    485 
    486 int32_t AudioDeviceBuffer::RequestPlayoutData(size_t nSamples)
    487 {
    488     uint32_t playSampleRate = 0;
    489     size_t playBytesPerSample = 0;
    490     size_t playChannels = 0;
    491     {
    492         CriticalSectionScoped lock(&_critSect);
    493 
    494         // Store copies under lock and use copies hereafter to avoid race with
    495         // setter methods.
    496         playSampleRate = _playSampleRate;
    497         playBytesPerSample = _playBytesPerSample;
    498         playChannels = _playChannels;
    499 
    500         // Ensure that user has initialized all essential members
    501         if ((playBytesPerSample == 0) ||
    502             (playChannels == 0)       ||
    503             (playSampleRate == 0))
    504         {
    505             assert(false);
    506             return -1;
    507         }
    508 
    509         _playSamples = nSamples;
    510         _playSize = playBytesPerSample * nSamples;  // {2,4}*nSamples
    511         if (_playSize > kMaxBufferSizeBytes)
    512         {
    513             assert(false);
    514             return -1;
    515         }
    516 
    517         if (nSamples != _playSamples)
    518         {
    519             WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "invalid number of samples to be played out (%d)", nSamples);
    520             return -1;
    521         }
    522     }
    523 
    524     size_t nSamplesOut(0);
    525 
    526     CriticalSectionScoped lock(&_critSectCb);
    527 
    528     if (_ptrCbAudioTransport == NULL)
    529     {
    530         WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "failed to feed data to playout (AudioTransport does not exist)");
    531         return 0;
    532     }
    533 
    534     if (_ptrCbAudioTransport)
    535     {
    536         uint32_t res(0);
    537         int64_t elapsed_time_ms = -1;
    538         int64_t ntp_time_ms = -1;
    539         res = _ptrCbAudioTransport->NeedMorePlayData(_playSamples,
    540                                                      playBytesPerSample,
    541                                                      playChannels,
    542                                                      playSampleRate,
    543                                                      &_playBuffer[0],
    544                                                      nSamplesOut,
    545                                                      &elapsed_time_ms,
    546                                                      &ntp_time_ms);
    547         if (res != 0)
    548         {
    549             WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "NeedMorePlayData() failed");
    550         }
    551     }
    552 
    553     return static_cast<int32_t>(nSamplesOut);
    554 }
    555 
    556 // ----------------------------------------------------------------------------
    557 //  GetPlayoutData
    558 // ----------------------------------------------------------------------------
    559 
    560 int32_t AudioDeviceBuffer::GetPlayoutData(void* audioBuffer)
    561 {
    562     CriticalSectionScoped lock(&_critSect);
    563 
    564     if (_playSize > kMaxBufferSizeBytes)
    565     {
    566        WEBRTC_TRACE(kTraceError, kTraceUtility, _id,
    567                     "_playSize %" PRIuS " exceeds kMaxBufferSizeBytes in "
    568                     "AudioDeviceBuffer::GetPlayoutData", _playSize);
    569        assert(false);
    570        return -1;
    571     }
    572 
    573     memcpy(audioBuffer, &_playBuffer[0], _playSize);
    574 
    575     if (_playFile.Open())
    576     {
    577         // write to binary file in mono or stereo (interleaved)
    578         _playFile.Write(&_playBuffer[0], _playSize);
    579     }
    580 
    581     return static_cast<int32_t>(_playSamples);
    582 }
    583 
    584 }  // namespace webrtc
    585