1
+ function PhaseVocoder ( winSize , sampleRate ) {
2
+
3
+ var _sampleRate = sampleRate ; var _RS = 0 ; var _RA = 0 ; var _omega ;
4
+
5
+ var _previousInputPhase ; var _previousOutputPhase ; var _framingWindow ;
6
+
7
+ var _squaredFramingWindow ; var _winSize = winSize ;
8
+
9
+ var _overlapBuffers ; var _owOverlapBuffers ;
10
+
11
+ var _first = true ;
12
+
13
+
14
+
15
+ this . overlap_and_slide = function ( RS , frame , overlapBuffer , windowSize , finishedBytes ) {
16
+
17
+ for ( var i = 0 ; i < RS ; i ++ ) {
18
+ finishedBytes [ i ] = overlapBuffer . shift ( ) ;
19
+ while ( overlapBuffer . length > windowSize - 1 && overlapBuffer . length >= 0 )
20
+ overlapBuffer . shift ( ) ;
21
+ overlapBuffer . push . apply ( overlapBuffer , [ 0.0 ] ) ;
22
+ }
23
+
24
+ var outBytes = [ ] . concat ( overlapBuffer ) ;
25
+
26
+ for ( var i = 0 ; i < outBytes . length ; i ++ )
27
+ outBytes [ i ] = frame [ i ] + overlapBuffer [ i ] ;
28
+
29
+ while ( ( overlapBuffer . length > windowSize - outBytes . length ) && overlapBuffer . length >= 0 ) {
30
+ overlapBuffer . shift ( ) ;
31
+ }
32
+
33
+ overlapBuffer . push . apply ( overlapBuffer , outBytes ) ;
34
+
35
+ return ;
36
+ }
37
+
38
+
39
+ this . find_peaks = function ( magFrame , out ) {
40
+ var magSpecPad = [ 0 , 0 ] . concat ( magFrame ) . concat ( [ 0 , 0 ] ) ;
41
+ out . peaks = [ ] ;
42
+
43
+ for ( var i = 2 , I = 0 ; i <= magSpecPad . length - 2 ; i ++ , I ++ ) {
44
+ x = magSpecPad [ i ] ;
45
+ if ( x > magSpecPad [ i - 2 ] && x > magSpecPad [ i - 1 ] && x > magSpecPad [ i + 1 ] && x > magSpecPad [ i + 2 ] ) {
46
+ out . peaks = out . peaks . concat ( I ) ;
47
+ }
48
+ }
49
+
50
+ out . inflRegStart = new Array ( out . peaks . length ) ;
51
+
52
+ out . inflRegStart [ 0 ] = 0 ;
53
+ for ( var i = 0 ; i < out . peaks . length - 1 ; i ++ ) {
54
+ out . inflRegStart [ i + 1 ] = Math . ceil ( ( out . peaks [ i ] + out . peaks [ i + 1 ] ) / 2 ) ;
55
+ }
56
+
57
+ out . inflRegEnd = new Array ( out . peaks . length ) ;
58
+ for ( var i = 1 ; i < out . inflRegStart . length ; i ++ ) {
59
+ out . inflRegEnd [ i - 1 ] = out . inflRegStart [ i ] - 1 ;
60
+ }
61
+ out . inflRegEnd [ out . inflRegEnd . length ] = out . inflRegEnd . length - 1 ;
62
+
63
+ out . influenceRegions = new Array ( out . inflRegStart . length ) ;
64
+ for ( var i = 0 ; i < out . influenceRegions . length ; i ++ )
65
+ out . influenceRegions [ i ] = Math . max ( 0 , out . inflRegEnd [ i ] - out . inflRegStart [ i ] + 1 ) ;
66
+
67
+ return ;
68
+ }
69
+
70
+
71
+ this . get_phase_advances = function ( currentInputPhase , previousInputPhase , omega , RA , RS , instPhaseAdvHop ) {
72
+ var twoPI = 2 * Math . PI ;
73
+
74
+ for ( var i = 0 ; i < omega . length ; i ++ ) {
75
+ var expectedPhaseAdv = omega [ i ] * RA ;
76
+
77
+ var auxheterodynedPhaseIncr = ( currentInputPhase [ i ] - previousInputPhase [ i ] ) - expectedPhaseAdv ;
78
+ var heterodynedPhaseIncr = auxheterodynedPhaseIncr - twoPI * Math . round ( auxheterodynedPhaseIncr / twoPI ) ;
79
+
80
+ var instPhaseAdvPerSampleHop = omega [ i ] + heterodynedPhaseIncr / RA ;
81
+
82
+ instPhaseAdvHop [ i ] = instPhaseAdvPerSampleHop * RS ;
83
+ }
84
+
85
+ return ;
86
+ }
87
+
88
+
89
+ this . get_phasor_theta_v2 = function ( currentInputPhase , previousOutputPhase , instPhaseAdv , frequencyBins , influenceRegions , theta ) {
90
+ // Get the peaks in the spectrum together with their regions of influence.
91
+
92
+ var theta_idx = 0 ;
93
+ for ( var i = 0 ; i < frequencyBins . length ; i ++ ) {
94
+ var bin = frequencyBins [ i ] ;
95
+ for ( var j = 0 ; j < influenceRegions [ i ] ; j ++ , theta_idx ++ ) {
96
+ theta [ theta_idx ] = previousOutputPhase [ bin ] + instPhaseAdv [ bin ] - currentInputPhase [ bin ] ;
97
+ }
98
+ }
99
+
100
+ var remaining_length = theta . length - theta_idx ;
101
+ for ( var i = 0 ; i < remaining_length ; i ++ , theta_idx ++ )
102
+ theta [ theta_idx ] = 0 ;
103
+
104
+ return ;
105
+ }
106
+
107
+
108
+ this . identity_phase_locking = function ( currentInputMagnitude , currentInputPhase , previousOutputPhase , instPhaseAdv , phasor_theta ) {
109
+ var _ = this ; var r = { } ;
110
+
111
+ _ . find_peaks ( currentInputMagnitude , r ) ;
112
+
113
+ _ . get_phasor_theta_v2 ( currentInputPhase , previousOutputPhase , instPhaseAdv , r . peaks , r . influenceRegions , phasor_theta ) ;
114
+
115
+ return ;
116
+ }
117
+
118
+ this . pv_step_v2 = function ( fftObject , previousInputPhase , previousOutputPhase , omega , RA , RS , out ) {
119
+
120
+ var _ = this ;
121
+
122
+ var currentInputPhase = fftObject . phase ;
123
+
124
+ var instPhaseAdv = new Array ( omega . length ) ;
125
+ _ . get_phase_advances ( currentInputPhase , previousInputPhase , omega , RA , RS , instPhaseAdv ) ;
126
+
127
+ var currentInputMag = fftObject . magnitude ;
128
+
129
+ var phasor_theta = new Array ( currentInputPhase . length ) ;
130
+ _ . identity_phase_locking ( currentInputMag , currentInputPhase , previousOutputPhase , instPhaseAdv , phasor_theta ) ;
131
+
132
+ out . real = new Array ( ( phasor_theta . length - 1 ) * 2 ) ;
133
+ out . imag = new Array ( ( phasor_theta . length - 1 ) * 2 ) ;
134
+ out . phase = new Array ( ( phasor_theta . length - 1 ) * 2 ) ;
135
+ out . magnitude = new Array ( ( phasor_theta . length - 1 ) * 2 ) ;
136
+ var doubleSize = ( phasor_theta . length - 1 ) * 2 ;
137
+ var sqrt = Math . sqrt ; var cos = Math . cos ;
138
+ var sin = Math . sin ; var atan2 = Math . atan2 ;
139
+
140
+
141
+ for ( var i = 0 ; i < phasor_theta . length ; i ++ ) {
142
+ var theta = phasor_theta [ i ] ;
143
+
144
+ var phasor_theta_real = cos ( theta ) ;
145
+ var phasor_theta_imag = sin ( theta ) ;
146
+ out . real [ i ] = phasor_theta_real * fftObject . real [ i ] - phasor_theta_imag * fftObject . imag [ i ] ;
147
+ out . imag [ i ] = phasor_theta_real * fftObject . imag [ i ] + phasor_theta_imag * fftObject . real [ i ] ;
148
+ out . phase [ i ] = atan2 ( out . imag [ i ] , out . real [ i ] ) ;
149
+ out . magnitude [ i ] = sqrt ( out . imag [ i ] * out . imag [ i ] + out . real [ i ] * out . real [ i ] ) ;
150
+
151
+ if ( i > 0 ) {
152
+ out . real [ doubleSize - i ] = out . real [ i ] ;
153
+ out . imag [ doubleSize - i ] = - out . imag [ i ] ;
154
+ out . phase [ doubleSize - i ] = atan2 ( out . imag [ doubleSize - i ] , out . real [ doubleSize - i ] ) ;
155
+ out . magnitude [ doubleSize - i ] = sqrt ( out . imag [ doubleSize - i ] * out . imag [ doubleSize - i ] + out . real [ doubleSize - i ] * out . real [ doubleSize - i ] ) ;
156
+ }
157
+
158
+ }
159
+
160
+ return ;
161
+ }
162
+
163
+
164
+ this . process = function ( inputFrame ) {
165
+
166
+ var _ = this ;
167
+
168
+ var __RS = _RS ;
169
+ var __RA = _RA ;
170
+
171
+ // -----------------------------
172
+ // ----------FFT STEP-----------
173
+ // -----------------------------
174
+
175
+ var fftObject = { } ;
176
+ var out = { } ;
177
+ var processedFrame = [ ] ;
178
+
179
+ if ( _first ) {
180
+ _ . STFT ( inputFrame , _framingWindow , _winSize , fftObject ) ;
181
+ _previousOutputPhase = fftObject . phase ;
182
+ _previousInputPhase = fftObject . phase ;
183
+ processedFrame = new Array ( fftObject . real . length ) ;
184
+ _ . ISTFT ( fftObject . real , fftObject . imag , _framingWindow , true , processedFrame ) ;
185
+ } else {
186
+ _ . STFT ( inputFrame , _framingWindow , Math . round ( _winSize / 2 ) + 1 , fftObject ) ;
187
+ _ . pv_step_v2 ( fftObject , _previousInputPhase , _previousOutputPhase , _omega , __RA , __RS , out ) ;
188
+ _previousOutputPhase = out . phase ;
189
+ _previousInputPhase = fftObject . phase ;
190
+ processedFrame = new Array ( out . real ) ;
191
+ _ . ISTFT ( out . real , out . imag , _framingWindow , true , processedFrame ) ;
192
+ }
193
+
194
+ _first = false ;
195
+
196
+
197
+ // -----------------------------
198
+ // ------OVERLAP AND SLIDE------
199
+ // -----------------------------
200
+ var outputFrame = [ ] ;
201
+ _ . overlap_and_slide ( __RS , processedFrame , _overlapBuffers , _winSize , outputFrame ) ;
202
+ var owFrame = [ ] ;
203
+ _ . overlap_and_slide ( __RS , _squaredFramingWindow , _owOverlapBuffers , _winSize , owFrame ) ;
204
+
205
+ for ( var i = 0 ; i < outputFrame . length ; i ++ )
206
+ outputFrame [ i ] = outputFrame [ i ] / ( ( owFrame [ i ] < 10e-3 ) ? 1 : owFrame [ i ] ) ;
207
+
208
+ return outputFrame ;
209
+
210
+ }
211
+
212
+
213
+
214
+ this . STFT = function ( inputFrame , windowFrame , wantedSize , out ) {
215
+ var winSize = windowFrame . length ;
216
+ var _inputFrame = new Array ( winSize ) ;
217
+ var fftFrame = new Array ( 2 * winSize ) ;
218
+
219
+ for ( var i = 0 ; i < winSize ; i ++ ) {
220
+ _inputFrame [ i ] = inputFrame [ i ] * windowFrame [ i ] ;
221
+ }
222
+ var fft = new FFT . complex ( winSize , false ) ;
223
+ fft . simple ( fftFrame , _inputFrame , 'real' ) ;
224
+
225
+ out . real = new Array ( Math . min ( winSize , wantedSize ) ) ;
226
+ out . imag = new Array ( Math . min ( winSize , wantedSize ) ) ;
227
+ out . magnitude = new Array ( Math . min ( winSize , wantedSize ) ) ;
228
+ out . phase = new Array ( Math . min ( winSize , wantedSize ) ) ;
229
+
230
+ for ( var p = 0 ; p < winSize && p < wantedSize ; p ++ ) {
231
+ var real = out . real ; var imag = out . imag ;
232
+ var phase = out . phase ; var magnitude = out . magnitude ;
233
+ real [ p ] = fftFrame [ 2 * p ] ;
234
+ imag [ p ] = fftFrame [ 2 * p + 1 ] ;
235
+ magnitude [ p ] = Math . sqrt ( imag [ p ] * imag [ p ] + real [ p ] * real [ p ] ) ;
236
+ phase [ p ] = Math . atan2 ( imag [ p ] , real [ p ] ) ;
237
+ }
238
+
239
+ return ;
240
+ }
241
+
242
+ this . ISTFT = function ( real , imaginary , windowFrame , restoreEnergy , output2 ) {
243
+ var input = new Array ( 2 * real . length ) ;
244
+ var output1 = new Array ( 2 * real . length ) ;
245
+
246
+ for ( var i = 0 ; i < real . length ; i ++ ) {
247
+ input [ 2 * i ] = real [ i ] ;
248
+ input [ 2 * i + 1 ] = imaginary [ i ] ;
249
+ }
250
+
251
+ var ifft = new FFT . complex ( real . length , true ) ;
252
+
253
+ ifft . simple ( output1 , input , 'complex' ) ;
254
+
255
+ if ( restoreEnergy ) {
256
+ var energy1 = 0 ;
257
+ var energy2 = 0 ;
258
+ var eps = 2.2204e-16 ;
259
+ for ( var i = 0 ; i < windowFrame . length ; i ++ ) {
260
+ energy1 += Math . abs ( output1 [ 2 * i ] ) ;
261
+ output2 [ i ] = output1 [ 2 * i ] / windowFrame . length ;
262
+ output2 [ i ] *= windowFrame [ i ] ;
263
+ energy2 += Math . abs ( output1 [ 2 * i ] ) ;
264
+ output2 [ i ] *= energy1 / ( energy2 + eps ) ;
265
+ }
266
+ } else if ( windowFrame ) {
267
+ for ( var i = 0 ; i < windowFrame . length ; i ++ ) {
268
+ output2 [ i ] = output1 [ 2 * i ] / windowFrame . length ;
269
+ output2 [ i ] *= windowFrame [ i ] ;
270
+ }
271
+ } else {
272
+ for ( var i = 0 ; i < real . length ; i ++ ) {
273
+ output2 [ i ] = output1 [ 2 * i ] / real . length ;
274
+ }
275
+ }
276
+
277
+ return ;
278
+ }
279
+
280
+
281
+ this . init = function ( ) {
282
+
283
+ var _ = this ;
284
+
285
+ _omega = _ . create_omega_array ( winSize ) ;
286
+
287
+ _previousInputPhase = _ . create_constant_array ( winSize / 2 , 0 ) ;
288
+ _previousOutputPhase = _ . create_constant_array ( winSize / 2 , 0 ) ;
289
+ _framingWindow = _ . create_sin_beta_window_array ( winSize , 1 ) ;
290
+ _squaredFramingWindow = _framingWindow . map ( function ( x , i ) { return x * x ; } ) ;
291
+
292
+ _overlapBuffers = _ . create_constant_array ( winSize , 0 ) ;
293
+
294
+ _owOverlapBuffers = _ . create_constant_array ( winSize , 0 ) ;
295
+
296
+ _ . set_alpha ( 1 ) ;
297
+ }
298
+
299
+ this . create_omega_array = function ( size ) {
300
+ return Array . apply ( null , Array ( size / 2 + 1 ) ) . map ( function ( x , i ) {
301
+ return 2 * Math . PI * i / size ;
302
+ } ) ;
303
+ }
304
+
305
+ this . create_sin_beta_window_array = function ( size , beta ) {
306
+ return Array . apply ( null , Array ( size ) ) . map ( function ( x , i ) {
307
+ return Math . pow ( Math . sin ( Math . PI * i / size ) , beta ) ;
308
+ } ) ;
309
+ }
310
+
311
+ this . create_constant_array = function ( size , constant ) {
312
+ return Array . apply ( null , Array ( size ) ) . map ( function ( ) {
313
+ return constant ;
314
+ } ) ;
315
+ }
316
+
317
+ this . reset = function ( ) {
318
+
319
+ var _ = this ;
320
+
321
+ _previousInputPhase = _ . create_constant_array ( winSize / 2 , 0 ) ;
322
+ _previousOutputPhase = _ . create_constant_array ( winSize / 2 , 0 ) ;
323
+
324
+ _overlapBuffers = _ . create_constant_array ( winSize , 0 ) ;
325
+ _owOverlapBuffers = _ . create_constant_array ( winSize , 0 ) ;
326
+
327
+ _first = true ;
328
+ }
329
+
330
+ this . reset2 = function ( ) {
331
+
332
+ var _ = this ;
333
+
334
+ _previousInputPhase = _ . create_constant_array ( winSize / 2 , 0 ) ;
335
+ _previousOutputPhase = _ . create_constant_array ( winSize / 2 , 0 ) ;
336
+
337
+ _first = true ;
338
+ }
339
+
340
+
341
+ this . get_previous_input_phase = function ( ) {
342
+ return _previousInputPhase ;
343
+ }
344
+
345
+ this . get_previous_output_phase = function ( ) {
346
+ return _previousOutputPhase ;
347
+ }
348
+
349
+ this . get_analysis_hop = function ( ) {
350
+ return _RA ;
351
+ }
352
+
353
+ this . get_synthesis_hop = function ( ) {
354
+ return _RS ;
355
+ }
356
+
357
+ this . get_alpha = function ( ) {
358
+ return _RS / _RA ;
359
+ }
360
+
361
+ this . get_framing_window = function ( ) {
362
+ return _framingWindow ;
363
+ }
364
+
365
+ this . get_squared_framing_window = function ( ) {
366
+ return _squaredFramingWindow ;
367
+ }
368
+
369
+ this . set_alpha = function ( newAlpha ) {
370
+ _RA = _winSize / 4 ;
371
+ _RS = Math . round ( newAlpha * _RA ) ;
372
+ // _RS = Math.round(_winSize/2);
373
+ // _RA = Math.round(_RS / newAlpha);
374
+ }
375
+
376
+ this . get_alpha_step = function ( ) {
377
+ return 1 / _RA ;
378
+ }
379
+
380
+ this . set_hops = function ( RA , RS ) {
381
+ _RA = RA ;
382
+ _RS = RS ;
383
+ }
384
+ }
0 commit comments