Work-in-progress repo for ambisonics extensions for OM-SoX
Marlon Schumacher
3 days ago 27d7ae0a3f50b5554d4ead0fbb09c2490d62ad07
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
;*********************************************************************
; OM-SoX, (c) 2011-2014 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-reverse ==================================
 
(defmethod! sox-reverse ( &key sox-append)
  :icon 70
  :initvals '(nil)
  :indoc (list *sox-append-doc*)
  :doc "Reverse audio"
 
  (let* ((thestring (format nil " reverse")))
    (sox-concat sox-append thestring))
  )
 
 
; sox-repeat ==================================
 
(defmethod! sox-repeat ((repetitions number) &key sox-append)
  :icon 70
  :initvals '(nil)
  :indoc (list "number of repetitions (loops)" *sox-append-doc*)
  :doc "repeats (loops) a soundfile n (repetition) number of times."
 
  (let ((thestring (format nil "repeat ~d" repetitions)))
    (sox-concat sox-append thestring))
  )
 
 
; sox-pad ==================================
; if float then seconds if int then samples!
; I should use sox-units for any unit (time, amplitude, etc.)
 
(defmethod! sox-pad ((duration float) &key position sox-append)
  :icon 70
  :initvals '(nil nil nil)
  :indoc (list "duration of silence/zero-padding (if float in seconds, otherwise in samples)" "position in the soundfile to insert silence" *sox-append-doc*)
  :doc "Pad the audio with silence. Optionally at beginning, end, or specified points through the audio."
 
; NEEDS TIME UNITS!  
 
;NB: length and position can be specified in secs [float] or samples [integer].
 
  (let ((thestring (if position 
                       (setf thestring (format nil " pad ~d@~d" duration position))
                     (format nil " pad ~d " duration))))
    (sox-concat sox-append thestring))
  )
 
;if ints are provided for duration, it is in samples
(defmethod! sox-pad ((duration integer) &key position sox-append)
            (let ((thestring (if position 
                                 (setf thestring (format nil " pad ~ds@~d" duration position))
                               (format nil " pad ~ds " duration))))
              (sox-concat sox-append thestring))
            )
 
(defmethod! sox-pad ((duration list) &key position sox-append)
  (let* ((thestring (format nil " pad")))
    (if position
        (loop for dur in duration
              for pos in position do
              (setf thestring (concatenate 'string thestring
                                           (format nil " ~d@~d" dur pos))))
      (loop for dur in duration do 
            (setf thestring (concatenate 'string thestring 
                                         (format nil " ~d" dur))))
      )
    (sox-concat sox-append thestring))
  )
 
 
; sox trim ==================================
 
(defmethod! sox-trim ((start number) &key unit sox-append)
  :icon 70
  :initvals '(nil nil nil)
  :indoc (list "start (number in secs), or start and end (list of 'start' and 'end' point (in secs)" "specify time in seconds or samples" *sox-append-doc* )
  :menuins '((1 (("seconds" "seconds") ("samples" "samples"))))
  :doc "Trims off unwanted parts from beginning and end of audio"
 
  (let* ((thestring (format nil " trim ~d" start))
         (thestring (sox-units thestring unit)))
    (sox-concat sox-append thestring))
  )
 
(defmethod! sox-trim ((start-and-end list) &key unit sox-append)
  (let* ((thestring (if (equal unit "samples") 
                        (format nil " trim ~ds ~ds " (first start-and-end) (- (second start-and-end) (first start-and-end)))
                      (format nil " trim ~d ~d " (first start-and-end) (- (second start-and-end) (first start-and-end))))))         
    (sox-concat sox-append thestring))
  )
 
 
; sox-crop ==================================
; (allows to crop from the end)
 
(defmethod! sox-crop ((start number) &key sox-append)
  :icon 70
  :initvals '(nil nil)
  :indoc (list "start (number in secs), or start and end (list of 'start' and 'end' point (in secs)" *sox-append-doc* )
  :doc "trims off unwanted audio from beginning and end of audio"
 
  (let* ((thestring (format nil "crop ~d " start)))
    (sox-concat sox-append thestring))
  )
   
 
(defmethod! sox-crop ((start-and-end list) &key sox-append)
  (let* ((thestring (format nil "crop ~d ~d" (first start-and-end) (- (second start-and-end) (first start-and-end)))))
    (sox-concat sox-append thestring))
  )
 
 
 
; sox-autotrim ==================================
; strips-off silence based on a cepstral power measurement to detect a human voice
 
(defmethod! sox-voicetrim ((mode string) &key sox-append)
  :icon 70
  :initvals '("front" nil nil nil nil nil nil)
  :menuins '((0 (("front" "front") ("back" "back") ("front+back" "front+back"))))
  :indoc (list "mode: trim silence from front/back/front+back" *sox-append-doc*)
  :doc "Automatically trim silence and quiet background sounds from the beginning/end of (voiced) audio. 
 
Sox-voicetrim attempts to automatically trim silence and quiet background sounds from the beginning/end of (fairly high resolution i.e. 16-bit, 44.1kHz) speech based on cepstral power measurement."
 
  (let* (
         (thestring 
         (cond ((equal mode "front")
                "vad")
               ((equal mode "back")
                "reverse vad reverse")
               ((equal mode "front+back")
                "vad reverse vad reverse")
                )))
    (sox-concat sox-append thestring)))
 
