[nas] [PATCH] changed method of setting the input gain

Erik Auerswald auerswal at unix-ag.uni-kl.de
Sun Jul 23 18:40:19 MDT 2006


Hi,

the attached patch changes the way the input gain is controlled. After
reading some docs and googling a bit it seems that the method currently
used in the voxware server was correct for OSS 3.0. For some cards
(Soundblaster) a seperate RECLEV setting existed which could (should?)
be used. The RECLEV method has been superseded by using IGain since. OSS
4.0 uses different ioctrls, but it shall be compatible when used with
older drivers.

With this patch the voxware server tries to use IGain, if that fails
RECLEV and if that fails LINE and MIC. This should work for old and new
hardware, I hope. If this logic fails on some hw/driver combination a
config option to manually specify which method to use can be added.

The "mixerinit" option (translated to leave_mixer in auvoxware.c) works
the same before and after the patch. IMHO this option needs some
overhaul -- it should leave the mixer settings and not set the default
values. An additional option "nomixer" could be added to tell nasd not
to open a mixer device.

Erik
-------------- next part --------------
Index: server/dda/voxware/auvoxware.c
===================================================================
--- server/dda/voxware/auvoxware.c	(revision 161)
+++ server/dda/voxware/auvoxware.c	(working copy)
@@ -216,13 +216,19 @@
 
 /* VOXware sound driver mixer control variables */
 
+#define useMixerNone 0
+#define useMixerIGain 1
+#define useMixerRecLev 2
+#define useMixerLineMic 3
+
 static AuBool  relinquish_device = 0;
 static AuBool  leave_mixer = 0;
 static AuBool  share_in_out = 0;
 
-static int      lastPhysicalOutputGain;       /* output gain */
-static int      lastPhysicalInputGain;     /* input gain */
-static int      lastPhysicalInputLineMode;     /* input line mode */
+static int      lastPhysicalOutputGain;     /* output gain */
+static int      lastPhysicalInputGain;      /* input gain */
+static int      lastPhysicalInputLineMode;  /* input line mode */
+static int      recControlMode = 0;         /* how to control recording level */
 static int      level[100];
 static int      mixerfd;	/* The mixer device */
 static int      devmask = 0;	/* Bitmask for supported mixer devices */
@@ -942,7 +948,7 @@
 setPhysicalOutputGain(AuFixedPoint gain)
 {
     AuInt32         g = AuFixedPointIntegralAddend(gain);
-    AuInt32         i, gusvolume;
+    AuInt32         gusvolume;
 
 
     if (g > 100)
@@ -952,7 +958,9 @@
     lastPhysicalOutputGain = g;
     gusvolume = g | (g << 8);
     if (mixerfd != -1)
-      i = ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_PCM), &gusvolume);
+      if (ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_PCM), &gusvolume) == -1)
+        osLogMsg("%s: ioctl(MIXER_WRITE(SOUND_MIXER_PCM)) failed: %s\n",
+                 sndStatOut.mixer, strerror(errno));
 }
 
 static          AuFixedPoint
@@ -971,7 +979,6 @@
   AuInt16 g = AuFixedPointIntegralAddend(gain);
   AuInt16 inputAttenuation;
   AuInt16 zero = 0;
-  AuInt32 params[4];
   
   if (g < 100)
     inputAttenuation = g;
@@ -980,22 +987,60 @@
 
   lastPhysicalInputGain = inputAttenuation;
   lastPhysicalInputLineMode = lineMode;
+
+  if (lineMode == AuDeviceLineModeHigh) {
+    recsrc = SOUND_MASK_MIC & recmask;
+  } else if (lineMode == AuDeviceLineModeLow) {
+    recsrc = SOUND_MASK_LINE & recmask;
+  }
   
   inputAttenuation = inputAttenuation << 8 | inputAttenuation;
   
