comparison src/rubberband-1.8.1/ladspa/RubberBandPitchShifter.cpp @ 95:89f5e221ed7b

Add FFTW3
author Chris Cannam <cannam@all-day-breakfast.com>
date Wed, 20 Mar 2013 15:35:50 +0000
parents
children
comparison
equal deleted inserted replaced
94:d278df1123f9 95:89f5e221ed7b
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 Rubber Band Library
5 An audio time-stretching and pitch-shifting library.
6 Copyright 2007-2012 Particular Programs Ltd.
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of the
11 License, or (at your option) any later version. See the file
12 COPYING included with this distribution for more information.
13
14 Alternatively, if you have a valid commercial licence for the
15 Rubber Band Library obtained by agreement with the copyright
16 holders, you may redistribute and/or modify it under the terms
17 described in that licence.
18
19 If you wish to distribute code using the Rubber Band Library
20 under terms other than those of the GNU General Public License,
21 you must obtain a valid commercial licence before doing so.
22 */
23
24 #include "RubberBandPitchShifter.h"
25
26 #include "RubberBandStretcher.h"
27
28 #include <iostream>
29 #include <cmath>
30
31 using namespace RubberBand;
32
33 using std::cout;
34 using std::cerr;
35 using std::endl;
36 using std::min;
37
38 const char *const
39 RubberBandPitchShifter::portNamesMono[PortCountMono] =
40 {
41 "latency",
42 "Cents",
43 "Semitones",
44 "Octaves",
45 "Crispness",
46 "Formant Preserving",
47 "Faster",
48 "Input",
49 "Output"
50 };
51
52 const char *const
53 RubberBandPitchShifter::portNamesStereo[PortCountStereo] =
54 {
55 "latency",
56 "Cents",
57 "Semitones",
58 "Octaves",
59 "Crispness",
60 "Formant Preserving",
61 "Faster",
62 "Input L",
63 "Output L",
64 "Input R",
65 "Output R"
66 };
67
68 const LADSPA_PortDescriptor
69 RubberBandPitchShifter::portsMono[PortCountMono] =
70 {
71 LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL,
72 LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL,
73 LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL,
74 LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL,
75 LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL,
76 LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL,
77 LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL,
78 LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO,
79 LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO
80 };
81
82 const LADSPA_PortDescriptor
83 RubberBandPitchShifter::portsStereo[PortCountStereo] =
84 {
85 LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL,
86 LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL,
87 LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL,
88 LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL,
89 LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL,
90 LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL,
91 LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL,
92 LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO,
93 LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
94 LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO,
95 LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO
96 };
97
98 const LADSPA_PortRangeHint
99 RubberBandPitchShifter::hintsMono[PortCountMono] =
100 {
101 { 0, 0, 0 }, // latency
102 { LADSPA_HINT_DEFAULT_0 | // cents
103 LADSPA_HINT_BOUNDED_BELOW |
104 LADSPA_HINT_BOUNDED_ABOVE,
105 -100.0, 100.0 },
106 { LADSPA_HINT_DEFAULT_0 | // semitones
107 LADSPA_HINT_BOUNDED_BELOW |
108 LADSPA_HINT_BOUNDED_ABOVE |
109 LADSPA_HINT_INTEGER,
110 -12.0, 12.0 },
111 { LADSPA_HINT_DEFAULT_0 | // octaves
112 LADSPA_HINT_BOUNDED_BELOW |
113 LADSPA_HINT_BOUNDED_ABOVE |
114 LADSPA_HINT_INTEGER,
115 -3.0, 3.0 },
116 { LADSPA_HINT_DEFAULT_MAXIMUM | // crispness
117 LADSPA_HINT_BOUNDED_BELOW |
118 LADSPA_HINT_BOUNDED_ABOVE |
119 LADSPA_HINT_INTEGER,
120 0.0, 3.0 },
121 { LADSPA_HINT_DEFAULT_0 | // formant preserving
122 LADSPA_HINT_BOUNDED_BELOW |
123 LADSPA_HINT_BOUNDED_ABOVE |
124 LADSPA_HINT_TOGGLED,
125 0.0, 1.0 },
126 { LADSPA_HINT_DEFAULT_0 | // fast
127 LADSPA_HINT_BOUNDED_BELOW |
128 LADSPA_HINT_BOUNDED_ABOVE |
129 LADSPA_HINT_TOGGLED,
130 0.0, 1.0 },
131 { 0, 0, 0 },
132 { 0, 0, 0 }
133 };
134
135 const LADSPA_PortRangeHint
136 RubberBandPitchShifter::hintsStereo[PortCountStereo] =
137 {
138 { 0, 0, 0 }, // latency
139 { LADSPA_HINT_DEFAULT_0 | // cents
140 LADSPA_HINT_BOUNDED_BELOW |
141 LADSPA_HINT_BOUNDED_ABOVE,
142 -100.0, 100.0 },
143 { LADSPA_HINT_DEFAULT_0 | // semitones
144 LADSPA_HINT_BOUNDED_BELOW |
145 LADSPA_HINT_BOUNDED_ABOVE |
146 LADSPA_HINT_INTEGER,
147 -12.0, 12.0 },
148 { LADSPA_HINT_DEFAULT_0 | // octaves
149 LADSPA_HINT_BOUNDED_BELOW |
150 LADSPA_HINT_BOUNDED_ABOVE |
151 LADSPA_HINT_INTEGER,
152 -3.0, 3.0 },
153 { LADSPA_HINT_DEFAULT_MAXIMUM | // crispness
154 LADSPA_HINT_BOUNDED_BELOW |
155 LADSPA_HINT_BOUNDED_ABOVE |
156 LADSPA_HINT_INTEGER,
157 0.0, 3.0 },
158 { LADSPA_HINT_DEFAULT_0 | // formant preserving
159 LADSPA_HINT_BOUNDED_BELOW |
160 LADSPA_HINT_BOUNDED_ABOVE |
161 LADSPA_HINT_TOGGLED,
162 0.0, 1.0 },
163 { LADSPA_HINT_DEFAULT_0 | // fast
164 LADSPA_HINT_BOUNDED_BELOW |
165 LADSPA_HINT_BOUNDED_ABOVE |
166 LADSPA_HINT_TOGGLED,
167 0.0, 1.0 },
168 { 0, 0, 0 },
169 { 0, 0, 0 },
170 { 0, 0, 0 },
171 { 0, 0, 0 }
172 };
173
174 const LADSPA_Properties
175 RubberBandPitchShifter::properties = LADSPA_PROPERTY_HARD_RT_CAPABLE;
176
177 const LADSPA_Descriptor
178 RubberBandPitchShifter::ladspaDescriptorMono =
179 {
180 2979, // "Unique" ID
181 "rubberband-pitchshifter-mono", // Label
182 properties,
183 "Rubber Band Mono Pitch Shifter", // Name
184 "Breakfast Quay",
185 "GPL",
186 PortCountMono,
187 portsMono,
188 portNamesMono,
189 hintsMono,
190 0, // Implementation data
191 instantiate,
192 connectPort,
193 activate,
194 run,
195 0, // Run adding
196 0, // Set run adding gain
197 deactivate,
198 cleanup
199 };
200
201 const LADSPA_Descriptor
202 RubberBandPitchShifter::ladspaDescriptorStereo =
203 {
204 9792, // "Unique" ID
205 "rubberband-pitchshifter-stereo", // Label
206 properties,
207 "Rubber Band Stereo Pitch Shifter", // Name
208 "Breakfast Quay",
209 "GPL",
210 PortCountStereo,
211 portsStereo,
212 portNamesStereo,
213 hintsStereo,
214 0, // Implementation data
215 instantiate,
216 connectPort,
217 activate,
218 run,
219 0, // Run adding
220 0, // Set run adding gain
221 deactivate,
222 cleanup
223 };
224
225 const LADSPA_Descriptor *
226 RubberBandPitchShifter::getDescriptor(unsigned long index)
227 {
228 if (index == 0) return &ladspaDescriptorMono;
229 if (index == 1) return &ladspaDescriptorStereo;
230 else return 0;
231 }
232
233 RubberBandPitchShifter::RubberBandPitchShifter(int sampleRate, size_t channels) :
234 m_latency(0),
235 m_cents(0),
236 m_semitones(0),
237 m_octaves(0),
238 m_crispness(0),
239 m_formant(0),
240 m_fast(0),
241 m_ratio(1.0),
242 m_prevRatio(1.0),
243 m_currentCrispness(-1),
244 m_currentFormant(false),
245 m_currentFast(false),
246 m_blockSize(1024),
247 m_reserve(1024),
248 m_minfill(0),
249 m_stretcher(new RubberBandStretcher
250 (sampleRate, channels,
251 RubberBandStretcher::OptionProcessRealTime |
252 RubberBandStretcher::OptionPitchHighConsistency)),
253 m_sampleRate(sampleRate),
254 m_channels(channels)
255 {
256 for (size_t c = 0; c < m_channels; ++c) {
257
258 m_input[c] = 0;
259 m_output[c] = 0;
260
261 int bufsize = m_blockSize + m_reserve + 8192;
262
263 m_outputBuffer[c] = new RingBuffer<float>(bufsize);
264
265 m_scratch[c] = new float[bufsize];
266 for (int i = 0; i < bufsize; ++i) m_scratch[c][i] = 0.f;
267 }
268
269 activateImpl();
270 }
271
272 RubberBandPitchShifter::~RubberBandPitchShifter()
273 {
274 delete m_stretcher;
275 for (size_t c = 0; c < m_channels; ++c) {
276 delete m_outputBuffer[c];
277 delete[] m_scratch[c];
278 }
279 }
280
281 LADSPA_Handle
282 RubberBandPitchShifter::instantiate(const LADSPA_Descriptor *desc, unsigned long rate)
283 {
284 if (desc->PortCount == ladspaDescriptorMono.PortCount) {
285 return new RubberBandPitchShifter(rate, 1);
286 } else if (desc->PortCount == ladspaDescriptorStereo.PortCount) {
287 return new RubberBandPitchShifter(rate, 2);
288 }
289 return 0;
290 }
291
292 void
293 RubberBandPitchShifter::connectPort(LADSPA_Handle handle,
294 unsigned long port, LADSPA_Data *location)
295 {
296 RubberBandPitchShifter *shifter = (RubberBandPitchShifter *)handle;
297
298 float **ports[PortCountStereo] = {
299 &shifter->m_latency,
300 &shifter->m_cents,
301 &shifter->m_semitones,
302 &shifter->m_octaves,
303 &shifter->m_crispness,
304 &shifter->m_formant,
305 &shifter->m_fast,
306 &shifter->m_input[0],
307 &shifter->m_output[0],
308 &shifter->m_input[1],
309 &shifter->m_output[1]
310 };
311
312 if (shifter->m_channels == 1) {
313 if (port >= PortCountMono) return;
314 } else {
315 if (port >= PortCountStereo) return;
316 }
317
318 *ports[port] = (float *)location;
319
320 if (shifter->m_latency) {
321 *(shifter->m_latency) =
322 float(shifter->m_stretcher->getLatency() + shifter->m_reserve);
323 }
324 }
325
326 void
327 RubberBandPitchShifter::activate(LADSPA_Handle handle)
328 {
329 RubberBandPitchShifter *shifter = (RubberBandPitchShifter *)handle;
330 shifter->activateImpl();
331 }
332
333 void
334 RubberBandPitchShifter::activateImpl()
335 {
336 updateRatio();
337 m_prevRatio = m_ratio;
338 m_stretcher->reset();
339 m_stretcher->setPitchScale(m_ratio);
340
341 for (size_t c = 0; c < m_channels; ++c) {
342 m_outputBuffer[c]->reset();
343 m_outputBuffer[c]->zero(m_reserve);
344 }
345
346 m_minfill = 0;
347
348 // prime stretcher
349 // for (int i = 0; i < 8; ++i) {
350 // int reqd = m_stretcher->getSamplesRequired();
351 // m_stretcher->process(m_scratch, reqd, false);
352 // int avail = m_stretcher->available();
353 // if (avail > 0) {
354 // m_stretcher->retrieve(m_scratch, avail);
355 // }
356 // }
357 }
358
359 void
360 RubberBandPitchShifter::run(LADSPA_Handle handle, unsigned long samples)
361 {
362 RubberBandPitchShifter *shifter = (RubberBandPitchShifter *)handle;
363 shifter->runImpl(samples);
364 }
365
366 void
367 RubberBandPitchShifter::updateRatio()
368 {
369 double oct = (m_octaves ? *m_octaves : 0.0);
370 oct += (m_semitones ? *m_semitones : 0.0) / 12;
371 oct += (m_cents ? *m_cents : 0.0) / 1200;
372 m_ratio = pow(2.0, oct);
373 }
374
375 void
376 RubberBandPitchShifter::updateCrispness()
377 {
378 if (!m_crispness) return;
379
380 int c = lrintf(*m_crispness);
381 if (c == m_currentCrispness) return;
382 if (c < 0 || c > 3) return;
383 RubberBandStretcher *s = m_stretcher;
384
385 switch (c) {
386 case 0:
387 s->setPhaseOption(RubberBandStretcher::OptionPhaseIndependent);
388 s->setTransientsOption(RubberBandStretcher::OptionTransientsSmooth);
389 break;
390 case 1:
391 s->setPhaseOption(RubberBandStretcher::OptionPhaseLaminar);
392 s->setTransientsOption(RubberBandStretcher::OptionTransientsSmooth);
393 break;
394 case 2:
395 s->setPhaseOption(RubberBandStretcher::OptionPhaseLaminar);
396 s->setTransientsOption(RubberBandStretcher::OptionTransientsMixed);
397 break;
398 case 3:
399 s->setPhaseOption(RubberBandStretcher::OptionPhaseLaminar);
400 s->setTransientsOption(RubberBandStretcher::OptionTransientsCrisp);
401 break;
402 }
403
404 m_currentCrispness = c;
405 }
406
407 void
408 RubberBandPitchShifter::updateFormant()
409 {
410 if (!m_formant) return;
411
412 bool f = (*m_formant > 0.5f);
413 if (f == m_currentFormant) return;
414
415 RubberBandStretcher *s = m_stretcher;
416
417 s->setFormantOption(f ?
418 RubberBandStretcher::OptionFormantPreserved :
419 RubberBandStretcher::OptionFormantShifted);
420
421 m_currentFormant = f;
422 }
423
424 void
425 RubberBandPitchShifter::updateFast()
426 {
427 if (!m_fast) return;
428
429 bool f = (*m_fast > 0.5f);
430 if (f == m_currentFast) return;
431
432 RubberBandStretcher *s = m_stretcher;
433
434 s->setPitchOption(f ?
435 RubberBandStretcher::OptionPitchHighSpeed :
436 RubberBandStretcher::OptionPitchHighConsistency);
437
438 m_currentFast = f;
439 }
440
441 void
442 RubberBandPitchShifter::runImpl(unsigned long insamples)
443 {
444 unsigned long offset = 0;
445
446 // We have to break up the input into chunks like this because
447 // insamples could be arbitrarily large and our output buffer is
448 // of limited size
449
450 while (offset < insamples) {
451
452 unsigned long block = (unsigned long)m_blockSize;
453 if (block + offset > insamples) block = insamples - offset;
454
455 runImpl(block, offset);
456
457 offset += block;
458 }
459 }
460
461 void
462 RubberBandPitchShifter::runImpl(unsigned long insamples, unsigned long offset)
463 {
464 // cerr << "RubberBandPitchShifter::runImpl(" << insamples << ")" << endl;
465
466 // static int incount = 0, outcount = 0;
467
468 updateRatio();
469 if (m_ratio != m_prevRatio) {
470 m_stretcher->setPitchScale(m_ratio);
471 m_prevRatio = m_ratio;
472 }
473
474 if (m_latency) {
475 *m_latency = float(m_stretcher->getLatency() + m_reserve);
476 // cerr << "latency = " << *m_latency << endl;
477 }
478
479 updateCrispness();
480 updateFormant();
481 updateFast();
482
483 const int samples = insamples;
484 int processed = 0;
485 size_t outTotal = 0;
486
487 float *ptrs[2];
488
489 int rs = m_outputBuffer[0]->getReadSpace();
490 if (rs < int(m_minfill)) {
491 // cerr << "temporary expansion (have " << rs << ", want " << m_reserve << ")" << endl;
492 m_stretcher->setTimeRatio(1.1); // fill up temporarily
493 } else if (rs > 8192) {
494 // cerr << "temporary reduction (have " << rs << ", want " << m_reserve << ")" << endl;
495 m_stretcher->setTimeRatio(0.9); // reduce temporarily
496 } else {
497 m_stretcher->setTimeRatio(1.0);
498 }
499
500 while (processed < samples) {
501
502 // never feed more than the minimum necessary number of
503 // samples at a time; ensures nothing will overflow internally
504 // and we don't need to call setMaxProcessSize
505
506 int toCauseProcessing = m_stretcher->getSamplesRequired();
507 int inchunk = min(samples - processed, toCauseProcessing);
508 for (size_t c = 0; c < m_channels; ++c) {
509 ptrs[c] = &(m_input[c][offset + processed]);
510 }
511 m_stretcher->process(ptrs, inchunk, false);
512 processed += inchunk;
513
514 int avail = m_stretcher->available();
515 int writable = m_outputBuffer[0]->getWriteSpace();
516 int outchunk = min(avail, writable);
517 size_t actual = m_stretcher->retrieve(m_scratch, outchunk);
518 outTotal += actual;
519
520 // incount += inchunk;
521 // outcount += actual;
522
523 // cout << "avail: " << avail << ", outchunk = " << outchunk;
524 // if (actual != outchunk) cout << " (" << actual << ")";
525 // cout << endl;
526
527 outchunk = actual;
528
529 for (size_t c = 0; c < m_channels; ++c) {
530 if (int(m_outputBuffer[c]->getWriteSpace()) < outchunk) {
531 cerr << "RubberBandPitchShifter::runImpl: buffer overrun: chunk = " << outchunk << ", space = " << m_outputBuffer[c]->getWriteSpace() << endl;
532 }
533 m_outputBuffer[c]->write(m_scratch[c], outchunk);
534 }
535 }
536
537 for (size_t c = 0; c < m_channels; ++c) {
538 int toRead = m_outputBuffer[c]->getReadSpace();
539 if (toRead < samples && c == 0) {
540 cerr << "RubberBandPitchShifter::runImpl: buffer underrun: required = " << samples << ", available = " << toRead << endl;
541 }
542 int chunk = min(toRead, samples);
543 m_outputBuffer[c]->read(&(m_output[c][offset]), chunk);
544 }
545
546 if (m_minfill == 0) {
547 m_minfill = m_outputBuffer[0]->getReadSpace();
548 // cerr << "minfill = " << m_minfill << endl;
549 }
550 }
551
552 void
553 RubberBandPitchShifter::deactivate(LADSPA_Handle handle)
554 {
555 activate(handle); // both functions just reset the plugin
556 }
557
558 void
559 RubberBandPitchShifter::cleanup(LADSPA_Handle handle)
560 {
561 delete (RubberBandPitchShifter *)handle;
562 }
563