Make buffer time and fragments configurable

This commit is contained in:
badaix 2020-11-23 13:51:19 +01:00
parent 2e64e53b5d
commit c1a5a52bc6
5 changed files with 48 additions and 18 deletions

View file

@ -22,11 +22,14 @@
#include "common/str_compat.hpp" #include "common/str_compat.hpp"
#include "common/utils/string_utils.hpp" #include "common/utils/string_utils.hpp"
//#define BUFFER_TIME 120000 using namespace std::chrono_literals;
#define PERIOD_TIME 30000 using namespace std;
static constexpr std::chrono::milliseconds BUFFER_TIME = 80ms;
static constexpr int PERIODS = 4;
#define exp10(x) (exp((x)*log(10))) #define exp10(x) (exp((x)*log(10)))
using namespace std;
static constexpr auto LOG_TAG = "Alsa"; static constexpr auto LOG_TAG = "Alsa";
static constexpr auto DEFAULT_MIXER = "PCM"; static constexpr auto DEFAULT_MIXER = "PCM";
@ -61,6 +64,16 @@ AlsaPlayer::AlsaPlayer(boost::asio::io_context& io_context, const ClientSettings
LOG(DEBUG, LOG_TAG) << "Mixer: " << mixer_name_ << ", device: " << mixer_device_ << "\n"; LOG(DEBUG, LOG_TAG) << "Mixer: " << mixer_name_ << ", device: " << mixer_device_ << "\n";
} }
buffer_time_ = BUFFER_TIME;
periods_ = PERIODS;
auto params = utils::string::split_pairs(settings.parameter, ',', '=');
if (params.find("buffer_time") != params.end())
buffer_time_ = std::chrono::milliseconds(std::max(cpt::stoi(params["buffer_time"]), 10));
if (params.find("fragments") != params.end())
periods_ = std::max(cpt::stoi(params["fragments"]), 2);
LOG(INFO, LOG_TAG) << "Using buffer_time: " << buffer_time_.count() / 1000 << " ms, fragments: " << periods_ << "\n";
} }
@ -334,15 +347,12 @@ void AlsaPlayer::initAlsa()
if ((err = snd_pcm_hw_params_set_rate_near(handle_, params, &rate, nullptr)) < 0) if ((err = snd_pcm_hw_params_set_rate_near(handle_, params, &rate, nullptr)) < 0)
throw SnapException("Can't set rate: " + string(snd_strerror(err))); throw SnapException("Can't set rate: " + string(snd_strerror(err)));
unsigned int period_time; unsigned int buffer_time = buffer_time_.count();
snd_pcm_hw_params_get_period_time_max(params, &period_time, nullptr); if ((err = snd_pcm_hw_params_set_buffer_time_near(handle_, params, &buffer_time, nullptr)) < 0)
if (period_time > PERIOD_TIME) throw SnapException("Can't set buffer time: " + string(snd_strerror(err)));
period_time = PERIOD_TIME;
unsigned int buffer_time = 4 * period_time; if ((err = snd_pcm_hw_params_set_periods(handle_, params, periods_, 0)) < 0)
throw SnapException("Can't set periods: " + string(snd_strerror(err)));
snd_pcm_hw_params_set_period_time_near(handle_, params, &period_time, nullptr);
snd_pcm_hw_params_set_buffer_time_near(handle_, params, &buffer_time, nullptr);
// long unsigned int periodsize = stream_->format.msRate() * 50;//2*rate/50; // long unsigned int periodsize = stream_->format.msRate() * 50;//2*rate/50;
// if ((pcm = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, params, &periodsize)) < 0) // if ((pcm = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, params, &periodsize)) < 0)
@ -365,9 +375,15 @@ void AlsaPlayer::initAlsa()
snd_pcm_hw_params_get_period_size(params, &frames_, nullptr); snd_pcm_hw_params_get_period_size(params, &frames_, nullptr);
LOG(DEBUG, LOG_TAG) << "frames: " << frames_ << "\n"; LOG(DEBUG, LOG_TAG) << "frames: " << frames_ << "\n";
snd_pcm_hw_params_get_buffer_time(params, &tmp, nullptr);
LOG(DEBUG, LOG_TAG) << "buffer time: " << tmp << "\n";
snd_pcm_hw_params_get_period_time(params, &tmp, nullptr); snd_pcm_hw_params_get_period_time(params, &tmp, nullptr);
LOG(DEBUG, LOG_TAG) << "period time: " << tmp << "\n"; LOG(DEBUG, LOG_TAG) << "period time: " << tmp << "\n";
snd_pcm_hw_params_get_periods(params, &tmp, nullptr);
LOG(DEBUG, LOG_TAG) << "periods: " << tmp << "\n";
snd_pcm_sw_params_t* swparams; snd_pcm_sw_params_t* swparams;
snd_pcm_sw_params_alloca(&swparams); snd_pcm_sw_params_alloca(&swparams);
snd_pcm_sw_params_current(handle_, swparams); snd_pcm_sw_params_current(handle_, swparams);

View file

@ -20,7 +20,9 @@
#define ALSA_PLAYER_H #define ALSA_PLAYER_H
#include "player.hpp" #include "player.hpp"
#include <alsa/asoundlib.h> #include <alsa/asoundlib.h>
#include <chrono>
/// Audio Player /// Audio Player
@ -73,6 +75,9 @@ private:
std::chrono::time_point<std::chrono::steady_clock> last_change_; std::chrono::time_point<std::chrono::steady_clock> last_change_;
std::recursive_mutex mutex_; std::recursive_mutex mutex_;
boost::asio::steady_timer timer_; boost::asio::steady_timer timer_;
std::chrono::microseconds buffer_time_;
unsigned int periods_;
}; };

View file

@ -25,8 +25,11 @@
#include "common/utils/string_utils.hpp" #include "common/utils/string_utils.hpp"
#include "pulse_player.hpp" #include "pulse_player.hpp"
using namespace std::chrono_literals;
using namespace std; using namespace std;
static constexpr std::chrono::milliseconds BUFFER_TIME = 80ms;
static constexpr auto LOG_TAG = "PulsePlayer"; static constexpr auto LOG_TAG = "PulsePlayer";
// Example code: // Example code:
@ -36,14 +39,13 @@ static constexpr auto LOG_TAG = "PulsePlayer";
PulsePlayer::PulsePlayer(boost::asio::io_context& io_context, const ClientSettings::Player& settings, std::shared_ptr<Stream> stream) PulsePlayer::PulsePlayer(boost::asio::io_context& io_context, const ClientSettings::Player& settings, std::shared_ptr<Stream> stream)
: Player(io_context, settings, stream), latency_(100ms), pa_ml_(nullptr), pa_ctx_(nullptr), playstream_(nullptr) : Player(io_context, settings, stream), latency_(BUFFER_TIME), pa_ml_(nullptr), pa_ctx_(nullptr), playstream_(nullptr)
{ {
auto params = utils::string::split_pairs(settings.parameter, ',', '='); auto params = utils::string::split_pairs(settings.parameter, ',', '=');
if (params.find("latency") != params.end()) if (params.find("buffer_time") != params.end())
{ latency_ = std::chrono::milliseconds(std::max(cpt::stoi(params["buffer_time"]), 10));
latency_ = std::chrono::milliseconds(std::max(cpt::stoi(params["latency"]), 10));
} LOG(INFO, LOG_TAG) << "Using buffer_time: " << latency_.count() / 1000 << " ms\n";
LOG(INFO, LOG_TAG) << "Using latency: " << latency_.count() / 1000 << " ms\n";
} }

View file

@ -20,6 +20,7 @@
#define PULSE_PLAYER_HPP #define PULSE_PLAYER_HPP
#include "player.hpp" #include "player.hpp"
#include <cstdio> #include <cstdio>
#include <memory> #include <memory>
#include <pulse/pulseaudio.h> #include <pulse/pulseaudio.h>

View file

@ -335,7 +335,13 @@ int main(int argc, char** argv)
else if (settings.player.player_name == "pulse") else if (settings.player.player_name == "pulse")
{ {
cout << "Options are a comma separated list of:\n" cout << "Options are a comma separated list of:\n"
<< " \"latency=<device latency [ms]>\" - default 100, min 10\n"; << " \"buffer_time=<buffer size [ms]>\" - default 80, min 10\n";
}
else if (settings.player.player_name == "alsa")
{
cout << "Options are a comma separated list of:\n"
<< " \"buffer_time=<total buffer size [ms]>\" - default 80, min 10\n"
<< " \"fragments=<number of buffers>\" - default 4, min 2\n";
} }
else else
{ {