Work-in-progress repo for ambisonics extensions for OM-SoX
Alexander Nguyen
22.01.25 92c40d00f8ffe4fc6491c0abb70210b31202bd70
commit | author | age
92c40d 1 ; ********************************************************************
AN 2 ; OM-SoX, (c) 2011-2013 Marlon Schumacher (CIRMMT/McGill University) *
3 ;           http://sourceforge.net/projects/omsox/                   *
4 ;                                                                    *
5 ;  Multichannel Audio Manipulation and Functional Batch Processing.  *
6 ;       DSP based on SoX - (c) C.Bagwell and Contributors            *
7 ;               http://sox.sourceforge.net/                          *
8 ; ********************************************************************
9 ;
10 ;This program is free software; you can redistribute it and/or
11 ;modify it under the terms of the GNU General Public License
12 ;as published by the Free Software Foundation; either version 2
13 ;of the License, or (at your option) any later version.
14 ;
15 ;See file LICENSE for further informations on licensing terms.
16 ;
17 ;This program is distributed in the hope that it will be useful,
18 ;but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 ;GNU General Public License for more details.
21 ;
22 ;You should have received a copy of the GNU General Public License
23 ;along with this program; if not, write to the Free Software
24 ;Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,10 USA.
25 ;
26 ;Authors: M. Schumacher
27
28 (in-package :om)
29
30 ;;; Sox-contrast ===============================================
31
32 (defmethod! sox-contrast ((amount number) &key sox-append)
33   :icon 30
34   :initvals '(50 nil)
35   :indoc (list "amount (percent)" *sox-append-doc*)
36   :doc "Comparable to compression sox-contrast makes an audio signal sound louder (using a time-domain transferfunction). 
37
38 <amount> controls the amount of the effect (0-100%). Note that an amount of 0 still gives a significant contrast enhancement."
39
40   (let* ((thestring (format nil "contrast ~d" amount)))
41     (sox-concat sox-append thestring))
42   )
43
44
45 ;;; Sox-loudness ===============================================
46
47 (defmethod! sox-loudness ((gain number) &key reference sox-append)
48   :icon 30
49   :initvals '(-10 nil)
50   :indoc (list "gain (in dB)" "reference-gain" *sox-append-doc*)
51   :doc "Loudness control - similar to sox-level, but provides equalisation for the human auditory system.
52
53 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.
54 An alternative reference level <reference> may be given if the original audio has been equalised for some other optimal level."
55
56   (let* ((thestring (format nil " loudness ~d" gain)))
57     (when reference
58       (setf thestring (concatenate 'string thestring 
59                                    (format nil " ~d" reference))))
60     (sox-concat sox-append thestring))
61   )
62
63 ;;; sox-amplitude ===========================================
64
65 (defmethod! sox-amplitude ((amplitude number) &key sox-append)
66             :icon 30
67             :initvals '(1)
68             :indoc (list "amplitude factor (linear)" *sox-append-doc*)
69             :doc "Scales the amplitude of the audio by a factor given in <amplitude>.
70
71 NB: Negative values for <amplitude> are possible. This results in phase-inversion of the audio."
72
73             (let* ((thestring (format nil "vol ~d" amplitude)))
74               (sox-concat sox-append thestring))
75             )
76
77
78 ;;; sox-level ===============================================
79
80 (defmethod! sox-level ((gain number) &key options balance-mode sox-append)
81   :icon 30
82   :initvals '(0 nil nil nil)
83   :menuins '((1 (( "normalize" "normalize" ) ("limit" "limit") ("headroom" "headroom") ("reclaim" "reclaim"))) (2 (("peak" "peak") ("rms" "rms")))) 
84   :indoc (list "gain (dB)" "options (applied before gain)" "balance channels in a multichannel-file using peak or rms detection" *sox-append-doc*)
85   :doc "Amplify, attenuate, limit, normalize audio to/by <gain>. Optionally 'balance' the gain levels of individual channels in multichannel audio. 
86
87 <gain> specifies amplfication or attenuation in dB.
88
89 <options>: 
90 'limit' will invoke a brickwall limiter, thus preventing the audio from clipping. NB: limiting more than a few dBs can cause audible distortion.
91 'normalize' will normalize the audio relative to 0dBFS; it is often used to normalize audio to a given level below 0dB.
92 'headroom' option is used to apply gain to provide head-room for subsequent processing.
93 '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.
94
95 <balance-mode> specifies how the levels in different channels in multichannel audio are determined in order to change their relative levels.
96 NB: unlike 'peak' 'rms' might cause clipping in certain channels."
97
98   (let* ((thestring (format nil " gain")))
99     ;(print balance-mode)
100     (cond ((equal balance-mode "peak")     
101            (setf thestring (concatenate 'string thestring 
102                                      (format nil " -e"))))
103           ((equal balance-mode "rms") 
104            (setf thestring (concatenate 'string thestring 
105                                      (format nil " -b")))))
106     ;(print options)
107     (cond ((equal options "normalize")     
108            (setf thestring (concatenate 'string thestring 
109                                      (format nil " -n"))))
110           ((equal options "limit") 
111            (setf thestring (concatenate 'string thestring 
112                                      (format nil " -l"))))
113           ((equal options "headroom") 
114            (setf thestring (concatenate 'string thestring 
115                                      (format nil " -h"))))
116           ((equal options "reclaim") 
117            (setf thestring (concatenate 'string thestring 
118                                      (format nil " -r")))))
119       (setf thestring (concatenate 'string thestring 
120                                    (format nil " ~d" gain)))
121     (sox-concat sox-append thestring))
122   )
123
124
125
126 ;;; Sox-Normalize ===============================================
127
128 ; this is included in sox-level
129 (defmethod! sox-normalize (&key (level 0.0) balance-mode sox-append)
130   :icon 30
131   :initvals '(0.0 nil nil )
132   :menuins '((1 (("peak" "peak") ("rms" "rms")))) 
133   :indoc (list "level (dB)" "balance channels in a multichannel-file using peak or rms detection (select from menu)" *sox-append-doc*)
134   :doc "Normalize audio or -optionally- all of the individual channels in multichannel audio.
135
136 <level> specifies the value (in dBFS) to which to normalize.
137 Optionally 'balance' the individual channels in multichannel audio (i.e. normalize individually) using peak or rms detection."
138
139   (let* ((thestring (format nil " gain")))
140     (cond ((equal balance-mode "peak")     
141            (setf thestring (concatenate 'string thestring 
142                                      (format nil " -e"))))
143           ((equal balance-mode "rms") 
144            (setf thestring (concatenate 'string thestring 
145                                      (format nil " -b")))))
146     (setf thestring (concatenate 'string thestring 
147                                  (format nil " -n ~d" level)))
148     (sox-concat sox-append thestring))
149   )
150
151
152
153 ; Sox-Overdrive ===============================================
154
155 (defmethod! sox-overdrive ((drive number) (colour number) &key sox-append)
156   :icon 30
157   :initvals '(20 20 nil)
158   :indoc (list "drive" "colour (amount of even harmonics)" *sox-append-doc*)
159   :doc "Apply non-linear distortion to the audio. 
160
161 The colour parameter controls the amount of even harmonic content in the over-driven output."
162
163   (let* ((thestring (format nil " overdrive ~d ~d" drive colour)))
164     (sox-concat sox-append thestring))
165   )
166
167
168 ;;; Sox-Compand ===============================================
169
170 (defmethod! sox-comp-format ((attack number) (release number) &key (softknee 6) (makeup-gain 0) transferfunction (minvolume -90) (lookahead 0.0))
171   (let* ((thestring (cond ((and softknee minvolume) (format nil "~d,~d ~d:~d," attack release softknee minvolume))
172                           (softknee (format nil "~d,~d ~d:" attack release softknee))
173                           (minvolume (format nil "~d,~d ~d" attack release minvolume))
174                           (t (format nil "~d,~d " attack release))
175                           )))
176
177     (if (bpf-p transferfunction)
178         (progn
179           (setf transferpoints (point-pairs transferfunction))
180           (setf firstpair (car transferpoints))
181           (setf thestring (concatenate 'string thestring 
182                                        (format nil "~d,~d" (first firstpair) (second firstpair))))
183           (loop for points in (cdr transferpoints) do
184                 (setf thestring (concatenate 'string thestring
185                                              (format nil ",~d,~d" (first points) (second points))))))
186       (setf thestring (concatenate 'string thestring (format nil "-70"))))
187    
188     (setf thestring (concatenate 'string thestring 
189                                  (format nil " ~d ~d ~d" (or makeup-gain 0) (or minvolume -90) (or lookahead 0.0))))
190     thestring))
191
192
193
194 (defmethod! sox-compand ((attack number) (release number) &key transferfunction (softknee 6) (makeup-gain -5) (minvolume -90) (lookahead 0.02) (sox-append))
195   :icon 30
196   :initvals '(0.3 0.8 nil 6 -5  -90 0.02 nil)
197   :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*)
198   :doc "Compand (compress and/or expand) the dynamic range of the audio.
199
200 <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.
201
202 <transferfunction> is a breakpoint function describing compression/expansion over the dynamic range of the input signal.
203
204 <softknee> will round the points at where adjacent line segments on the transfer function meet by the specified amount.
205
206 <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.
207
208 <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.
209
210 <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."
211 (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*)
212 ;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. 
213
214   (setf thestring
215         (sox-comp-format attack release :softknee softknee :makeup-gain makeup-gain :transferfunction transferfunction 
216                          :minvolume minvolume :lookahead lookahead))
217   (setf thestring (string+ " compand " thestring))
218   (sox-concat sox-append thestring)
219   )
220
221
222 #|
223 ;;; sox-compand needs a method for lists of attacks and releases (for multichannel)!
224 (defmethod! sox-compand ((attack number) (release number) &key (softknee 6) (makeup-gain -5) transferfunction (minvolume -90) (lookahead 0.3) (sox-append))
225   :icon 30
226   :initvals '(0.3 0.8 6 -5 nil -90 0.3 nil)
227   :indoc '("attack-time (secs)" "release-time (secs)" "softknee in dB" )
228   :doc "Compand (compress or expand) the dynamic range of the audio."
229   (let* (
230          (thestring (format nil "compand ~d,~d ~d:~d," attack release softknee minvolume)))
231     (if (bpf-p transferfunction)
232         (progn
233           (setf transferpoints (point-pairs transferfunction))
234           (setf firstpair (car transferpoints))
235           ;(print firstpair)
236           (setf thestring (concatenate 'string thestring 
237                                        (format nil "~d,~d" (first firstpair) (second firstpair))))
238           (loop for points in (cdr transferpoints) do
239                 (setf thestring (concatenate 'string thestring
240                                              (format nil ",~d,~d" (first points) (second points))))))
241       (setf thestring (concatenate 'string thestring (format nil "-70" attack release softknee)))
242           )
243       (setf thestring (csoundfileoncatenate 'string thestring 
244                                    (format nil " ~d ~d ~d" makeup-gain minvolume lookahead)))
245     (when sox-append
246       (setf thestring (concatenate 'string thestring 
247                                    (format nil " ~a" sox-append))))
248     thestring))
249 |#
250
251 ;;; Sox-MultiCompand ===========================================
252
253 (defmethod! sox-multi-compand ((attacks list) (releases list) (crossover-freqs list) &key transferfunction softknee makeup-gain minvolume lookahead sox-append)
254   :icon 30
255   :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)  
256               (-90 -90 -90 -90 -90) (0.3 0.3 0.3 0.3 0.3) nil)
257   :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*)
258   :doc "Compand (compress and/or expand) the dynamic range of the audio in individual frequency bands.
259
260
261 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.
262 See the sox-compand doc for the definition of its parameters.
263 "
264
265   (let* ((mystr "")
266          (mystrings
267           (loop for att in attacks
268                 for rel in releases
269                 counting att into counter
270                 collect
271                 (let ((count (1- counter)))
272                    (format nil "~s" (sox-comp-format att rel :softknee (nth count softknee) :makeup-gain (nth count makeup-gain)
273                                :transferfunction (nth count transferfunction) :minvolume (nth count minvolume) :lookahead (nth count lookahead)))
274                   )))
275          (mylists (mat-trans (list mystrings crossover-freqs))))
276
277     (loop for item in mylists do
278                 (print item)
279                 (if (second item)
280                 (setf mystr (concatenate 'string mystr (format nil "~a ~d " (first item) (second item))))
281                  (setf mystr (concatenate 'string mystr (format nil "~a" (first item))))))
282     (sox-concat sox-append (format nil " mcompand ~a" mystr)))
283   )
284
285