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>
This commit is contained in:
Igor V. Kovalenko 2021-09-10 23:21:09 +03:00
parent 76e01b25f5
commit f2b748e851
3 changed files with 53 additions and 0 deletions

View file

@ -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,
},
};

View file

@ -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;

View file

@ -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);