* Fix failure to remember that we have constructed an interpolator

window already (#25).  Also avoid using alloca for substantial buffers
* Lose FFT::getFloatTimeBuffer and getDoubleTimeBuffer -- it's too
unclear when it's safe to use them and it's safer to control sizes externally.
In RB with smoothing on, these buffers were incorrectly being used for window-si
zed calculations (larger than FFT-sized).
* Fix some incorrect buffer resize sizes
* Build fixes for OS/X
This commit is contained in:
Chris Cannam
2011-03-19 12:41:38 +00:00
parent 0b8c1bd90b
commit c45acda473
15 changed files with 133 additions and 205 deletions

View File

@@ -4,10 +4,29 @@ Rubber Band
An audio time-stretching and pitch-shifting library and utility program. An audio time-stretching and pitch-shifting library and utility program.
Copyright 2007-2010 Chris Cannam, chris.cannam@breakfastquay.com. Copyright 2007-2011 Chris Cannam, chris.cannam@breakfastquay.com.
Distributed under the GNU General Public License. Distributed under the GNU General Public License.
Contents
========
1. About Rubber Band
- Attractive features
- Limitations
2. Compiling Rubber Band
3. Using the Rubber Band utility
4. Using the Rubber Band library
About Rubber Band
-----------------
Rubber Band is a library and utility program that permits you to Rubber Band is a library and utility program that permits you to
change the tempo and pitch of an audio recording independently of one change the tempo and pitch of an audio recording independently of one
another. another.
@@ -90,11 +109,15 @@ Limitations
Compiling Rubber Band Compiling Rubber Band
--------------------- ---------------------
Rubber Band is supplied with build scripts that have been tested on Rubber Band Library is supplied with a configure script for Linux and
Linux platforms. It is also possible to build Rubber Band on other other systems with pkg-config, and a separate Makefile for basic OS/X
platforms, including both POSIX platforms such as OS/X and non-POSIX builds without pkg-config. It's also possible to build the Rubber
platforms such as Win32. There are some example Makefiles in the misc Band Library GPL edition for Windows using MinGW, though you'll have
directory. to hack your own Makefile for that.
Using configure
~~~~~~~~~~~~~~~
To build Rubber Band you will also need libsndfile, libsamplerate, To build Rubber Band you will also need libsndfile, libsamplerate,
FFTW3, the Vamp plugin SDK, the LADSPA plugin header, the pthread FFTW3, the Vamp plugin SDK, the LADSPA plugin header, the pthread
@@ -113,6 +136,18 @@ to compile, and optionally
to install. to install.
Simple build for OS/X
~~~~~~~~~~~~~~~~~~~~~
To build just the library (but not the command-line utility, Vamp
plugin or LADSPA plugin) for OS/X, run
$ make -f build/Makefile.osx
You will need libsamplerate and libfftw3 installed, but no other
non-system dependencies.
Using the Rubber Band utility Using the Rubber Band utility
----------------------------- -----------------------------

View File

@@ -3,8 +3,12 @@
# Does not build the Vamp plugin, LADSPA plugin, or command-line utility. # Does not build the Vamp plugin, LADSPA plugin, or command-line utility.
CXX := g++ CXX := g++
CXXFLAGS := -DHAVE_FFTW3 -DFFTW_DOUBLE_ONLY -DNO_THREAD_CHECKS -DNO_TIMING -DNDEBUG -mmacosx-version-min=10.4 -isysroot /Developer/SDKs/MacOSX10.4u.sdk -O3 -arch i386 -arch ppc -msse -msse2 -ffast-math -ftree-vectorize -I../include -I/usr/local/include -Irubberband -I. -Isrc CXXFLAGS := -DHAVE_FFTW3 -DFFTW_DOUBLE_ONLY -DNO_THREAD_CHECKS -DNO_TIMING -DNDEBUG -O3 -arch i386 -arch x86_64 -msse -msse2 -ffast-math -ftree-vectorize -I../include -I/usr/local/include -Irubberband -I. -Isrc
LDFLAGS := -mmacosx-version-min=10.4 -isysroot /Developer/SDKs/MacOSX10.4u.sdk -arch i386 -arch ppc -L../lib -L/usr/local/lib LDFLAGS := -arch i386 -arch x86_64 -L../lib -L/usr/local/lib
# CXX := g++-4.0
# CXXFLAGS := -DHAVE_FFTW3 -DFFTW_DOUBLE_ONLY -DNO_THREAD_CHECKS -DNO_TIMING -DNDEBUG -mmacosx-version-min=10.4 -isysroot /Developer/SDKs/MacOSX10.4u.sdk -O3 -arch i386 -msse -msse2 -ffast-math -ftree-vectorize -I../include -I/usr/local/include -Irubberband -I. -Isrc
# LDFLAGS := -mmacosx-version-min=10.4 -isysroot /Developer/SDKs/MacOSX10.4u.sdk -arch i386 -L../lib -L/usr/local/lib
LIBRARY_LIBS := -lsamplerate -lfftw3 -lpthread -lm LIBRARY_LIBS := -lsamplerate -lfftw3 -lpthread -lm

View File

@@ -26,13 +26,9 @@
#include "system/sysutils.h" #include "system/sysutils.h"
#ifdef __MSVC__
#include "getopt/getopt.h"
#else
#include <getopt.h> #include <getopt.h>
#include <unistd.h> #include <unistd.h>
#include <sys/time.h> #include <sys/time.h>
#endif
#include "base/Profiler.h" #include "base/Profiler.h"
@@ -43,9 +39,6 @@ using namespace RubberBand;
using RubberBand::gettimeofday; using RubberBand::gettimeofday;
#endif #endif
#ifdef __MSVC__
using RubberBand::usleep;
#endif
double tempo_convert(const char *str) double tempo_convert(const char *str)
{ {

View File

@@ -70,9 +70,10 @@ RubberBandStretcher::Impl::ChannelData::construct(const std::set<size_t> &sizes,
unwrappedPhase = allocate_and_zero<process_t>(realSize); unwrappedPhase = allocate_and_zero<process_t>(realSize);
envelope = allocate_and_zero<process_t>(realSize); envelope = allocate_and_zero<process_t>(realSize);
freqPeak = new size_t[realSize]; freqPeak = allocate_and_zero<size_t>(realSize);
fltbuf = allocate_and_zero<float>(maxSize); fltbuf = allocate_and_zero<float>(maxSize);
dblbuf = allocate_and_zero<process_t>(maxSize);
accumulator = allocate_and_zero<float>(maxSize); accumulator = allocate_and_zero<float>(maxSize);
windowAccumulator = allocate_and_zero<float>(maxSize); windowAccumulator = allocate_and_zero<float>(maxSize);
@@ -90,31 +91,12 @@ RubberBandStretcher::Impl::ChannelData::construct(const std::set<size_t> &sizes,
} }
fft = ffts[initialFftSize]; fft = ffts[initialFftSize];
if (sizeof(process_t) == sizeof(double)) {
dblbuf = (process_t *)fft->getDoubleTimeBuffer();
} else {
dblbuf = (process_t *)fft->getFloatTimeBuffer();
}
resampler = 0; resampler = 0;
resamplebuf = 0; resamplebuf = 0;
resamplebufSize = 0; resamplebufSize = 0;
reset(); reset();
for (size_t i = 0; i < realSize; ++i) {
freqPeak[i] = 0;
}
for (size_t i = 0; i < initialFftSize; ++i) {
dblbuf[i] = 0.0;
}
for (size_t i = 0; i < maxSize; ++i) {
accumulator[i] = 0.f;
windowAccumulator[i] = 0.f;
}
// Avoid dividing opening sample (which will be discarded anyway) by zero // Avoid dividing opening sample (which will be discarded anyway) by zero
windowAccumulator[0] = 1.f; windowAccumulator[0] = 1.f;
} }
@@ -127,6 +109,7 @@ RubberBandStretcher::Impl::ChannelData::setSizes(size_t windowSize,
size_t maxSize = std::max(windowSize, fftSize); size_t maxSize = std::max(windowSize, fftSize);
size_t realSize = maxSize / 2 + 1; size_t realSize = maxSize / 2 + 1;
size_t oldMax = inbuf->getSize(); size_t oldMax = inbuf->getSize();
size_t oldReal = oldMax / 2 + 1;
if (oldMax >= maxSize) { if (oldMax >= maxSize) {
@@ -149,12 +132,7 @@ RubberBandStretcher::Impl::ChannelData::setSizes(size_t windowSize,
fft = ffts[fftSize]; fft = ffts[fftSize];
if (sizeof(process_t) == sizeof(double)) { v_zero(fltbuf, maxSize);
dblbuf = (process_t *)fft->getDoubleTimeBuffer();
} else {
dblbuf = (process_t *)fft->getFloatTimeBuffer();
}
v_zero(dblbuf, maxSize); v_zero(dblbuf, maxSize);
v_zero(mag, realSize); v_zero(mag, realSize);
@@ -180,34 +158,25 @@ RubberBandStretcher::Impl::ChannelData::setSizes(size_t windowSize,
// We don't want to preserve data in these arrays // We don't want to preserve data in these arrays
mag = reallocate_and_zero<process_t>(mag, oldMax, realSize); mag = reallocate_and_zero(mag, oldReal, realSize);
phase = reallocate_and_zero<process_t>(phase, oldMax, realSize); phase = reallocate_and_zero(phase, oldReal, realSize);
prevPhase = reallocate_and_zero<process_t>(prevPhase, oldMax, realSize); prevPhase = reallocate_and_zero(prevPhase, oldReal, realSize);
prevError = reallocate_and_zero<process_t>(prevError, oldMax, realSize); prevError = reallocate_and_zero(prevError, oldReal, realSize);
unwrappedPhase = reallocate_and_zero<process_t>(unwrappedPhase, oldMax, realSize); unwrappedPhase = reallocate_and_zero(unwrappedPhase, oldReal, realSize);
envelope = reallocate_and_zero<process_t>(envelope, oldMax, realSize); envelope = reallocate_and_zero(envelope, oldReal, realSize);
freqPeak = reallocate_and_zero(freqPeak, oldReal, realSize);
fltbuf = reallocate_and_zero(fltbuf, oldMax, maxSize);
dblbuf = reallocate_and_zero(dblbuf, oldMax, maxSize);
delete[] freqPeak; interpolator = reallocate_and_zero<float>(interpolator, oldMax, maxSize);
freqPeak = new size_t[realSize];
deallocate(fltbuf);
fltbuf = allocate_and_zero<float>(maxSize);
// But we do want to preserve data in these // But we do want to preserve data in these
float *newAcc = allocate_and_zero<float>(maxSize); accumulator = reallocate_and_zero_extension
(accumulator, oldMax, maxSize);
v_copy(newAcc, accumulator, oldMax); windowAccumulator = reallocate_and_zero_extension
(windowAccumulator, oldMax, maxSize);
deallocate(accumulator);
accumulator = newAcc;
newAcc = allocate_and_zero<float>(maxSize);
v_copy(newAcc, windowAccumulator, oldMax);
deallocate(windowAccumulator);
windowAccumulator = newAcc;
interpolatorScale = 0; interpolatorScale = 0;
@@ -223,14 +192,6 @@ RubberBandStretcher::Impl::ChannelData::setSizes(size_t windowSize,
} }
fft = ffts[fftSize]; fft = ffts[fftSize];
if (sizeof(process_t) == sizeof(double)) {
dblbuf = (process_t *)fft->getDoubleTimeBuffer();
} else {
dblbuf = (process_t *)fft->getFloatTimeBuffer();
}
v_zero(dblbuf, fftSize);
} }
void void
@@ -273,7 +234,7 @@ RubberBandStretcher::Impl::ChannelData::~ChannelData()
deallocate(prevError); deallocate(prevError);
deallocate(unwrappedPhase); deallocate(unwrappedPhase);
deallocate(envelope); deallocate(envelope);
delete[] freqPeak; deallocate(freqPeak);
deallocate(accumulator); deallocate(accumulator);
deallocate(windowAccumulator); deallocate(windowAccumulator);
deallocate(fltbuf); deallocate(fltbuf);

View File

@@ -783,8 +783,10 @@ RubberBandStretcher::Impl::reconfigure()
new Resampler(Resampler::FastestTolerable, 1, m_sWindowSize, new Resampler(Resampler::FastestTolerable, 1, m_sWindowSize,
m_debugLevel); m_debugLevel);
m_channelData[c]->setResampleBufSize size_t rbs =
(lrintf(ceil((m_increment * m_timeRatio * 2) / m_pitchScale))); lrintf(ceil((m_increment * m_timeRatio * 2) / m_pitchScale));
if (rbs < m_increment * 16) rbs = m_increment * 16;
m_channelData[c]->setResampleBufSize(rbs);
} }
} }

