OSDN Git Service

pcm: introduce pcm_frame_diff and pcm_frame_diff2 helpers
authorJaroslav Kysela <perex@perex.cz>
Tue, 13 Oct 2020 18:10:49 +0000 (20:10 +0200)
committerJaroslav Kysela <perex@perex.cz>
Tue, 13 Oct 2020 18:10:49 +0000 (20:10 +0200)
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
src/pcm/pcm_dmix.c
src/pcm/pcm_dshare.c
src/pcm/pcm_dsnoop.c
src/pcm/pcm_local.h

index 8bce7ac..bcac273 100644 (file)
@@ -319,18 +319,13 @@ static void snd_pcm_dmix_sync_area(snd_pcm_t *pcm)
        /* check the available size in the local buffer
         * last_appl_ptr keeps the last updated position
         */
-       size = dmix->appl_ptr - dmix->last_appl_ptr;
+       size = pcm_frame_diff2(dmix->appl_ptr, dmix->last_appl_ptr, pcm->boundary);
        if (! size)
                return;
-       if (size >= pcm->boundary / 2)
-               size = pcm->boundary - size;
 
        /* the slave_app_ptr can be far behind the slave_hw_ptr */
        /* reduce mixing and errors here - just skip not catched writes */
-       if (dmix->slave_hw_ptr <= dmix->slave_appl_ptr)
-               slave_size = dmix->slave_appl_ptr - dmix->slave_hw_ptr;
-       else
-               slave_size = dmix->slave_appl_ptr + (dmix->slave_boundary - dmix->slave_hw_ptr);
+       slave_size = pcm_frame_diff(dmix->slave_appl_ptr, dmix->slave_hw_ptr, dmix->slave_boundary);
        if (slave_size > dmix->slave_buffer_size) {
                transfer = dmix->slave_buffer_size - slave_size;
                if (transfer > size)
@@ -339,11 +334,9 @@ static void snd_pcm_dmix_sync_area(snd_pcm_t *pcm)
                dmix->last_appl_ptr %= pcm->boundary;
                dmix->slave_appl_ptr += transfer;
                dmix->slave_appl_ptr %= dmix->slave_boundary;
-               size = dmix->appl_ptr - dmix->last_appl_ptr;
+               size = pcm_frame_diff2(dmix->appl_ptr, dmix->last_appl_ptr, pcm->boundary);
                if (! size)
                        return;
-               if (size >= pcm->boundary / 2)
-                       size = pcm->boundary - size;
        }
 
        /* check the available size in the slave PCM buffer */
@@ -355,10 +348,7 @@ static void snd_pcm_dmix_sync_area(snd_pcm_t *pcm)
        slave_hw_ptr += dmix->slave_buffer_size;
        if (slave_hw_ptr >= dmix->slave_boundary)
                slave_hw_ptr -= dmix->slave_boundary;
-       if (slave_hw_ptr < dmix->slave_appl_ptr)
-               slave_size = slave_hw_ptr + (dmix->slave_boundary - dmix->slave_appl_ptr);
-       else
-               slave_size = slave_hw_ptr - dmix->slave_appl_ptr;
+       slave_size = pcm_frame_diff(slave_hw_ptr, dmix->slave_appl_ptr, dmix->slave_boundary);
        if (slave_size < size)
                size = slave_size;
        if (! size)
@@ -726,10 +716,7 @@ static snd_pcm_sframes_t snd_pcm_dmix_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t f
         * So they can be remixed.
         */
 
-       if (dmix->last_appl_ptr < dmix->appl_ptr)
-               size = dmix->appl_ptr - dmix->last_appl_ptr;
-       else
-               size = dmix->appl_ptr + (pcm->boundary - dmix->last_appl_ptr);
+       size = pcm_frames_diff(dmix->last_appl_ptr, dmix->appl_ptr, pcm->boundary);
        if (frames < size)
                size = frames;
        snd_pcm_mmap_appl_backward(pcm, size);
@@ -741,16 +728,10 @@ static snd_pcm_sframes_t snd_pcm_dmix_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t f
        /* Always at this point last_appl_ptr == appl_ptr
         * So (appl_ptr - hw_ptr) indicates the frames which can be remixed
         */
-       if (dmix->hw_ptr < dmix->appl_ptr)
-               size = dmix->appl_ptr - dmix->hw_ptr;
-       else
-               size = dmix->appl_ptr + (pcm->boundary - dmix->hw_ptr);
+       size = pcm_frames_diff(dmix->appl_ptr, dmix->hw_ptr, pcm->boundary);
        if (size > frames)
                size = frames;
