summaryrefslogtreecommitdiffstats
path: root/sys/dev/sound/pcm/feeder.c
diff options
context:
space:
mode:
authorcg <cg@FreeBSD.org>2000-09-09 21:24:03 +0000
committercg <cg@FreeBSD.org>2000-09-09 21:24:03 +0000
commitb5350bb3a5beaa89886049b7fe66b1c8d754891e (patch)
treeef8f5854ae0d42e828288bf7617795a2ebf5aaff /sys/dev/sound/pcm/feeder.c
parenta081b436a34dc6b7c3f1418e1429edbd7a31c3ff (diff)
downloadFreeBSD-src-b5350bb3a5beaa89886049b7fe66b1c8d754891e.zip
FreeBSD-src-b5350bb3a5beaa89886049b7fe66b1c8d754891e.tar.gz
add 16bit mono/stereo conversion feeder
prefer feeder chains of length 1 over length 2
Diffstat (limited to 'sys/dev/sound/pcm/feeder.c')
-rw-r--r--sys/dev/sound/pcm/feeder.c96
1 files changed, 90 insertions, 6 deletions
diff --git a/sys/dev/sound/pcm/feeder.c b/sys/dev/sound/pcm/feeder.c
index 91049e6..66e9fb1 100644
--- a/sys/dev/sound/pcm/feeder.c
+++ b/sys/dev/sound/pcm/feeder.c
@@ -29,6 +29,7 @@
#include <dev/sound/pcm/sound.h>
#define FEEDBUFSZ 8192
+#undef FEEDER_DEBUG
static unsigned char ulaw_to_u8[] = {
3, 7, 11, 15, 19, 23, 27, 31,
@@ -271,6 +272,38 @@ SYSINIT(feeder_monotostereo8, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, feeder_register,
/*****************************************************************************/
static int
+feed_monotostereo16(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct uio *stream)
+{
+ int i, j, k = f->source->feed(f->source, c, b, count / 2, stream);
+ u_int8_t x, y;
+
+ j = k - 1;
+ i = j * 2 + 1;
+ while (i > 3 && j >= 1) {
+ x = b[j--];
+ y = b[j--];
+ b[i--] = x;
+ b[i--] = y;
+ b[i--] = x;
+ b[i--] = y;
+ }
+ return k * 2;
+}
+
+static struct pcm_feederdesc desc_monotostereo16[] = {
+ {FEEDER_FMT, AFMT_U16_LE, AFMT_U16_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S16_LE, AFMT_S16_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U16_BE, AFMT_U16_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S16_BE, AFMT_S16_BE | AFMT_STEREO, 0},
+ {0},
+};
+static pcm_feeder feeder_monotostereo16 =
+ { "monotostereo16", 0, desc_monotostereo16, NULL, NULL, feed_monotostereo16 };
+SYSINIT(feeder_monotostereo16, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, feeder_register, &feeder_monotostereo16);
+
+/*****************************************************************************/
+
+static int
feed_stereotomono8_init(pcm_feeder *f)
{
f->data = malloc(FEEDBUFSZ, M_DEVBUF, M_NOWAIT);
@@ -311,6 +344,49 @@ SYSINIT(feeder_stereotomono8, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, feeder_register,
/*****************************************************************************/
static int
+feed_stereotomono16_init(pcm_feeder *f)
+{
+ f->data = malloc(FEEDBUFSZ, M_DEVBUF, M_NOWAIT);
+ return (f->data == NULL);
+}
+
+static int
+feed_stereotomono16_free(pcm_feeder *f)
+{
+ if (f->data) free(f->data, M_DEVBUF);
+ f->data = NULL;
+ return 0;
+}
+
+static int
+feed_stereotomono16(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct uio *stream)
+{
+ u_int32_t i = 0, toget = count * 2;
+ int j = 0, k;
+
+ k = f->source->feed(f->source, c, f->data, min(toget, FEEDBUFSZ), stream);
+ while (j < k) {
+ b[i++] = ((u_int8_t *)f->data)[j];
+ b[i++] = ((u_int8_t *)f->data)[j + 1];
+ j += 4;
+ }
+ return i;
+}
+
+static struct pcm_feederdesc desc_stereotomono16[] = {
+ {FEEDER_FMT, AFMT_U16_LE | AFMT_STEREO, AFMT_U16_LE, 0},
+ {FEEDER_FMT, AFMT_S16_LE | AFMT_STEREO, AFMT_S16_LE, 0},
+ {FEEDER_FMT, AFMT_U16_BE | AFMT_STEREO, AFMT_U16_BE, 0},
+ {FEEDER_FMT, AFMT_S16_BE | AFMT_STEREO, AFMT_S16_BE, 0},
+ {0},
+};
+static pcm_feeder feeder_stereotomono16 =
+ { "stereotomono16", 1, desc_stereotomono16, feed_stereotomono16_init, feed_stereotomono16_free, feed_stereotomono16 };
+SYSINIT(feeder_stereotomono16, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, feeder_register, &feeder_stereotomono16);
+
+/*****************************************************************************/
+
+static int
feed_endian(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct uio *stream)
{
u_int8_t t;
@@ -529,17 +605,23 @@ chn_feedchain(pcm_channel *c, u_int32_t *to)
stop = c->feeder;
try = NULL;
max = 0;
- while (try == NULL && max++ < 8)
+ while (try == NULL && max < 8) {
try = feeder_fmtchain(to, c->feeder, stop, max);
+ max++;
+ }
if (try == NULL)
return 0;
c->feeder = try;
c->align = 0;
- /* printf("chain: "); */
+#ifdef FEEDER_DEBUG
+ printf("chain: ");
+#endif
while (try && (try != stop)) {
- /* printf("%s [%d]", try->name, try->desc->idx); */
- /* if (try->source) */
- /* printf(" -> "); */
+#ifdef FEEDER_DEBUG
+ printf("%s [%d]", try->name, try->desc->idx);
+ if (try->source)
+ printf(" -> ");
+#endif
if (try->init)
try->init(try);
if (try->align > 0)
@@ -548,6 +630,8 @@ chn_feedchain(pcm_channel *c, u_int32_t *to)
c->align = -try->align;
try = try->source;
}
- /* printf("%s [%d]", try->name, try->desc->idx); */
+#ifdef FEEDER_DEBUG
+ printf("%s [%d]\n", try->name, try->desc->idx);
+#endif
return c->feeder->desc->out;
}
OpenPOWER on IntegriCloud