mirror of
https://github.com/badaix/snapcast.git
synced 2025-05-12 08:36:43 +02:00
player volume is adjusted in software
This commit is contained in:
parent
11a45d3508
commit
0893f40fd1
3 changed files with 42 additions and 39 deletions
|
@ -27,7 +27,14 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
Player::Player(const PcmDevice& pcmDevice, Stream* stream) : handle_(NULL), buff_(NULL), active_(false), stream_(stream), pcmDevice_(pcmDevice)
|
Player::Player(const PcmDevice& pcmDevice, Stream* stream) :
|
||||||
|
handle_(NULL),
|
||||||
|
buff_(NULL),
|
||||||
|
active_(false),
|
||||||
|
stream_(stream),
|
||||||
|
pcmDevice_(pcmDevice),
|
||||||
|
volume_(1.0),
|
||||||
|
muted_(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,9 +191,22 @@ void Player::worker()
|
||||||
snd_pcm_delay(handle_, &framesDelay);
|
snd_pcm_delay(handle_, &framesDelay);
|
||||||
chronos::usec delay((chronos::usec::rep) (1000 * (double) framesDelay / stream_->getFormat().msRate()));
|
chronos::usec delay((chronos::usec::rep) (1000 * (double) framesDelay / stream_->getFormat().msRate()));
|
||||||
// logO << "delay: " << framesDelay << ", delay[ms]: " << delay.count() / 1000 << "\n";
|
// logO << "delay: " << framesDelay << ", delay[ms]: " << delay.count() / 1000 << "\n";
|
||||||
|
double volume = volume_;
|
||||||
|
if (muted_)
|
||||||
|
volume = 0.;
|
||||||
|
|
||||||
|
const msg::SampleFormat& sampleFormat = stream_->getFormat();
|
||||||
if (stream_->getPlayerChunk(buff_, delay, frames_))
|
if (stream_->getPlayerChunk(buff_, delay, frames_))
|
||||||
{
|
{
|
||||||
|
if (volume < 1.0)
|
||||||
|
{
|
||||||
|
if (sampleFormat.bits == 8)
|
||||||
|
adjustVolume<int8_t>(buff_, frames_*sampleFormat.channels, volume);
|
||||||
|
else if (sampleFormat.bits == 16)
|
||||||
|
adjustVolume<int16_t>(buff_, frames_*sampleFormat.channels, volume);
|
||||||
|
else if (sampleFormat.bits == 32)
|
||||||
|
adjustVolume<int32_t>(buff_, frames_*sampleFormat.channels, volume);
|
||||||
|
}
|
||||||
if ((pcm = snd_pcm_writei(handle_, buff_, frames_)) == -EPIPE)
|
if ((pcm = snd_pcm_writei(handle_, buff_, frames_)) == -EPIPE)
|
||||||
{
|
{
|
||||||
logE << "XRUN\n";
|
logE << "XRUN\n";
|
||||||
|
@ -211,49 +231,14 @@ void Player::worker()
|
||||||
|
|
||||||
void Player::setVolume(double volume)
|
void Player::setVolume(double volume)
|
||||||
{
|
{
|
||||||
long min, max;
|
volume_ = volume;
|
||||||
snd_mixer_t *handle;
|
|
||||||
snd_mixer_selem_id_t *sid;
|
|
||||||
const char *selem_name = "Master";
|
|
||||||
|
|
||||||
snd_mixer_open(&handle, 0);
|
|
||||||
snd_mixer_attach(handle, pcmDevice_.name.c_str());
|
|
||||||
snd_mixer_selem_register(handle, NULL, NULL);
|
|
||||||
snd_mixer_load(handle);
|
|
||||||
|
|
||||||
snd_mixer_selem_id_alloca(&sid);
|
|
||||||
snd_mixer_selem_id_set_index(sid, 0);
|
|
||||||
snd_mixer_selem_id_set_name(sid, selem_name);
|
|
||||||
snd_mixer_elem_t* elem = snd_mixer_find_selem(handle, sid);
|
|
||||||
|
|
||||||
snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
|
|
||||||
snd_mixer_selem_set_playback_volume_all(elem, volume * max);
|
|
||||||
|
|
||||||
snd_mixer_close(handle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Player::setMute(bool mute)
|
void Player::setMute(bool mute)
|
||||||
{
|
{
|
||||||
snd_mixer_t *handle;
|
muted_ = mute;
|
||||||
snd_mixer_selem_id_t *sid;
|
|
||||||
const char *selem_name = "Master";
|
|
||||||
|
|
||||||
snd_mixer_open(&handle, 0);
|
|
||||||
snd_mixer_attach(handle, pcmDevice_.name.c_str());
|
|
||||||
snd_mixer_selem_register(handle, NULL, NULL);
|
|
||||||
snd_mixer_load(handle);
|
|
||||||
|
|
||||||
snd_mixer_selem_id_alloca(&sid);
|
|
||||||
snd_mixer_selem_id_set_index(sid, 0);
|
|
||||||
snd_mixer_selem_id_set_name(sid, selem_name);
|
|
||||||
snd_mixer_elem_t* elem = snd_mixer_find_selem(handle, sid);
|
|
||||||
|
|
||||||
if (snd_mixer_selem_has_playback_switch(elem))
|
|
||||||
snd_mixer_selem_set_playback_switch_all(elem, mute?0:1);
|
|
||||||
|
|
||||||
snd_mixer_close(handle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,15 +28,23 @@
|
||||||
#include "pcmDevice.h"
|
#include "pcmDevice.h"
|
||||||
|
|
||||||
|
|
||||||
|
/// Audio Player
|
||||||
|
/**
|
||||||
|
* Audio player implementation using Alsa
|
||||||
|
*/
|
||||||
class Player
|
class Player
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Player(const PcmDevice& pcmDevice, Stream* stream);
|
Player(const PcmDevice& pcmDevice, Stream* stream);
|
||||||
virtual ~Player();
|
virtual ~Player();
|
||||||
|
|
||||||
|
/// Set audio volume in range [0..1]
|
||||||
void setVolume(double volume);
|
void setVolume(double volume);
|
||||||
void setMute(bool mute);
|
void setMute(bool mute);
|
||||||
void start();
|
void start();
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
|
/// List the system's audio output devices
|
||||||
static std::vector<PcmDevice> pcm_list(void);
|
static std::vector<PcmDevice> pcm_list(void);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -44,6 +52,14 @@ private:
|
||||||
void uninitAlsa();
|
void uninitAlsa();
|
||||||
void worker();
|
void worker();
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void adjustVolume(char *buffer, size_t count, double volume)
|
||||||
|
{
|
||||||
|
T* bufferT = (T*)buffer;
|
||||||
|
for (size_t n=0; n<count; ++n)
|
||||||
|
bufferT[n] *= volume;
|
||||||
|
}
|
||||||
|
|
||||||
snd_pcm_t* handle_;
|
snd_pcm_t* handle_;
|
||||||
snd_pcm_uframes_t frames_;
|
snd_pcm_uframes_t frames_;
|
||||||
|
|
||||||
|
@ -52,6 +68,8 @@ private:
|
||||||
Stream* stream_;
|
Stream* stream_;
|
||||||
std::thread playerThread_;
|
std::thread playerThread_;
|
||||||
PcmDevice pcmDevice_;
|
PcmDevice pcmDevice_;
|
||||||
|
double volume_;
|
||||||
|
bool muted_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -180,7 +180,7 @@ void Controller::worker()
|
||||||
stream_->setBufferLen(serverSettings->bufferMs - latency_);
|
stream_->setBufferLen(serverSettings->bufferMs - latency_);
|
||||||
|
|
||||||
player_.reset(new Player(pcmDevice_, stream_));
|
player_.reset(new Player(pcmDevice_, stream_));
|
||||||
player_->setVolume(serverSettings->volume);
|
player_->setVolume(serverSettings->volume / 100.);
|
||||||
player_->start();
|
player_->start();
|
||||||
|
|
||||||
msg::Command startStream("startStream");
|
msg::Command startStream("startStream");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue