Home | History | Annotate | Download | only in common_audio
      1 /*
      2  *  Copyright (c) 2015 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 "webrtc/common_audio/audio_ring_buffer.h"
     12 
     13 #include "testing/gtest/include/gtest/gtest.h"
     14 #include "webrtc/common_audio/channel_buffer.h"
     15 
     16 namespace webrtc {
     17 
     18 class AudioRingBufferTest :
     19     public ::testing::TestWithParam< ::testing::tuple<int, int, int, int> > {
     20 };
     21 
     22 void ReadAndWriteTest(const ChannelBuffer<float>& input,
     23                       size_t num_write_chunk_frames,
     24                       size_t num_read_chunk_frames,
     25                       size_t buffer_frames,
     26                       ChannelBuffer<float>* output) {
     27   const size_t num_channels = input.num_channels();
     28   const size_t total_frames = input.num_frames();
     29   AudioRingBuffer buf(num_channels, buffer_frames);
     30   rtc::scoped_ptr<float* []> slice(new float* [num_channels]);
     31 
     32   size_t input_pos = 0;
     33   size_t output_pos = 0;
     34   while (input_pos + buf.WriteFramesAvailable() < total_frames) {
     35     // Write until the buffer is as full as possible.
     36     while (buf.WriteFramesAvailable() >= num_write_chunk_frames) {
     37       buf.Write(input.Slice(slice.get(), input_pos), num_channels,
     38                 num_write_chunk_frames);
     39       input_pos += num_write_chunk_frames;
     40     }
     41     // Read until the buffer is as empty as possible.
     42     while (buf.ReadFramesAvailable() >= num_read_chunk_frames) {
     43       EXPECT_LT(output_pos, total_frames);
     44       buf.Read(output->Slice(slice.get(), output_pos), num_channels,
     45                num_read_chunk_frames);
     46       output_pos += num_read_chunk_frames;
     47     }
     48   }
     49 
     50   // Write and read the last bit.
     51   if (input_pos < total_frames) {
     52     buf.Write(input.Slice(slice.get(), input_pos), num_channels,
     53               total_frames - input_pos);
     54   }
     55   if (buf.ReadFramesAvailable()) {
     56     buf.Read(output->Slice(slice.get(), output_pos), num_channels,
     57              buf.ReadFramesAvailable());
     58   }
     59   EXPECT_EQ(0u, buf.ReadFramesAvailable());
     60 }
     61 
     62 TEST_P(AudioRingBufferTest, ReadDataMatchesWrittenData) {
     63   const size_t kFrames = 5000;
     64   const size_t num_channels = ::testing::get<3>(GetParam());
     65 
     66   // Initialize the input data to an increasing sequence.
     67   ChannelBuffer<float> input(kFrames, static_cast<int>(num_channels));
     68   for (size_t i = 0; i < num_channels; ++i)
     69     for (size_t j = 0; j < kFrames; ++j)
     70       input.channels()[i][j] = (i + 1) * (j + 1);
     71 
     72   ChannelBuffer<float> output(kFrames, static_cast<int>(num_channels));
     73   ReadAndWriteTest(input,
     74                    ::testing::get<0>(GetParam()),
     75                    ::testing::get<1>(GetParam()),
     76                    ::testing::get<2>(GetParam()),
     77                    &output);
     78 
     79   // Verify the read data matches the input.
     80   for (size_t i = 0; i < num_channels; ++i)
     81     for (size_t j = 0; j < kFrames; ++j)
     82       EXPECT_EQ(input.channels()[i][j], output.channels()[i][j]);
     83 }
     84 
     85 INSTANTIATE_TEST_CASE_P(
     86     AudioRingBufferTest, AudioRingBufferTest,
     87     ::testing::Combine(::testing::Values(10, 20, 42),  // num_write_chunk_frames
     88                        ::testing::Values(1, 10, 17),   // num_read_chunk_frames
     89                        ::testing::Values(100, 256),    // buffer_frames
     90                        ::testing::Values(1, 4)));      // num_channels
     91 
     92 TEST_F(AudioRingBufferTest, MoveReadPosition) {
     93   const size_t kNumChannels = 1;
     94   const float kInputArray[] = {1, 2, 3, 4};
     95   const size_t kNumFrames = sizeof(kInputArray) / sizeof(*kInputArray);
     96   ChannelBuffer<float> input(kNumFrames, kNumChannels);
     97   input.SetDataForTesting(kInputArray, kNumFrames);
     98   AudioRingBuffer buf(kNumChannels, kNumFrames);
     99   buf.Write(input.channels(), kNumChannels, kNumFrames);
    100 
    101   buf.MoveReadPositionForward(3);
    102   ChannelBuffer<float> output(1, kNumChannels);
    103   buf.Read(output.channels(), kNumChannels, 1);
    104   EXPECT_EQ(4, output.channels()[0][0]);
    105   buf.MoveReadPositionBackward(3);
    106   buf.Read(output.channels(), kNumChannels, 1);
    107   EXPECT_EQ(2, output.channels()[0][0]);
    108 }
    109 
    110 }  // namespace webrtc
    111