* Share dblbuf with FFT object to avoid a copy; fix reset(); add spectral

difference audio curve; some tidying; add FLOAT_ONLY FFT option
This commit is contained in:
Chris Cannam
2007-12-10 15:47:06 +00:00
parent 2b1693aa3f
commit d4ff782668
14 changed files with 266 additions and 94 deletions

View File

@@ -1,6 +1,6 @@
CXX := @CXX@
CXXFLAGS := @CXXFLAGS@ @SRC_CFLAGS@ @SNDFILE_CFLAGS@ @FFTW_CFLAGS@ @Vamp_CFLAGS@ -Irubberband -Isrc $(OPTFLAGS)
CXXFLAGS := -DFFTW_DOUBLE_ONLY @CXXFLAGS@ @SRC_CFLAGS@ @SNDFILE_CFLAGS@ @FFTW_CFLAGS@ @Vamp_CFLAGS@ -Irubberband -Isrc $(OPTFLAGS)
LDFLAGS := @LDFLAGS@ -lpthread $(LDFLAGS)
LIBRARY_LIBS := @SRC_LIBS@ @FFTW_LIBS@
@@ -42,6 +42,7 @@ LIBRARY_INCLUDES := \
src/Resampler.h \
src/RingBuffer.h \
src/Scavenger.h \
src/SpectralDifferenceAudioCurve.h \
src/StretchCalculator.h \
src/StretcherImpl.h \
src/StretcherChannelData.h \
@@ -56,6 +57,7 @@ LIBRARY_SOURCES := \
src/PercussiveAudioCurve.cpp \
src/AudioCurve.cpp \
src/Resampler.cpp \
src/SpectralDifferenceAudioCurve.cpp \
src/StretchCalculator.cpp \
src/StretcherImpl.cpp \
src/StretcherProcess.cpp \

2
TODO
View File

