annotate src/rubberband-1.8.1/ladspa/RubberBandPitchShifter.cpp @ 148:b4bfdf10c4b3

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