[pulseaudio-commits] [SCM] PulseAudio Sound Server branch, master, updated. v0.9.15-test7-52-gc32c6c8

Lennart Poettering gitmailer-noreply at 0pointer.de
Tue Apr 7 18:52:11 PDT 2009


This is an automated email from the git hooks/post-receive script. It was
generated because of a push to the "PulseAudio Sound Server" repository.

The master branch has been updated
      from  c523b16d33a772b59407622c1066e11536f4cfa0 (commit)

- Log -----------------------------------------------------------------
c32c6c8 introduce relative_volume field in sink_input and make use of it on sink flat volume change
14e89d4 when calculating volume from dB use ceil()
4ff41ec print smallest attenuation/sample
aacb11b update documentation regarding stream timing a bit
-----------------------------------------------------------------------

Summary of changes:
 src/pulse/stream.h         |   70 ++++++++++++++++++++++++++++++-------------
 src/pulse/volume.c         |    4 +-
 src/pulsecore/sink-input.c |   56 +++++++++++++++++++++++++++--------
 src/pulsecore/sink-input.h |    8 ++++-
 src/pulsecore/sink.c       |   59 ++++++++++++++++++-------------------
 src/pulsecore/sink.h       |    5 ++-
 src/tests/voltest.c        |    3 ++
 7 files changed, 136 insertions(+), 69 deletions(-)

-----------------------------------------------------------------------

commit aacb11bb40a33f2415156517a4ff799e78e6190f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Apr 7 17:53:51 2009 +0200

    update documentation regarding stream timing a bit

diff --git a/src/pulse/stream.h b/src/pulse/stream.h
index 8993143..49c132a 100644
--- a/src/pulse/stream.h
+++ b/src/pulse/stream.h
@@ -424,7 +424,9 @@ int pa_stream_disconnect(pa_stream *s);
  * is not copied. If NULL, the data is copied into an internal
  * buffer. The client my freely seek around in the output buffer. For
  * most applications passing 0 and PA_SEEK_RELATIVE as arguments for
