* Separate out analysis and synthesis window sizes from FFT size.
This is an internal change only, so far -- results should be unchanged from 1.5.0.
This commit is contained in:
@@ -22,41 +22,39 @@ namespace RubberBand
|
|||||||
{
|
{
|
||||||
|
|
||||||
RubberBandStretcher::Impl::ChannelData::ChannelData(size_t windowSize,
|
RubberBandStretcher::Impl::ChannelData::ChannelData(size_t windowSize,
|
||||||
int overSample,
|
size_t fftSize,
|
||||||
size_t outbufSize) :
|
size_t outbufSize)
|
||||||
oversample(overSample)
|
|
||||||
{
|
{
|
||||||
std::set<size_t> s;
|
std::set<size_t> s;
|
||||||
construct(s, windowSize, outbufSize);
|
construct(s, windowSize, fftSize, outbufSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
RubberBandStretcher::Impl::ChannelData::ChannelData(const std::set<size_t> &windowSizes,
|
RubberBandStretcher::Impl::ChannelData::ChannelData(const std::set<size_t> &sizes,
|
||||||
int overSample,
|
|
||||||
size_t initialWindowSize,
|
size_t initialWindowSize,
|
||||||
size_t outbufSize) :
|
size_t initialFftSize,
|
||||||
oversample(overSample)
|
size_t outbufSize)
|
||||||
{
|
{
|
||||||
construct(windowSizes, initialWindowSize, outbufSize);
|
construct(sizes, initialWindowSize, initialFftSize, outbufSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RubberBandStretcher::Impl::ChannelData::construct(const std::set<size_t> &windowSizes,
|
RubberBandStretcher::Impl::ChannelData::construct(const std::set<size_t> &sizes,
|
||||||
size_t initialWindowSize,
|
size_t initialWindowSize,
|
||||||
|
size_t initialFftSize,
|
||||||
size_t outbufSize)
|
size_t outbufSize)
|
||||||
{
|
{
|
||||||
size_t maxSize = initialWindowSize;
|
size_t maxSize = initialWindowSize;
|
||||||
|
if (initialFftSize > maxSize) maxSize = initialFftSize;
|
||||||
|
|
||||||
if (!windowSizes.empty()) {
|
|
||||||
// std::set is ordered by value
|
// std::set is ordered by value
|
||||||
std::set<size_t>::const_iterator i = windowSizes.end();
|
std::set<size_t>::const_iterator i = sizes.end();
|
||||||
maxSize = *--i;
|
if (i != sizes.begin()) {
|
||||||
}
|
--i;
|
||||||
if (windowSizes.find(initialWindowSize) == windowSizes.end()) {
|
if (*i > maxSize) maxSize = *i;
|
||||||
if (initialWindowSize > maxSize) maxSize = initialWindowSize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// max size of the real "half" of freq data
|
// max possible size of the real "half" of freq data
|
||||||
size_t realSize = (maxSize * oversample)/2 + 1;
|
size_t realSize = maxSize / 2 + 1;
|
||||||
|
|
||||||
// std::cerr << "ChannelData::construct([" << windowSizes.size() << "], " << maxSize << ", " << outbufSize << ")" << std::endl;
|
// std::cerr << "ChannelData::construct([" << windowSizes.size() << "], " << maxSize << ", " << outbufSize << ")" << std::endl;
|
||||||
|
|
||||||
@@ -79,16 +77,12 @@ RubberBandStretcher::Impl::ChannelData::construct(const std::set<size_t> &window
|
|||||||
accumulator = allocate<float>(maxSize);
|
accumulator = allocate<float>(maxSize);
|
||||||
windowAccumulator = allocate<float>(maxSize);
|
windowAccumulator = allocate<float>(maxSize);
|
||||||
|
|
||||||
for (std::set<size_t>::const_iterator i = windowSizes.begin();
|
for (std::set<size_t>::const_iterator i = sizes.begin();
|
||||||
i != windowSizes.end(); ++i) {
|
i != sizes.end(); ++i) {
|
||||||
ffts[*i] = new FFT(*i * oversample);
|
ffts[*i] = new FFT(*i);
|
||||||
ffts[*i]->initDouble();
|
ffts[*i]->initDouble();
|
||||||
}
|
}
|
||||||
if (windowSizes.find(initialWindowSize) == windowSizes.end()) {
|
fft = ffts[initialFftSize];
|
||||||
ffts[initialWindowSize] = new FFT(initialWindowSize * oversample);
|
|
||||||
ffts[initialWindowSize]->initDouble();
|
|
||||||
}
|
|
||||||
fft = ffts[initialWindowSize];
|
|
||||||
|
|
||||||
dblbuf = fft->getDoubleTimeBuffer();
|
dblbuf = fft->getDoubleTimeBuffer();
|
||||||
|
|
||||||
@@ -102,7 +96,7 @@ RubberBandStretcher::Impl::ChannelData::construct(const std::set<size_t> &window
|
|||||||
freqPeak[i] = 0;
|
freqPeak[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < initialWindowSize * oversample; ++i) {
|
for (size_t i = 0; i < initialFftSize; ++i) {
|
||||||
dblbuf[i] = 0.0;
|
dblbuf[i] = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,15 +109,16 @@ RubberBandStretcher::Impl::ChannelData::construct(const std::set<size_t> &window
|
|||||||
windowAccumulator[0] = 1.f;
|
windowAccumulator[0] = 1.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
RubberBandStretcher::Impl::ChannelData::setWindowSize(size_t windowSize)
|
RubberBandStretcher::Impl::ChannelData::setSizes(size_t windowSize,
|
||||||
|
size_t fftSize)
|
||||||
{
|
{
|
||||||
size_t oldSize = inbuf->getSize();
|
size_t maxSize = std::max(windowSize, fftSize);
|
||||||
size_t realSize = (windowSize * oversample) / 2 + 1;
|
size_t realSize = maxSize / 2 + 1;
|
||||||
|
size_t oldMax = inbuf->getSize();
|
||||||
|
|
||||||
// std::cerr << "ChannelData::setWindowSize(" << windowSize << ") [from " << oldSize << "]" << std::endl;
|
if (oldMax >= maxSize) {
|
||||||
|
|
||||||
if (oldSize >= windowSize) { //!!! shurely >= realSize?
|
|
||||||
|
|
||||||
// no need to reallocate buffers, just reselect fft
|
// no need to reallocate buffers, just reselect fft
|
||||||
|
|
||||||
@@ -131,18 +126,18 @@ RubberBandStretcher::Impl::ChannelData::setWindowSize(size_t windowSize)
|
|||||||
//process thread, can we? we need to zero the mag/phase
|
//process thread, can we? we need to zero the mag/phase
|
||||||
//buffers without interference
|
//buffers without interference
|
||||||
|
|
||||||
if (ffts.find(windowSize) == ffts.end()) {
|
if (ffts.find(fftSize) == ffts.end()) {
|
||||||
//!!! this also requires a lock, but it shouldn't occur in
|
//!!! this also requires a lock, but it shouldn't occur in
|
||||||
//RT mode with proper initialisation
|
//RT mode with proper initialisation
|
||||||
ffts[windowSize] = new FFT(windowSize * oversample);
|
ffts[fftSize] = new FFT(fftSize);
|
||||||
ffts[windowSize]->initDouble();
|
ffts[fftSize]->initDouble();
|
||||||
}
|
}
|
||||||
|
|
||||||
fft = ffts[windowSize];
|
fft = ffts[fftSize];
|
||||||
|
|
||||||
dblbuf = fft->getDoubleTimeBuffer();
|
dblbuf = fft->getDoubleTimeBuffer();
|
||||||
|
|
||||||
for (size_t i = 0; i < windowSize * oversample; ++i) {
|
for (size_t i = 0; i < maxSize; ++i) {
|
||||||
dblbuf[i] = 0.0;
|
dblbuf[i] = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,37 +160,37 @@ RubberBandStretcher::Impl::ChannelData::setWindowSize(size_t windowSize)
|
|||||||
//is unavailable (since this should never normally be the case in
|
//is unavailable (since this should never normally be the case in
|
||||||
//general use in RT mode)
|
//general use in RT mode)
|
||||||
|
|
||||||
RingBuffer<float> *newbuf = inbuf->resized(windowSize);
|
RingBuffer<float> *newbuf = inbuf->resized(maxSize);
|
||||||
delete inbuf;
|
delete inbuf;
|
||||||
inbuf = newbuf;
|
inbuf = newbuf;
|
||||||
|
|
||||||
// We don't want to preserve data in these arrays
|
// We don't want to preserve data in these arrays
|
||||||
|
|
||||||
mag = reallocate<double>(mag, oldSize, realSize);
|
mag = reallocate<double>(mag, oldMax, realSize);
|
||||||
phase = reallocate<double>(phase, oldSize, realSize);
|
phase = reallocate<double>(phase, oldMax, realSize);
|
||||||
prevPhase = reallocate<double>(prevPhase, oldSize, realSize);
|
prevPhase = reallocate<double>(prevPhase, oldMax, realSize);
|
||||||
prevError = reallocate<double>(prevError, oldSize, realSize);
|
prevError = reallocate<double>(prevError, oldMax, realSize);
|
||||||
unwrappedPhase = reallocate<double>(unwrappedPhase, oldSize, realSize);
|
unwrappedPhase = reallocate<double>(unwrappedPhase, oldMax, realSize);
|
||||||
envelope = reallocate<double>(envelope, oldSize, realSize);
|
envelope = reallocate<double>(envelope, oldMax, realSize);
|
||||||
|
|
||||||
delete[] freqPeak;
|
delete[] freqPeak;
|
||||||
freqPeak = new size_t[realSize];
|
freqPeak = new size_t[realSize];
|
||||||
|
|
||||||
deallocate(fltbuf);
|
deallocate(fltbuf);
|
||||||
fltbuf = allocate<float>(windowSize);
|
fltbuf = allocate<float>(maxSize);
|
||||||
|
|
||||||
// But we do want to preserve data in these
|
// But we do want to preserve data in these
|
||||||
|
|
||||||
float *newAcc = allocate<float>(windowSize);
|
float *newAcc = allocate<float>(maxSize);
|
||||||
|
|
||||||
v_copy(newAcc, accumulator, oldSize);
|
v_copy(newAcc, accumulator, oldMax);
|
||||||
|
|
||||||
deallocate(accumulator);
|
deallocate(accumulator);
|
||||||
accumulator = newAcc;
|
accumulator = newAcc;
|
||||||
|
|
||||||
newAcc = allocate<float>(windowSize);
|
newAcc = allocate<float>(maxSize);
|
||||||
|
|
||||||
v_copy(newAcc, windowAccumulator, oldSize);
|
v_copy(newAcc, windowAccumulator, oldMax);
|
||||||
|
|
||||||
deallocate(windowAccumulator);
|
deallocate(windowAccumulator);
|
||||||
windowAccumulator = newAcc;
|
windowAccumulator = newAcc;
|
||||||
@@ -206,20 +201,20 @@ RubberBandStretcher::Impl::ChannelData::setWindowSize(size_t windowSize)
|
|||||||
freqPeak[i] = 0;
|
freqPeak[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < windowSize; ++i) {
|
for (size_t i = 0; i < maxSize; ++i) {
|
||||||
fltbuf[i] = 0.f;
|
fltbuf[i] = 0.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ffts.find(windowSize) == ffts.end()) {
|
if (ffts.find(fftSize) == ffts.end()) {
|
||||||
ffts[windowSize] = new FFT(windowSize * oversample);
|
ffts[fftSize] = new FFT(fftSize);
|
||||||
ffts[windowSize]->initDouble();
|
ffts[fftSize]->initDouble();
|
||||||
}
|
}
|
||||||
|
|
||||||
fft = ffts[windowSize];
|
fft = ffts[fftSize];
|
||||||
|
|
||||||
dblbuf = fft->getDoubleTimeBuffer();
|
dblbuf = fft->getDoubleTimeBuffer();
|
||||||
|
|
||||||
for (size_t i = 0; i < windowSize * oversample; ++i) {
|
for (size_t i = 0; i < fftSize; ++i) {
|
||||||
dblbuf[i] = 0.0;
|
dblbuf[i] = 0.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,31 +32,36 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Construct a ChannelData structure.
|
* Construct a ChannelData structure.
|
||||||
*
|
*
|
||||||
* The window size passed in here is the size for the FFT
|
* The sizes passed in here are for the time-domain analysis
|
||||||
* calculation, and most of the buffer sizes also depend on
|
* window and FFT calculation, and most of the buffer sizes also
|
||||||
* it. In practice it is always a power of two and except for
|
* depend on them. In practice they are always powers of two, the
|
||||||
* very extreme stretches is always either 1024, 2048 or 4096.
|
* window and FFT sizes are either equal or generally in a 2:1
|
||||||
|
* relationship either way, and except for very extreme stretches
|
||||||
|
* the FFT size is either 1024, 2048 or 4096.
|
||||||
*
|
*
|
||||||
* The outbuf size depends on other factors as well, including
|
* The outbuf size depends on other factors as well, including
|
||||||
* the pitch scale factor and any maximum processing block
|
* the pitch scale factor and any maximum processing block
|
||||||
* size specified by the user of the code.
|
* size specified by the user of the code.
|
||||||
*/
|
*/
|
||||||
ChannelData(size_t windowSize, int overSample, size_t outbufSize);
|
ChannelData(size_t windowSize,
|
||||||
|
size_t fftSize,
|
||||||
|
size_t outbufSize);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a ChannelData structure that can process at
|
* Construct a ChannelData structure that can process at different
|
||||||
* different FFT sizes without requiring reallocation when the
|
* FFT sizes without requiring reallocation when the size changes.
|
||||||
* size changes. The size can subsequently be changed with a
|
* The sizes can subsequently be changed with a call to setSizes.
|
||||||
* call to setWindowSize. Reallocation will only be necessary
|
* Reallocation will only be necessary if setSizes is called with
|
||||||
* if setWindowSize is called with a value not equal to one of
|
* values not equal to any of those passed in to the constructor.
|
||||||
* those passed in to the constructor.
|
|
||||||
*
|
*
|
||||||
* The outbufSize should be the maximum possible outbufSize to
|
* The outbufSize should be the maximum possible outbufSize to
|
||||||
* avoid reallocation, which will happen if setOutbufSize is
|
* avoid reallocation, which will happen if setOutbufSize is
|
||||||
* called subsequently.
|
* called subsequently.
|
||||||
*/
|
*/
|
||||||
ChannelData(const std::set<size_t> &windowSizes,
|
ChannelData(const std::set<size_t> &sizes,
|
||||||
int overSample, size_t initialWindowSize, size_t outbufSize);
|
size_t initialWindowSize,
|
||||||
|
size_t initialFftSize,
|
||||||
|
size_t outbufSize);
|
||||||
~ChannelData();
|
~ChannelData();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -65,12 +70,12 @@ public:
|
|||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the FFT and buffer sizes from the given processing
|
* Set the FFT, analysis window, and buffer sizes. If this
|
||||||
* window size. If this ChannelData was constructed with a set
|
* ChannelData was constructed with a set of sizes and the given
|
||||||
* of window sizes and the given window size here was among
|
* window and FFT sizes here were among them, no reallocation will
|
||||||
* them, no reallocation will be required.
|
* be required.
|
||||||
*/
|
*/
|
||||||
void setWindowSize(size_t windowSize);
|
void setSizes(size_t windowSize, size_t fftSizes);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the outbufSize for the channel data. Reallocation will
|
* Set the outbufSize for the channel data. Reallocation will
|
||||||
@@ -94,7 +99,6 @@ public:
|
|||||||
double *prevError;
|
double *prevError;
|
||||||
double *unwrappedPhase;
|
double *unwrappedPhase;
|
||||||
|
|
||||||
|
|
||||||
size_t *freqPeak;
|
size_t *freqPeak;
|
||||||
|
|
||||||
float *accumulator;
|
float *accumulator;
|
||||||
@@ -123,11 +127,10 @@ public:
|
|||||||
float *resamplebuf;
|
float *resamplebuf;
|
||||||
size_t resamplebufSize;
|
size_t resamplebufSize;
|
||||||
|
|
||||||
int oversample;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void construct(const std::set<size_t> &windowSizes,
|
void construct(const std::set<size_t> &sizes,
|
||||||
size_t initialWindowSize, size_t outbufSize);
|
size_t initialWindowSize, size_t initialFftSize,
|
||||||
|
size_t outbufSize);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ const size_t
|
|||||||
RubberBandStretcher::Impl::m_defaultIncrement = 256;
|
RubberBandStretcher::Impl::m_defaultIncrement = 256;
|
||||||
|
|
||||||
const size_t
|
const size_t
|
||||||
RubberBandStretcher::Impl::m_defaultWindowSize = 2048;
|
RubberBandStretcher::Impl::m_defaultFftSize = 2048;
|
||||||
|
|
||||||
int
|
int
|
||||||
RubberBandStretcher::Impl::m_defaultDebugLevel = 0;
|
RubberBandStretcher::Impl::m_defaultDebugLevel = 0;
|
||||||
@@ -68,17 +68,20 @@ RubberBandStretcher::Impl::Impl(size_t sampleRate,
|
|||||||
m_channels(channels),
|
m_channels(channels),
|
||||||
m_timeRatio(initialTimeRatio),
|
m_timeRatio(initialTimeRatio),
|
||||||
m_pitchScale(initialPitchScale),
|
m_pitchScale(initialPitchScale),
|
||||||
m_windowSize(m_defaultWindowSize),
|
m_fftSize(m_defaultFftSize),
|
||||||
|
m_aWindowSize(m_defaultFftSize),
|
||||||
|
m_sWindowSize(m_defaultFftSize),
|
||||||
m_increment(m_defaultIncrement),
|
m_increment(m_defaultIncrement),
|
||||||
m_outbufSize(m_defaultWindowSize * 2),
|
m_outbufSize(m_defaultFftSize * 2),
|
||||||
m_maxProcessSize(m_defaultWindowSize),
|
m_maxProcessSize(m_defaultFftSize),
|
||||||
m_expectedInputDuration(0),
|
m_expectedInputDuration(0),
|
||||||
m_threaded(false),
|
m_threaded(false),
|
||||||
m_realtime(false),
|
m_realtime(false),
|
||||||
m_options(options),
|
m_options(options),
|
||||||
m_debugLevel(m_defaultDebugLevel),
|
m_debugLevel(m_defaultDebugLevel),
|
||||||
m_mode(JustCreated),
|
m_mode(JustCreated),
|
||||||
m_window(0),
|
m_awindow(0),
|
||||||
|
m_swindow(0),
|
||||||
m_studyFFT(0),
|
m_studyFFT(0),
|
||||||
m_spaceAvailable("space"),
|
m_spaceAvailable("space"),
|
||||||
m_inputDuration(0),
|
m_inputDuration(0),
|
||||||
@@ -94,7 +97,7 @@ RubberBandStretcher::Impl::Impl(size_t sampleRate,
|
|||||||
m_freq0(600),
|
m_freq0(600),
|
||||||
m_freq1(1200),
|
m_freq1(1200),
|
||||||
m_freq2(12000),
|
m_freq2(12000),
|
||||||
m_baseWindowSize(m_defaultWindowSize)
|
m_baseFftSize(m_defaultFftSize)
|
||||||
{
|
{
|
||||||
if (!_initialised) {
|
if (!_initialised) {
|
||||||
system_specific_initialise();
|
system_specific_initialise();
|
||||||
@@ -109,25 +112,27 @@ RubberBandStretcher::Impl::Impl(size_t sampleRate,
|
|||||||
// we don't let it drop below the 48k default
|
// we don't let it drop below the 48k default
|
||||||
m_rateMultiple = float(m_sampleRate) / 48000.f;
|
m_rateMultiple = float(m_sampleRate) / 48000.f;
|
||||||
// if (m_rateMultiple < 1.f) m_rateMultiple = 1.f;
|
// if (m_rateMultiple < 1.f) m_rateMultiple = 1.f;
|
||||||
m_baseWindowSize = roundUp(int(m_defaultWindowSize * m_rateMultiple));
|
m_baseFftSize = roundUp(int(m_defaultFftSize * m_rateMultiple));
|
||||||
|
|
||||||
if ((options & OptionWindowShort) || (options & OptionWindowLong)) {
|
if ((options & OptionWindowShort) || (options & OptionWindowLong)) {
|
||||||
if ((options & OptionWindowShort) && (options & OptionWindowLong)) {
|
if ((options & OptionWindowShort) && (options & OptionWindowLong)) {
|
||||||
cerr << "RubberBandStretcher::Impl::Impl: Cannot specify OptionWindowLong and OptionWindowShort together; falling back to OptionWindowStandard" << endl;
|
cerr << "RubberBandStretcher::Impl::Impl: Cannot specify OptionWindowLong and OptionWindowShort together; falling back to OptionWindowStandard" << endl;
|
||||||
} else if (options & OptionWindowShort) {
|
} else if (options & OptionWindowShort) {
|
||||||
m_baseWindowSize = m_baseWindowSize / 2;
|
m_baseFftSize = m_baseFftSize / 2;
|
||||||
if (m_debugLevel > 0) {
|
if (m_debugLevel > 0) {
|
||||||
cerr << "setting baseWindowSize to " << m_baseWindowSize << endl;
|
cerr << "setting baseFftSize to " << m_baseFftSize << endl;
|
||||||
}
|
}
|
||||||
} else if (options & OptionWindowLong) {
|
} else if (options & OptionWindowLong) {
|
||||||
m_baseWindowSize = m_baseWindowSize * 2;
|
m_baseFftSize = m_baseFftSize * 2;
|
||||||
if (m_debugLevel > 0) {
|
if (m_debugLevel > 0) {
|
||||||
cerr << "setting baseWindowSize to " << m_baseWindowSize << endl;
|
cerr << "setting baseFftSize to " << m_baseFftSize << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_windowSize = m_baseWindowSize;
|
m_fftSize = m_baseFftSize;
|
||||||
m_outbufSize = m_baseWindowSize * 2;
|
m_aWindowSize = m_baseFftSize;
|
||||||
m_maxProcessSize = m_baseWindowSize;
|
m_sWindowSize = m_baseFftSize;
|
||||||
|
m_outbufSize = m_sWindowSize * 2;
|
||||||
|
m_maxProcessSize = m_aWindowSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_options & OptionProcessRealTime) {
|
if (m_options & OptionProcessRealTime) {
|
||||||
@@ -378,7 +383,7 @@ void
|
|||||||
RubberBandStretcher::Impl::calculateSizes()
|
RubberBandStretcher::Impl::calculateSizes()
|
||||||
{
|
{
|
||||||
size_t inputIncrement = m_defaultIncrement;
|
size_t inputIncrement = m_defaultIncrement;
|
||||||
size_t windowSize = m_baseWindowSize;
|
size_t windowSize = m_baseFftSize;
|
||||||
size_t outputIncrement;
|
size_t outputIncrement;
|
||||||
|
|
||||||
if (m_pitchScale <= 0.0) {
|
if (m_pitchScale <= 0.0) {
|
||||||
@@ -413,7 +418,7 @@ RubberBandStretcher::Impl::calculateSizes()
|
|||||||
if (outputIncrement < m_defaultIncrement / 4) {
|
if (outputIncrement < m_defaultIncrement / 4) {
|
||||||
if (outputIncrement < 1) outputIncrement = 1;
|
if (outputIncrement < 1) outputIncrement = 1;
|
||||||
while (outputIncrement < m_defaultIncrement / 4 &&
|
while (outputIncrement < m_defaultIncrement / 4 &&
|
||||||
windowSize < m_baseWindowSize * 4) {
|
windowSize < m_baseFftSize * 4) {
|
||||||
outputIncrement *= 2;
|
outputIncrement *= 2;
|
||||||
inputIncrement = lrint(ceil(outputIncrement / r));
|
inputIncrement = lrint(ceil(outputIncrement / r));
|
||||||
windowSize = roundUp(lrint(ceil(inputIncrement * windowIncrRatio)));
|
windowSize = roundUp(lrint(ceil(inputIncrement * windowIncrRatio)));
|
||||||
@@ -483,9 +488,11 @@ RubberBandStretcher::Impl::calculateSizes()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// windowSize can be almost anything, but it can't be greater than
|
// windowSize can be almost anything, but it can't be greater than
|
||||||
// 4 * m_baseWindowSize unless ratio is less than 1/1024.
|
// 4 * m_baseFftSize unless ratio is less than 1/1024.
|
||||||
|
|
||||||
m_windowSize = windowSize;
|
m_fftSize = windowSize;
|
||||||
|
m_aWindowSize = windowSize;
|
||||||
|
m_sWindowSize = windowSize;
|
||||||
m_increment = inputIncrement;
|
m_increment = inputIncrement;
|
||||||
|
|
||||||
// When squashing, the greatest theoretically possible output
|
// When squashing, the greatest theoretically possible output
|
||||||
@@ -497,18 +504,18 @@ RubberBandStretcher::Impl::calculateSizes()
|
|||||||
|
|
||||||
if (m_debugLevel > 0) {
|
if (m_debugLevel > 0) {
|
||||||
cerr << "configure: effective ratio = " << getEffectiveRatio() << endl;
|
cerr << "configure: effective ratio = " << getEffectiveRatio() << endl;
|
||||||
cerr << "configure: window size = " << m_windowSize << ", increment = " << m_increment << " (approx output increment = " << int(lrint(m_increment * getEffectiveRatio())) << ")" << endl;
|
cerr << "configure: analysis window size = " << m_aWindowSize << ", synthesis window size = " << m_sWindowSize << ", fft size = " << m_fftSize << ", increment = " << m_increment << " (approx output increment = " << int(lrint(m_increment * getEffectiveRatio())) << ")" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_windowSize > m_maxProcessSize) {
|
if (std::max(m_aWindowSize, m_sWindowSize) > m_maxProcessSize) {
|
||||||
m_maxProcessSize = m_windowSize;
|
m_maxProcessSize = std::max(m_aWindowSize, m_sWindowSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_outbufSize =
|
m_outbufSize =
|
||||||
size_t
|
size_t
|
||||||
(ceil(max
|
(ceil(max
|
||||||
(m_maxProcessSize / m_pitchScale,
|
(m_maxProcessSize / m_pitchScale,
|
||||||
m_windowSize * 2 * (m_timeRatio > 1.f ? m_timeRatio : 1.f))));
|
m_sWindowSize * 2 * (m_timeRatio > 1.f ? m_timeRatio : 1.f))));
|
||||||
|
|
||||||
if (m_realtime) {
|
if (m_realtime) {
|
||||||
// This headroom is so as to try to avoid reallocation when
|
// This headroom is so as to try to avoid reallocation when
|
||||||
@@ -535,16 +542,22 @@ RubberBandStretcher::Impl::configure()
|
|||||||
// std::cerr << "configure[" << this << "]: realtime = " << m_realtime << ", pitch scale = "
|
// std::cerr << "configure[" << this << "]: realtime = " << m_realtime << ", pitch scale = "
|
||||||
// << m_pitchScale << ", channels = " << m_channels << std::endl;
|
// << m_pitchScale << ", channels = " << m_channels << std::endl;
|
||||||
|
|
||||||
size_t prevWindowSize = m_windowSize;
|
size_t prevFftSize = m_fftSize;
|
||||||
|
size_t prevAWindowSize = m_aWindowSize;
|
||||||
|
size_t prevSWindowSize = m_sWindowSize;
|
||||||
size_t prevOutbufSize = m_outbufSize;
|
size_t prevOutbufSize = m_outbufSize;
|
||||||
if (m_windows.empty()) {
|
if (m_windows.empty()) {
|
||||||
prevWindowSize = 0;
|
prevFftSize = 0;
|
||||||
|
prevAWindowSize = 0;
|
||||||
|
prevSWindowSize = 0;
|
||||||
prevOutbufSize = 0;
|
prevOutbufSize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
calculateSizes();
|
calculateSizes();
|
||||||
|
|
||||||
bool windowSizeChanged = (prevWindowSize != m_windowSize);
|
bool fftSizeChanged = (prevFftSize != m_fftSize);
|
||||||
|
bool windowSizeChanged = ((prevAWindowSize != m_aWindowSize) ||
|
||||||
|
(prevSWindowSize != m_sWindowSize));
|
||||||
bool outbufSizeChanged = (prevOutbufSize != m_outbufSize);
|
bool outbufSizeChanged = (prevOutbufSize != m_outbufSize);
|
||||||
|
|
||||||
// This function may be called at any time in non-RT mode, after a
|
// This function may be called at any time in non-RT mode, after a
|
||||||
@@ -557,12 +570,14 @@ RubberBandStretcher::Impl::configure()
|
|||||||
|
|
||||||
set<size_t> windowSizes;
|
set<size_t> windowSizes;
|
||||||
if (m_realtime) {
|
if (m_realtime) {
|
||||||
windowSizes.insert(m_baseWindowSize);
|
windowSizes.insert(m_baseFftSize);
|
||||||
windowSizes.insert(m_baseWindowSize / 2);
|
windowSizes.insert(m_baseFftSize / 2);
|
||||||
windowSizes.insert(m_baseWindowSize * 2);
|
windowSizes.insert(m_baseFftSize * 2);
|
||||||
// windowSizes.insert(m_baseWindowSize * 4);
|
// windowSizes.insert(m_baseFftSize * 4);
|
||||||
}
|
}
|
||||||
windowSizes.insert(m_windowSize);
|
windowSizes.insert(m_fftSize);
|
||||||
|
windowSizes.insert(m_aWindowSize);
|
||||||
|
windowSizes.insert(m_sWindowSize);
|
||||||
|
|
||||||
if (windowSizeChanged) {
|
if (windowSizeChanged) {
|
||||||
|
|
||||||
@@ -572,10 +587,11 @@ RubberBandStretcher::Impl::configure()
|
|||||||
m_windows[*i] = new Window<float>(HanningWindow, *i);
|
m_windows[*i] = new Window<float>(HanningWindow, *i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_window = m_windows[m_windowSize];
|
m_awindow = m_windows[m_aWindowSize];
|
||||||
|
m_swindow = m_windows[m_sWindowSize];
|
||||||
|
|
||||||
if (m_debugLevel > 0) {
|
if (m_debugLevel > 0) {
|
||||||
cerr << "Window area: " << m_window->getArea() << "; synthesis window area: " << m_window->getArea() << endl;
|
cerr << "Window area: " << m_awindow->getArea() << "; synthesis window area: " << m_swindow->getArea() << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -588,13 +604,16 @@ RubberBandStretcher::Impl::configure()
|
|||||||
|
|
||||||
for (size_t c = 0; c < m_channels; ++c) {
|
for (size_t c = 0; c < m_channels; ++c) {
|
||||||
m_channelData.push_back
|
m_channelData.push_back
|
||||||
(new ChannelData(windowSizes, 1, m_windowSize, m_outbufSize));
|
(new ChannelData(windowSizes,
|
||||||
|
std::max(m_aWindowSize, m_sWindowSize),
|
||||||
|
m_fftSize,
|
||||||
|
m_outbufSize));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_realtime && windowSizeChanged) {
|
if (!m_realtime && fftSizeChanged) {
|
||||||
delete m_studyFFT;
|
delete m_studyFFT;
|
||||||
m_studyFFT = new FFT(m_windowSize, m_debugLevel);
|
m_studyFFT = new FFT(m_fftSize, m_debugLevel);
|
||||||
m_studyFFT->initFloat();
|
m_studyFFT->initFloat();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -626,21 +645,21 @@ RubberBandStretcher::Impl::configure()
|
|||||||
|
|
||||||
delete m_phaseResetAudioCurve;
|
delete m_phaseResetAudioCurve;
|
||||||
m_phaseResetAudioCurve = new CompoundAudioCurve
|
m_phaseResetAudioCurve = new CompoundAudioCurve
|
||||||
(CompoundAudioCurve::Parameters(m_sampleRate, m_windowSize));
|
(CompoundAudioCurve::Parameters(m_sampleRate, m_fftSize));
|
||||||
m_phaseResetAudioCurve->setType(m_detectorType);
|
m_phaseResetAudioCurve->setType(m_detectorType);
|
||||||
|
|
||||||
delete m_silentAudioCurve;
|
delete m_silentAudioCurve;
|
||||||
m_silentAudioCurve = new SilentAudioCurve
|
m_silentAudioCurve = new SilentAudioCurve
|
||||||
(SilentAudioCurve::Parameters(m_sampleRate, m_windowSize));
|
(SilentAudioCurve::Parameters(m_sampleRate, m_fftSize));
|
||||||
|
|
||||||
if (!m_realtime) {
|
if (!m_realtime) {
|
||||||
delete m_stretchAudioCurve;
|
delete m_stretchAudioCurve;
|
||||||
if (!(m_options & OptionStretchPrecise)) {
|
if (!(m_options & OptionStretchPrecise)) {
|
||||||
m_stretchAudioCurve = new SpectralDifferenceAudioCurve
|
m_stretchAudioCurve = new SpectralDifferenceAudioCurve
|
||||||
(SpectralDifferenceAudioCurve::Parameters(m_sampleRate, m_windowSize));
|
(SpectralDifferenceAudioCurve::Parameters(m_sampleRate, m_fftSize));
|
||||||
} else {
|
} else {
|
||||||
m_stretchAudioCurve = new ConstantAudioCurve
|
m_stretchAudioCurve = new ConstantAudioCurve
|
||||||
(ConstantAudioCurve::Parameters(m_sampleRate, m_windowSize));
|
(ConstantAudioCurve::Parameters(m_sampleRate, m_fftSize));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -666,7 +685,7 @@ RubberBandStretcher::Impl::configure()
|
|||||||
if (!m_realtime) {
|
if (!m_realtime) {
|
||||||
for (size_t c = 0; c < m_channels; ++c) {
|
for (size_t c = 0; c < m_channels; ++c) {
|
||||||
m_channelData[c]->reset();
|
m_channelData[c]->reset();
|
||||||
m_channelData[c]->inbuf->zero(m_windowSize/2);
|
m_channelData[c]->inbuf->zero(m_aWindowSize/2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -688,7 +707,9 @@ RubberBandStretcher::Impl::reconfigure()
|
|||||||
configure();
|
configure();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t prevWindowSize = m_windowSize;
|
size_t prevFftSize = m_fftSize;
|
||||||
|
size_t prevAWindowSize = m_aWindowSize;
|
||||||
|
size_t prevSWindowSize = m_sWindowSize;
|
||||||
size_t prevOutbufSize = m_outbufSize;
|
size_t prevOutbufSize = m_outbufSize;
|
||||||
|
|
||||||
calculateSizes();
|
calculateSizes();
|
||||||
@@ -698,18 +719,29 @@ RubberBandStretcher::Impl::reconfigure()
|
|||||||
// where not all of the things we need were correctly created when
|
// where not all of the things we need were correctly created when
|
||||||
// we first configured (for whatever reason). This is intended to
|
// we first configured (for whatever reason). This is intended to
|
||||||
// be "effectively" realtime safe. The same goes for
|
// be "effectively" realtime safe. The same goes for
|
||||||
// ChannelData::setOutbufSize and setWindowSize.
|
// ChannelData::setOutbufSize and setSizes.
|
||||||
|
|
||||||
if (m_windowSize != prevWindowSize) {
|
if (m_aWindowSize != prevAWindowSize ||
|
||||||
|
m_sWindowSize != prevSWindowSize) {
|
||||||
|
|
||||||
if (m_windows.find(m_windowSize) == m_windows.end()) {
|
if (m_windows.find(m_aWindowSize) == m_windows.end()) {
|
||||||
std::cerr << "WARNING: reconfigure(): window allocation (size " << m_windowSize << ") required in RT mode" << std::endl;
|
std::cerr << "WARNING: reconfigure(): window allocation (size " << m_aWindowSize << ") required in RT mode" << std::endl;
|
||||||
m_windows[m_windowSize] = new Window<float>(HanningWindow, m_windowSize);
|
m_windows[m_aWindowSize] = new Window<float>
|
||||||
|
(HanningWindow, m_aWindowSize);
|
||||||
}
|
}
|
||||||
m_window = m_windows[m_windowSize];
|
|
||||||
|
if (m_windows.find(m_sWindowSize) == m_windows.end()) {
|
||||||
|
std::cerr << "WARNING: reconfigure(): window allocation (size " << m_sWindowSize << ") required in RT mode" << std::endl;
|
||||||
|
m_windows[m_sWindowSize] = new Window<float>
|
||||||
|
(HanningWindow, m_sWindowSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_awindow = m_windows[m_aWindowSize];
|
||||||
|
m_swindow = m_windows[m_sWindowSize];
|
||||||
|
|
||||||
for (size_t c = 0; c < m_channels; ++c) {
|
for (size_t c = 0; c < m_channels; ++c) {
|
||||||
m_channelData[c]->setWindowSize(m_windowSize);
|
m_channelData[c]->setSizes(std::max(m_aWindowSize, m_sWindowSize),
|
||||||
|
m_fftSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -727,7 +759,7 @@ RubberBandStretcher::Impl::reconfigure()
|
|||||||
std::cerr << "WARNING: reconfigure(): resampler construction required in RT mode" << std::endl;
|
std::cerr << "WARNING: reconfigure(): resampler construction required in RT mode" << std::endl;
|
||||||
|
|
||||||
m_channelData[c]->resampler =
|
m_channelData[c]->resampler =
|
||||||
new Resampler(Resampler::FastestTolerable, 1, m_windowSize,
|
new Resampler(Resampler::FastestTolerable, 1, m_sWindowSize,
|
||||||
m_debugLevel);
|
m_debugLevel);
|
||||||
|
|
||||||
m_channelData[c]->setResampleBufSize
|
m_channelData[c]->setResampleBufSize
|
||||||
@@ -735,8 +767,8 @@ RubberBandStretcher::Impl::reconfigure()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_windowSize != prevWindowSize) {
|
if (m_fftSize != prevFftSize) {
|
||||||
m_phaseResetAudioCurve->setWindowSize(m_windowSize);
|
m_phaseResetAudioCurve->setFftSize(m_fftSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -744,7 +776,7 @@ size_t
|
|||||||
RubberBandStretcher::Impl::getLatency() const
|
RubberBandStretcher::Impl::getLatency() const
|
||||||
{
|
{
|
||||||
if (!m_realtime) return 0;
|
if (!m_realtime) return 0;
|
||||||
return int((m_windowSize/2) / m_pitchScale + 1);
|
return int((m_aWindowSize/2) / m_pitchScale + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -887,21 +919,24 @@ RubberBandStretcher::Impl::study(const float *const *input, size_t samples, bool
|
|||||||
consumed += writable;
|
consumed += writable;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((inbuf.getReadSpace() >= int(m_windowSize)) ||
|
while ((inbuf.getReadSpace() >= int(m_aWindowSize)) ||
|
||||||
(final && (inbuf.getReadSpace() >= int(m_windowSize/2)))) {
|
(final && (inbuf.getReadSpace() >= int(m_aWindowSize/2)))) {
|
||||||
|
|
||||||
// We know we have at least m_windowSize samples available
|
// We know we have at least m_aWindowSize samples
|
||||||
// in m_inbuf. We need to peek m_windowSize of them for
|
// available in m_inbuf. We need to peek m_aWindowSize of
|
||||||
// processing, and then skip m_increment to advance the
|
// them for processing, and then skip m_increment to
|
||||||
// read pointer.
|
// advance the read pointer.
|
||||||
|
|
||||||
// cd.accumulator is not otherwise used during studying,
|
// cd.accumulator is not otherwise used during studying,
|
||||||
// so we can use it as a temporary buffer here
|
// so we can use it as a temporary buffer here
|
||||||
|
|
||||||
size_t got = inbuf.peek(cd.accumulator, m_windowSize);
|
size_t got = inbuf.peek(cd.accumulator, m_aWindowSize);
|
||||||
assert(final || got == m_windowSize);
|
assert(final || got == m_aWindowSize);
|
||||||
|
|
||||||
m_window->cut(cd.accumulator);
|
m_awindow->cut(cd.accumulator);
|
||||||
|
|
||||||
|
//!!! insert appropriate cunning here if m_aWindowSize !=
|
||||||
|
//!!! m_fftSize
|
||||||
|
|
||||||
// We don't need the fftshift for studying, as we're only
|
// We don't need the fftshift for studying, as we're only
|
||||||
// interested in magnitude
|
// interested in magnitude
|
||||||
@@ -925,12 +960,12 @@ RubberBandStretcher::Impl::study(const float *const *input, size_t samples, bool
|
|||||||
|
|
||||||
// cout << df << endl;
|
// cout << df << endl;
|
||||||
|
|
||||||
// We have augmented the input by m_windowSize/2 so
|
// We have augmented the input by m_aWindowSize/2 so that
|
||||||
// that the first chunk is centred on the first audio
|
// the first chunk is centred on the first audio sample.
|
||||||
// sample. We want to ensure that m_inputDuration
|
// We want to ensure that m_inputDuration contains the
|
||||||
// contains the exact input duration without including
|
// exact input duration without including this extra bit.
|
||||||
// this extra bit. We just add up all the increments
|
// We just add up all the increments here, and deduct the
|
||||||
// here, and deduct the extra afterwards.
|
// extra afterwards.
|
||||||
|
|
||||||
m_inputDuration += m_increment;
|
m_inputDuration += m_increment;
|
||||||
// cerr << "incr input duration by increment: " << m_increment << " -> " << m_inputDuration << endl;
|
// cerr << "incr input duration by increment: " << m_increment << " -> " << m_inputDuration << endl;
|
||||||
@@ -943,8 +978,8 @@ RubberBandStretcher::Impl::study(const float *const *input, size_t samples, bool
|
|||||||
m_inputDuration += rs;
|
m_inputDuration += rs;
|
||||||
// cerr << "incr input duration by read space: " << rs << " -> " << m_inputDuration << endl;
|
// cerr << "incr input duration by read space: " << rs << " -> " << m_inputDuration << endl;
|
||||||
|
|
||||||
if (m_inputDuration > m_windowSize/2) { // deducting the extra
|
if (m_inputDuration > m_aWindowSize/2) { // deducting the extra
|
||||||
m_inputDuration -= m_windowSize/2;
|
m_inputDuration -= m_aWindowSize/2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1029,7 +1064,7 @@ RubberBandStretcher::Impl::calculateStretch()
|
|||||||
if (i >= m_silence.size()) break;
|
if (i >= m_silence.size()) break;
|
||||||
if (m_silence[i]) ++history;
|
if (m_silence[i]) ++history;
|
||||||
else history = 0;
|
else history = 0;
|
||||||
if (history >= int(m_windowSize / m_increment) && increments[i] >= 0) {
|
if (history >= int(m_aWindowSize / m_increment) && increments[i] >= 0) {
|
||||||
increments[i] = -increments[i];
|
increments[i] = -increments[i];
|
||||||
if (m_debugLevel > 1) {
|
if (m_debugLevel > 1) {
|
||||||
std::cerr << "phase reset on silence (silent history == "
|
std::cerr << "phase reset on silence (silent history == "
|
||||||
@@ -1073,16 +1108,16 @@ RubberBandStretcher::Impl::getSamplesRequired() const
|
|||||||
|
|
||||||
// See notes in testInbufReadSpace
|
// See notes in testInbufReadSpace
|
||||||
|
|
||||||
if (rs < m_windowSize && !cd.draining) {
|
if (rs < m_aWindowSize && !cd.draining) {
|
||||||
|
|
||||||
if (cd.inputSize == -1) {
|
if (cd.inputSize == -1) {
|
||||||
reqdHere = m_windowSize - rs;
|
reqdHere = m_aWindowSize - rs;
|
||||||
if (reqdHere > reqd) reqd = reqdHere;
|
if (reqdHere > reqd) reqd = reqdHere;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rs == 0) {
|
if (rs == 0) {
|
||||||
reqdHere = m_windowSize;
|
reqdHere = m_aWindowSize;
|
||||||
if (reqdHere > reqd) reqd = reqdHere;
|
if (reqdHere > reqd) reqd = reqdHere;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1110,7 +1145,7 @@ RubberBandStretcher::Impl::process(const float *const *input, size_t samples, bo
|
|||||||
|
|
||||||
for (size_t c = 0; c < m_channels; ++c) {
|
for (size_t c = 0; c < m_channels; ++c) {
|
||||||
m_channelData[c]->reset();
|
m_channelData[c]->reset();
|
||||||
m_channelData[c]->inbuf->zero(m_windowSize/2);
|
m_channelData[c]->inbuf->zero(m_aWindowSize/2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_threaded) {
|
if (m_threaded) {
|
||||||
|
|||||||
@@ -123,7 +123,11 @@ protected:
|
|||||||
double m_timeRatio;
|
double m_timeRatio;
|
||||||
double m_pitchScale;
|
double m_pitchScale;
|
||||||
|
|
||||||
size_t m_windowSize;
|
// n.b. either m_fftSize is an integer multiple of m_windowSize,
|
||||||
|
// or vice versa
|
||||||
|
size_t m_fftSize;
|
||||||
|
size_t m_aWindowSize; //!!! or use m_awindow->getSize() throughout?
|
||||||
|
size_t m_sWindowSize; //!!! or use m_swindow->getSize() throughout?
|
||||||
size_t m_increment;
|
size_t m_increment;
|
||||||
size_t m_outbufSize;
|
size_t m_outbufSize;
|
||||||
|
|
||||||
@@ -145,7 +149,8 @@ protected:
|
|||||||
ProcessMode m_mode;
|
ProcessMode m_mode;
|
||||||
|
|
||||||
std::map<size_t, Window<float> *> m_windows;
|
std::map<size_t, Window<float> *> m_windows;
|
||||||
Window<float> *m_window;
|
Window<float> *m_awindow;
|
||||||
|
Window<float> *m_swindow;
|
||||||
FFT *m_studyFFT;
|
FFT *m_studyFFT;
|
||||||
|
|
||||||
Condition m_spaceAvailable;
|
Condition m_spaceAvailable;
|
||||||
@@ -194,7 +199,7 @@ protected:
|
|||||||
float m_freq1;
|
float m_freq1;
|
||||||
float m_freq2;
|
float m_freq2;
|
||||||
|
|
||||||
size_t m_baseWindowSize;
|
size_t m_baseFftSize;
|
||||||
float m_rateMultiple;
|
float m_rateMultiple;
|
||||||
|
|
||||||
void writeOutput(RingBuffer<float> &to, float *from,
|
void writeOutput(RingBuffer<float> &to, float *from,
|
||||||
@@ -202,7 +207,7 @@ protected:
|
|||||||
|
|
||||||
static int m_defaultDebugLevel;
|
static int m_defaultDebugLevel;
|
||||||
static const size_t m_defaultIncrement;
|
static const size_t m_defaultIncrement;
|
||||||
static const size_t m_defaultWindowSize;
|
static const size_t m_defaultFftSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -215,8 +215,8 @@ RubberBandStretcher::Impl::processChunks(size_t c, bool &any, bool &last)
|
|||||||
any = true;
|
any = true;
|
||||||
|
|
||||||
if (!cd.draining) {
|
if (!cd.draining) {
|
||||||
size_t got = cd.inbuf->peek(cd.fltbuf, m_windowSize);
|
size_t got = cd.inbuf->peek(cd.fltbuf, m_aWindowSize);
|
||||||
assert(got == m_windowSize || cd.inputSize >= 0);
|
assert(got == m_aWindowSize || cd.inputSize >= 0);
|
||||||
cd.inbuf->skip(m_increment);
|
cd.inbuf->skip(m_increment);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,20 +224,20 @@ RubberBandStretcher::Impl::processChunks(size_t c, bool &any, bool &last)
|
|||||||
size_t phaseIncrement, shiftIncrement;
|
size_t phaseIncrement, shiftIncrement;
|
||||||
getIncrements(c, phaseIncrement, shiftIncrement, phaseReset);
|
getIncrements(c, phaseIncrement, shiftIncrement, phaseReset);
|
||||||
|
|
||||||
if (shiftIncrement <= m_windowSize) {
|
if (shiftIncrement <= m_aWindowSize) {
|
||||||
analyseChunk(c);
|
analyseChunk(c);
|
||||||
last = processChunkForChannel
|
last = processChunkForChannel
|
||||||
(c, phaseIncrement, shiftIncrement, phaseReset);
|
(c, phaseIncrement, shiftIncrement, phaseReset);
|
||||||
} else {
|
} else {
|
||||||
size_t bit = m_windowSize/4;
|
size_t bit = m_aWindowSize/4;
|
||||||
if (m_debugLevel > 1) {
|
if (m_debugLevel > 1) {
|
||||||
cerr << "channel " << c << " breaking down overlong increment " << shiftIncrement << " into " << bit << "-size bits" << endl;
|
cerr << "channel " << c << " breaking down overlong increment " << shiftIncrement << " into " << bit << "-size bits" << endl;
|
||||||
}
|
}
|
||||||
analyseChunk(c);
|
analyseChunk(c);
|
||||||
float *tmp = (float *)alloca(m_windowSize * sizeof(float));
|
float *tmp = (float *)alloca(m_aWindowSize * sizeof(float));
|
||||||
v_copy(tmp, cd.fltbuf, m_windowSize);
|
v_copy(tmp, cd.fltbuf, m_aWindowSize);
|
||||||
for (size_t i = 0; i < shiftIncrement; i += bit) {
|
for (size_t i = 0; i < shiftIncrement; i += bit) {
|
||||||
v_copy(cd.fltbuf, tmp, m_windowSize);
|
v_copy(cd.fltbuf, tmp, m_aWindowSize);
|
||||||
size_t thisIncrement = bit;
|
size_t thisIncrement = bit;
|
||||||
if (i + thisIncrement > shiftIncrement) {
|
if (i + thisIncrement > shiftIncrement) {
|
||||||
thisIncrement = shiftIncrement - i;
|
thisIncrement = shiftIncrement - i;
|
||||||
@@ -270,8 +270,8 @@ RubberBandStretcher::Impl::processOneChunk()
|
|||||||
if (!testInbufReadSpace(c)) return false;
|
if (!testInbufReadSpace(c)) return false;
|
||||||
ChannelData &cd = *m_channelData[c];
|
ChannelData &cd = *m_channelData[c];
|
||||||
if (!cd.draining) {
|
if (!cd.draining) {
|
||||||
size_t got = cd.inbuf->peek(cd.fltbuf, m_windowSize);
|
size_t got = cd.inbuf->peek(cd.fltbuf, m_aWindowSize);
|
||||||
assert(got == m_windowSize || cd.inputSize >= 0);
|
assert(got == m_aWindowSize || cd.inputSize >= 0);
|
||||||
cd.inbuf->skip(m_increment);
|
cd.inbuf->skip(m_increment);
|
||||||
analyseChunk(c);
|
analyseChunk(c);
|
||||||
}
|
}
|
||||||
@@ -302,7 +302,7 @@ RubberBandStretcher::Impl::testInbufReadSpace(size_t c)
|
|||||||
|
|
||||||
size_t rs = inbuf.getReadSpace();
|
size_t rs = inbuf.getReadSpace();
|
||||||
|
|
||||||
if (rs < m_windowSize && !cd.draining) {
|
if (rs < m_aWindowSize && !cd.draining) {
|
||||||
|
|
||||||
if (cd.inputSize == -1) {
|
if (cd.inputSize == -1) {
|
||||||
|
|
||||||
@@ -328,7 +328,7 @@ RubberBandStretcher::Impl::testInbufReadSpace(size_t c)
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
} else if (rs < m_windowSize/2) {
|
} else if (rs < m_aWindowSize/2) {
|
||||||
|
|
||||||
if (m_debugLevel > 1) {
|
if (m_debugLevel > 1) {
|
||||||
cerr << "read space = " << rs << ", setting draining true" << endl;
|
cerr << "read space = " << rs << ", setting draining true" << endl;
|
||||||
@@ -368,12 +368,12 @@ RubberBandStretcher::Impl::processChunkForChannel(size_t c,
|
|||||||
// to write from the existing accumulator into the output.
|
// to write from the existing accumulator into the output.
|
||||||
|
|
||||||
// We know we have enough samples available in m_inbuf --
|
// We know we have enough samples available in m_inbuf --
|
||||||
// this is usually m_windowSize, but we know that if fewer
|
// this is usually m_aWindowSize, but we know that if fewer
|
||||||
// are available, it's OK to use zeroes for the rest
|
// are available, it's OK to use zeroes for the rest
|
||||||
// (which the ring buffer will provide) because we've
|
// (which the ring buffer will provide) because we've
|
||||||
// reached the true end of the data.
|
// reached the true end of the data.
|
||||||
|
|
||||||
// We need to peek m_windowSize samples for processing, and
|
// We need to peek m_aWindowSize samples for processing, and
|
||||||
// then skip m_increment to advance the read pointer.
|
// then skip m_increment to advance the read pointer.
|
||||||
|
|
||||||
modifyChunk(c, phaseIncrement, phaseReset);
|
modifyChunk(c, phaseIncrement, phaseReset);
|
||||||
@@ -474,7 +474,7 @@ RubberBandStretcher::Impl::calculateIncrements(size_t &phaseIncrementRtn,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const int hs = m_windowSize/2 + 1;
|
const int hs = m_fftSize/2 + 1;
|
||||||
|
|
||||||
// Normally we would mix down the time-domain signal and apply a
|
// Normally we would mix down the time-domain signal and apply a
|
||||||
// single FFT, or else mix down the Cartesian form of the
|
// single FFT, or else mix down the Cartesian form of the
|
||||||
@@ -544,7 +544,7 @@ RubberBandStretcher::Impl::calculateIncrements(size_t &phaseIncrementRtn,
|
|||||||
if (silent) ++m_silentHistory;
|
if (silent) ++m_silentHistory;
|
||||||
else m_silentHistory = 0;
|
else m_silentHistory = 0;
|
||||||
|
|
||||||
if (m_silentHistory >= int(m_windowSize / m_increment) && !phaseReset) {
|
if (m_silentHistory >= int(m_aWindowSize / m_increment) && !phaseReset) {
|
||||||
phaseReset = true;
|
phaseReset = true;
|
||||||
if (m_debugLevel > 1) {
|
if (m_debugLevel > 1) {
|
||||||
cerr << "calculateIncrements: phase reset on silence (silent history == "
|
cerr << "calculateIncrements: phase reset on silence (silent history == "
|
||||||
@@ -641,37 +641,24 @@ RubberBandStretcher::Impl::analyseChunk(size_t channel)
|
|||||||
double *const R__ dblbuf = cd.dblbuf;
|
double *const R__ dblbuf = cd.dblbuf;
|
||||||
float *const R__ fltbuf = cd.fltbuf;
|
float *const R__ fltbuf = cd.fltbuf;
|
||||||
|
|
||||||
int sz = m_windowSize;
|
int sz = m_fftSize;
|
||||||
int hs = m_windowSize/2;
|
int hs = sz / 2;
|
||||||
|
|
||||||
// cd.fltbuf is known to contain m_windowSize samples
|
// cd.fltbuf is known to contain m_aWindowSize samples
|
||||||
|
|
||||||
m_window->cut(fltbuf);
|
m_awindow->cut(fltbuf);
|
||||||
|
|
||||||
if (cd.oversample > 1) {
|
if (m_aWindowSize == m_fftSize) {
|
||||||
|
|
||||||
int bufsiz = sz * cd.oversample;
|
|
||||||
int offset = (bufsiz - sz) / 2;
|
|
||||||
|
|
||||||
// eek
|
|
||||||
|
|
||||||
for (i = 0; i < offset; ++i) {
|
|
||||||
dblbuf[i] = 0.0;
|
|
||||||
}
|
|
||||||
for (i = 0; i < offset; ++i) {
|
|
||||||
dblbuf[bufsiz - i - 1] = 0.0;
|
|
||||||
}
|
|
||||||
for (i = 0; i < sz; ++i) {
|
|
||||||
dblbuf[offset + i] = fltbuf[i];
|
|
||||||
}
|
|
||||||
for (i = 0; i < bufsiz / 2; ++i) {
|
|
||||||
double tmp = dblbuf[i];
|
|
||||||
dblbuf[i] = dblbuf[i + bufsiz/2];
|
|
||||||
dblbuf[i + bufsiz/2] = tmp;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
v_convert(dblbuf, fltbuf + hs, hs);
|
v_convert(dblbuf, fltbuf + hs, hs);
|
||||||
v_convert(dblbuf + hs, fltbuf, hs);
|
v_convert(dblbuf + hs, fltbuf, hs);
|
||||||
|
} else {
|
||||||
|
v_zero(dblbuf, sz);
|
||||||
|
int j = sz - m_aWindowSize/2;
|
||||||
|
while (j < 0) j += sz;
|
||||||
|
for (int i = 0; i < m_aWindowSize; ++i) {
|
||||||
|
dblbuf[j] += fltbuf[i];
|
||||||
|
if (++j == sz) j = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cd.fft->forwardPolar(dblbuf, cd.mag, cd.phase);
|
cd.fft->forwardPolar(dblbuf, cd.mag, cd.phase);
|
||||||
@@ -691,15 +678,14 @@ RubberBandStretcher::Impl::modifyChunk(size_t channel,
|
|||||||
}
|
}
|
||||||
|
|
||||||
const double rate = m_sampleRate;
|
const double rate = m_sampleRate;
|
||||||
const int sz = m_windowSize;
|
const int count = m_fftSize / 2;
|
||||||
const int count = (sz * cd.oversample) / 2;
|
|
||||||
|
|
||||||
bool unchanged = cd.unchanged && (outputIncrement == m_increment);
|
bool unchanged = cd.unchanged && (outputIncrement == m_increment);
|
||||||
bool fullReset = phaseReset;
|
bool fullReset = phaseReset;
|
||||||
bool laminar = !(m_options & OptionPhaseIndependent);
|
bool laminar = !(m_options & OptionPhaseIndependent);
|
||||||
bool bandlimited = (m_options & OptionTransientsMixed);
|
bool bandlimited = (m_options & OptionTransientsMixed);
|
||||||
int bandlow = lrint((150 * sz * cd.oversample) / rate);
|
int bandlow = lrint((150 * m_fftSize) / rate);
|
||||||
int bandhigh = lrint((1000 * sz * cd.oversample) / rate);
|
int bandhigh = lrint((1000 * m_fftSize) / rate);
|
||||||
|
|
||||||
float freq0 = m_freq0;
|
float freq0 = m_freq0;
|
||||||
float freq1 = m_freq1;
|
float freq1 = m_freq1;
|
||||||
@@ -717,9 +703,9 @@ RubberBandStretcher::Impl::modifyChunk(size_t channel,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int limit0 = lrint((freq0 * sz * cd.oversample) / rate);
|
int limit0 = lrint((freq0 * m_fftSize) / rate);
|
||||||
int limit1 = lrint((freq1 * sz * cd.oversample) / rate);
|
int limit1 = lrint((freq1 * m_fftSize) / rate);
|
||||||
int limit2 = lrint((freq2 * sz * cd.oversample) / rate);
|
int limit2 = lrint((freq2 * m_fftSize) / rate);
|
||||||
|
|
||||||
if (limit1 < limit0) limit1 = limit0;
|
if (limit1 < limit0) limit1 = limit0;
|
||||||
if (limit2 < limit1) limit2 = limit1;
|
if (limit2 < limit1) limit2 = limit1;
|
||||||
@@ -758,7 +744,7 @@ RubberBandStretcher::Impl::modifyChunk(size_t channel,
|
|||||||
|
|
||||||
if (!resetThis) {
|
if (!resetThis) {
|
||||||
|
|
||||||
double omega = (2 * M_PI * m_increment * i) / (sz * cd.oversample);
|
double omega = (2 * M_PI * m_increment * i) / (m_fftSize);
|
||||||
|
|
||||||
double pp = cd.prevPhase[i];
|
double pp = cd.prevPhase[i];
|
||||||
double ep = pp + omega;
|
double ep = pp + omega;
|
||||||
@@ -833,8 +819,8 @@ RubberBandStretcher::Impl::formantShiftChunk(size_t channel)
|
|||||||
double *const R__ envelope = cd.envelope;
|
double *const R__ envelope = cd.envelope;
|
||||||
double *const R__ dblbuf = cd.dblbuf;
|
double *const R__ dblbuf = cd.dblbuf;
|
||||||
|
|
||||||
const int sz = m_windowSize;
|
const int sz = m_fftSize;
|
||||||
const int hs = m_windowSize/2;
|
const int hs = sz / 2;
|
||||||
const double factor = 1.0 / sz;
|
const double factor = 1.0 / sz;
|
||||||
|
|
||||||
cd.fft->inverseCepstral(mag, dblbuf);
|
cd.fft->inverseCepstral(mag, dblbuf);
|
||||||
@@ -861,7 +847,7 @@ RubberBandStretcher::Impl::formantShiftChunk(size_t channel)
|
|||||||
// scaling up, we want a new envelope that is lower by the pitch factor
|
// scaling up, we want a new envelope that is lower by the pitch factor
|
||||||
for (int target = 0; target <= hs; ++target) {
|
for (int target = 0; target <= hs; ++target) {
|
||||||
int source = lrint(target * m_pitchScale);
|
int source = lrint(target * m_pitchScale);
|
||||||
if (source > int(m_windowSize)) {
|
if (source > sz) {
|
||||||
envelope[target] = 0.0;
|
envelope[target] = 0.0;
|
||||||
} else {
|
} else {
|
||||||
envelope[target] = envelope[source];
|
envelope[target] = envelope[source];
|
||||||
@@ -899,47 +885,40 @@ RubberBandStretcher::Impl::synthesiseChunk(size_t channel)
|
|||||||
float *const R__ accumulator = cd.accumulator;
|
float *const R__ accumulator = cd.accumulator;
|
||||||
float *const R__ windowAccumulator = cd.windowAccumulator;
|
float *const R__ windowAccumulator = cd.windowAccumulator;
|
||||||
|
|
||||||
int sz = m_windowSize;
|
int sz = m_fftSize;
|
||||||
int hs = m_windowSize/2;
|
int hs = sz / 2;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
|
||||||
if (!cd.unchanged) {
|
if (!cd.unchanged) {
|
||||||
|
|
||||||
cd.fft->inversePolar(cd.mag, cd.phase, cd.dblbuf);
|
cd.fft->inversePolar(cd.mag, cd.phase, cd.dblbuf);
|
||||||
|
|
||||||
if (cd.oversample > 1) {
|
// our ffts produced unscaled results
|
||||||
|
float factor = 1.0 / m_fftSize;
|
||||||
|
v_scale(dblbuf, factor, sz);
|
||||||
|
|
||||||
int bufsiz = sz * cd.oversample;
|
if (m_sWindowSize == m_fftSize) {
|
||||||
int hbs = hs * cd.oversample;
|
|
||||||
int offset = (bufsiz - sz) / 2;
|
|
||||||
|
|
||||||
for (i = 0; i < hbs; ++i) {
|
|
||||||
double tmp = dblbuf[i];
|
|
||||||
dblbuf[i] = dblbuf[i + hbs];
|
|
||||||
dblbuf[i + hbs] = tmp;
|
|
||||||
}
|
|
||||||
for (i = 0; i < sz; ++i) {
|
|
||||||
fltbuf[i] = float(dblbuf[i + offset]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
v_convert(fltbuf, dblbuf + hs, hs);
|
v_convert(fltbuf, dblbuf + hs, hs);
|
||||||
v_convert(fltbuf + hs, dblbuf, hs);
|
v_convert(fltbuf + hs, dblbuf, hs);
|
||||||
|
} else {
|
||||||
|
v_zero(fltbuf, m_sWindowSize);
|
||||||
|
int j = sz - m_sWindowSize/2;
|
||||||
|
while (j < 0) j += sz;
|
||||||
|
for (int i = 0; i < m_sWindowSize; ++i) {
|
||||||
|
fltbuf[i] += dblbuf[j];
|
||||||
|
if (++j == sz) j = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// our ffts produced unscaled results
|
m_swindow->cut(fltbuf);
|
||||||
float factor = 1.f / float(sz * cd.oversample);
|
|
||||||
v_scale(fltbuf, factor, sz);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_window->cut(fltbuf);
|
v_add(accumulator, fltbuf, m_sWindowSize);
|
||||||
|
|
||||||
v_add(accumulator, fltbuf, sz);
|
cd.accumulatorFill = m_sWindowSize;
|
||||||
|
|
||||||
cd.accumulatorFill = m_windowSize;
|
float fixed = m_swindow->getArea() * 1.5f;
|
||||||
|
m_swindow->add(windowAccumulator, fixed);
|
||||||
float fixed = m_window->getArea() * 1.5f;
|
|
||||||
m_window->add(windowAccumulator, fixed);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -952,7 +931,7 @@ RubberBandStretcher::Impl::writeChunk(size_t channel, size_t shiftIncrement, boo
|
|||||||
float *const R__ accumulator = cd.accumulator;
|
float *const R__ accumulator = cd.accumulator;
|
||||||
float *const R__ windowAccumulator = cd.windowAccumulator;
|
float *const R__ windowAccumulator = cd.windowAccumulator;
|
||||||
|
|
||||||
const int sz = m_windowSize;
|
const int sz = m_sWindowSize;
|
||||||
const int si = shiftIncrement;
|
const int si = shiftIncrement;
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
@@ -1035,7 +1014,7 @@ RubberBandStretcher::Impl::writeOutput(RingBuffer<float> &to, float *from, size_
|
|||||||
|
|
||||||
size_t startSkip = 0;
|
size_t startSkip = 0;
|
||||||
if (!m_realtime) {
|
if (!m_realtime) {
|
||||||
startSkip = lrintf((m_windowSize/2) / m_pitchScale);
|
startSkip = lrintf((m_sWindowSize/2) / m_pitchScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (outCount > startSkip) {
|
if (outCount > startSkip) {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ static const int MaxPerceivedFreq = 16000;
|
|||||||
|
|
||||||
AudioCurveCalculator::AudioCurveCalculator(Parameters parameters) :
|
AudioCurveCalculator::AudioCurveCalculator(Parameters parameters) :
|
||||||
m_sampleRate(parameters.sampleRate),
|
m_sampleRate(parameters.sampleRate),
|
||||||
m_windowSize(parameters.windowSize)
|
m_fftSize(parameters.fftSize)
|
||||||
{
|
{
|
||||||
recalculateLastPerceivedBin();
|
recalculateLastPerceivedBin();
|
||||||
}
|
}
|
||||||
@@ -40,9 +40,9 @@ AudioCurveCalculator::setSampleRate(int newRate)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AudioCurveCalculator::setWindowSize(int newSize)
|
AudioCurveCalculator::setFftSize(int newSize)
|
||||||
{
|
{
|
||||||
m_windowSize = newSize;
|
m_fftSize = newSize;
|
||||||
recalculateLastPerceivedBin();
|
recalculateLastPerceivedBin();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,9 +53,9 @@ AudioCurveCalculator::recalculateLastPerceivedBin()
|
|||||||
m_lastPerceivedBin = 0;
|
m_lastPerceivedBin = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_lastPerceivedBin = ((MaxPerceivedFreq * m_windowSize) / m_sampleRate);
|
m_lastPerceivedBin = ((MaxPerceivedFreq * m_fftSize) / m_sampleRate);
|
||||||
if (m_lastPerceivedBin > m_windowSize/2) {
|
if (m_lastPerceivedBin > m_fftSize/2) {
|
||||||
m_lastPerceivedBin = m_windowSize/2;
|
m_lastPerceivedBin = m_fftSize/2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,29 +27,29 @@ class AudioCurveCalculator
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
struct Parameters {
|
struct Parameters {
|
||||||
Parameters(int _sampleRate, int _windowSize) :
|
Parameters(int _sampleRate, int _fftSize) :
|
||||||
sampleRate(_sampleRate),
|
sampleRate(_sampleRate),
|
||||||
windowSize(_windowSize)
|
fftSize(_fftSize)
|
||||||
{ }
|
{ }
|
||||||
int sampleRate;
|
int sampleRate;
|
||||||
int windowSize;
|
int fftSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
AudioCurveCalculator(Parameters parameters);
|
AudioCurveCalculator(Parameters parameters);
|
||||||
virtual ~AudioCurveCalculator();
|
virtual ~AudioCurveCalculator();
|
||||||
|
|
||||||
int getSampleRate() const { return m_sampleRate; }
|
int getSampleRate() const { return m_sampleRate; }
|
||||||
int getWindowSize() const { return m_windowSize; }
|
int getFftSize() const { return m_fftSize; }
|
||||||
|
|
||||||
virtual void setSampleRate(int newRate);
|
virtual void setSampleRate(int newRate);
|
||||||
virtual void setWindowSize(int newSize);
|
virtual void setFftSize(int newSize);
|
||||||
|
|
||||||
Parameters getParameters() const {
|
Parameters getParameters() const {
|
||||||
return Parameters(m_sampleRate, m_windowSize);
|
return Parameters(m_sampleRate, m_fftSize);
|
||||||
}
|
}
|
||||||
void setParameters(Parameters p) {
|
void setParameters(Parameters p) {
|
||||||
setSampleRate(p.sampleRate);
|
setSampleRate(p.sampleRate);
|
||||||
setWindowSize(p.windowSize);
|
setFftSize(p.fftSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
// You may not mix calls to the various process functions on a
|
// You may not mix calls to the various process functions on a
|
||||||
@@ -65,7 +65,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
int m_sampleRate;
|
int m_sampleRate;
|
||||||
int m_windowSize;
|
int m_fftSize;
|
||||||
int m_lastPerceivedBin;
|
int m_lastPerceivedBin;
|
||||||
void recalculateLastPerceivedBin();
|
void recalculateLastPerceivedBin();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -58,11 +58,11 @@ CompoundAudioCurve::reset()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CompoundAudioCurve::setWindowSize(int newSize)
|
CompoundAudioCurve::setFftSize(int newSize)
|
||||||
{
|
{
|
||||||
m_percussive.setWindowSize(newSize);
|
m_percussive.setFftSize(newSize);
|
||||||
m_hf.setWindowSize(newSize);
|
m_hf.setFftSize(newSize);
|
||||||
m_windowSize = newSize;
|
m_fftSize = newSize;
|
||||||
m_lastHf = 0.0;
|
m_lastHf = 0.0;
|
||||||
m_lastResult = 0.0;
|
m_lastResult = 0.0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public:
|
|||||||
};
|
};
|
||||||
virtual void setType(Type);
|
virtual void setType(Type);
|
||||||
|
|
||||||
virtual void setWindowSize(int newSize);
|
virtual void setFftSize(int newSize);
|
||||||
|
|
||||||
virtual float processFloat(const float *R__ mag, int increment);
|
virtual float processFloat(const float *R__ mag, int increment);
|
||||||
virtual double processDouble(const double *R__ mag, int increment);
|
virtual double processDouble(const double *R__ mag, int increment);
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace RubberBand
|
|||||||
PercussiveAudioCurve::PercussiveAudioCurve(Parameters parameters) :
|
PercussiveAudioCurve::PercussiveAudioCurve(Parameters parameters) :
|
||||||
AudioCurveCalculator(parameters)
|
AudioCurveCalculator(parameters)
|
||||||
{
|
{
|
||||||
m_prevMag = allocate_and_zero<double>(m_windowSize/2 + 1);
|
m_prevMag = allocate_and_zero<double>(m_fftSize/2 + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
PercussiveAudioCurve::~PercussiveAudioCurve()
|
PercussiveAudioCurve::~PercussiveAudioCurve()
|
||||||
@@ -37,14 +37,14 @@ PercussiveAudioCurve::~PercussiveAudioCurve()
|
|||||||
void
|
void
|
||||||
PercussiveAudioCurve::reset()
|
PercussiveAudioCurve::reset()
|
||||||
{
|
{
|
||||||
v_zero(m_prevMag, m_windowSize/2 + 1);
|
v_zero(m_prevMag, m_fftSize/2 + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PercussiveAudioCurve::setWindowSize(int newSize)
|
PercussiveAudioCurve::setFftSize(int newSize)
|
||||||
{
|
{
|
||||||
m_prevMag = reallocate(m_prevMag, m_windowSize, newSize);
|
m_prevMag = reallocate(m_prevMag, m_fftSize, newSize);
|
||||||
AudioCurveCalculator::setWindowSize(newSize);
|
AudioCurveCalculator::setFftSize(newSize);
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ public:
|
|||||||
|
|
||||||
virtual ~PercussiveAudioCurve();
|
virtual ~PercussiveAudioCurve();
|
||||||
|
|
||||||
virtual void setWindowSize(int newSize);
|
virtual void setFftSize(int newSize);
|
||||||
|
|
||||||
virtual float processFloat(const float *R__ mag, int increment);
|
virtual float processFloat(const float *R__ mag, int increment);
|
||||||
virtual double processDouble(const double *R__ mag, int increment);
|
virtual double processDouble(const double *R__ mag, int increment);
|
||||||
|
|||||||
@@ -42,11 +42,11 @@ SpectralDifferenceAudioCurve::reset()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SpectralDifferenceAudioCurve::setWindowSize(int newSize)
|
SpectralDifferenceAudioCurve::setFftSize(int newSize)
|
||||||
{
|
{
|
||||||
deallocate(m_tmpbuf);
|
deallocate(m_tmpbuf);
|
||||||
deallocate(m_mag);
|
deallocate(m_mag);
|
||||||
AudioCurveCalculator::setWindowSize(newSize);
|
AudioCurveCalculator::setFftSize(newSize);
|
||||||
m_mag = allocate<double>(m_lastPerceivedBin + 1);
|
m_mag = allocate<double>(m_lastPerceivedBin + 1);
|
||||||
m_tmpbuf = allocate<double>(m_lastPerceivedBin + 1);
|
m_tmpbuf = allocate<double>(m_lastPerceivedBin + 1);
|
||||||
reset();
|
reset();
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public:
|
|||||||
|
|
||||||
virtual ~SpectralDifferenceAudioCurve();
|
virtual ~SpectralDifferenceAudioCurve();
|
||||||
|
|
||||||
virtual void setWindowSize(int newSize);
|
virtual void setFftSize(int newSize);
|
||||||
|
|
||||||
virtual float processFloat(const float *R__ mag, int increment);
|
virtual float processFloat(const float *R__ mag, int increment);
|
||||||
virtual double processDouble(const double *R__ mag, int increment);
|
virtual double processDouble(const double *R__ mag, int increment);
|
||||||
|
|||||||
@@ -44,15 +44,11 @@ T *allocate(size_t count)
|
|||||||
if (posix_memalign(&ptr, 16, count * sizeof(T))) {
|
if (posix_memalign(&ptr, 16, count * sizeof(T))) {
|
||||||
ptr = malloc(count * sizeof(T));
|
ptr = malloc(count * sizeof(T));
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
#ifdef __MSVC__
|
|
||||||
ptr = _aligned_malloc(count * sizeof(T), 16);
|
|
||||||
#else
|
#else
|
||||||
// Note that malloc always aligns to 16 byte boundaries on OS/X,
|
// Note that malloc always aligns to 16 byte boundaries on OS/X,
|
||||||
// so we don't need posix_memalign there (which is fortunate,
|
// so we don't need posix_memalign there (which is fortunate,
|
||||||
// since it doesn't exist)
|
// since it doesn't exist)
|
||||||
ptr = malloc(count * sizeof(T));
|
ptr = malloc(count * sizeof(T));
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
if (!ptr) throw(std::bad_alloc());
|
if (!ptr) throw(std::bad_alloc());
|
||||||
return (T *)ptr;
|
return (T *)ptr;
|
||||||
@@ -70,11 +66,7 @@ T *allocate_and_zero(size_t count)
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
void deallocate(T *ptr)
|
void deallocate(T *ptr)
|
||||||
{
|
{
|
||||||
#ifdef __MSVC__
|
|
||||||
if (ptr) _aligned_free((void *)ptr);
|
|
||||||
#else
|
|
||||||
if (ptr) free((void *)ptr);
|
if (ptr) free((void *)ptr);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -47,11 +47,6 @@ void gettimeofday(struct timeval *p, void *tz);
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __MSVC__
|
|
||||||
|
|
||||||
void usleep(unsigned long);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum ProcessStatus { ProcessRunning, ProcessNotRunning, UnknownProcessStatus };
|
enum ProcessStatus { ProcessRunning, ProcessNotRunning, UnknownProcessStatus };
|
||||||
extern ProcessStatus GetProcessStatus(int pid);
|
extern ProcessStatus GetProcessStatus(int pid);
|
||||||
|
|||||||
Reference in New Issue
Block a user