[patch] stereo input is mixed to monaural via SoundBlaster16 recording mixer

Watanabe Kazuhiro CQG00620 at nifty.ne.jp
Tue Nov 8 15:36:00 GMT 2005


Hi, all.

I have a SoundBlaster Vibra16S(CT2800) soundcard.

When I try to record with wavrec (a part of ports/audio/wavplay), even
if an input source is 2-channel stereo, the recording output becomes
2-channel monaural.

 * Environment (FreeBSD-current; CVSup'ed Nov. 8)

$ uname -a
FreeBSD scorpio.zodiac.org 7.0-CURRENT FreeBSD 7.0-CURRENT #4: Tue Nov  8 18:41:14 JST 2005     nabe at scorpio.zodiac.org:/FreeBSD/obj-current/FreeBSD/FreeBSD-current/src/sys/GENERIC  i386
$ cat /dev/sndstat
FreeBSD Audio Driver (newpcm)
Installed devices:
pcm0: <Avance Logic ALS4000> at io 0xe800 irq 9 kld snd_als4000 (1p/1r/0v channels duplex default)
pcm1: <SB16 DSP 4.13> at io 0x240 irq 5 drq 1:5 bufsz 4096 kld snd_sb16 (1p/1r/0v channels duplex)
pcm2: <CS423x> at io 0x534 irq 10 drq 3:0 bufsz 4096 (1p/1r/0v channels duplex)

 * How to test

$ mixer -f /dev/mixer1 =rec cd
Recording source: cd
$ cdcontrol play && wavrec -d /dev/dsp1 -M -s 44100 -b 16 -t 30 mono.wav
$ cdcontrol stop
$ cdcontrol play && wavrec -d /dev/dsp1 -S -s 44100 -b 16 -t 30 stereo.wav
$ cdcontrol stop
$ wavplay -d /dev/dsp1 mono.wav stereo.wav
Pathname:       mono.wav
Device:         /dev/dsp1
Sampling Rate:  44100 Hz
Mode:           Mono
Samples:        1323000
Bits:           16

Pathname:       stereo.wav
Device:         /dev/dsp1
Sampling Rate:  44100 Hz
Mode:           Stereo
Samples:        1323000
Bits:           16

/* listen the two files carefully... */


This behavior is hard-coded in /sys/dev/sound/isa/sb16.c:

| static int
| sb16mix_setrecsrc(struct snd_mixer *m, u_int32_t src)
| {
|         struct sb_info *sb = mix_getdevinfo(m);
|         u_char recdev;
| 
|         recdev = 0;
|         if (src & SOUND_MASK_MIC)
|                 recdev |= 0x01; /* mono mic */
| 
|         if (src & SOUND_MASK_CD)
|                 recdev |= 0x06; /* l+r cd */
| 
|         if (src & SOUND_MASK_LINE)
|                 recdev |= 0x18; /* l+r line */
| 
|         if (src & SOUND_MASK_SYNTH)
|                 recdev |= 0x60; /* l+r midi */
| 
|         sb_setmixer(sb, SB16_IMASK_L, recdev);
|         sb_setmixer(sb, SB16_IMASK_R, recdev);

This behavior has not been changed since the newpcm driver was
commited to the FreeBSD source tree (8 years ago).

It seems that there is no one who is worried about this behavior;
even so, I think these are improper settings as default.


It's a fix patch.  This patch also fixes `cat /dev/sndstat` output.
I've referred to following sources:

sb_mixer.[ch] (OSS/Free sound driver)
ftp://sources.freebsd.org/pub/FreeBSD/sources/RELENG_4/src/sys/i386/isa/sound/

"Hardware Programming Reference" pp70 ("Register Map of CT1745 Mixer")
http://www.alsa-project.org/alsa/ftp/datasheets/creative/hwmnl.pdf

--- sys/dev/sound/isa/sb16.c.orig	Mon Oct 10 00:44:31 2005
+++ sys/dev/sound/isa/sb16.c	Mon Nov  7 14:33:38 2005
@@ -370,23 +370,28 @@ static int
 sb16mix_setrecsrc(struct snd_mixer *m, u_int32_t src)
 {
     	struct sb_info *sb = mix_getdevinfo(m);
-    	u_char recdev;
+	u_char recdev_l, recdev_r;
 
-	recdev = 0;
+	recdev_l = 0;
+	recdev_r = 0;
 	if (src & SOUND_MASK_MIC)
-		recdev |= 0x01; /* mono mic */
+		recdev_l |= 0x01; /* mono mic */
+		recdev_r |= 0x01;
 
 	if (src & SOUND_MASK_CD)
-		recdev |= 0x06; /* l+r cd */
+		recdev_l |= 0x04; /* l cd */
+		recdev_r |= 0x02; /* r cd */
 
 	if (src & SOUND_MASK_LINE)
-		recdev |= 0x18; /* l+r line */
+		recdev_l |= 0x10; /* l line */
+		recdev_r |= 0x08; /* r line */
 
 	if (src & SOUND_MASK_SYNTH)
-		recdev |= 0x60; /* l+r midi */
+		recdev_l |= 0x40; /* l midi */
+		recdev_r |= 0x20; /* r midi */
 
-	sb_setmixer(sb, SB16_IMASK_L, recdev);
-	sb_setmixer(sb, SB16_IMASK_R, recdev);
+	sb_setmixer(sb, SB16_IMASK_L, recdev_l);
+	sb_setmixer(sb, SB16_IMASK_R, recdev_r);
 
 	/* Switch on/off FM tuner source */
 	if (src & SOUND_MASK_LINE1)
@@ -849,7 +854,7 @@ sb16_attach(device_t dev)
 	else
 		status2[0] = '\0';
 
-    	snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld drq %ld%s bufsz %ud %s",
+    	snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld drq %ld%s bufsz %u %s",
     	     	rman_get_start(sb->io_base), rman_get_start(sb->irq),
 		rman_get_start(sb->drq1), status2, sb->bufsize,
 		PCM_KLDSTRING(snd_sb16));

---
Watanabe Kazuhiro (CQG00620 at nifty.ne.jp)


More information about the freebsd-multimedia mailing list