; for compatibility
#|
(defmethod! sox-autotrim ((mode string) &key sox-append)
            :icon 70
            (sox-voicetrim mode :sox-append sox-append))
|#
 
;; PS these options don't seem to work ... 
;; bug in sox?
#|
(defmethod! sox-autotrim ((mode string) &key trigger-level ignore-time prior-time gap-time preserve-time commands)
  :icon 01
  :initvals '(front nil nil nil nil nil nil)
  :menuins '((0 (("front" "front") ("back" "back") ("front+back" "front+back"))))
  :indoc '("mode: trim silence from front/back/front+back" "autotrim-settings" "connect other commands to add to the processing chain")
  :doc "Attempts to trim silence and quiet background sounds from the ends of (fairly high resolution i.e. 16-bit, 44-48kHz) recordings of speech based on cepstral power measurement."
  (let* (
         (thestring 
         (cond ((equal mode "front")
                (format nil "vad t ~d T ~d s ~d g ~d p ~d" (or trigger-level 7) (or ignore-time 0.25) (or prior-time 1) (or gap-time 0.25) (or preserve-time 0)))
               ((equal mode "back")
                (format nil "reverse vad t ~d T ~d s ~d g ~d p ~d reverse" (or trigger-level 7) (or ignore-time 0.25) (or prior-time 1) (or gap-time 0.25) (or preserve-time 0)))
               ((equal mode "front+back")
                (format nil "vad t ~d T ~d s ~d g ~d p ~d reverse vad t ~d T ~d s ~d g ~d p ~d reverse" (or trigger-level 7) (or ignore-time 0.25) (or prior-time 1) (or gap-time 0.25) (or preserve-time 0) (or trigger-level 7) (or ignore-time 0.25) (or prior-time 1) (or gap-time 0.25) (or preserve-time 0) ))
                )))
    (when commands
      (setf thestring (concatenate 'string thestring 
                                   (format nil " ~a" commands))))
    thestring))
|#
 
;; sox-fade ==================================
(defmethod! sox-fade ((fadein-length number) (fadeout-length number) (stoptime t) &key (type "l") sox-append)
  :icon 70
  :initvals '(1 1 "-0" "l" nil)
  :menuins '((3 (("logarithmic" "l") ("parabola" "p") ("quarter sinewave" "q") ("half sinewave" "h") ("linear" "t")))) 
  :indoc (list "fadein-length (in secs). Optionally <sound> object." "fadeout-length (in secs)" "stoptime (in secs). if 0 = duration of soundfile)" "fade-type (logarithmic/parabola/quarter-sine/half-sine/linear)" *sox-append-doc*)
  :doc "creates fadeins/outs"
 
  (setf thestring (format nil " fade ~a ~d ~d ~d " type fadein-length stoptime fadeout-length))
    ;; settings here!
    (sox-concat sox-append thestring))
 
 
(defmethod! sox-fade ((soundfile sound) (fadeout-length number) (stoptime number) &key (type "l") sox-append)
  (let* ((duration (sound-dur soundfile))
         (markers (markers soundfile))
         (fadein-length (first markers))
         (fadeout-length (- duration (second markers)))
         (stoptime duration))
  (setf thestring (format nil " fade ~a ~d ~d ~d " type fadein-length stoptime fadeout-length)))
  (sox-concat sox-append thestring))
 
 
 
;; sox-silence ==================================
; remove (cut) silence from a recording
(defmethod! sox-trimsilence  ((above-periods number) (duration number) (threshold number) &key below-periods (below-duration 1) (below-threshold -50) leave-beginning sox-append)
  :icon 70
  :initvals '(1 2 -60 1 1 -50 nil nil)
  :indoc (list "How many periods of non-silence should be retained" 
               "Amount of time that non-silence must be detected before it stops trimming audio" 
               "Silence-threshold (in dB)" 
               "How many periods of silence should be retained"
               "Amount of time that silence must be detected before it trims audio"
               "Below-threshold (in dB)"
               "Leave the beginning of audio untouched"
               *sox-append-doc*)
  :doc "Removes (trims off) silence from the audo. 'Silence' is determined via duration (in secs) and threshold (in dB)."
 
  (let ((thestring (format nil " silence ")))
    (when leave-beginning (setf thestring (concatenate 'string thestring " -l")))
    (setf thestring (if (equal above-periods 0)
                        (string+ thestring (format nil " ~d" above-periods))
                      (string+ thestring (format nil " ~d ~f ~d" above-periods duration (db->lin threshold))))) ; if it's in percent I should multiply by 100, no?
    (when below-periods (setf thestring (string+ thestring (format nil " ~d ~f ~d" below-periods below-duration (db->lin below-threshold)))))
    (sox-concat sox-append thestring)
    ))