Index: sys/dev/audio/audio.c
===================================================================
RCS file: /cvsroot/src/sys/dev/audio/audio.c,v
retrieving revision 1.17
diff -p -u -r1.17 audio.c
--- sys/dev/audio/audio.c	12 Jun 2019 13:53:25 -0000	1.17
+++ sys/dev/audio/audio.c	15 Jun 2019 18:19:53 -0000
@@ -2452,6 +2452,30 @@ abort:
 	return error;
 }
 
+static u_int
+audio_interpolate_offset(audio_track_t *track)
+{
+	const audio_format2_t *f = &track->inputfmt;
+	struct timeval *last = &track->usrbuf_stamp_time;
+	struct timeval tv;
+	u_int bps, bytes;
+
+	getmicrotime(&tv);
+	timersub(&tv, last, &tv);
+
+	/* out of sync */
+	if (tv.tv_sec > 0)
+		return 0;
+
+	bps = f->sample_rate * f->stride * f->channels / 8;
+
+	bytes = tv.tv_usec * bps * track->usrbuf_blksize / 1000000;
+	if (bytes >= track->usrbuf_blksize)
+		bytes = track->usrbuf_blksize - 1;
+
+	return bytes;
+}
+
 int
 audio_ioctl(dev_t dev, struct audio_softc *sc, u_long cmd, void *addr, int flag,
 	struct lwp *l, audio_file_t *file)
@@ -2590,7 +2614,7 @@ audio_ioctl(dev_t dev, struct audio_soft
 		    (track->usrbuf_stamp_last / track->usrbuf_blksize);
 		track->usrbuf_stamp_last = stamp;
 		offs = rounddown(offs, track->usrbuf_blksize)
-		    + track->usrbuf_blksize;
+		    + audio_interpolate_offset(track);
 		if (offs >= track->usrbuf.capacity)
 			offs -= track->usrbuf.capacity;
 		ao->offset = offs;
@@ -4352,6 +4376,7 @@ audio_track_play(audio_track_t *track)
 	}
 
 	track->usrbuf_stamp += bytes;
+	getmicrotime(&track->usrbuf_stamp_time);
 
 	if (usrbuf->head + bytes < usrbuf->capacity) {
 		memcpy((uint8_t *)input->mem + auring_tail(input) * framesize,
Index: sys/dev/audio/audiodef.h
===================================================================
RCS file: /cvsroot/src/sys/dev/audio/audiodef.h,v
retrieving revision 1.4
diff -p -u -r1.4 audiodef.h
--- sys/dev/audio/audiodef.h	10 Jun 2019 13:49:39 -0000	1.4
+++ sys/dev/audio/audiodef.h	15 Jun 2019 18:19:53 -0000
@@ -91,6 +91,7 @@ typedef struct audio_track {
 	bool		mmapped;	/* device is mmap()-ed */
 	u_int		usrbuf_stamp;	/* transferred bytes from/to stage */
 	u_int		usrbuf_stamp_last; /* last stamp */
+	struct timeval	usrbuf_stamp_time; /* time of last transfer */
 	u_int		usrbuf_usedhigh;/* high water mark in bytes */
 	u_int		usrbuf_usedlow;	/* low water mark in bytes */
 
