From 411a7d88e4121e04da1f63fa9072fd6444f753a2 Mon Sep 17 00:00:00 2001 From: dvdli Date: Wed, 10 Mar 2021 18:17:23 +0800 Subject: add a loopback test for floating point PCM --- tests/src/pcm_loopback_test.cc | 118 ++++++++++++++++++++++++++++------------- 1 file changed, 81 insertions(+), 37 deletions(-) (limited to 'tests/src/pcm_loopback_test.cc') diff --git a/tests/src/pcm_loopback_test.cc b/tests/src/pcm_loopback_test.cc index 6a3ffb8..5c6ff4d 100644 --- a/tests/src/pcm_loopback_test.cc +++ b/tests/src/pcm_loopback_test.cc @@ -64,6 +64,7 @@ public: template struct PcmFormat { using Type = void; + static constexpr pcm_format kFormat = F; static constexpr int32_t kMax = 0; static constexpr int32_t kMin = 0; }; @@ -71,10 +72,19 @@ struct PcmFormat { template<> struct PcmFormat { using Type = int16_t; + static constexpr pcm_format kFormat = PCM_FORMAT_S16_LE; static constexpr Type kMax = std::numeric_limits::max(); static constexpr Type kMin = std::numeric_limits::min(); }; +template<> +struct PcmFormat { + using Type = float; + static constexpr pcm_format kFormat = PCM_FORMAT_FLOAT_LE; + static constexpr Type kMax = 1.0; + static constexpr Type kMin = -1.0; +}; + // CH: channels // SR: sampling rate // FQ: sine wave frequency @@ -139,43 +149,77 @@ static double Energy(T *buffer, size_t samples) { return sum; } -TEST(PcmLoopbackTest, LoopbackS16le) { +template +class PcmLoopbackTest : public ::testing::Test { + protected: + PcmLoopbackTest() = default; + virtual ~PcmLoopbackTest() = default; + + void SetUp() override { + static constexpr pcm_config kInConfig = { + .channels = kDefaultChannels, + .rate = kDefaultSamplingRate, + .period_size = kDefaultPeriodSize, + .period_count = kDefaultPeriodCount, + .format = kPcmForamt, + .start_threshold = 0, + .stop_threshold = 0, + .silence_threshold = 0, + .silence_size = 0, + }; + pcm_in = pcm_open(kLoopbackCard, kLoopbackCaptureDevice, PCM_IN, &kInConfig); + ASSERT_TRUE(pcm_is_ready(pcm_in)); + + static constexpr pcm_config kOutConfig = { + .channels = kDefaultChannels, + .rate = kDefaultSamplingRate, + .period_size = kDefaultPeriodSize, + .period_count = kDefaultPeriodCount, + .format = kPcmForamt, + .start_threshold = kDefaultPeriodSize, + .stop_threshold = kDefaultPeriodSize * kDefaultPeriodCount, + .silence_threshold = 0, + .silence_size = 0, + }; + pcm_out = pcm_open(kLoopbackCard, kLoopbackPlaybackDevice, PCM_OUT, &kOutConfig); + ASSERT_TRUE(pcm_is_ready(pcm_out)); + ASSERT_EQ(pcm_link(pcm_in, pcm_out), 0); + } + + void TearDown() override { + ASSERT_EQ(pcm_unlink(pcm_in), 0); + pcm_close(pcm_in); + pcm_close(pcm_out); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + static constexpr unsigned int kDefaultChannels = 2; static constexpr unsigned int kDefaultSamplingRate = 48000; static constexpr unsigned int kDefaultPeriodSize = 1024; static constexpr unsigned int kDefaultPeriodCount = 3; static constexpr unsigned int kDefaultPeriodTimeInMs = kDefaultPeriodSize * 1000 / kDefaultSamplingRate; + static constexpr pcm_format kPcmForamt = F::Format; + pcm *pcm_in; + pcm *pcm_out; +}; - static constexpr pcm_config kInConfig = { - .channels = kDefaultChannels, - .rate = kDefaultSamplingRate, - .period_size = kDefaultPeriodSize, - .period_count = kDefaultPeriodCount, - .format = PCM_FORMAT_S16_LE, - .start_threshold = 0, - .stop_threshold = 0, - .silence_threshold = 0, - .silence_size = 0, - }; - pcm *pcm_in = pcm_open(kLoopbackCard, kLoopbackCaptureDevice, PCM_IN, &kInConfig); - ASSERT_TRUE(pcm_is_ready(pcm_in)); - - static constexpr pcm_config kOutConfig = { - .channels = kDefaultChannels, - .rate = kDefaultSamplingRate, - .period_size = kDefaultPeriodSize, - .period_count = kDefaultPeriodCount, - .format = PCM_FORMAT_S16_LE, - .start_threshold = kDefaultPeriodSize, - .stop_threshold = kDefaultPeriodSize * kDefaultPeriodCount, - .silence_threshold = 0, - .silence_size = 0, - }; - pcm *pcm_out = pcm_open(kLoopbackCard, kLoopbackPlaybackDevice, PCM_OUT, &kOutConfig); - ASSERT_TRUE(pcm_is_ready(pcm_out)); +using S16bitlePcmFormat = PcmFormat; +using FloatPcmFormat = PcmFormat; - ASSERT_EQ(pcm_link(pcm_in, pcm_out), 0); +using Formats = ::testing::Types; + +TYPED_TEST_SUITE(PcmLoopbackTest, Formats); + +TYPED_TEST(PcmLoopbackTest, Loopback) { + static constexpr unsigned int kDefaultChannels = this->kDefaultChannels; + static constexpr unsigned int kDefaultSamplingRate = this->kDefaultSamplingRate; + static constexpr unsigned int kDefaultPeriodSize = this->kDefaultPeriodSize; + // static constexpr unsigned int kDefaultPeriodCount = this->kDefaultPeriodCount; + static constexpr unsigned int kDefaultPeriodTimeInMs = this->kDefaultPeriodTimeInMs; + static constexpr pcm_format kPcmForamt = this->kPcmForamt; + pcm *pcm_in = this->pcm_in; + pcm *pcm_out = this->pcm_out; bool stopping = false; ASSERT_EQ(pcm_get_subdevice(pcm_in), pcm_get_subdevice(pcm_out)); @@ -190,23 +234,26 @@ TEST(PcmLoopbackTest, LoopbackS16le) { if (res == -1) { std::cout << pcm_get_error(pcm_in) << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(kDefaultPeriodTimeInMs)); + counter++; continue; } - EXPECT_EQ(pcm_readi(pcm_in, buffer.get(), frames), frames) << counter; + // Test the energy of the buffer after the sine tone samples fill in the buffer. // Therefore, check the buffer 5 times later. if (counter >= 5) { - double e = Energy(buffer.get(), frames * kInConfig.channels); + double e = Energy(buffer.get(), frames * kDefaultChannels); EXPECT_GT(e, 0.0) << counter; } counter++; } + std::cout << "read count = " << counter << std::endl; }); std::thread playback([pcm_out, &stopping] { - SineToneGenerator<2, 48000, 1000, 0, PCM_FORMAT_S16_LE> generator; + SineToneGenerator generator; size_t buffer_size = pcm_frames_to_bytes(pcm_out, kDefaultPeriodSize); unsigned int frames = pcm_bytes_to_frames(pcm_out, buffer_size); + std::cout << buffer_size << std::endl; auto buffer = std::make_unique(buffer_size); int32_t counter = 0; while (!stopping) { @@ -214,16 +261,13 @@ TEST(PcmLoopbackTest, LoopbackS16le) { EXPECT_EQ(pcm_writei(pcm_out, buffer.get(), frames), frames) << counter; counter++; } + std::cout << "write count = " << counter << std::endl; }); - std::this_thread::sleep_for(std::chrono::seconds(1)); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); stopping = true; capture.join(); playback.join(); - - ASSERT_EQ(pcm_unlink(pcm_in), 0); - pcm_close(pcm_in); - pcm_close(pcm_out); } } // namespace testing -- cgit v1.2.3