View File

@@ -910,22 +910,27 @@ RubberBandStretcher::Impl::synthesiseChunk(size_t channel,
} }
if (wsz > fsz) { if (wsz > fsz) {
float *tmp = (float *)alloca(wsz * sizeof(float));
int p = shiftIncrement * 2; int p = shiftIncrement * 2;
if (cd.interpolatorScale != p) { if (cd.interpolatorScale != p) {
SincWindow<float>::write(cd.interpolator, wsz, p); SincWindow<float>::write(cd.interpolator, wsz, p);
cd.interpolatorScale = p;
} }
v_multiply(fltbuf, cd.interpolator, wsz); v_multiply(fltbuf, cd.interpolator, wsz);
v_copy(tmp, cd.interpolator, wsz);
m_swindow->cut(tmp);
v_add(windowAccumulator, tmp, wsz);
} else {
m_swindow->add(windowAccumulator, m_awindow->getArea() * 1.5f);
} }
m_swindow->cut(fltbuf); m_swindow->cut(fltbuf);
v_add(accumulator, fltbuf, wsz); v_add(accumulator, fltbuf, wsz);
cd.accumulatorFill = wsz; cd.accumulatorFill = wsz;
if (wsz > fsz) {
// reuse fltbuf to calculate interpolating window shape for
// window accumulator
v_copy(fltbuf, cd.interpolator, wsz);
m_swindow->cut(fltbuf);
v_add(windowAccumulator, fltbuf, wsz);
} else {
m_swindow->add(windowAccumulator, m_awindow->getArea() * 1.5f);
}
} }
void void

