[pulseaudio-discuss] [PATCH 2/4] volume ramp: add volume ramping to sink
Sangchul Lee
sangchul1011 at gmail.com
Thu Jul 7 18:50:24 UTC 2016
The original patch is
- https://review.tizen.org/git/?p=platform/upstream/pulseaudio.git;a=commit;h=cc436915c0a1f4d9734d9d1828760774ea09549a
- by Jaska Uimonen <jaska.uimonen <at> helsinki.fi>
Signed-off-by: Sangchul Lee <sc11.lee at samsung.com>
---
src/pulsecore/sink.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++---
src/pulsecore/sink.h | 8 +++++
2 files changed, 94 insertions(+), 5 deletions(-)
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index a41a78a..0450f52 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -324,6 +324,8 @@ pa_sink* pa_sink_new(
&s->sample_spec,
0);
+ pa_cvolume_ramp_int_init(&s->ramp, PA_VOLUME_NORM,
data->sample_spec.channels);
+
s->thread_info.rtpoll = NULL;
s->thread_info.inputs =
pa_hashmap_new_full(pa_idxset_trivial_hash_func,
pa_idxset_trivial_compare_func, NULL,
(pa_free_cb_t)
pa_sink_input_unref);
@@ -347,6 +349,8 @@ pa_sink* pa_sink_new(
s->thread_info.volume_change_extra_delay =
core->deferred_volume_extra_delay_usec;
s->thread_info.port_latency_offset = s->port_latency_offset;
+ s->thread_info.ramp = s->ramp;
+
/* FIXME: This should probably be moved to pa_sink_put() */
pa_assert_se(pa_idxset_put(core->sinks, s, &s->index) >= 0);
@@ -1207,6 +1211,7 @@ void pa_sink_render(pa_sink*s, size_t length,
pa_memchunk *result) {
} else if (n == 1) {
pa_cvolume volume;
+ pa_cvolume target;
*result = info[0].chunk;
pa_memblock_ref(result->memblock);
@@ -1223,12 +1228,25 @@ void pa_sink_render(pa_sink*s, size_t length,
pa_memchunk *result) {
result,
&s->sample_spec,
result->length);
- } else if (!pa_cvolume_is_norm(&volume)) {
+ } else if (!pa_cvolume_is_norm(&volume) ||
pa_cvolume_ramp_target_active(&s->thread_info.ramp) ||
pa_cvolume_ramp_active(&s->thread_info.ramp)) {
pa_memchunk_make_writable(result, 0);
- pa_volume_memchunk(result, &s->sample_spec, &volume);
+ if (pa_cvolume_ramp_active(&s->thread_info.ramp)) {
+ if (!pa_cvolume_is_norm(&volume))
+ pa_volume_memchunk(result, &s->sample_spec, &volume);
+ pa_volume_ramp_memchunk(result, &s->sample_spec,
&(s->thread_info.ramp));
+ }
+ else {
+ if (pa_cvolume_ramp_target_active(&s->thread_info.ramp)) {
+ pa_cvolume_ramp_get_targets(&s->thread_info.ramp, &target);
+ pa_sw_cvolume_multiply(&volume, &volume, &target);
+ }
+ pa_volume_memchunk(result, &s->sample_spec, &volume);
+ }
}
} else {
void *ptr;
+ pa_cvolume target_vol;
+
result->memblock = pa_memblock_new(s->core->mempool, length);
ptr = pa_memblock_acquire(result->memblock);
@@ -1237,6 +1255,16 @@ void pa_sink_render(pa_sink*s, size_t length,
pa_memchunk *result) {
&s->sample_spec,
&s->thread_info.soft_volume,
s->thread_info.soft_muted);
+
+ if (pa_cvolume_ramp_target_active(&s->thread_info.ramp) ||
pa_cvolume_ramp_active(&s->thread_info.ramp)) {
+ if (pa_cvolume_ramp_active(&s->thread_info.ramp))
+ pa_volume_ramp_memchunk(result, &s->sample_spec,
&(s->thread_info.ramp));
+ else {
+ pa_cvolume_ramp_get_targets(&s->thread_info.ramp,
&target_vol);
+ pa_volume_memchunk(result, &s->sample_spec, &target_vol);
+ }
+ }
+
pa_memblock_release(result->memblock);
result->index = 0;
@@ -1297,6 +1325,7 @@ void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
pa_silence_memchunk(target, &s->sample_spec);
else {
pa_memchunk vchunk;
+ pa_cvolume target_vol;
vchunk = info[0].chunk;
pa_memblock_ref(vchunk.memblock);
@@ -1304,9 +1333,20 @@ void pa_sink_render_into(pa_sink*s, pa_memchunk
*target) {
if (vchunk.length > length)
vchunk.length = length;
- if (!pa_cvolume_is_norm(&volume)) {
+ if (!pa_cvolume_is_norm(&volume) ||
pa_cvolume_ramp_target_active(&s->thread_info.ramp) ||
pa_cvolume_ramp_active(&s->thread_info.ramp)) {
pa_memchunk_make_writable(&vchunk, 0);
- pa_volume_memchunk(&vchunk, &s->sample_spec, &volume);
+ if (pa_cvolume_ramp_active(&s->thread_info.ramp)) {
+ if (!pa_cvolume_is_norm(&volume))
+ pa_volume_memchunk(&vchunk, &s->sample_spec, &volume);
+ pa_volume_ramp_memchunk(&vchunk, &s->sample_spec,
&(s->thread_info.ramp));
+ }
+ else {
+ if (pa_cvolume_ramp_target_active(&s->thread_info.ramp)) {
+
pa_cvolume_ramp_get_targets(&s->thread_info.ramp, &target_vol);
+ pa_sw_cvolume_multiply(&volume, &volume, &target_vol);
+ }
+ pa_volume_memchunk(&vchunk, &s->sample_spec, &volume);
+ }
}
pa_memchunk_memcpy(target, &vchunk);
@@ -1315,6 +1355,7 @@ void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
} else {
void *ptr;
+ pa_cvolume target_vol;
ptr = pa_memblock_acquire(target->memblock);
@@ -1324,6 +1365,15 @@ void pa_sink_render_into(pa_sink*s, pa_memchunk
*target) {
&s->thread_info.soft_volume,
s->thread_info.soft_muted);
+ if (pa_cvolume_ramp_target_active(&s->thread_info.ramp) ||
pa_cvolume_ramp_active(&s->thread_info.ramp)) {
+ if (pa_cvolume_ramp_active(&s->thread_info.ramp))
+ pa_volume_ramp_memchunk(target, &s->sample_spec,
&(s->thread_info.ramp));
+ else {
+ pa_cvolume_ramp_get_targets(&s->thread_info.ramp, &target_vol);
+ pa_volume_memchunk(target, &s->sample_spec, &target_vol);
+ }
+ }
+
pa_memblock_release(target->memblock);
}
@@ -2090,6 +2140,32 @@ void pa_sink_set_volume(
pa_assert_se(pa_asyncmsgq_send(root_sink->asyncmsgq,
PA_MSGOBJECT(root_sink), PA_SINK_MESSAGE_SET_SHARED_VOLUME, NULL, 0,
NULL) == 0);
}
+/* Called from main thread */
+void pa_sink_set_volume_ramp(
+ pa_sink *s,
+ const pa_cvolume_ramp *ramp,
+ pa_bool_t send_msg,
+ pa_bool_t save) {
+
+ pa_sink_assert_ref(s);
+ pa_assert_ctl_context();
+ pa_assert(PA_SINK_IS_LINKED(s->state));
+ pa_assert(ramp);
+
+ /* make sure we don't change the volume when a PASSTHROUGH input
is connected ...
+ * ... *except* if we're being invoked to reset the volume to
ensure 0 dB gain */
+ if (pa_sink_is_passthrough(s)) {
+ pa_log_warn("Cannot do volume ramp, Sink is connected to
PASSTHROUGH input");
+ return;
+ }
+
+ pa_cvolume_ramp_convert(ramp, &s->ramp, s->sample_spec.rate);
+
+ /* This tells the sink that volume ramp changed */
+ if (send_msg)
+ pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s),
PA_SINK_MESSAGE_SET_VOLUME_RAMP, NULL, 0, NULL) == 0);
+}
+
/* Called from the io thread if sync volume is used, otherwise from
the main thread.
* Only to be called by sink implementor */
void pa_sink_set_soft_volume(pa_sink *s, const pa_cvolume *volume) {
@@ -2738,13 +2814,18 @@ int pa_sink_process_msg(pa_msgobject *o, int
code, void *userdata, int64_t offse
s->thread_info.soft_volume = s->soft_volume;
pa_sink_request_rewind(s, (size_t) -1);
}
-
/* Fall through ... */
case PA_SINK_MESSAGE_SYNC_VOLUMES:
sync_input_volumes_within_thread(s);
return 0;
+ case PA_SINK_MESSAGE_SET_VOLUME_RAMP:
+ /* if we have ongoing ramp where we take current start values */
+ pa_cvolume_ramp_start_from(&s->thread_info.ramp, &s->ramp);
+ s->thread_info.ramp = s->ramp;
+ return 0;
+
case PA_SINK_MESSAGE_GET_VOLUME:
if ((s->flags & PA_SINK_DEFERRED_VOLUME) && s->get_volume) {
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index c549869..85f1ddf 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -33,6 +33,7 @@
#include <pulsecore/core.h>
#include <pulsecore/idxset.h>
#include <pulsecore/memchunk.h>
+#include <pulsecore/mix.h>
#include <pulsecore/source.h>
#include <pulsecore/module.h>
#include <pulsecore/asyncmsgq.h>
@@ -109,6 +110,9 @@ struct pa_sink {
pa_cvolume saved_volume;
bool saved_save_volume:1;
+ /* for volume ramps */
+ pa_cvolume_ramp_int ramp;
+
pa_asyncmsgq *asyncmsgq;
pa_memchunk silence;
@@ -304,6 +308,8 @@ struct pa_sink {
uint32_t volume_change_safety_margin;
/* Usec delay added to all volume change events, may be negative. */
int32_t volume_change_extra_delay;
+
+ pa_cvolume_ramp_int ramp;
} thread_info;
void *userdata;
@@ -338,6 +344,7 @@ typedef enum pa_sink_message {
PA_SINK_MESSAGE_SET_PORT,
PA_SINK_MESSAGE_UPDATE_VOLUME_AND_MUTE,
PA_SINK_MESSAGE_SET_PORT_LATENCY_OFFSET,
+ PA_SINK_MESSAGE_SET_VOLUME_RAMP,
PA_SINK_MESSAGE_MAX
} pa_sink_message_t;
@@ -460,6 +467,7 @@ void pa_sink_set_mute(pa_sink *sink, bool mute, bool save);
bool pa_sink_get_mute(pa_sink *sink, bool force_refresh);
bool pa_sink_update_proplist(pa_sink *s, pa_update_mode_t mode,
pa_proplist *p);
+void pa_sink_set_volume_ramp(pa_sink *s, const pa_cvolume_ramp *ramp,
pa_bool_t send_msg, pa_bool_t save);
int pa_sink_set_port(pa_sink *s, const char *name, bool save);
void pa_sink_set_mixer_dirty(pa_sink *s, bool is_dirty);
--
2.7.4
More information about the pulseaudio-discuss
mailing list