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