fine_audio_buffer.cc (5708B)
1 /* 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 11 #include "modules/audio_device/fine_audio_buffer.h" 12 13 #include <cstdint> 14 #include <cstring> 15 #include <optional> 16 17 #include "api/array_view.h" 18 #include "modules/audio_device/audio_device_buffer.h" 19 #include "rtc_base/checks.h" 20 #include "rtc_base/logging.h" 21 #include "rtc_base/numerics/safe_conversions.h" 22 23 namespace webrtc { 24 25 FineAudioBuffer::FineAudioBuffer(AudioDeviceBuffer* audio_device_buffer) 26 : audio_device_buffer_(audio_device_buffer), 27 playout_samples_per_channel_10ms_(dchecked_cast<size_t>( 28 audio_device_buffer->PlayoutSampleRate() * 10 / 1000)), 29 record_samples_per_channel_10ms_(dchecked_cast<size_t>( 30 audio_device_buffer->RecordingSampleRate() * 10 / 1000)), 31 playout_channels_(audio_device_buffer->PlayoutChannels()), 32 record_channels_(audio_device_buffer->RecordingChannels()) { 33 RTC_DCHECK(audio_device_buffer_); 34 RTC_DLOG(LS_INFO) << __FUNCTION__; 35 if (IsReadyForPlayout()) { 36 RTC_DLOG(LS_INFO) << "playout_samples_per_channel_10ms: " 37 << playout_samples_per_channel_10ms_; 38 RTC_DLOG(LS_INFO) << "playout_channels: " << playout_channels_; 39 } 40 if (IsReadyForRecord()) { 41 RTC_DLOG(LS_INFO) << "record_samples_per_channel_10ms: " 42 << record_samples_per_channel_10ms_; 43 RTC_DLOG(LS_INFO) << "record_channels: " << record_channels_; 44 } 45 } 46 47 FineAudioBuffer::~FineAudioBuffer() { 48 RTC_DLOG(LS_INFO) << __FUNCTION__; 49 } 50 51 void FineAudioBuffer::ResetPlayout() { 52 playout_buffer_.Clear(); 53 } 54 55 void FineAudioBuffer::ResetRecord() { 56 record_buffer_.Clear(); 57 } 58 59 bool FineAudioBuffer::IsReadyForPlayout() const { 60 return playout_samples_per_channel_10ms_ > 0 && playout_channels_ > 0; 61 } 62 63 bool FineAudioBuffer::IsReadyForRecord() const { 64 return record_samples_per_channel_10ms_ > 0 && record_channels_ > 0; 65 } 66 67 void FineAudioBuffer::GetPlayoutData(ArrayView<int16_t> audio_buffer, 68 int playout_delay_ms) { 69 RTC_DCHECK(IsReadyForPlayout()); 70 // Ask WebRTC for new data in chunks of 10ms until we have enough to 71 // fulfill the request. It is possible that the buffer already contains 72 // enough samples from the last round. 73 while (playout_buffer_.size() < audio_buffer.size()) { 74 // Get 10ms decoded audio from WebRTC. The ADB knows about number of 75 // channels; hence we can ask for number of samples per channel here. 76 if (audio_device_buffer_->RequestPlayoutData( 77 playout_samples_per_channel_10ms_) == 78 static_cast<int32_t>(playout_samples_per_channel_10ms_)) { 79 // Append 10ms to the end of the local buffer taking number of channels 80 // into account. 81 const size_t num_elements_10ms = 82 playout_channels_ * playout_samples_per_channel_10ms_; 83 const size_t written_elements = playout_buffer_.AppendData( 84 num_elements_10ms, [&](ArrayView<int16_t> buf) { 85 const size_t samples_per_channel_10ms = 86 audio_device_buffer_->GetPlayoutData(buf.data()); 87 return playout_channels_ * samples_per_channel_10ms; 88 }); 89 RTC_DCHECK_EQ(num_elements_10ms, written_elements); 90 } else { 91 // Provide silence if AudioDeviceBuffer::RequestPlayoutData() fails. 92 // Can e.g. happen when an AudioTransport has not been registered. 93 const size_t num_bytes = audio_buffer.size() * sizeof(int16_t); 94 std::memset(audio_buffer.data(), 0, num_bytes); 95 return; 96 } 97 } 98 99 // Provide the requested number of bytes to the consumer. 100 const size_t num_bytes = audio_buffer.size() * sizeof(int16_t); 101 memcpy(audio_buffer.data(), playout_buffer_.data(), num_bytes); 102 // Move remaining samples to start of buffer to prepare for next round. 103 memmove(playout_buffer_.data(), playout_buffer_.data() + audio_buffer.size(), 104 (playout_buffer_.size() - audio_buffer.size()) * sizeof(int16_t)); 105 playout_buffer_.SetSize(playout_buffer_.size() - audio_buffer.size()); 106 // Cache playout latency for usage in DeliverRecordedData(); 107 playout_delay_ms_ = playout_delay_ms; 108 } 109 110 void FineAudioBuffer::DeliverRecordedData( 111 ArrayView<const int16_t> audio_buffer, 112 int record_delay_ms, 113 std::optional<int64_t> capture_time_ns) { 114 RTC_DCHECK(IsReadyForRecord()); 115 // Always append new data and grow the buffer when needed. 116 record_buffer_.AppendData(audio_buffer.data(), audio_buffer.size()); 117 // Consume samples from buffer in chunks of 10ms until there is not 118 // enough data left. The number of remaining samples in the cache is given by 119 // the new size of the internal `record_buffer_`. 120 const size_t num_elements_10ms = 121 record_channels_ * record_samples_per_channel_10ms_; 122 while (record_buffer_.size() >= num_elements_10ms) { 123 audio_device_buffer_->SetRecordedBuffer(record_buffer_.data(), 124 record_samples_per_channel_10ms_, 125 capture_time_ns); 126 audio_device_buffer_->SetVQEData(playout_delay_ms_, record_delay_ms); 127 audio_device_buffer_->DeliverRecordedData(); 128 memmove(record_buffer_.data(), record_buffer_.data() + num_elements_10ms, 129 (record_buffer_.size() - num_elements_10ms) * sizeof(int16_t)); 130 record_buffer_.SetSize(record_buffer_.size() - num_elements_10ms); 131 } 132 } 133 134 } // namespace webrtc