#
# vim:sw=4 ts=8:et sta:ft=unknown:textwidth=78
#
Note: This draft represent what will go into manual pages, and hopefully
handbook.
Summary:
+--------------------------------------------+
| 1) Volume Per Channel (VPC) |
| 2) New, High Quality Sample Rate Converter |
| 3) Parametric Software Equalizer |
| 4) Transparent / Adaptive Virtual Channel |
| 5) Bitperfect |
| 6) Exclusive Access |
| 7) Multichannel 'Matrix' Processing |
| 8) NULL Driver |
| 9) Others.. |
+--------------------------------------------+
1) Volume Per Channel (VPC)
------------------------
Default: enabled
Provides: Independent, individual volume control for each
application/channel/streams without touching master
"pcm" volume.
Related ioctls():
SNDCTL_DSP_GETPLAYVOL, SNDCTL_DSP_SETPLAYVOL,
SNDCTL_DSP_GETRECVOL, SNDCTL_DSP_SETRECVOL,
SOUND_MIXER_PCM (compat mode)
Hints/systcls:
hint.pcm.X.vpc (default=undefined, enabled)
0=disable, 1=enable
Notes: The only place to enable/disable vpc.
Enabling/Disabling requires driver reload.
hw.snd.vpc_reset (default=0)
1=reset all channels back to 0 dB
Notes: This switch provides central control to 'restore' all
channels volume back to 0dB.
hw.snd.vpc_0db (default=45)
default 0 dB relative level
Notes: Default value for pcm volume. Increasing it will give
more room for attenuation control, while decreasing it
will give more room for amplification at the cost of
possible sound clipping.
hw.snd.vpc_autoreset (default=1, enabled)
0=disable, 1=enable
Notes: By default, channel volume will be reset to 0db
relative after the channel is closed which means that any
changes will be lost and not preserved. Setting this to '0'
will preserve the volume at the cost of possible confusion
for other applications trying to re-open the same
device (see hw.snd.vpc_reset for possible 'panic' switch to
fix the volumes).
hw.snd.vpc_mixer_bypass (default=1, enabled)
0=disable, 1=enable
Notes: The recommended way to use the VPC feature is
to teach/change applications using the proper ioctl():
SNDCTL_DSP_GETPLAYVOL, SNDCTL_DSP_SETPLAYVOL,
SNDCTL_DSP_GETRECVOL, SNDCTL_DSP_SETRECVOL.
However, these ioctls() are rather new and not quite
popular yet. By enabling 'mixer bypass' mode, existing
applications (mplayer, xmms, etc) can use their own
existing mixer logic to control their own opened channel
volume.
OSSv4 Compatibility:
Mostly, but we did it a 'better' way, like providing a special
bypass mode for legacy applications.
2) New, High Quality Sample Rate Converter
---------------------------------------
(Codename: feeder_rate, zresampler, z, The Z zsrc, whatever)
(sample-rate-converte abbreviated as 'src')
(SINC = Sine Cardinal)
Default: Compile time enabled, runtime disabled
Provides: High quality, production quality, scalable, tunable
sample-rate-converter (and fast too).
Comparisons: http://people.freebsd.org/~ariff/z_comparison/
(require browser with javascript for interactive comparison).
Hints/sysctls:
hw.snd.feeder_rate_quality (default=1, Linear Interpolation)
(0 - 4)
Notes: 0 = Zero Order Hold (ZOH), fastest, poorest quality. The
first ever src was created resembling this form by
Cameron Grant <cg@FreeBSD.org>
1 = Linear Interpolation, fast, quality subject to personal
preferences or usage but technically the quality is
poor due to lack of anti-aliasing filter. First
materialized by Orion Hodson <orion@FreeBSD.org>, but
limited to 16bit samples and 48KHz at most. Later
rewritten by Ariff Abdullah <ariff@FreeBSD.org> to
support other than 16bit and a wider frequency range.
>= 2 Bandlimited SINC Interpolator, technically based on
Julius O'Smith's Digital Audio Resampling -
http://ccrma.stanford.edu/~jos/resample/ .
This implementation takes us one step further by
implementing Polyphase banking to boost the conversion
speed (at the cost of memory usage) with multiple
high-quality polynomial interpolators
(Olli Niemitalo
http://www.student.oulu.fi/~oniemita/dsp/deip.pdf)
to raise the bar of conversion accuracy. It is 100%
fixed point, 64bit accumulator with 32bit coefficients
and high precision sample buffering.
Default quality value is mapped sequentially as:
2 = 100dB stopband, 8 taps, 85% bandwidth
3 = 100dB stopband, 36 taps, 90% bandwidth
4 = 100dB stopband, 164 taps, 97% bandwidth
hw.snd.feeder_rate_polyphase_max (default=183040)
Notes: Applicable for SINC interpolator.
SINC interpolator works in 2 modes:
1) Ordinary coefficients calculation during conversion,
slower, but highly economical in terms of memory
consumption.
2) High Speed Polyphase Banking (default), fast, but
require amounts of memory to store all coefficients for
all possible phases before the conversion process.
Conversion quality is also higher than #1 due to the
usage of complex polynomial interpolators which results
in better coefficients.
This will set the maximum polyphases entries allowable
during the process of building resampling filters. Setting
this to 0 will disable polyphase resampling and revert to
ordinary SINC #1.
hw.snd.feeder_rate_presets (strings, read-only)
Notes: Show the compiled in FEEDER_RATE_PRESETS (note below).
FEEDER_RATE_PRESETS
The default rate presets are "100:8:0.85 100:36:0.90 100:164:0.97",
which is a compile time tunable by defining FEEDER_RATE_PRESETS in
/etc/make.conf. In its simplest form, defining
FEEDER_RATE_PRESETS="8 16 32 64 128"
will create a resampler that will be filtered through 8, 16, 32, 64 or
128 taps filter.
Acceptable form:
* "8 16 ..." simplest form, define taps per-filter.
* "100:32 ..." stopband-attenuation:taps.
* "100:32:0.95 .." stopband-attenuation:taps:rolloff/bandwidth.
Caution: defining too many presets, or a preset with large taps will
bloat the kernel!
OSSv4 Compatibility:
Not relevant. The infrastructure of this src is far, far better
than 4front OSS.
3) Parametric Software Equalizer (feeder_eq)
-----------------------------
Default: disabled
Provides: Compile time, Parametric Equalizer through 'bass' and 'treble'
controls.
This feature gives 'tone' controls for any pcm streams, either
for ear-candy or frequency compensation due to variability of
hardware/speakers/headsets/phones quality or frequency response.
Hints/systcls:
hint.pcm.X.eq (default=undefined, disabled)
0=disable, 1=enable
Notes: The only place to enable/disable eq.
Enabling/Disabling requires driver reload. Enabling will
make 'bass' and 'treble' controls appear in mixer
applications.
dev.pcm.X.eq (default=1, enabled)
0=disable, 1=enable, 2=bypass
Notes: Once the EQ is enabled, use this sysctl to switch its
modes:
0=disable - Soft disable the adjustment of the EQ value.
Everything is 0dB but the streams will still go
through the filter for possible eq_preamp
adjustments.
1=enable - Enable EQ adjustements.
2=bypass - Entirely bypass the EQ filter (as in disabling
it). This is different than '0' since this
value will be a 'hard' disable, and totally
bypass even the eq_preamp processing.
dev.pcm.X.eq_preamp (default=+0.0dB)
(-min dB <-> +max dB, depending on presets)
Notes: feeder_eq is a passive filter, which means that the gain
and attenuation are illusions from the listener
perspective. Enabling EQ with a -9dB <-> +9dB range means
that first the entire stream will be attenuated to -9dB
(minus +max dB) and further gain is a process relative to
that 0dB point. This will somehow create a lower volume
from the listeners perspective. To accomodate that, this
sysctl is present to give a slight 'compensation' for such
a situation, at the cost of possible sound clipping if
applied excessively.
hw.snd.feeder_eq_exact_rate (default=0, disable)
Notes: Technically only certain rates are allowable for proper and
precise processing (see below, on 'Supported Rates'). This
switch will toggle the rigidness of such requirements and
even allow sloppy processing for unsupported rates, which
is why the default setting is '0' (allow sloppy).
hw.snd.feeder_eq_presets (strings, read-only)
Notes: Show the compiled in FEEDER_EQ_PRESETS (note below).
FEEDER_EQ_PRESETS
The default rate presets is
"PEQ:16000,0.2500,62,0.2500:-9,9,1.0:44100,48000,88200,96000,176400,192000"
which is a compile time tunable by defining FEEDER_EQ_PRESETS in
/etc/make.conf. The 4 main fields (separated by double colons) and
subfields separated by commas:
1) EQ Type:
PEQ - Peaking EQ -or-
SHELF - Shelving EQ
Default: 'PEQ'
2) Tone Parameters:
Divided by 4 subfields:
Treble Corner Frequency (in Hz),
Treble Q (peaking EQ) or S (Shelving) parameter,
Bass Corner Frequency (in Hz),
Bass Q (peaking EQ) or S (Shelving) parameter
Default: '16000,0.2500,62,0.2500'
3) Gain Range/Step:
Divided by 3 subfields:
Minimum attenuation (dB),
Maximum gain (dB),
Step level for attenuation/gain
Default: '-9,9,1.0'
4) Supported Rates:
Define as many supported rates as possible, separated by commas.
Default: '44100,48000,88200,96000,176400,192000'
Caution: defining too many rates may bloat the kernel!
This setting will dictate what rate is suitable for processing if
hw.snd.feeder_eq_exact=1 and reject all other rates that was not
part of this list.
Further readings on EQ type, Q or S:
"Cookbook formulae for audio EQ biquad filter coefficients"
by Robert Bristow-Johnson <rbj@audioimagination.com>
- http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
OSSv4 Compatibility:
Not relevant. The infrastructure of this eq is far, far better
than 4front OSS.
4) Transparent / Adaptive Virtual Channel
--------------------------------------
Default: Enabled for hardware channel which support digital format (ac3),
disabled for others.
Provides: Transparent digital passthrough and adaptive/dynamic format/rate
channel mixing.
With this feature, disabling vchans are no longer needed in
order to make digital format pass through. It also makes vchans
more dynamic by choosing a better format/rate among all the
concurrent streams, which means that
dev.pcm.X.[rec|play].vchan[format|rate] becomes sort of
optional.
Hints/sysctls:
dev.pcm.X.[play|rec].vchanmode (default=depends...)
'fixed' or '0':
The good old mode. Channel mixing is done using fixed
format/rate. Digital passthrough or other advanced operations
will not work in this mode (consider it as a 'legacy' mode).
For hardware channels that doesn't support digital formats, this
is the default mode.
'passthrough' or '1':
Channel mixing is done using fixed format/rate, but advanced
operations such as digital passthrough or 'Exclusive Access'
(#6 down below) will start working. All channels should
produce sound as usual until there is a request for a digital
format playback, which in this case will 'mute' other channels
and let the latest incoming digital format pass through
undisturbed. Multiple / concurrent digital streams are
supported, but the LATEST stream will take precedence and
mute all other streams.
'adaptive' or '2':
Advanced mode. Works like much like'passthrough' mode, but is
a bit smarter, especially for multiple pcm channels with
different format/rate. Whenever a new channel is about to start,
it will scan the entire list of virtual channels and decide which
format/rate is the best (mostly, the higher/bigger). This will
ensure that the quality of mixing depends on the best of all
channels. The (bad) side effect of this mode is that the
hardware DMA needs to be restarted and might cause annoying
pops/clicks, but for a long running playback, this issue
might be acceptable. Any changes for current format/rate can
be seen through the output of sysctl
dev.pcm.[play|rev].vchan[format|rate].
OSSv4 Compatibility:
4front OSS incapable of doing this magic.
5) Bitperfect
----------
Default: disabled
Provides: Pristine, pure pcm stream directly to your 'hardware'. In this
mode the channel will avoid/skip all kinds of dsp processing
(channel matrixing, rate converter, eq, etc)
Related ioctls():
SNDCTL_DSP_COOKMODE (0=enable bitperfect, 1=disable bitperfect)
Notes: The 'soft' way of enabling/disabling bitperfect mode,
per-application.
Hints/sysctls:
dev.pcm.X.bitperfect (default=0)
(0=disable, 1=enable)
Notes: This sysctl provides the 'hard' way of enabling bitperfect.
Caveats/Notes:
* 'hardware' in this sense is kind of relative. If vchans are enabled,
the bitperfectness will consider default vchan format/rate as the
definitive format/rate target. The true, recommended way to enable
pure bitperfect is to disable vchans and use dev.pcm.X.bitperfect
-or- SNDCTL_DSP_COOKEDMODE instead.
* Enabling bitperfect either way (sysctl or ioctl()) will cause funny
results in vchan+'adaptive' mode.
OSSv4 Compatibility:
SNDCTL_DSP_COOKEDMODE is mostly compatible, except that it will handle
complex situation with vchans enabled 'better' compared to 4front OSS.
6) Exclusive Access
----------------
Default: Disabled, applicable only together with vchans with vchanmode
'passthrough' and above.
Provides: This feature provides the same effect of vchan 'passthrough'
mode (muting all other streams/channels), but works with any type
of pcm stream as long as the application uses open() with
O_EXCL mode. Consider it as a some sort of 'urgent' notification
for applications that requires it, maybe or maybe not.
How:
open("/dev/dsp", O_<insert your typical open mode> | O_EXCL);
OSSv4 Compatibility:
This feature is mostly compatible with OSSv4, except that 4front OSS
prevents all other applications from running (stalled/halted, other
unknown grave effects) if any sound device being accessed in a such
way. FreeBSD does this smartly on top of the Transparent / Adaptive
Virtual Channel.
7) Multichannel 'Matrix' Processing
--------------------------------
Default: Enabled
Provides: The core component for multi channel matrixing, seamless
any-to-any channel conversion and routing.
This matrix processor supports processing up to 18 channels
interleaved, but currently limits itself to just 8 channels
(known as 7.1) as a maximum (intentionally). It can handle
reduction, expansion or re-routing channels depending on
internally defined complex matrix mapping. It provides a base
interface for related multichannel ioctls. It also works with or
without vchans.
Notes: Implementation on specific hardware drivers not yet
completed, but trivial. Example of possible matrix usages
is currently implemented in snd_uaudio(4) to handle
quirky swapped channels.
Related ioctls():
SNDCTL_DSP_GET_CHNORDER:
get channel interleaving order.
SNDCTL_DSP_SET_CHNORDER:
set channel interleaving order.
SNDCTL_DSP_GETCHANNELMASK (kind of 'obsolete', but who cares?)
vlc uses this to detect possible multichannel capability.
Hints/sysctls:
hw.snd.report_soft_matrix (default=1, enabled)
Notes: This will allow seamless channel matrixing regardless of
supported hardware or not, which means that you can play
multichannel streams (mplayer -channel 6/8) even with
simple stereo soundcard.
dev.pcm.X.[play|rec].vchanformat: (default=s16le:2.0)
Notes: These sysctls have been extended to allow the following
notions:
1.0 = mono
2.0 = stereo
2.1 = 3 channels (left, right, LFE)
3.0 = 3 channels (left, right, rear center)
4.0 = 4 channels (Quadraphonic: front/rear left and right)
4.1 = 5 channels (4.0 + LFE)
5.0 = 5 channels (4.0 + center)
5.1 = 6 channels (4.0 + center + LFE)
6.0 = 6 channels (4.0 + front/rear center)
6.1 = 7 channels (6.0 + LFE)
7.1 = 8 channels (4.0 + center + LFE + side left and right)
OSSv4 Compatibility:
Good enough, though 4front claims that their implementation of
CHNORDER is sort of incomplete and subject to more butchering.
8) NULL Driver XXX (underway)
Default: Not enabled, but buildable on i386 and amd64 as part of modules
compilation.
Provides: Loopback driver.
9) Others.. XXX
* most feeder_* stuffs are compilable in userland. Let's not speculate
whether we should go all out for it (save that for FreeBSD 12.0-RELEASE)
* kobj signature fixups Andriy Gapon <avg@freebsd.org>
* pull out channel mixing logic out of vchan.c and create its own
feeder_mixer
* various refactoring here and there.
* opt_snd.h for possible compile time configuration:
(mostly for debugging purposes)
SND_DEBUG
SND_DIAGNOSTIC
SND_FEEDER_MULTIFORMAT
SND_FEEDER_FULL_MULTIFORMAT
SND_FEEDER_RATE_HP
SND_PCM_64
SND_OLDSTEREO