lbajardsilogic@79
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
lbajardsilogic@79
|
2
|
lbajardsilogic@79
|
3 /* Sound Access
|
lbajardsilogic@79
|
4 EASAIER client application.
|
lbajardsilogic@79
|
5 Silogic 2007. Laure Bajard.
|
lbajardsilogic@79
|
6
|
lbajardsilogic@79
|
7 This program is free software; you can redistribute it and/or
|
lbajardsilogic@79
|
8 modify it under the terms of the GNU General Public License as
|
lbajardsilogic@79
|
9 published by the Free Software Foundation; either version 2 of the
|
lbajardsilogic@79
|
10 License, or (at your option) any later version. See the file
|
lbajardsilogic@79
|
11 COPYING included with this distribution for more information.
|
lbajardsilogic@79
|
12 */
|
lbajardsilogic@79
|
13
|
lbajardsilogic@79
|
14 #include <math.h>
|
lbajardsilogic@82
|
15 #include <iostream>
|
lbajardsilogic@79
|
16
|
lbajardsilogic@79
|
17 #include "TimeStretchFilter.h"
|
lbajardsilogic@79
|
18
|
lbajardsilogic@79
|
19 #include "FFTReal.h"
|
lbajardsilogic@79
|
20 #include "DSP.h"
|
lbajardsilogic@79
|
21
|
lbajardsilogic@82
|
22 #include "system/System.h"
|
lbajardsilogic@82
|
23
|
lbajardsilogic@82
|
24 /*float *audioframe;
|
lbajardsilogic@79
|
25 float *prev_audioframe;
|
lbajardsilogic@79
|
26 float *window;
|
lbajardsilogic@79
|
27 float *processedframe;
|
lbajardsilogic@79
|
28 float *outbuffer;
|
lbajardsilogic@79
|
29 float *holdbuffer3;
|
lbajardsilogic@79
|
30 float *holdbuffer2;
|
lbajardsilogic@79
|
31 float *holdbuffer1;
|
lbajardsilogic@79
|
32
|
lbajardsilogic@79
|
33 float *c_phase; ///CURRENT FRAME phases
|
lbajardsilogic@79
|
34 float *p_phase; ///PREVIOUS FRAME phases
|
lbajardsilogic@79
|
35 float *c_synthphase;
|
lbajardsilogic@79
|
36 float *p_synthphase;
|
lbajardsilogic@82
|
37 float *synthframe;*/
|
lbajardsilogic@82
|
38
|
lbajardsilogic@82
|
39 float *c_mags; ///CURRENT FRAME MAGNITUDES
|
lbajardsilogic@82
|
40 float *p_mags; ///PREVIOUS FRAME MAGNITUDES
|
lbajardsilogic@79
|
41
|
lbajardsilogic@79
|
42 float *FFTframe;
|
lbajardsilogic@79
|
43
|
lbajardsilogic@79
|
44 float hopfactor = 1;
|
lbajardsilogic@82
|
45
|
lbajardsilogic@82
|
46 //need in DSP.cpp
|
lbajardsilogic@79
|
47 float lastfactor;
|
lbajardsilogic@79
|
48
|
lbajardsilogic@79
|
49 int numpeaks;
|
lbajardsilogic@79
|
50 float *peak_locations;
|
lbajardsilogic@82
|
51 int currentposition = 1024+1;//= hop+1;
|
lbajardsilogic@82
|
52 //
|
lbajardsilogic@79
|
53
|
lbajardsilogic@82
|
54 TimeStretchFilter::TimeStretchFilter() : Filter(),
|
lbajardsilogic@82
|
55 m_bypass(false),
|
lbajardsilogic@82
|
56 m_transcheck(false),
|
lbajardsilogic@82
|
57 m_peakcheck(false),
|
lbajardsilogic@82
|
58 m_framesize(4096),
|
lbajardsilogic@82
|
59 m_interpfactor(1)
|
lbajardsilogic@79
|
60 {
|
lbajardsilogic@82
|
61 m_hop = m_framesize/4;
|
lbajardsilogic@79
|
62
|
lbajardsilogic@82
|
63 m_inputBuffer = (float *)calloc((m_framesize*2+1), sizeof(float));
|
lbajardsilogic@82
|
64
|
lbajardsilogic@79
|
65 /**********malloc***********/
|
lbajardsilogic@82
|
66 FFTframe=(float *)calloc((m_framesize), sizeof(float));
|
lbajardsilogic@79
|
67
|
lbajardsilogic@79
|
68 //This block specifically sets up the buffers required to do a 75% overlap scheme
|
lbajardsilogic@82
|
69 audioframe=(float *)calloc((m_framesize), sizeof(float)); //The current frame
|
lbajardsilogic@82
|
70 prev_audioframe=(float *)calloc((m_framesize), sizeof(float));
|
lbajardsilogic@82
|
71 window=(float *)calloc((m_framesize), sizeof(float)); //Window
|
lbajardsilogic@82
|
72 processedframe=(float *)calloc((m_framesize), sizeof(float)); //The current frame
|
lbajardsilogic@82
|
73 synthframe=(float *)calloc((m_framesize), sizeof(float));
|
lbajardsilogic@82
|
74 outbuffer=(float *)calloc((m_framesize/4), sizeof(float)); //The current output segment which is 1/4 framesize for 75% overlap
|
lbajardsilogic@79
|
75
|
lbajardsilogic@82
|
76 holdbuffer3=(float *)calloc((m_framesize*0.75), sizeof(float)); //The hold buffer for the previous frame segment
|
lbajardsilogic@82
|
77 holdbuffer2=(float *)calloc((m_framesize/2), sizeof(float)); //The fold buffer for the frame segment 2 frames ago
|
lbajardsilogic@82
|
78 holdbuffer1=(float *)calloc((m_framesize/4), sizeof(float));
|
lbajardsilogic@79
|
79
|
lbajardsilogic@82
|
80 c_mags=(float *)calloc((m_framesize/2), sizeof(float)); //The magnitude and phase arrays
|
lbajardsilogic@82
|
81 p_mags=(float *)calloc((m_framesize/2), sizeof(float));
|
lbajardsilogic@82
|
82 c_phase=(float *)calloc((m_framesize/2), sizeof(float));
|
lbajardsilogic@82
|
83 p_phase=(float *)calloc((m_framesize/2), sizeof(float));
|
lbajardsilogic@82
|
84 c_synthphase=(float *)calloc((m_framesize/2), sizeof(float));
|
lbajardsilogic@82
|
85 p_synthphase=(float *)calloc((m_framesize/2), sizeof(float));
|
lbajardsilogic@79
|
86
|
lbajardsilogic@82
|
87 peak_locations=(float *)calloc((m_framesize/2), sizeof(float));
|
lbajardsilogic@79
|
88
|
lbajardsilogic@82
|
89 hanning(window, m_framesize);
|
lbajardsilogic@82
|
90
|
lbajardsilogic@79
|
91 /***************************/
|
lbajardsilogic@79
|
92 }
|
lbajardsilogic@79
|
93
|
lbajardsilogic@79
|
94 TimeStretchFilter::~TimeStretchFilter()
|
lbajardsilogic@79
|
95 {
|
lbajardsilogic@79
|
96 /**********de-alloc***********/
|
lbajardsilogic@82
|
97 delete m_inputBuffer;
|
lbajardsilogic@82
|
98 delete FFTframe;
|
lbajardsilogic@79
|
99
|
lbajardsilogic@79
|
100 delete audioframe;
|
lbajardsilogic@79
|
101 delete prev_audioframe;
|
lbajardsilogic@79
|
102 delete window;
|
lbajardsilogic@79
|
103 delete processedframe;
|
lbajardsilogic@79
|
104 delete synthframe;
|
lbajardsilogic@79
|
105
|
lbajardsilogic@79
|
106 delete holdbuffer3;
|
lbajardsilogic@79
|
107 delete holdbuffer2;
|
lbajardsilogic@79
|
108 delete holdbuffer1;
|
lbajardsilogic@79
|
109
|
lbajardsilogic@79
|
110 delete c_mags;
|
lbajardsilogic@79
|
111 delete p_mags;
|
lbajardsilogic@79
|
112 delete c_phase;
|
lbajardsilogic@79
|
113 delete p_phase;
|
lbajardsilogic@79
|
114 delete c_synthphase;
|
lbajardsilogic@79
|
115 delete p_synthphase;
|
lbajardsilogic@79
|
116
|
lbajardsilogic@79
|
117 delete peak_locations;
|
lbajardsilogic@79
|
118
|
lbajardsilogic@82
|
119 delete outbuffer;
|
lbajardsilogic@79
|
120
|
lbajardsilogic@79
|
121 /***************************/
|
lbajardsilogic@79
|
122 }
|
lbajardsilogic@79
|
123
|
lbajardsilogic@79
|
124 TimeStretchFilter::PropertyList TimeStretchFilter::getProperties() const
|
lbajardsilogic@79
|
125 {
|
lbajardsilogic@79
|
126 PropertyList list;
|
lbajardsilogic@90
|
127 //list.push_back("Time");
|
lbajardsilogic@79
|
128 list.push_back("Pitch");
|
lbajardsilogic@79
|
129 list.push_back("Bypass");
|
lbajardsilogic@79
|
130 list.push_back("Transdetect");
|
lbajardsilogic@79
|
131 list.push_back("Peaklock");
|
lbajardsilogic@79
|
132 return list;
|
lbajardsilogic@79
|
133 }
|
lbajardsilogic@79
|
134
|
lbajardsilogic@79
|
135 QString TimeStretchFilter::getPropertyLabel(const PropertyName &name) const
|
lbajardsilogic@79
|
136 {
|
lbajardsilogic@79
|
137 if (name == "Time") return tr("Time");
|
lbajardsilogic@79
|
138 if (name == "Pitch") return tr("Pitch");
|
lbajardsilogic@79
|
139 if (name == "Bypass") return tr("Bypass Processing");
|
lbajardsilogic@79
|
140 if (name == "Transdetect") return tr("Transient Detection");
|
lbajardsilogic@79
|
141 if (name == "Peaklock") return tr("Peak Locking");
|
lbajardsilogic@79
|
142 return "";
|
lbajardsilogic@79
|
143 }
|
lbajardsilogic@79
|
144
|
lbajardsilogic@79
|
145 TimeStretchFilter::PropertyType TimeStretchFilter::getPropertyType(const PropertyName &name) const
|
lbajardsilogic@79
|
146 {
|
lbajardsilogic@79
|
147 if (name == "Time") return RangeProperty;
|
lbajardsilogic@79
|
148 if (name == "Pitch") return RangeProperty;
|
lbajardsilogic@79
|
149 if (name == "Bypass") return ToggleProperty;
|
lbajardsilogic@79
|
150 if (name == "Transdetect") return ToggleProperty;
|
lbajardsilogic@79
|
151 if (name == "Peaklock") return ToggleProperty;
|
lbajardsilogic@79
|
152 return InvalidProperty;
|
lbajardsilogic@79
|
153 }
|
lbajardsilogic@79
|
154
|
lbajardsilogic@79
|
155 int TimeStretchFilter::getPropertyRangeAndValue(const PropertyName &name,
|
lbajardsilogic@79
|
156 int *min, int *max, int *deflt) const
|
lbajardsilogic@79
|
157 {
|
lbajardsilogic@79
|
158 //!!! factor this colour handling stuff out into a colour manager class
|
lbajardsilogic@79
|
159 int val = 0;
|
lbajardsilogic@79
|
160
|
lbajardsilogic@79
|
161 if (name == "Time") {
|
lbajardsilogic@79
|
162 if (min) *min = -100;
|
lbajardsilogic@79
|
163 if (max) *max = 100;
|
lbajardsilogic@79
|
164 if (deflt) *deflt = 0;
|
lbajardsilogic@79
|
165 }
|
lbajardsilogic@79
|
166
|
lbajardsilogic@79
|
167 if (name == "Pitch") {
|
lbajardsilogic@79
|
168 if (min) *min = -100;
|
lbajardsilogic@79
|
169 if (max) *max = 100;
|
lbajardsilogic@79
|
170 if (deflt) *deflt = 0;
|
lbajardsilogic@82
|
171 }
|
lbajardsilogic@79
|
172
|
lbajardsilogic@82
|
173 if (name == "Bypass") {
|
lbajardsilogic@82
|
174 if (deflt) *deflt = 0;
|
lbajardsilogic@82
|
175 val = (m_bypass ? 1 : 0);
|
lbajardsilogic@82
|
176 }
|
lbajardsilogic@82
|
177
|
lbajardsilogic@82
|
178 if (name == "Transdetect") {
|
lbajardsilogic@82
|
179 if (deflt) *deflt = 0;
|
lbajardsilogic@82
|
180 val = (m_transcheck ? 1 : 0);
|
lbajardsilogic@82
|
181 }
|
lbajardsilogic@82
|
182
|
lbajardsilogic@82
|
183 if (name == "Peaklock") {
|
lbajardsilogic@82
|
184 if (deflt) *deflt = 0;
|
lbajardsilogic@82
|
185 val = (m_peakcheck ? 1 : 0);
|
lbajardsilogic@82
|
186 }
|
lbajardsilogic@79
|
187
|
lbajardsilogic@79
|
188 return val;
|
lbajardsilogic@79
|
189 }
|
lbajardsilogic@79
|
190
|
lbajardsilogic@79
|
191 QString TimeStretchFilter::getPropertyValueLabel(const PropertyName &name,
|
lbajardsilogic@79
|
192 int value) const
|
lbajardsilogic@79
|
193 {
|
lbajardsilogic@79
|
194 if (name == "Time") {
|
lbajardsilogic@79
|
195 if (value == -100)
|
lbajardsilogic@79
|
196 return tr("Slow");
|
lbajardsilogic@79
|
197 if (value == 100)
|
lbajardsilogic@79
|
198 return tr("Fast");
|
lbajardsilogic@79
|
199 }
|
lbajardsilogic@79
|
200 return tr("<unknown>");
|
lbajardsilogic@79
|
201 }
|
lbajardsilogic@79
|
202
|
lbajardsilogic@79
|
203 void TimeStretchFilter::setProperty(const PropertyName &name, int value)
|
lbajardsilogic@79
|
204 {
|
lbajardsilogic@79
|
205 if (name == "Time") {
|
lbajardsilogic@82
|
206 float tmaxfactor=2;
|
lbajardsilogic@79
|
207 if (value > 0){
|
lbajardsilogic@82
|
208 hopfactor=1.0+((tmaxfactor-1)*(((float)value)/100));
|
lbajardsilogic@79
|
209 }
|
lbajardsilogic@79
|
210 if (value < 0){
|
lbajardsilogic@82
|
211 hopfactor=1.0/(1.0+((tmaxfactor-1)*(-((float)value)/100)));
|
lbajardsilogic@79
|
212 }
|
lbajardsilogic@79
|
213 if(value == 0){
|
lbajardsilogic@79
|
214 hopfactor=1;
|
lbajardsilogic@79
|
215 }
|
lbajardsilogic@79
|
216 } else if (name == "Pitch") {
|
lbajardsilogic@82
|
217 float pmaxfactor=2;
|
lbajardsilogic@79
|
218 if (value > 0){
|
lbajardsilogic@82
|
219 m_interpfactor=1.0+((pmaxfactor-1)*(((float)value)/100));
|
lbajardsilogic@79
|
220 }
|
lbajardsilogic@79
|
221 if (value < 0){
|
lbajardsilogic@82
|
222 m_interpfactor=1.0/(1.0+((pmaxfactor-1)*(-((float)value)/100)));
|
lbajardsilogic@79
|
223 }
|
lbajardsilogic@79
|
224 if(value == 0){
|
lbajardsilogic@82
|
225 m_interpfactor=1;
|
lbajardsilogic@79
|
226 }
|
lbajardsilogic@79
|
227 } else if (name == "Bypass"){
|
lbajardsilogic@79
|
228 m_bypass = (value > 0) ? true : false;
|
lbajardsilogic@79
|
229 } else if (name == "Transdetect"){
|
lbajardsilogic@79
|
230 m_transcheck = (value > 0) ? true : false;
|
lbajardsilogic@79
|
231 } else if (name == "Peaklock"){
|
lbajardsilogic@79
|
232 m_peakcheck = (value > 0) ? true : false;
|
lbajardsilogic@79
|
233 }
|
lbajardsilogic@79
|
234
|
lbajardsilogic@79
|
235 }
|
lbajardsilogic@79
|
236
|
lbajardsilogic@79
|
237 void TimeStretchFilter::putInput(float **input, size_t samples)
|
lbajardsilogic@82
|
238 {
|
lbajardsilogic@82
|
239 int dd;
|
lbajardsilogic@82
|
240 float sampdiff;
|
lbajardsilogic@82
|
241 float difratio;
|
lbajardsilogic@82
|
242 float interpsample;
|
lbajardsilogic@82
|
243
|
lbajardsilogic@82
|
244 bool drum = 0;
|
lbajardsilogic@82
|
245 float drumthresh = 65;
|
lbajardsilogic@82
|
246 int transhold = 0;
|
lbajardsilogic@82
|
247
|
lbajardsilogic@82
|
248 if (samples < floor(m_framesize*m_interpfactor + 1))
|
lbajardsilogic@82
|
249 return;
|
lbajardsilogic@82
|
250
|
lbajardsilogic@84
|
251 int channel = getSourceChannelCount();
|
lbajardsilogic@82
|
252
|
lbajardsilogic@82
|
253 for (int i=0; i<samples; i++){
|
lbajardsilogic@82
|
254 if (channel > 1)
|
lbajardsilogic@82
|
255 m_inputBuffer[i] = (input[0][i] + input[1][i]) /2;
|
lbajardsilogic@82
|
256 else
|
lbajardsilogic@82
|
257 m_inputBuffer[i] = input[0][i];
|
lbajardsilogic@79
|
258 }
|
lbajardsilogic@82
|
259
|
lbajardsilogic@82
|
260 for (int i = 0; i<(m_framesize); i++)
|
lbajardsilogic@79
|
261 {
|
lbajardsilogic@79
|
262
|
lbajardsilogic@79
|
263 //This block was specifically written to do resampling interpolation for crude pitch shifting
|
lbajardsilogic@79
|
264 //if it's not being used the audioframe line after the else should be used which is also used in bypass mode
|
lbajardsilogic@79
|
265 //At
|
lbajardsilogic@79
|
266
|
lbajardsilogic@79
|
267 if (m_bypass == false) {
|
lbajardsilogic@82
|
268 dd = floor(double(i*m_interpfactor));
|
lbajardsilogic@82
|
269 difratio = (double(i*m_interpfactor)) - floor(double(i*m_interpfactor));
|
lbajardsilogic@82
|
270
|
lbajardsilogic@79
|
271 // this block loads a frame as normal
|
lbajardsilogic@82
|
272 sampdiff=m_inputBuffer[dd+1]-m_inputBuffer[dd];
|
lbajardsilogic@82
|
273 interpsample = (difratio*sampdiff)+m_inputBuffer[dd];
|
lbajardsilogic@82
|
274 audioframe[i] = (interpsample)*window[i];
|
lbajardsilogic@79
|
275 }
|
lbajardsilogic@79
|
276 else {
|
lbajardsilogic@82
|
277 audioframe[i] = (m_inputBuffer[i+1])*window[i];
|
lbajardsilogic@79
|
278 processedframe[i] = (audioframe[i])*window[i];
|
lbajardsilogic@79
|
279 }
|
lbajardsilogic@79
|
280 }
|
lbajardsilogic@79
|
281
|
lbajardsilogic@82
|
282 FFTReal fft_object (m_framesize);
|
lbajardsilogic@79
|
283
|
lbajardsilogic@79
|
284 if (m_bypass == false)
|
lbajardsilogic@79
|
285 {
|
lbajardsilogic@79
|
286 fft_object.do_fft (FFTframe,audioframe);
|
lbajardsilogic@79
|
287
|
lbajardsilogic@82
|
288 cart2pol(FFTframe, c_mags, c_phase, m_framesize);
|
lbajardsilogic@79
|
289
|
lbajardsilogic@79
|
290 //--------------------------------------------
|
lbajardsilogic@79
|
291
|
lbajardsilogic@79
|
292 fft_object.do_fft (FFTframe,prev_audioframe);
|
lbajardsilogic@79
|
293
|
lbajardsilogic@82
|
294 cart2pol(FFTframe, p_mags, p_phase, m_framesize);
|
lbajardsilogic@79
|
295
|
lbajardsilogic@82
|
296 drum=transient_detect(c_mags, c_mags, p_mags, p_mags, drumthresh, m_framesize);
|
lbajardsilogic@79
|
297
|
lbajardsilogic@79
|
298
|
lbajardsilogic@79
|
299 if (m_transcheck)
|
lbajardsilogic@79
|
300 {
|
lbajardsilogic@79
|
301
|
lbajardsilogic@79
|
302 if (drum && transhold==0){
|
lbajardsilogic@82
|
303 cur2last(c_phase, c_synthphase, p_synthphase, m_framesize);
|
lbajardsilogic@79
|
304 transhold=4;
|
lbajardsilogic@79
|
305 }
|
lbajardsilogic@79
|
306 else{
|
lbajardsilogic@79
|
307 if(m_peakcheck){
|
lbajardsilogic@82
|
308 rotatephases_peaklocked(c_phase, p_phase, c_synthphase, p_synthphase, m_framesize, m_interpfactor);
|
lbajardsilogic@79
|
309 }
|
lbajardsilogic@79
|
310 else{
|
lbajardsilogic@82
|
311 rotatephases(c_phase, p_phase, c_synthphase, p_synthphase, m_framesize, m_interpfactor);
|
lbajardsilogic@79
|
312 }
|
lbajardsilogic@79
|
313 }
|
lbajardsilogic@79
|
314 }
|
lbajardsilogic@79
|
315 else
|
lbajardsilogic@79
|
316 {
|
lbajardsilogic@79
|
317 if(m_peakcheck){
|
lbajardsilogic@82
|
318 rotatephases_peaklocked(c_phase, p_phase, c_synthphase, p_synthphase, m_framesize, m_interpfactor);
|
lbajardsilogic@79
|
319 }
|
lbajardsilogic@79
|
320 else{
|
lbajardsilogic@82
|
321 rotatephases(c_phase, p_phase, c_synthphase, p_synthphase, m_framesize, m_interpfactor);
|
lbajardsilogic@79
|
322 }
|
lbajardsilogic@79
|
323 }
|
lbajardsilogic@79
|
324
|
lbajardsilogic@79
|
325 if(transhold != 0){
|
lbajardsilogic@79
|
326 transhold=transhold-1;
|
lbajardsilogic@79
|
327 }
|
lbajardsilogic@79
|
328
|
lbajardsilogic@79
|
329 drum = 0;
|
lbajardsilogic@79
|
330
|
lbajardsilogic@82
|
331 pol2cart(FFTframe, c_mags, c_synthphase, m_framesize);
|
lbajardsilogic@79
|
332
|
lbajardsilogic@79
|
333 fft_object.do_ifft (FFTframe,processedframe);
|
lbajardsilogic@79
|
334 fft_object.rescale (processedframe); //VIP######## I have edited this function to do rewindowing also######
|
lbajardsilogic@79
|
335 }
|
lbajardsilogic@79
|
336
|
lbajardsilogic@82
|
337 for (int p = 0; p<(m_framesize); p++){
|
lbajardsilogic@79
|
338 processedframe[p]=processedframe[p]*window[p];
|
lbajardsilogic@79
|
339 }
|
lbajardsilogic@79
|
340
|
lbajardsilogic@82
|
341 for (int j = 0; j<(m_framesize); j++)
|
lbajardsilogic@79
|
342 {
|
lbajardsilogic@79
|
343 //This block deals with the buffers for a 75% overlap scheme
|
lbajardsilogic@79
|
344
|
lbajardsilogic@82
|
345 if (j < m_framesize/4){
|
lbajardsilogic@79
|
346 outbuffer[j]=(processedframe[j]+holdbuffer1[j]+holdbuffer2[j]+holdbuffer3[j])*0.5;
|
lbajardsilogic@82
|
347 holdbuffer1[j]=holdbuffer2[j+(m_framesize/4)];
|
lbajardsilogic@79
|
348 }
|
lbajardsilogic@79
|
349
|
lbajardsilogic@82
|
350 if (j < m_framesize/2){
|
lbajardsilogic@82
|
351 holdbuffer2[j]=holdbuffer3[j+(m_framesize/4)];
|
lbajardsilogic@79
|
352 }
|
lbajardsilogic@79
|
353
|
lbajardsilogic@82
|
354 if (j < m_framesize*0.75){
|
lbajardsilogic@82
|
355 holdbuffer3[j]=processedframe[j+(m_framesize/4)];
|
lbajardsilogic@79
|
356 }
|
lbajardsilogic@79
|
357 }
|
lbajardsilogic@82
|
358
|
lbajardsilogic@82
|
359 for (int i = 0; i<(m_framesize); i++)
|
lbajardsilogic@82
|
360 {
|
lbajardsilogic@82
|
361 prev_audioframe[i] = audioframe[i];
|
lbajardsilogic@82
|
362 }
|
lbajardsilogic@79
|
363 }
|
lbajardsilogic@79
|
364
|
lbajardsilogic@79
|
365 void TimeStretchFilter::getOutput(float **output, size_t samples)
|
lbajardsilogic@79
|
366 {
|
lbajardsilogic@82
|
367 if (samples > m_framesize/4)
|
lbajardsilogic@82
|
368 return;
|
lbajardsilogic@82
|
369
|
lbajardsilogic@84
|
370 int channel = getSourceChannelCount();
|
lbajardsilogic@82
|
371
|
lbajardsilogic@82
|
372 for (int i=0; i<samples; i++){
|
lbajardsilogic@82
|
373 output[0][i] = outbuffer[i];
|
lbajardsilogic@82
|
374 if (channel > 1)
|
lbajardsilogic@82
|
375 output[1][i] = outbuffer[i];
|
lbajardsilogic@82
|
376 }
|
lbajardsilogic@82
|
377 }
|
lbajardsilogic@82
|
378
|
lbajardsilogic@82
|
379 size_t TimeStretchFilter::getRequiredInputSamples(size_t outputSamplesNeeded)
|
lbajardsilogic@82
|
380 {
|
lbajardsilogic@82
|
381 // max (m_framesize, outputSamplesNeeded*2)
|
lbajardsilogic@82
|
382 size_t need = max( floor(m_framesize*m_interpfactor + 1), outputSamplesNeeded*2);
|
lbajardsilogic@79
|
383
|
lbajardsilogic@82
|
384 return need;
|
lbajardsilogic@79
|
385 } |