- * offset and seek should be useful.*/
+ * offset and seek should be useful. Afte ther write call succeeded
+ * the write index will be a the position after where this chunk of
+ * data has been written to. */
 int pa_stream_write(
         pa_stream *p             /**< The stream to use */,
         const void *data         /**< The data to write */,
@@ -551,37 +553,63 @@ pa_operation* pa_stream_set_name(pa_stream *s, const char *name, pa_stream_succe
 
 /** Return the current playback/recording time. This is based on the
  * data in the timing info structure returned by
- * pa_stream_get_timing_info(). This function will usually only return
- * new data if a timing info update has been recieved. Only if timing
- * interpolation has been requested (PA_STREAM_INTERPOLATE_TIMING)
- * the data from the last timing update is used for an estimation of
- * the current playback/recording time based on the local time that
- * passed since the timing info structure has been acquired. The time
- * value returned by this function is guaranteed to increase
- * monotonically. (that means: the returned value is always greater or
- * equal to the value returned on the last call) This behaviour can
- * be disabled by using PA_STREAM_NOT_MONOTONIC. This may be
+ * pa_stream_get_timing_info().
+ *
+ * This function will usually only return new data if a timing info
+ * update has been recieved. Only if timing interpolation has been
+ * requested (PA_STREAM_INTERPOLATE_TIMING) the data from the last
+ * timing update is used for an estimation of the current
+ * playback/recording time based on the local time that passed since
+ * the timing info structure has been acquired.
+ *
+ * The time value returned by this function is guaranteed to increase
+ * monotonically.  (that means: the returned value is always greater
+ * or equal to the value returned on the last call). This behaviour
+ * can be disabled by using PA_STREAM_NOT_MONOTONIC. This may be
  * desirable to deal better with bad estimations of transport
  * latencies, but may have strange effects if the application is not
- * able to deal with time going 'backwards'. */
+ * able to deal with time going 'backwards'.
+ *
+ * The time interpolator activated by PA_STREAM_INTERPOLATE_TIMING
+ * favours 'smooth' time graphs over accurate ones to improve the
+ * smoothness of UI operations that are tied to the audio clock. If
+ * accuracy is more important to you you might need to estimate your
+ * timing based on the data from pa_stream_get_timing_info() yourself
+ * or not work with interpolated timing at all and instead always
+ * query on the server side for the most up to date timing with
+ * pa_stream_update_timing_info().
+ *
+ * If no timing information has been
+ * recieved yet this call will return PA_ERR_NODATA. For more details
+ * see pa_stream_get_timing_info(). */
 int pa_stream_get_time(pa_stream *s, pa_usec_t *r_usec);
 
 /** Return the total stream latency. This function is based on
- * pa_stream_get_time(). In case the stream is a monitoring stream the
- * result can be negative, i.e. the captured samples are not yet
- * played. In this case *negative is set to 1. */
+ * pa_stream_get_time().
+ *
+ * In case the stream is a monitoring stream the result can be
+ * negative, i.e. the captured samples are not yet played. In this
+ * case *negative is set to 1.
+ *
+ * If no timing information has been recieved yet this call will
+ * return PA_ERR_NODATA. For more details see
+ * pa_stream_get_timing_info() and pa_stream_get_time(). */
 int pa_stream_get_latency(pa_stream *s, pa_usec_t *r_usec, int *negative);
 
 /** Return the latest raw timing data structure. The returned pointer
  * points to an internal read-only instance of the timing
  * structure. The user should make a copy of this structure if he
  * wants to modify it. An in-place update to this data structure may
- * be requested using pa_stream_update_timing_info(). If no
- * pa_stream_update_timing_info() call was issued before, this
- * function will fail with PA_ERR_NODATA. Please note that the
- * write_index member field (and only this field) is updated on each
- * pa_stream_write() call, not just when a timing update has been
- * recieved. */
+ * be requested using pa_stream_update_timing_info().
+ *
+ * If no timing information has been received before (i.e. by
+ * requesting pa_stream_update_timing_info() or by using
+ * PA_STREAM_AUTO_TIMING_UPDATE), this function will fail with
+ * PA_ERR_NODATA.
+ *
+ * Please note that the write_index member field (and only this field)
+ * is updated on each pa_stream_write() call, not just when a timing
+ * update has been recieved. */
 const pa_timing_info* pa_stream_get_timing_info(pa_stream *s);
 
 /** Return a pointer to the stream's sample specification. */

commit 4ff41ecbb090e36a394ab4c6721e763085961c91
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Apr 8 03:47:18 2009 +0200

    print smallest attenuation/sample

diff --git a/src/tests/voltest.c b/src/tests/voltest.c
index 0c6d2ea..2dcfa53 100644
--- a/src/tests/voltest.c
+++ b/src/tests/voltest.c
@@ -9,6 +9,9 @@ int main(int argc, char *argv[]) {
     float b;
     pa_channel_map map;
 
+    printf("Attenuation of sample 1 against 32767: %g dB\n", 20.0*log10(1.0/32767.0));
+    printf("Smallest possible attenutation > 0 applied to 32767: %li\n", lrint(32767.0*pa_sw_volume_to_linear(1)));
+
     for (v = PA_VOLUME_MUTED; v <= PA_VOLUME_NORM*2; v += 256) {
 
         double dB = pa_sw_volume_to_dB(v);

commit 14e89d4ecdded1d201ac3a382d265f117988c369
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Apr 8 03:47:48 2009 +0200

    when calculating volume from dB use ceil()

diff --git a/src/pulse/volume.c b/src/pulse/volume.c
index 9033c32..ad3b3a4 100644
--- a/src/pulse/volume.c
+++ b/src/pulse/volume.c
@@ -126,7 +126,7 @@ pa_volume_t pa_sw_volume_from_dB(double dB) {
     if (isinf(dB) < 0 || dB <= -USER_DECIBEL_RANGE)
         return PA_VOLUME_MUTED;
 
-    return (pa_volume_t) lrint((dB/USER_DECIBEL_RANGE+1)*PA_VOLUME_NORM);
+    return (pa_volume_t) lrint(ceil((dB/USER_DECIBEL_RANGE+1.0)*PA_VOLUME_NORM));
 }
 
 double pa_sw_volume_to_dB(pa_volume_t v) {
@@ -144,7 +144,7 @@ pa_volume_t pa_sw_volume_from_linear(double v) {
     if (v > .999 && v < 1.001)
         return PA_VOLUME_NORM;
 
-    return pa_sw_volume_from_dB(20*log10(v));
+    return pa_sw_volume_from_dB(20.0*log10(v));
 }
 
 double pa_sw_volume_to_linear(pa_volume_t v) {

commit c32c6c833e328610729ec034801ea110f5178cc1
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Apr 8 03:49:16 2009 +0200

    introduce relative_volume field in sink_input and make use of it on sink flat volume change

diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index ad6b9ca..5855977 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -288,6 +288,7 @@ int pa_sink_input_new(
 
     i->volume_factor = data->volume_factor;
     pa_cvolume_init(&i->soft_volume);
+    memset(i->relative_volume, 0, sizeof(i->relative_volume));
     i->save_volume = data->save_volume;
     i->save_sink = data->save_sink;
     i->save_muted = data->save_muted;
@@ -530,7 +531,7 @@ void pa_sink_input_put(pa_sink_input *i) {
         pa_sink_update_flat_volume(i->sink, &new_volume);
         pa_sink_set_volume(i->sink, &new_volume, FALSE, FALSE);
     } else
-        pa_sw_cvolume_multiply(&i->soft_volume, &i->virtual_volume, &i->volume_factor);
+        pa_sink_input_set_relative_volume(i, &i->virtual_volume);
 
     i->thread_info.soft_volume = i->soft_volume;
     i->thread_info.muted = i->muted;
@@ -901,11 +902,12 @@ void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, pa_boo
 
         /* OK, we are in normal volume mode. The volume only affects
          * ourselves */
-        pa_sw_cvolume_multiply(&i->soft_volume, volume, &i->volume_factor);
+        pa_sink_input_set_relative_volume(i, volume);
 
         /* Hooks have the ability to play games with i->soft_volume */
         pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_SET_VOLUME], i);
 
+        /* Copy the new soft_volume to the thread_info struct */
         pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME, NULL, 0, NULL) == 0);
     }
 
@@ -923,24 +925,50 @@ const pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i) {
 
 /* Called from main context */
 pa_cvolume *pa_sink_input_get_relative_volume(pa_sink_input *i, pa_cvolume *v) {
+    unsigned c;
+
     pa_sink_input_assert_ref(i);
     pa_assert(v);
     pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
 
-    *v = i->virtual_volume;
-
     /* This always returns a relative volume, even in flat volume mode */
 
-    if (i->sink->flags & PA_SINK_FLAT_VOLUME) {
-        pa_cvolume sv;
+    v->channels = i->sample_spec.channels;
+
+    for (c = 0; c < v->channels; c++)
+        v->values[c] = pa_sw_volume_from_linear(i->relative_volume[c]);
+
+    return v;
+}
+
+/* Called from main context */
+void pa_sink_input_set_relative_volume(pa_sink_input *i, const pa_cvolume *v) {
+    unsigned c;
+    pa_cvolume _v;
 
-        sv = *pa_sink_get_volume(i->sink, FALSE);
+    pa_sink_input_assert_ref(i);
+    pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
+    pa_assert(!v || pa_cvolume_compatible(v, &i->sample_spec));
+
+    if (!v)
+        v = pa_cvolume_reset(&_v, i->sample_spec.channels);
+
+    /* This basically calculates:
+     *
+     * i->relative_volume := v
+     * i->soft_volume := i->relative_volume * i->volume_factor */
 
-        pa_sw_cvolume_divide(v, v,
-                             pa_cvolume_remap(&sv, &i->sink->channel_map, &i->channel_map));
+    i->soft_volume.channels = i->sample_spec.channels;
+
+    for (c = 0; c < i->sample_spec.channels; c++) {
+        i->relative_volume[c] = pa_sw_volume_to_linear(v->values[c]);
+
+        i->soft_volume.values[c] = pa_sw_volume_from_linear(
+                i->relative_volume[c] *
+                pa_sw_volume_to_linear(i->volume_factor.values[c]));
     }
 
-    return v;
+    /* We don't copy the data to the thread_info data. That's left for someone else to do */
 }
 
 /* Called from main context */
@@ -1110,9 +1138,11 @@ int pa_sink_input_start_move(pa_sink_input *i) {
     if (i->sink->flags & PA_SINK_FLAT_VOLUME) {
         pa_cvolume new_volume;
 
-        /* Make the absolute volume relative */
-        i->virtual_volume = i->soft_volume;
-        i->soft_volume = i->volume_factor;
+        /* Make the virtual volume relative */
+        pa_sink_input_get_relative_volume(i, &i->virtual_volume);
+
+        /* And reset the the relative volume */
+        pa_sink_input_set_relative_volume(i, NULL);
 
         /* We might need to update the sink's volume if we are in flat
          * volume mode. */
diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h
index 6ecb5d7..96ad2ba 100644
--- a/src/pulsecore/sink-input.h
+++ b/src/pulsecore/sink-input.h
@@ -91,7 +91,10 @@ struct pa_sink_input {
 
     pa_sink_input *sync_prev, *sync_next;
 
-    pa_cvolume virtual_volume, soft_volume, volume_factor;
+    pa_cvolume virtual_volume;  /* The volume clients are informed about */
+    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 */
+    double relative_volume[PA_CHANNELS_MAX]; /* The calculated volume relative to the sink volume as linear factors. */
+    pa_cvolume soft_volume;     /* The internal software volume we apply to all PCM data while it passes through. Usually calculated as relative_volume * volume_factor  */
     pa_bool_t muted:1;
 
     /* if TRUE then the source we are connected to and/or the volume
@@ -349,4 +352,7 @@ pa_bool_t pa_sink_input_safe_to_remove(pa_sink_input *i);
 
 pa_memchunk* pa_sink_input_get_silence(pa_sink_input *i, pa_memchunk *ret);
 
+/* To be used by sink.c only */
+void pa_sink_input_set_relative_volume(pa_sink_input *i, const pa_cvolume *v);
+
 #endif
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 886402a..4cf7b6c 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -990,22 +990,32 @@ static void compute_new_soft_volume(pa_sink_input *i, const pa_cvolume *new_volu
     pa_sink_input_assert_ref(i);
     pa_assert(new_volume->channels == i->sample_spec.channels);
 
-    /* This basically calculates i->soft_volume := i->virtual_volume / new_volume * i->volume_factor */
+    /*
+     * This basically calculates:
+     *
+     * i->relative_volume := i->virtual_volume / new_volume
+     * i->soft_volume := i->relative_volume * i->volume_factor
+     */
 
     /* The new sink volume passed in here must already be remapped to
      * the sink input's channel map! */
 
+    i->soft_volume.channels = i->sample_spec.channels;
+
     for (c = 0; c < i->sample_spec.channels; c++)
 
         if (new_volume->values[c] <= PA_VOLUME_MUTED)
+            /* We leave i->relative_volume untouched */
             i->soft_volume.values[c] = PA_VOLUME_MUTED;
-        else
-            i->soft_volume.values[c] = pa_sw_volume_from_linear(
-                    pa_sw_volume_to_linear(i->virtual_volume.values[c]) *
-                    pa_sw_volume_to_linear(i->volume_factor.values[c]) /
-                    pa_sw_volume_to_linear(new_volume->values[c]));
+        else {
+            i->relative_volume[c] =
+                pa_sw_volume_to_linear(i->virtual_volume.values[c]) /
+                pa_sw_volume_to_linear(new_volume->values[c]);
 
-    i->soft_volume.channels = i->sample_spec.channels;
+            i->soft_volume.values[c] = pa_sw_volume_from_linear(
+                    i->relative_volume[c] *
+                    pa_sw_volume_to_linear(i->volume_factor.values[c]));
+        }
 
     /* Hooks have the ability to play games with i->soft_volume */
     pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_SET_VOLUME], i);
@@ -1071,12 +1081,11 @@ void pa_sink_update_flat_volume(pa_sink *s, pa_cvolume *new_volume) {
 }
 
 /* Called from main thread */
-void pa_sink_propagate_flat_volume(pa_sink *s, const pa_cvolume *old_volume) {
+void pa_sink_propagate_flat_volume(pa_sink *s) {
     pa_sink_input *i;
     uint32_t idx;
 
     pa_sink_assert_ref(s);
-    pa_assert(old_volume);
     pa_assert(PA_SINK_IS_LINKED(s->state));
     pa_assert(s->flags & PA_SINK_FLAT_VOLUME);
 
@@ -1085,26 +1094,18 @@ void pa_sink_propagate_flat_volume(pa_sink *s, const pa_cvolume *old_volume) {
      * sink input volumes accordingly */
 
     for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx))) {
-        pa_cvolume remapped_old_volume, remapped_new_volume, new_virtual_volume;
+        pa_cvolume sink_volume, new_virtual_volume;
         unsigned c;
 
-        /* This basically calculates i->virtual_volume := i->virtual_volume * s->virtual_volume / old_volume */
-
-        remapped_new_volume = s->virtual_volume;
-        pa_cvolume_remap(&remapped_new_volume, &s->channel_map, &i->channel_map);
+        /* This basically calculates i->virtual_volume := i->relative_volume * s->virtual_volume  */
 
-        remapped_old_volume = *old_volume;
-        pa_cvolume_remap(&remapped_old_volume, &s->channel_map, &i->channel_map);
+        sink_volume = s->virtual_volume;
+        pa_cvolume_remap(&sink_volume, &s->channel_map, &i->channel_map);
 
         for (c = 0; c < i->sample_spec.channels; c++)
-
-            if (remapped_old_volume.values[c] <= PA_VOLUME_MUTED)
-                new_virtual_volume.values[c] = remapped_new_volume.values[c];
-            else
-                new_virtual_volume.values[c] = pa_sw_volume_from_linear(
-                        pa_sw_volume_to_linear(i->virtual_volume.values[c]) *
-                        pa_sw_volume_to_linear(remapped_new_volume.values[c]) /
-                        pa_sw_volume_to_linear(remapped_old_volume.values[c]));
+            new_virtual_volume.values[c] = pa_sw_volume_from_linear(
+                    i->relative_volume[c] *
+                    pa_sw_volume_to_linear(sink_volume.values[c]));
 
         new_virtual_volume.channels = i->sample_spec.channels;
 
@@ -1116,7 +1117,7 @@ void pa_sink_propagate_flat_volume(pa_sink *s, const pa_cvolume *old_volume) {
              * especially when the old volume was
              * PA_VOLUME_MUTED. Hence let's recalculate the soft
              * volumes here. */
-            compute_new_soft_volume(i, &remapped_new_volume);
+            compute_new_soft_volume(i, &sink_volume);
 
             /* The virtual volume changed, let's tell people so */
             pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
@@ -1130,7 +1131,6 @@ void pa_sink_propagate_flat_volume(pa_sink *s, const pa_cvolume *old_volume) {
 
 /* Called from main thread */
 void pa_sink_set_volume(pa_sink *s, const pa_cvolume *volume, pa_bool_t propagate, pa_bool_t sendmsg) {
-    pa_cvolume old_virtual_volume;
     pa_bool_t virtual_volume_changed;
 
     pa_sink_assert_ref(s);
@@ -1139,14 +1139,13 @@ void pa_sink_set_volume(pa_sink *s, const pa_cvolume *volume, pa_bool_t propagat
     pa_assert(pa_cvolume_valid(volume));
     pa_assert(pa_cvolume_compatible(volume, &s->sample_spec));
 
-    old_virtual_volume = s->virtual_volume;
+    virtual_volume_changed = !pa_cvolume_equal(volume, &s->virtual_volume);
     s->virtual_volume = *volume;
-    virtual_volume_changed = !pa_cvolume_equal(&old_virtual_volume, &s->virtual_volume);
 
     /* Propagate this volume change back to the inputs */
     if (virtual_volume_changed)
         if (propagate && (s->flags & PA_SINK_FLAT_VOLUME))
-            pa_sink_propagate_flat_volume(s, &old_virtual_volume);
+            pa_sink_propagate_flat_volume(s);
 
     if (s->set_volume) {
         /* If we have a function set_volume(), then we do not apply a
@@ -1197,7 +1196,7 @@ const pa_cvolume *pa_sink_get_volume(pa_sink *s, pa_bool_t force_refresh) {
         if (!pa_cvolume_equal(&old_virtual_volume, &s->virtual_volume)) {
 
             if (s->flags & PA_SINK_FLAT_VOLUME)
-                pa_sink_propagate_flat_volume(s, &old_virtual_volume);
+                pa_sink_propagate_flat_volume(s);
 
             pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
         }
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index eb1c88f..289054d 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -74,7 +74,8 @@ struct pa_sink {
     pa_volume_t base_volume; /* shall be constant */
     unsigned n_volume_steps; /* shall be constant */
 
-    pa_cvolume virtual_volume, soft_volume;
+    pa_cvolume virtual_volume; /* The volume clients are informed about */
+    pa_cvolume soft_volume;    /* The internal software volume we apply to all PCM data while it passes through */
     pa_bool_t muted:1;
 
     pa_bool_t refresh_volume:1;
@@ -250,7 +251,7 @@ int pa_sink_suspend(pa_sink *s, pa_bool_t suspend);
 int pa_sink_suspend_all(pa_core *c, pa_bool_t suspend);
 
 void pa_sink_update_flat_volume(pa_sink *s, pa_cvolume *new_volume);
-void pa_sink_propagate_flat_volume(pa_sink *s, const pa_cvolume *old_volume);
+void pa_sink_propagate_flat_volume(pa_sink *s);
 
 void pa_sink_set_volume(pa_sink *sink, const pa_cvolume *volume, pa_bool_t propagate, pa_bool_t sendmsg);
 const pa_cvolume *pa_sink_get_volume(pa_sink *sink, pa_bool_t force_refresh);

-- 
hooks/post-receive
PulseAudio Sound Server



More information about the pulseaudio-commits mailing list