diff --git a/src/common/timecode.h b/src/common/timecode.h index 73ac9f797..abe435677 100644 --- a/src/common/timecode.h +++ b/src/common/timecode.h @@ -105,6 +105,14 @@ public: return m_timecode * 9 / 100000; } + T to_samples(T sample_rate) const { + if (!m_valid) + throw std::domain_error{"invalid timecode"}; + if (!sample_rate) + throw std::domain_error{"invalid sample rate"}; + return (m_timecode * sample_rate / 100000000 + 5) / 10; + } + // arithmetic basic_timecode_c operator +=(basic_timecode_c const &other) { if (!m_valid || !other.m_valid) @@ -186,6 +194,12 @@ public: static basic_timecode_c factor(T value) { return basic_timecode_c{value}; } + + static basic_timecode_c samples(T samples, T sample_rate) { + if (!sample_rate) + throw std::domain_error{"invalid sample rate"}; + return basic_timecode_c{(samples * 10000000000 / sample_rate + 5) / 10}; + } }; typedef basic_timecode_c timecode_c; diff --git a/tests/unit/common/basic_timecode_c.cpp b/tests/unit/common/basic_timecode_c.cpp index 4bab90fbf..e74a8ee5c 100644 --- a/tests/unit/common/basic_timecode_c.cpp +++ b/tests/unit/common/basic_timecode_c.cpp @@ -113,6 +113,26 @@ TEST(BasicTimecode, ThrowOnDeconstructionOfInvalid) { EXPECT_NO_THROW(timecode_c{}.to_ns(1)); } +TEST(BasicTimecode, ConstructFromSamples) { + EXPECT_EQ(timecode_c::samples( 0, 48000).to_ns(), 0); + EXPECT_EQ(timecode_c::samples( 19999, 48000).to_ns(), 416645833); + EXPECT_EQ(timecode_c::samples( 20000, 48000).to_ns(), 416666667); + EXPECT_EQ(timecode_c::samples( 48000, 48000).to_ns(), 1000000000); + EXPECT_EQ(timecode_c::samples(123456, 48000).to_ns(), 2572000000); + + EXPECT_THROW(timecode_c::samples(123, 0), std::domain_error); +} + +TEST(BasicTimecode, DeconstructToSamples) { + EXPECT_EQ(timecode_c::ns( 0).to_samples(48000), 0); + EXPECT_EQ(timecode_c::ns( 416645833).to_samples(48000), 19999); + EXPECT_EQ(timecode_c::ns( 416666667).to_samples(48000), 20000); + EXPECT_EQ(timecode_c::ns(1000000000).to_samples(48000), 48000); + EXPECT_EQ(timecode_c::ns(2572000000).to_samples(48000), 123456); + + EXPECT_THROW(timecode_c::ns(123).to_samples(0), std::domain_error); +} + TEST(BasicTimecode, Resetting) { auto v = timecode_c::ns(1);