annotate src/rubberband-1.8.1/ladspa/RubberBandPitchShifter.cpp @ 23:619f715526df sv_v2.1

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