Commit 6d31045a authored by Raymond Toy's avatar Raymond Toy Committed by Commit Bot

Atomically access RealtimeAnalyser write_index_

The write index for the buffer that holds the time domain data is read
from the main thread and written by the audio thread.  Atomically
access these and also read (and write) them exactly once in each
routine so that they don't get out of sync within each routine.

Can't add a trylock to protect access in WriteInput because if the
audio thread can't get the lock, there will be strange gaps in the
saved data.  It's ok if the main thread reads a slightly old value of
the index; the data is just a bit stale, which is fine for the
AnalyserNode.

Bug: 786829
Test: test case from bug passes
Change-Id: Id8d5658b9610beb0d78c2c16d9eac579406e4c2b
Reviewed-on: https://chromium-review.googlesource.com/790945Reviewed-by: default avatarHongchan Choi <hongchan@chromium.org>
Commit-Queue: Raymond Toy <rtoy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#519767}
parent a88afd25
...@@ -86,16 +86,17 @@ void RealtimeAnalyser::WriteInput(AudioBus* bus, size_t frames_to_process) { ...@@ -86,16 +86,17 @@ void RealtimeAnalyser::WriteInput(AudioBus* bus, size_t frames_to_process) {
if (!is_bus_good) if (!is_bus_good)
return; return;
unsigned write_index = GetWriteIndex();
// FIXME : allow to work with non-FFTSize divisible chunking // FIXME : allow to work with non-FFTSize divisible chunking
bool is_destination_good = bool is_destination_good =
write_index_ < input_buffer_.size() && write_index < input_buffer_.size() &&
write_index_ + frames_to_process <= input_buffer_.size(); write_index + frames_to_process <= input_buffer_.size();
DCHECK(is_destination_good); DCHECK(is_destination_good);
if (!is_destination_good) if (!is_destination_good)
return; return;
// Perform real-time analysis // Perform real-time analysis
float* dest = input_buffer_.Data() + write_index_; float* dest = input_buffer_.Data() + write_index;
// Clear the bus and downmix the input according to the down mixing rules. // Clear the bus and downmix the input according to the down mixing rules.
// Then save the result in the m_inputBuffer at the appropriate place. // Then save the result in the m_inputBuffer at the appropriate place.
...@@ -104,9 +105,10 @@ void RealtimeAnalyser::WriteInput(AudioBus* bus, size_t frames_to_process) { ...@@ -104,9 +105,10 @@ void RealtimeAnalyser::WriteInput(AudioBus* bus, size_t frames_to_process) {
memcpy(dest, down_mix_bus_->Channel(0)->Data(), memcpy(dest, down_mix_bus_->Channel(0)->Data(),
frames_to_process * sizeof(*dest)); frames_to_process * sizeof(*dest));
write_index_ += frames_to_process; write_index += frames_to_process;
if (write_index_ >= kInputBufferSize) if (write_index >= kInputBufferSize)
write_index_ = 0; write_index = 0;
SetWriteIndex(write_index);
} }
namespace { namespace {
...@@ -143,7 +145,7 @@ void RealtimeAnalyser::DoFFTAnalysis() { ...@@ -143,7 +145,7 @@ void RealtimeAnalyser::DoFFTAnalysis() {
// Take the previous fftSize values from the input buffer and copy into the // Take the previous fftSize values from the input buffer and copy into the
// temporary buffer. // temporary buffer.
unsigned write_index = write_index_; unsigned write_index = GetWriteIndex();
if (write_index < fft_size) { if (write_index < fft_size) {
memcpy(temp_p, input_buffer + write_index - fft_size + kInputBufferSize, memcpy(temp_p, input_buffer + write_index - fft_size + kInputBufferSize,
sizeof(*temp_p) * (fft_size - write_index)); sizeof(*temp_p) * (fft_size - write_index));
...@@ -290,7 +292,7 @@ void RealtimeAnalyser::GetFloatTimeDomainData( ...@@ -290,7 +292,7 @@ void RealtimeAnalyser::GetFloatTimeDomainData(
float* input_buffer = input_buffer_.Data(); float* input_buffer = input_buffer_.Data();
float* destination = destination_array->Data(); float* destination = destination_array->Data();
unsigned write_index = write_index_; unsigned write_index = GetWriteIndex();
for (unsigned i = 0; i < len; ++i) { for (unsigned i = 0; i < len; ++i) {
// Buffer access is protected due to modulo operation. // Buffer access is protected due to modulo operation.
...@@ -319,7 +321,7 @@ void RealtimeAnalyser::GetByteTimeDomainData(DOMUint8Array* destination_array) { ...@@ -319,7 +321,7 @@ void RealtimeAnalyser::GetByteTimeDomainData(DOMUint8Array* destination_array) {
float* input_buffer = input_buffer_.Data(); float* input_buffer = input_buffer_.Data();
unsigned char* destination = destination_array->Data(); unsigned char* destination = destination_array->Data();
unsigned write_index = write_index_; unsigned write_index = GetWriteIndex();
for (unsigned i = 0; i < len; ++i) { for (unsigned i = 0; i < len; ++i) {
// Buffer access is protected due to modulo operation. // Buffer access is protected due to modulo operation.
......
...@@ -79,6 +79,11 @@ class RealtimeAnalyser final { ...@@ -79,6 +79,11 @@ class RealtimeAnalyser final {
AudioFloatArray input_buffer_; AudioFloatArray input_buffer_;
unsigned write_index_; unsigned write_index_;
unsigned GetWriteIndex() const { return AcquireLoad(&write_index_); }
void SetWriteIndex(unsigned new_index) {
ReleaseStore(&write_index_, new_index);
}
// Input audio is downmixed to this bus before copying to m_inputBuffer. // Input audio is downmixed to this bus before copying to m_inputBuffer.
scoped_refptr<AudioBus> down_mix_bus_; scoped_refptr<AudioBus> down_mix_bus_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment