[pulseaudio-discuss] [PATCH] alsa-sink: take base volume into account when applying hw volume

2010-11-25 Thread Juho Hämäläinen
Currently if sink base volume differs from 0dB and sync-volume is used, 
wrong volume values are written to hw. This patch fixes that.



Signed-off-by: Juho Hämäläinen 
---
  src/modules/alsa/alsa-sink.c |   10 --
  1 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index 2249f66..53c14b8 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -1263,12 +1263,18 @@ static void sink_write_volume_cb(pa_sink *s) {
 pa_assert(u->mixer_handle);
 pa_assert(s->flags & PA_SINK_SYNC_VOLUME);
 
+/* Shift up by the base volume */
+pa_sw_cvolume_divide_scalar(&hw_vol, &hw_vol, s->base_volume);
+
 if (pa_alsa_path_set_volume(u->mixer_path, u->mixer_handle, &s->channel_map, &hw_vol, TRUE) < 0)
 pa_log_error("Writing HW volume failed");
 else {
 pa_cvolume tmp_vol;
 pa_bool_t accurate_enough;
 
+/* Shift down by the base volume, so that 0dB becomes maximum volume */
+pa_sw_cvolume_multiply_scalar(&hw_vol, &hw_vol, s->base_volume);
+
 pa_sw_cvolume_divide(&tmp_vol, &hw_vol, &s->thread_info.current_hw_volume);
 accurate_enough =
 (pa_cvolume_min(&tmp_vol) >= (PA_VOLUME_NORM - VOLUME_ACCURACY)) &&
@@ -1278,10 +1284,10 @@ static void sink_write_volume_cb(pa_sink *s) {
 char vol_str_pcnt[PA_CVOLUME_SNPRINT_MAX];
 char vol_str_db[PA_SW_CVOLUME_SNPRINT_DB_MAX];
 
-pa_log_debug("Written HW volume did not match with the request %s != %s",
+pa_log_debug("Written HW volume did not match with the request: %s (request) != %s",
  pa_cvolume_snprint(vol_str_pcnt, sizeof(vol_str_pcnt), &s->thread_info.current_hw_volume),
  pa_cvolume_snprint(vol_str_pcnt, sizeof(vol_str_pcnt), &hw_vol));
-pa_log_debug("  in dB: %s != %s",
+pa_log_debug("   in dB: %s (request) != %s",
  pa_sw_cvolume_snprint_dB(vol_str_db, sizeof(vol_str_db), &s->thread_info.current_hw_volume),
  pa_sw_cvolume_snprint_dB(vol_str_db, sizeof(vol_str_db), &hw_vol));
 }
___
pulseaudio-discuss mailing list
pulseaudio-discuss@mail.0pointer.de
https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss


[pulseaudio-discuss] [PATCH] bluetooth-device: fix rounding errors caused by few bt volume steps

2011-04-04 Thread Juho Hämäläinen


When volume changes in bluetooth device PulseAudio volume is rounded
one too low, so if bluetooth headset changes volume and that volume
is immediately set again for bluetooth device, bluetooth step drifts
lower all the time. Volume is incremented by one in the conversion so
that we get right bluetooth step when re-applying volume.

Signed-off-by: Juho Hämäläinen 
---
 src/modules/bluetooth/module-bluetooth-device.c |   48 
+-

 1 files changed, 37 insertions(+), 11 deletions(-)

diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index e4a2cef..46826eb 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -1725,6 +1725,8 @@ finish:
 pa_log_debug("IO thread shutting down");
 }
 
+#define HSP_MAX_GAIN (15)
+
 /* Run from main thread */
 static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *userdata) {
 DBusError err;
@@ -1750,20 +1752,30 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us
 dbus_uint16_t gain;
 pa_cvolume v;
 
-if (!dbus_message_get_args(m, &err, DBUS_TYPE_UINT16, &gain, DBUS_TYPE_INVALID) || gain > 15) {
+if (!dbus_message_get_args(m, &err, DBUS_TYPE_UINT16, &gain, DBUS_TYPE_INVALID) || gain > HSP_MAX_GAIN) {
 pa_log("Failed to parse org.bluez.Headset.{Speaker|Microphone}GainChanged: %s", err.message);
 goto fail;
 }
 
 if (u->profile == PROFILE_HSP) {
 if (u->sink && dbus_message_is_signal(m, "org.bluez.Headset", "SpeakerGainChanged")) {
+pa_volume_t volume = (pa_volume_t) (gain * PA_VOLUME_NORM / HSP_MAX_GAIN);
+
+/* increment volume by one to correct rounding errors */
+if (volume < PA_VOLUME_NORM)
+volume ++;
 
-pa_cvolume_set(&v, u->sample_spec.channels, (pa_volume_t) (gain * PA_VOLUME_NORM / 15));
+pa_cvolume_set(&v, u->sample_spec.channels, volume);
 pa_sink_volume_changed(u->sink, &v);
 
 } else if (u->source && dbus_message_is_signal(m, "org.bluez.Headset", "MicrophoneGainChanged")) {
+pa_volume_t volume = (pa_volume_t) (gain * PA_VOLUME_NORM / HSP_MAX_GAIN);
 
-pa_cvolume_set(&v, u->sample_spec.channels, (pa_volume_t) (gain * PA_VOLUME_NORM / 15));
+/* increment volume by one to correct rounding errors */
+if (volume < PA_VOLUME_NORM)
+volume ++;
+
+pa_cvolume_set(&v, u->sample_spec.channels, volume);
 pa_source_volume_changed(u->source, &v);
 }
 }
@@ -1801,6 +1813,7 @@ fail:
 static void sink_set_volume_cb(pa_sink *s) {
 DBusMessage *m;
 dbus_uint16_t gain;
+pa_volume_t volume;
 struct userdata *u;
 char *k;
 
@@ -1815,12 +1828,18 @@ static void sink_set_volume_cb(pa_sink *s) {
 pa_assert(u->sink == s);
 pa_assert(u->profile == PROFILE_HSP);
 
-gain = (pa_cvolume_max(&s->real_volume) * 15) / PA_VOLUME_NORM;
+gain = (pa_cvolume_max(&s->real_volume) * HSP_MAX_GAIN) / PA_VOLUME_NORM;
+
+if (gain > HSP_MAX_GAIN)
+gain = HSP_MAX_GAIN;
 
-if (gain > 15)
-gain = 15;
+volume = (pa_volume_t) (gain * PA_VOLUME_NORM / HSP_MAX_GAIN);
 
-pa_cvolume_set(&s->real_volume, u->sample_spec.channels, (pa_volume_t) (gain * PA_VOLUME_NORM / 15));
+/* increment volume by one to correct rounding errors */
+if (volume < PA_VOLUME_NORM)
+volume ++;
+
+pa_cvolume_set(&s->real_volume, u->sample_spec.channels, volume);
 
 pa_assert_se(m = dbus_message_new_method_call("org.bluez", u->path, "org.bluez.Headset", "SetSpeakerGain"));
 pa_assert_se(dbus_message_append_args(m, DBUS_TYPE_UINT16, &gain, DBUS_TYPE_INVALID));
@@ -1832,6 +1851,7 @@ static void sink_set_volume_cb(pa_sink *s) {
 static void source_set_volume_cb(pa_source *s) {
 DBusMessage *m;
 dbus_uint16_t gain;
+pa_volume_t volume;
 struct userdata *u;
 char *k;
 
@@ -1846,12 +1866,18 @@ static void source_set_volume_cb(pa_source *s) {
 pa_assert(u->source == s);
 pa_assert(u->profile == PROFILE_HSP);
 
-gain = (pa_cvolume_max(&s->volume) * 15) / PA_VOLUME_NORM;
+gain = (pa_cvolume_max(&s->volume) * HSP_MAX_GAIN) / PA_VOLUME_NORM;
+
+if (gain > HSP_MAX_GAIN)
+gain = HSP_MAX_GAIN;
+
+volume = (pa_volume_t) (gain * PA_VOLUME_NORM / HSP_MAX_GAIN);
 
-if (gain > 15)
-gain = 15;
+/* increment volume by one to correct rounding errors */
+if (volume < PA_VOLUME_NORM)
+volu