-  if (lineMode == AuDeviceLineModeHigh) {
-    if (mixerfd != -1) {
-      ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_MIC), &inputAttenuation);
-      ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_LINE), &zero);
+  if (mixerfd != -1) {
+    switch (recControlMode) {
+      case useMixerNone:
+        break;
+
+      case useMixerIGain:
+        if (ioctl(mixerfd,MIXER_WRITE(SOUND_MIXER_IGAIN),&inputAttenuation)==-1)
+          osLogMsg("%s: ioctl(MIXER_WRITE(SOUND_MIXER_IGAIN)) failed: %s\n",
+                   sndStatOut.mixer, strerror(errno));
+          break;
+
+      case useMixerRecLev:
+        if(ioctl(mixerfd,MIXER_WRITE(SOUND_MIXER_RECLEV),&inputAttenuation)==-1)
+          osLogMsg("%s: ioctl(MIXER_WRITE(SOUND_MIXER_RECLEV)) failed: %s\n",
+                   sndStatOut.mixer, strerror(errno));
+          break;
+
+      case useMixerLineMic:
+        if (lineMode == AuDeviceLineModeHigh) {
+          if (ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_LINE), &zero) == -1)
+            osLogMsg("%s: ioctl(MIXER_WRITE(SOUND_MIXER_LINE)) failed: %s\n",
+                     sndStatOut.mixer, strerror(errno));
+          if (ioctl(mixerfd,MIXER_WRITE(SOUND_MIXER_MIC),&inputAttenuation)==-1)
+            osLogMsg("%s: ioctl(MIXER_WRITE(SOUND_MIXER_MIC)) failed: %s\n",
+                     sndStatOut.mixer, strerror(errno));
+        } else if (lineMode == AuDeviceLineModeLow) {
+          if(ioctl(mixerfd,MIXER_WRITE(SOUND_MIXER_LINE),&inputAttenuation)==-1)
+            osLogMsg("%s: ioctl(MIXER_WRITE(SOUND_MIXER_LINE)) failed: %s\n",
+                     sndStatOut.mixer, strerror(errno));
+          if (ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_MIC), &zero) == -1)
+            osLogMsg("%s: ioctl(MIXER_WRITE(SOUND_MIXER_MIC)) failed: %s\n",
+                     sndStatOut.mixer, strerror(errno));
+        }
+        break;
+
+      default:
+        osLogMsg("unknown value %d of recControlMode\n", recControlMode);
+        break;
     }
+
+    if (!leave_mixer)
+      if (ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_RECSRC), &recsrc) == -1)
+        osLogMsg("%s: ioctl(MIXER_WRITE(SOUND_MIXER_RECSRC)) failed: %s\n",
+                 sndStatOut.mixer, strerror(errno));
   }
- 
-  if (lineMode == AuDeviceLineModeLow) {
-    if (mixerfd != -1) {
-      ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_LINE), &inputAttenuation);
-      ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_MIC), &zero);
-    }
-  }
 }
 
 static AuFixedPoint
@@ -1463,29 +1508,24 @@
     close(mixerfd);
     mixerfd = -1;
   } else {
+    if (devmask & (1<<SOUND_MIXER_IGAIN)) {
+      recControlMode = useMixerIGain;
+    } else if (devmask & (1<<SOUND_MIXER_RECLEV)) {
+      recControlMode = useMixerRecLev;
+    } else if ((devmask & (1<<SOUND_MIXER_LINE)) ||
+               (devmask & (1<<SOUND_MIXER_MIC))) {
+      recControlMode = useMixerLineMic;
+    } else {
+      recControlMode = useMixerNone;
+      osLogMsg("%s: can't control recording level\n", sndStatOut.mixer);
+    }
+    osLogMsg("%s: using recording level control method %d\n",
+             sndStatOut.mixer, recControlMode);
+
     if (ioctl(mixerfd, SOUND_MIXER_READ_RECMASK, &recmask) == -1) {
       return AuFalse;
     }
   
-    {
-      /* Enable all used recording sources ( mic & line ) and
-       * control which is active via level setting later. There
-       * should be a better way to do this!
-       */
-     if (!leave_mixer)
-     {
-       int mask = SOUND_MASK_MIC | SOUND_MASK_LINE; /* enable these */
-       mask &= recmask;    /* if supported */
-       if (ioctl(mixerfd, SOUND_MIXER_WRITE_RECSRC, &mask) == -1) 
-         {
-           osLogMsg("%s: ioctl(SOUND_MIXER_WRITE_RECSRC) failed: %s\n",
-                    sndStatOut.mixer,
-                    strerror(errno));
-           /*                return AuFalse; - no need to exit here..*/
-         }
-     }
-    }
-
     if (ioctl(mixerfd, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) {
       UNIDENTMSG;
       osLogMsg("%s: ioctl(SOUND_MIXER_READ_RECSRC) failed: %s\n",


More information about the Nas mailing list