patch for 24-bit soft volume and uaudio's tiny fix
Kazuhito HONDA
kazuhito at ph.noda.tus.ac.jp
Fri Dec 16 10:37:18 PST 2005
Hello,
We have already had a soft volume, feeder_volume_s16().
But it is of 16 bit. So 24-bit sound streams are
always downgraded to 16-bit before soft volume
even though a sound device has a 24-bit port.
Thus 24-bit soft volume is necessary.
This mail has a patch for 24-bit soft volume.
I tried to use it with `SB Live! 24-bit external'
and it worked.
And the patch includes a fix of tiny mistakes in uaudio.c, too.
Sincerely yours,
Kazuhito HONDA
-------------- next part --------------
--- sys/dev/sound/pcm/feeder_volume.c.old Tue Nov 22 10:13:37 2005
+++ sys/dev/sound/pcm/feeder_volume.c Sat Dec 17 02:41:08 2005
@@ -67,6 +67,49 @@ feed_volume_s16(struct pcm_feeder *f, st
return k;
}
+static int
+feed_volume_s24(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
+ uint32_t count, void *source)
+{
+ int i, k, vol[2];
+ int32_t buf, j;
+ uint8_t *buf8;
+
+ k = FEEDER_FEED(f->source, c, b, (count / 3) * 3, source);
+ if (k < 3) {
+#if 0
+ device_printf(c->dev, "%s: Not enough data (Got: %d bytes)\n",
+ __func__, k);
+#endif
+ return 0;
+ }
+#if 0
+ if (k % 3)
+ device_printf(c->dev, "%s: Bytes not 24bit aligned.\n", __func__);
+#endif
+ k -= k % 3;
+ i = k;
+ vol[0] = c->volume & 0x7f;
+ vol[1] = (c->volume >> 8) & 0x7f;
+ while (i > 2) {
+ buf = 0;
+ buf8 = (int8_t *) (&buf);
+ buf8[0] = b[--i];
+ buf8[1] = b[--i];
+ buf8[2] = b[--i];
+ j = (vol[i & 1] * buf) / 100;
+ if (j > 8388607)
+ j = 8388607;
+ if (j < -8388608)
+ j = -8388608;
+ buf8 = (int8_t *) (&j);
+ b[i + 2] = buf8[0];
+ b[i + 1] = buf8[1];
+ b[i] = buf8[2];
+ }
+ return k;
+}
+
static struct pcm_feederdesc feeder_volume_s16_desc[] = {
{FEEDER_VOLUME, AFMT_S16_LE|AFMT_STEREO, AFMT_S16_LE|AFMT_STEREO, 0},
{0, 0, 0, 0},
@@ -76,3 +119,13 @@ static kobj_method_t feeder_volume_s16_m
{0, 0}
};
FEEDER_DECLARE(feeder_volume_s16, 2, NULL);
+
+static struct pcm_feederdesc feeder_volume_s24_desc[] = {
+ {FEEDER_VOLUME, AFMT_S24_LE|AFMT_STEREO, AFMT_S24_LE|AFMT_STEREO, 0},
+ {0, 0, 0, 0},
+};
+static kobj_method_t feeder_volume_s24_methods[] = {
+ KOBJMETHOD(feeder_feed, feed_volume_s24),
+ {0, 0}
+};
+FEEDER_DECLARE(feeder_volume_s24, 2, NULL);
--- sys/dev/sound/pcm/channel.c.old Fri Dec 16 23:44:24 2005
+++ sys/dev/sound/pcm/channel.c Fri Dec 16 23:57:30 2005
@@ -1372,9 +1372,19 @@ chn_buildfeeder(struct pcm_channel *c)
for (type = FEEDER_RATE; type <= FEEDER_LAST; type++) {
if (flags & (1 << type)) {
desc.type = type;
- desc.in = 0;
desc.out = 0;
desc.flags = 0;
+ if (type == FEEDER_VOLUME) {
+ if (c->feeder->desc->out & (AFMT_S24_LE | AFMT_S24_BE | AFMT_U24_LE | AFMT_U24_BE)) {
+ desc.in = AFMT_S24_LE | AFMT_STEREO;
+ } else if (c->feeder->desc->out & (AFMT_S16_LE | AFMT_S16_BE | AFMT_U16_LE | AFMT_U16_BE)) {
+ desc.in = AFMT_S16_LE | AFMT_STEREO;
+ } else {
+ desc.in = 0;
+ }
+ } else {
+ desc.in = 0;
+ }
DEB(printf("find feeder type %d, ", type));
fc = feeder_getclass(&desc);
DEB(printf("got %p\n", fc));
--- sys/dev/sound/usb/uaudio.c.old Sun Nov 13 23:20:26 2005
+++ sys/dev/sound/usb/uaudio.c Sat Dec 17 00:00:11 2005
@@ -3909,10 +3909,10 @@ const struct uaudio_conversion const acc
{AUDIO_ENCODING_SLINEAR_LE, 8, AFMT_S8},
{AUDIO_ENCODING_SLINEAR_LE, 16, AFMT_S16_LE},
{AUDIO_ENCODING_SLINEAR_LE, 24, AFMT_S24_LE},
- {AUDIO_ENCODING_SLINEAR_LE, 24, AFMT_S32_LE},
+ {AUDIO_ENCODING_SLINEAR_LE, 32, AFMT_S32_LE},
{AUDIO_ENCODING_SLINEAR_BE, 16, AFMT_S16_BE},
{AUDIO_ENCODING_SLINEAR_BE, 24, AFMT_S24_BE},
- {AUDIO_ENCODING_SLINEAR_BE, 24, AFMT_S32_BE},
+ {AUDIO_ENCODING_SLINEAR_BE, 32, AFMT_S32_BE},
{AUDIO_ENCODING_ALAW, 8, AFMT_A_LAW},
{AUDIO_ENCODING_ULAW, 8, AFMT_MU_LAW},
{0,0,0}
More information about the freebsd-multimedia
mailing list