Skip to content

Commit

Permalink
pcm: introduce pcm_frame_diff and pcm_frame_diff2 helpers
Browse files Browse the repository at this point in the history
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
  • Loading branch information
perexg committed Oct 13, 2020
1 parent a6c8ac0 commit 6d06fcc
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 40 deletions.
33 changes: 7 additions & 26 deletions src/pcm/pcm_dmix.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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 */
Expand All @@ -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)
Expand Down Expand Up @@ -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);
Expand All @@ -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;

Expand Down
11 changes: 2 additions & 9 deletions src/pcm/pcm_dshare.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand Down
6 changes: 1 addition & 5 deletions src/pcm/pcm_dsnoop.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
20 changes: 20 additions & 0 deletions src/pcm/pcm_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 6d06fcc

Please sign in to comment.