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 */