; ********************************************************************
|
; OM-SoX, (c) 2011-2013 Marlon Schumacher (CIRMMT/McGill University) *
|
; http://sourceforge.net/projects/omsox/ *
|
; *
|
; Multichannel Audio Manipulation and Functional Batch Processing. *
|
; DSP based on SoX - (c) C.Bagwell and Contributors *
|
; http://sox.sourceforge.net/ *
|
; ********************************************************************
|
;
|
;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.
|
;
|
;See file LICENSE for further informations on licensing terms.
|
;
|
;This program is distributed in the hope that it will be useful,
|
;but WITHOUT ANY WARRANTY; without even the implied warranty of
|
;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
;GNU General Public License for more details.
|
;
|
;You should have received a copy of the GNU General Public License
|
;along with this program; if not, write to the Free Software
|
;Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,10 USA.
|
;
|
;Authors: M. Schumacher
|
|
(in-package :om)
|
|
;;; Sox-contrast ===============================================
|
|
(defmethod! sox-contrast ((amount number) &key sox-append)
|
:icon 30
|
:initvals '(50 nil)
|
:indoc (list "amount (percent)" *sox-append-doc*)
|
:doc "Comparable to compression sox-contrast makes an audio signal sound louder (using a time-domain transferfunction).
|
|
<amount> controls the amount of the effect (0-100%). Note that an amount of 0 still gives a significant contrast enhancement."
|
|
(let* ((thestring (format nil "contrast ~d" amount)))
|
(sox-concat sox-append thestring))
|
)
|
|
|
;;; Sox-loudness ===============================================
|
|
(defmethod! sox-loudness ((gain number) &key reference sox-append)
|
:icon 30
|
:initvals '(-10 nil)
|
:indoc (list "gain (in dB)" "reference-gain" *sox-append-doc*)
|
:doc "Loudness control - similar to sox-level, but provides equalisation for the human auditory system.
|
|
The gain is adjusted by the value for <gain> (usually negative) and the signal equalised according to ISO 226 w.r.t. a reference level of 65dB.
|
An alternative reference level <reference> may be given if the original audio has been equalised for some other optimal level."
|
|
(let* ((thestring (format nil " loudness ~d" gain)))
|
(when reference
|
(setf thestring (concatenate 'string thestring
|
(format nil " ~d" reference))))
|
(sox-concat sox-append thestring))
|
)
|
|
;;; sox-amplitude ===========================================
|
|
(defmethod! sox-amplitude ((amplitude number) &key sox-append)
|
:icon 30
|
:initvals '(1)
|
:indoc (list "amplitude factor (linear)" *sox-append-doc*)
|
:doc "Scales the amplitude of the audio by a factor given in <amplitude>.
|
|
NB: Negative values for <amplitude> are possible. This results in phase-inversion of the audio."
|
|
(let* ((thestring (format nil "vol ~d" amplitude)))
|
(sox-concat sox-append thestring))
|
)
|
|
|
;;; sox-level ===============================================
|
|
(defmethod! sox-level ((gain number) &key options balance-mode sox-append)
|
:icon 30
|
:initvals '(0 nil nil nil)
|
:menuins '((1 (( "normalize" "normalize" ) ("limit" "limit") ("headroom" "headroom") ("reclaim" "reclaim"))) (2 (("peak" "peak") ("rms" "rms"))))
|
:indoc (list "gain (dB)" "options (applied before gain)" "balance channels in a multichannel-file using peak or rms detection" *sox-append-doc*)
|
:doc "Amplify, attenuate, limit, normalize audio to/by <gain>. Optionally 'balance' the gain levels of individual channels in multichannel audio.
|
|
<gain> specifies amplfication or attenuation in dB.
|
|
<options>:
|
'limit' will invoke a brickwall limiter, thus preventing the audio from clipping. NB: limiting more than a few dBs can cause audible distortion.
|
'normalize' will normalize the audio relative to 0dBFS; it is often used to normalize audio to a given level below 0dB.
|
'headroom' option is used to apply gain to provide head-room for subsequent processing.
|
'reclaim' option is used after a prior invocation of sox-level with 'headroom': if the headroom is not used by subsequent effects, it can be reclaimed with this option.
|
|
<balance-mode> specifies how the levels in different channels in multichannel audio are determined in order to change their relative levels.
|
NB: unlike 'peak' 'rms' might cause clipping in certain channels."
|
|
(let* ((thestring (format nil " gain")))
|
;(print balance-mode)
|
(cond ((equal balance-mode "peak")
|
(setf thestring (concatenate 'string thestring
|
(format nil " -e"))))
|
((equal balance-mode "rms")
|
(setf thestring (concatenate 'string thestring
|
(format nil " -b")))))
|
;(print options)
|
(cond ((equal options "normalize")
|
(setf thestring (concatenate 'string thestring
|
(format nil " -n"))))
|
((equal options "limit")
|
(setf thestring (concatenate 'string thestring
|
(format nil " -l"))))
|
((equal options "headroom")
|
(setf thestring (concatenate 'string thestring
|
(format nil " -h"))))
|
((equal options "reclaim")
|
(setf thestring (concatenate 'string thestring
|
(format nil " -r")))))
|
(setf thestring (concatenate 'string thestring
|
(format nil " ~d" gain)))
|
(sox-concat sox-append thestring))
|
)
|
|
|
|
;;; Sox-Normalize ===============================================
|
|
; this is included in sox-level
|
(defmethod! sox-normalize (&key (level 0.0) balance-mode sox-append)
|
:icon 30
|
:initvals '(0.0 nil nil )
|
:menuins '((1 (("peak" "peak") ("rms" "rms"))))
|
:indoc (list "level (dB)" "balance channels in a multichannel-file using peak or rms detection (select from menu)" *sox-append-doc*)
|
:doc "Normalize audio or -optionally- all of the individual channels in multichannel audio.
|
|
<level> specifies the value (in dBFS) to which to normalize.
|
Optionally 'balance' the individual channels in multichannel audio (i.e. normalize individually) using peak or rms detection."
|
|
(let* ((thestring (format nil " gain")))
|
(cond ((equal balance-mode "peak")
|
(setf thestring (concatenate 'string thestring
|
(format nil " -e"))))
|
((equal balance-mode "rms")
|
(setf thestring (concatenate 'string thestring
|
(format nil " -b")))))
|
(setf thestring (concatenate 'string thestring
|
(format nil " -n ~d" level)))
|
(sox-concat sox-append thestring))
|
)
|
|
|
|
; Sox-Overdrive ===============================================
|
|
(defmethod! sox-overdrive ((drive number) (colour number) &key sox-append)
|
:icon 30
|
:initvals '(20 20 nil)
|
:indoc (list "drive" "colour (amount of even harmonics)" *sox-append-doc*)
|
:doc "Apply non-linear distortion to the audio.
|
|
The colour parameter controls the amount of even harmonic content in the over-driven output."
|
|
(let* ((thestring (format nil " overdrive ~d ~d" drive colour)))
|
(sox-concat sox-append thestring))
|
)
|
|
|
;;; Sox-Compand ===============================================
|
|
(defmethod! sox-comp-format ((attack number) (release number) &key (softknee 6) (makeup-gain 0) transferfunction (minvolume -90) (lookahead 0.0))
|
(let* ((thestring (cond ((and softknee minvolume) (format nil "~d,~d ~d:~d," attack release softknee minvolume))
|
(softknee (format nil "~d,~d ~d:" attack release softknee))
|
(minvolume (format nil "~d,~d ~d" attack release minvolume))
|
(t (format nil "~d,~d " attack release))
|
)))
|
|
(if (bpf-p transferfunction)
|
(progn
|
(setf transferpoints (point-pairs transferfunction))
|
(setf firstpair (car transferpoints))
|
(setf thestring (concatenate 'string thestring
|
(format nil "~d,~d" (first firstpair) (second firstpair))))
|
(loop for points in (cdr transferpoints) do
|
(setf thestring (concatenate 'string thestring
|
(format nil ",~d,~d" (first points) (second points))))))
|
(setf thestring (concatenate 'string thestring (format nil "-70"))))
|
|
(setf thestring (concatenate 'string thestring
|
(format nil " ~d ~d ~d" (or makeup-gain 0) (or minvolume -90) (or lookahead 0.0))))
|
thestring))
|
|
|
|
(defmethod! sox-compand ((attack number) (release number) &key transferfunction (softknee 6) (makeup-gain -5) (minvolume -90) (lookahead 0.02) (sox-append))
|
:icon 30
|
:initvals '(0.3 0.8 nil 6 -5 -90 0.02 nil)
|
:indoc (list "attack-time (secs)" "release-time (secs)" "transferfunction describing changes from input to output levels over dynamic range of audio (bpf)" "softknee (in dB)" "makeup-gain (in dB)" "an initial level for when companding starts" "A delay in seconds. Allows the compander to effectively operate in a 'predictive' rather than a reactive mode" *sox-append-doc*)
|
:doc "Compand (compress and/or expand) the dynamic range of the audio.
|
|
<attack> and <release> determine the time over which the instantaneous level of the input signal is averaged to determine its volume; <attack> refers to increases in volume and <release> refers to decreases. For most situations, <attack> should be smaller than <release> because the human ear is more sensitive to sudden increases rather than decreases in audio levels. Typical values are 0.3,0.8 seconds.
|
|
<transferfunction> is a breakpoint function describing compression/expansion over the dynamic range of the input signal.
|
|
<softknee> will round the points at where adjacent line segments on the transfer function meet by the specified amount.
|
|
<makeup-gain> is an additional gain in dB to be applied at all points on the transfer function which allows easy adjustment of the overall gain.
|
|
<minvolume> permits the user to supply a nominal level initially, so that, for example, a very large gain is not applied to initial signal levels before the companding action has begun to operate: it is quite probable that in such an event, the output would be severely clipped while the compander gain properly adjusts itself.
|
|
<lookahead> is a delay in seconds. The input signal is analysed immediately to control the compander, but it is delayed before being fed to the volume adjuster. Specifying a delay approximately equal to the attack/release times allows the compander to effectively operate in a 'predictive' rather than a reactive mode."
|
(list "attack-time (secs)" "release-time (secs)" "transferfunction in dB relative to the maximum possible signal amplitude (bpf)" "softknee (in dB)." "makeup-gain (in dB)" "an initial level for when companding starts" "A delay in seconds. Allows the compander to effectively operate in a 'predictive' rather than a reactive mode" *sox-append-doc*)
|
;Where more than one pair of attack/decay parameters are specified, each input channel is companded separately and the number of pairs must agree with the number of input channels.
|
|
(setf thestring
|
(sox-comp-format attack release :softknee softknee :makeup-gain makeup-gain :transferfunction transferfunction
|
:minvolume minvolume :lookahead lookahead))
|
(setf thestring (string+ " compand " thestring))
|
(sox-concat sox-append thestring)
|
)
|
|
|
#|
|
;;; sox-compand needs a method for lists of attacks and releases (for multichannel)!
|
(defmethod! sox-compand ((attack number) (release number) &key (softknee 6) (makeup-gain -5) transferfunction (minvolume -90) (lookahead 0.3) (sox-append))
|
:icon 30
|
:initvals '(0.3 0.8 6 -5 nil -90 0.3 nil)
|
:indoc '("attack-time (secs)" "release-time (secs)" "softknee in dB" )
|
:doc "Compand (compress or expand) the dynamic range of the audio."
|
(let* (
|
(thestring (format nil "compand ~d,~d ~d:~d," attack release softknee minvolume)))
|
(if (bpf-p transferfunction)
|
(progn
|
(setf transferpoints (point-pairs transferfunction))
|
(setf firstpair (car transferpoints))
|
;(print firstpair)
|
(setf thestring (concatenate 'string thestring
|
(format nil "~d,~d" (first firstpair) (second firstpair))))
|
(loop for points in (cdr transferpoints) do
|
(setf thestring (concatenate 'string thestring
|
(format nil ",~d,~d" (first points) (second points))))))
|
(setf thestring (concatenate 'string thestring (format nil "-70" attack release softknee)))
|
)
|
(setf thestring (csoundfileoncatenate 'string thestring
|
(format nil " ~d ~d ~d" makeup-gain minvolume lookahead)))
|
(when sox-append
|
(setf thestring (concatenate 'string thestring
|
(format nil " ~a" sox-append))))
|
thestring))
|
|#
|
|
;;; Sox-MultiCompand ===========================================
|
|
(defmethod! sox-multi-compand ((attacks list) (releases list) (crossover-freqs list) &key transferfunction softknee makeup-gain minvolume lookahead sox-append)
|
:icon 30
|
:initvals '((0.005 0.003 0.000625 0.0001 0) (0.8 6 -5 -90 0.3) (100 400 1600 6400 nil) nil (3 3 3 3 3) (-12 -12 -12 -12 -12)
|
(-90 -90 -90 -90 -90) (0.3 0.3 0.3 0.3 0.3) nil)
|
:indoc (list "attack-time (secs)" "release-time (secs)" "crossover frequencies (Hz)" "transferfunction describing changes from input to output levels over dynamic range of audio (bpf)" "softknee (in dB)" "makeup-gain (in dB)" "an initial level for when companding starts" "A delay in seconds. Allows the compander to effectively operate in a 'predictive' rather than a reactive mode" *sox-append-doc*)
|
:doc "Compand (compress and/or expand) the dynamic range of the audio in individual frequency bands.
|
|
|
The multi-band compander (sox-multicompand) is similar to the single-band compander (sox-compand) but the audio is first divided into bands using Linkwitz-Riley cross-over filters and a separately specifiable compander run on each band.
|
See the sox-compand doc for the definition of its parameters.
|
"
|
|
(let* ((mystr "")
|
(mystrings
|
(loop for att in attacks
|
for rel in releases
|
counting att into counter
|
collect
|
(let ((count (1- counter)))
|
(format nil "~s" (sox-comp-format att rel :softknee (nth count softknee) :makeup-gain (nth count makeup-gain)
|
:transferfunction (nth count transferfunction) :minvolume (nth count minvolume) :lookahead (nth count lookahead)))
|
)))
|
(mylists (mat-trans (list mystrings crossover-freqs))))
|
|
(loop for item in mylists do
|
(print item)
|
(if (second item)
|
(setf mystr (concatenate 'string mystr (format nil "~a ~d " (first item) (second item))))
|
(setf mystr (concatenate 'string mystr (format nil "~a" (first item))))))
|
(sox-concat sox-append (format nil " mcompand ~a" mystr)))
|
)
|