forked from Bananymous/banan-os
AudioServer: Add software volume control
This commit is contained in:
@@ -111,17 +111,18 @@ bool AudioServer::on_client_packet(int fd, LibAudio::Packet packet)
|
|||||||
{
|
{
|
||||||
// NOTE: maybe we should map [0->100%] -> [min, 0] instead?
|
// NOTE: maybe we should map [0->100%] -> [min, 0] instead?
|
||||||
|
|
||||||
|
double hw_percent = 1.0;
|
||||||
|
|
||||||
const auto& volume = device().volume;
|
const auto& volume = device().volume;
|
||||||
if (volume.min_mdB == volume.max_mdB)
|
if (volume.min_mdB != volume.max_mdB)
|
||||||
response = 1000;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
const double min_dB = volume.min_mdB / 1000.0;
|
const double min_mdB = volume.min_mdB;
|
||||||
const double max_dB = volume.max_mdB / 1000.0;
|
const double max_mdB = volume.max_mdB;
|
||||||
const double dB = volume.mdB / 1000.0;
|
hw_percent = (BAN::Math::pow(10.0, (device().volume.mdB - min_mdB) / (max_mdB - min_mdB)) - 1.0) / 9.0;
|
||||||
const double percent = (BAN::Math::pow(10.0, (dB - min_dB) / (max_dB - min_dB)) - 1.0) / 9.0;
|
|
||||||
response = BAN::Math::round(percent * 1000.0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
response = BAN::Math::round(device().volume_mult * hw_percent * 1000.0);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LibAudio::Packet::SetVolume:
|
case LibAudio::Packet::SetVolume:
|
||||||
@@ -129,16 +130,24 @@ bool AudioServer::on_client_packet(int fd, LibAudio::Packet packet)
|
|||||||
// NOTE: maybe we should map [0->100%] -> [min, 0] instead?
|
// NOTE: maybe we should map [0->100%] -> [min, 0] instead?
|
||||||
|
|
||||||
const auto& volume = device().volume;
|
const auto& volume = device().volume;
|
||||||
const double min_dB = volume.min_mdB / 1000.0;
|
const double min_mdB = volume.min_mdB;
|
||||||
const double max_dB = volume.max_mdB / 1000.0;
|
const double max_mdB = volume.max_mdB;
|
||||||
const double percent = packet.parameter / 1000.0;
|
const double percent = packet.parameter / 1000.0;
|
||||||
const double dB = min_dB + (max_dB - min_dB) * BAN::Math::log10(1.0 + 9.0 * percent);
|
const int32_t mdB = BAN::Math::round(min_mdB + (max_mdB - min_mdB) * BAN::Math::log10(1.0 + 9.0 * percent));
|
||||||
|
|
||||||
const int32_t mdB = BAN::Math::round(dB * 1000.0);
|
|
||||||
if (ioctl(device().fd, SND_SET_VOLUME_MDB, &mdB) != 0)
|
if (ioctl(device().fd, SND_SET_VOLUME_MDB, &mdB) != 0)
|
||||||
dwarnln("Failed to set volume: {}", strerror(errno));
|
dwarnln("Failed to set hardware volume: {}", strerror(errno));
|
||||||
else if (ioctl(device().fd, SND_GET_VOLUME_INFO, &device().volume) != 0)
|
|
||||||
dwarnln("Failed to query new volume: {}", strerror(errno));
|
if (ioctl(device().fd, SND_GET_VOLUME_INFO, &device().volume) != 0)
|
||||||
|
{
|
||||||
|
dwarnln("Failed to query new hardware volume: {}", strerror(errno));
|
||||||
|
device().volume_mult = 1.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const double hw_percent = (BAN::Math::pow(10.0, (device().volume.mdB - min_mdB) / (max_mdB - min_mdB)) - 1.0) / 9.0;
|
||||||
|
device().volume_mult = percent / hw_percent;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -313,11 +322,13 @@ void AudioServer::send_samples()
|
|||||||
auto buffer = BAN::ByteSpan(static_cast<uint8_t*>(alloca(samples_to_send * sizeof(kernel_sample_t))), samples_to_send * sizeof(kernel_sample_t));
|
auto buffer = BAN::ByteSpan(static_cast<uint8_t*>(alloca(samples_to_send * sizeof(kernel_sample_t))), samples_to_send * sizeof(kernel_sample_t));
|
||||||
|
|
||||||
{
|
{
|
||||||
|
const double sample_mult = device().volume_mult * BAN::numeric_limits<kernel_sample_t>::max();
|
||||||
|
|
||||||
auto sample_buffer = buffer.as_span<kernel_sample_t>();
|
auto sample_buffer = buffer.as_span<kernel_sample_t>();
|
||||||
for (size_t i = 0; i < samples_to_send; i++)
|
for (size_t i = 0; i < samples_to_send; i++)
|
||||||
{
|
{
|
||||||
sample_buffer[i] = BAN::Math::clamp<sample_t>(
|
sample_buffer[i] = BAN::Math::clamp<sample_t>(
|
||||||
m_samples[m_samples_sent + i] * BAN::numeric_limits<kernel_sample_t>::max(),
|
sample_mult * m_samples[m_samples_sent + i],
|
||||||
BAN::numeric_limits<kernel_sample_t>::min(),
|
BAN::numeric_limits<kernel_sample_t>::min(),
|
||||||
BAN::numeric_limits<kernel_sample_t>::max()
|
BAN::numeric_limits<kernel_sample_t>::max()
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ struct AudioDevice
|
|||||||
uint32_t sample_rate;
|
uint32_t sample_rate;
|
||||||
uint32_t total_pins;
|
uint32_t total_pins;
|
||||||
uint32_t current_pin;
|
uint32_t current_pin;
|
||||||
|
double volume_mult;
|
||||||
snd_volume_info volume;
|
snd_volume_info volume;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ static BAN::Optional<AudioDevice> initialize_audio_device(int fd)
|
|||||||
{
|
{
|
||||||
AudioDevice result {};
|
AudioDevice result {};
|
||||||
result.fd = fd;
|
result.fd = fd;
|
||||||
|
result.volume_mult = 1.0;
|
||||||
if (ioctl(fd, SND_GET_CHANNELS, &result.channels) != 0)
|
if (ioctl(fd, SND_GET_CHANNELS, &result.channels) != 0)
|
||||||
return {};
|
return {};
|
||||||
if (ioctl(fd, SND_GET_SAMPLE_RATE, &result.sample_rate) != 0)
|
if (ioctl(fd, SND_GET_SAMPLE_RATE, &result.sample_rate) != 0)
|
||||||
|
|||||||
Reference in New Issue
Block a user