View File

@@ -43,6 +43,9 @@ namespace RubberBand {
* -- it's just a quick hack for use with things like plugins. * -- it's just a quick hack for use with things like plugins.
*/ */
//!!! should review this, it's not really thread safe owing to lack of
//!!! atomic updates
template <typename T> template <typename T>
class Scavenger class Scavenger
{ {

View File

@@ -28,6 +28,7 @@ CompoundAudioCurve::CompoundAudioCurve(Parameters parameters) :
m_hf(parameters), m_hf(parameters),
m_hfFilter(new MovingMedian<double>(19, 85)), m_hfFilter(new MovingMedian<double>(19, 85)),
m_hfDerivFilter(new MovingMedian<double>(19, 90)), m_hfDerivFilter(new MovingMedian<double>(19, 90)),
m_type(CompoundDetector),
m_lastHf(0.0), m_lastHf(0.0),
m_lastResult(0.0), m_lastResult(0.0),
m_risingCount(0) m_risingCount(0)

View File

@@ -35,7 +35,7 @@ public:
CompoundDetector, CompoundDetector,
SoftDetector SoftDetector
}; };
virtual void setType(Type); virtual void setType(Type); // default is CompoundDetector
virtual void setFftSize(int newSize); virtual void setFftSize(int newSize);

View File

@@ -17,8 +17,9 @@
#include "base/Profiler.h" #include "base/Profiler.h"
#include "system/Allocators.h" #include "system/Allocators.h"
#include "system/VectorOps.h" #include "system/VectorOps.h"
#include "system/VectorOpsComplex.h"
//#define FFT_MEASUREMENT 1 #define FFT_MEASUREMENT 1
#ifdef HAVE_FFTW3 #ifdef HAVE_FFTW3
@@ -77,9 +78,6 @@ public:
virtual void inverseInterleaved(const float *R__ complexIn, float *R__ realOut) = 0; virtual void inverseInterleaved(const float *R__ complexIn, float *R__ realOut) = 0;
virtual void inversePolar(const float *R__ magIn, const float *R__ phaseIn, float *R__ realOut) = 0; virtual void inversePolar(const float *R__ magIn, const float *R__ phaseIn, float *R__ realOut) = 0;
virtual void inverseCepstral(const float *R__ magIn, float *R__ cepOut) = 0; virtual void inverseCepstral(const float *R__ magIn, float *R__ cepOut) = 0;
virtual float *getFloatTimeBuffer() = 0;
virtual double *getDoubleTimeBuffer() = 0;
}; };
namespace FFTs { namespace FFTs {
@@ -152,15 +150,8 @@ namespace FFTs {
class D_FFTW : public FFTImpl class D_FFTW : public FFTImpl
{ {
public: public:
D_FFTW(int size) : m_fplanf(0) D_FFTW(int size) :
#ifdef FFTW_DOUBLE_ONLY m_fplanf(0), m_dplanf(0), m_size(size)
, m_frb(0)
#endif
, m_dplanf(0)
#ifdef FFTW_FLOAT_ONLY
, m_drb(0)
#endif
, m_size(size)
{ {
} }
@@ -176,9 +167,6 @@ public:
fftwf_destroy_plan(m_fplani); fftwf_destroy_plan(m_fplani);
fftwf_free(m_fbuf); fftwf_free(m_fbuf);
fftwf_free(m_fpacked); fftwf_free(m_fpacked);
#ifdef FFTW_DOUBLE_ONLY
if (m_frb) fftw_free(m_frb);
#endif
m_commonMutex.unlock(); m_commonMutex.unlock();
} }
if (m_dplanf) { if (m_dplanf) {
@@ -192,9 +180,6 @@ public:
fftw_destroy_plan(m_dplani); fftw_destroy_plan(m_dplani);
fftw_free(m_dbuf); fftw_free(m_dbuf);
fftw_free(m_dpacked); fftw_free(m_dpacked);
#ifdef FFTW_FLOAT_ONLY
if (m_drb) fftwf_free(m_drb);
#endif
m_commonMutex.unlock(); m_commonMutex.unlock();
} }
} }
@@ -390,14 +375,8 @@ public:
dbuf[i] = realIn[i]; dbuf[i] = realIn[i];
} }
fftw_execute(m_dplanf); fftw_execute(m_dplanf);
const int hs = m_size/2; v_cartesian_interleaved_to_polar(magOut, phaseOut,
for (int i = 0; i <= hs; ++i) { (double *)m_dpacked, m_size/2+1);
magOut[i] = sqrt(m_dpacked[i][0] * m_dpacked[i][0] +
m_dpacked[i][1] * m_dpacked[i][1]);
}
for (int i = 0; i <= hs; ++i) {
phaseOut[i] = atan2(m_dpacked[i][1], m_dpacked[i][0]);
}
} }
void forwardMagnitude(const double *R__ realIn, double *R__ magOut) { void forwardMagnitude(const double *R__ realIn, double *R__ magOut) {
@@ -457,14 +436,8 @@ public:
fbuf[i] = realIn[i]; fbuf[i] = realIn[i];
} }
fftwf_execute(m_fplanf); fftwf_execute(m_fplanf);
const int hs = m_size/2; v_cartesian_interleaved_to_polar(magOut, phaseOut,
for (int i = 0; i <= hs; ++i) { (float *)m_fpacked, m_size/2+1);
magOut[i] = sqrtf(m_fpacked[i][0] * m_fpacked[i][0] +
m_fpacked[i][1] * m_fpacked[i][1]);
}
for (int i = 0; i <= hs; ++i) {
phaseOut[i] = atan2f(m_fpacked[i][1], m_fpacked[i][0]) ;
}
} }
void forwardMagnitude(const float *R__ realIn, float *R__ magOut) { void forwardMagnitude(const float *R__ realIn, float *R__ magOut) {
@@ -625,31 +598,10 @@ public:
} }
} }
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: private:
fftwf_plan m_fplanf; fftwf_plan m_fplanf;
fftwf_plan m_fplani; fftwf_plan m_fplani;
#ifdef FFTW_DOUBLE_ONLY #ifdef FFTW_DOUBLE_ONLY
float *m_frb;
double *m_fbuf; double *m_fbuf;
#else #else
float *m_fbuf; float *m_fbuf;
@@ -659,11 +611,10 @@ private:
fftw_plan m_dplani; fftw_plan m_dplani;
#ifdef FFTW_FLOAT_ONLY #ifdef FFTW_FLOAT_ONLY
float *m_dbuf; float *m_dbuf;
double *m_drb;
#else #else
double *m_dbuf; double *m_dbuf;
#endif #endif
fftw_complex * m_dpacked; fftw_complex *m_dpacked;
const int m_size; const int m_size;
static int m_extantf; static int m_extantf;
static int m_extantd; static int m_extantd;
@@ -688,8 +639,6 @@ class D_KISSFFT : public FFTImpl
public: public:
D_KISSFFT(int size) : D_KISSFFT(int size) :
m_size(size), m_size(size),
m_frb(0),
m_drb(0),
m_fplanf(0), m_fplanf(0),
m_fplani(0) m_fplani(0)
{ {
@@ -714,9 +663,6 @@ public:
delete[] m_fbuf; delete[] m_fbuf;
delete[] m_fpacked; delete[] m_fpacked;
if (m_frb) delete[] m_frb;
if (m_drb) delete[] m_drb;
} }
void initFloat() { } void initFloat() { }
@@ -957,20 +903,8 @@ public:
kiss_fftri(m_fplani, m_fpacked, cepOut); kiss_fftri(m_fplani, m_fpacked, cepOut);
} }
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: private:
const int m_size; const int m_size;
float* m_frb;
double* m_drb;
kiss_fftr_cfg m_fplanf; kiss_fftr_cfg m_fplanf;
kiss_fftr_cfg m_fplani; kiss_fftr_cfg m_fplani;
kiss_fft_scalar *m_fbuf; kiss_fft_scalar *m_fbuf;
@@ -984,7 +918,7 @@ private:
class D_Cross : public FFTImpl class D_Cross : public FFTImpl
{ {
public: public:
D_Cross(int size) : m_size(size), m_table(0), m_frb(0), m_drb(0) { D_Cross(int size) : m_size(size), m_table(0) {
m_a = new double[size]; m_a = new double[size];
m_b = new double[size]; m_b = new double[size];
@@ -1022,8 +956,6 @@ public:
delete[] m_b; delete[] m_b;
delete[] m_c; delete[] m_c;
delete[] m_d; delete[] m_d;
delete[] m_frb;
delete[] m_drb;
} }
void initFloat() { } void initFloat() { }
@@ -1221,21 +1153,9 @@ public:
for (int i = 0; i < m_size; ++i) cepOut[i] = m_c[i]; for (int i = 0; i < m_size; ++i) cepOut[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: private:
const int m_size; const int m_size;
int *m_table; int *m_table;
float *m_frb;
double *m_drb;
double *m_a; double *m_a;
double *m_b; double *m_b;
double *m_c; double *m_c;
@@ -1561,18 +1481,6 @@ FFT::initDouble()
d->initDouble(); d->initDouble();
} }
float *
FFT::getFloatTimeBuffer()
{
return d->getFloatTimeBuffer();
}
double *
FFT::getDoubleTimeBuffer()
{
return d->getDoubleTimeBuffer();
}
void void
FFT::tune() FFT::tune()

View File

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

View File

@@ -43,7 +43,7 @@ PercussiveAudioCurve::reset()
void void
PercussiveAudioCurve::setFftSize(int newSize) PercussiveAudioCurve::setFftSize(int newSize)
{ {
m_prevMag = reallocate(m_prevMag, m_fftSize, newSize); m_prevMag = reallocate(m_prevMag, m_fftSize/2 + 1, newSize/2 + 1);
AudioCurveCalculator::setFftSize(newSize); AudioCurveCalculator::setFftSize(newSize);
reset(); reset();
} }

View File

@@ -506,6 +506,14 @@ Resampler::Resampler(Resampler::Quality quality, int channels,
#endif #endif
break; break;
} }
if (!d) {
std::cerr << "Resampler::Resampler(" << quality << ", " << channels
<< ", " << maxBufferSize
<< "): Internal error: No implementation selected"
<< std::endl;
abort();
}
} }
Resampler::~Resampler() Resampler::~Resampler()

View File

@@ -70,6 +70,7 @@ void deallocate(T *ptr)
} }
/// Reallocate preserving contents but leaving additional memory uninitialised
template <typename T> template <typename T>
T *reallocate(T *ptr, size_t oldcount, size_t count) T *reallocate(T *ptr, size_t oldcount, size_t count)
{ {
@@ -87,6 +88,7 @@ T *reallocate(T *ptr, size_t oldcount, size_t count)
return newptr; return newptr;
} }
/// Reallocate, zeroing all contents
template <typename T> template <typename T>
T *reallocate_and_zero(T *ptr, size_t oldcount, size_t count) T *reallocate_and_zero(T *ptr, size_t oldcount, size_t count)
{ {
@@ -95,6 +97,15 @@ T *reallocate_and_zero(T *ptr, size_t oldcount, size_t count)
return ptr; return ptr;
} }
/// Reallocate preserving contents and zeroing any additional memory
template <typename T>
T *reallocate_and_zero_extension(T *ptr, size_t oldcount, size_t count)
{
ptr = reallocate(ptr, oldcount, count);
if (count > oldcount) v_zero(ptr + oldcount, count - oldcount);
return ptr;
}
template <typename T> template <typename T>
T **allocate_channels(size_t channels, size_t count) T **allocate_channels(size_t channels, size_t count)
{ {

View File

@@ -99,26 +99,26 @@ private:
Mutex *m_mutex; Mutex *m_mutex;
}; };
/**
The Condition class bundles a condition variable and mutex.
To wait on a condition, call lock(), test the termination condition
if desired, then wait(). The condition will be unlocked during the
wait and re-locked when wait() returns (which will happen when the
condition is signalled or the timer times out).
To signal a condition, call signal(). If the condition is signalled
between lock() and wait(), the signal may be missed by the waiting
thread. To avoid this, the signalling thread should also lock the
condition before calling signal() and unlock it afterwards.
*/
class Condition class Condition
{ {
public: public:
Condition(std::string name); Condition(std::string name);
~Condition(); ~Condition();
// The Condition class bundles a condition variable and mutex.
// To wait on a condition, call lock(), test the termination
// condition if desired, then wait(). The condition will be
// unlocked during the wait and re-locked when wait() returns
// (which will happen when the condition is signalled or the timer
// times out).
// To signal a condition, call signal(). If the condition is
// signalled between lock() and wait(), the signal may be missed
// by the waiting thread. To avoid this, the signalling thread
// should also lock the condition before calling signal() and
// unlock it afterwards.
void lock(); void lock();
void unlock(); void unlock();
void wait(int us = 0); void wait(int us = 0);