Add DeinterleavedView<float> view() to AudioBuffer

This helps with making AudioBuffer compatible with current and upcoming
code that uses audio_views.h (a simpler abstraction).

Bug: chromium:335805780
Change-Id: Ib59bba274c7abfb441e3c4d606f804b365df236d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/355844
Reviewed-by: Sam Zackrisson <saza@webrtc.org>
Commit-Queue: Tomas Gunnarsson <tommi@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#42590}
diff --git a/modules/audio_processing/BUILD.gn b/modules/audio_processing/BUILD.gn
index 7959fdb..8cabb1d 100644
--- a/modules/audio_processing/BUILD.gn
+++ b/modules/audio_processing/BUILD.gn
@@ -56,6 +56,7 @@
 
   deps = [
     "../../api:array_view",
+    "../../api/audio:audio_frame_api",
     "../../api/audio:audio_processing",
     "../../common_audio",
     "../../common_audio:common_audio_c",
@@ -364,6 +365,7 @@
         "../../api:scoped_refptr",
         "../../api/audio:aec3_config",
         "../../api/audio:aec3_factory",
+        "../../api/audio:audio_frame_api",
         "../../api/audio:audio_processing",
         "../../api/audio:echo_detector_creator",
         "../../common_audio",
diff --git a/modules/audio_processing/audio_buffer.h b/modules/audio_processing/audio_buffer.h
index 3fdc064..9369572 100644
--- a/modules/audio_processing/audio_buffer.h
+++ b/modules/audio_processing/audio_buffer.h
@@ -18,6 +18,7 @@
 #include <vector>
 
 #include "api/audio/audio_processing.h"
+#include "api/audio/audio_view.h"
 #include "common_audio/channel_buffer.h"
 #include "common_audio/include/audio_util.h"
 
@@ -58,6 +59,13 @@
   // reset at each call to CopyFrom or InterleaveFrom.
   void set_num_channels(size_t num_channels);
 
+  // Returns a DeinterleavedView<> over the channel data.
+  DeinterleavedView<float> view() {
+    return DeinterleavedView<float>(
+        num_channels_ && buffer_num_frames_ ? channels()[0] : nullptr,
+        buffer_num_frames_, num_channels_);
+  }
+
   size_t num_channels() const { return num_channels_; }
   size_t num_frames() const { return buffer_num_frames_; }
   size_t num_frames_per_band() const { return num_split_frames_; }
diff --git a/modules/audio_processing/audio_buffer_unittest.cc b/modules/audio_processing/audio_buffer_unittest.cc
index f3b2ddc..ef3479e 100644
--- a/modules/audio_processing/audio_buffer_unittest.cc
+++ b/modules/audio_processing/audio_buffer_unittest.cc
@@ -12,6 +12,7 @@
 
 #include <cmath>
 
+#include "api/audio/audio_view.h"
 #include "test/gtest.h"
 #include "test/testsupport/rtc_expect_death.h"
 
@@ -90,4 +91,28 @@
   // Verify that energies match.
   EXPECT_NEAR(energy_ab1, energy_ab2 * 32000.f / 48000.f, .01f * energy_ab1);
 }
+
+TEST(AudioBufferTest, DeinterleavedView) {
+  AudioBuffer ab(48000, 2, 48000, 2, 48000, 2);
+  // Fill the buffer with data.
+  const float pi = std::acos(-1.f);
+  float* const* channels = ab.channels();
+  for (size_t ch = 0; ch < ab.num_channels(); ++ch) {
+    for (size_t i = 0; i < ab.num_frames(); ++i) {
+      channels[ch][i] = std::sin(2 * pi * 100.f / 32000.f * i);
+    }
+  }
+
+  // Verify that the DeinterleavedView correctly maps to channels.
+  DeinterleavedView<float> view = ab.view();
+  ASSERT_EQ(view.num_channels(), ab.num_channels());
+  for (size_t c = 0; c < view.num_channels(); ++c) {
+    MonoView<float> channel = view[c];
+    EXPECT_EQ(SamplesPerChannel(channel), ab.num_frames());
+    for (size_t s = 0; s < SamplesPerChannel(channel); ++s) {
+      ASSERT_EQ(channel[s], channels[c][s]);
+    }
+  }
+}
+
 }  // namespace webrtc
diff --git a/modules/audio_processing/audio_processing_impl.cc b/modules/audio_processing/audio_processing_impl.cc
index 2d0b327..f0625c5 100644
--- a/modules/audio_processing/audio_processing_impl.cc
+++ b/modules/audio_processing/audio_processing_impl.cc
@@ -1474,9 +1474,7 @@
     absl::optional<float> voice_probability;
     if (!!submodules_.voice_activity_detector) {
       voice_probability = submodules_.voice_activity_detector->Analyze(
-          AudioFrameView<const float>(capture_buffer->channels(),
-                                      capture_buffer->num_channels(),
-                                      capture_buffer->num_frames()));
+          AudioFrameView<const float>(capture_buffer->view()));
     }
 
     if (submodules_.transient_suppressor) {