octal-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Octal-dev] Standardized Log Volume Controls


From: Neil Nelson
Subject: [Octal-dev] Standardized Log Volume Controls
Date: Sun, 25 Jun 2000 12:18:39 -0700

It appears that it is fairly common to use linear volume controls
as just done in my soxflanger.c taken from the SoX code.  However,
volume controls are traditionally logarithmic.  It may be desirable
to give a standard volume control method so that the eventual GUI
controls behave the same and according to the usual analog method.

A different apparent volume response will be heard in the same
volume control according to different playing environments result-
ing from the available dynamic range that on the bottom is the
background noise (competing volume from other sources) and on
the top is the maximum volume the ear can reasonably (without pain)
hear.  I.e., in a quiet environment, as would be found in an orchestra
auditorium, the dynamic range is approximately 60 db (amplitude/volume
doubles each 3 db); whereas in a noisy dance-club environment the
dynamic range may easily go below 10 db.  A volume control providing
the volume variations effective in the first (orchestra) environment
will seem unresponsive except for the last (highest) one-sixth of
volume control range because the volume output from the lower five-
sixths of the control will be masked by the background noise.

If we provide a global dynamic range variable, then it will be
easy to adjust all volume controls simultaneously to the available
dynamic range of the environment.  E.g.:

Add master dynamic range control variables to (?) engine.h under

  struct _engine {
     double  mdyn_range;    // Use double if variable will be used with
exp().
     double  mdyn_unit;     // Scaling factor for unit (maximum) volume.

     double  mdyn_exp_frct; // Fractional exponent value used to compute
volume.

Set the master dynamic range control on a system/master parameter
screen and then update the above engine variables.

/* make `e' the engine pointer, `gui' the param pointer from
   the master control screen. */

   e->mdyn_range    = (double)gui->params[ix_dynamic_range] / 255.0 *
60.0;
   e->mdyn_unit     = exp(e->mdyn_range / 3.0) - 1.0;
   e->mdyn_exp_frct = (e->mdyn_range  / 3.0) / 255.0;

In the machine or effects program, use the following to obtain the
multiplication factor from the 1 byte volume control parameter.

   temp = m->params[0][ix_gain_out];
   s->out_gain = ((float)exp((double)temp * e->mdyn_exp_frct) - 1.0)
                / e->mdyn_unit;

Previously, as now in soxflanger.c, s->out_gain would have been computed
as
(temp / 255.0) and then multiplied by the output (resulting) samples to
obtain
the volume change.  But, the code above makes the 1 byte param number a
log
volume control.

This approach I just put together this morning, and other contributors
will
likely have a commonly used software method that would be good see and
may
be preferred over this ad-hoc suggestion.  (Additionally, a standard exp
table
in a common header file may be faster than using the math.h exp.)

Neil Nelson




reply via email to

[Prev in Thread] Current Thread [Next in Thread]