ALSA LADSPA Plugin Chain For FM Transmission
I found a great tool for enhancing audio for FM transmission and adding RDS text to the signal, Stereo Tool. It's free to use the basic features but it costs $600+ to unlock all of the FM-related features if you want to use them. In the free version they have a beep tone that goes off every few seconds when you are using unlicensed features.
Turns out that it is possible to do similar enhancements using the LADSPA plugins in ALSA. As an example, here's the /etc/alsa/conf.d/50-radio.conf that I use with my radio station Linux server, a Raspberry Pi using a high-quality USB digital/analog converter (think "sound card"). The DAC is the hw:1,0 device in ALSA so my config uses that as the default device and the target of the "ladspa" pcm definition.
With this config you would direct output to the "radio" device to use the LAPDSPA plugin chain, .i.e., "aplay -D radio some.wav"
/etc/alsa/conf.d/50-radio.conf:
# This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at https://mozilla.org/MPL/2.0/. # Make USB DAC the default device pcm.!default { type hw card 1 } ctl.!default { type hw card 1 } # Use libavcodec as the default sample rate converter # Source package = alsa-plugins-freeworld-lavcrate on RPMFusion # The following converter types are available: # - lavcrate_higher Use length=64 # - lavcrate_high Use length=32 # - lavcrate Use length=16 # - lavcrate_fast Use length=8 # - lavcrate_faster Use length=4 # Linear interpolation and cutoff values are automatically used depending on # the supplied parameters and whether the plugin is used to upsample or downsample. defaults.pcm.rate_converter "lavcrate_high" # LADSPA plugin chain for radio station processing pcm.radio { type plug slave.pcm "ladspa" hint { show on description "in -> expander -> equal -> compressor -> limiter -> out" } } # LADSPA plugins: # Install Debian (apt) packages: # libasound2-plugins libasound2-plugin-equal libasound-plugin-smixer swh-plugins tap-plugins # ladspalist ladspa-sdk # Install Fedora (dnf) packages: # ladspa ladspa-caps-plugins ladspa-swh-plugins ladspa-tap-plugins # "listplugins" to see the list of installed plugins # "analyseplugin <filename>" to see plugin controls # Use "ardour" to test plugin settings pcm.ladspa { type ladspa slave.pcm "plughw:1,0" path "/usr/lib/ladspa" plugins { 0 { # Expander - remove low-level noise/hiss label se4 input { # RMS/peak, 0 to 1, default 0 # Attack time (ms), 1.5 to 400, default 101.125 # Release time (ms), 2 to 800, default 401 # Threshold level (dB), -30 to 0, default 0 # Ratio (1:n), 1 to 20, default 1 # Knee radius (dB), 1 to 10, default 3.25 # Attenuation (dB), -24 to 0, default 0 controls [ 1 101.125 401 -26 10 3.25 0 ] } } 1 { # Equalizer - FM curve (approx, should cut at 19kHz, not 16) # FM Pre-emphasis = +15dB @ 15kHz # So, do the math, -30 + 15 = -15kHz @ 15 kHz label Eq10X2 input { # 31 Hz, -48 to 24, default 0 # 63 Hz, -48 to 24, default 0 # 125 Hz, -48 to 24, default 0 # 250 Hz, -48 to 24, default 0 # 500 Hz, -48 to 24, default 0 # 1 kHz, -48 to 24, default 0 # 2 kHz, -48 to 24, default 0 # 4 kHz, -48 to 24, default 0 # 8 kHz, -48 to 24, default 0 # 16 kHz, -48 to 24, default 0 #controls [ -30 0 0 0 0 0 0 0 0 -15 ] # ---------------------------------------------------- # Never mind all that, set to what sounds good to me controls [ 3 2 1 0 0 0 0 1 2 3 ] } } 2 { # Compressor label sc4 input { # RMS/peak, 0 to 1, default 0 # Attack time (ms), 1.5 to 400, default 101.125 # Release time (ms), 2 to 800, default 401 # Threshold level (dB), -30 to 0, default 0 # Ratio (1:n), 1 to 20, default 1 # Knee radius (dB), 1 to 10, default 3.25 # Makeup gain (dB), 0 to 24, default 0 controls [ 0.9 101.125 401 -10 2 3.25 0 ] } } 3 { # Limiter label fastLookaheadLimiter input { # Input gain (dB), -20 to 20, default 0 # Limit (dB), -20 to 0, default 0 # Release time (s), 0.01 to 2, default 0.5075 controls [ 10 0 0.8 ] } } } }