Hello, Here's a patch against us428control in the latest alsa-tools that adds the following enhancements: - Master fader and Input Monitor faders use a logarithmic scale, like in Windows - When the Master fader is all the way down, the sound stops instead of just getting really quiet - Input Monitor pan knob now requires 1 revolution instead of 10 to pan from left to right, like in Windows - LEDs are reset to a known state when us428control starts - A new command line option "-g" to allow the gain sliders to go above 0dB gain, which may result in clipping Mike Bourgeous
diff -u4 alsa-tools-1.0.14rc3/us428control/Cus428State.cc alsa-tools-1.0.14rc3-new/us428control/Cus428State.cc --- alsa-tools-1.0.14rc3/us428control/Cus428State.cc 2007-02-26 02:24:15.000000000 -0700 +++ alsa-tools-1.0.14rc3-new/us428control/Cus428State.cc 2007-09-07 15:15:22.000000000 -0600 @@ -45,8 +45,11 @@ void Cus428State::InitDevice(void) { if (us428ctls_sharedmem->CtlSnapShotLast >= 0) SliderChangedTo(eFaderM, ((unsigned char*)(us428ctls_sharedmem->CtlSnapShot + us428ctls_sharedmem->CtlSnapShotLast))[eFaderM]); + + // Reset the LEDs to the state known by us428control + LightSend(); } int Cus428State::LightSend() { @@ -349,9 +352,13 @@ while( index < 4 && (1 << index) != Light[0].Value) index++; if (index >= 4) return; - Volume[index].PanTo(Diff, us428_ctls->Knob(eK_SET)); + + // The pan encoder has 24 detents. A multiple of 13 allows + // the pan to go from full-left to full-right in 20 clicks + // instead of 255 clicks (over 10 full turns!). + Volume[index].PanTo(Diff * 13, us428_ctls->Knob(eK_SET)); if (!LightIs(eL_Mute0 + index)) SendVolume(Volume[index]); return; } diff -u4 alsa-tools-1.0.14rc3/us428control/us428control.cc alsa-tools-1.0.14rc3-new/us428control/us428control.cc --- alsa-tools-1.0.14rc3/us428control/us428control.cc 2007-02-26 02:24:15.000000000 -0700 +++ alsa-tools-1.0.14rc3-new/us428control/us428control.cc 2007-09-07 15:19:39.000000000 -0600 @@ -43,8 +43,10 @@ #define SND_CARDS 8 int verbose = 1; +int positive_gain = 0; + Cus428Midi Midi; static void error(const char *fmt, ...) @@ -62,10 +64,11 @@ static void usage(void) { printf("Tascam US-428 Control\n"); printf("version %s\n", VERSION); - printf("usage: "PROGNAME" [-v verbosity_level 0..2] [-c card] [-D device] [-u usb-device] [-m mode]\n"); + printf("usage: "PROGNAME" [-v verbosity_level 0..3] [-c card] [-D device] [-u usb-device] [-m mode] [-g]\n"); printf("mode is one of (us224, us428, mixxx)\n"); + printf("The -g option allows the Input Monitor and Master gains to go above 0dB\n"); } /* * check the name id of the given hwdep handle */ @@ -170,9 +173,9 @@ char *device_name = NULL, *usb_device_name = getenv("DEVICE"); char name[64]; - while ((c = getopt(argc, argv, "c:D:u:v:m:")) != -1) { + while ((c = getopt(argc, argv, "c:D:u:v:m:g")) != -1) { switch (c) { case 'c': card = atoi(optarg); break; @@ -194,8 +197,12 @@ else if (!strcmp(optarg, "mixxx")) mode = 1; break; + case 'g': + // Allow positive gain on sliders (which may result in clipping) + positive_gain = 1; + break; default: usage(); return 1; } diff -u4 alsa-tools-1.0.14rc3/us428control/usbus428ctldefs.h alsa-tools-1.0.14rc3-new/us428control/usbus428ctldefs.h --- alsa-tools-1.0.14rc3/us428control/usbus428ctldefs.h 2007-02-26 02:24:15.000000000 -0700 +++ alsa-tools-1.0.14rc3-new/us428control/usbus428ctldefs.h 2007-09-07 15:16:36.000000000 -0600 @@ -2,8 +2,10 @@ /* * * Copyright (c) 2003 by Karsten Wiese <annabellesgarden@xxxxxxxx> * + * Logarithmic slider code (c) 2007 by Mike Bourgeous <nitrogen@xxxxxxxxxxxxxxxxxxxxx> + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. @@ -19,9 +21,12 @@ */ #ifdef __cplusplus #include <string.h> +#include <math.h> +#include <stdlib.h> extern int verbose; +extern int positive_gain; #endif enum E_In84 { eFader0 = 0, @@ -98,26 +103,94 @@ } int Scale(){return 0x40;} void calculate() { - int lPan = (int)Pan * Slider / 0x80; - int ValL = (Slider - lPan) * Scale(); - LH = ValL >> 8; - LL = ValL; - int ValR = (Slider + lPan) * Scale(); - RH = ValR >> 8; - RL = ValR; + int Val; + int ScaledL, ScaledR; + float PanLeft, PanRight; + float Norm; + float dBL, dBR; + + // Subtract 1 because the sliders usually don't reach 0 due to sampling inaccuracy + Val = (Slider - 1); + + if(Val < 0) { + Val = 0; + } + + // This is a balance knob-style pan law + PanLeft = (float)(Pan + 127) / 127.0; + PanRight = 2.0 - PanLeft; + + if(PanLeft < 0.0) { + PanLeft = 0.0; + } + if(PanLeft > 1.0) { + PanLeft = 1.0; + } + if(PanRight < 0.0) { + PanRight = 0.0; + } + if(PanRight > 1.0) { + PanRight = 1.0; + } + + Norm = (float)Val / 254.0; + + if(positive_gain) { + // -55dB to +12dB + dBL = 67.0 * (Norm - 1.0) + 12.0; + dBR = 67.0 * (Norm - 1.0) + 12.0; + } else { + // -55dB to 0dB + dBL = 55.0 * (Norm - 1.0); + dBR = 55.0 * (Norm - 1.0); + } + + // 16384 == 0dB (unity) gain + ScaledL = 16384.0 * pow(10.0, dBL / 20.0) * PanLeft; + ScaledR = 16384.0 * pow(10.0, dBR / 20.0) * PanRight; + + // Make sure the sound stops completely when the slider is at the bottom + if(ScaledL < 30) { + ScaledL = 0; + } + if(ScaledR < 30) { + ScaledR = 0; + } + + // Prevent overflow of the 16-bit gain value + if(positive_gain) { + if(ScaledL > 65535) { + ScaledL = 65535; + } + if(ScaledR > 65535) { + ScaledR = 65535; + } + } else { + if(ScaledL > 16384) { + ScaledL = 16384; + } + if(ScaledR > 16384) { + ScaledR = 16384; + } + } + + LH = ScaledL >> 8; + LL = ScaledL; + RH = ScaledR >> 8; + RL = ScaledR; if (2 < verbose) - printf("S=% 3i, P=% 3i, lP=% 3i, VL=%05i, VR=%05i\n", (int)Slider, (int)Pan, (int)lPan, ValL, ValR); + printf("Slider=% 3i, Pan=% 4i, Val=% 3i, dBL=% 6.2f, dBR=% 6.2f, ScaledL=%05i, ScaledR=%05i\n", (int)Slider, (int)Pan, Val, dBL, dBR, ScaledL, ScaledR); } void SetTo(unsigned char _Channel, int RawValue){ Slider = RawValue; Channel = eFaderM == _Channel ? 4 : _Channel; calculate(); } void PanTo(int RawValue, bool Grob) { - int NewPan; + int NewPan = 0; if (Grob) { static int GrobVals[] = {-128, -64, 0, 64, 127}; int i = 4; while (i >= 0 && GrobVals[i] > Pan) @@ -134,10 +207,24 @@ } else { NewPan = Pan + RawValue; } + + // Since the step is now 13, make sure 0 can still be reached + if (abs(NewPan) < 7) { + NewPan = 0; + } + + // If we went past the limit, but we weren't at the limit, clamp to the limit + if (NewPan < -128 && Pan > -128) + NewPan = -128; + else if (NewPan > 127 && Pan < 127) + NewPan = 127; + + // If we were already at the limit, then clamping didn't occur above, so ignore the new value if (NewPan < -128 || NewPan > 127) return; + Pan = NewPan; calculate(); } #endif
_______________________________________________ Alsa-devel mailing list Alsa-devel@xxxxxxxxxxxxxxxx http://mailman.alsa-project.org/mailman/listinfo/alsa-devel