blob: 183a043efb1898ca61f7a0c6ef544e4a13c7c94b [file] [log] [blame]
// Copyright 2022 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/format2/format.h"
#include <gtest/gtest.h>
#include "fidl/fuchsia.mediastreams/cpp/wire_types.h"
#include "src/media/audio/lib/format2/fixed.h"
using SampleType = fuchsia_audio::SampleType;
namespace media_audio {
TEST(FormatTest, CreateFromWire) {
fidl::Arena<> arena;
auto msg = fuchsia_audio::wire::Format::Builder(arena)
.sample_type(SampleType::kInt32)
.channel_count(2)
.frames_per_second(48000)
.Build();
Format format = Format::CreateOrDie(msg);
EXPECT_EQ(format.sample_type(), SampleType::kInt32);
EXPECT_EQ(format.channels(), 2);
EXPECT_EQ(format.frames_per_second(), 48000);
EXPECT_EQ(format.bytes_per_frame(), 8);
EXPECT_EQ(format.bytes_per_sample(), 4);
EXPECT_EQ(format.valid_bits_per_sample(), 32);
}
TEST(FormatTest, CreateFromNatural) {
fuchsia_audio::Format msg;
msg.sample_type() = SampleType::kInt32;
msg.channel_count() = 2;
msg.frames_per_second() = 48000;
auto format = Format::CreateOrDie(msg);
EXPECT_EQ(format.sample_type(), SampleType::kInt32);
EXPECT_EQ(format.channels(), 2);
EXPECT_EQ(format.frames_per_second(), 48000);
EXPECT_EQ(format.bytes_per_frame(), 8);
EXPECT_EQ(format.bytes_per_sample(), 4);
EXPECT_EQ(format.valid_bits_per_sample(), 32);
}
TEST(FormatTest, CreateFromHardwareWire) {
fidl::Arena<> arena;
auto msg = fuchsia_hardware_audio::wire::Format::Builder(arena)
.pcm_format(fuchsia_hardware_audio::wire::PcmFormat{
.number_of_channels = 2,
.sample_format = fuchsia_hardware_audio::SampleFormat::kPcmSigned,
.bytes_per_sample = 4,
.valid_bits_per_sample = 1, // anything <= 32 is ok
.frame_rate = 48000,
})
.Build();
auto format_result = Format::Create(msg);
ASSERT_TRUE(format_result.is_ok());
auto format = format_result.take_value();
EXPECT_EQ(format.sample_type(), SampleType::kInt32);
EXPECT_EQ(format.channels(), 2);
EXPECT_EQ(format.frames_per_second(), 48000);
EXPECT_EQ(format.bytes_per_frame(), 8);
EXPECT_EQ(format.bytes_per_sample(), 4);
EXPECT_EQ(format.valid_bits_per_sample(), 32);
}
TEST(FormatTest, CreateFromHardwareNatural) {
fidl::Arena<> arena;
auto msg = fuchsia_hardware_audio::Format({
.pcm_format = fuchsia_hardware_audio::PcmFormat({
.number_of_channels = 2,
.sample_format = fuchsia_hardware_audio::SampleFormat::kPcmFloat,
.bytes_per_sample = 4,
.valid_bits_per_sample = 32, // anything <= 32 is ok
.frame_rate = 48000,
}),
});
auto format_result = Format::Create(msg);
ASSERT_TRUE(format_result.is_ok());
auto format = format_result.take_value();
EXPECT_EQ(format.sample_type(), SampleType::kFloat32);
EXPECT_EQ(format.channels(), 2);
EXPECT_EQ(format.frames_per_second(), 48000);
EXPECT_EQ(format.bytes_per_frame(), 8);
EXPECT_EQ(format.bytes_per_sample(), 4);
EXPECT_EQ(format.valid_bits_per_sample(), 32);
}
TEST(FormatTest, CreateFromArgs) {
Format format = Format::CreateOrDie({
.sample_type = SampleType::kInt32,
.channels = 2,
.frames_per_second = 48000,
});
EXPECT_EQ(format.sample_type(), SampleType::kInt32);
EXPECT_EQ(format.channels(), 2);
EXPECT_EQ(format.frames_per_second(), 48000);
EXPECT_EQ(format.bytes_per_frame(), 8);
EXPECT_EQ(format.bytes_per_sample(), 4);
EXPECT_EQ(format.valid_bits_per_sample(), 32);
}
TEST(FormatTest, ToWireFidl) {
Format format = Format::CreateOrDie({
.sample_type = SampleType::kInt32,
.channels = 2,
.frames_per_second = 48000,
});
fidl::Arena<> arena;
auto msg = format.ToWireFidl(arena);
ASSERT_TRUE(msg.has_sample_type());
ASSERT_TRUE(msg.has_channel_count());
ASSERT_TRUE(msg.has_frames_per_second());
EXPECT_EQ(msg.sample_type(), SampleType::kInt32);
EXPECT_EQ(msg.channel_count(), 2u);
EXPECT_EQ(msg.frames_per_second(), 48000u);
}
TEST(FormatTest, ToNaturalFidl) {
Format format = Format::CreateOrDie({
.sample_type = SampleType::kInt32,
.channels = 2,
.frames_per_second = 48000,
});
auto msg = format.ToNaturalFidl();
ASSERT_TRUE(msg.sample_type().has_value());
ASSERT_TRUE(msg.channel_count().has_value());
ASSERT_TRUE(msg.frames_per_second().has_value());
EXPECT_EQ(*msg.sample_type(), SampleType::kInt32);
EXPECT_EQ(*msg.channel_count(), 2u);
EXPECT_EQ(*msg.frames_per_second(), 48000u);
}
TEST(FormatTest, ToLegacyMediaWireFidl) {
Format format = Format::CreateOrDie({
.sample_type = SampleType::kInt32,
.channels = 2,
.frames_per_second = 48000,
});
auto msg = format.ToLegacyMediaWireFidl();
EXPECT_EQ(msg.sample_format, fuchsia_media::AudioSampleFormat::kSigned24In32);
EXPECT_EQ(msg.channels, 2u);
EXPECT_EQ(msg.frames_per_second, 48000u);
}
TEST(FormatTest, ToLegacyMediastreamsWireFidl) {
Format format = Format::CreateOrDie({
.sample_type = SampleType::kInt32,
.channels = 2,
.frames_per_second = 48000,
});
auto msg = format.ToLegacyMediastreamsWireFidl();
EXPECT_EQ(msg.sample_format, fuchsia_mediastreams::AudioSampleFormat::kSigned24In32);
EXPECT_EQ(msg.channel_count, 2u);
EXPECT_EQ(msg.frames_per_second, 48000u);
}
TEST(FormatTest, OperatorEquals) {
Format format1 = Format::CreateOrDie({
.sample_type = SampleType::kFloat32,
.channels = 2,
.frames_per_second = 48000,
});
Format format2 = Format::CreateOrDie({
.sample_type = SampleType::kFloat32,
.channels = 2,
.frames_per_second = 48000,
});
EXPECT_EQ(format1, format2);
}
TEST(FormatTest, OperatorEqualsDifferentChannels) {
Format format1 = Format::CreateOrDie({
.sample_type = SampleType::kFloat32,
.channels = 2,
.frames_per_second = 48000,
});
Format format2 = Format::CreateOrDie({
.sample_type = SampleType::kFloat32,
.channels = 1,
.frames_per_second = 48000,
});
EXPECT_NE(format1, format2);
}
TEST(FormatTest, OperatorEqualsDifferentRates) {
Format format1 = Format::CreateOrDie({
.sample_type = SampleType::kFloat32,
.channels = 2,
.frames_per_second = 48000,
});
Format format2 = Format::CreateOrDie({
.sample_type = SampleType::kFloat32,
.channels = 2,
.frames_per_second = 96000,
});
EXPECT_NE(format1, format2);
}
TEST(FormatTest, OperatorEqualsDifferentSampleTypes) {
Format format1 = Format::CreateOrDie({
.sample_type = SampleType::kFloat32,
.channels = 2,
.frames_per_second = 48000,
});
Format format2 = Format::CreateOrDie({
.sample_type = SampleType::kUint8,
.channels = 2,
.frames_per_second = 48000,
});
EXPECT_NE(format1, format2);
}
TEST(FormatTest, IntegerFramesPer) {
Format format = Format::CreateOrDie({
.sample_type = SampleType::kFloat32,
.channels = 2,
.frames_per_second = 48000,
});
// Rounds up by default.
EXPECT_EQ(format.integer_frames_per(zx::msec(10) - zx::nsec(1)), 480);
EXPECT_EQ(format.integer_frames_per(zx::msec(10) + zx::nsec(0)), 480);
EXPECT_EQ(format.integer_frames_per(zx::msec(10) + zx::nsec(1)), 481);
// Round down should work too.
constexpr auto kFloor = media::TimelineRate::RoundingMode::Floor;
EXPECT_EQ(format.integer_frames_per(zx::msec(10) - zx::nsec(1), kFloor), 479);
EXPECT_EQ(format.integer_frames_per(zx::msec(10) + zx::nsec(0), kFloor), 480);
EXPECT_EQ(format.integer_frames_per(zx::msec(10) + zx::nsec(1), kFloor), 480);
}
TEST(FormatTest, FracFramesPer) {
Format format = Format::CreateOrDie({
.sample_type = SampleType::kFloat32,
.channels = 2,
.frames_per_second = 48000,
});
// For 48kHz audio, there are ~20833 ns/frame, which is ~2.5 ns/subframe
// (since Fixed has 8192 subframes/frame). Hence, adding or subtracting
// 1 ns should round to the same subframe.
// 4.5 frames = 93750ns.
const Fixed expected = ffl::FromRatio(9, 2);
const Fixed expected_minus_one = expected - Fixed::FromRaw(1);
const Fixed expected_plus_one = expected + Fixed::FromRaw(1);
// Rounds up by default.
EXPECT_EQ(format.frac_frames_per(zx::nsec(93750) - zx::nsec(1)), expected);
EXPECT_EQ(format.frac_frames_per(zx::nsec(93750) + zx::nsec(0)), expected);
EXPECT_EQ(format.frac_frames_per(zx::nsec(93750) + zx::nsec(1)), expected_plus_one);
// Round down should work too.
constexpr auto kFloor = media::TimelineRate::RoundingMode::Floor;
EXPECT_EQ(format.frac_frames_per(zx::nsec(93750) - zx::nsec(1), kFloor), expected_minus_one);
EXPECT_EQ(format.frac_frames_per(zx::nsec(93750) + zx::nsec(0), kFloor), expected);
EXPECT_EQ(format.frac_frames_per(zx::nsec(93750) + zx::nsec(1), kFloor), expected);
}
TEST(FormatTest, BytesPer) {
Format format = Format::CreateOrDie({
.sample_type = SampleType::kFloat32,
.channels = 2,
.frames_per_second = 48000,
});
// Rounds up by default.
EXPECT_EQ(format.bytes_per(zx::msec(10) - zx::nsec(1)), 480 * 8);
EXPECT_EQ(format.bytes_per(zx::msec(10) + zx::nsec(0)), 480 * 8);
EXPECT_EQ(format.bytes_per(zx::msec(10) + zx::nsec(1)), 481 * 8);
// Round down should work too.
constexpr auto kFloor = media::TimelineRate::RoundingMode::Floor;
EXPECT_EQ(format.bytes_per(zx::msec(10) - zx::nsec(1), kFloor), 479 * 8);
EXPECT_EQ(format.bytes_per(zx::msec(10) + zx::nsec(0), kFloor), 480 * 8);
EXPECT_EQ(format.bytes_per(zx::msec(10) + zx::nsec(1), kFloor), 480 * 8);
}
TEST(FormatTest, DurationPer) {
Format format = Format::CreateOrDie({
.sample_type = SampleType::kFloat32,
.channels = 2,
.frames_per_second = 300000,
});
// For 300kHz audio, there are ~3333 ns/frame, which is ~2.4 subframes/ns
// (since Fixed has 8192 subframes/frame). Hence, adding or subtracting
// 1 subframe should round to the same ns.
// For 300kHz audio, 4.5 frames = 15000ns.
const Fixed frame = ffl::FromRatio(9, 2);
// Rounds up by default.
EXPECT_EQ(format.duration_per(frame - Fixed::FromRaw(1)), zx::nsec(15000));
EXPECT_EQ(format.duration_per(frame + Fixed::FromRaw(0)), zx::nsec(15000));
EXPECT_EQ(format.duration_per(frame + Fixed::FromRaw(1)), zx::nsec(15001));
// Round down should work too.
constexpr auto kFloor = media::TimelineRate::RoundingMode::Floor;
EXPECT_EQ(format.duration_per(frame - Fixed::FromRaw(1), kFloor), zx::nsec(14999));
EXPECT_EQ(format.duration_per(frame + Fixed::FromRaw(0), kFloor), zx::nsec(15000));
EXPECT_EQ(format.duration_per(frame + Fixed::FromRaw(1), kFloor), zx::nsec(15000));
}
} // namespace media_audio