Work-in-progress repo for ambisonics extensions for OM-SoX
Marlon Schumacher
5 days ago 6ae8ed47dd6caf4ff4df39f1195b87d02e2537f0
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
;*********************************************************************
; 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)
 
;%%%%%%%%%%%% Time/Frequency %%%%%%%%%%%%%%%%%%%%%%%%
 
;; Sox-Transpose ==================================
 
(defmethod! sox-transpose ((transposition number) &key segment search overlap sox-append)
  :icon 50
  :initvals '(nil 82 14.68 12 nil)
  :indoc (list "transposition in midicents" "segment-size (ms)" "search-size (ms)" "overlap (ms)" *sox-append-doc*)
  :doc "Transposes a sound (without changing the speed/length).
 
This effect uses the WSOLA algorithm. The audio is chopped up into segments which are then shifted in the time domain and overlapped (cross-faded) at points where their waveforms are most similar as determined by measurement of 'least squares'."
 
  (let* ((thestring (format nil " pitch ~a ~d ~d ~d" transposition (or segment 82) (or search 14.68) (or overlap 12))))
    (sox-concat sox-append thestring))
  )
 
;; Sox-Multitranspose
 
;; keep the delta-times in the list-based function, but use start-times and 0 bend (or vice versa) for th BPF case
 
(defmethod! sox-multi-transpose ((midicents list) (delta-times list) (durations list) &key (framerate 25) (oversampling 16) sox-append) 
  :icon 50
  :initvals '(nil nil nil 25 16 nil)
  :indoc (list "transposition in midicents (list) or pitch-profile (bpf)" "Delta-times between transpositions (in secs) or pitch-profile (bpf)" "duration of 'portamento'" "framerate of DFTs" "oversampling factor" *sox-append-doc*)
  :doc "Changes pitch by specified amounts at specified times (without changing the speed). 
 
The pitch-bending algorithm utilises the Discrete Fourier Transform (DFT) at a particular frame rate and over-sampling rate. 
The <framerate> (default: 25, max: 64) and <oversampling> (default: 16, max: 32) parameters may be used to adjust these parameters and thus control the smoothness of the changes in pitch.
"  
 
;delay is the amount of time after the start of the audio stream, or the end of the previous bend, at which to start bending the pitch
;cents is the number of cents
;duration the length of time over which the pitch will be bent.
 
;(delta-times should be 'start times' absolute not, deltas
 
  (let* (
         (thestring (format nil "bend -f ~d -o ~d" (clip (or framerate 25) 1 64) (clip (or oversampling) 1 32))))
         ;(delta-times (x-append (first start-times) (x->dx start-times))))
    (unless (listp midicents)
      (setf midicents
            (make-list (length delta-times) :initial-element midicents)))
    (unless (listp durations)
      (setf durations
            (make-list (length delta-times) :initial-element (clip durations 0.001 9999))))
    (loop for time in delta-times
          for cents in midicents
          for durs in durations do
          (setf thestring (concatenate 'string thestring
                                        (format nil " ~d,~d,~d" time cents durs))))
              (sox-concat sox-append thestring))
  )
 
 
(defmethod! sox-multi-transpose ((midicents bpf) (delta-times list) (durations list) &key (framerate 25) (oversampling 16) sox-append)
  (let* ((thepoints (mat-trans (point-pairs midicents)))
         ;(thedxpoints (mat-trans (list (x-append (first (first thepoints)) (x->dx (first thepoints))) (x->dx (second thepoints)))))
         (thexpoints (loop for item in (x->dx (first thepoints)) collect
                           (if (= 0 item) 0.001 item)))
                      
         (theypoints (loop for item in (x->dx (second thepoints)) collect
                           (if (= 0 item)  0.01 item)))
                             
         (thedxpoints (mat-trans (list thexpoints theypoints)))
        
         (thestring (format nil " bend -f ~a -o ~a" framerate oversampling)))
 
    (loop for pair in thedxpoints collect
          (setf thestring (concatenate 'string thestring         
                                       (format nil " 0,~d,~d" (second pair) (first pair))))
          )
    (sox-concat sox-append thestring)
    ))
 
;; Sox-Stretch ==================================
 
(defmethod! sox-stretch ((factor number) &key preset segment (search 14.68) (overlap 12) sox-append)
  :icon 50
  :initvals '(nil nil nil nil nil nil)
  :menuins '((1 (("music" "-m") ("speech" "-s") ("linear" "-l"))))
  :indoc (list "stretch-factor" "preset (default = linear)" "segment-size (ms)" "search-size (ms)" "overlap (ms)" *sox-append-doc*)
  :doc "Stretch/compress a sound temporally (without changing the pitch).
 
This effect uses the WSOLA algorithm. The audio is chopped up into segments which are then shifted in the time domain and overlapped (cross-faded) at points where their waveforms are most similar as determined bymeasurement of 'least squares'."
 
  (let* (
        (thestring (format nil "tempo"))
        (factor (float (/ 1 factor))))
    (if preset     
        (setf thestring (concatenate 'string thestring 
                                     (format nil " ~a ~a" preset factor)))
      (setf thestring (concatenate 'string thestring 
                                   (format nil " ~a ~d ~d ~d" factor (or segment 82) (or search 14.68) (or (clip overlap 0 search) 12)))))
    (sox-concat sox-append thestring))
  )
 
;; Sox-Speed ==================================
 
(defmethod! sox-speed ((speed number) &key mode sox-append)
  :icon 50
  :initvals '(nil "ratio" nil)
  :menuins '((1 (("ratio" "ratio") ("midicent" "midicent"))))
  :indoc (list "speed-factor / midicents (depending on mode)" 
               "ratio or midicent to control change in speed (default = ratio)" 
               *sox-append-doc*)
  :doc "Adjust the audio speed (pitch and tempo together). 
 
Speed is either the ratio of the new speed to the old speed: greater than 1 speeds up, less than 1 slows down, or, depending on 'mode' the number of cents by which the pitch (and tempo) should be adjusted: greater than 0 increases, less than 0 decreases."
 
  (let* ((thestring (format nil "speed ~d" speed)))
    (when (equal mode "midicent")
      (setf thestring (concatenate 'string thestring 
                                   (format nil "c" sox-append))))
   (sox-concat sox-append thestring))
  )