-       if (dmix->slave_hw_ptr < dmix->slave_appl_ptr)
-               slave_size = dmix->slave_appl_ptr - dmix->slave_hw_ptr;
-       else
-               slave_size = dmix->slave_appl_ptr + (pcm->boundary - dmix->slave_hw_ptr);
+       slave_size = pcm_frames_diff(dmix->slave_appl_ptr, dmix->slave_hw_ptr, pcm->boundary);
        if (slave_size < size)
                size = slave_size;
 
index 6a99452..88fb8bf 100644 (file)
@@ -123,10 +123,7 @@ static void snd_pcm_dshare_sync_area(snd_pcm_t *pcm)
        slave_hw_ptr += dshare->slave_buffer_size;
        if (slave_hw_ptr >= dshare->slave_boundary)
                slave_hw_ptr -= dshare->slave_boundary;
-       if (slave_hw_ptr < dshare->slave_appl_ptr)
-               slave_size = slave_hw_ptr + (dshare->slave_boundary - dshare->slave_appl_ptr);
-       else
-               slave_size = slave_hw_ptr - dshare->slave_appl_ptr;
+       slave_size = pcm_frames_diff(slave_hw_ptr, dshare->slave_appl_ptr, dshare->slave_boundary);
        if (slave_size < size)
                size = slave_size;
        if (! size)
@@ -169,17 +166,13 @@ static int snd_pcm_dshare_sync_ptr0(snd_pcm_t *pcm, snd_pcm_uframes_t slave_hw_p
 
        old_slave_hw_ptr = dshare->slave_hw_ptr;
        dshare->slave_hw_ptr = slave_hw_ptr;
-       diff = slave_hw_ptr - old_slave_hw_ptr;
+       diff = pcm_frames_diff(slave_hw_ptr, old_slave_hw_ptr, dshare->slave_boundary);
        if (diff == 0)          /* fast path */
                return 0;
        if (dshare->state != SND_PCM_STATE_RUNNING &&
            dshare->state != SND_PCM_STATE_DRAINING)
                /* not really started yet - don't update hw_ptr */
                return 0;
-       if (diff < 0) {
-               slave_hw_ptr += dshare->slave_boundary;
-               diff = slave_hw_ptr - old_slave_hw_ptr;
-       }
        dshare->hw_ptr += diff;
        dshare->hw_ptr %= pcm->boundary;
        // printf("sync ptr diff = %li\n", diff);
index 7904314..bafb6dd 100644 (file)
@@ -152,13 +152,9 @@ static int snd_pcm_dsnoop_sync_ptr(snd_pcm_t *pcm)
        old_slave_hw_ptr = dsnoop->slave_hw_ptr;
        snoop_timestamp(pcm);
        slave_hw_ptr = dsnoop->slave_hw_ptr;
-       diff = slave_hw_ptr - old_slave_hw_ptr;
+       diff = pcm_frames_diff(slave_hw_ptr, old_slave_hw_ptr, dsnoop->slave_boundary);
        if (diff == 0)          /* fast path */
                return 0;
-       if (diff < 0) {
-               slave_hw_ptr += dsnoop->slave_boundary;
-               diff = slave_hw_ptr - old_slave_hw_ptr;
-       }
        snd_pcm_dsnoop_sync_area(pcm, old_slave_hw_ptr, diff);
        dsnoop->hw_ptr += diff;
        dsnoop->hw_ptr %= pcm->boundary;
index aae58ed..fe77e50 100644 (file)
@@ -1170,6 +1170,26 @@ static inline void sw_set_period_event(snd_pcm_sw_params_t *params, int val)
 
 #define PCMINABORT(pcm) (((pcm)->mode & SND_PCM_ABORT) != 0)
 
+static inline snd_pcm_sframes_t pcm_frame_diff(snd_pcm_uframes_t ptr1,
+                                              snd_pcm_uframes_t ptr2,
+                                              snd_pcm_uframes_t boundary)
+{
+       if (ptr1 < ptr2)
+               return ptr1 + (boundary - ptr2);
+       else
+               return ptr1 - ptr2;
+}
+
+static inline snd_pcm_sframes_t pcm_frame_diff2(snd_pcm_uframes_t ptr1,
+                                               snd_pcm_uframes_t ptr2,
+                                               snd_pcm_uframes_t boundary)
+{
+       snd_pcm_sframes_t r = ptr1 - ptr2;
+       if (r >= (snd_pcm_sframes_t)boundary / 2)
+               return boundary - r;
+       return r;
+}
+
 #ifdef THREAD_SAFE_API
 /*
  * __snd_pcm_lock() and __snd_pcm_unlock() are used to lock/unlock the plugin