2007-11-06 21:41:16 +00:00
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
/*
2012-09-09 16:57:42 +01:00
Rubber Band Library
2007-11-06 21:41:16 +00:00
An audio time - stretching and pitch - shifting library .
2022-01-04 17:50:15 +00:00
Copyright 2007 - 2022 Particular Programs Ltd .
2012-09-09 16:57:42 +01:00
2007-11-06 21:41:16 +00:00
This program is free software ; you can redistribute it and / or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation ; either version 2 of the
License , or ( at your option ) any later version . See the file
COPYING included with this distribution for more information .
2012-09-09 16:57:42 +01:00
Alternatively , if you have a valid commercial licence for the
Rubber Band Library obtained by agreement with the copyright
holders , you may redistribute and / or modify it under the terms
described in that licence .
If you wish to distribute code using the Rubber Band Library
under terms other than those of the GNU General Public License ,
you must obtain a valid commercial licence before doing so .
2007-11-06 21:41:16 +00:00
*/
# include "RubberBandPitchShifter.h"
# include "RubberBandStretcher.h"
# include <iostream>
# include <cmath>
2007-11-21 19:57:49 +00:00
using namespace RubberBand ;
2008-07-06 19:24:53 +00:00
using std : : cout ;
using std : : cerr ;
using std : : endl ;
using std : : min ;
2007-11-06 21:41:16 +00:00
const char * const
RubberBandPitchShifter : : portNamesMono [ PortCountMono ] =
{
2008-01-28 17:24:55 +00:00
" latency " ,
2007-11-06 21:41:16 +00:00
" Cents " ,
" Semitones " ,
" Octaves " ,
2007-11-21 19:57:49 +00:00
" Crispness " ,
2008-07-04 19:31:23 +00:00
" Formant Preserving " ,
2021-05-14 11:35:08 +01:00
" Wet-Dry Mix " ,
2007-11-06 21:41:16 +00:00
" Input " ,
" Output "
} ;
const char * const
RubberBandPitchShifter : : portNamesStereo [ PortCountStereo ] =
{
2008-01-28 17:24:55 +00:00
" latency " ,
2007-11-06 21:41:16 +00:00
" Cents " ,
" Semitones " ,
" Octaves " ,
2007-11-21 19:57:49 +00:00
" Crispness " ,
2008-07-04 19:31:23 +00:00
" Formant Preserving " ,
2021-05-14 11:35:08 +01:00
" Wet-Dry Mix " ,
2007-11-06 21:41:16 +00:00
" Input L " ,
" Output L " ,
" Input R " ,
" Output R "
} ;
const LADSPA_PortDescriptor
RubberBandPitchShifter : : portsMono [ PortCountMono ] =
{
LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL ,
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL ,
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL ,
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL ,
2007-11-21 19:57:49 +00:00
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL ,
2008-05-22 16:54:27 +00:00
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL ,
2008-07-04 19:31:23 +00:00
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL ,
2007-11-06 21:41:16 +00:00
LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO ,
LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO
} ;
const LADSPA_PortDescriptor
RubberBandPitchShifter : : portsStereo [ PortCountStereo ] =
{
LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL ,
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL ,
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL ,
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL ,
2007-11-21 19:57:49 +00:00
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL ,
2008-05-22 16:54:27 +00:00
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL ,
2008-07-04 19:31:23 +00:00
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL ,
2007-11-06 21:41:16 +00:00
LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO ,
LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO ,
LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO ,
LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO
} ;
const LADSPA_PortRangeHint
RubberBandPitchShifter : : hintsMono [ PortCountMono ] =
{
2008-07-04 14:19:32 +00:00
{ 0 , 0 , 0 } , // latency
{ LADSPA_HINT_DEFAULT_0 | // cents
2007-11-06 21:41:16 +00:00
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE ,
- 100.0 , 100.0 } ,
2008-07-04 14:19:32 +00:00
{ LADSPA_HINT_DEFAULT_0 | // semitones
2007-11-06 21:41:16 +00:00
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_INTEGER ,
- 12.0 , 12.0 } ,
2008-07-04 14:19:32 +00:00
{ LADSPA_HINT_DEFAULT_0 | // octaves
2007-11-06 21:41:16 +00:00
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_INTEGER ,
2021-05-14 14:26:52 +01:00
- 2.0 , 2.0 } ,
2008-07-04 14:19:32 +00:00
{ LADSPA_HINT_DEFAULT_MAXIMUM | // crispness
2007-11-21 19:57:49 +00:00
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_INTEGER ,
0.0 , 3.0 } ,
2008-07-04 14:19:32 +00:00
{ LADSPA_HINT_DEFAULT_0 | // formant preserving
2008-05-22 16:54:27 +00:00
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_TOGGLED ,
0.0 , 1.0 } ,
2021-05-14 11:35:08 +01:00
{ LADSPA_HINT_DEFAULT_0 | // wet-dry mix
2008-07-04 19:31:23 +00:00
LADSPA_HINT_BOUNDED_BELOW |
2021-05-14 11:35:08 +01:00
LADSPA_HINT_BOUNDED_ABOVE ,
2008-07-04 19:31:23 +00:00
0.0 , 1.0 } ,
2007-11-06 21:41:16 +00:00
{ 0 , 0 , 0 } ,
{ 0 , 0 , 0 }
} ;
const LADSPA_PortRangeHint
RubberBandPitchShifter : : hintsStereo [ PortCountStereo ] =
{
2008-07-04 14:19:32 +00:00
{ 0 , 0 , 0 } , // latency
{ LADSPA_HINT_DEFAULT_0 | // cents
2007-11-06 21:41:16 +00:00
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE ,
- 100.0 , 100.0 } ,
2008-07-04 14:19:32 +00:00
{ LADSPA_HINT_DEFAULT_0 | // semitones
2007-11-06 21:41:16 +00:00
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_INTEGER ,
- 12.0 , 12.0 } ,
2008-07-04 14:19:32 +00:00
{ LADSPA_HINT_DEFAULT_0 | // octaves
2007-11-06 21:41:16 +00:00
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_INTEGER ,
2021-05-14 14:26:52 +01:00
- 2.0 , 2.0 } ,
2008-07-04 14:19:32 +00:00
{ LADSPA_HINT_DEFAULT_MAXIMUM | // crispness
2007-11-21 19:57:49 +00:00
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_INTEGER ,
0.0 , 3.0 } ,
2008-07-04 14:19:32 +00:00
{ LADSPA_HINT_DEFAULT_0 | // formant preserving
2008-05-22 16:54:27 +00:00
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_TOGGLED ,
0.0 , 1.0 } ,
2021-05-14 11:35:08 +01:00
{ LADSPA_HINT_DEFAULT_0 | // wet-dry mix
2008-07-04 19:31:23 +00:00
LADSPA_HINT_BOUNDED_BELOW |
2021-05-14 11:35:08 +01:00
LADSPA_HINT_BOUNDED_ABOVE ,
2008-07-04 19:31:23 +00:00
0.0 , 1.0 } ,
2007-11-06 21:41:16 +00:00
{ 0 , 0 , 0 } ,
{ 0 , 0 , 0 } ,
{ 0 , 0 , 0 } ,
{ 0 , 0 , 0 }
} ;
const LADSPA_Properties
RubberBandPitchShifter : : properties = LADSPA_PROPERTY_HARD_RT_CAPABLE ;
const LADSPA_Descriptor
RubberBandPitchShifter : : ladspaDescriptorMono =
{
2979 , // "Unique" ID
" rubberband-pitchshifter-mono " , // Label
properties ,
" Rubber Band Mono Pitch Shifter " , // Name
2008-06-04 20:43:22 +00:00
" Breakfast Quay " ,
2007-12-10 15:47:06 +00:00
" GPL " ,
2007-11-06 21:41:16 +00:00
PortCountMono ,
portsMono ,
portNamesMono ,
hintsMono ,
0 , // Implementation data
instantiate ,
connectPort ,
activate ,
run ,
0 , // Run adding
0 , // Set run adding gain
deactivate ,
cleanup
} ;
const LADSPA_Descriptor
RubberBandPitchShifter : : ladspaDescriptorStereo =
{
9792 , // "Unique" ID
" rubberband-pitchshifter-stereo " , // Label
properties ,
" Rubber Band Stereo Pitch Shifter " , // Name
2008-06-04 20:43:22 +00:00
" Breakfast Quay " ,
2007-12-10 15:47:06 +00:00
" GPL " ,
2007-11-06 21:41:16 +00:00
PortCountStereo ,
portsStereo ,
portNamesStereo ,
hintsStereo ,
0 , // Implementation data
instantiate ,
connectPort ,
activate ,
run ,
0 , // Run adding
0 , // Set run adding gain
deactivate ,
cleanup
} ;
const LADSPA_Descriptor *
RubberBandPitchShifter : : getDescriptor ( unsigned long index )
{
if ( index = = 0 ) return & ladspaDescriptorMono ;
if ( index = = 1 ) return & ladspaDescriptorStereo ;
else return 0 ;
}
RubberBandPitchShifter : : RubberBandPitchShifter ( int sampleRate , size_t channels ) :
m_latency ( 0 ) ,
m_cents ( 0 ) ,
m_semitones ( 0 ) ,
m_octaves ( 0 ) ,
2007-11-21 19:57:49 +00:00
m_crispness ( 0 ) ,
2008-06-09 20:46:37 +00:00
m_formant ( 0 ) ,
2021-05-14 11:35:08 +01:00
m_wetDry ( 0 ) ,
2007-11-06 21:41:16 +00:00
m_ratio ( 1.0 ) ,
m_prevRatio ( 1.0 ) ,
2007-11-21 19:57:49 +00:00
m_currentCrispness ( - 1 ) ,
2008-06-09 20:46:37 +00:00
m_currentFormant ( false ) ,
2008-07-04 14:19:32 +00:00
m_blockSize ( 1024 ) ,
2021-05-14 14:26:52 +01:00
m_reserve ( 8192 ) ,
m_bufsize ( 0 ) ,
2008-07-06 19:24:53 +00:00
m_minfill ( 0 ) ,
2007-11-21 19:57:49 +00:00
m_stretcher ( new RubberBandStretcher
2007-11-06 21:41:16 +00:00
( sampleRate , channels ,
2008-07-04 14:19:32 +00:00
RubberBandStretcher : : OptionProcessRealTime |
RubberBandStretcher : : OptionPitchHighConsistency ) ) ,
2007-11-06 21:41:16 +00:00
m_sampleRate ( sampleRate ) ,
m_channels ( channels )
{
2014-09-03 17:11:07 +01:00
m_input = new float * [ m_channels ] ;
m_output = new float * [ m_channels ] ;
m_outputBuffer = new RingBuffer < float > * [ m_channels ] ;
2021-05-14 11:35:08 +01:00
m_delayMixBuffer = new RingBuffer < float > * [ m_channels ] ;
2014-09-03 17:11:07 +01:00
m_scratch = new float * [ m_channels ] ;
2021-05-14 14:26:52 +01:00
m_bufsize = m_blockSize + m_reserve + 8192 ;
2007-11-06 21:41:16 +00:00
for ( size_t c = 0 ; c < m_channels ; + + c ) {
2008-07-04 14:19:32 +00:00
2007-11-06 21:41:16 +00:00
m_input [ c ] = 0 ;
m_output [ c ] = 0 ;
2008-07-04 14:19:32 +00:00
2021-05-14 14:26:52 +01:00
m_outputBuffer [ c ] = new RingBuffer < float > ( m_bufsize ) ;
m_delayMixBuffer [ c ] = new RingBuffer < float > ( m_bufsize ) ;
2008-07-04 14:19:32 +00:00
2021-05-14 14:26:52 +01:00
m_scratch [ c ] = new float [ m_bufsize ] ;
2021-05-14 15:09:28 +01:00
for ( size_t i = 0 ; i < m_bufsize ; + + i ) {
2021-05-14 14:26:52 +01:00
m_scratch [ c ] [ i ] = 0.f ;
}
2007-11-06 21:41:16 +00:00
}
2008-07-04 14:19:32 +00:00
activateImpl ( ) ;
2007-11-06 21:41:16 +00:00
}
RubberBandPitchShifter : : ~ RubberBandPitchShifter ( )
{
delete m_stretcher ;
for ( size_t c = 0 ; c < m_channels ; + + c ) {
delete m_outputBuffer [ c ] ;
2021-05-14 11:35:08 +01:00
delete m_delayMixBuffer [ c ] ;
2007-11-06 21:41:16 +00:00
delete [ ] m_scratch [ c ] ;
}
2014-09-03 17:11:07 +01:00
delete [ ] m_outputBuffer ;
2021-05-14 11:35:08 +01:00
delete [ ] m_delayMixBuffer ;
2014-09-03 17:11:07 +01:00
delete [ ] m_scratch ;
delete [ ] m_output ;
delete [ ] m_input ;
2007-11-06 21:41:16 +00:00
}
LADSPA_Handle
RubberBandPitchShifter : : instantiate ( const LADSPA_Descriptor * desc , unsigned long rate )
{
if ( desc - > PortCount = = ladspaDescriptorMono . PortCount ) {
return new RubberBandPitchShifter ( rate , 1 ) ;
} else if ( desc - > PortCount = = ladspaDescriptorStereo . PortCount ) {
return new RubberBandPitchShifter ( rate , 2 ) ;
}
return 0 ;
}
void
RubberBandPitchShifter : : connectPort ( LADSPA_Handle handle ,
unsigned long port , LADSPA_Data * location )
{
RubberBandPitchShifter * shifter = ( RubberBandPitchShifter * ) handle ;
float * * ports [ PortCountStereo ] = {
& shifter - > m_latency ,
& shifter - > m_cents ,
& shifter - > m_semitones ,
& shifter - > m_octaves ,
2007-11-21 19:57:49 +00:00
& shifter - > m_crispness ,
2008-06-09 20:46:37 +00:00
& shifter - > m_formant ,
2021-05-14 11:35:08 +01:00
& shifter - > m_wetDry ,
2008-05-22 16:54:27 +00:00
& shifter - > m_input [ 0 ] ,
2007-11-06 21:41:16 +00:00
& shifter - > m_output [ 0 ] ,
& shifter - > m_input [ 1 ] ,
& shifter - > m_output [ 1 ]
} ;
2008-07-04 19:31:23 +00:00
if ( shifter - > m_channels = = 1 ) {
if ( port > = PortCountMono ) return ;
} else {
if ( port > = PortCountStereo ) return ;
}
2007-11-06 21:41:16 +00:00
* ports [ port ] = ( float * ) location ;
2008-07-04 14:19:32 +00:00
if ( shifter - > m_latency ) {
2021-05-14 11:35:08 +01:00
* ( shifter - > m_latency ) = shifter - > getLatency ( ) ;
}
}
int
RubberBandPitchShifter : : getLatency ( ) const
{
2021-05-14 15:09:28 +01:00
return m_reserve ;
2007-11-06 21:41:16 +00:00
}
void
RubberBandPitchShifter : : activate ( LADSPA_Handle handle )
{
RubberBandPitchShifter * shifter = ( RubberBandPitchShifter * ) handle ;
2008-07-04 14:19:32 +00:00
shifter - > activateImpl ( ) ;
}
void
RubberBandPitchShifter : : activateImpl ( )
{
updateRatio ( ) ;
m_prevRatio = m_ratio ;
m_stretcher - > reset ( ) ;
m_stretcher - > setPitchScale ( m_ratio ) ;
2008-07-04 19:31:23 +00:00
for ( size_t c = 0 ; c < m_channels ; + + c ) {
2008-07-04 14:19:32 +00:00
m_outputBuffer [ c ] - > reset ( ) ;
}
2021-05-14 11:35:08 +01:00
for ( size_t c = 0 ; c < m_channels ; + + c ) {
m_delayMixBuffer [ c ] - > reset ( ) ;
m_delayMixBuffer [ c ] - > zero ( getLatency ( ) ) ;
}
2021-05-14 14:26:52 +01:00
for ( size_t c = 0 ; c < m_channels ; + + c ) {
2021-05-14 15:09:28 +01:00
for ( size_t i = 0 ; i < m_bufsize ; + + i ) {
2021-05-14 14:26:52 +01:00
m_scratch [ c ] [ i ] = 0.f ;
}
}
2021-05-14 11:35:08 +01:00
2008-07-06 19:24:53 +00:00
m_minfill = 0 ;
2021-05-14 15:09:28 +01:00
m_stretcher - > process ( m_scratch , m_reserve , false ) ;
2007-11-06 21:41:16 +00:00
}
void
RubberBandPitchShifter : : run ( LADSPA_Handle handle , unsigned long samples )
{
RubberBandPitchShifter * shifter = ( RubberBandPitchShifter * ) handle ;
shifter - > runImpl ( samples ) ;
}
void
RubberBandPitchShifter : : updateRatio ( )
{
2008-07-04 14:19:32 +00:00
double oct = ( m_octaves ? * m_octaves : 0.0 ) ;
oct + = ( m_semitones ? * m_semitones : 0.0 ) / 12 ;
oct + = ( m_cents ? * m_cents : 0.0 ) / 1200 ;
2007-11-06 21:41:16 +00:00
m_ratio = pow ( 2.0 , oct ) ;
}
2007-11-21 19:57:49 +00:00
void
RubberBandPitchShifter : : updateCrispness ( )
{
if ( ! m_crispness ) return ;
int c = lrintf ( * m_crispness ) ;
if ( c = = m_currentCrispness ) return ;
if ( c < 0 | | c > 3 ) return ;
RubberBandStretcher * s = m_stretcher ;
switch ( c ) {
case 0 :
s - > setPhaseOption ( RubberBandStretcher : : OptionPhaseIndependent ) ;
s - > setTransientsOption ( RubberBandStretcher : : OptionTransientsSmooth ) ;
break ;
case 1 :
2008-07-08 15:00:22 +00:00
s - > setPhaseOption ( RubberBandStretcher : : OptionPhaseLaminar ) ;
2007-11-21 19:57:49 +00:00
s - > setTransientsOption ( RubberBandStretcher : : OptionTransientsSmooth ) ;
break ;
case 2 :
2008-07-08 15:00:22 +00:00
s - > setPhaseOption ( RubberBandStretcher : : OptionPhaseLaminar ) ;
2007-11-21 19:57:49 +00:00
s - > setTransientsOption ( RubberBandStretcher : : OptionTransientsMixed ) ;
break ;
case 3 :
2008-07-08 15:00:22 +00:00
s - > setPhaseOption ( RubberBandStretcher : : OptionPhaseLaminar ) ;
2007-11-21 19:57:49 +00:00
s - > setTransientsOption ( RubberBandStretcher : : OptionTransientsCrisp ) ;
break ;
}
m_currentCrispness = c ;
}
2008-06-09 20:46:37 +00:00
void
RubberBandPitchShifter : : updateFormant ( )
{
if ( ! m_formant ) return ;
bool f = ( * m_formant > 0.5f ) ;
if ( f = = m_currentFormant ) return ;
RubberBandStretcher * s = m_stretcher ;
s - > setFormantOption ( f ?
RubberBandStretcher : : OptionFormantPreserved :
RubberBandStretcher : : OptionFormantShifted ) ;
m_currentFormant = f ;
}
2007-11-06 21:41:16 +00:00
void
RubberBandPitchShifter : : runImpl ( unsigned long insamples )
2008-07-04 14:19:32 +00:00
{
unsigned long offset = 0 ;
// We have to break up the input into chunks like this because
// insamples could be arbitrarily large and our output buffer is
// of limited size
while ( offset < insamples ) {
unsigned long block = ( unsigned long ) m_blockSize ;
2008-07-04 19:31:23 +00:00
if ( block + offset > insamples ) block = insamples - offset ;
2008-07-04 14:19:32 +00:00
runImpl ( block , offset ) ;
offset + = block ;
}
2021-05-14 11:35:08 +01:00
if ( m_wetDry ) {
for ( size_t c = 0 ; c < m_channels ; + + c ) {
m_delayMixBuffer [ c ] - > write ( m_input [ c ] , insamples ) ;
}
float mix = * m_wetDry ;
for ( size_t c = 0 ; c < m_channels ; + + c ) {
if ( mix > 0.0 ) {
for ( unsigned long i = 0 ; i < insamples ; + + i ) {
float dry = m_delayMixBuffer [ c ] - > readOne ( ) ;
m_output [ c ] [ i ] * = ( 1.0 - mix ) ;
m_output [ c ] [ i ] + = dry * mix ;
}
} else {
m_delayMixBuffer [ c ] - > skip ( insamples ) ;
}
}
}
2008-07-04 14:19:32 +00:00
}
void
RubberBandPitchShifter : : runImpl ( unsigned long insamples , unsigned long offset )
2007-11-06 21:41:16 +00:00
{
updateRatio ( ) ;
if ( m_ratio ! = m_prevRatio ) {
m_stretcher - > setPitchScale ( m_ratio ) ;
m_prevRatio = m_ratio ;
}
2021-05-14 14:26:52 +01:00
2007-11-06 21:41:16 +00:00
if ( m_latency ) {
2021-05-14 11:35:08 +01:00
* m_latency = getLatency ( ) ;
2007-11-06 21:41:16 +00:00
}
2021-05-14 14:26:52 +01:00
2007-11-21 19:57:49 +00:00
updateCrispness ( ) ;
2008-06-09 20:46:37 +00:00
updateFormant ( ) ;
2007-11-21 19:57:49 +00:00
2008-07-04 14:19:32 +00:00
const int samples = insamples ;
2007-11-06 21:41:16 +00:00
int processed = 0 ;
size_t outTotal = 0 ;
float * ptrs [ 2 ] ;
while ( processed < samples ) {
2008-07-04 14:19:32 +00:00
// never feed more than the minimum necessary number of
// samples at a time; ensures nothing will overflow internally
// and we don't need to call setMaxProcessSize
2007-11-06 21:41:16 +00:00
int toCauseProcessing = m_stretcher - > getSamplesRequired ( ) ;
2008-07-06 19:24:53 +00:00
int inchunk = min ( samples - processed , toCauseProcessing ) ;
2007-11-06 21:41:16 +00:00
for ( size_t c = 0 ; c < m_channels ; + + c ) {
2008-07-04 14:19:32 +00:00
ptrs [ c ] = & ( m_input [ c ] [ offset + processed ] ) ;
2007-11-06 21:41:16 +00:00
}
m_stretcher - > process ( ptrs , inchunk , false ) ;
processed + = inchunk ;
int avail = m_stretcher - > available ( ) ;
int writable = m_outputBuffer [ 0 ] - > getWriteSpace ( ) ;
2021-05-14 11:35:08 +01:00
int outchunk = avail ;
if ( outchunk > writable ) {
2021-05-14 14:26:52 +01:00
cerr < < " RubberBandPitchShifter::runImpl: buffer is not large enough: size = " < < m_outputBuffer [ 0 ] - > getSize ( ) < < " , chunk = " < < outchunk < < " , space = " < < writable < < " (buffer contains " < < m_outputBuffer [ 0 ] - > getReadSpace ( ) < < " unread) " < < endl ;
2021-05-14 11:35:08 +01:00
outchunk = writable ;
}
2007-11-06 21:41:16 +00:00
size_t actual = m_stretcher - > retrieve ( m_scratch , outchunk ) ;
outTotal + = actual ;
for ( size_t c = 0 ; c < m_channels ; + + c ) {
2021-05-14 11:35:08 +01:00
m_outputBuffer [ c ] - > write ( m_scratch [ c ] , actual ) ;
2007-11-06 21:41:16 +00:00
}
}
for ( size_t c = 0 ; c < m_channels ; + + c ) {
2008-07-04 14:19:32 +00:00
int toRead = m_outputBuffer [ c ] - > getReadSpace ( ) ;
if ( toRead < samples & & c = = 0 ) {
2008-07-06 19:24:53 +00:00
cerr < < " RubberBandPitchShifter::runImpl: buffer underrun: required = " < < samples < < " , available = " < < toRead < < endl ;
2007-11-06 21:41:16 +00:00
}
2008-07-06 19:24:53 +00:00
int chunk = min ( toRead , samples ) ;
2008-07-04 14:19:32 +00:00
m_outputBuffer [ c ] - > read ( & ( m_output [ c ] [ offset ] ) , chunk ) ;
2007-11-27 14:12:04 +00:00
}
2008-07-06 19:24:53 +00:00
2021-05-14 15:09:28 +01:00
size_t fill = m_outputBuffer [ 0 ] - > getReadSpace ( ) ;
2021-05-14 14:26:52 +01:00
if ( fill < m_minfill | | m_minfill = = 0 ) {
m_minfill = fill ;
2021-05-14 15:09:28 +01:00
// cerr << "minfill = " << m_minfill << endl;
2008-07-06 19:24:53 +00:00
}
2007-11-06 21:41:16 +00:00
}
void
RubberBandPitchShifter : : deactivate ( LADSPA_Handle handle )
{
activate ( handle ) ; // both functions just reset the plugin
}
void
RubberBandPitchShifter : : cleanup ( LADSPA_Handle handle )
{
delete ( RubberBandPitchShifter * ) handle ;
}