mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-29 05:40:23 -04:00
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:
parent
76e01b25f5
commit
f2b748e851
3 changed files with 53 additions and 0 deletions
|
|
@ -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,
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue