mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-29 05:40:23 -04:00
core: add an additional volume factor that is applied after resampling took place
This commit is contained in:
parent
6fa2445e11
commit
a015d56fac
2 changed files with 56 additions and 10 deletions
|
|
@ -92,6 +92,18 @@ void pa_sink_input_new_data_apply_volume_factor(pa_sink_input_new_data *data, co
|
|||
}
|
||||
}
|
||||
|
||||
void pa_sink_input_new_data_apply_volume_factor_sink(pa_sink_input_new_data *data, const pa_cvolume *volume_factor) {
|
||||
pa_assert(data);
|
||||
pa_assert(volume_factor);
|
||||
|
||||
if (data->volume_factor_sink_is_set)
|
||||
pa_sw_cvolume_multiply(&data->volume_factor_sink, &data->volume_factor_sink, volume_factor);
|
||||
else {
|
||||
data->volume_factor_sink_is_set = TRUE;
|
||||
data->volume_factor_sink = *volume_factor;
|
||||
}
|
||||
}
|
||||
|
||||
void pa_sink_input_new_data_set_muted(pa_sink_input_new_data *data, pa_bool_t mute) {
|
||||
pa_assert(data);
|
||||
|
||||
|
|
@ -176,7 +188,6 @@ int pa_sink_input_new(
|
|||
pa_channel_map_init_extend(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
|
||||
}
|
||||
|
||||
pa_return_val_if_fail(pa_channel_map_valid(&data->channel_map), -PA_ERR_INVALID);
|
||||
pa_return_val_if_fail(pa_channel_map_compatible(&data->channel_map, &data->sample_spec), -PA_ERR_INVALID);
|
||||
|
||||
if (!data->volume_is_set) {
|
||||
|
|
@ -185,15 +196,18 @@ int pa_sink_input_new(
|
|||
data->save_volume = FALSE;
|
||||
}
|
||||
|
||||
pa_return_val_if_fail(pa_cvolume_valid(&data->volume), -PA_ERR_INVALID);
|
||||
pa_return_val_if_fail(pa_cvolume_compatible(&data->volume, &data->sample_spec), -PA_ERR_INVALID);
|
||||
|
||||
if (!data->volume_factor_is_set)
|
||||
pa_cvolume_reset(&data->volume_factor, data->sample_spec.channels);
|
||||
|
||||
pa_return_val_if_fail(pa_cvolume_valid(&data->volume_factor), -PA_ERR_INVALID);
|
||||
pa_return_val_if_fail(pa_cvolume_compatible(&data->volume_factor, &data->sample_spec), -PA_ERR_INVALID);
|
||||
|
||||
if (!data->volume_factor_sink_is_set)
|
||||
pa_cvolume_reset(&data->volume_factor_sink, data->sink->sample_spec.channels);
|
||||
|
||||
pa_return_val_if_fail(pa_cvolume_compatible(&data->volume_factor_sink, &data->sink->sample_spec), -PA_ERR_INVALID);
|
||||
|
||||
if (!data->muted_is_set)
|
||||
data->muted = FALSE;
|
||||
|
||||
|
|
@ -283,6 +297,7 @@ int pa_sink_input_new(
|
|||
i->volume = data->volume;
|
||||
|
||||
i->volume_factor = data->volume_factor;
|
||||
i->volume_factor_sink = data->volume_factor_sink;
|
||||
i->real_ratio = i->reference_ratio = data->volume;
|
||||
pa_cvolume_reset(&i->soft_volume, i->sample_spec.channels);
|
||||
pa_cvolume_reset(&i->real_ratio, i->sample_spec.channels);
|
||||
|
|
@ -576,7 +591,7 @@ pa_usec_t pa_sink_input_get_latency(pa_sink_input *i, pa_usec_t *sink_latency) {
|
|||
|
||||
/* Called from thread context */
|
||||
void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa_memchunk *chunk, pa_cvolume *volume) {
|
||||
pa_bool_t do_volume_adj_here;
|
||||
pa_bool_t do_volume_adj_here, need_volume_factor_sink;
|
||||
pa_bool_t volume_is_norm;
|
||||
size_t block_size_max_sink, block_size_max_sink_input;
|
||||
size_t ilength;
|
||||
|
|
@ -624,6 +639,7 @@ void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, p
|
|||
|
||||
do_volume_adj_here = !pa_channel_map_equal(&i->channel_map, &i->sink->channel_map);
|
||||
volume_is_norm = pa_cvolume_is_norm(&i->thread_info.soft_volume) && !i->thread_info.muted;
|
||||
need_volume_factor_sink = !pa_cvolume_is_norm(&i->volume_factor_sink);
|
||||
|
||||
while (!pa_memblockq_is_readable(i->thread_info.render_memblockq)) {
|
||||
pa_memchunk tchunk;
|
||||
|
|
@ -655,6 +671,7 @@ void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, p
|
|||
|
||||
while (tchunk.length > 0) {
|
||||
pa_memchunk wchunk;
|
||||
pa_bool_t nvfs = need_volume_factor_sink;
|
||||
|
||||
wchunk = tchunk;
|
||||
pa_memblock_ref(wchunk.memblock);
|
||||
|
|
@ -666,18 +683,41 @@ void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, p
|
|||
if (do_volume_adj_here && !volume_is_norm) {
|
||||
pa_memchunk_make_writable(&wchunk, 0);
|
||||
|
||||
if (i->thread_info.muted)
|
||||
if (i->thread_info.muted) {
|
||||
pa_silence_memchunk(&wchunk, &i->thread_info.sample_spec);
|
||||
else
|
||||
nvfs = FALSE;
|
||||
|
||||
} else if (!i->thread_info.resampler && nvfs) {
|
||||
pa_cvolume v;
|
||||
|
||||
/* If we don't need a resampler we can merge the
|
||||
* post and the pre volume adjustment into one */
|
||||
|
||||
pa_sw_cvolume_multiply(&v, &i->thread_info.soft_volume, &i->volume_factor_sink);
|
||||
pa_volume_memchunk(&wchunk, &i->thread_info.sample_spec, &v);
|
||||
nvfs = FALSE;
|
||||
|
||||
} else
|
||||
pa_volume_memchunk(&wchunk, &i->thread_info.sample_spec, &i->thread_info.soft_volume);
|
||||
}
|
||||
|
||||
if (!i->thread_info.resampler)
|
||||
if (!i->thread_info.resampler) {
|
||||
|
||||
if (nvfs) {
|
||||
pa_memchunk_make_writable(&wchunk, 0);
|
||||
pa_volume_memchunk(&wchunk, &i->sink->sample_spec, &i->volume_factor_sink);
|
||||
}
|
||||
|
||||
pa_memblockq_push_align(i->thread_info.render_memblockq, &wchunk);
|
||||
else {
|
||||
} else {
|
||||
pa_memchunk rchunk;
|
||||
pa_resampler_run(i->thread_info.resampler, &wchunk, &rchunk);
|
||||
|
||||
if (nvfs) {
|
||||
pa_memchunk_make_writable(&rchunk, 0);
|
||||
pa_volume_memchunk(&rchunk, &i->sink->sample_spec, &i->volume_factor_sink);
|
||||
}
|
||||
|
||||
/* pa_log_debug("pushing %lu", (unsigned long) rchunk.length); */
|
||||
|
||||
if (rchunk.memblock) {
|
||||
|
|
@ -1186,6 +1226,7 @@ int pa_sink_input_start_move(pa_sink_input *i) {
|
|||
pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_START_MOVE, i, 0, NULL) == 0);
|
||||
|
||||
pa_sink_update_status(i->sink);
|
||||
pa_cvolume_remap(&i->volume_factor_sink, &i->sink->channel_map, &i->channel_map);
|
||||
i->sink = NULL;
|
||||
|
||||
pa_sink_input_unref(i);
|
||||
|
|
@ -1240,6 +1281,8 @@ int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, pa_bool_t save) {
|
|||
i->save_sink = save;
|
||||
pa_idxset_put(dest->inputs, pa_sink_input_ref(i), NULL);
|
||||
|
||||
pa_cvolume_remap(&i->volume_factor_sink, &i->channel_map, &i->sink->channel_map);
|
||||
|
||||
if (pa_sink_input_get_state(i) == PA_SINK_INPUT_CORKED)
|
||||
i->sink->n_corked++;
|
||||
|
||||
|
|
|
|||
|
|
@ -100,6 +100,8 @@ struct pa_sink_input {
|
|||
pa_cvolume volume_factor; /* An internally used volume factor that can be used by modules to apply effects and suchlike without having that visible to the outside */
|
||||
pa_cvolume soft_volume; /* The internal software volume we apply to all PCM data while it passes through. Usually calculated as real_ratio * volume_factor */
|
||||
|
||||
pa_cvolume volume_factor_sink; /* A second volume factor in format of the sink this stream is connected to */
|
||||
|
||||
pa_bool_t muted:1;
|
||||
|
||||
/* if TRUE then the source we are connected to and/or the volume
|
||||
|
|
@ -273,13 +275,13 @@ typedef struct pa_sink_input_new_data {
|
|||
pa_sample_spec sample_spec;
|
||||
pa_channel_map channel_map;
|
||||
|
||||
pa_cvolume volume, volume_factor;
|
||||
pa_cvolume volume, volume_factor, volume_factor_sink;
|
||||
pa_bool_t muted:1;
|
||||
|
||||
pa_bool_t sample_spec_is_set:1;
|
||||
pa_bool_t channel_map_is_set:1;
|
||||
|
||||
pa_bool_t volume_is_set:1, volume_factor_is_set:1;
|
||||
pa_bool_t volume_is_set:1, volume_factor_is_set:1, volume_factor_sink_is_set:1;
|
||||
pa_bool_t muted_is_set:1;
|
||||
|
||||
pa_bool_t volume_is_absolute:1;
|
||||
|
|
@ -292,6 +294,7 @@ void pa_sink_input_new_data_set_sample_spec(pa_sink_input_new_data *data, const
|
|||
void pa_sink_input_new_data_set_channel_map(pa_sink_input_new_data *data, const pa_channel_map *map);
|
||||
void pa_sink_input_new_data_set_volume(pa_sink_input_new_data *data, const pa_cvolume *volume);
|
||||
void pa_sink_input_new_data_apply_volume_factor(pa_sink_input_new_data *data, const pa_cvolume *volume_factor);
|
||||
void pa_sink_input_new_data_apply_volume_factor_sink(pa_sink_input_new_data *data, const pa_cvolume *volume_factor);
|
||||
void pa_sink_input_new_data_set_muted(pa_sink_input_new_data *data, pa_bool_t mute);
|
||||
void pa_sink_input_new_data_done(pa_sink_input_new_data *data);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue