FineAudioBuffer now uses 16-bit audio samples to match the AudioDeviceBuffer.
This work is also done as a preparation for adding stereo support to the FineAudioBuffer. Review hints: Actual changes are in modules/audio_device/fine_audio_buffer.h,cc, the rest is just adaptations to match these changes. We do have a forked ADM today, hence, some changes are duplicated. The changes have been verified on all affected platforms. Bug: webrtc:6560 Change-Id: I413af41c43809f61455c45ad383fc4b1c65e1fa1 Reviewed-on: https://webrtc-review.googlesource.com/70781 Commit-Queue: Henrik Andreassson <henrika@webrtc.org> Reviewed-by: Karl Wiberg <kwiberg@webrtc.org> Cr-Commit-Position: refs/heads/master@{#22938}
This commit is contained in:
@ -123,7 +123,7 @@ void AAudioPlayer::AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) {
|
||||
// size per callback used by AAudio. Use an initial capacity of 50ms to ensure
|
||||
// that the buffer can cache old data and at the same time be prepared for
|
||||
// increased burst size in AAudio if buffer underruns are detected.
|
||||
const size_t capacity = 5 * audio_parameters.GetBytesPer10msBuffer();
|
||||
const size_t capacity = 5 * audio_parameters.frames_per_10ms_buffer();
|
||||
fine_audio_buffer_.reset(new FineAudioBuffer(
|
||||
audio_device_buffer_, audio_parameters.sample_rate(), capacity));
|
||||
}
|
||||
@ -200,16 +200,16 @@ aaudio_data_callback_result_t AAudioPlayer::OnDataCallback(void* audio_data,
|
||||
|
||||
// Read audio data from the WebRTC source using the FineAudioBuffer object
|
||||
// and write that data into |audio_data| to be played out by AAudio.
|
||||
const size_t num_bytes =
|
||||
sizeof(int16_t) * aaudio_.samples_per_frame() * num_frames;
|
||||
// Prime output with zeros during a short initial phase to avoid distortion.
|
||||
// TODO(henrika): do more work to figure out of if the initial forced silence
|
||||
// period is really needed.
|
||||
if (aaudio_.frames_written() < 50 * aaudio_.frames_per_burst()) {
|
||||
const size_t num_bytes =
|
||||
sizeof(int16_t) * aaudio_.samples_per_frame() * num_frames;
|
||||
memset(audio_data, 0, num_bytes);
|
||||
} else {
|
||||
fine_audio_buffer_->GetPlayoutData(
|
||||
rtc::ArrayView<int8_t>(static_cast<int8_t*>(audio_data), num_bytes),
|
||||
rtc::MakeArrayView(static_cast<int16_t*>(audio_data), num_frames),
|
||||
static_cast<int>(latency_millis_ + 0.5));
|
||||
}
|
||||
|
||||
|
||||
@ -192,11 +192,8 @@ aaudio_data_callback_result_t AAudioRecorder::OnDataCallback(
|
||||
}
|
||||
// Copy recorded audio in |audio_data| to the WebRTC sink using the
|
||||
// FineAudioBuffer object.
|
||||
const size_t num_bytes =
|
||||
sizeof(int16_t) * aaudio_.samples_per_frame() * num_frames;
|
||||
fine_audio_buffer_->DeliverRecordedData(
|
||||
rtc::ArrayView<const int8_t>(static_cast<const int8_t*>(audio_data),
|
||||
num_bytes),
|
||||
rtc::MakeArrayView(static_cast<const int16_t*>(audio_data), num_frames),
|
||||
static_cast<int>(latency_millis_ + 0.5));
|
||||
|
||||
return AAUDIO_CALLBACK_RESULT_CONTINUE;
|
||||
|
||||
@ -222,16 +222,16 @@ void OpenSLESPlayer::AllocateDataBuffers() {
|
||||
// recommended to construct audio buffers so that they contain an exact
|
||||
// multiple of this number. If so, callbacks will occur at regular intervals,
|
||||
// which reduces jitter.
|
||||
const size_t buffer_size_in_bytes = audio_parameters_.GetBytesPerBuffer();
|
||||
ALOGD("native buffer size: %" PRIuS, buffer_size_in_bytes);
|
||||
const size_t buffer_size_in_samples = audio_parameters_.frames_per_buffer();
|
||||
ALOGD("native buffer size: %" PRIuS, buffer_size_in_samples);
|
||||
ALOGD("native buffer size in ms: %.2f",
|
||||
audio_parameters_.GetBufferSizeInMilliseconds());
|
||||
fine_audio_buffer_.reset(new FineAudioBuffer(audio_device_buffer_,
|
||||
audio_parameters_.sample_rate(),
|
||||
2 * buffer_size_in_bytes));
|
||||
fine_audio_buffer_.reset(
|
||||
new FineAudioBuffer(audio_device_buffer_, audio_parameters_.sample_rate(),
|
||||
2 * audio_parameters_.frames_per_buffer()));
|
||||
// Allocated memory for audio buffers.
|
||||
for (int i = 0; i < kNumOfOpenSLESBuffers; ++i) {
|
||||
audio_buffers_[i].reset(new SLint8[buffer_size_in_bytes]);
|
||||
audio_buffers_[i].reset(new SLint16[buffer_size_in_samples]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -403,13 +403,14 @@ void OpenSLESPlayer::EnqueuePlayoutData(bool silence) {
|
||||
ALOGW("Bad OpenSL ES playout timing, dT=%u [ms]", diff);
|
||||
}
|
||||
last_play_time_ = current_time;
|
||||
SLint8* audio_ptr = audio_buffers_[buffer_index_].get();
|
||||
SLint8* audio_ptr8 =
|
||||
reinterpret_cast<SLint8*>(audio_buffers_[buffer_index_].get());
|
||||
if (silence) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
// Avoid aquiring real audio data from WebRTC and fill the buffer with
|
||||
// zeros instead. Used to prime the buffer with silence and to avoid asking
|
||||
// for audio data from two different threads.
|
||||
memset(audio_ptr, 0, audio_parameters_.GetBytesPerBuffer());
|
||||
memset(audio_ptr8, 0, audio_parameters_.GetBytesPerBuffer());
|
||||
} else {
|
||||
RTC_DCHECK(thread_checker_opensles_.CalledOnValidThread());
|
||||
// Read audio data from the WebRTC source using the FineAudioBuffer object
|
||||
@ -417,13 +418,13 @@ void OpenSLESPlayer::EnqueuePlayoutData(bool silence) {
|
||||
// OpenSL ES. Use hardcoded delay estimate since OpenSL ES does not support
|
||||
// delay estimation.
|
||||
fine_audio_buffer_->GetPlayoutData(
|
||||
rtc::ArrayView<SLint8>(audio_ptr,
|
||||
audio_parameters_.GetBytesPerBuffer()),
|
||||
rtc::ArrayView<int16_t>(audio_buffers_[buffer_index_].get(),
|
||||
audio_parameters_.frames_per_buffer()),
|
||||
25);
|
||||
}
|
||||
// Enqueue the decoded audio buffer for playback.
|
||||
SLresult err = (*simple_buffer_queue_)
|
||||
->Enqueue(simple_buffer_queue_, audio_ptr,
|
||||
->Enqueue(simple_buffer_queue_, audio_ptr8,
|
||||
audio_parameters_.GetBytesPerBuffer());
|
||||
if (SL_RESULT_SUCCESS != err) {
|
||||
ALOGE("Enqueue failed: %d", err);
|
||||
|
||||
@ -140,9 +140,8 @@ class OpenSLESPlayer : public AudioOutput {
|
||||
SLDataFormat_PCM pcm_format_;
|
||||
|
||||
// Queue of audio buffers to be used by the player object for rendering
|
||||
// audio. They will be used in a Round-robin way and the size of each buffer
|
||||
// is given by FineAudioBuffer::RequiredBufferSizeBytes().
|
||||
std::unique_ptr<SLint8[]> audio_buffers_[kNumOfOpenSLESBuffers];
|
||||
// audio.
|
||||
std::unique_ptr<SLint16[]> audio_buffers_[kNumOfOpenSLESBuffers];
|
||||
|
||||
// FineAudioBuffer takes an AudioDeviceBuffer which delivers audio data
|
||||
// in chunks of 10ms. It then allows for this data to be pulled in
|
||||
|
||||
@ -355,12 +355,12 @@ void OpenSLESRecorder::AllocateDataBuffers() {
|
||||
RTC_DCHECK(audio_device_buffer_);
|
||||
fine_audio_buffer_.reset(
|
||||
new FineAudioBuffer(audio_device_buffer_, audio_parameters_.sample_rate(),
|
||||
2 * audio_parameters_.GetBytesPerBuffer()));
|
||||
2 * audio_parameters_.frames_per_buffer()));
|
||||
// Allocate queue of audio buffers that stores recorded audio samples.
|
||||
const int data_size_bytes = audio_parameters_.GetBytesPerBuffer();
|
||||
audio_buffers_.reset(new std::unique_ptr<SLint8[]>[kNumOfOpenSLESBuffers]);
|
||||
const int data_size_samples = audio_parameters_.frames_per_buffer();
|
||||
audio_buffers_.reset(new std::unique_ptr<SLint16[]>[kNumOfOpenSLESBuffers]);
|
||||
for (int i = 0; i < kNumOfOpenSLESBuffers; ++i) {
|
||||
audio_buffers_[i].reset(new SLint8[data_size_bytes]);
|
||||
audio_buffers_[i].reset(new SLint16[data_size_samples]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -385,12 +385,12 @@ void OpenSLESRecorder::ReadBufferQueue() {
|
||||
// since there is no support to turn off built-in EC in combination with
|
||||
// OpenSL ES anyhow. Hence, as is, the WebRTC based AEC (which would use
|
||||
// these estimates) will never be active.
|
||||
const size_t size_in_bytes =
|
||||
static_cast<size_t>(audio_parameters_.GetBytesPerBuffer());
|
||||
const int8_t* data =
|
||||
static_cast<const int8_t*>(audio_buffers_[buffer_index_].get());
|
||||
const size_t size_in_samples =
|
||||
static_cast<size_t>(audio_parameters_.frames_per_buffer());
|
||||
fine_audio_buffer_->DeliverRecordedData(
|
||||
rtc::ArrayView<const int8_t>(data, size_in_bytes), 25);
|
||||
rtc::ArrayView<const int16_t>(audio_buffers_[buffer_index_].get(),
|
||||
size_in_samples),
|
||||
25);
|
||||
// Enqueue the utilized audio buffer and use if for recording again.
|
||||
EnqueueAudioBuffer();
|
||||
}
|
||||
@ -398,8 +398,10 @@ void OpenSLESRecorder::ReadBufferQueue() {
|
||||
bool OpenSLESRecorder::EnqueueAudioBuffer() {
|
||||
SLresult err =
|
||||
(*simple_buffer_queue_)
|
||||
->Enqueue(simple_buffer_queue_, audio_buffers_[buffer_index_].get(),
|
||||
audio_parameters_.GetBytesPerBuffer());
|
||||
->Enqueue(
|
||||
simple_buffer_queue_,
|
||||
reinterpret_cast<SLint8*>(audio_buffers_[buffer_index_].get()),
|
||||
audio_parameters_.GetBytesPerBuffer());
|
||||
if (SL_RESULT_SUCCESS != err) {
|
||||
ALOGE("Enqueue failed: %s", GetSLErrorString(err));
|
||||
return false;
|
||||
|
||||
@ -173,9 +173,9 @@ class OpenSLESRecorder : public AudioInput {
|
||||
|
||||
// Queue of audio buffers to be used by the recorder object for capturing
|
||||
// audio. They will be used in a Round-robin way and the size of each buffer
|
||||
// is given by AudioParameters::GetBytesPerBuffer(), i.e., it corresponds to
|
||||
// is given by AudioParameters::frames_per_buffer(), i.e., it corresponds to
|
||||
// the native OpenSL ES buffer size.
|
||||
std::unique_ptr<std::unique_ptr<SLint8[]>[]> audio_buffers_;
|
||||
std::unique_ptr<std::unique_ptr<SLint16[]>[]> audio_buffers_;
|
||||
|
||||
// Keeps track of active audio buffer 'n' in the audio_buffers_[n] queue.
|
||||
// Example (kNumOfOpenSLESBuffers = 2): counts 0, 1, 0, 1, ...
|
||||
|
||||
Reference in New Issue
Block a user