From c934cfadd1ea1fb9ac2c5aa3bf99bbe86c8f70b8 Mon Sep 17 00:00:00 2001 From: ariff Date: Tue, 24 Jan 2006 01:10:07 +0000 Subject: 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. --- sys/dev/sound/pcm/feeder_rate.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) (limited to 'sys/dev/sound/pcm/feeder_rate.c') diff --git a/sys/dev/sound/pcm/feeder_rate.c b/sys/dev/sound/pcm/feeder_rate.c index a8f55e8..f3b1522 100644 --- a/sys/dev/sound/pcm/feeder_rate.c +++ b/sys/dev/sound/pcm/feeder_rate.c @@ -100,6 +100,7 @@ struct feed_rate_info { uint32_t alpha; /* interpolation distance */ uint32_t pos, bpos; /* current sample / buffer positions */ uint32_t bufsz; /* total buffer size */ + uint32_t stray; /* stray bytes */ int32_t scale, roll; /* scale / roll factor */ int16_t *buffer; 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->bpos = 4; info->alpha = 0; + info->stray = 0; feed_rate_reset(info); 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; RATE_TEST((slot & 1) == 0, ("%s: Slot count not sample integral (%d)\n", __func__, slot)); - slot &= ~1; /* * Optimize buffer feeding aggresively to ensure calculated slot * can be fitted nicely into available buffer free space, hence * 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 && info->bpos + slot > info->bufsz) { /* @@ -734,25 +737,31 @@ feed_rate(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b, i = 0; for (;;) { for (;;) { - fetch = info->bufsz - info->bpos; + fetch = (info->bufsz - info->bpos) << 1; + fetch -= info->stray; RATE_ASSERT(fetch >= 0, ("%s: [1] Buffer overrun: %d > %d\n", __func__, info->bpos, info->bufsz)); - if (slot < fetch) - fetch = slot; - fetch &= ~1; + if ((slot << 1) < fetch) + fetch = slot << 1; if (fetch > 0) { - RATE_TEST((fetch & 1) == 0, - ("%s: Fetch size not sample integral (%d)\n", - __func__, fetch)); + RATE_ASSERT(((info->bpos << 1) - info->stray) >= 0 && + ((info->bpos << 1) - info->stray) < (info->bufsz << 1), + ("%s: DANGER - BUFFER OVERRUN! bufsz=%d, pos=%d\n", __func__, + info->bufsz << 1, (info->bpos << 1) - info->stray)); fetch = FEEDER_FEED(f->source, c, - (uint8_t *)(info->buffer + info->bpos), - fetch << 1, source); + (uint8_t *)(info->buffer) + (info->bpos << 1) - info->stray, + fetch, source); + info->stray = 0; if (fetch == 0) break; RATE_TEST((fetch & 3) == 0, ("%s: Fetch size not byte integral (%d)\n", __func__, fetch)); + info->stray += fetch & 3; + RATE_TEST(info->stray == 0, + ("%s: Stray bytes detected (%d)\n", + __func__, info->stray)); fetch >>= 1; fetch &= ~1; 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 * 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[1] = info->buffer[info->pos - 1]; info->bpos = 2; @@ -798,7 +808,10 @@ feed_rate(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b, if (i == count) break; } +#if 0 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; } -- cgit v1.1