blob: bd18359009d2a729fe47e903c20ff30311b656d8 [file] [log] [blame]
henrika86d907c2015-09-07 16:09:50 +02001/*
2 * Copyright (c) 2013 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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/audio_device/fine_audio_buffer.h"
henrika86d907c2015-09-07 16:09:50 +020012
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020013#include "modules/audio_device/audio_device_buffer.h"
14#include "rtc_base/checks.h"
15#include "rtc_base/logging.h"
henrika29e865a2018-04-24 13:22:31 +020016#include "rtc_base/numerics/safe_conversions.h"
henrika86d907c2015-09-07 16:09:50 +020017
18namespace webrtc {
19
henrika29e865a2018-04-24 13:22:31 +020020FineAudioBuffer::FineAudioBuffer(AudioDeviceBuffer* audio_device_buffer)
21 : audio_device_buffer_(audio_device_buffer),
22 playout_samples_per_channel_10ms_(rtc::dchecked_cast<size_t>(
23 audio_device_buffer->PlayoutSampleRate() * 10 / 1000)),
24 record_samples_per_channel_10ms_(rtc::dchecked_cast<size_t>(
25 audio_device_buffer->RecordingSampleRate() * 10 / 1000)),
26 playout_channels_(audio_device_buffer->PlayoutChannels()),
27 record_channels_(audio_device_buffer->RecordingChannels()) {
28 RTC_DCHECK(audio_device_buffer_);
29 if (IsReadyForPlayout()) {
30 RTC_DLOG(INFO) << "playout_samples_per_channel_10ms: "
31 << playout_samples_per_channel_10ms_;
32 RTC_DLOG(INFO) << "playout_channels: " << playout_channels_;
33 }
34 if (IsReadyForRecord()) {
35 RTC_DLOG(INFO) << "record_samples_per_channel_10ms: "
36 << record_samples_per_channel_10ms_;
37 RTC_DLOG(INFO) << "record_channels: " << record_channels_;
38 }
henrika86d907c2015-09-07 16:09:50 +020039}
40
41FineAudioBuffer::~FineAudioBuffer() {}
42
henrika86d907c2015-09-07 16:09:50 +020043void FineAudioBuffer::ResetPlayout() {
henrikab3ebc1a2017-02-27 05:14:17 -080044 playout_buffer_.Clear();
henrika86d907c2015-09-07 16:09:50 +020045}
46
47void FineAudioBuffer::ResetRecord() {
henrikaf166e1b2017-02-23 02:44:55 -080048 record_buffer_.Clear();
henrika86d907c2015-09-07 16:09:50 +020049}
50
henrika29e865a2018-04-24 13:22:31 +020051bool FineAudioBuffer::IsReadyForPlayout() const {
52 return playout_samples_per_channel_10ms_ > 0 && playout_channels_ > 0;
53}
54
55bool FineAudioBuffer::IsReadyForRecord() const {
56 return record_samples_per_channel_10ms_ > 0 && record_channels_ > 0;
57}
58
henrika8d7393b2018-04-19 13:40:15 +020059void FineAudioBuffer::GetPlayoutData(rtc::ArrayView<int16_t> audio_buffer,
henrika883d00f2018-03-16 10:09:49 +010060 int playout_delay_ms) {
henrika29e865a2018-04-24 13:22:31 +020061 RTC_DCHECK(IsReadyForPlayout());
henrikab3ebc1a2017-02-27 05:14:17 -080062 // Ask WebRTC for new data in chunks of 10ms until we have enough to
63 // fulfill the request. It is possible that the buffer already contains
64 // enough samples from the last round.
henrika8d7393b2018-04-19 13:40:15 +020065 while (playout_buffer_.size() < audio_buffer.size()) {
henrika29e865a2018-04-24 13:22:31 +020066 // Get 10ms decoded audio from WebRTC. The ADB knows about number of
67 // channels; hence we can ask for number of samples per channel here.
henrikaec9c7452018-06-08 16:10:03 +020068 if (audio_device_buffer_->RequestPlayoutData(
69 playout_samples_per_channel_10ms_) ==
70 static_cast<int32_t>(playout_samples_per_channel_10ms_)) {
71 // Append 10ms to the end of the local buffer taking number of channels
72 // into account.
73 const size_t num_elements_10ms =
74 playout_channels_ * playout_samples_per_channel_10ms_;
75 const size_t written_elements = playout_buffer_.AppendData(
76 num_elements_10ms, [&](rtc::ArrayView<int16_t> buf) {
77 const size_t samples_per_channel_10ms =
78 audio_device_buffer_->GetPlayoutData(buf.data());
79 return playout_channels_ * samples_per_channel_10ms;
80 });
81 RTC_DCHECK_EQ(num_elements_10ms, written_elements);
82 } else {
83 // Provide silence if AudioDeviceBuffer::RequestPlayoutData() fails.
84 // Can e.g. happen when an AudioTransport has not been registered.
85 const size_t num_bytes = audio_buffer.size() * sizeof(int16_t);
86 std::memset(audio_buffer.data(), 0, num_bytes);
87 return;
88 }
henrika86d907c2015-09-07 16:09:50 +020089 }
henrika8d7393b2018-04-19 13:40:15 +020090
henrikab3ebc1a2017-02-27 05:14:17 -080091 // Provide the requested number of bytes to the consumer.
henrika29e865a2018-04-24 13:22:31 +020092 const size_t num_bytes = audio_buffer.size() * sizeof(int16_t);
henrikabb6f7522017-05-30 02:01:30 -070093 memcpy(audio_buffer.data(), playout_buffer_.data(), num_bytes);
henrikab3ebc1a2017-02-27 05:14:17 -080094 // Move remaining samples to start of buffer to prepare for next round.
henrika8d7393b2018-04-19 13:40:15 +020095 memmove(playout_buffer_.data(), playout_buffer_.data() + audio_buffer.size(),
96 (playout_buffer_.size() - audio_buffer.size()) * sizeof(int16_t));
97 playout_buffer_.SetSize(playout_buffer_.size() - audio_buffer.size());
henrika883d00f2018-03-16 10:09:49 +010098 // Cache playout latency for usage in DeliverRecordedData();
99 playout_delay_ms_ = playout_delay_ms;
henrika86d907c2015-09-07 16:09:50 +0200100}
101
henrikabb6f7522017-05-30 02:01:30 -0700102void FineAudioBuffer::DeliverRecordedData(
henrika8d7393b2018-04-19 13:40:15 +0200103 rtc::ArrayView<const int16_t> audio_buffer,
henrikabb6f7522017-05-30 02:01:30 -0700104 int record_delay_ms) {
henrika29e865a2018-04-24 13:22:31 +0200105 RTC_DCHECK(IsReadyForRecord());
106 // Always append new data and grow the buffer when needed.
henrikabb6f7522017-05-30 02:01:30 -0700107 record_buffer_.AppendData(audio_buffer.data(), audio_buffer.size());
henrikaf166e1b2017-02-23 02:44:55 -0800108 // Consume samples from buffer in chunks of 10ms until there is not
henrika8d7393b2018-04-19 13:40:15 +0200109 // enough data left. The number of remaining samples in the cache is given by
henrika29e865a2018-04-24 13:22:31 +0200110 // the new size of the internal |record_buffer_|.
111 const size_t num_elements_10ms =
112 record_channels_ * record_samples_per_channel_10ms_;
113 while (record_buffer_.size() >= num_elements_10ms) {
114 audio_device_buffer_->SetRecordedBuffer(record_buffer_.data(),
115 record_samples_per_channel_10ms_);
116 audio_device_buffer_->SetVQEData(playout_delay_ms_, record_delay_ms);
117 audio_device_buffer_->DeliverRecordedData();
118 memmove(record_buffer_.data(), record_buffer_.data() + num_elements_10ms,
119 (record_buffer_.size() - num_elements_10ms) * sizeof(int16_t));
120 record_buffer_.SetSize(record_buffer_.size() - num_elements_10ms);
henrika86d907c2015-09-07 16:09:50 +0200121 }
122}
123
124} // namespace webrtc