* 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:
47
README.txt
47
README.txt
@@ -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
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
112
src/dsp/FFT.cpp
112
src/dsp/FFT.cpp
@@ -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()
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user