summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor V. Kovalenko <igor.v.kovalenko@gmail.com>2021-09-10 23:21:09 +0300
committerIgor V. Kovalenko <igor.v.kovalenko@gmail.com>2022-10-17 09:07:09 +0300
commitf2b748e851668acc67a8dcc190ff8ba822fa034e (patch)
tree13511240ec6bcdafa59ffe99a44799d0bf14721e
parent76e01b25f55fb0b82900681ba0616a34d1e4771f (diff)
downloadpulseaudio-f2b748e851668acc67a8dcc190ff8ba822fa034e.tar.gz
bluetooth: Add 20dB boost for faststream source volume
Some devices unexpectedly return stereo backchannel stream with wrong frequency, and volume of backchannel stream appears too low. If this happens, boost source volume by 20dB. Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/628>
-rw-r--r--src/modules/bluetooth/a2dp-codec-sbc.c19
-rw-r--r--src/modules/bluetooth/bt-codec-api.h3
-rw-r--r--src/modules/bluetooth/module-bluez5-device.c31
3 files changed, 53 insertions, 0 deletions
diff --git a/src/modules/bluetooth/a2dp-codec-sbc.c b/src/modules/bluetooth/a2dp-codec-sbc.c
index 2c069cb6f..5476697f8 100644
--- a/src/modules/bluetooth/a2dp-codec-sbc.c
+++ b/src/modules/bluetooth/a2dp-codec-sbc.c
@@ -57,6 +57,7 @@ struct sbc_info {
uint8_t nr_blocks;
uint8_t nr_subbands;
+ bool boost_source_volume;
/* Size of SBC frame fragment left over from previous decoding iteration */
size_t frame_fragment_size;
/* Maximum SBC frame size is 512 bytes when SBC compression ratio > 1 */
@@ -943,6 +944,9 @@ static int reset(void *codec_info) {
struct sbc_info *sbc_info = (struct sbc_info *) codec_info;
int ret;
+ /* forget about source volume boost */
+ sbc_info->boost_source_volume = false;
+
/* forget last saved frame fragment */
sbc_info->frame_fragment_size = 0;
@@ -1356,6 +1360,10 @@ static size_t decode_buffer_faststream(void *codec_info, const uint8_t *input_bu
* remember this, and keep incoming sample rate at 16000 */
pa_log_debug("FastStream decoder detected SBC frequency %u, expected %u", sbc_info->sbc.frequency, sbc_info->frequency);
sbc_info->frequency = sbc_info->sbc.frequency;
+
+ /* volume is too low for known devices with unexpected source SBC frequency */
+ pa_log_debug("FastStream decoder requesting 20dB boost for source volume");
+ sbc_info->boost_source_volume = true;
}
if (sbc_info->sbc.mode == SBC_MODE_MONO) {
@@ -1396,6 +1404,16 @@ static size_t decode_buffer_faststream(void *codec_info, const uint8_t *input_bu
return d - output_buffer;
}
+/* Boost sink backchannel mic volume by 20dB as it appears too quiet */
+double get_source_output_volume_factor_dB_faststream(void *codec_info) {
+ struct sbc_info *sbc_info = (struct sbc_info *) codec_info;
+
+ if (sbc_info->boost_source_volume)
+ return 20.;
+
+ return 1.0;
+}
+
const pa_a2dp_endpoint_conf pa_a2dp_endpoint_conf_sbc = {
.id = { A2DP_CODEC_SBC, 0, 0 },
.can_be_supported = can_be_supported,
@@ -1547,5 +1565,6 @@ const pa_a2dp_endpoint_conf pa_a2dp_endpoint_conf_faststream = {
.get_encoded_block_size = get_encoded_block_size_faststream,
.encode_buffer = encode_buffer_faststream,
.decode_buffer = decode_buffer_faststream,
+ .get_source_output_volume_factor_dB = get_source_output_volume_factor_dB_faststream,
},
};
diff --git a/src/modules/bluetooth/bt-codec-api.h b/src/modules/bluetooth/bt-codec-api.h
index 3ed47166a..700c28753 100644
--- a/src/modules/bluetooth/bt-codec-api.h
+++ b/src/modules/bluetooth/bt-codec-api.h
@@ -67,4 +67,7 @@ typedef struct pa_bt_codec {
* returns size of filled ouput_buffer and set processed to size of
* processed input_buffer */
size_t (*decode_buffer)(void *codec_info, const uint8_t *input_buffer, size_t input_size, uint8_t *output_buffer, size_t output_size, size_t *processed);
+
+ /* Get volume factor which needs to be applied to output samples */
+ double (*get_source_output_volume_factor_dB)(void *codec_info);
} pa_bt_codec;
diff --git a/src/modules/bluetooth/module-bluez5-device.c b/src/modules/bluetooth/module-bluez5-device.c
index f50521c59..ab1bc098e 100644
--- a/src/modules/bluetooth/module-bluez5-device.c
+++ b/src/modules/bluetooth/module-bluez5-device.c
@@ -116,6 +116,8 @@ struct userdata {
pa_hook_slot *sink_volume_changed_slot;
pa_hook_slot *source_volume_changed_slot;
+ pa_hook_slot *source_output_new_hook_slot;
+
pa_bluetooth_discovery *discovery;
pa_bluetooth_device *device;
pa_bluetooth_transport *transport;
@@ -2755,6 +2757,30 @@ static int device_process_msg(pa_msgobject *obj, int code, void *data, int64_t o
return 0;
}
+/* Run from main thread */
+static pa_hook_result_t a2dp_source_output_fixate_hook_callback(pa_core *c, pa_source_output_new_data *new_data, struct userdata *u) {
+ double volume_factor_dB;
+ pa_cvolume cv;
+
+ pa_assert(c);
+ pa_assert(new_data);
+ pa_assert(u);
+
+ /* When transport is released, there is no decoder and no codec */
+ if (!u->bt_codec || !u->decoder_info)
+ return PA_HOOK_OK;
+
+ if (!u->bt_codec->get_source_output_volume_factor_dB)
+ return PA_HOOK_OK;
+
+ volume_factor_dB = u->bt_codec->get_source_output_volume_factor_dB(u->decoder_info);
+
+ pa_cvolume_set(&cv, u->decoder_sample_spec.channels, pa_sw_volume_from_dB(volume_factor_dB));
+ pa_source_output_new_data_apply_volume_factor_source(new_data, &cv);
+
+ return PA_HOOK_OK;
+}
+
int pa__init(pa_module* m) {
struct userdata *u;
const char *path;
@@ -2836,6 +2862,8 @@ int pa__init(pa_module* m) {
u->transport_source_volume_changed_slot =
pa_hook_connect(pa_bluetooth_discovery_hook(u->discovery, PA_BLUETOOTH_HOOK_TRANSPORT_SOURCE_VOLUME_CHANGED), PA_HOOK_NORMAL, (pa_hook_cb_t) transport_source_volume_changed_cb, u);
+ u->source_output_new_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NEW], PA_HOOK_EARLY, (pa_hook_cb_t) a2dp_source_output_fixate_hook_callback, u);
+
if (add_card(u) < 0)
goto fail;
@@ -2899,6 +2927,9 @@ void pa__done(pa_module *m) {
stop_thread(u);
+ if (u->source_output_new_hook_slot)
+ pa_hook_slot_free(u->source_output_new_hook_slot);
+
if (u->device_connection_changed_slot)
pa_hook_slot_free(u->device_connection_changed_slot);