@@ -3,10 +3,10 @@
* LADSPA plugin has too much "artificial latency"
* LADSPA plugin probably doesn't want to go any higher than about +2 octaves
* Return value check in FFT and resampler!
* implement+test, or remove, reset()
* sweeps & tones
* ensure default options don't produce garbage at any extreme
DONE * implement+test, or remove, reset()
DONE * Add and test Win32 threading primitives in Thread.cpp
DONE * Threading lock structure is very slow if it becomes starved of CPUs
DONE * Rationalise naming further (e.g. use of "lock" for both peak phases

View File

@@ -47,33 +47,79 @@ public:
virtual void inverse(float *realIn, float *imagIn, float *realOut) = 0;
virtual void inversePolar(float *magIn, float *phaseIn, float *realOut) = 0;
virtual float *getFloatTimeBuffer() = 0;
virtual double *getDoubleTimeBuffer() = 0;
};
// Remove this define to make float FFTs be carried out using fftwf_*
// functions instead of converting to doubles and using fftw_*.
#define FFTW_DOUBLE_ONLY 1
// Define FFTW_DOUBLE_ONLY to make all uses of FFTW functions be
// double-precision (so "float" FFTs are calculated by casting to
// doubles and using the double-precision FFTW function).
//
// Define FFTW_FLOAT_ONLY to make all uses of FFTW functions be
// single-precision (so "double" FFTs are calculated by casting to
// floats and using the single-precision FFTW function).
//
// Neither of these flags is terribly desirable -- FFTW_FLOAT_ONLY
// obviously loses you precision, and neither is handled in the most
// efficient way so any performance improvement will be small at best.
// The only real reason to define either flag would be to avoid
// linking against both fftw3 and fftw3f libraries.
//#define FFTW_DOUBLE_ONLY 1
//#define FFTW_FLOAT_ONLY 1
#ifdef FFTW_DOUBLE_ONLY
#ifdef FFTW_FLOAT_ONLY
// Can't meaningfully define both
#undef FFTW_DOUBLE_ONLY
#undef FFTW_FLOAT_ONLY
#else /* !FFTW_FLOAT_ONLY */
#define fftwf_complex fftw_complex
#define fftwf_plan fftw_plan
#define fftwf_plan_dft_r2c_1d fftw_plan_dft_r2c_1d
#define fftwf_plan_dft_c2r_1d fftw_plan_dft_c2r_1d
#define fftwf_destroy_plan fftw_destroy_plan
#define fftwf_malloc fftw_malloc
#define fftwf_free fftw_free
#define fftwf_execute fftw_execute
#define atan2f atan2
#define sqrtf sqrt
#define cosf cos
#define sinf sin
#endif
#endif /* !FFTW_FLOAT_ONLY */
#ifdef FFTW_FLOAT_ONLY
#define fftw_complex fftwf_complex
#define fftw_plan fftwf_plan
#define fftw_plan_dft_r2c_1d fftwf_plan_dft_r2c_1d
#define fftw_plan_dft_c2r_1d fftwf_plan_dft_c2r_1d
#define fftw_destroy_plan fftwf_destroy_plan
#define fftw_malloc fftwf_malloc
#define fftw_free fftwf_free
#define fftw_execute fftwf_execute
#define atan2 atan2f
#define sqrt sqrtf
#define cos cosf
#define sif sinf
#endif /* FFTW_FLOAT_ONLY */
class D_FFTW : public FFTImpl
{
public:
D_FFTW(unsigned int size) : m_size(size), m_fplanf(0), m_dplanf(0) {
D_FFTW(unsigned int size) : m_fplanf(0)
#ifdef FFTW_DOUBLE_ONLY
, m_frb(0)
#endif
, m_dplanf(0)
#ifdef FFTW_FLOAT_ONLY
, m_drb(0)
#endif
, m_size(size)
{
}
~D_FFTW() {
@@ -87,6 +133,9 @@ public:
fftwf_destroy_plan(m_fplani);
fftwf_free(m_fbuf);
fftwf_free(m_fpacked);
#ifdef FFTW_DOUBLE_ONLY
if (m_frb) fftw_free(m_frb);
#endif
}
if (m_dplanf) {
bool save = false;
@@ -98,6 +147,9 @@ public:
fftw_destroy_plan(m_dplani);
fftw_free(m_dbuf);
fftw_free(m_dpacked);
#ifdef FFTW_FLOAT_ONLY
if (m_drb) fftwf_free(m_drb);
#endif
}
}
@@ -107,11 +159,12 @@ public:
m_extantMutex.lock();
if (m_extantf++ == 0) load = true;
m_extantMutex.unlock();
if (load) loadWisdom('f');
#ifdef FFTW_DOUBLE_ONLY
if (load) loadWisdom('d');
m_fbuf = (double *)fftw_malloc(m_size * sizeof(double));
#else
m_fbuf = (float *)fftw_malloc(m_size * sizeof(float));
if (load) loadWisdom('f');
m_fbuf = (float *)fftwf_malloc(m_size * sizeof(float));
#endif
m_fpacked = (fftwf_complex *)fftw_malloc
((m_size/2 + 1) * sizeof(fftwf_complex));
@@ -127,8 +180,13 @@ public:
m_extantMutex.lock();
if (m_extantd++ == 0) load = true;
m_extantMutex.unlock();
#ifdef FFTW_FLOAT_ONLY
if (load) loadWisdom('f');
m_dbuf = (float *)fftwf_malloc(m_size * sizeof(float));
#else
if (load) loadWisdom('d');
m_dbuf = (double *)fftw_malloc(m_size * sizeof(double));
#endif
m_dpacked = (fftw_complex *)fftw_malloc
((m_size/2 + 1) * sizeof(fftw_complex));
m_dplanf = fftw_plan_dft_r2c_1d
@@ -145,6 +203,9 @@ public:
#ifdef FFTW_DOUBLE_ONLY
if (type == 'f') return;
#endif
#ifdef FFTW_FLOAT_ONLY
if (type == 'd') return;
#endif
const char *home = getenv("HOME");
if (!home) return;
@@ -162,7 +223,11 @@ public:
#else
case 'f': fftwf_export_wisdom_to_file(f); break;
#endif
#ifdef FFTW_FLOAT_ONLY
case 'd': break;
#else
case 'd': fftw_export_wisdom_to_file(f); break;
#endif
default: break;
}
} else {
@@ -172,7 +237,11 @@ public:
#else
case 'f': fftwf_import_wisdom_from_file(f); break;
#endif
#ifdef FFTW_FLOAT_ONLY
case 'd': break;
#else
case 'd': fftw_import_wisdom_from_file(f); break;
#endif
default: break;
}
}
@@ -210,31 +279,42 @@ public:
void forward(double *realIn, double *realOut, double *imagOut) {
if (!m_dplanf) initDouble();
for (unsigned int i = 0; i < m_size; ++i) {
m_dbuf[i] = realIn[i];
}
#ifndef FFTW_FLOAT_ONLY
if (realIn != m_dbuf)
#endif
for (unsigned int i = 0; i < m_size; ++i) {
m_dbuf[i] = realIn[i];
}
fftw_execute(m_dplanf);
unpackDouble(realOut, imagOut);
}
void forwardPolar(double *realIn, double *magOut, double *phaseOut) {
if (!m_dplanf) initDouble();
for (unsigned int i = 0; i < m_size; ++i) {
m_dbuf[i] = realIn[i];
}
#ifndef FFTW_FLOAT_ONLY
if (realIn != m_dbuf)
#endif
for (unsigned int i = 0; i < m_size; ++i) {
m_dbuf[i] = realIn[i];
}
fftw_execute(m_dplanf);
for (unsigned int i = 0; i <= m_size/2; ++i) {
magOut[i] = sqrt(m_dpacked[i][0] * m_dpacked[i][0] +
m_dpacked[i][1] * m_dpacked[i][1]);
}
for (unsigned int i = 0; i <= m_size/2; ++i) {
phaseOut[i] = atan2(m_dpacked[i][1], m_dpacked[i][0]);
}
}
void forwardMagnitude(double *realIn, double *magOut) {
if (!m_dplanf) initDouble();
for (unsigned int i = 0; i < m_size; ++i) {
m_dbuf[i] = realIn[i];
}
#ifndef FFTW_FLOAT_ONLY
if (realIn != m_dbuf)
#endif
for (unsigned int i = 0; i < m_size; ++i) {
m_dbuf[i] = realIn[i];
}
fftw_execute(m_dplanf);
for (unsigned int i = 0; i <= m_size/2; ++i) {
magOut[i] = sqrt(m_dpacked[i][0] * m_dpacked[i][0] +
@@ -244,31 +324,42 @@ public:
void forward(float *realIn, float *realOut, float *imagOut) {
if (!m_fplanf) initFloat();
for (unsigned int i = 0; i < m_size; ++i) {
m_fbuf[i] = realIn[i];
}
#ifndef FFTW_DOUBLE_ONLY
if (realIn != m_fbuf)
#endif
for (unsigned int i = 0; i < m_size; ++i) {
m_fbuf[i] = realIn[i];
}
fftwf_execute(m_fplanf);
unpackFloat(realOut, imagOut);
}
void forwardPolar(float *realIn, float *magOut, float *phaseOut) {
if (!m_fplanf) initFloat();
for (unsigned int i = 0; i < m_size; ++i) {
m_fbuf[i] = realIn[i];
}
#ifndef FFTW_DOUBLE_ONLY
if (realIn != m_fbuf)
#endif
for (unsigned int i = 0; i < m_size; ++i) {
m_fbuf[i] = realIn[i];
}
fftwf_execute(m_fplanf);
for (unsigned int i = 0; i <= m_size/2; ++i) {
magOut[i] = sqrtf(m_fpacked[i][0] * m_fpacked[i][0] +
m_fpacked[i][1] * m_fpacked[i][1]);
}
for (unsigned int i = 0; i <= m_size/2; ++i) {
phaseOut[i] = atan2f(m_fpacked[i][1], m_fpacked[i][0]) ;
}
}
void forwardMagnitude(float *realIn, float *magOut) {
if (!m_fplanf) initFloat();
for (unsigned int i = 0; i < m_size; ++i) {
m_fbuf[i] = realIn[i];
}
#ifndef FFTW_DOUBLE_ONLY
if (realIn != m_fbuf)
#endif
for (unsigned int i = 0; i < m_size; ++i) {
m_fbuf[i] = realIn[i];
}
fftwf_execute(m_fplanf);
for (unsigned int i = 0; i <= m_size/2; ++i) {
magOut[i] = sqrtf(m_fpacked[i][0] * m_fpacked[i][0] +
@@ -280,9 +371,12 @@ public:
if (!m_dplanf) initDouble();
packDouble(realIn, imagIn);
fftw_execute(m_dplani);
for (unsigned int i = 0; i < m_size; ++i) {
realOut[i] = m_dbuf[i];
}
#ifndef FFTW_FLOAT_ONLY
if (realOut != m_dbuf)
#endif
for (unsigned int i = 0; i < m_size; ++i) {
realOut[i] = m_dbuf[i];
}
}
void inversePolar(double *magIn, double *phaseIn, double *realOut) {
@@ -292,18 +386,24 @@ public:
m_dpacked[i][1] = magIn[i] * sin(phaseIn[i]);
}
fftw_execute(m_dplani);
for (unsigned int i = 0; i < m_size; ++i) {
realOut[i] = m_dbuf[i];
}
#ifndef FFTW_FLOAT_ONLY
if (realOut != m_dbuf)
#endif
for (unsigned int i = 0; i < m_size; ++i) {
realOut[i] = m_dbuf[i];
}
}
void inverse(float *realIn, float *imagIn, float *realOut) {
if (!m_fplanf) initFloat();
packFloat(realIn, imagIn);
fftwf_execute(m_fplani);
for (unsigned int i = 0; i < m_size; ++i) {
realOut[i] = m_fbuf[i];
}
#ifndef FFTW_DOUBLE_ONLY
if (realOut != m_fbuf)
#endif
for (unsigned int i = 0; i < m_size; ++i) {
realOut[i] = m_fbuf[i];
}
}
void inversePolar(float *magIn, float *phaseIn, float *realOut) {
@@ -313,15 +413,39 @@ public:
m_fpacked[i][1] = magIn[i] * sinf(phaseIn[i]);
}
fftwf_execute(m_fplani);
for (unsigned int i = 0; i < m_size; ++i) {
realOut[i] = m_fbuf[i];
}
#ifndef FFTW_DOUBLE_ONLY
if (realOut != m_fbuf)
#endif
for (unsigned int i = 0; i < m_size; ++i) {
realOut[i] = m_fbuf[i];
}
}
float *getFloatTimeBuffer() {
initFloat();
#ifdef FFTW_DOUBLE_ONLY
if (!m_frb) m_frb = (float *)fftw_malloc(m_size * sizeof(float));
return m_frb;
#else
return m_fbuf;
#endif
}
double *getDoubleTimeBuffer() {
initDouble();
#ifdef FFTW_FLOAT_ONLY
if (!m_drb) m_drb = (double *)fftwf_malloc(m_size * sizeof(double));
return m_drb;
#else
return m_dbuf;
#endif
}
private:
fftwf_plan m_fplanf;
fftwf_plan m_fplani;
#ifdef FFTW_DOUBLE_ONLY
float *m_frb;
double *m_fbuf;
#else
float *m_fbuf;
@@ -329,7 +453,12 @@ private:
fftwf_complex *m_fpacked;
fftw_plan m_dplanf;
fftw_plan m_dplani;
#ifdef FFTW_FLOAT_ONLY
float *m_dbuf;
double *m_drb;
#else
double *m_dbuf;
#endif
fftw_complex *m_dpacked;
unsigned int m_size;
static unsigned int m_extantf;
@@ -346,11 +475,12 @@ D_FFTW::m_extantd = 0;
Mutex
D_FFTW::m_extantMutex;
#endif
class D_Cross : public FFTImpl
{
public:
D_Cross(unsigned int size) : m_size(size), m_table(0) {
D_Cross(unsigned int size) : m_size(size), m_table(0), m_frb(0), m_drb(0) {
m_a = new double[size];
m_b = new double[size];
@@ -388,6 +518,8 @@ public:
delete[] m_b;
delete[] m_c;
delete[] m_d;
delete[] m_frb;
delete[] m_drb;
}
void initFloat() { }
@@ -496,9 +628,21 @@ public:
for (unsigned int i = 0; i < m_size; ++i) realOut[i] = m_c[i];
}
float *getFloatTimeBuffer() {
if (!m_frb) m_frb = new float[m_size];
return m_frb;
}
double *getDoubleTimeBuffer() {
if (!m_drb) m_drb = new double[m_size];
return m_drb;
}
private:
unsigned int m_size;
int *m_table;
float *m_frb;
double *m_drb;
double *m_a;
double *m_b;
double *m_c;
@@ -701,6 +845,18 @@ FFT::initDouble()
d->initDouble();
}
float *
FFT::getFloatTimeBuffer()
{
return d->getFloatTimeBuffer();
}
double *
FFT::getDoubleTimeBuffer()
{
return d->getDoubleTimeBuffer();
}
void
FFT::tune()

View File

@@ -60,6 +60,9 @@ public:
void initFloat();
void initDouble();
float *getFloatTimeBuffer();
double *getDoubleTimeBuffer();
static void tune();
protected:

View File

@@ -20,24 +20,15 @@ namespace RubberBand
HighFrequencyAudioCurve::HighFrequencyAudioCurve(size_t sampleRate, size_t windowSize) :
AudioCurve(sampleRate, windowSize)
{
m_prevMag = new double[m_windowSize/2 + 1];
for (size_t i = 0; i <= m_windowSize/2; ++i) {
m_prevMag[i] = 0.f;
}
}
HighFrequencyAudioCurve::~HighFrequencyAudioCurve()
{
delete[] m_prevMag;
}
void
HighFrequencyAudioCurve::reset()
{
for (size_t i = 0; i <= m_windowSize/2; ++i) {
m_prevMag[i] = 0;
}
}
void
@@ -52,7 +43,7 @@ HighFrequencyAudioCurve::process(float *mag, size_t increment)
float result = 0.0;
for (size_t n = 0; n <= m_windowSize / 2; ++n) {
result += mag[n];
result += mag[n] * n;
}
return result;

View File

@@ -32,9 +32,6 @@ public:
virtual float process(float *mag, size_t increment);
virtual void reset();
protected:
double *m_prevMag;
};
}

View File

@@ -63,7 +63,6 @@ PercussiveAudioCurve::process(float *mag, size_t increment)
size_t nonZeroCount = 0;
for (size_t n = 1; n <= m_windowSize / 2; ++n) {
//!!! adjust threshold so that this multiplication is unnecessary
float sqrmag = mag[n] * mag[n];
bool above = ((sqrmag / m_prevMag[n]) >= threshold);
if (above) ++count;
@@ -71,7 +70,6 @@ PercussiveAudioCurve::process(float *mag, size_t increment)
m_prevMag[n] = sqrmag;
}
//!!! return float(count) / float(m_windowSize);
if (nonZeroCount == 0) return 0;
else return float(count) / float(nonZeroCount);
}

