channel.c:
(1) Fix DMA alignment, based on bytes per sample. feeder_rate.c: Handle strayed bytes (mostly caused by #1) better. This DMA alignment issues are extremely hard to reproduce unless the user happen to have a 32bit capable soundcards (ATI IXP) and knowledgeable enough to force it to operate under pure 32bit operations on both record and play directions.
This commit is contained in:
parent
7f34b521c7
commit
14665331ab
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=154741
@ -34,8 +34,11 @@
|
|||||||
SND_DECLARE_FILE("$FreeBSD$");
|
SND_DECLARE_FILE("$FreeBSD$");
|
||||||
|
|
||||||
#define MIN_CHUNK_SIZE 256 /* for uiomove etc. */
|
#define MIN_CHUNK_SIZE 256 /* for uiomove etc. */
|
||||||
|
#if 0
|
||||||
#define DMA_ALIGN_THRESHOLD 4
|
#define DMA_ALIGN_THRESHOLD 4
|
||||||
#define DMA_ALIGN_MASK (~(DMA_ALIGN_THRESHOLD - 1))
|
#define DMA_ALIGN_MASK (~(DMA_ALIGN_THRESHOLD - 1))
|
||||||
|
#endif
|
||||||
|
#define DMA_ALIGN_MASK(bps) (~((bps) - 1))
|
||||||
|
|
||||||
#define CANCHANGE(c) (!(c->flags & CHN_F_TRIGGERED))
|
#define CANCHANGE(c) (!(c->flags & CHN_F_TRIGGERED))
|
||||||
|
|
||||||
@ -1253,7 +1256,10 @@ chn_getptr(struct pcm_channel *c)
|
|||||||
#if 1
|
#if 1
|
||||||
hwptr &= ~a ; /* Apply channel align mask */
|
hwptr &= ~a ; /* Apply channel align mask */
|
||||||
#endif
|
#endif
|
||||||
|
#if 0
|
||||||
hwptr &= DMA_ALIGN_MASK; /* Apply DMA align mask */
|
hwptr &= DMA_ALIGN_MASK; /* Apply DMA align mask */
|
||||||
|
#endif
|
||||||
|
hwptr &= DMA_ALIGN_MASK(sndbuf_getbps(c->bufhard));
|
||||||
return hwptr;
|
return hwptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,6 +100,7 @@ struct feed_rate_info {
|
|||||||
uint32_t alpha; /* interpolation distance */
|
uint32_t alpha; /* interpolation distance */
|
||||||
uint32_t pos, bpos; /* current sample / buffer positions */
|
uint32_t pos, bpos; /* current sample / buffer positions */
|
||||||
uint32_t bufsz; /* total buffer size */
|
uint32_t bufsz; /* total buffer size */
|
||||||
|
uint32_t stray; /* stray bytes */
|
||||||
int32_t scale, roll; /* scale / roll factor */
|
int32_t scale, roll; /* scale / roll factor */
|
||||||
int16_t *buffer;
|
int16_t *buffer;
|
||||||
uint32_t (*convert)(struct feed_rate_info *, int16_t *, uint32_t);
|
uint32_t (*convert)(struct feed_rate_info *, int16_t *, uint32_t);
|
||||||
@ -350,6 +351,7 @@ feed_rate_setup(struct pcm_feeder *f)
|
|||||||
info->pos = 2;
|
info->pos = 2;
|
||||||
info->bpos = 4;
|
info->bpos = 4;
|
||||||
info->alpha = 0;
|
info->alpha = 0;
|
||||||
|
info->stray = 0;
|
||||||
feed_rate_reset(info);
|
feed_rate_reset(info);
|
||||||
if (info->src == info->dst) {
|
if (info->src == info->dst) {
|
||||||
/*
|
/*
|
||||||
@ -710,12 +712,13 @@ feed_rate(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
|
|||||||
slot = (((info->gx * (count >> 1)) + info->gy - info->alpha - 1) / info->gy) << 1;
|
slot = (((info->gx * (count >> 1)) + info->gy - info->alpha - 1) / info->gy) << 1;
|
||||||
RATE_TEST((slot & 1) == 0, ("%s: Slot count not sample integral (%d)\n",
|
RATE_TEST((slot & 1) == 0, ("%s: Slot count not sample integral (%d)\n",
|
||||||
__func__, slot));
|
__func__, slot));
|
||||||
slot &= ~1;
|
|
||||||
/*
|
/*
|
||||||
* Optimize buffer feeding aggresively to ensure calculated slot
|
* Optimize buffer feeding aggresively to ensure calculated slot
|
||||||
* can be fitted nicely into available buffer free space, hence
|
* can be fitted nicely into available buffer free space, hence
|
||||||
* avoiding multiple feeding.
|
* avoiding multiple feeding.
|
||||||
*/
|
*/
|
||||||
|
RATE_TEST(info->stray == 0, ("%s: [1] Stray bytes: %u\n",
|
||||||
|
__func__,info->stray));
|
||||||
if (info->pos != 2 && info->bpos - info->pos == 2 &&
|
if (info->pos != 2 && info->bpos - info->pos == 2 &&
|
||||||
info->bpos + slot > info->bufsz) {
|
info->bpos + slot > info->bufsz) {
|
||||||
/*
|
/*
|
||||||
@ -734,25 +737,31 @@ feed_rate(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
|
|||||||
i = 0;
|
i = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
fetch = info->bufsz - info->bpos;
|
fetch = (info->bufsz - info->bpos) << 1;
|
||||||
|
fetch -= info->stray;
|
||||||
RATE_ASSERT(fetch >= 0,
|
RATE_ASSERT(fetch >= 0,
|
||||||
("%s: [1] Buffer overrun: %d > %d\n",
|
("%s: [1] Buffer overrun: %d > %d\n",
|
||||||
__func__, info->bpos, info->bufsz));
|
__func__, info->bpos, info->bufsz));
|
||||||
if (slot < fetch)
|
if ((slot << 1) < fetch)
|
||||||
fetch = slot;
|
fetch = slot << 1;
|
||||||
fetch &= ~1;
|
|
||||||
if (fetch > 0) {
|
if (fetch > 0) {
|
||||||
RATE_TEST((fetch & 1) == 0,
|
RATE_ASSERT(((info->bpos << 1) - info->stray) >= 0 &&
|
||||||
("%s: Fetch size not sample integral (%d)\n",
|
((info->bpos << 1) - info->stray) < (info->bufsz << 1),
|
||||||
__func__, fetch));
|
("%s: DANGER - BUFFER OVERRUN! bufsz=%d, pos=%d\n", __func__,
|
||||||
|
info->bufsz << 1, (info->bpos << 1) - info->stray));
|
||||||
fetch = FEEDER_FEED(f->source, c,
|
fetch = FEEDER_FEED(f->source, c,
|
||||||
(uint8_t *)(info->buffer + info->bpos),
|
(uint8_t *)(info->buffer) + (info->bpos << 1) - info->stray,
|
||||||
fetch << 1, source);
|
fetch, source);
|
||||||
|
info->stray = 0;
|
||||||
if (fetch == 0)
|
if (fetch == 0)
|
||||||
break;
|
break;
|
||||||
RATE_TEST((fetch & 3) == 0,
|
RATE_TEST((fetch & 3) == 0,
|
||||||
("%s: Fetch size not byte integral (%d)\n",
|
("%s: Fetch size not byte integral (%d)\n",
|
||||||
__func__, fetch));
|
__func__, fetch));
|
||||||
|
info->stray += fetch & 3;
|
||||||
|
RATE_TEST(info->stray == 0,
|
||||||
|
("%s: Stray bytes detected (%d)\n",
|
||||||
|
__func__, info->stray));
|
||||||
fetch >>= 1;
|
fetch >>= 1;
|
||||||
fetch &= ~1;
|
fetch &= ~1;
|
||||||
info->bpos += fetch;
|
info->bpos += fetch;
|
||||||
@ -790,6 +799,7 @@ feed_rate(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
|
|||||||
* to beginning of buffer so next cycle can
|
* to beginning of buffer so next cycle can
|
||||||
* interpolate using it.
|
* interpolate using it.
|
||||||
*/
|
*/
|
||||||
|
RATE_TEST(info->stray == 0, ("%s: [2] Stray bytes: %u\n", __func__, info->stray));
|
||||||
info->buffer[0] = info->buffer[info->pos - 2];
|
info->buffer[0] = info->buffer[info->pos - 2];
|
||||||
info->buffer[1] = info->buffer[info->pos - 1];
|
info->buffer[1] = info->buffer[info->pos - 1];
|
||||||
info->bpos = 2;
|
info->bpos = 2;
|
||||||
@ -798,7 +808,10 @@ feed_rate(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
|
|||||||
if (i == count)
|
if (i == count)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
RATE_TEST(count == i, ("Expect: %u , Got: %u\n", count << 1, i << 1));
|
RATE_TEST(count == i, ("Expect: %u , Got: %u\n", count << 1, i << 1));
|
||||||
|
#endif
|
||||||
|
RATE_TEST(info->stray == 0, ("%s: [3] Stray bytes: %u\n", __func__, info->stray));
|
||||||
return i << 1;
|
return i << 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user