blob: 1e64d132893077617f98b96de45fe1a53892c934 [file] [log] [blame]
// 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/analysis/generators.h"
#include <vector>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
using testing::FloatEq;
using testing::Pointwise;
using ASF = fuchsia::media::AudioSampleFormat;
namespace media::audio {
// If unspecified, GenerateCosineAudio magnitude is "max" and phase is 0.
// Test default amplitude and phase for uint8: 0xFF (127 after being shifted) and 0x01 (-127)
// For each of these cases we generate a buffer with length 2 and (in-buffer) frequency 1.0
TEST(GeneratorsTest, GenerateCosine8Default) {
auto format = Format::Create<ASF::UNSIGNED_8>(1, 48000).take_value();
auto got = GenerateCosineAudio(format, 2, 1.0);
EXPECT_EQ(got.samples(), (std::vector<uint8_t>{0xFF, 0x01}));
}
// Test default amplitude and phase for int16: 0x7FFF (32767) and 0
TEST(GeneratorsTest, GenerateCosine16Default) {
auto format = Format::Create<ASF::SIGNED_16>(1, 48000).take_value();
auto got = GenerateCosineAudio(format, 2, 1.0);
EXPECT_EQ(got.samples(), (std::vector<int16_t>{0x7FFF, -0x7FFF}));
}
// Test default amplitude and phase for int24-in-32: 0x7FFFFF00 and 0
TEST(GeneratorsTest, GenerateCosine24Default) {
auto format = Format::Create<ASF::SIGNED_24_IN_32>(1, 48000).take_value();
auto got = GenerateCosineAudio(format, 2, 1.0);
EXPECT_EQ(got.samples(), (std::vector<int32_t>{0x7FFFFF00, -0x7FFFFF00}));
}
// Test default amplitude and phase for float32: 1.0 and 0
TEST(GeneratorsTest, GenerateCosineFloatDefault) {
auto format = Format::Create<ASF::FLOAT>(1, 48000).take_value();
auto got = GenerateCosineAudio(format, 2, 1.0);
EXPECT_THAT(got.samples(), Pointwise(FloatEq(), (std::vector<float>{1.0f, -1.0f})));
}
TEST(GeneratorsTest, GenerateCosine8) {
auto format = Format::Create<ASF::UNSIGNED_8>(1, 48000).take_value();
auto got = GenerateCosineAudio(format, 4, 1.0, 16.0);
// Frequency 1.0 produces a four-frame cycle. uint8 values are shifted by 0x80.
EXPECT_EQ(got.samples(), (std::vector<uint8_t>{0x90, 0x80, 0x70, 0x80}));
}
TEST(GeneratorsTest, GenerateCosine16) {
auto format = Format::Create<ASF::SIGNED_16>(1, 48000).take_value();
// Frequency of 0.0 produces constant value, with -.4 rounded toward zero.
auto got = GenerateCosineAudio(format, 2, 0, -32766.4);
EXPECT_EQ(got.samples(), (std::vector<int16_t>{-32766, -32766}));
}
// For 24-in-32, all output must be a multiple of 256 (bottom byte is 0)
TEST(GeneratorsTest, GenerateCosine24) {
auto format = Format::Create<ASF::SIGNED_24_IN_32>(1, 48000).take_value();
// PI phase with invert the output, so we expect [-12345.6, 0, +12345.6, 0].
// Output must be a multiple of 256, and 12345.6 is closer to 12288 than 12544.
auto got = GenerateCosineAudio(format, 4, 1.0, 12345.6, M_PI);
EXPECT_EQ(got.samples(), (std::vector<int32_t>{-12288, 0, 12288, 0}));
// PI/2 phase shifts the signal by one frame. We expect [0, -12416, 0, 12416]. Value 12416 is
// exactly midway between multiples of 256, so we expect to round out (away from zero).
got = GenerateCosineAudio(format, 4, 1.0, 12416);
EXPECT_EQ(got.samples(), (std::vector<int32_t>{12544, 0, -12544, 0}));
}
// Test float-based version of AccumCosine
TEST(GeneratorsTest, GenerateCosineFloat) {
auto format = Format::Create<ASF::FLOAT>(1, 48000).take_value();
// Frequency 2.0 produces alternating value. PI phase inverts the cosine output.
auto got = GenerateCosineAudio(format, 4, 2.0, 1.0, M_PI);
EXPECT_THAT(got.samples(), Pointwise(FloatEq(), (std::vector<float>{-1.0f, 1.0f, -1.0f, 1.0f})));
}
TEST(GeneratorsTest, PadToNearestPower2) {
auto format = Format::Create<ASF::UNSIGNED_8>(1, 48000).take_value();
auto unpadded = GenerateSequentialAudio(format, 6);
auto got = PadToNearestPower2(AudioBufferSlice(&unpadded));
EXPECT_EQ(got.samples(), (std::vector<uint8_t>{0, 1, 2, 3, 4, 5, 0x80, 0x80}));
}
} // namespace media::audio