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:
Ariff Abdullah 2006-01-24 01:10:07 +00:00
parent 7f34b521c7
commit 14665331ab
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=154741
2 changed files with 29 additions and 10 deletions

View File

@ -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;
} }

View File

@ -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;
} }