diff options
Diffstat (limited to 'src/modules')
-rw-r--r-- | src/modules/bluetooth/a2dp-codec-sbc.c | 19 | ||||
-rw-r--r-- | src/modules/bluetooth/bt-codec-api.h | 3 | ||||
-rw-r--r-- | src/modules/bluetooth/module-bluez5-device.c | 31 |
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); |