View File

@@ -56,7 +56,6 @@ RubberBandStretcher::Impl::ChannelData::construct(const std::set<size_t> &window
windowAccumulator = new float[maxSize];
fltbuf = new float[maxSize];
dblbuf = new double[maxSize];
for (std::set<size_t>::const_iterator i = windowSizes.begin();
i != windowSizes.end(); ++i) {
@@ -69,6 +68,8 @@ RubberBandStretcher::Impl::ChannelData::construct(const std::set<size_t> &window
}
fft = ffts[initialWindowSize];
dblbuf = fft->getDoubleTimeBuffer();
resampler = 0;
resamplebuf = 0;
resamplebufSize = 0;
@@ -83,10 +84,13 @@ RubberBandStretcher::Impl::ChannelData::construct(const std::set<size_t> &window
freqPeak[i] = 0;
}
for (size_t i = 0; i < initialWindowSize; ++i) {
dblbuf[i] = 0.0;
}
for (size_t i = 0; i < maxSize; ++i) {
accumulator[i] = 0.f;
windowAccumulator[i] = 0.f;
dblbuf[i] = 0.0;
fltbuf[i] = 0.0;
}
}
@@ -116,6 +120,12 @@ RubberBandStretcher::Impl::ChannelData::setWindowSize(size_t windowSize)
fft = ffts[windowSize];
dblbuf = fft->getDoubleTimeBuffer();
for (size_t i = 0; i < windowSize; ++i) {
dblbuf[i] = 0.0;
}
for (size_t i = 0; i < realSize; ++i) {
mag[i] = 0.0;
phase[i] = 0.0;
@@ -153,10 +163,7 @@ RubberBandStretcher::Impl::ChannelData::setWindowSize(size_t windowSize)
freqPeak = new size_t[realSize];
delete[] fltbuf;
delete[] dblbuf;
fltbuf = new float[windowSize];
dblbuf = new double[windowSize];
// But we do want to preserve data in these
@@ -181,7 +188,6 @@ RubberBandStretcher::Impl::ChannelData::setWindowSize(size_t windowSize)
}
for (size_t i = 0; i < windowSize; ++i) {
dblbuf[i] = 0.0;
fltbuf[i] = 0.0;
}
@@ -196,6 +202,12 @@ RubberBandStretcher::Impl::ChannelData::setWindowSize(size_t windowSize)
}
fft = ffts[windowSize];
dblbuf = fft->getDoubleTimeBuffer();
for (size_t i = 0; i < windowSize; ++i) {
dblbuf[i] = 0.0;
}
}
void
@@ -231,7 +243,6 @@ RubberBandStretcher::Impl::ChannelData::~ChannelData()
delete[] accumulator;
delete[] windowAccumulator;
delete[] fltbuf;
delete[] dblbuf;
for (std::map<size_t, FFT *>::iterator i = ffts.begin();
i != ffts.end(); ++i) {

View File

@@ -92,7 +92,7 @@ public:
float *windowAccumulator;
float *fltbuf;
double *dblbuf;
double *dblbuf; // owned by FFT object, only used for time domain FFT i/o
size_t prevIncrement; // only used in RT mode

View File

@@ -15,6 +15,7 @@
#include "StretcherImpl.h"
#include "PercussiveAudioCurve.h"
#include "HighFrequencyAudioCurve.h"
#include "SpectralDifferenceAudioCurve.h"
#include "ConstantAudioCurve.h"
#include "StretchCalculator.h"
#include "StretcherChannelData.h"
@@ -113,7 +114,6 @@ RubberBandStretcher::Impl::Impl(RubberBandStretcher *stretcher,
m_realtime = true;
if (!(m_options & OptionStretchPrecise)) {
cerr << "RubberBandStretcher::Impl::Impl: Real-time mode: enabling OptionStretchPrecise" << endl;
m_options |= OptionStretchPrecise;
}
}
@@ -148,6 +148,7 @@ RubberBandStretcher::Impl::~Impl()
if (m_debugLevel > 0) {
cerr << "RubberBandStretcher::~RubberBandStretcher: joining (channel " << *i << ")" << endl;
}
(*i)->abandon();
(*i)->wait();
delete *i;
}
@@ -171,21 +172,32 @@ RubberBandStretcher::Impl::~Impl()
void
RubberBandStretcher::Impl::reset()
{
//!!! does not do the right thing in threaded mode
if (m_threaded) m_threadSetMutex.lock();
if (m_threaded) {
m_threadSetMutex.lock();
for (set<ProcessThread *>::iterator i = m_threadSet.begin();
i != m_threadSet.end(); ++i) {
if (m_debugLevel > 0) {
cerr << "RubberBandStretcher::~RubberBandStretcher: joining (channel " << *i << ")" << endl;
}
(*i)->abandon();
(*i)->wait();
delete *i;
}
m_threadSet.clear();
}
for (size_t c = 0; c < m_channels; ++c) {
delete m_channelData[c];
m_channelData[c] = new ChannelData(m_windowSize, m_outbufSize);
m_channelData[c]->reset();
}
m_mode = JustCreated;
if (m_phaseResetAudioCurve) m_phaseResetAudioCurve->reset();
if (m_stretchAudioCurve) m_stretchAudioCurve->reset();
m_inputDuration = 0;
if (m_threaded) m_threadSetMutex.unlock();
// m_done = false;
reconfigure();
}
void
@@ -407,19 +419,14 @@ RubberBandStretcher::Impl::calculateSizes()
if (m_debugLevel > 0) {
cerr << "configure: outbuf size = " << m_outbufSize << endl;
}
//!!! for very long stretches (e.g. x5), this is necessary; for
//even longer ones (e.g. x10), even more of an outbuf is
//necessary. clearly something wrong in our calculations... or do
//we just need to ensure client calls setMaxProcessSize?
// if (!m_realtime && !m_threaded) {
// m_outbufSize = m_outbufSize * 10;
// }
}
void
RubberBandStretcher::Impl::configure()
{
std::cerr << "configure[" << this << "]: realtime = " << m_realtime << ", pitch scale = "
<< m_pitchScale << ", channels = " << m_channels << std::endl;
size_t prevWindowSize = m_windowSize;
size_t prevOutbufSize = m_outbufSize;
if (m_windows.empty()) {
@@ -512,9 +519,7 @@ RubberBandStretcher::Impl::configure()
if (!m_realtime) {
delete m_stretchAudioCurve;
if (!(m_options & OptionStretchPrecise)) {
//!!! probably adaptively-whitened spectral difference curve
//would be better
m_stretchAudioCurve = new HighFrequencyAudioCurve
m_stretchAudioCurve = new SpectralDifferenceAudioCurve
(m_stretcher->m_sampleRate, m_windowSize);
} else {
m_stretchAudioCurve = new ConstantAudioCurve
@@ -550,8 +555,6 @@ RubberBandStretcher::Impl::configure()
}
//!!! separated out from configure() for the moment so we can look at
// the logic of it
void
RubberBandStretcher::Impl::reconfigure()
{
@@ -882,9 +885,6 @@ RubberBandStretcher::Impl::process(const float *const *input, size_t samples, bo
if (m_mode == JustCreated || m_mode == Studying) {
//!!! m_studying isn't the right test for "is this the first
//time we've processed?"
if (m_mode == Studying) {
calculateStretch();
}

View File

@@ -145,10 +145,12 @@ protected:
ProcessThread(Impl *s, size_t c);
void run();
void signalDataAvailable();
void abandon();
private:
Impl *m_s;
size_t m_channel;
Condition m_dataAvailable;
bool m_abandoning;
};
mutable Mutex m_threadSetMutex;

View File

@@ -33,7 +33,8 @@ namespace RubberBand {
RubberBandStretcher::Impl::ProcessThread::ProcessThread(Impl *s, size_t c) :
m_s(s),
m_channel(c),
m_dataAvailable(std::string("data ") + char('A' + c))
m_dataAvailable(std::string("data ") + char('A' + c)),
m_abandoning(false)
{ }
void
@@ -61,11 +62,18 @@ RubberBandStretcher::Impl::ProcessThread::run()
if (any) m_s->m_spaceAvailable.signal();
m_dataAvailable.lock();
if (!m_s->testInbufReadSpace(m_channel)) {
if (!m_s->testInbufReadSpace(m_channel) && !m_abandoning) {
m_dataAvailable.wait();
} else {
m_dataAvailable.unlock();
}
if (m_abandoning) {
if (m_s->m_debugLevel > 1) {
cerr << "thread " << m_channel << " abandoning" << endl;
}
return;
}
}
bool any = false, last = false;
@@ -83,6 +91,12 @@ RubberBandStretcher::Impl::ProcessThread::signalDataAvailable()
m_dataAvailable.signal();
}
void
RubberBandStretcher::Impl::ProcessThread::abandon()
{
m_abandoning = true;
}
void
RubberBandStretcher::Impl::processChunks(size_t c, bool &any, bool &last)
{

View File

@@ -59,7 +59,6 @@ Thread::start()
{
m_id = CreateThread(NULL, 0, staticRun, this, 0, 0);
if (!m_id) {
//!!!
cerr << "ERROR: thread creation failed" << endl;
exit(1);
} else {
@@ -296,7 +295,6 @@ void
Thread::start()
{
if (pthread_create(&m_id, 0, staticRun, this)) {
//!!!
cerr << "ERROR: thread creation failed" << endl;
exit(1);
} else {

View File

@@ -139,8 +139,8 @@ RubberBandPitchShifter::ladspaDescriptorMono =
"rubberband-pitchshifter-mono", // Label
properties,
"Rubber Band Mono Pitch Shifter", // Name
"Chris Cannam", //!!! Maker
"GPL", //!!! Copyright
"Chris Cannam",
"GPL",
PortCountMono,
portsMono,
portNamesMono,
@@ -163,8 +163,8 @@ RubberBandPitchShifter::ladspaDescriptorStereo =
"rubberband-pitchshifter-stereo", // Label
properties,
"Rubber Band Stereo Pitch Shifter", // Name
"Chris Cannam", //!!! Maker
"GPL", //!!! Copyright
"Chris Cannam",
"GPL",
PortCountStereo,
portsStereo,
portNamesStereo,