From 2024e32085ffa497e2066a143089311b04676ab4 Mon Sep 17 00:00:00 2001 From: Maciej Kisielewski Date: Thu, 12 Sep 2019 13:19:00 +0200 Subject: dont drain capture PCMs, drop them instead Signed-off-by: Maciej Kisielewski --- src/alsa_test.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/alsa_test.cpp b/src/alsa_test.cpp index 5145c91..dd7eeb4 100644 --- a/src/alsa_test.cpp +++ b/src/alsa_test.cpp @@ -102,9 +102,22 @@ struct Pcm { + string(". ") + string(snd_strerror(res)); throw std::system_error(ec, msg); } + logger.info() << "PCM opened. Name: " << device_name << " PCM handle: " + << pcm_handle << " PCM mode: " + << (int(mode) ? "capture" : "playback") << std::endl; } ~Pcm() { - snd_pcm_drain(this->pcm_handle); + switch (mode) { + case Mode::playback: + logger.info() << "Draining PCM " << pcm_handle << std::endl; + snd_pcm_drain(this->pcm_handle); + break; + case Mode::capture: + logger.info() << "Dropping PCM " << pcm_handle << std::endl; + snd_pcm_drop(this->pcm_handle); + break; + } + logger.info() << "Closing PCM " << pcm_handle << std::endl; snd_pcm_close(this->pcm_handle); } void drain() { @@ -234,6 +247,7 @@ private: snd_pcm_t *pcm_handle; unsigned rate; snd_pcm_uframes_t period; + Mode mode; }; template<> -- cgit v1.2.3 From 773339d3688089e418fed13f20732e8486034968 Mon Sep 17 00:00:00 2001 From: Maciej Kisielewski Date: Fri, 13 Sep 2019 18:10:53 +0200 Subject: alsa_test: fix warnings regarding no return statement --- src/alsa_test.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/alsa_test.cpp b/src/alsa_test.cpp index dd7eeb4..3e9ded5 100644 --- a/src/alsa_test.cpp +++ b/src/alsa_test.cpp @@ -54,7 +54,9 @@ private: Level level; struct NullStream : std::ostream { template - NullStream& operator<<(T const&) {} + NullStream& operator<<(T const&) { + return *this; + } }; NullStream nullStream; }; @@ -327,6 +329,7 @@ int playback_test(float duration, int sampling_rate, const char* capture_pcm, co auto player = Alsa::Pcm(); player.set_params(sampling_rate); player.sine(440, duration, 0.5f); + return 0; } template -- cgit v1.2.3 From bfd58c26d50754cd7b362252608c3e0fa88eccb2 Mon Sep 17 00:00:00 2001 From: Maciej Kisielewski Date: Fri, 13 Sep 2019 18:11:12 +0200 Subject: alsa_test: use proper AlsaError --- src/alsa_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/alsa_test.cpp b/src/alsa_test.cpp index 3e9ded5..58a66e8 100644 --- a/src/alsa_test.cpp +++ b/src/alsa_test.cpp @@ -102,7 +102,7 @@ struct Pcm { auto ec = std::error_code(-res, std::system_category()); auto msg = string("Failed to open device: ") + string(device_name) + string(". ") + string(snd_strerror(res)); - throw std::system_error(ec, msg); + throw AlsaError(msg); } logger.info() << "PCM opened. Name: " << device_name << " PCM handle: " << pcm_handle << " PCM mode: " -- cgit v1.2.3 From c9956610c0a67d91dac8d0744666f77c5e1368b9 Mon Sep 17 00:00:00 2001 From: Maciej Kisielewski Date: Fri, 13 Sep 2019 18:12:45 +0200 Subject: alsa_test: add list-devices subcmd --- src/alsa_test.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'src') diff --git a/src/alsa_test.cpp b/src/alsa_test.cpp index 58a66e8..deb2d6d 100644 --- a/src/alsa_test.cpp +++ b/src/alsa_test.cpp @@ -322,6 +322,31 @@ private: snd_mixer_selem_id_t *sid; snd_mixer_elem_t* elem; }; + +std::vector get_devices(std::string io) { + std::vector result; + void **out; + int err = snd_device_name_hint(-1 /* all cards */, "pcm", &out); + if (err) { + logger.normal() << "Couldn't get the device hints" << std::endl; + return result; + } + while (*out) { + const char *name = snd_device_name_get_hint(*out, "NAME"); + const char *desc = snd_device_name_get_hint(*out, "DESC"); + const char *ioid = snd_device_name_get_hint(*out, "IOID"); + if (ioid == nullptr) ioid = "Both"; + logger.info() << "Got a device hint. Name: " << name + << " Description: " << desc + << " IOID: " << ioid << std::endl; + std::string direction{ioid}; + if (direction == io) { + result.push_back(std::string{name}); + } + out++; + } + return result; +} }; //namespace Alsa template @@ -407,6 +432,24 @@ int list_formats(){ std::cout << "description: " << format.second << std::endl; std::cout << std::endl; } + return 0; +} + +int list_devices() { + auto playback = Alsa::get_devices("Output"); + auto record = Alsa::get_devices("Input"); + auto both = Alsa::get_devices("Both"); + std::copy(both.begin(), both.end(), std::back_inserter(playback)); + std::copy(both.begin(), both.end(), std::back_inserter(record)); + std::cout << "Playback devices: " << std::endl; + for (auto i = playback.cbegin(); i != playback.cend(); ++i) { + std::cout << *i << std::endl; + } + std::cout << "\n\nRecording devices: " << std::endl; + for (auto i = record.cbegin(); i != record.cend(); ++i) { + std::cout << *i << std::endl; + } + return 0; } void set_volumes(const std::string playback_pcm, const std::string capture_pcm) { @@ -503,6 +546,9 @@ int main(int argc, char *argv[]) { else if (scenario == "list-formats") { return list_formats(); } + else if (scenario == "list-devices") { + return list_devices(); + } if (scenarios.find(args[1]) == scenarios.end()) { std::cerr << args[1] << " scenario not found!" << std::endl; return 1; -- cgit v1.2.3 From 96fb8ba3da210d103b75805e00f422a4d431a29b Mon Sep 17 00:00:00 2001 From: Maciej Kisielewski Date: Fri, 13 Sep 2019 18:13:17 +0200 Subject: alsa_test: add fallback loopback scenario --- src/alsa_test.cpp | 58 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 48 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/alsa_test.cpp b/src/alsa_test.cpp index deb2d6d..fc9f1f4 100644 --- a/src/alsa_test.cpp +++ b/src/alsa_test.cpp @@ -377,22 +377,28 @@ float dominant_freq(storage_type *buff, int buffsize, int rate) { } template int loopback_test(float duration, int sampling_rate, const char* capture_pcm, const char* playback_pcm) { + const float test_freq = 440.0f; int buffsize = static_cast(ceil(float(sampling_rate * 2) * duration)); - auto *buff = new storage_type[buffsize]; + std::vector buff(buffsize); for (int attempt = 0; attempt < 3; ++attempt) { for (int i=0; i (capture_pcm, Alsa::Pcm::Mode::capture); recorder.set_params(sampling_rate); std::thread rec_thread([&recorder, &buff, &buffsize]() mutable{ - recorder.record(buff, buffsize); + recorder.record(&buff[0], buffsize); }); - const float test_freq = 440.0f; - auto player = Alsa::Pcm(playback_pcm); - player.set_params(sampling_rate); - player.sine(test_freq, duration, 0.5f); - player.drain(); - rec_thread.join(); - float dominant = dominant_freq(buff, buffsize, sampling_rate * 2); + try { + auto player = Alsa::Pcm(playback_pcm); + player.set_params(sampling_rate); + player.sine(test_freq, duration, 0.5f); + player.drain(); + rec_thread.join(); + } + catch (Alsa::AlsaError& exc) { + rec_thread.join(); + return 1; + } + float dominant = dominant_freq(&buff[0], buffsize, sampling_rate * 2); if (dominant > 0.0f) { //buff contains stereo samples, so the sampling rate can be considered 88200 logger.normal() << "Dominant frequency: " << dominant << std::endl; @@ -407,6 +413,33 @@ int loopback_test(float duration, int sampling_rate, const char* capture_pcm, co } return 1; } +template +int fallback_loopback(float duration, int sampling_rate, const char* _1, const char* _2) { + auto playback = Alsa::get_devices("Output"); + auto record = Alsa::get_devices("Input"); + auto both = Alsa::get_devices("Both"); + std::copy(both.begin(), both.end(), std::back_inserter(playback)); + std::copy(both.begin(), both.end(), std::back_inserter(record)); + for (auto player = playback.cbegin(); player != playback.cend(); ++player) { + if (*player == std::string{"surround40:CARD=PCH,DEV=0"}) { + continue; + } + for (auto recorder = record.cbegin(); recorder != record.cend(); ++recorder) { + logger.normal() << "Trying combination " << *player << " -> " << *recorder << std::endl; + try { + int error = loopback_test( + duration, sampling_rate, recorder->c_str(), player->c_str()); + if (!error) { + return 0; + } + } + catch(Alsa::AlsaError& exc) { + logger.normal() << "Alsa problem: " << exc.what() << std::endl; + } + } + } + return 1; +} int list_formats(){ const char* env_var = std::getenv("ALSA_TEST_FORMATS"); std::vector picked_formats; @@ -497,14 +530,17 @@ int main(int argc, char *argv[]) { if (sample_format == "float") { scenarios["playback"] = playback_test; scenarios["loopback"] = loopback_test; + scenarios["fallback"] = fallback_loopback; } else if (sample_format == "int16") { scenarios["playback"] = playback_test; scenarios["loopback"] = loopback_test; + scenarios["fallback"] = fallback_loopback; } else if (sample_format == "uint16") { scenarios["playback"] = playback_test; scenarios["loopback"] = loopback_test; + scenarios["fallback"] = fallback_loopback; } else { assert(!"MISSING IF-ELSES FOR FORMATS"); @@ -541,7 +577,9 @@ int main(int argc, char *argv[]) { return scenarios["playback"](duration, sampling_rate, capture_pcm.c_str(), playback_pcm.c_str()); } else if (scenario == "loopback") { - return scenarios["loopback"](duration, sampling_rate, capture_pcm.c_str(), playback_pcm.c_str()); + int error = scenarios["loopback"](duration, sampling_rate, capture_pcm.c_str(), playback_pcm.c_str()); + if (!error) return 0; + return scenarios["fallback"](duration, sampling_rate, nullptr, nullptr); } else if (scenario == "list-formats") { return list_formats(); -- cgit v1.2.3