// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/media/audio/lib/format/audio_buffer.h"

#include <fuchsia/media/cpp/fidl.h>

#include <vector>

#include <gmock/gmock.h>
#include <gtest/gtest.h>

namespace media::audio {

constexpr auto kSampleFormat = fuchsia::media::AudioSampleFormat::SIGNED_16;
static const Format kFormat = Format::Create(fuchsia::media::AudioStreamType{
                                                 .sample_format = kSampleFormat,
                                                 .channels = 2,
                                                 .frames_per_second = 48000,
                                             })
                                  .take_value();

TEST(AudioBufferTest, Basics) {
  AudioBuffer<kSampleFormat> buffer(kFormat, 10);
  EXPECT_EQ(buffer.NumFrames(), 10);
  EXPECT_EQ(buffer.NumSamples(), buffer.NumFrames() * 2);
  EXPECT_EQ(buffer.NumBytes(), buffer.NumSamples() * static_cast<int64_t>(sizeof(int16_t)));

  AudioBufferSlice slice1(&buffer);
  EXPECT_EQ(slice1.NumFrames(), buffer.NumFrames());
  EXPECT_EQ(slice1.NumSamples(), buffer.NumSamples());
  EXPECT_EQ(slice1.NumBytes(), buffer.NumBytes());

  AudioBufferSlice slice2(&buffer, 5, 8);
  EXPECT_EQ(slice2.NumFrames(), 3);
  EXPECT_EQ(slice2.NumSamples(), 6);
  EXPECT_EQ(slice2.NumBytes(), 12);
}

// Verify Buffer::samples (lvalue and rvalue), and SampleIndex() / SampleAt() for Buffer and Slice
TEST(AudioBufferTest, SampleAccess) {
  AudioBuffer<kSampleFormat> buffer(kFormat, 10);
  buffer.samples()[0] = 10000;
  buffer.samples()[1] = 11;
  buffer.samples()[10] = 222;
  buffer.samples()[15] = 3333;

  EXPECT_EQ(buffer.SampleIndex(0, 0), 0);
  EXPECT_EQ(buffer.SampleIndex(0, 1), 1);
  EXPECT_EQ(buffer.SampleIndex(5, 0), 10);
  EXPECT_EQ(buffer.SampleIndex(7, 1), 15);

  EXPECT_EQ(buffer.SampleAt(0, 0), 10000);
  EXPECT_EQ(buffer.SampleAt(0, 1), 11);
  EXPECT_EQ(buffer.SampleAt(5, 0), 222);
  EXPECT_EQ(buffer.SampleAt(7, 1), 3333);

  AudioBufferSlice slice(&buffer);
  EXPECT_EQ(slice.SampleIndex(0, 0), buffer.SampleIndex(0, 0));
  EXPECT_EQ(slice.SampleIndex(7, 1), buffer.SampleIndex(7, 1));

  EXPECT_EQ(slice.SampleAt(0, 0), buffer.samples()[0]);
  EXPECT_EQ(slice.SampleAt(5, 0), buffer.samples()[10]);
  EXPECT_EQ(slice.SampleAt(0, 1), buffer.SampleAt(0, 1));
  EXPECT_EQ(slice.SampleAt(7, 1), buffer.SampleAt(7, 1));

  AudioBufferSlice slice2(&buffer, 5, 8);
  EXPECT_EQ(slice2.SampleIndex(0, 1), 11);
  EXPECT_EQ(slice2.SampleIndex(2, 0), 14);

  EXPECT_EQ(slice2.SampleAt(0, 0), buffer.SampleAt(5, 0));
  EXPECT_EQ(slice2.SampleAt(2, 1), slice.SampleAt(7, 1));

  EXPECT_EQ(*(slice2.begin()), buffer.SampleAt(5, 0));
  EXPECT_EQ(*(slice2.end() - 1), slice.SampleAt(7, 1));
}

// An AudioBufferSlice can be appended to an AudioBuffer
TEST(AudioBufferTest, AppendSlice) {
  // 2 frames with 2 channels per frame, so buffer has samples [0..3]
  AudioBuffer<kSampleFormat> buffer(kFormat, 2);
  buffer.samples()[2] = 2345;

  // buffer2 has 3 frames, thus samples [0..5]
  AudioBuffer<kSampleFormat> buffer2(kFormat, 3);
  buffer2.samples()[3] = 3333;

  // slice contains only buffer2[2..5]
  AudioBufferSlice slice2(&buffer2, 1, 3);

  // Appending slice[] will copy buffer2[2..5] to buffer[4..7]
  buffer.Append(slice2);
  EXPECT_EQ(buffer.NumFrames(), 4);
  EXPECT_EQ(buffer.NumSamples(), 8);
  EXPECT_EQ(buffer.NumBytes(), 16);
  EXPECT_EQ(buffer.samples()[2], 2345);
  EXPECT_EQ(buffer.samples()[5], 3333);

  // buffer2 and slice2 should be unchanged
  EXPECT_EQ(buffer2.samples()[3], 3333);
  EXPECT_EQ(buffer2.NumFrames(), 3);
  EXPECT_EQ(buffer2.NumSamples(), 6);
  EXPECT_EQ(buffer2.NumBytes(), 12);

  EXPECT_EQ(slice2.SampleAt(0, 1), 3333);
  EXPECT_EQ(slice2.NumFrames(), 2);
  EXPECT_EQ(slice2.NumSamples(), 4);
  EXPECT_EQ(slice2.NumBytes(), 8);
}

// Multiple mono AudioBufferSlice can be interleaved to an AudioBuffer
TEST(AudioBufferTest, Interleave) {
  constexpr int32_t kFrameRate = 32000;
  const Format kFormat1 = Format::Create(fuchsia::media::AudioStreamType{
                                             .sample_format = kSampleFormat,
                                             .channels = 1,
                                             .frames_per_second = kFrameRate,
                                         })
                              .take_value();

  // Mono 20 frames, with values 0..19
  AudioBuffer<kSampleFormat> buffer(kFormat1, 20);
  for (int16_t frame = 0; frame < 20; ++frame) {
    buffer.samples()[frame] = frame;
  }

  // Slice #0 has vals 0..3; #1 has 4..7; #2 8..11; #3 12..15; #4 16..19.
  auto slices = std::vector<AudioBufferSlice<kSampleFormat>>();
  slices.push_back(AudioBufferSlice(&buffer, 0, 4));
  slices.push_back(AudioBufferSlice(&buffer, 4, 8));
  slices.push_back(AudioBufferSlice(&buffer, 8, 12));
  slices.push_back(AudioBufferSlice(&buffer, 12, 16));
  slices.push_back(AudioBufferSlice(&buffer, 16, 20));

  // Interleave these five slices into a 5-channel file.
  auto interleaved = AudioBuffer<kSampleFormat>::Interleave(slices);
  EXPECT_EQ(interleaved.format().channels(), 5);

  // All characteristics except channels must match the original slices.
  EXPECT_EQ(interleaved.NumFrames(), 4);
  EXPECT_EQ(interleaved.format().frames_per_second(), kFrameRate);
  EXPECT_EQ(interleaved.format().sample_format(), kSampleFormat);

  // In resulting buffer, first frame has values [0,4,8,12,16], second frame [1,5,9,13,17], etc.
  for (auto frame = 0u; frame < interleaved.NumFrames(); ++frame) {
    // Within a frame, values should increase by 4 with each successive channel.
    EXPECT_EQ(interleaved.SampleAt(frame, 0), static_cast<int16_t>(frame));
    EXPECT_EQ(interleaved.SampleAt(frame, 1), interleaved.SampleAt(frame, 0) + 4);
    EXPECT_EQ(interleaved.SampleAt(frame, 2), interleaved.SampleAt(frame, 1) + 4);
    EXPECT_EQ(interleaved.SampleAt(frame, 3), interleaved.SampleAt(frame, 2) + 4);
    EXPECT_EQ(interleaved.SampleAt(frame, 4), interleaved.SampleAt(frame, 3) + 4);
  }
}

}  // namespace media::audio
