diff options
Diffstat (limited to 'libs/rubberband/src')
49 files changed, 0 insertions, 11732 deletions
diff --git a/libs/rubberband/src/AudioCurve.cpp b/libs/rubberband/src/AudioCurve.cpp deleted file mode 100644 index 8cf247b1db..0000000000 --- a/libs/rubberband/src/AudioCurve.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#include "AudioCurve.h" - -#include <iostream> -using namespace std; - -namespace RubberBand -{ - -AudioCurve::AudioCurve(size_t sampleRate, size_t windowSize) : - m_sampleRate(sampleRate), - m_windowSize(windowSize) -{ -} - -AudioCurve::~AudioCurve() -{ -} - -float -AudioCurve::processDouble(const double *R__ mag, size_t increment) -{ - cerr << "AudioCurve::processDouble: WARNING: Using inefficient and lossy conversion for AudioCurve::process(float)" << endl; - float *tmp = new float[m_windowSize]; - for (int i = 0; i < int(m_windowSize); ++i) tmp[i] = float(mag[i]); - float df = process(tmp, increment); - delete[] tmp; - return df; -} - -} diff --git a/libs/rubberband/src/AudioCurve.h b/libs/rubberband/src/AudioCurve.h deleted file mode 100644 index a34a4aab9a..0000000000 --- a/libs/rubberband/src/AudioCurve.h +++ /dev/null @@ -1,45 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#ifndef _AUDIO_CURVE_H_ -#define _AUDIO_CURVE_H_ - -#include <sys/types.h> - -#include "sysutils.h" - -namespace RubberBand -{ - -class AudioCurve -{ -public: - AudioCurve(size_t sampleRate, size_t windowSize); - virtual ~AudioCurve(); - - virtual void setWindowSize(size_t newSize) = 0; - - virtual float process(const float *R__ mag, size_t increment) = 0; - virtual float processDouble(const double *R__ mag, size_t increment); - virtual void reset() = 0; - -protected: - size_t m_sampleRate; - size_t m_windowSize; -}; - -} - -#endif - diff --git a/libs/rubberband/src/ConstantAudioCurve.cpp b/libs/rubberband/src/ConstantAudioCurve.cpp deleted file mode 100644 index 87867f3cb2..0000000000 --- a/libs/rubberband/src/ConstantAudioCurve.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#include "ConstantAudioCurve.h" - -namespace RubberBand -{ - -ConstantAudioCurve::ConstantAudioCurve(size_t sampleRate, size_t windowSize) : - AudioCurve(sampleRate, windowSize) -{ -} - -ConstantAudioCurve::~ConstantAudioCurve() -{ -} - -void -ConstantAudioCurve::reset() -{ -} - -void -ConstantAudioCurve::setWindowSize(size_t newSize) -{ - m_windowSize = newSize; -} - -float -ConstantAudioCurve::process(const float *R__, size_t) -{ - return 1.f; -} - -float -ConstantAudioCurve::processDouble(const double *R__, size_t) -{ - return 1.f; -} - -} - diff --git a/libs/rubberband/src/ConstantAudioCurve.h b/libs/rubberband/src/ConstantAudioCurve.h deleted file mode 100644 index 41a2ea0ca5..0000000000 --- a/libs/rubberband/src/ConstantAudioCurve.h +++ /dev/null @@ -1,38 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#ifndef _CONSTANT_AUDIO_CURVE_H_ -#define _CONSTANT_AUDIO_CURVE_H_ - -#include "AudioCurve.h" - -namespace RubberBand -{ - -class ConstantAudioCurve : public AudioCurve -{ -public: - ConstantAudioCurve(size_t sampleRate, size_t windowSize); - virtual ~ConstantAudioCurve(); - - virtual void setWindowSize(size_t newSize); - - virtual float process(const float *R__ mag, size_t increment); - virtual float processDouble(const double *R__ mag, size_t increment); - virtual void reset(); -}; - -} - -#endif diff --git a/libs/rubberband/src/FFT.cpp b/libs/rubberband/src/FFT.cpp deleted file mode 100644 index f04f6506d6..0000000000 --- a/libs/rubberband/src/FFT.cpp +++ /dev/null @@ -1,1369 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#include "FFT.h" -#include "Thread.h" -#include "Profiler.h" - -//#define FFT_MEASUREMENT 1 - -#ifndef HAVE_FFTW3 -#define HAVE_FFTW3 // for Ardour -#endif - -#ifdef HAVE_FFTW3 -#include <fftw3.h> -#endif - -#include <cstdlib> - -#ifdef USE_KISSFFT -#include "bsd-3rdparty/kissfft/kiss_fftr.h" -#endif - -#ifndef HAVE_FFTW3 -#ifndef USE_KISSFFT -#ifndef USE_BUILTIN_FFT -#error No FFT implementation selected! -#endif -#endif -#endif - -#include <cmath> -#include <iostream> -#include <map> -#include <cstdio> -#include <cstdlib> -#include <vector> - -namespace RubberBand { - -class FFTImpl -{ -public: - virtual ~FFTImpl() { } - - virtual void initFloat() = 0; - virtual void initDouble() = 0; - - virtual void forward(const double *R__ realIn, double *R__ realOut, double *R__ imagOut) = 0; - virtual void forwardPolar(const double *R__ realIn, double *R__ magOut, double *R__ phaseOut) = 0; - virtual void forwardMagnitude(const double *R__ realIn, double *R__ magOut) = 0; - - virtual void forward(const float *R__ realIn, float *R__ realOut, float *R__ imagOut) = 0; - virtual void forwardPolar(const float *R__ realIn, float *R__ magOut, float *R__ phaseOut) = 0; - virtual void forwardMagnitude(const float *R__ realIn, float *R__ magOut) = 0; - - virtual void inverse(const double *R__ realIn, const double *R__ imagIn, double *R__ realOut) = 0; - virtual void inversePolar(const double *R__ magIn, const double *R__ phaseIn, double *R__ realOut) = 0; - virtual void inverseCepstral(const double *R__ magIn, double *R__ cepOut) = 0; - - virtual void inverse(const float *R__ realIn, const float *R__ imagIn, 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 float *getFloatTimeBuffer() = 0; - virtual double *getDoubleTimeBuffer() = 0; -}; - -namespace FFTs { - - -#ifdef HAVE_FFTW3 - -// 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 - -#if defined(FFTW_DOUBLE_ONLY) && defined(FFTW_FLOAT_ONLY) -// Can't meaningfully define both -#undef FFTW_DOUBLE_ONLY -#undef FFTW_FLOAT_ONLY -#endif - -#ifdef FFTW_DOUBLE_ONLY -#define fft_float_type double -#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 -#else -#define fft_float_type float -#endif /* FFTW_DOUBLE_ONLY */ - -#ifdef FFTW_FLOAT_ONLY -#define fft_double_type float -#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 sin sinf -#else -#define fft_double_type double -#endif /* FFTW_FLOAT_ONLY */ - -class D_FFTW : public FFTImpl -{ -public: - D_FFTW(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() { - if (m_fplanf) { - bool save = false; - m_extantMutex.lock(); - if (m_extantf > 0 && --m_extantf == 0) save = true; - m_extantMutex.unlock(); -#ifndef FFTW_DOUBLE_ONLY - if (save) saveWisdom('f'); -#endif - fftwf_destroy_plan(m_fplanf); - 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; - m_extantMutex.lock(); - if (m_extantd > 0 && --m_extantd == 0) save = true; - m_extantMutex.unlock(); -#ifndef FFTW_FLOAT_ONLY - if (save) saveWisdom('d'); -#endif - fftw_destroy_plan(m_dplanf); - 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 - } - } - - void initFloat() { - if (m_fplanf) return; - bool load = false; - m_extantMutex.lock(); - if (m_extantf++ == 0) load = true; - m_extantMutex.unlock(); -#ifdef FFTW_DOUBLE_ONLY - if (load) loadWisdom('d'); -#else - if (load) loadWisdom('f'); -#endif - m_fbuf = (fft_float_type *)fftw_malloc(m_size * sizeof(fft_float_type)); - m_fpacked = (fftwf_complex *)fftw_malloc - ((m_size/2 + 1) * sizeof(fftwf_complex)); - m_fplanf = fftwf_plan_dft_r2c_1d - (m_size, m_fbuf, m_fpacked, FFTW_MEASURE); - m_fplani = fftwf_plan_dft_c2r_1d - (m_size, m_fpacked, m_fbuf, FFTW_MEASURE); - } - - void initDouble() { - if (m_dplanf) return; - bool load = false; - m_extantMutex.lock(); - if (m_extantd++ == 0) load = true; - m_extantMutex.unlock(); -#ifdef FFTW_FLOAT_ONLY - if (load) loadWisdom('f'); -#else - if (load) loadWisdom('d'); -#endif - m_dbuf = (fft_double_type *)fftw_malloc(m_size * sizeof(fft_double_type)); - m_dpacked = (fftw_complex *)fftw_malloc - ((m_size/2 + 1) * sizeof(fftw_complex)); - m_dplanf = fftw_plan_dft_r2c_1d - (m_size, m_dbuf, m_dpacked, FFTW_MEASURE); - m_dplani = fftw_plan_dft_c2r_1d - (m_size, m_dpacked, m_dbuf, FFTW_MEASURE); - } - - void loadWisdom(char type) { wisdom(false, type); } - void saveWisdom(char type) { wisdom(true, type); } - - void wisdom(bool save, char type) { - -#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; - - char fn[256]; - snprintf(fn, 256, "%s/%s.%c", home, ".rubberband.wisdom", type); - - FILE *f = fopen(fn, save ? "wb" : "rb"); - if (!f) return; - - if (save) { - switch (type) { -#ifdef FFTW_DOUBLE_ONLY - case 'f': break; -#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 { - switch (type) { -#ifdef FFTW_DOUBLE_ONLY - case 'f': break; -#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; - } - } - - fclose(f); - } - - void packFloat(const float *R__ re, const float *R__ im) { - const int hs = m_size/2; - fftwf_complex *const R__ fpacked = m_fpacked; - for (int i = 0; i <= hs; ++i) { - fpacked[i][0] = re[i]; - } - if (im) { - for (int i = 0; i <= hs; ++i) { - fpacked[i][1] = im[i]; - } - } else { - for (int i = 0; i <= hs; ++i) { - fpacked[i][1] = 0.f; - } - } - } - - void packDouble(const double *R__ re, const double *R__ im) { - const int hs = m_size/2; - fftw_complex *const R__ dpacked = m_dpacked; - for (int i = 0; i <= hs; ++i) { - dpacked[i][0] = re[i]; - } - if (im) { - for (int i = 0; i <= hs; ++i) { - dpacked[i][1] = im[i]; - } - } else { - for (int i = 0; i <= hs; ++i) { - dpacked[i][1] = 0.0; - } - } - } - - void unpackFloat(float *R__ re, float *R__ im) { - const int hs = m_size/2; - for (int i = 0; i <= hs; ++i) { - re[i] = m_fpacked[i][0]; - } - if (im) { - for (int i = 0; i <= hs; ++i) { - im[i] = m_fpacked[i][1]; - } - } - } - - void unpackDouble(double *R__ re, double *R__ im) { - const int hs = m_size/2; - for (int i = 0; i <= hs; ++i) { - re[i] = m_dpacked[i][0]; - } - if (im) { - for (int i = 0; i <= hs; ++i) { - im[i] = m_dpacked[i][1]; - } - } - } - - void forward(const double *R__ realIn, double *R__ realOut, double *R__ imagOut) { - if (!m_dplanf) initDouble(); - const int sz = m_size; - fft_double_type *const R__ dbuf = m_dbuf; -#ifndef FFTW_FLOAT_ONLY - if (realIn != dbuf) -#endif - for (int i = 0; i < sz; ++i) { - dbuf[i] = realIn[i]; - } - fftw_execute(m_dplanf); - unpackDouble(realOut, imagOut); - } - - void forwardPolar(const double *R__ realIn, double *R__ magOut, double *R__ phaseOut) { - if (!m_dplanf) initDouble(); - fft_double_type *const R__ dbuf = m_dbuf; - const int sz = m_size; -#ifndef FFTW_FLOAT_ONLY - if (realIn != dbuf) -#endif - for (int i = 0; i < sz; ++i) { - dbuf[i] = realIn[i]; - } - fftw_execute(m_dplanf); - const int hs = m_size/2; - for (int i = 0; i <= hs; ++i) { - 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) { - if (!m_dplanf) initDouble(); - fft_double_type *const R__ dbuf = m_dbuf; - const int sz = m_size; -#ifndef FFTW_FLOAT_ONLY - if (realIn != m_dbuf) -#endif - for (int i = 0; i < sz; ++i) { - dbuf[i] = realIn[i]; - } - fftw_execute(m_dplanf); - const int hs = m_size/2; - for (int i = 0; i <= hs; ++i) { - magOut[i] = sqrt(m_dpacked[i][0] * m_dpacked[i][0] + - m_dpacked[i][1] * m_dpacked[i][1]); - } - } - - void forward(const float *R__ realIn, float *R__ realOut, float *R__ imagOut) { - if (!m_fplanf) initFloat(); - fft_float_type *const R__ fbuf = m_fbuf; - const int sz = m_size; -#ifndef FFTW_DOUBLE_ONLY - if (realIn != fbuf) -#endif - for (int i = 0; i < sz; ++i) { - fbuf[i] = realIn[i]; - } - fftwf_execute(m_fplanf); - unpackFloat(realOut, imagOut); - } - - void forwardPolar(const float *R__ realIn, float *R__ magOut, float *R__ phaseOut) { - if (!m_fplanf) initFloat(); - fft_float_type *const R__ fbuf = m_fbuf; - const int sz = m_size; -#ifndef FFTW_DOUBLE_ONLY - if (realIn != fbuf) -#endif - for (int i = 0; i < sz; ++i) { - fbuf[i] = realIn[i]; - } - fftwf_execute(m_fplanf); - const int hs = m_size/2; - for (int i = 0; i <= hs; ++i) { - 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) { - if (!m_fplanf) initFloat(); - fft_float_type *const R__ fbuf = m_fbuf; - const int sz = m_size; -#ifndef FFTW_DOUBLE_ONLY - if (realIn != fbuf) -#endif - for (int i = 0; i < sz; ++i) { - fbuf[i] = realIn[i]; - } - fftwf_execute(m_fplanf); - const int hs = m_size/2; - for (int i = 0; i <= hs; ++i) { - magOut[i] = sqrtf(m_fpacked[i][0] * m_fpacked[i][0] + - m_fpacked[i][1] * m_fpacked[i][1]); - } - } - - void inverse(const double *R__ realIn, const double *R__ imagIn, double *R__ realOut) { - if (!m_dplanf) initDouble(); - packDouble(realIn, imagIn); - fftw_execute(m_dplani); - const int sz = m_size; - fft_double_type *const R__ dbuf = m_dbuf; -#ifndef FFTW_FLOAT_ONLY - if (realOut != dbuf) -#endif - for (int i = 0; i < sz; ++i) { - realOut[i] = dbuf[i]; - } - } - - void inversePolar(const double *R__ magIn, const double *R__ phaseIn, double *R__ realOut) { - if (!m_dplanf) initDouble(); - const int hs = m_size/2; - fftw_complex *const R__ dpacked = m_dpacked; - for (int i = 0; i <= hs; ++i) { - dpacked[i][0] = magIn[i] * cos(phaseIn[i]); - } - for (int i = 0; i <= hs; ++i) { - dpacked[i][1] = magIn[i] * sin(phaseIn[i]); - } - fftw_execute(m_dplani); - const int sz = m_size; - fft_double_type *const R__ dbuf = m_dbuf; -#ifndef FFTW_FLOAT_ONLY - if (realOut != dbuf) -#endif - for (int i = 0; i < sz; ++i) { - realOut[i] = dbuf[i]; - } - } - - void inverseCepstral(const double *R__ magIn, double *R__ cepOut) { - if (!m_dplanf) initDouble(); - fft_double_type *const R__ dbuf = m_dbuf; - fftw_complex *const R__ dpacked = m_dpacked; - const int hs = m_size/2; - for (int i = 0; i <= hs; ++i) { - dpacked[i][0] = log(magIn[i] + 0.000001); - } - for (int i = 0; i <= hs; ++i) { - dpacked[i][1] = 0.0; - } - fftw_execute(m_dplani); - const int sz = m_size; -#ifndef FFTW_FLOAT_ONLY - if (cepOut != dbuf) -#endif - for (int i = 0; i < sz; ++i) { - cepOut[i] = dbuf[i]; - } - } - - void inverse(const float *R__ realIn, const float *R__ imagIn, float *R__ realOut) { - if (!m_fplanf) initFloat(); - packFloat(realIn, imagIn); - fftwf_execute(m_fplani); - const int sz = m_size; - fft_float_type *const R__ fbuf = m_fbuf; -#ifndef FFTW_DOUBLE_ONLY - if (realOut != fbuf) -#endif - for (int i = 0; i < sz; ++i) { - realOut[i] = fbuf[i]; - } - } - - void inversePolar(const float *R__ magIn, const float *R__ phaseIn, float *R__ realOut) { - if (!m_fplanf) initFloat(); - const int hs = m_size/2; - fftwf_complex *const R__ fpacked = m_fpacked; - for (int i = 0; i <= hs; ++i) { - fpacked[i][0] = magIn[i] * cosf(phaseIn[i]); - } - for (int i = 0; i <= hs; ++i) { - fpacked[i][1] = magIn[i] * sinf(phaseIn[i]); - } - fftwf_execute(m_fplani); - const int sz = m_size; - fft_float_type *const R__ fbuf = m_fbuf; -#ifndef FFTW_DOUBLE_ONLY - if (realOut != fbuf) -#endif - for (int i = 0; i < sz; ++i) { - realOut[i] = fbuf[i]; - } - } - - void inverseCepstral(const float *R__ magIn, float *R__ cepOut) { - if (!m_fplanf) initFloat(); - const int hs = m_size/2; - fftwf_complex *const R__ fpacked = m_fpacked; - for (int i = 0; i <= hs; ++i) { - fpacked[i][0] = logf(magIn[i] + 0.000001f); - } - for (int i = 0; i <= hs; ++i) { - fpacked[i][1] = 0.f; - } - fftwf_execute(m_fplani); - const int sz = m_size; - fft_float_type *const R__ fbuf = m_fbuf; -#ifndef FFTW_DOUBLE_ONLY - if (cepOut != fbuf) -#endif - for (int i = 0; i < sz; ++i) { - cepOut[i] = 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; -#endif - 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; - const int m_size; - static int m_extantf; - static int m_extantd; - static Mutex m_extantMutex; -}; - -int -D_FFTW::m_extantf = 0; - -int -D_FFTW::m_extantd = 0; - -Mutex -D_FFTW::m_extantMutex; - -#endif /* HAVE_FFTW3 */ - -#ifdef USE_KISSFFT - -class D_KISSFFT : public FFTImpl -{ -public: - D_KISSFFT(int size) : - m_size(size), - m_frb(0), - m_drb(0), - m_fplanf(0), - m_fplani(0) - { -#ifdef FIXED_POINT -#error KISSFFT is not configured for float values -#endif - if (sizeof(kiss_fft_scalar) != sizeof(float)) { - std::cerr << "ERROR: KISSFFT is not configured for float values" - << std::endl; - } - - m_fbuf = new kiss_fft_scalar[m_size + 2]; - m_fpacked = new kiss_fft_cpx[m_size + 2]; - m_fplanf = kiss_fftr_alloc(m_size, 0, NULL, NULL); - m_fplani = kiss_fftr_alloc(m_size, 1, NULL, NULL); - } - - ~D_KISSFFT() { - kiss_fftr_free(m_fplanf); - kiss_fftr_free(m_fplani); - kiss_fft_cleanup(); - - delete[] m_fbuf; - delete[] m_fpacked; - - if (m_frb) delete[] m_frb; - if (m_drb) delete[] m_drb; - } - - void initFloat() { } - void initDouble() { } - - void packFloat(const float *R__ re, const float *R__ im) { - const int hs = m_size/2; - for (int i = 0; i <= hs; ++i) { - m_fpacked[i].r = re[i]; - m_fpacked[i].i = im[i]; - } - } - - void unpackFloat(float *R__ re, float *R__ im) { - const int hs = m_size/2; - for (int i = 0; i <= hs; ++i) { - re[i] = m_fpacked[i].r; - im[i] = m_fpacked[i].i; - } - } - - void packDouble(const double *R__ re, const double *R__ im) { - const int hs = m_size/2; - for (int i = 0; i <= hs; ++i) { - m_fpacked[i].r = float(re[i]); - m_fpacked[i].i = float(im[i]); - } - } - - void unpackDouble(double *R__ re, double *R__ im) { - const int hs = m_size/2; - for (int i = 0; i <= hs; ++i) { - re[i] = double(m_fpacked[i].r); - im[i] = double(m_fpacked[i].i); - } - } - - void forward(const double *R__ realIn, double *R__ realOut, double *R__ imagOut) { - - for (int i = 0; i < m_size; ++i) { - m_fbuf[i] = float(realIn[i]); - } - - kiss_fftr(m_fplanf, m_fbuf, m_fpacked); - unpackDouble(realOut, imagOut); - } - - void forwardPolar(const double *R__ realIn, double *R__ magOut, double *R__ phaseOut) { - - for (int i = 0; i < m_size; ++i) { - m_fbuf[i] = float(realIn[i]); - } - - kiss_fftr(m_fplanf, m_fbuf, m_fpacked); - - const int hs = m_size/2; - - for (int i = 0; i <= hs; ++i) { - magOut[i] = sqrt(double(m_fpacked[i].r) * double(m_fpacked[i].r) + - double(m_fpacked[i].i) * double(m_fpacked[i].i)); - } - - for (int i = 0; i <= hs; ++i) { - phaseOut[i] = atan2(double(m_fpacked[i].i), double(m_fpacked[i].r)); - } - } - - void forwardMagnitude(const double *R__ realIn, double *R__ magOut) { - - for (int i = 0; i < m_size; ++i) { - m_fbuf[i] = float(realIn[i]); - } - - kiss_fftr(m_fplanf, m_fbuf, m_fpacked); - - const int hs = m_size/2; - - for (int i = 0; i <= hs; ++i) { - magOut[i] = sqrt(double(m_fpacked[i].r) * double(m_fpacked[i].r) + - double(m_fpacked[i].i) * double(m_fpacked[i].i)); - } - } - - void forward(const float *R__ realIn, float *R__ realOut, float *R__ imagOut) { - - kiss_fftr(m_fplanf, realIn, m_fpacked); - unpackFloat(realOut, imagOut); - } - - void forwardPolar(const float *R__ realIn, float *R__ magOut, float *R__ phaseOut) { - - kiss_fftr(m_fplanf, realIn, m_fpacked); - - const int hs = m_size/2; - - for (int i = 0; i <= hs; ++i) { - magOut[i] = sqrtf(m_fpacked[i].r * m_fpacked[i].r + - m_fpacked[i].i * m_fpacked[i].i); - } - - for (int i = 0; i <= hs; ++i) { - phaseOut[i] = atan2f(m_fpacked[i].i, m_fpacked[i].r); - } - } - - void forwardMagnitude(const float *R__ realIn, float *R__ magOut) { - - kiss_fftr(m_fplanf, realIn, m_fpacked); - - const int hs = m_size/2; - - for (int i = 0; i <= hs; ++i) { - magOut[i] = sqrtf(m_fpacked[i].r * m_fpacked[i].r + - m_fpacked[i].i * m_fpacked[i].i); - } - } - - void inverse(const double *R__ realIn, const double *R__ imagIn, double *R__ realOut) { - - packDouble(realIn, imagIn); - - kiss_fftri(m_fplani, m_fpacked, m_fbuf); - - for (int i = 0; i < m_size; ++i) { - realOut[i] = m_fbuf[i]; - } - } - - void inversePolar(const double *R__ magIn, const double *R__ phaseIn, double *R__ realOut) { - - const int hs = m_size/2; - - for (int i = 0; i <= hs; ++i) { - m_fpacked[i].r = float(magIn[i] * cos(phaseIn[i])); - m_fpacked[i].i = float(magIn[i] * sin(phaseIn[i])); - } - - kiss_fftri(m_fplani, m_fpacked, m_fbuf); - - for (int i = 0; i < m_size; ++i) { - realOut[i] = m_fbuf[i]; - } - } - - void inverseCepstral(const double *R__ magIn, double *R__ cepOut) { - - const int hs = m_size/2; - - for (int i = 0; i <= hs; ++i) { - m_fpacked[i].r = float(log(magIn[i] + 0.000001)); - m_fpacked[i].i = 0.0f; - } - - kiss_fftri(m_fplani, m_fpacked, m_fbuf); - - for (int i = 0; i < m_size; ++i) { - cepOut[i] = m_fbuf[i]; - } - } - - void inverse(const float *R__ realIn, const float *R__ imagIn, float *R__ realOut) { - - packFloat(realIn, imagIn); - kiss_fftri(m_fplani, m_fpacked, realOut); - } - - void inversePolar(const float *R__ magIn, const float *R__ phaseIn, float *R__ realOut) { - - const int hs = m_size/2; - - for (int i = 0; i <= hs; ++i) { - m_fpacked[i].r = magIn[i] * cosf(phaseIn[i]); - m_fpacked[i].i = magIn[i] * sinf(phaseIn[i]); - } - - kiss_fftri(m_fplani, m_fpacked, realOut); - } - - void inverseCepstral(const float *R__ magIn, float *R__ cepOut) { - - const int hs = m_size/2; - - for (int i = 0; i <= hs; ++i) { - m_fpacked[i].r = logf(magIn[i] + 0.000001f); - m_fpacked[i].i = 0.0f; - } - - 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: - const int m_size; - float* m_frb; - double* m_drb; - kiss_fftr_cfg m_fplanf; - kiss_fftr_cfg m_fplani; - kiss_fft_scalar *m_fbuf; - kiss_fft_cpx *m_fpacked; -}; - -#endif /* USE_KISSFFT */ - -#ifdef USE_BUILTIN_FFT - -class D_Cross : public FFTImpl -{ -public: - D_Cross(int size) : m_size(size), m_table(0), m_frb(0), m_drb(0) { - - m_a = new double[size]; - m_b = new double[size]; - m_c = new double[size]; - m_d = new double[size]; - - m_table = new int[m_size]; - - int bits; - int i, j, k, m; - - for (i = 0; ; ++i) { - if (m_size & (1 << i)) { - bits = i; - break; - } - } - - for (i = 0; i < m_size; ++i) { - - m = i; - - for (j = k = 0; j < bits; ++j) { - k = (k << 1) | (m & 1); - m >>= 1; - } - - m_table[i] = k; - } - } - - ~D_Cross() { - delete[] m_table; - delete[] m_a; - delete[] m_b; - delete[] m_c; - delete[] m_d; - delete[] m_frb; - delete[] m_drb; - } - - void initFloat() { } - void initDouble() { } - - void forward(const double *R__ realIn, double *R__ realOut, double *R__ imagOut) { - basefft(false, realIn, 0, m_c, m_d); - const int hs = m_size/2; - for (int i = 0; i <= hs; ++i) realOut[i] = m_c[i]; - if (imagOut) { - for (int i = 0; i <= hs; ++i) imagOut[i] = m_d[i]; - } - } - - void forwardPolar(const double *R__ realIn, double *R__ magOut, double *R__ phaseOut) { - basefft(false, realIn, 0, m_c, m_d); - const int hs = m_size/2; - for (int i = 0; i <= hs; ++i) { - magOut[i] = sqrt(m_c[i] * m_c[i] + m_d[i] * m_d[i]); - phaseOut[i] = atan2(m_d[i], m_c[i]) ; - } - } - - void forwardMagnitude(const double *R__ realIn, double *R__ magOut) { - basefft(false, realIn, 0, m_c, m_d); - const int hs = m_size/2; - for (int i = 0; i <= hs; ++i) { - magOut[i] = sqrt(m_c[i] * m_c[i] + m_d[i] * m_d[i]); - } - } - - void forward(const float *R__ realIn, float *R__ realOut, float *R__ imagOut) { - for (int i = 0; i < m_size; ++i) m_a[i] = realIn[i]; - basefft(false, m_a, 0, m_c, m_d); - const int hs = m_size/2; - for (int i = 0; i <= hs; ++i) realOut[i] = m_c[i]; - if (imagOut) { - for (int i = 0; i <= hs; ++i) imagOut[i] = m_d[i]; - } - } - - void forwardPolar(const float *R__ realIn, float *R__ magOut, float *R__ phaseOut) { - for (int i = 0; i < m_size; ++i) m_a[i] = realIn[i]; - basefft(false, m_a, 0, m_c, m_d); - const int hs = m_size/2; - for (int i = 0; i <= hs; ++i) { - magOut[i] = sqrt(m_c[i] * m_c[i] + m_d[i] * m_d[i]); - phaseOut[i] = atan2(m_d[i], m_c[i]) ; - } - } - - void forwardMagnitude(const float *R__ realIn, float *R__ magOut) { - for (int i = 0; i < m_size; ++i) m_a[i] = realIn[i]; - basefft(false, m_a, 0, m_c, m_d); - const int hs = m_size/2; - for (int i = 0; i <= hs; ++i) { - magOut[i] = sqrt(m_c[i] * m_c[i] + m_d[i] * m_d[i]); - } - } - - void inverse(const double *R__ realIn, const double *R__ imagIn, double *R__ realOut) { - const int hs = m_size/2; - for (int i = 0; i <= hs; ++i) { - double real = realIn[i]; - double imag = imagIn[i]; - m_a[i] = real; - m_b[i] = imag; - if (i > 0) { - m_a[m_size-i] = real; - m_b[m_size-i] = -imag; - } - } - basefft(true, m_a, m_b, realOut, m_d); - } - - void inversePolar(const double *R__ magIn, const double *R__ phaseIn, double *R__ realOut) { - const int hs = m_size/2; - for (int i = 0; i <= hs; ++i) { - double real = magIn[i] * cos(phaseIn[i]); - double imag = magIn[i] * sin(phaseIn[i]); - m_a[i] = real; - m_b[i] = imag; - if (i > 0) { - m_a[m_size-i] = real; - m_b[m_size-i] = -imag; - } - } - basefft(true, m_a, m_b, realOut, m_d); - } - - void inverseCepstral(const double *R__ magIn, double *R__ cepOut) { - const int hs = m_size/2; - for (int i = 0; i <= hs; ++i) { - double real = log(magIn[i] + 0.000001); - m_a[i] = real; - m_b[i] = 0.0; - if (i > 0) { - m_a[m_size-i] = real; - m_b[m_size-i] = 0.0; - } - } - basefft(true, m_a, m_b, cepOut, m_d); - } - - void inverse(const float *R__ realIn, const float *R__ imagIn, float *R__ realOut) { - const int hs = m_size/2; - for (int i = 0; i <= hs; ++i) { - float real = realIn[i]; - float imag = imagIn[i]; - m_a[i] = real; - m_b[i] = imag; - if (i > 0) { - m_a[m_size-i] = real; - m_b[m_size-i] = -imag; - } - } - basefft(true, m_a, m_b, m_c, m_d); - for (int i = 0; i < m_size; ++i) realOut[i] = m_c[i]; - } - - void inversePolar(const float *R__ magIn, const float *R__ phaseIn, float *R__ realOut) { - const int hs = m_size/2; - for (int i = 0; i <= hs; ++i) { - float real = magIn[i] * cosf(phaseIn[i]); - float imag = magIn[i] * sinf(phaseIn[i]); - m_a[i] = real; - m_b[i] = imag; - if (i > 0) { - m_a[m_size-i] = real; - m_b[m_size-i] = -imag; - } - } - basefft(true, m_a, m_b, m_c, m_d); - for (int i = 0; i < m_size; ++i) realOut[i] = m_c[i]; - } - - void inverseCepstral(const float *R__ magIn, float *R__ cepOut) { - const int hs = m_size/2; - for (int i = 0; i <= hs; ++i) { - float real = logf(magIn[i] + 0.000001); - m_a[i] = real; - m_b[i] = 0.0; - if (i > 0) { - m_a[m_size-i] = real; - m_b[m_size-i] = 0.0; - } - } - basefft(true, m_a, m_b, m_c, m_d); - 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: - const int m_size; - int *m_table; - float *m_frb; - double *m_drb; - double *m_a; - double *m_b; - double *m_c; - double *m_d; - void basefft(bool inverse, const double *R__ ri, const double *R__ ii, double *R__ ro, double *R__ io); -}; - -void -D_Cross::basefft(bool inverse, const double *R__ ri, const double *R__ ii, double *R__ ro, double *R__ io) -{ - if (!ri || !ro || !io) return; - - int i, j, k, m; - int blockSize, blockEnd; - - double tr, ti; - - double angle = 2.0 * M_PI; - if (inverse) angle = -angle; - - const int n = m_size; - - if (ii) { - for (i = 0; i < n; ++i) { - ro[m_table[i]] = ri[i]; - } - for (i = 0; i < n; ++i) { - io[m_table[i]] = ii[i]; - } - } else { - for (i = 0; i < n; ++i) { - ro[m_table[i]] = ri[i]; - } - for (i = 0; i < n; ++i) { - io[m_table[i]] = 0.0; - } - } - - blockEnd = 1; - - for (blockSize = 2; blockSize <= n; blockSize <<= 1) { - - double delta = angle / (double)blockSize; - double sm2 = -sin(-2 * delta); - double sm1 = -sin(-delta); - double cm2 = cos(-2 * delta); - double cm1 = cos(-delta); - double w = 2 * cm1; - double ar[3], ai[3]; - - for (i = 0; i < n; i += blockSize) { - - ar[2] = cm2; - ar[1] = cm1; - - ai[2] = sm2; - ai[1] = sm1; - - for (j = i, m = 0; m < blockEnd; j++, m++) { - - ar[0] = w * ar[1] - ar[2]; - ar[2] = ar[1]; - ar[1] = ar[0]; - - ai[0] = w * ai[1] - ai[2]; - ai[2] = ai[1]; - ai[1] = ai[0]; - - k = j + blockEnd; - tr = ar[0] * ro[k] - ai[0] * io[k]; - ti = ar[0] * io[k] + ai[0] * ro[k]; - - ro[k] = ro[j] - tr; - io[k] = io[j] - ti; - - ro[j] += tr; - io[j] += ti; - } - } - - blockEnd = blockSize; - } - -/* fftw doesn't rescale, so nor will we - - if (inverse) { - - double denom = (double)n; - - for (i = 0; i < n; i++) { - ro[i] /= denom; - io[i] /= denom; - } - } -*/ -} - -#endif /* USE_BUILTIN_FFT */ - -} /* end namespace FFTs */ - -int -FFT::m_method = -1; - -FFT::FFT(int size, int debugLevel) -{ - if ((size < 2) || - (size & (size-1))) { - std::cerr << "FFT::FFT(" << size << "): power-of-two sizes only supported, minimum size 2" << std::endl; - throw InvalidSize; - } - - if (m_method == -1) { - m_method = 3; -#ifdef USE_KISSFFT - m_method = 2; -#endif -#ifdef HAVE_FFTW3 - m_method = 1; -#endif - } - - switch (m_method) { - - case 0: - std::cerr << "FFT::FFT(" << size << "): WARNING: Selected implementation not available" << std::endl; -#ifdef USE_BUILTIN_FFT - d = new FFTs::D_Cross(size); -#else - std::cerr << "FFT::FFT(" << size << "): ERROR: Fallback implementation not available!" << std::endl; - abort(); -#endif - break; - - case 1: -#ifdef HAVE_FFTW3 - if (debugLevel > 0) { - std::cerr << "FFT::FFT(" << size << "): using FFTW3 implementation" - << std::endl; - } - d = new FFTs::D_FFTW(size); -#else - std::cerr << "FFT::FFT(" << size << "): WARNING: Selected implementation not available" << std::endl; -#ifdef USE_BUILTIN_FFT - d = new FFTs::D_Cross(size); -#else - std::cerr << "FFT::FFT(" << size << "): ERROR: Fallback implementation not available!" << std::endl; - abort(); -#endif -#endif - break; - - case 2: -#ifdef USE_KISSFFT - if (debugLevel > 0) { - std::cerr << "FFT::FFT(" << size << "): using KISSFFT implementation" - << std::endl; - } - d = new FFTs::D_KISSFFT(size); -#else - std::cerr << "FFT::FFT(" << size << "): WARNING: Selected implementation not available" << std::endl; -#ifdef USE_BUILTIN_FFT - d = new FFTs::D_Cross(size); -#else - std::cerr << "FFT::FFT(" << size << "): ERROR: Fallback implementation not available!" << std::endl; - abort(); -#endif -#endif - break; - - default: -#ifdef USE_BUILTIN_FFT - std::cerr << "FFT::FFT(" << size << "): WARNING: using slow built-in implementation" << std::endl; - d = new FFTs::D_Cross(size); -#else - std::cerr << "FFT::FFT(" << size << "): ERROR: Fallback implementation not available!" << std::endl; - abort(); -#endif - break; - } -} - -FFT::~FFT() -{ - delete d; -} - -void -FFT::forward(const double *R__ realIn, double *R__ realOut, double *R__ imagOut) -{ - d->forward(realIn, realOut, imagOut); -} - -void -FFT::forwardPolar(const double *R__ realIn, double *R__ magOut, double *R__ phaseOut) -{ - d->forwardPolar(realIn, magOut, phaseOut); -} - -void -FFT::forwardMagnitude(const double *R__ realIn, double *R__ magOut) -{ - d->forwardMagnitude(realIn, magOut); -} - -void -FFT::forward(const float *R__ realIn, float *R__ realOut, float *R__ imagOut) -{ - d->forward(realIn, realOut, imagOut); -} - -void -FFT::forwardPolar(const float *R__ realIn, float *R__ magOut, float *R__ phaseOut) -{ - d->forwardPolar(realIn, magOut, phaseOut); -} - -void -FFT::forwardMagnitude(const float *R__ realIn, float *R__ magOut) -{ - d->forwardMagnitude(realIn, magOut); -} - -void -FFT::inverse(const double *R__ realIn, const double *R__ imagIn, double *R__ realOut) -{ - d->inverse(realIn, imagIn, realOut); -} - -void -FFT::inversePolar(const double *R__ magIn, const double *R__ phaseIn, double *R__ realOut) -{ - d->inversePolar(magIn, phaseIn, realOut); -} - -void -FFT::inverseCepstral(const double *R__ magIn, double *R__ cepOut) -{ - d->inverseCepstral(magIn, cepOut); -} - -void -FFT::inverse(const float *R__ realIn, const float *R__ imagIn, float *R__ realOut) -{ - d->inverse(realIn, imagIn, realOut); -} - -void -FFT::inversePolar(const float *R__ magIn, const float *R__ phaseIn, float *R__ realOut) -{ - d->inversePolar(magIn, phaseIn, realOut); -} - -void -FFT::inverseCepstral(const float *R__ magIn, float *R__ cepOut) -{ - d->inverseCepstral(magIn, cepOut); -} - -void -FFT::initFloat() -{ - d->initFloat(); -} - -void -FFT::initDouble() -{ - d->initDouble(); -} - -float * -FFT::getFloatTimeBuffer() -{ - return d->getFloatTimeBuffer(); -} - -double * -FFT::getDoubleTimeBuffer() -{ - return d->getDoubleTimeBuffer(); -} - - -void -FFT::tune() -{ -} - - -} diff --git a/libs/rubberband/src/FFT.h b/libs/rubberband/src/FFT.h deleted file mode 100644 index b31d925d36..0000000000 --- a/libs/rubberband/src/FFT.h +++ /dev/null @@ -1,80 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#ifndef _RUBBERBAND_FFT_H_ -#define _RUBBERBAND_FFT_H_ - -#include "sysutils.h" - -namespace RubberBand { - -class FFTImpl; - -/** - * Provide the basic FFT computations we need, using one of a set of - * candidate FFT implementations (depending on compile flags). - * - * Implements real->complex FFTs of power-of-two sizes only. Note - * that only the first half of the output signal is returned (the - * complex conjugates half is omitted), so the "complex" arrays need - * room for size/2+1 elements. - * - * Not thread safe: use a separate instance per thread. - */ - -class FFT -{ -public: - enum Exception { InvalidSize }; - - FFT(int size, int debugLevel = 0); // may throw InvalidSize - ~FFT(); - - void forward(const double *R__ realIn, double *R__ realOut, double *R__ imagOut); - void forwardPolar(const double *R__ realIn, double *R__ magOut, double *R__ phaseOut); - void forwardMagnitude(const double *R__ realIn, double *R__ magOut); - - void forward(const float *R__ realIn, float *R__ realOut, float *R__ imagOut); - void forwardPolar(const float *R__ realIn, float *R__ magOut, float *R__ phaseOut); - void forwardMagnitude(const float *R__ realIn, float *R__ magOut); - - void inverse(const double *R__ realIn, const double *R__ imagIn, double *R__ realOut); - void inversePolar(const double *R__ magIn, const double *R__ phaseIn, double *R__ realOut); - void inverseCepstral(const double *R__ magIn, double *R__ cepOut); - - void inverse(const float *R__ realIn, const float *R__ imagIn, float *R__ realOut); - void inversePolar(const float *R__ magIn, const float *R__ phaseIn, float *R__ realOut); - void inverseCepstral(const float *R__ magIn, float *R__ cepOut); - - // Calling one or both of these is optional -- if neither is - // called, the first call to a forward or inverse method will call - // init(). You only need call these if you don't want to risk - // expensive allocations etc happening in forward or inverse. - void initFloat(); - void initDouble(); - - float *getFloatTimeBuffer(); - double *getDoubleTimeBuffer(); - - static void tune(); - -protected: - FFTImpl *d; - static int m_method; -}; - -} - -#endif - diff --git a/libs/rubberband/src/HighFrequencyAudioCurve.cpp b/libs/rubberband/src/HighFrequencyAudioCurve.cpp deleted file mode 100644 index 2ede70d283..0000000000 --- a/libs/rubberband/src/HighFrequencyAudioCurve.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#include "HighFrequencyAudioCurve.h" - -namespace RubberBand -{ - -HighFrequencyAudioCurve::HighFrequencyAudioCurve(size_t sampleRate, size_t windowSize) : - AudioCurve(sampleRate, windowSize) -{ -} - -HighFrequencyAudioCurve::~HighFrequencyAudioCurve() -{ -} - -void -HighFrequencyAudioCurve::reset() -{ -} - -void -HighFrequencyAudioCurve::setWindowSize(size_t newSize) -{ - m_windowSize = newSize; -} - -float -HighFrequencyAudioCurve::process(const float *R__ mag, size_t /*increment*/) -{ - float result = 0.0; - - const int sz = m_windowSize / 2; - - for (int n = 0; n <= sz; ++n) { - result = result + mag[n] * n; - } - - return result; -} - -float -HighFrequencyAudioCurve::processDouble(const double *R__ mag, size_t /*increment*/) -{ - float result = 0.0; - - const int sz = m_windowSize / 2; - - for (int n = 0; n <= sz; ++n) { - result = result + (float)mag[n] * n; - } - - return result; -} - -} - diff --git a/libs/rubberband/src/HighFrequencyAudioCurve.h b/libs/rubberband/src/HighFrequencyAudioCurve.h deleted file mode 100644 index b0a3ec2db7..0000000000 --- a/libs/rubberband/src/HighFrequencyAudioCurve.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#ifndef _HIGHFREQUENCY_AUDIO_CURVE_H_ -#define _HIGHFREQUENCY_AUDIO_CURVE_H_ - -#include "AudioCurve.h" -#include "Window.h" - -namespace RubberBand -{ - -class HighFrequencyAudioCurve : public AudioCurve -{ -public: - HighFrequencyAudioCurve(size_t sampleRate, size_t windowSize); - - virtual ~HighFrequencyAudioCurve(); - - virtual void setWindowSize(size_t newSize); - - virtual float process(const float *R__ mag, size_t increment); - virtual float processDouble(const double *R__ mag, size_t increment); - virtual void reset(); -}; - -} - -#endif diff --git a/libs/rubberband/src/PercussiveAudioCurve.cpp b/libs/rubberband/src/PercussiveAudioCurve.cpp deleted file mode 100644 index aced9e08c2..0000000000 --- a/libs/rubberband/src/PercussiveAudioCurve.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#include "PercussiveAudioCurve.h" - -#include "Profiler.h" - -#include <cmath> - - -namespace RubberBand -{ - -PercussiveAudioCurve::PercussiveAudioCurve(size_t sampleRate, size_t windowSize) : - AudioCurve(sampleRate, windowSize) -{ - m_prevMag = new float[m_windowSize/2 + 1]; - - for (size_t i = 0; i <= m_windowSize/2; ++i) { - m_prevMag[i] = 0.f; - } -} - -PercussiveAudioCurve::~PercussiveAudioCurve() -{ - delete[] m_prevMag; -} - -void -PercussiveAudioCurve::reset() -{ - for (size_t i = 0; i <= m_windowSize/2; ++i) { - m_prevMag[i] = 0; - } -} - -void -PercussiveAudioCurve::setWindowSize(size_t newSize) -{ - m_windowSize = newSize; - - delete[] m_prevMag; - m_prevMag = new float[m_windowSize/2 + 1]; - - reset(); -} - -float -PercussiveAudioCurve::process(const float *R__ mag, size_t /*increment*/) -{ - static float threshold = powf(10.f, 0.15f); // 3dB rise in square of magnitude - static float zeroThresh = powf(10.f, -8); - - size_t count = 0; - size_t nonZeroCount = 0; - - const int sz = m_windowSize / 2; - - for (int n = 1; n <= sz; ++n) { - bool above = ((mag[n] / m_prevMag[n]) >= threshold); - if (above) ++count; - if (mag[n] > zeroThresh) ++nonZeroCount; - } - - for (int n = 1; n <= sz; ++n) { - m_prevMag[n] = mag[n]; - } - - if (nonZeroCount == 0) return 0; - else return float(count) / float(nonZeroCount); -} - -float -PercussiveAudioCurve::processDouble(const double *R__ mag, size_t /*increment*/) -{ - Profiler profiler("PercussiveAudioCurve::process"); - - static double threshold = pow(10.0, 0.15); // 3dB rise in square of magnitude - static double zeroThresh = pow(10.0, -8); - - size_t count = 0; - size_t nonZeroCount = 0; - - const int sz = m_windowSize / 2; - - for (int n = 1; n <= sz; ++n) { - bool above = ((mag[n] / m_prevMag[n]) >= threshold); - if (above) ++count; - if (mag[n] > zeroThresh) ++nonZeroCount; - } - - for (int n = 1; n <= sz; ++n) { - m_prevMag[n] = mag[n]; - } - - if (nonZeroCount == 0) return 0; - else return float(count) / float(nonZeroCount); -} - -} - diff --git a/libs/rubberband/src/PercussiveAudioCurve.h b/libs/rubberband/src/PercussiveAudioCurve.h deleted file mode 100644 index 9f087053a4..0000000000 --- a/libs/rubberband/src/PercussiveAudioCurve.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#ifndef _PERCUSSIVE_AUDIO_CURVE_H_ -#define _PERCUSSIVE_AUDIO_CURVE_H_ - -#include "AudioCurve.h" - -namespace RubberBand -{ - -class PercussiveAudioCurve : public AudioCurve -{ -public: - PercussiveAudioCurve(size_t sampleRate, size_t windowSize); - - virtual ~PercussiveAudioCurve(); - - virtual void setWindowSize(size_t newSize); - - virtual float process(const float *R__ mag, size_t increment); - virtual float processDouble(const double *R__ mag, size_t increment); - virtual void reset(); - -protected: - float *R__ m_prevMag; -}; - -} - -#endif diff --git a/libs/rubberband/src/Profiler.cpp b/libs/rubberband/src/Profiler.cpp deleted file mode 100644 index df148d48e3..0000000000 --- a/libs/rubberband/src/Profiler.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#include "Profiler.h" - -#include <algorithm> -#include <set> -#include <string> -#include <map> - -#include <cstdio> - -namespace RubberBand { - -#ifndef NO_TIMING - -Profiler::ProfileMap -Profiler::m_profiles; - -Profiler::WorstCallMap -Profiler::m_worstCalls; - -void -Profiler::add(const char *id, float ms) -{ - ProfileMap::iterator pmi = m_profiles.find(id); - if (pmi != m_profiles.end()) { - ++pmi->second.first; - pmi->second.second += ms; - } else { - m_profiles[id] = TimePair(1, ms); - } - - WorstCallMap::iterator wci = m_worstCalls.find(id); - if (wci != m_worstCalls.end()) { - if (ms > wci->second) wci->second = ms; - } else { - m_worstCalls[id] = ms; - } -} - -void -Profiler::dump() -{ -#ifdef PROFILE_CLOCKS - fprintf(stderr, "Profiling points [CPU time]:\n"); -#else - fprintf(stderr, "Profiling points [Wall time]:\n"); -#endif - - fprintf(stderr, "\nBy name:\n"); - - typedef std::set<const char *, std::less<std::string> > StringSet; - - StringSet profileNames; - for (ProfileMap::const_iterator i = m_profiles.begin(); - i != m_profiles.end(); ++i) { - profileNames.insert(i->first); - } - - for (StringSet::const_iterator i = profileNames.begin(); - i != profileNames.end(); ++i) { - - ProfileMap::const_iterator j = m_profiles.find(*i); - if (j == m_profiles.end()) continue; - - const TimePair &pp(j->second); - fprintf(stderr, "%s(%d):\n", *i, pp.first); - fprintf(stderr, "\tReal: \t%f ms \t[%f ms total]\n", - (pp.second / pp.first), - (pp.second)); - - WorstCallMap::const_iterator k = m_worstCalls.find(*i); - if (k == m_worstCalls.end()) continue; - - fprintf(stderr, "\tWorst:\t%f ms/call\n", k->second); - } - - typedef std::multimap<float, const char *> TimeRMap; - typedef std::multimap<int, const char *> IntRMap; - TimeRMap totmap, avgmap, worstmap; - IntRMap ncallmap; - - for (ProfileMap::const_iterator i = m_profiles.begin(); - i != m_profiles.end(); ++i) { - totmap.insert(TimeRMap::value_type(i->second.second, i->first)); - avgmap.insert(TimeRMap::value_type(i->second.second / - i->second.first, i->first)); - ncallmap.insert(IntRMap::value_type(i->second.first, i->first)); - } - - for (WorstCallMap::const_iterator i = m_worstCalls.begin(); - i != m_worstCalls.end(); ++i) { - worstmap.insert(TimeRMap::value_type(i->second, i->first)); - } - - fprintf(stderr, "\nBy total:\n"); - for (TimeRMap::const_iterator i = totmap.end(); i != totmap.begin(); ) { - --i; - fprintf(stderr, "%-40s %f ms\n", i->second, i->first); - } - - fprintf(stderr, "\nBy average:\n"); - for (TimeRMap::const_iterator i = avgmap.end(); i != avgmap.begin(); ) { - --i; - fprintf(stderr, "%-40s %f ms\n", i->second, i->first); - } - - fprintf(stderr, "\nBy worst case:\n"); - for (TimeRMap::const_iterator i = worstmap.end(); i != worstmap.begin(); ) { - --i; - fprintf(stderr, "%-40s %f ms\n", i->second, i->first); - } - - fprintf(stderr, "\nBy number of calls:\n"); - for (IntRMap::const_iterator i = ncallmap.end(); i != ncallmap.begin(); ) { - --i; - fprintf(stderr, "%-40s %d\n", i->second, i->first); - } -} - -Profiler::Profiler(const char* c) : - m_c(c), - m_ended(false) -{ -#ifdef PROFILE_CLOCKS - m_start = clock(); -#else - (void)gettimeofday(&m_start, 0); -#endif -} - -Profiler::~Profiler() -{ - if (!m_ended) end(); -} - -void -Profiler::end() -{ -#ifdef PROFILE_CLOCKS - clock_t end = clock(); - clock_t elapsed = end - m_start; - float ms = float((double(elapsed) / double(CLOCKS_PER_SEC)) * 1000.0); -#else - struct timeval tv; - (void)gettimeofday(&tv, 0); - - tv.tv_sec -= m_start.tv_sec; - if (tv.tv_usec < m_start.tv_usec) { - tv.tv_usec += 1000000; - tv.tv_sec -= 1; - } - tv.tv_usec -= m_start.tv_usec; - float ms = float((double(tv.tv_sec) + (double(tv.tv_usec) / 1000000.0)) * 1000.0); -#endif - - add(m_c, ms); - - m_ended = true; -} - -#endif - -} diff --git a/libs/rubberband/src/Profiler.h b/libs/rubberband/src/Profiler.h deleted file mode 100644 index 616a553ecb..0000000000 --- a/libs/rubberband/src/Profiler.h +++ /dev/null @@ -1,91 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#ifndef _PROFILER_H_ -#define _PROFILER_H_ - -#define NO_TIMING 1 - -//#define WANT_TIMING 1 -//#define PROFILE_CLOCKS 1 - -#ifdef NDEBUG -#ifndef WANT_TIMING -#define NO_TIMING 1 -#endif -#endif - -#ifndef NO_TIMING -#ifdef PROFILE_CLOCKS -#include <time.h> -#else -#include "sysutils.h" -#ifndef _WIN32 -#include <sys/time.h> -#endif -#endif -#endif - -#include <map> - -namespace RubberBand { - -#ifndef NO_TIMING - -class Profiler -{ -public: - Profiler(const char *name); - ~Profiler(); - - void end(); // same action as dtor - - static void dump(); - -protected: - const char* m_c; -#ifdef PROFILE_CLOCKS - clock_t m_start; -#else - struct timeval m_start; -#endif - bool m_showOnDestruct; - bool m_ended; - - typedef std::pair<int, float> TimePair; - typedef std::map<const char *, TimePair> ProfileMap; - typedef std::map<const char *, float> WorstCallMap; - static ProfileMap m_profiles; - static WorstCallMap m_worstCalls; - static void add(const char *, float); -}; - -#else - -class Profiler -{ -public: - Profiler(const char *) { } - ~Profiler() { } - - void update() const { } - void end() { } - static void dump() { } -}; - -#endif - -} - -#endif diff --git a/libs/rubberband/src/Resampler.cpp b/libs/rubberband/src/Resampler.cpp deleted file mode 100644 index 1e479363b5..0000000000 --- a/libs/rubberband/src/Resampler.cpp +++ /dev/null @@ -1,261 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#include "Resampler.h" - -#include "Profiler.h" - -#include <cstdlib> -#include <cmath> - -#include <iostream> - - -#include <samplerate.h> - - - -namespace RubberBand { - -class ResamplerImpl -{ -public: - virtual ~ResamplerImpl() { } - - virtual int resample(const float *const R__ *const R__ in, - float *const R__ *const R__ out, - int incount, - float ratio, - bool final) = 0; - - virtual void reset() = 0; -}; - -namespace Resamplers { - - - -class D_SRC : public ResamplerImpl -{ -public: - D_SRC(Resampler::Quality quality, int channels, int maxBufferSize, - int m_debugLevel); - ~D_SRC(); - - int resample(const float *const R__ *const R__ in, - float *const R__ *const R__ out, - int incount, - float ratio, - bool final); - - void reset(); - -protected: - SRC_STATE *m_src; - float *m_iin; - float *m_iout; - float m_lastRatio; - int m_channels; - int m_iinsize; - int m_ioutsize; - int m_debugLevel; -}; - -D_SRC::D_SRC(Resampler::Quality quality, int channels, int maxBufferSize, - int debugLevel) : - m_src(0), - m_iin(0), - m_iout(0), - m_lastRatio(1.f), - m_channels(channels), - m_iinsize(0), - m_ioutsize(0), - m_debugLevel(debugLevel) -{ - if (m_debugLevel > 0) { - std::cerr << "Resampler::Resampler: using libsamplerate implementation" - << std::endl; - } - - int err = 0; - m_src = src_new(quality == Resampler::Best ? SRC_SINC_BEST_QUALITY : - quality == Resampler::Fastest ? SRC_LINEAR : - SRC_SINC_FASTEST, - channels, &err); - - if (err) { - std::cerr << "Resampler::Resampler: failed to create libsamplerate resampler: " - << src_strerror(err) << std::endl; - throw Resampler::ImplementationError; //!!! of course, need to catch this! - } - - if (maxBufferSize > 0 && m_channels > 1) { - m_iinsize = maxBufferSize * m_channels; - m_ioutsize = maxBufferSize * m_channels * 2; - m_iin = allocFloat(m_iinsize); - m_iout = allocFloat(m_ioutsize); - } - - reset(); -} - -D_SRC::~D_SRC() -{ - src_delete(m_src); - if (m_iinsize > 0) { - free(m_iin); - } - if (m_ioutsize > 0) { - free(m_iout); - } -} - -int -D_SRC::resample(const float *const R__ *const R__ in, - float *const R__ *const R__ out, - int incount, - float ratio, - bool final) -{ - SRC_DATA data; - - int outcount = lrintf(ceilf(incount * ratio)); - - if (m_channels == 1) { - data.data_in = const_cast<float *>(*in); //!!!??? - data.data_out = *out; - } else { - if (incount * m_channels > m_iinsize) { - m_iinsize = incount * m_channels; - m_iin = allocFloat(m_iin, m_iinsize); - } - if (outcount * m_channels > m_ioutsize) { - m_ioutsize = outcount * m_channels; - m_iout = allocFloat(m_iout, m_ioutsize); - } - for (int i = 0; i < incount; ++i) { - for (int c = 0; c < m_channels; ++c) { - m_iin[i * m_channels + c] = in[c][i]; - } - } - data.data_in = m_iin; - data.data_out = m_iout; - } - - data.input_frames = incount; - data.output_frames = outcount; - data.src_ratio = ratio; - data.end_of_input = (final ? 1 : 0); - - int err = 0; - err = src_process(m_src, &data); - - if (err) { - std::cerr << "Resampler::process: libsamplerate error: " - << src_strerror(err) << std::endl; - throw Resampler::ImplementationError; //!!! of course, need to catch this! - } - - if (m_channels > 1) { - for (int i = 0; i < data.output_frames_gen; ++i) { - for (int c = 0; c < m_channels; ++c) { - out[c][i] = m_iout[i * m_channels + c]; - } - } - } - - m_lastRatio = ratio; - - return data.output_frames_gen; -} - -void -D_SRC::reset() -{ - src_reset(m_src); -} - - - -} /* end namespace Resamplers */ - -Resampler::Resampler(Resampler::Quality quality, int channels, - int maxBufferSize, int debugLevel) -{ - m_method = -1; - - switch (quality) { - - case Resampler::Best: - m_method = 1; - break; - - case Resampler::FastestTolerable: - m_method = 1; - break; - - case Resampler::Fastest: - m_method = 1; - break; - } - - if (m_method == -1) { - std::cerr << "Resampler::Resampler(" << quality << ", " << channels - << ", " << maxBufferSize << "): No implementation available!" - << std::endl; - abort(); - } - - switch (m_method) { - case 0: - std::cerr << "Resampler::Resampler(" << quality << ", " << channels - << ", " << maxBufferSize << "): No implementation available!" - << std::endl; - abort(); - break; - - case 1: - d = new Resamplers::D_SRC(quality, channels, maxBufferSize, debugLevel); - break; - - case 2: - std::cerr << "Resampler::Resampler(" << quality << ", " << channels - << ", " << maxBufferSize << "): No implementation available!" - << std::endl; - abort(); - break; - } -} - -Resampler::~Resampler() -{ - delete d; -} - -int -Resampler::resample(const float *const R__ *const R__ in, - float *const R__ *const R__ out, - int incount, float ratio, bool final) -{ - Profiler profiler("Resampler::resample"); - return d->resample(in, out, incount, ratio, final); -} - -void -Resampler::reset() -{ - d->reset(); -} - -} diff --git a/libs/rubberband/src/Resampler.h b/libs/rubberband/src/Resampler.h deleted file mode 100644 index 3c4af40e8e..0000000000 --- a/libs/rubberband/src/Resampler.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#ifndef _RUBBERBAND_RESAMPLER_H_ -#define _RUBBERBAND_RESAMPLER_H_ - -#include <sys/types.h> - -#include "sysutils.h" - -namespace RubberBand { - -class ResamplerImpl; - -class Resampler -{ -public: - enum Quality { Best, FastestTolerable, Fastest }; - enum Exception { ImplementationError }; - - /** - * Construct a resampler with the given quality level and channel - * count. maxBufferSize gives a bound on the maximum incount size - * that may be passed to the resample function before the - * resampler needs to reallocate its internal buffers. - */ - Resampler(Quality quality, int channels, int maxBufferSize = 0, - int debugLevel = 0); - ~Resampler(); - - int resample(const float *const R__ *const R__ in, - float *const R__ *const R__ out, - int incount, - float ratio, - bool final = false); - - void reset(); - -protected: - ResamplerImpl *d; - int m_method; -}; - -} - -#endif diff --git a/libs/rubberband/src/RingBuffer.h b/libs/rubberband/src/RingBuffer.h deleted file mode 100644 index 07312169a6..0000000000 --- a/libs/rubberband/src/RingBuffer.h +++ /dev/null @@ -1,670 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#ifndef _RUBBERBAND_RINGBUFFER_H_ -#define _RUBBERBAND_RINGBUFFER_H_ - -#include <cstring> -#include <sys/types.h> - -#include <cstring> - -#ifndef _WIN32 -#include <sys/mman.h> -#endif - -#include "Scavenger.h" -#include "Profiler.h" - - -//#define DEBUG_RINGBUFFER 1 - -#ifdef _WIN32 -#define MLOCK(a,b) 1 -#define MUNLOCK(a,b) 1 -#else -#define MLOCK(a,b) ::mlock(a,b) -#define MUNLOCK(a,b) ::munlock(a,b) -#endif - -#ifdef DEBUG_RINGBUFFER -#include <iostream> -#endif - -namespace RubberBand { - -/** - * RingBuffer implements a lock-free ring buffer for one writer and N - * readers, that is to be used to store a sample type T. - */ - -template <typename T, int N = 1> -class RingBuffer -{ -public: - /** - * Create a ring buffer with room to write n samples. - * - * Note that the internal storage size will actually be n+1 - * samples, as one element is unavailable for administrative - * reasons. Since the ring buffer performs best if its size is a - * power of two, this means n should ideally be some power of two - * minus one. - */ - RingBuffer(int n); - - virtual ~RingBuffer(); - - /** - * Return the total capacity of the ring buffer in samples. - * (This is the argument n passed to the constructor.) - */ - int getSize() const; - - /** - * Resize the ring buffer. This also empties it; use resized() - * below if you do not want this to happen. Actually swaps in a - * new, larger buffer; the old buffer is scavenged after a seemly - * delay. Should be called from the write thread. - */ - void resize(int newSize); - - /** - * Return a new ring buffer (allocated with "new" -- called must - * delete when no longer needed) of the given size, containing the - * same data as this one. If another thread reads from or writes - * to this buffer during the call, the results may be incomplete - * or inconsistent. If this buffer's data will not fit in the new - * size, the contents are undefined. - */ - RingBuffer<T, N> *resized(int newSize, int R = 0) const; - - /** - * Lock the ring buffer into physical memory. Returns true - * for success. - */ - bool mlock(); - - /** - * Reset read and write pointers, thus emptying the buffer. - * Should be called from the write thread. - */ - void reset(); - - /** - * Return the amount of data available for reading by reader R, in - * samples. - */ - int getReadSpace(int R = 0) const; - - /** - * Return the amount of space available for writing, in samples. - */ - int getWriteSpace() const; - - /** - * Read n samples from the buffer, for reader R. If fewer than n - * are available, the remainder will be zeroed out. Returns the - * number of samples actually read. - */ - int read(T *R__ destination, int n, int R = 0); - - /** - * Read n samples from the buffer, for reader R, adding them to - * the destination. If fewer than n are available, the remainder - * will be left alone. Returns the number of samples actually - * read. - */ - int readAdding(T *R__ destination, int n, int R = 0); - - /** - * Read one sample from the buffer, for reader R. If no sample is - * available, this will silently return zero. Calling this - * repeatedly is obviously slower than calling read once, but it - * may be good enough if you don't want to allocate a buffer to - * read into. - */ - T readOne(int R = 0); - - /** - * Read n samples from the buffer, if available, for reader R, - * without advancing the read pointer -- i.e. a subsequent read() - * or skip() will be necessary to empty the buffer. If fewer than - * n are available, the remainder will be zeroed out. Returns the - * number of samples actually read. - */ - int peek(T *R__ destination, int n, int R = 0) const; - - /** - * Read one sample from the buffer, if available, without - * advancing the read pointer -- i.e. a subsequent read() or - * skip() will be necessary to empty the buffer. Returns zero if - * no sample was available. - */ - T peekOne(int R = 0) const; - - /** - * Pretend to read n samples from the buffer, for reader R, - * without actually returning them (i.e. discard the next n - * samples). Returns the number of samples actually available for - * discarding. - */ - int skip(int n, int R = 0); - - /** - * Write n samples to the buffer. If insufficient space is - * available, not all samples may actually be written. Returns - * the number of samples actually written. - */ - int write(const T *source, int n); - - /** - * Write n zero-value samples to the buffer. If insufficient - * space is available, not all zeros may actually be written. - * Returns the number of zeroes actually written. - */ - int zero(int n); - -protected: - T *R__ m_buffer; - volatile int m_writer; - volatile int m_readers[N]; - int m_size; - bool m_mlocked; - - static Scavenger<ScavengerArrayWrapper<T> > m_scavenger; - -private: - RingBuffer(const RingBuffer &); // not provided - RingBuffer &operator=(const RingBuffer &); // not provided -}; - -template <typename T, int N> -Scavenger<ScavengerArrayWrapper<T> > RingBuffer<T, N>::m_scavenger; - -template <typename T, int N> -RingBuffer<T, N>::RingBuffer(int n) : - m_buffer(new T[n + 1]), - m_writer(0), - m_size(n + 1), - m_mlocked(false) -{ -#ifdef DEBUG_RINGBUFFER - std::cerr << "RingBuffer<T," << N << ">[" << this << "]::RingBuffer(" << n << ")" << std::endl; -#endif - - for (int i = 0; i < N; ++i) m_readers[i] = 0; - - m_scavenger.scavenge(); -} - -template <typename T, int N> -RingBuffer<T, N>::~RingBuffer() -{ -#ifdef DEBUG_RINGBUFFER - std::cerr << "RingBuffer<T," << N << ">[" << this << "]::~RingBuffer" << std::endl; -#endif - - if (m_mlocked) { - MUNLOCK((void *)m_buffer, m_size * sizeof(T)); - } - delete[] m_buffer; - - m_scavenger.scavenge(); -} - -template <typename T, int N> -int -RingBuffer<T, N>::getSize() const -{ -#ifdef DEBUG_RINGBUFFER - std::cerr << "RingBuffer<T," << N << ">[" << this << "]::getSize(): " << m_size-1 << std::endl; -#endif - - return m_size - 1; -} - -template <typename T, int N> -void -RingBuffer<T, N>::resize(int newSize) -{ -#ifdef DEBUG_RINGBUFFER - std::cerr << "RingBuffer<T," << N << ">[" << this << "]::resize(" << newSize << ")" << std::endl; -#endif - - m_scavenger.scavenge(); - - if (m_mlocked) { - MUNLOCK((void *)m_buffer, m_size * sizeof(T)); - } - - m_scavenger.claim(new ScavengerArrayWrapper<T>(m_buffer)); - - reset(); - m_buffer = new T[newSize + 1]; - m_size = newSize + 1; - - if (m_mlocked) { - if (MLOCK((void *)m_buffer, m_size * sizeof(T))) { - m_mlocked = false; - } - } -} - -template <typename T, int N> -RingBuffer<T, N> * -RingBuffer<T, N>::resized(int newSize, int R) const -{ - RingBuffer<T, N> *newBuffer = new RingBuffer<T, N>(newSize); - - int w = m_writer; - int r = m_readers[R]; - - while (r != w) { - T value = m_buffer[r]; - newBuffer->write(&value, 1); - if (++r == m_size) r = 0; - } - - return newBuffer; -} - -template <typename T, int N> -bool -RingBuffer<T, N>::mlock() -{ - if (MLOCK((void *)m_buffer, m_size * sizeof(T))) return false; - m_mlocked = true; - return true; -} - -template <typename T, int N> -void -RingBuffer<T, N>::reset() -{ -#ifdef DEBUG_RINGBUFFER - std::cerr << "RingBuffer<T," << N << ">[" << this << "]::reset" << std::endl; -#endif - - m_writer = 0; - for (int i = 0; i < N; ++i) m_readers[i] = 0; -} - -template <typename T, int N> -int -RingBuffer<T, N>::getReadSpace(int R) const -{ - int writer = m_writer; - int reader = m_readers[R]; - int space; - -#ifdef DEBUG_RINGBUFFER - std::cerr << "RingBuffer<T," << N << ">[" << this << "]::getReadSpace(" << R << "): reader " << reader << ", writer " << writer << std::endl; -#endif - - if (writer > reader) space = writer - reader; - else if (writer < reader) space = (writer + m_size) - reader; - else space = 0; - -#ifdef DEBUG_RINGBUFFER - std::cerr << "RingBuffer<T," << N << ">[" << this << "]::getReadSpace(" << R << "): " << space << std::endl; -#endif - - return space; -} - -template <typename T, int N> -int -RingBuffer<T, N>::getWriteSpace() const -{ - int space = 0; - for (int i = 0; i < N; ++i) { - int writer = m_writer; - int reader = m_readers[i]; - int here = (reader + m_size - writer - 1); - if (here >= m_size) here -= m_size; - if (i == 0 || here < space) space = here; - } - -#ifdef DEBUG_RINGBUFFER - int rs(getReadSpace()), rp(m_readers[0]); - - std::cerr << "RingBuffer: write space " << space << ", read space " - << rs << ", total " << (space + rs) << ", m_size " << m_size << std::endl; - std::cerr << "RingBuffer: reader " << rp << ", writer " << m_writer << std::endl; -#endif - -#ifdef DEBUG_RINGBUFFER - std::cerr << "RingBuffer<T," << N << ">[" << this << "]::getWriteSpace(): " << space << std::endl; -#endif - - return space; -} - -template <typename T, int N> -int -RingBuffer<T, N>::read(T *R__ destination, int n, int R) -{ - Profiler profiler("RingBuffer::read"); - -#ifdef DEBUG_RINGBUFFER - std::cerr << "RingBuffer<T," << N << ">[" << this << "]::read(dest, " << n << ", " << R << ")" << std::endl; -#endif - - int available = getReadSpace(R); - if (n > available) { -#ifdef DEBUG_RINGBUFFER - std::cerr << "WARNING: Only " << available << " samples available" - << std::endl; -#endif - for (int i = available; i < n; ++i) { - destination[i] = 0; - } - n = available; - } - if (n == 0) return n; - - int reader = m_readers[R]; - int here = m_size - reader; - T *const R__ bufbase = m_buffer + reader; - - if (here >= n) { - for (int i = 0; i < n; ++i) { - destination[i] = bufbase[i]; - } - } else { - for (int i = 0; i < here; ++i) { - destination[i] = bufbase[i]; - } - T *const R__ destbase = destination + here; - const int nh = n - here; - for (int i = 0; i < nh; ++i) { - destbase[i] = m_buffer[i]; - } - } - - reader += n; - while (reader >= m_size) reader -= m_size; - m_readers[R] = reader; - -#ifdef DEBUG_RINGBUFFER - std::cerr << "RingBuffer<T," << N << ">[" << this << "]::read: read " << n << ", reader now " << m_readers[R] << std::endl; -#endif - - return n; -} - -template <typename T, int N> -int -RingBuffer<T, N>::readAdding(T *R__ destination, int n, int R) -{ - Profiler profiler("RingBuffer::readAdding"); - -#ifdef DEBUG_RINGBUFFER - std::cerr << "RingBuffer<T," << N << ">[" << this << "]::readAdding(dest, " << n << ", " << R << ")" << std::endl; -#endif - - int available = getReadSpace(R); - if (n > available) { -#ifdef DEBUG_RINGBUFFER - std::cerr << "WARNING: Only " << available << " samples available" - << std::endl; -#endif - n = available; - } - if (n == 0) return n; - - int reader = m_readers[R]; - int here = m_size - reader; - const T *const R__ bufbase = m_buffer + reader; - - if (here >= n) { - for (int i = 0; i < n; ++i) { - destination[i] += bufbase[i]; - } - } else { - for (int i = 0; i < here; ++i) { - destination[i] += bufbase[i]; - } - T *const R__ destbase = destination + here; - const int nh = n - here; - for (int i = 0; i < nh; ++i) { - destbase[i] += m_buffer[i]; - } - } - - reader += n; - while (reader >= m_size) reader -= m_size; - m_readers[R] = reader; - return n; -} - -template <typename T, int N> -T -RingBuffer<T, N>::readOne(int R) -{ -#ifdef DEBUG_RINGBUFFER - std::cerr << "RingBuffer<T," << N << ">[" << this << "]::readOne(" << R << ")" << std::endl; -#endif - - if (m_writer == m_readers[R]) { -#ifdef DEBUG_RINGBUFFER - std::cerr << "WARNING: No sample available" - << std::endl; -#endif - return 0; - } - int reader = m_readers[R]; - T value = m_buffer[reader]; - if (++reader == m_size) reader = 0; - m_readers[R] = reader; - return value; -} - -template <typename T, int N> -int -RingBuffer<T, N>::peek(T *R__ destination, int n, int R) const -{ - Profiler profiler("RingBuffer::peek"); - -#ifdef DEBUG_RINGBUFFER - std::cerr << "RingBuffer<T," << N << ">[" << this << "]::peek(dest, " << n << ", " << R << ")" << std::endl; -#endif - - int available = getReadSpace(R); - if (n > available) { -#ifdef DEBUG_RINGBUFFER - std::cerr << "WARNING: Only " << available << " samples available" - << std::endl; -#endif - memset(destination + available, 0, (n - available) * sizeof(T)); - n = available; - } - if (n == 0) return n; - - int reader = m_readers[R]; - int here = m_size - reader; - const T *const R__ bufbase = m_buffer + reader; - - if (here >= n) { - for (int i = 0; i < n; ++i) { - destination[i] = bufbase[i]; - } - } else { - for (int i = 0; i < here; ++i) { - destination[i] = bufbase[i]; - } - T *const R__ destbase = destination + here; - const int nh = n - here; - for (int i = 0; i < nh; ++i) { - destbase[i] = m_buffer[i]; - } - } - -#ifdef DEBUG_RINGBUFFER - std::cerr << "RingBuffer<T," << N << ">[" << this << "]::peek: read " << n << std::endl; -#endif - - return n; -} - -template <typename T, int N> -T -RingBuffer<T, N>::peekOne(int R) const -{ -#ifdef DEBUG_RINGBUFFER - std::cerr << "RingBuffer<T," << N << ">[" << this << "]::peek(" << R << ")" << std::endl; -#endif - - if (m_writer == m_readers[R]) { -#ifdef DEBUG_RINGBUFFER - std::cerr << "WARNING: No sample available" - << std::endl; -#endif - return 0; - } - T value = m_buffer[m_readers[R]]; - return value; -} - -template <typename T, int N> -int -RingBuffer<T, N>::skip(int n, int R) -{ -#ifdef DEBUG_RINGBUFFER - std::cerr << "RingBuffer<T," << N << ">[" << this << "]::skip(" << n << ", " << R << ")" << std::endl; -#endif - - int available = getReadSpace(R); - if (n > available) { -#ifdef DEBUG_RINGBUFFER - std::cerr << "WARNING: Only " << available << " samples available" - << std::endl; -#endif - n = available; - } - if (n == 0) return n; - - int reader = m_readers[R]; - reader += n; - while (reader >= m_size) reader -= m_size; - m_readers[R] = reader; - return n; -} - -template <typename T, int N> -int -RingBuffer<T, N>::write(const T *source, int n) -{ - Profiler profiler("RingBuffer::write"); - -#ifdef DEBUG_RINGBUFFER - std::cerr << "RingBuffer<T," << N << ">[" << this << "]::write(" << n << ")" << std::endl; -#endif - - int available = getWriteSpace(); - if (n > available) { -#ifdef DEBUG_RINGBUFFER - std::cerr << "WARNING: Only room for " << available << " samples" - << std::endl; -#endif - n = available; - } - if (n == 0) return n; - - int writer = m_writer; - int here = m_size - writer; - T *const R__ bufbase = m_buffer + writer; - - if (here >= n) { - for (int i = 0; i < n; ++i) { - bufbase[i] = source[i]; - } - } else { - for (int i = 0; i < here; ++i) { - bufbase[i] = source[i]; - } - const int nh = n - here; - const T *const R__ srcbase = source + here; - T *const R__ buf = m_buffer; - for (int i = 0; i < nh; ++i) { - buf[i] = srcbase[i]; - } - } - - writer += n; - while (writer >= m_size) writer -= m_size; - m_writer = writer; - -#ifdef DEBUG_RINGBUFFER - std::cerr << "RingBuffer<T," << N << ">[" << this << "]::write: wrote " << n << ", writer now " << m_writer << std::endl; -#endif - - return n; -} - -template <typename T, int N> -int -RingBuffer<T, N>::zero(int n) -{ - Profiler profiler("RingBuffer::zero"); - -#ifdef DEBUG_RINGBUFFER - std::cerr << "RingBuffer<T," << N << ">[" << this << "]::zero(" << n << ")" << std::endl; -#endif - - int available = getWriteSpace(); - if (n > available) { -#ifdef DEBUG_RINGBUFFER - std::cerr << "WARNING: Only room for " << available << " samples" - << std::endl; -#endif - n = available; - } - if (n == 0) return n; - - int writer = m_writer; - int here = m_size - writer; - T *const R__ bufbase = m_buffer + writer; - - if (here >= n) { - for (int i = 0; i < n; ++i) { - bufbase[i] = 0; - } - } else { - for (int i = 0; i < here; ++i) { - bufbase[i] = 0; - } - const int nh = n - here; - for (int i = 0; i < nh; ++i) { - m_buffer[i] = 0; - } - } - - writer += n; - while (writer >= m_size) writer -= m_size; - m_writer = writer; - -#ifdef DEBUG_RINGBUFFER - std::cerr << "writer -> " << m_writer << std::endl; -#endif - - return n; -} - -} - -//#include "RingBuffer.cpp" - -#endif // _RINGBUFFER_H_ diff --git a/libs/rubberband/src/RubberBandStretcher.cpp b/libs/rubberband/src/RubberBandStretcher.cpp deleted file mode 100644 index 7e249c6633..0000000000 --- a/libs/rubberband/src/RubberBandStretcher.cpp +++ /dev/null @@ -1,200 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#include "StretcherImpl.h" - -namespace RubberBand { - - -RubberBandStretcher::RubberBandStretcher(size_t sampleRate, - size_t channels, - Options options, - double initialTimeRatio, - double initialPitchScale) : - m_d(new Impl(sampleRate, channels, options, - initialTimeRatio, initialPitchScale)) -{ -} - -RubberBandStretcher::~RubberBandStretcher() -{ - delete m_d; -} - -void -RubberBandStretcher::reset() -{ - m_d->reset(); -} - -void -RubberBandStretcher::setTimeRatio(double ratio) -{ - m_d->setTimeRatio(ratio); -} - -void -RubberBandStretcher::setPitchScale(double scale) -{ - m_d->setPitchScale(scale); -} - -double -RubberBandStretcher::getTimeRatio() const -{ - return m_d->getTimeRatio(); -} - -double -RubberBandStretcher::getPitchScale() const -{ - return m_d->getPitchScale(); -} - -size_t -RubberBandStretcher::getLatency() const -{ - return m_d->getLatency(); -} - -void -RubberBandStretcher::setTransientsOption(Options options) -{ - m_d->setTransientsOption(options); -} - -void -RubberBandStretcher::setPhaseOption(Options options) -{ - m_d->setPhaseOption(options); -} - -void -RubberBandStretcher::setFormantOption(Options options) -{ - m_d->setFormantOption(options); -} - -void -RubberBandStretcher::setPitchOption(Options options) -{ - m_d->setPitchOption(options); -} - -void -RubberBandStretcher::setExpectedInputDuration(size_t samples) -{ - m_d->setExpectedInputDuration(samples); -} - -void -RubberBandStretcher::setMaxProcessSize(size_t samples) -{ - m_d->setMaxProcessSize(samples); -} - -size_t -RubberBandStretcher::getSamplesRequired() const -{ - return m_d->getSamplesRequired(); -} - -void -RubberBandStretcher::study(const float *const *input, size_t samples, - bool final) -{ - m_d->study(input, samples, final); -} - -void -RubberBandStretcher::process(const float *const *input, size_t samples, - bool final) -{ - m_d->process(input, samples, final); -} - -int -RubberBandStretcher::available() const -{ - return m_d->available(); -} - -size_t -RubberBandStretcher::retrieve(float *const *output, size_t samples) const -{ - return m_d->retrieve(output, samples); -} - -float -RubberBandStretcher::getFrequencyCutoff(int n) const -{ - return m_d->getFrequencyCutoff(n); -} - -void -RubberBandStretcher::setFrequencyCutoff(int n, float f) -{ - m_d->setFrequencyCutoff(n, f); -} - -size_t -RubberBandStretcher::getInputIncrement() const -{ - return m_d->getInputIncrement(); -} - -std::vector<int> -RubberBandStretcher::getOutputIncrements() const -{ - return m_d->getOutputIncrements(); -} - -std::vector<float> -RubberBandStretcher::getPhaseResetCurve() const -{ - return m_d->getPhaseResetCurve(); -} - -std::vector<int> -RubberBandStretcher::getExactTimePoints() const -{ - return m_d->getExactTimePoints(); -} - -size_t -RubberBandStretcher::getChannelCount() const -{ - return m_d->getChannelCount(); -} - -void -RubberBandStretcher::calculateStretch() -{ - m_d->calculateStretch(); -} - -void -RubberBandStretcher::setDebugLevel(int level) -{ - m_d->setDebugLevel(level); -} - -void -RubberBandStretcher::setDefaultDebugLevel(int level) -{ - Impl::setDefaultDebugLevel(level); -} - -} - diff --git a/libs/rubberband/src/Scavenger.h b/libs/rubberband/src/Scavenger.h deleted file mode 100644 index d1b6ca9ffa..0000000000 --- a/libs/rubberband/src/Scavenger.h +++ /dev/null @@ -1,202 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#ifndef _RUBBERBAND_SCAVENGER_H_ -#define _RUBBERBAND_SCAVENGER_H_ - -#include <vector> -#include <list> -#include <iostream> - -#ifndef WIN32 -#include <sys/time.h> -#endif - -#include "Thread.h" -#include "sysutils.h" - -namespace RubberBand { - -/** - * A very simple class that facilitates running things like plugins - * without locking, by collecting unwanted objects and deleting them - * after a delay so as to be sure nobody's in the middle of using - * them. Requires scavenge() to be called regularly from a non-RT - * thread. - * - * This is currently not at all suitable for large numbers of objects - * -- it's just a quick hack for use with things like plugins. - */ - -template <typename T> -class Scavenger -{ -public: - Scavenger(int sec = 2, int defaultObjectListSize = 200); - ~Scavenger(); - - /** - * Call from an RT thread etc., to pass ownership of t to us. - * Only one thread should be calling this on any given scavenger. - */ - void claim(T *t); - - /** - * Call from a non-RT thread. - * Only one thread should be calling this on any given scavenger. - */ - void scavenge(bool clearNow = false); - -protected: - typedef std::pair<T *, int> ObjectTimePair; - typedef std::vector<ObjectTimePair> ObjectTimeList; - ObjectTimeList m_objects; - int m_sec; - - typedef std::list<T *> ObjectList; - ObjectList m_excess; - int m_lastExcess; - Mutex m_excessMutex; - void pushExcess(T *); - void clearExcess(int); - - unsigned int m_claimed; - unsigned int m_scavenged; -}; - -/** - * A wrapper to permit arrays to be scavenged. - */ - -template <typename T> -class ScavengerArrayWrapper -{ -public: - ScavengerArrayWrapper(T *array) : m_array(array) { } - ~ScavengerArrayWrapper() { delete[] m_array; } - -private: - T *m_array; -}; - - -template <typename T> -Scavenger<T>::Scavenger(int sec, int defaultObjectListSize) : - m_objects(ObjectTimeList(defaultObjectListSize)), - m_sec(sec), - m_claimed(0), - m_scavenged(0) -{ -} - -template <typename T> -Scavenger<T>::~Scavenger() -{ - if (m_scavenged < m_claimed) { - for (size_t i = 0; i < m_objects.size(); ++i) { - ObjectTimePair &pair = m_objects[i]; - if (pair.first != 0) { - T *ot = pair.first; - pair.first = 0; - delete ot; - ++m_scavenged; - } - } - } - - clearExcess(0); -} - -template <typename T> -void -Scavenger<T>::claim(T *t) -{ -// std::cerr << "Scavenger::claim(" << t << ")" << std::endl; - - struct timeval tv; - (void)gettimeofday(&tv, 0); - int sec = tv.tv_sec; - - for (size_t i = 0; i < m_objects.size(); ++i) { - ObjectTimePair &pair = m_objects[i]; - if (pair.first == 0) { - pair.second = sec; - pair.first = t; - ++m_claimed; - return; - } - } - - std::cerr << "WARNING: Scavenger::claim(" << t << "): run out of slots, " - << "using non-RT-safe method" << std::endl; - pushExcess(t); -} - -template <typename T> -void -Scavenger<T>::scavenge(bool clearNow) -{ -// std::cerr << "Scavenger::scavenge: scavenged " << m_scavenged << ", claimed " << m_claimed << std::endl; - - if (m_scavenged >= m_claimed) return; - - struct timeval tv; - (void)gettimeofday(&tv, 0); - int sec = tv.tv_sec; - - for (size_t i = 0; i < m_objects.size(); ++i) { - ObjectTimePair &pair = m_objects[i]; - if (clearNow || - (pair.first != 0 && pair.second + m_sec < sec)) { - T *ot = pair.first; - pair.first = 0; - delete ot; - ++m_scavenged; - } - } - - if (sec > m_lastExcess + m_sec) { - clearExcess(sec); - } -} - -template <typename T> -void -Scavenger<T>::pushExcess(T *t) -{ - m_excessMutex.lock(); - m_excess.push_back(t); - struct timeval tv; - (void)gettimeofday(&tv, 0); - m_lastExcess = tv.tv_sec; - m_excessMutex.unlock(); -} - -template <typename T> -void -Scavenger<T>::clearExcess(int sec) -{ - m_excessMutex.lock(); - for (typename ObjectList::iterator i = m_excess.begin(); - i != m_excess.end(); ++i) { - delete *i; - } - m_excess.clear(); - m_lastExcess = sec; - m_excessMutex.unlock(); -} - -} - -#endif diff --git a/libs/rubberband/src/SilentAudioCurve.cpp b/libs/rubberband/src/SilentAudioCurve.cpp deleted file mode 100644 index 2bc8bdcf5f..0000000000 --- a/libs/rubberband/src/SilentAudioCurve.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#include "SilentAudioCurve.h" - -#include <cmath> - -namespace RubberBand -{ - -SilentAudioCurve::SilentAudioCurve(size_t sampleRate, size_t windowSize) : - AudioCurve(sampleRate, windowSize) -{ -} - -SilentAudioCurve::~SilentAudioCurve() -{ -} - -void -SilentAudioCurve::reset() -{ -} - -void -SilentAudioCurve::setWindowSize(size_t newSize) -{ - m_windowSize = newSize; -} - -float -SilentAudioCurve::process(const float *R__ mag, size_t) -{ - const int hs = m_windowSize / 2; - static float threshold = powf(10.f, -6); - - for (int i = 0; i <= hs; ++i) { - if (mag[i] > threshold) return 0.f; - } - - return 1.f; -} - -float -SilentAudioCurve::processDouble(const double *R__ mag, size_t) -{ - const int hs = m_windowSize / 2; - static double threshold = pow(10.0, -6); - - for (int i = 0; i <= hs; ++i) { - if (mag[i] > threshold) return 0.f; - } - - return 1.f; -} - -} - diff --git a/libs/rubberband/src/SilentAudioCurve.h b/libs/rubberband/src/SilentAudioCurve.h deleted file mode 100644 index 6309f9dddf..0000000000 --- a/libs/rubberband/src/SilentAudioCurve.h +++ /dev/null @@ -1,38 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#ifndef _SILENT_AUDIO_CURVE_H_ -#define _SILENT_AUDIO_CURVE_H_ - -#include "AudioCurve.h" - -namespace RubberBand -{ - -class SilentAudioCurve : public AudioCurve -{ -public: - SilentAudioCurve(size_t sampleRate, size_t windowSize); - virtual ~SilentAudioCurve(); - - virtual void setWindowSize(size_t newSize); - - virtual float process(const float *R__ mag, size_t increment); - virtual float processDouble(const double *R__ mag, size_t increment); - virtual void reset(); -}; - -} - -#endif diff --git a/libs/rubberband/src/SpectralDifferenceAudioCurve.cpp b/libs/rubberband/src/SpectralDifferenceAudioCurve.cpp deleted file mode 100644 index 7d98828915..0000000000 --- a/libs/rubberband/src/SpectralDifferenceAudioCurve.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#include "SpectralDifferenceAudioCurve.h" - -namespace RubberBand -{ - -SpectralDifferenceAudioCurve::SpectralDifferenceAudioCurve(size_t sampleRate, size_t windowSize) : - AudioCurve(sampleRate, windowSize) -{ - m_prevMag = new float[m_windowSize/2 + 1]; - - for (size_t i = 0; i <= m_windowSize/2; ++i) { - m_prevMag[i] = 0.f; - } -} - -SpectralDifferenceAudioCurve::~SpectralDifferenceAudioCurve() -{ - delete[] m_prevMag; -} - -void -SpectralDifferenceAudioCurve::reset() -{ - for (size_t i = 0; i <= m_windowSize/2; ++i) { - m_prevMag[i] = 0; - } -} - -void -SpectralDifferenceAudioCurve::setWindowSize(size_t newSize) -{ - delete[] m_prevMag; - m_windowSize = newSize; - - m_prevMag = new float[m_windowSize/2 + 1]; - - reset(); -} - -float -SpectralDifferenceAudioCurve::process(const float *R__ mag, size_t /*increment*/) -{ - float result = 0.0; - - for (size_t n = 0; n <= m_windowSize / 2; ++n) { - result += sqrtf(fabsf((mag[n] * mag[n]) - - (m_prevMag[n] * m_prevMag[n]))); - m_prevMag[n] = mag[n]; - } - - return result; -} - -float -SpectralDifferenceAudioCurve::processDouble(const double *R__ mag, size_t /*increment*/) -{ - float result = 0.0; - - for (size_t n = 0; n <= m_windowSize / 2; ++n) { - result += sqrtf(fabsf((mag[n] * mag[n]) - - (m_prevMag[n] * m_prevMag[n]))); - m_prevMag[n] = (float)mag[n]; - } - - return result; -} - -} - diff --git a/libs/rubberband/src/SpectralDifferenceAudioCurve.h b/libs/rubberband/src/SpectralDifferenceAudioCurve.h deleted file mode 100644 index 4295653cf0..0000000000 --- a/libs/rubberband/src/SpectralDifferenceAudioCurve.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#ifndef _SPECTRALDIFFERENCE_AUDIO_CURVE_H_ -#define _SPECTRALDIFFERENCE_AUDIO_CURVE_H_ - -#include "AudioCurve.h" -#include "Window.h" - -namespace RubberBand -{ - -class SpectralDifferenceAudioCurve : public AudioCurve -{ -public: - SpectralDifferenceAudioCurve(size_t sampleRate, size_t windowSize); - - virtual ~SpectralDifferenceAudioCurve(); - - virtual void setWindowSize(size_t newSize); - - virtual float process(const float *R__ mag, size_t increment); - virtual float processDouble(const double *R__ mag, size_t increment); - virtual void reset(); - -protected: - float *R__ m_prevMag; -}; - -} - -#endif diff --git a/libs/rubberband/src/StretchCalculator.cpp b/libs/rubberband/src/StretchCalculator.cpp deleted file mode 100644 index 1541759762..0000000000 --- a/libs/rubberband/src/StretchCalculator.cpp +++ /dev/null @@ -1,799 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#include "StretchCalculator.h" - -#include <algorithm> -#include <math.h> -#include <algorithm> -#include <iostream> -#include <deque> -#include <set> -#include <cassert> -#include <algorithm> - -#include "sysutils.h" - -namespace RubberBand -{ - -StretchCalculator::StretchCalculator(size_t sampleRate, - size_t inputIncrement, - bool useHardPeaks) : - m_sampleRate(sampleRate), - m_increment(inputIncrement), - m_prevDf(0), - m_divergence(0), - m_recovery(0), - m_prevRatio(1.0), - m_transientAmnesty(0), - m_useHardPeaks(useHardPeaks) -{ -// std::cerr << "StretchCalculator::StretchCalculator: useHardPeaks = " << useHardPeaks << std::endl; -} - -StretchCalculator::~StretchCalculator() -{ -} - -std::vector<int> -StretchCalculator::calculate(double ratio, size_t inputDuration, - const std::vector<float> &phaseResetDf, - const std::vector<float> &stretchDf) -{ - assert(phaseResetDf.size() == stretchDf.size()); - - m_lastPeaks = findPeaks(phaseResetDf); - std::vector<Peak> &peaks = m_lastPeaks; - size_t totalCount = phaseResetDf.size(); - - std::vector<int> increments; - - size_t outputDuration = lrint(inputDuration * ratio); - - if (m_debugLevel > 0) { - std::cerr << "StretchCalculator::calculate(): inputDuration " << inputDuration << ", ratio " << ratio << ", outputDuration " << outputDuration; - } - - outputDuration = lrint((phaseResetDf.size() * m_increment) * ratio); - - if (m_debugLevel > 0) { - std::cerr << " (rounded up to " << outputDuration << ")"; - std::cerr << ", df size " << phaseResetDf.size() << std::endl; - } - - std::vector<size_t> fixedAudioChunks; - for (size_t i = 0; i < peaks.size(); ++i) { - fixedAudioChunks.push_back - (lrint((double(peaks[i].chunk) * outputDuration) / totalCount)); - } - - if (m_debugLevel > 1) { - std::cerr << "have " << peaks.size() << " fixed positions" << std::endl; - } - - size_t totalInput = 0, totalOutput = 0; - - // For each region between two consecutive time sync points, we - // want to take the number of output chunks to be allocated and - // the detection function values within the range, and produce a - // series of increments that sum to the number of output chunks, - // such that each increment is displaced from the input increment - // by an amount inversely proportional to the magnitude of the - // stretch detection function at that input step. - - size_t regionTotalChunks = 0; - - for (size_t i = 0; i <= peaks.size(); ++i) { - - size_t regionStart, regionStartChunk, regionEnd, regionEndChunk; - bool phaseReset = false; - - if (i == 0) { - regionStartChunk = 0; - regionStart = 0; - } else { - regionStartChunk = peaks[i-1].chunk; - regionStart = fixedAudioChunks[i-1]; - phaseReset = peaks[i-1].hard; - } - - if (i == peaks.size()) { - regionEndChunk = totalCount; - regionEnd = outputDuration; - } else { - regionEndChunk = peaks[i].chunk; - regionEnd = fixedAudioChunks[i]; - } - - size_t regionDuration = regionEnd - regionStart; - regionTotalChunks += regionDuration; - - std::vector<float> dfRegion; - - for (size_t j = regionStartChunk; j != regionEndChunk; ++j) { - dfRegion.push_back(stretchDf[j]); - } - - if (m_debugLevel > 1) { - std::cerr << "distributeRegion from " << regionStartChunk << " to " << regionEndChunk << " (chunks " << regionStart << " to " << regionEnd << ")" << std::endl; - } - - dfRegion = smoothDF(dfRegion); - - std::vector<int> regionIncrements = distributeRegion - (dfRegion, regionDuration, ratio, phaseReset); - - size_t totalForRegion = 0; - - for (size_t j = 0; j < regionIncrements.size(); ++j) { - - int incr = regionIncrements[j]; - - if (j == 0 && phaseReset) increments.push_back(-incr); - else increments.push_back(incr); - - if (incr > 0) totalForRegion += incr; - else totalForRegion += -incr; - - totalInput += m_increment; - } - - if (totalForRegion != regionDuration) { - std::cerr << "*** WARNING: distributeRegion returned wrong duration " << totalForRegion << ", expected " << regionDuration << std::endl; - } - - totalOutput += totalForRegion; - } - - if (m_debugLevel > 0) { - std::cerr << "total input increment = " << totalInput << " (= " << totalInput / m_increment << " chunks), output = " << totalOutput << ", ratio = " << double(totalOutput)/double(totalInput) << ", ideal output " << size_t(ceil(totalInput * ratio)) << std::endl; - std::cerr << "(region total = " << regionTotalChunks << ")" << std::endl; - } - - return increments; -} - -int -StretchCalculator::calculateSingle(double ratio, - float df, - size_t increment) -{ - if (increment == 0) increment = m_increment; - - bool isTransient = false; - - // We want to ensure, as close as possible, that the phase reset - // points appear at _exactly_ the right audio frame numbers. - - // In principle, the threshold depends on chunk size: larger chunk - // sizes need higher thresholds. Since chunk size depends on - // ratio, I suppose we could in theory calculate the threshold - // from the ratio directly. For the moment we're happy if it - // works well in common situations. - - float transientThreshold = 0.35f; - if (ratio > 1) transientThreshold = 0.25f; - - if (m_useHardPeaks && df > m_prevDf * 1.1f && df > transientThreshold) { - isTransient = true; - } - - if (m_debugLevel > 2) { - std::cerr << "df = " << df << ", prevDf = " << m_prevDf - << ", thresh = " << transientThreshold << std::endl; - } - - m_prevDf = df; - - bool ratioChanged = (ratio != m_prevRatio); - m_prevRatio = ratio; - - if (isTransient && m_transientAmnesty == 0) { - if (m_debugLevel > 1) { - std::cerr << "StretchCalculator::calculateSingle: transient" - << std::endl; - } - m_divergence += increment - (increment * ratio); - - // as in offline mode, 0.05 sec approx min between transients - m_transientAmnesty = - lrint(ceil(double(m_sampleRate) / (20 * double(increment)))); - - m_recovery = m_divergence / ((m_sampleRate / 10.0) / increment); - return -int(increment); - } - - if (ratioChanged) { - m_recovery = m_divergence / ((m_sampleRate / 10.0) / increment); - } - - if (m_transientAmnesty > 0) --m_transientAmnesty; - - int incr = lrint(increment * ratio - m_recovery); - if (m_debugLevel > 2 || (m_debugLevel > 1 && m_divergence != 0)) { - std::cerr << "divergence = " << m_divergence << ", recovery = " << m_recovery << ", incr = " << incr << ", "; - } - if (incr < lrint((increment * ratio) / 2)) { - incr = lrint((increment * ratio) / 2); - } else if (incr > lrint(increment * ratio * 2)) { - incr = lrint(increment * ratio * 2); - } - - double divdiff = (increment * ratio) - incr; - - if (m_debugLevel > 2 || (m_debugLevel > 1 && m_divergence != 0)) { - std::cerr << "divdiff = " << divdiff << std::endl; - } - - double prevDivergence = m_divergence; - m_divergence -= divdiff; - if ((prevDivergence < 0 && m_divergence > 0) || - (prevDivergence > 0 && m_divergence < 0)) { - m_recovery = m_divergence / ((m_sampleRate / 10.0) / increment); - } - - return incr; -} - -void -StretchCalculator::reset() -{ - m_prevDf = 0; - m_divergence = 0; -} - -std::vector<StretchCalculator::Peak> -StretchCalculator::findPeaks(const std::vector<float> &rawDf) -{ - std::vector<float> df = smoothDF(rawDf); - - // We distinguish between "soft" and "hard" peaks. A soft peak is - // simply the result of peak-picking on the smoothed onset - // detection function, and it represents any (strong-ish) onset. - // We aim to ensure always that soft peaks are placed at the - // correct position in time. A hard peak is where there is a very - // rapid rise in detection function, and it presumably represents - // a more broadband, noisy transient. For these we perform a - // phase reset (if in the appropriate mode), and we locate the - // reset at the first point where we notice enough of a rapid - // rise, rather than necessarily at the peak itself, in order to - // preserve the shape of the transient. - - std::set<size_t> hardPeakCandidates; - std::set<size_t> softPeakCandidates; - - if (m_useHardPeaks) { - - // 0.05 sec approx min between hard peaks - size_t hardPeakAmnesty = lrint(ceil(double(m_sampleRate) / - (20 * double(m_increment)))); - size_t prevHardPeak = 0; - - if (m_debugLevel > 1) { - std::cerr << "hardPeakAmnesty = " << hardPeakAmnesty << std::endl; - } - - for (size_t i = 1; i + 1 < df.size(); ++i) { - - if (df[i] < 0.1) continue; - if (df[i] <= df[i-1] * 1.1) continue; - if (df[i] < 0.22) continue; - - if (!hardPeakCandidates.empty() && - i < prevHardPeak + hardPeakAmnesty) { - continue; - } - - bool hard = (df[i] > 0.4); - - if (hard && (m_debugLevel > 1)) { - std::cerr << "hard peak at " << i << ": " << df[i] - << " > absolute " << 0.4 - << std::endl; - } - - if (!hard) { - hard = (df[i] > df[i-1] * 1.4); - - if (hard && (m_debugLevel > 1)) { - std::cerr << "hard peak at " << i << ": " << df[i] - << " > prev " << df[i-1] << " * 1.4" - << std::endl; - } - } - - if (!hard && i > 1) { - hard = (df[i] > df[i-1] * 1.2 && - df[i-1] > df[i-2] * 1.2); - - if (hard && (m_debugLevel > 1)) { - std::cerr << "hard peak at " << i << ": " << df[i] - << " > prev " << df[i-1] << " * 1.2 and " - << df[i-1] << " > prev " << df[i-2] << " * 1.2" - << std::endl; - } - } - - if (!hard && i > 2) { - // have already established that df[i] > df[i-1] * 1.1 - hard = (df[i] > 0.3 && - df[i-1] > df[i-2] * 1.1 && - df[i-2] > df[i-3] * 1.1); - - if (hard && (m_debugLevel > 1)) { - std::cerr << "hard peak at " << i << ": " << df[i] - << " > prev " << df[i-1] << " * 1.1 and " - << df[i-1] << " > prev " << df[i-2] << " * 1.1 and " - << df[i-2] << " > prev " << df[i-3] << " * 1.1" - << std::endl; - } - } - - if (!hard) continue; - -// (df[i+1] > df[i] && df[i+1] > df[i-1] * 1.8) || -// df[i] > 0.4) { - - size_t peakLocation = i; - - if (i + 1 < rawDf.size() && - rawDf[i + 1] > rawDf[i] * 1.4) { - - ++peakLocation; - - if (m_debugLevel > 1) { - std::cerr << "pushing hard peak forward to " << peakLocation << ": " << df[peakLocation] << " > " << df[peakLocation-1] << " * " << 1.4 << std::endl; - } - } - - hardPeakCandidates.insert(peakLocation); - prevHardPeak = peakLocation; - } - } - - size_t medianmaxsize = lrint(ceil(double(m_sampleRate) / - double(m_increment))); // 1 sec ish - - if (m_debugLevel > 1) { - std::cerr << "mediansize = " << medianmaxsize << std::endl; - } - if (medianmaxsize < 7) { - medianmaxsize = 7; - if (m_debugLevel > 1) { - std::cerr << "adjusted mediansize = " << medianmaxsize << std::endl; - } - } - - int minspacing = lrint(ceil(double(m_sampleRate) / - (20 * double(m_increment)))); // 0.05 sec ish - - std::deque<float> medianwin; - std::vector<float> sorted; - int softPeakAmnesty = 0; - - for (size_t i = 0; i < medianmaxsize/2; ++i) { - medianwin.push_back(0); - } - for (size_t i = 0; i < medianmaxsize/2 && i < df.size(); ++i) { - medianwin.push_back(df[i]); - } - - size_t lastSoftPeak = 0; - - for (size_t i = 0; i < df.size(); ++i) { - - size_t mediansize = medianmaxsize; - - if (medianwin.size() < mediansize) { - mediansize = medianwin.size(); - } - - size_t middle = medianmaxsize / 2; - if (middle >= mediansize) middle = mediansize-1; - - size_t nextDf = i + mediansize - middle; - - if (mediansize < 2) { - if (mediansize > medianmaxsize) { // absurd, but never mind that - medianwin.pop_front(); - } - if (nextDf < df.size()) { - medianwin.push_back(df[nextDf]); - } else { - medianwin.push_back(0); - } - continue; - } - - if (m_debugLevel > 2) { -// std::cerr << "have " << mediansize << " in median buffer" << std::endl; - } - - sorted.clear(); - for (size_t j = 0; j < mediansize; ++j) { - sorted.push_back(medianwin[j]); - } - std::sort(sorted.begin(), sorted.end()); - - size_t n = 90; // percentile above which we pick peaks - size_t index = (sorted.size() * n) / 100; - if (index >= sorted.size()) index = sorted.size()-1; - if (index == sorted.size()-1 && index > 0) --index; - float thresh = sorted[index]; - -// if (m_debugLevel > 2) { -// std::cerr << "medianwin[" << middle << "] = " << medianwin[middle] << ", thresh = " << thresh << std::endl; -// if (medianwin[middle] == 0.f) { -// std::cerr << "contents: "; -// for (size_t j = 0; j < medianwin.size(); ++j) { -// std::cerr << medianwin[j] << " "; -// } -// std::cerr << std::endl; -// } -// } - - if (medianwin[middle] > thresh && - medianwin[middle] > medianwin[middle-1] && - medianwin[middle] > medianwin[middle+1] && - softPeakAmnesty == 0) { - - size_t maxindex = middle; - float maxval = medianwin[middle]; - - for (size_t j = middle+1; j < mediansize; ++j) { - if (medianwin[j] > maxval) { - maxval = medianwin[j]; - maxindex = j; - } else if (medianwin[j] < medianwin[middle]) { - break; - } - } - - size_t peak = i + maxindex - middle; - -// std::cerr << "i = " << i << ", maxindex = " << maxindex << ", middle = " << middle << ", so peak at " << peak << std::endl; - - if (softPeakCandidates.empty() || lastSoftPeak != peak) { - - if (m_debugLevel > 1) { - std::cerr << "soft peak at " << peak << " (" - << peak * m_increment << "): " - << medianwin[middle] << " > " - << thresh << " and " - << medianwin[middle] - << " > " << medianwin[middle-1] << " and " - << medianwin[middle] - << " > " << medianwin[middle+1] - << std::endl; - } - - if (peak >= df.size()) { - if (m_debugLevel > 2) { - std::cerr << "peak is beyond end" << std::endl; - } - } else { - softPeakCandidates.insert(peak); - lastSoftPeak = peak; - } - } - - softPeakAmnesty = minspacing + maxindex - middle; - if (m_debugLevel > 2) { - std::cerr << "amnesty = " << softPeakAmnesty << std::endl; - } - - } else if (softPeakAmnesty > 0) --softPeakAmnesty; - - if (mediansize >= medianmaxsize) { - medianwin.pop_front(); - } - if (nextDf < df.size()) { - medianwin.push_back(df[nextDf]); - } else { - medianwin.push_back(0); - } - } - - std::vector<Peak> peaks; - - while (!hardPeakCandidates.empty() || !softPeakCandidates.empty()) { - - bool haveHardPeak = !hardPeakCandidates.empty(); - bool haveSoftPeak = !softPeakCandidates.empty(); - - size_t hardPeak = (haveHardPeak ? *hardPeakCandidates.begin() : 0); - size_t softPeak = (haveSoftPeak ? *softPeakCandidates.begin() : 0); - - Peak peak; - peak.hard = false; - peak.chunk = softPeak; - - bool ignore = false; - - if (haveHardPeak && - (!haveSoftPeak || hardPeak <= softPeak)) { - - if (m_debugLevel > 2) { - std::cerr << "Hard peak: " << hardPeak << std::endl; - } - - peak.hard = true; - peak.chunk = hardPeak; - hardPeakCandidates.erase(hardPeakCandidates.begin()); - - } else { - if (m_debugLevel > 2) { - std::cerr << "Soft peak: " << softPeak << std::endl; - } - if (!peaks.empty() && - peaks[peaks.size()-1].hard && - peaks[peaks.size()-1].chunk + 3 >= softPeak) { - if (m_debugLevel > 2) { - std::cerr << "(ignoring, as we just had a hard peak)" - << std::endl; - } - ignore = true; - } - } - - if (haveSoftPeak && peak.chunk == softPeak) { - softPeakCandidates.erase(softPeakCandidates.begin()); - } - - if (!ignore) { - peaks.push_back(peak); - } - } - - return peaks; -} - -std::vector<float> -StretchCalculator::smoothDF(const std::vector<float> &df) -{ - std::vector<float> smoothedDF; - - for (size_t i = 0; i < df.size(); ++i) { - // three-value moving mean window for simple smoothing - float total = 0.f, count = 0; - if (i > 0) { total += df[i-1]; ++count; } - total += df[i]; ++count; - if (i+1 < df.size()) { total += df[i+1]; ++count; } - float mean = total / count; - smoothedDF.push_back(mean); - } - - return smoothedDF; -} - -std::vector<int> -StretchCalculator::distributeRegion(const std::vector<float> &dfIn, - size_t duration, float ratio, bool phaseReset) -{ - std::vector<float> df(dfIn); - std::vector<int> increments; - - // The peak for the stretch detection function may appear after - // the peak that we're using to calculate the start of the region. - // We don't want that. If we find a peak in the first half of - // the region, we should set all the values up to that point to - // the same value as the peak. - - // (This might not be subtle enough, especially if the region is - // long -- we want a bound that corresponds to acoustic perception - // of the audible bounce.) - - for (size_t i = 1; i < df.size()/2; ++i) { - if (df[i] < df[i-1]) { - if (m_debugLevel > 1) { - std::cerr << "stretch peak offset: " << i-1 << " (peak " << df[i-1] << ")" << std::endl; - } - for (size_t j = 0; j < i-1; ++j) { - df[j] = df[i-1]; - } - break; - } - } - - float maxDf = 0; - - for (size_t i = 0; i < df.size(); ++i) { - if (i == 0 || df[i] > maxDf) maxDf = df[i]; - } - - // We want to try to ensure the last 100ms or so (if possible) are - // tending back towards the maximum df, so that the stretchiness - // reduces at the end of the stretched region. - - int reducedRegion = lrint((0.1 * m_sampleRate) / m_increment); - if (reducedRegion > int(df.size()/5)) reducedRegion = df.size()/5; - - for (int i = 0; i < reducedRegion; ++i) { - size_t index = df.size() - reducedRegion + i; - df[index] = df[index] + ((maxDf - df[index]) * i) / reducedRegion; - } - - long toAllot = long(duration) - long(m_increment * df.size()); - - if (m_debugLevel > 1) { - std::cerr << "region of " << df.size() << " chunks, output duration " << duration << ", toAllot " << toAllot << std::endl; - } - - size_t totalIncrement = 0; - - // We place limits on the amount of displacement per chunk. if - // ratio < 0, no increment should be larger than increment*ratio - // or smaller than increment*ratio/2; if ratio > 0, none should be - // smaller than increment*ratio or larger than increment*ratio*2. - // We need to enforce this in the assignment of displacements to - // allotments, not by trying to respond if something turns out - // wrong. - - // Note that the ratio is only provided to this function for the - // purposes of establishing this bound to the displacement. - - // so if - // maxDisplacement / totalDisplacement > increment * ratio*2 - increment - // (for ratio > 1) - // or - // maxDisplacement / totalDisplacement < increment * ratio/2 - // (for ratio < 1) - - // then we need to adjust and accommodate - - bool acceptableSquashRange = false; - - double totalDisplacement = 0; - double maxDisplacement = 0; // min displacement will be 0 by definition - - maxDf = 0; - float adj = 0; - - while (!acceptableSquashRange) { - - acceptableSquashRange = true; - calculateDisplacements(df, maxDf, totalDisplacement, maxDisplacement, - adj); - - if (m_debugLevel > 1) { - std::cerr << "totalDisplacement " << totalDisplacement << ", max " << maxDisplacement << " (maxDf " << maxDf << ", df count " << df.size() << ")" << std::endl; - } - - if (totalDisplacement == 0) { -// Not usually a problem, in fact -// std::cerr << "WARNING: totalDisplacement == 0 (duration " << duration << ", " << df.size() << " values in df)" << std::endl; - if (!df.empty() && adj == 0) { - acceptableSquashRange = false; - adj = 1; - } - continue; - } - - int extremeIncrement = m_increment + lrint((toAllot * maxDisplacement) / totalDisplacement); - if (ratio < 1.0) { - if (extremeIncrement > lrint(ceil(m_increment * ratio))) { - std::cerr << "ERROR: extreme increment " << extremeIncrement << " > " << m_increment * ratio << " (this should not happen)" << std::endl; - } else if (extremeIncrement < (m_increment * ratio) / 2) { - if (m_debugLevel > 0) { - std::cerr << "WARNING: extreme increment " << extremeIncrement << " < " << (m_increment * ratio) / 2 << std::endl; - } - acceptableSquashRange = false; - } - } else { - if (extremeIncrement > m_increment * ratio * 2) { - if (m_debugLevel > 0) { - std::cerr << "WARNING: extreme increment " << extremeIncrement << " > " << m_increment * ratio * 2 << std::endl; - } - acceptableSquashRange = false; - } else if (extremeIncrement < lrint(floor(m_increment * ratio))) { - std::cerr << "ERROR: extreme increment " << extremeIncrement << " < " << m_increment * ratio << " (I thought this couldn't happen?)" << std::endl; - } - } - - if (!acceptableSquashRange) { - // Need to make maxDisplacement smaller as a proportion of - // the total displacement, yet ensure that the - // displacements still sum to the total. - adj += maxDf/10; - } - } - - for (size_t i = 0; i < df.size(); ++i) { - - double displacement = maxDf - df[i]; - if (displacement < 0) displacement -= adj; - else displacement += adj; - - if (i == 0 && phaseReset) { - if (df.size() == 1) { - increments.push_back(duration); - totalIncrement += duration; - } else { - increments.push_back(m_increment); - totalIncrement += m_increment; - } - totalDisplacement -= displacement; - continue; - } - - double theoreticalAllotment = 0; - - if (totalDisplacement != 0) { - theoreticalAllotment = (toAllot * displacement) / totalDisplacement; - } - int allotment = lrint(theoreticalAllotment); - if (i + 1 == df.size()) allotment = toAllot; - - int increment = m_increment + allotment; - - if (increment <= 0) { - // this is a serious problem, the allocation is quite - // wrong if it allows increment to diverge so far from the - // input increment - std::cerr << "*** WARNING: increment " << increment << " <= 0, rounding to zero" << std::endl; - increment = 0; - allotment = increment - m_increment; - } - - increments.push_back(increment); - totalIncrement += increment; - - toAllot -= allotment; - totalDisplacement -= displacement; - - if (m_debugLevel > 2) { - std::cerr << "df " << df[i] << ", smoothed " << df[i] << ", disp " << displacement << ", allot " << theoreticalAllotment << ", incr " << increment << ", remain " << toAllot << std::endl; - } - } - - if (m_debugLevel > 2) { - std::cerr << "total increment: " << totalIncrement << ", left over: " << toAllot << " to allot, displacement " << totalDisplacement << std::endl; - } - - if (totalIncrement != duration) { - std::cerr << "*** WARNING: calculated output duration " << totalIncrement << " != expected " << duration << std::endl; - } - - return increments; -} - -void -StretchCalculator::calculateDisplacements(const std::vector<float> &df, - float &maxDf, - double &totalDisplacement, - double &maxDisplacement, - float adj) const -{ - totalDisplacement = maxDisplacement = 0; - - maxDf = 0; - - for (size_t i = 0; i < df.size(); ++i) { - if (i == 0 || df[i] > maxDf) maxDf = df[i]; - } - - for (size_t i = 0; i < df.size(); ++i) { - double displacement = maxDf - df[i]; - if (displacement < 0) displacement -= adj; - else displacement += adj; - totalDisplacement += displacement; - if (i == 0 || displacement > maxDisplacement) { - maxDisplacement = displacement; - } - } -} - -} - diff --git a/libs/rubberband/src/StretchCalculator.h b/libs/rubberband/src/StretchCalculator.h deleted file mode 100644 index e79c8e3c1e..0000000000 --- a/libs/rubberband/src/StretchCalculator.h +++ /dev/null @@ -1,98 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#ifndef _RUBBERBAND_STRETCH_CALCULATOR_H_ -#define _RUBBERBAND_STRETCH_CALCULATOR_H_ - -#include <sys/types.h> - -#include <vector> - -namespace RubberBand -{ - -class StretchCalculator -{ -public: - StretchCalculator(size_t sampleRate, size_t inputIncrement, bool useHardPeaks); - virtual ~StretchCalculator(); - - /** - * Calculate phase increments for a region of audio, given the - * overall target stretch ratio, input duration in audio samples, - * and the audio curves to use for identifying phase lock points - * (lockAudioCurve) and for allocating stretches to relatively - * less prominent points (stretchAudioCurve). - */ - virtual std::vector<int> calculate(double ratio, size_t inputDuration, - const std::vector<float> &lockAudioCurve, - const std::vector<float> &stretchAudioCurve); - - /** - * Calculate the phase increment for a single audio block, given - * the overall target stretch ratio and the block's value on the - * phase-lock audio curve. State is retained between calls in the - * StretchCalculator object; call reset() to reset it. This uses - * a less sophisticated method than the offline calculate(). - * - * If increment is non-zero, use it for the input increment for - * this block in preference to m_increment. - */ - virtual int calculateSingle(double ratio, float curveValue, - size_t increment = 0); - - void setUseHardPeaks(bool use) { m_useHardPeaks = use; } - - void reset(); - - void setDebugLevel(int level) { m_debugLevel = level; } - - struct Peak { - size_t chunk; - bool hard; - }; - std::vector<Peak> getLastCalculatedPeaks() const { return m_lastPeaks; } - - std::vector<float> smoothDF(const std::vector<float> &df); - -protected: - std::vector<Peak> findPeaks(const std::vector<float> &audioCurve); - - std::vector<int> distributeRegion(const std::vector<float> ®ionCurve, - size_t outputDuration, float ratio, - bool phaseReset); - - void calculateDisplacements(const std::vector<float> &df, - float &maxDf, - double &totalDisplacement, - double &maxDisplacement, - float adj) const; - - size_t m_sampleRate; - size_t m_blockSize; - size_t m_increment; - float m_prevDf; - double m_divergence; - float m_recovery; - float m_prevRatio; - int m_transientAmnesty; // only in RT mode; handled differently offline - int m_debugLevel; - bool m_useHardPeaks; - - std::vector<Peak> m_lastPeaks; -}; - -} - -#endif diff --git a/libs/rubberband/src/StretcherChannelData.cpp b/libs/rubberband/src/StretcherChannelData.cpp deleted file mode 100644 index 240df230d1..0000000000 --- a/libs/rubberband/src/StretcherChannelData.cpp +++ /dev/null @@ -1,305 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#include "StretcherChannelData.h" - -#include "Resampler.h" - - -namespace RubberBand -{ - -RubberBandStretcher::Impl::ChannelData::ChannelData(size_t windowSize, - int overSample, - size_t outbufSize) : - oversample(overSample) -{ - std::set<size_t> s; - construct(s, windowSize, outbufSize); -} - -RubberBandStretcher::Impl::ChannelData::ChannelData(const std::set<size_t> &windowSizes, - int overSample, - size_t initialWindowSize, - size_t outbufSize) : - oversample(overSample) -{ - construct(windowSizes, initialWindowSize, outbufSize); -} - -void -RubberBandStretcher::Impl::ChannelData::construct(const std::set<size_t> &windowSizes, - size_t initialWindowSize, - size_t outbufSize) -{ - size_t maxSize = initialWindowSize; - - if (!windowSizes.empty()) { - // std::set is ordered by value - std::set<size_t>::const_iterator i = windowSizes.end(); - maxSize = *--i; - } - if (windowSizes.find(initialWindowSize) == windowSizes.end()) { - if (initialWindowSize > maxSize) maxSize = initialWindowSize; - } - - // max size of the real "half" of freq data - size_t realSize = (maxSize * oversample)/2 + 1; - -// std::cerr << "ChannelData::construct([" << windowSizes.size() << "], " << maxSize << ", " << outbufSize << ")" << std::endl; - - if (outbufSize < maxSize) outbufSize = maxSize; - - inbuf = new RingBuffer<float>(maxSize); - outbuf = new RingBuffer<float>(outbufSize); - - mag = allocDouble(realSize); - phase = allocDouble(realSize); - prevPhase = allocDouble(realSize); - prevError = allocDouble(realSize); - unwrappedPhase = allocDouble(realSize); - envelope = allocDouble(realSize); - - freqPeak = new size_t[realSize]; - - fltbuf = allocFloat(maxSize); - - accumulator = allocFloat(maxSize); - windowAccumulator = allocFloat(maxSize); - - for (std::set<size_t>::const_iterator i = windowSizes.begin(); - i != windowSizes.end(); ++i) { - ffts[*i] = new FFT(*i * oversample); - ffts[*i]->initDouble(); - } - if (windowSizes.find(initialWindowSize) == windowSizes.end()) { - ffts[initialWindowSize] = new FFT(initialWindowSize * oversample); - ffts[initialWindowSize]->initDouble(); - } - fft = ffts[initialWindowSize]; - - dblbuf = fft->getDoubleTimeBuffer(); - - resampler = 0; - resamplebuf = 0; - resamplebufSize = 0; - - reset(); - - for (size_t i = 0; i < realSize; ++i) { - freqPeak[i] = 0; - } - - for (size_t i = 0; i < initialWindowSize * oversample; ++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 - windowAccumulator[0] = 1.f; -} - -void -RubberBandStretcher::Impl::ChannelData::setWindowSize(size_t windowSize) -{ - size_t oldSize = inbuf->getSize(); - size_t realSize = (windowSize * oversample) / 2 + 1; - -// std::cerr << "ChannelData::setWindowSize(" << windowSize << ") [from " << oldSize << "]" << std::endl; - - if (oldSize >= windowSize) { - - // no need to reallocate buffers, just reselect fft - - //!!! we can't actually do this without locking against the - //process thread, can we? we need to zero the mag/phase - //buffers without interference - - if (ffts.find(windowSize) == ffts.end()) { - //!!! this also requires a lock, but it shouldn't occur in - //RT mode with proper initialisation - ffts[windowSize] = new FFT(windowSize * oversample); - ffts[windowSize]->initDouble(); - } - - fft = ffts[windowSize]; - - dblbuf = fft->getDoubleTimeBuffer(); - - for (size_t i = 0; i < windowSize * oversample; ++i) { - dblbuf[i] = 0.0; - } - - for (size_t i = 0; i < realSize; ++i) { - mag[i] = 0.0; - phase[i] = 0.0; - prevPhase[i] = 0.0; - prevError[i] = 0.0; - unwrappedPhase[i] = 0.0; - freqPeak[i] = 0; - } - - return; - } - - //!!! at this point we need a lock in case a different client - //thread is calling process() -- we need this lock even if we - //aren't running in threaded mode ourselves -- if we're in RT - //mode, then the process call should trylock and fail if the lock - //is unavailable (since this should never normally be the case in - //general use in RT mode) - - RingBuffer<float> *newbuf = inbuf->resized(windowSize); - delete inbuf; - inbuf = newbuf; - - // We don't want to preserve data in these arrays - - mag = allocDouble(mag, realSize); - phase = allocDouble(phase, realSize); - prevPhase = allocDouble(prevPhase, realSize); - prevError = allocDouble(prevError, realSize); - unwrappedPhase = allocDouble(unwrappedPhase, realSize); - envelope = allocDouble(envelope, realSize); - - delete[] freqPeak; - freqPeak = new size_t[realSize]; - - fltbuf = allocFloat(fltbuf, windowSize); - - // But we do want to preserve data in these - - float *newAcc = allocFloat(windowSize); - - for (size_t i = 0; i < oldSize; ++i) newAcc[i] = accumulator[i]; - - freeFloat(accumulator); - accumulator = newAcc; - - newAcc = allocFloat(windowSize); - - for (size_t i = 0; i < oldSize; ++i) newAcc[i] = windowAccumulator[i]; - - freeFloat(windowAccumulator); - windowAccumulator = newAcc; - - //!!! and resampler? - - for (size_t i = 0; i < realSize; ++i) { - freqPeak[i] = 0; - } - - for (size_t i = 0; i < windowSize; ++i) { - fltbuf[i] = 0.f; - } - - if (ffts.find(windowSize) == ffts.end()) { - ffts[windowSize] = new FFT(windowSize * oversample); - ffts[windowSize]->initDouble(); - } - - fft = ffts[windowSize]; - - dblbuf = fft->getDoubleTimeBuffer(); - - for (size_t i = 0; i < windowSize * oversample; ++i) { - dblbuf[i] = 0.0; - } -} - -void -RubberBandStretcher::Impl::ChannelData::setOutbufSize(size_t outbufSize) -{ - size_t oldSize = outbuf->getSize(); - -// std::cerr << "ChannelData::setOutbufSize(" << outbufSize << ") [from " << oldSize << "]" << std::endl; - - if (oldSize < outbufSize) { - - //!!! at this point we need a lock in case a different client - //thread is calling process() - - RingBuffer<float> *newbuf = outbuf->resized(outbufSize); - delete outbuf; - outbuf = newbuf; - } -} - -void -RubberBandStretcher::Impl::ChannelData::setResampleBufSize(size_t sz) -{ - resamplebuf = allocFloat(resamplebuf, sz); - resamplebufSize = sz; -} - -RubberBandStretcher::Impl::ChannelData::~ChannelData() -{ - delete resampler; - - freeFloat(resamplebuf); - - delete inbuf; - delete outbuf; - - freeDouble(mag); - freeDouble(phase); - freeDouble(prevPhase); - freeDouble(prevError); - freeDouble(unwrappedPhase); - freeDouble(envelope); - delete[] freqPeak; - freeFloat(accumulator); - freeFloat(windowAccumulator); - freeFloat(fltbuf); - - for (std::map<size_t, FFT *>::iterator i = ffts.begin(); - i != ffts.end(); ++i) { - delete i->second; - } -} - -void -RubberBandStretcher::Impl::ChannelData::reset() -{ - inbuf->reset(); - outbuf->reset(); - - if (resampler) resampler->reset(); - - size_t size = inbuf->getSize(); - - for (size_t i = 0; i < size; ++i) { - accumulator[i] = 0.f; - windowAccumulator[i] = 0.f; - } - - // Avoid dividing opening sample (which will be discarded anyway) by zero - windowAccumulator[0] = 1.f; - - accumulatorFill = 0; - prevIncrement = 0; - chunkCount = 0; - inCount = 0; - inputSize = -1; - outCount = 0; - unchanged = true; - draining = false; - outputComplete = false; -} - -} diff --git a/libs/rubberband/src/StretcherChannelData.h b/libs/rubberband/src/StretcherChannelData.h deleted file mode 100644 index b56a6e07dc..0000000000 --- a/libs/rubberband/src/StretcherChannelData.h +++ /dev/null @@ -1,135 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#ifndef _RUBBERBAND_STRETCHERCHANNELDATA_H_ -#define _RUBBERBAND_STRETCHERCHANNELDATA_H_ - -#include "StretcherImpl.h" - -#include <set> - -//#define EXPERIMENT 1 - -namespace RubberBand -{ - -class Resampler; - -class RubberBandStretcher::Impl::ChannelData -{ -public: - /** - * Construct a ChannelData structure. - * - * The window size passed in here is the size for the FFT - * calculation, and most of the buffer sizes also depend on - * it. In practice it is always a power of two and except for - * very extreme stretches is always either 1024, 2048 or 4096. - * - * The outbuf size depends on other factors as well, including - * the pitch scale factor and any maximum processing block - * size specified by the user of the code. - */ - ChannelData(size_t windowSize, int overSample, size_t outbufSize); - - /** - * Construct a ChannelData structure that can process at - * different FFT sizes without requiring reallocation when the - * size changes. The size can subsequently be changed with a - * call to setWindowSize. Reallocation will only be necessary - * if setWindowSize is called with a value not equal to one of - * those passed in to the constructor. - * - * The outbufSize should be the maximum possible outbufSize to - * avoid reallocation, which will happen if setOutbufSize is - * called subsequently. - */ - ChannelData(const std::set<size_t> &windowSizes, - int overSample, size_t initialWindowSize, size_t outbufSize); - ~ChannelData(); - - /** - * Reset buffers - */ - void reset(); - - /** - * Set the FFT and buffer sizes from the given processing - * window size. If this ChannelData was constructed with a set - * of window sizes and the given window size here was among - * them, no reallocation will be required. - */ - void setWindowSize(size_t windowSize); - - /** - * Set the outbufSize for the channel data. Reallocation will - * occur. - */ - void setOutbufSize(size_t outbufSize); - - /** - * Set the resampler buffer size. Default if not called is no - * buffer allocated at all. - */ - void setResampleBufSize(size_t resamplebufSize); - - RingBuffer<float> *inbuf; - RingBuffer<float> *outbuf; - - double *mag; - double *phase; - - double *prevPhase; - double *prevError; - double *unwrappedPhase; - - - size_t *freqPeak; - - float *accumulator; - size_t accumulatorFill; - float *windowAccumulator; - - float *fltbuf; - double *dblbuf; // owned by FFT object, only used for time domain FFT i/o - double *envelope; // for cepstral formant shift - bool unchanged; - - size_t prevIncrement; // only used in RT mode - - size_t chunkCount; - size_t inCount; - long inputSize; // set only after known (when data ended); -1 previously - size_t outCount; - - bool draining; - bool outputComplete; - - FFT *fft; - std::map<size_t, FFT *> ffts; - - Resampler *resampler; - float *resamplebuf; - size_t resamplebufSize; - - int oversample; - -private: - void construct(const std::set<size_t> &windowSizes, - size_t initialWindowSize, size_t outbufSize); -}; - -} - -#endif diff --git a/libs/rubberband/src/StretcherImpl.cpp b/libs/rubberband/src/StretcherImpl.cpp deleted file mode 100644 index 200c8771a8..0000000000 --- a/libs/rubberband/src/StretcherImpl.cpp +++ /dev/null @@ -1,1144 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#include "StretcherImpl.h" -#include "PercussiveAudioCurve.h" -#include "HighFrequencyAudioCurve.h" -#include "SpectralDifferenceAudioCurve.h" -#include "SilentAudioCurve.h" -#include "ConstantAudioCurve.h" -#include "StretchCalculator.h" -#include "StretcherChannelData.h" -#include "Resampler.h" -#include "Profiler.h" - -#include <cassert> -#include <cmath> -#include <set> -#include <map> - -using std::cerr; -using std::endl; -using std::vector; -using std::map; -using std::set; -using std::max; -using std::min; - - -namespace RubberBand { - -const size_t -RubberBandStretcher::Impl::m_defaultIncrement = 256; - -const size_t -RubberBandStretcher::Impl::m_defaultWindowSize = 2048; - -int -RubberBandStretcher::Impl::m_defaultDebugLevel = 0; - - - -RubberBandStretcher::Impl::Impl(size_t sampleRate, - size_t channels, - Options options, - double initialTimeRatio, - double initialPitchScale) : - m_sampleRate(sampleRate), - m_channels(channels), - m_timeRatio(initialTimeRatio), - m_pitchScale(initialPitchScale), - m_windowSize(m_defaultWindowSize), - m_increment(m_defaultIncrement), - m_outbufSize(m_defaultWindowSize * 2), - m_maxProcessSize(m_defaultWindowSize), - m_expectedInputDuration(0), - m_threaded(false), - m_realtime(false), - m_options(options), - m_debugLevel(m_defaultDebugLevel), - m_mode(JustCreated), - m_window(0), - m_studyFFT(0), - m_spaceAvailable("space"), - m_inputDuration(0), - m_silentHistory(0), - m_lastProcessOutputIncrements(16), - m_lastProcessPhaseResetDf(16), - m_phaseResetAudioCurve(0), - m_stretchAudioCurve(0), - m_silentAudioCurve(0), - m_stretchCalculator(0), - m_freq0(600), - m_freq1(1200), - m_freq2(12000), - m_baseWindowSize(m_defaultWindowSize) -{ - - if (m_debugLevel > 0) { - cerr << "RubberBandStretcher::Impl::Impl: rate = " << m_sampleRate << ", options = " << options << endl; - } - - // Window size will vary according to the audio sample rate, but - // we don't let it drop below the 48k default - m_rateMultiple = float(m_sampleRate) / 48000.f; - if (m_rateMultiple < 1.f) m_rateMultiple = 1.f; - m_baseWindowSize = roundUp(int(m_defaultWindowSize * m_rateMultiple)); - - 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; - } else if (options & OptionWindowShort) { - m_baseWindowSize = m_baseWindowSize / 2; - if (m_debugLevel > 0) { - cerr << "setting baseWindowSize to " << m_baseWindowSize << endl; - } - } else if (options & OptionWindowLong) { - m_baseWindowSize = m_baseWindowSize * 2; - if (m_debugLevel > 0) { - cerr << "setting baseWindowSize to " << m_baseWindowSize << endl; - } - } - m_windowSize = m_baseWindowSize; - m_outbufSize = m_baseWindowSize * 2; - m_maxProcessSize = m_baseWindowSize; - } - - if (m_options & OptionProcessRealTime) { - - m_realtime = true; - - if (!(m_options & OptionStretchPrecise)) { - m_options |= OptionStretchPrecise; - } - } - - if (m_channels > 1) { - - m_threaded = true; - - if (m_realtime) { - m_threaded = false; - } else if (m_options & OptionThreadingNever) { - m_threaded = false; - } else if (!(m_options & OptionThreadingAlways) && - !system_is_multiprocessor()) { - m_threaded = false; - } - - if (m_threaded && m_debugLevel > 0) { - cerr << "Going multithreaded..." << endl; - } - } - - configure(); -} - -RubberBandStretcher::Impl::~Impl() -{ - if (m_threaded) { - MutexLocker locker(&m_threadSetMutex); - 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; - } - } - - for (size_t c = 0; c < m_channels; ++c) { - delete m_channelData[c]; - } - - delete m_phaseResetAudioCurve; - delete m_stretchAudioCurve; - delete m_silentAudioCurve; - delete m_stretchCalculator; - delete m_studyFFT; - - for (map<size_t, Window<float> *>::iterator i = m_windows.begin(); - i != m_windows.end(); ++i) { - delete i->second; - } -} - -void -RubberBandStretcher::Impl::reset() -{ - 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) { - m_channelData[c]->reset(); - } - - m_mode = JustCreated; - if (m_phaseResetAudioCurve) m_phaseResetAudioCurve->reset(); - if (m_stretchAudioCurve) m_stretchAudioCurve->reset(); - if (m_silentAudioCurve) m_silentAudioCurve->reset(); - m_inputDuration = 0; - m_silentHistory = 0; - - if (m_threaded) m_threadSetMutex.unlock(); - - reconfigure(); -} - -void -RubberBandStretcher::Impl::setTimeRatio(double ratio) -{ - if (!m_realtime) { - if (m_mode == Studying || m_mode == Processing) { - cerr << "RubberBandStretcher::Impl::setTimeRatio: Cannot set ratio while studying or processing in non-RT mode" << endl; - return; - } - } - - if (ratio == m_timeRatio) return; - m_timeRatio = ratio; - - reconfigure(); -} - -void -RubberBandStretcher::Impl::setPitchScale(double fs) -{ - if (!m_realtime) { - if (m_mode == Studying || m_mode == Processing) { - cerr << "RubberBandStretcher::Impl::setPitchScale: Cannot set ratio while studying or processing in non-RT mode" << endl; - return; - } - } - - if (fs == m_pitchScale) return; - - bool was1 = (m_pitchScale == 1.f); - bool rbs = resampleBeforeStretching(); - - m_pitchScale = fs; - - reconfigure(); - - if (!(m_options & OptionPitchHighConsistency) && - (was1 || resampleBeforeStretching() != rbs) && - m_pitchScale != 1.f) { - - // resampling mode has changed - for (int c = 0; c < int(m_channels); ++c) { - if (m_channelData[c]->resampler) { - m_channelData[c]->resampler->reset(); - } - } - } -} - -double -RubberBandStretcher::Impl::getTimeRatio() const -{ - return m_timeRatio; -} - -double -RubberBandStretcher::Impl::getPitchScale() const -{ - return m_pitchScale; -} - -void -RubberBandStretcher::Impl::setExpectedInputDuration(size_t samples) -{ - if (samples == m_expectedInputDuration) return; - m_expectedInputDuration = samples; - - reconfigure(); -} - -void -RubberBandStretcher::Impl::setMaxProcessSize(size_t samples) -{ - if (samples <= m_maxProcessSize) return; - m_maxProcessSize = samples; - - reconfigure(); -} - -float -RubberBandStretcher::Impl::getFrequencyCutoff(int n) const -{ - switch (n) { - case 0: return m_freq0; - case 1: return m_freq1; - case 2: return m_freq2; - } - return 0.f; -} - -void -RubberBandStretcher::Impl::setFrequencyCutoff(int n, float f) -{ - switch (n) { - case 0: m_freq0 = f; break; - case 1: m_freq1 = f; break; - case 2: m_freq2 = f; break; - } -} - -double -RubberBandStretcher::Impl::getEffectiveRatio() const -{ - // Returns the ratio that the internal time stretcher needs to - // achieve, not the resulting duration ratio of the output (which - // is simply m_timeRatio). - - // A frequency shift is achieved using an additional time shift, - // followed by resampling back to the original time shift to - // change the pitch. Note that the resulting frequency change is - // fixed, as it is effected by the resampler -- in contrast to - // time shifting, which is variable aiming to place the majority - // of the stretch or squash in low-interest regions of audio. - - return m_timeRatio * m_pitchScale; -} - -size_t -RubberBandStretcher::Impl::roundUp(size_t value) -{ - if (!(value & (value - 1))) return value; - int bits = 0; - while (value) { ++bits; value >>= 1; } - value = 1 << bits; - return value; -} - -void -RubberBandStretcher::Impl::calculateSizes() -{ - size_t inputIncrement = m_defaultIncrement; - size_t windowSize = m_baseWindowSize; - size_t outputIncrement; - - if (m_pitchScale <= 0.0) { - // This special case is likelier than one might hope, because - // of naive initialisations in programs that set it from a - // variable - std::cerr << "RubberBandStretcher: WARNING: Pitch scale must be greater than zero!\nResetting it from " << m_pitchScale << " to the default of 1.0: no pitch change will occur" << std::endl; - m_pitchScale = 1.0; - } - if (m_timeRatio <= 0.0) { - // Likewise - std::cerr << "RubberBandStretcher: WARNING: Time ratio must be greater than zero!\nResetting it from " << m_timeRatio << " to the default of 1.0: no time stretch will occur" << std::endl; - m_timeRatio = 1.0; - } - - double r = getEffectiveRatio(); - - if (m_realtime) { - - if (r < 1) { - - bool rsb = (m_pitchScale < 1.0 && !resampleBeforeStretching()); - float windowIncrRatio = 4.5; - if (r == 1.0) windowIncrRatio = 4; - else if (rsb) windowIncrRatio = 4.5; - else windowIncrRatio = 6; - - inputIncrement = int(windowSize / windowIncrRatio); - outputIncrement = int(floor(inputIncrement * r)); - - // Very long stretch or very low pitch shift - if (outputIncrement < m_defaultIncrement / 4) { - if (outputIncrement < 1) outputIncrement = 1; - while (outputIncrement < m_defaultIncrement / 4 && - windowSize < m_baseWindowSize * 4) { - outputIncrement *= 2; - inputIncrement = lrint(ceil(outputIncrement / r)); - windowSize = roundUp(lrint(ceil(inputIncrement * windowIncrRatio))); - } - } - - } else { - - bool rsb = (m_pitchScale > 1.0 && resampleBeforeStretching()); - float windowIncrRatio = 4.5; - if (r == 1.0) windowIncrRatio = 4; - else if (rsb) windowIncrRatio = 4.5; - else windowIncrRatio = 6; - - outputIncrement = int(windowSize / windowIncrRatio); - inputIncrement = int(outputIncrement / r); - while (outputIncrement > 1024 * m_rateMultiple && - inputIncrement > 1) { - outputIncrement /= 2; - inputIncrement = int(outputIncrement / r); - } - size_t minwin = roundUp(lrint(outputIncrement * windowIncrRatio)); - if (windowSize < minwin) windowSize = minwin; - - if (rsb) { -// cerr << "adjusting window size from " << windowSize; - size_t newWindowSize = roundUp(lrint(windowSize / m_pitchScale)); - if (newWindowSize < 512) newWindowSize = 512; - size_t div = windowSize / newWindowSize; - if (inputIncrement > div && outputIncrement > div) { - inputIncrement /= div; - outputIncrement /= div; - windowSize /= div; - } -// cerr << " to " << windowSize << " (inputIncrement = " << inputIncrement << ", outputIncrement = " << outputIncrement << ")" << endl; - } - } - - } else { - - if (r < 1) { - inputIncrement = windowSize / 4; - while (inputIncrement >= 512) inputIncrement /= 2; - outputIncrement = int(floor(inputIncrement * r)); - if (outputIncrement < 1) { - outputIncrement = 1; - inputIncrement = roundUp(lrint(ceil(outputIncrement / r))); - windowSize = inputIncrement * 4; - } - } else { - outputIncrement = windowSize / 6; - inputIncrement = int(outputIncrement / r); - while (outputIncrement > 1024 && inputIncrement > 1) { - outputIncrement /= 2; - inputIncrement = int(outputIncrement / r); - } - windowSize = std::max(windowSize, roundUp(outputIncrement * 6)); - if (r > 5) while (windowSize < 8192) windowSize *= 2; - } - } - - if (m_expectedInputDuration > 0) { - while (inputIncrement * 4 > m_expectedInputDuration && - inputIncrement > 1) { - inputIncrement /= 2; - } - } - - // windowSize can be almost anything, but it can't be greater than - // 4 * m_baseWindowSize unless ratio is less than 1/1024. - - m_windowSize = windowSize; - m_increment = inputIncrement; - - // When squashing, the greatest theoretically possible output - // increment is the input increment. When stretching adaptively - // the sky's the limit in principle, but we expect - // StretchCalculator to restrict itself to using no more than - // twice the basic output increment (i.e. input increment times - // ratio) for any chunk. - - if (m_debugLevel > 0) { - cerr << "configure: effective ratio = " << getEffectiveRatio() << endl; - cerr << "configure: window size = " << m_windowSize << ", increment = " << m_increment << " (approx output increment = " << int(lrint(m_increment * getEffectiveRatio())) << ")" << endl; - } - - if (m_windowSize > m_maxProcessSize) { - m_maxProcessSize = m_windowSize; - } - - m_outbufSize = - size_t - (ceil(max - (m_maxProcessSize / m_pitchScale, - m_windowSize * 2 * (m_timeRatio > 1.f ? m_timeRatio : 1.f)))); - - if (m_realtime) { - // This headroom is so as to try to avoid reallocation when - // the pitch scale changes - m_outbufSize = m_outbufSize * 16; - } else { - if (m_threaded) { - // This headroom is to permit the processing threads to - // run ahead of the buffer output drainage; the exact - // amount of headroom is a question of tuning rather than - // results - m_outbufSize = m_outbufSize * 16; - } - } - - if (m_debugLevel > 0) { - cerr << "configure: outbuf size = " << m_outbufSize << endl; - } -} - -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()) { - prevWindowSize = 0; - prevOutbufSize = 0; - } - - calculateSizes(); - - bool windowSizeChanged = (prevWindowSize != m_windowSize); - bool outbufSizeChanged = (prevOutbufSize != m_outbufSize); - - // This function may be called at any time in non-RT mode, after a - // parameter has changed. It shouldn't be legal to call it after - // processing has already begun. - - // This function is only called once (on construction) in RT - // mode. After that reconfigure() does the work in a hopefully - // RT-safe way. - - set<size_t> windowSizes; - if (m_realtime) { - windowSizes.insert(m_baseWindowSize); - windowSizes.insert(m_baseWindowSize / 2); - windowSizes.insert(m_baseWindowSize * 2); -// windowSizes.insert(m_baseWindowSize * 4); - } - windowSizes.insert(m_windowSize); - - if (windowSizeChanged) { - - for (set<size_t>::const_iterator i = windowSizes.begin(); - i != windowSizes.end(); ++i) { - if (m_windows.find(*i) == m_windows.end()) { - m_windows[*i] = new Window<float>(HanningWindow, *i); - } - } - m_window = m_windows[m_windowSize]; - - if (m_debugLevel > 0) { - cerr << "Window area: " << m_window->getArea() << "; synthesis window area: " << m_window->getArea() << endl; - } - } - - if (windowSizeChanged || outbufSizeChanged) { - - for (size_t c = 0; c < m_channelData.size(); ++c) { - delete m_channelData[c]; - } - m_channelData.clear(); - - for (size_t c = 0; c < m_channels; ++c) { - m_channelData.push_back - (new ChannelData(windowSizes, 1, m_windowSize, m_outbufSize)); - } - } - - if (!m_realtime && windowSizeChanged) { - delete m_studyFFT; - m_studyFFT = new FFT(m_windowSize, m_debugLevel); - m_studyFFT->initFloat(); - } - - if (m_pitchScale != 1.0 || - (m_options & OptionPitchHighConsistency) || - m_realtime) { - - for (size_t c = 0; c < m_channels; ++c) { - - if (m_channelData[c]->resampler) continue; - - m_channelData[c]->resampler = - new Resampler(Resampler::FastestTolerable, 1, 4096 * 16, - m_debugLevel); - - // rbs is the amount of buffer space we think we'll need - // for resampling; but allocate a sensible amount in case - // the pitch scale changes during use - size_t rbs = - lrintf(ceil((m_increment * m_timeRatio * 2) / m_pitchScale)); - if (rbs < m_increment * 16) rbs = m_increment * 16; - m_channelData[c]->setResampleBufSize(rbs); - } - } - - // stretchAudioCurve is unused in RT mode; phaseResetAudioCurve, - // silentAudioCurve and stretchCalculator however are used in all - // modes - - delete m_phaseResetAudioCurve; - m_phaseResetAudioCurve = new PercussiveAudioCurve - (m_sampleRate, m_windowSize); - - delete m_silentAudioCurve; - m_silentAudioCurve = new SilentAudioCurve - (m_sampleRate, m_windowSize); - - if (!m_realtime) { - delete m_stretchAudioCurve; - if (!(m_options & OptionStretchPrecise)) { - m_stretchAudioCurve = new SpectralDifferenceAudioCurve - (m_sampleRate, m_windowSize); - } else { - m_stretchAudioCurve = new ConstantAudioCurve - (m_sampleRate, m_windowSize); - } - } - - delete m_stretchCalculator; - m_stretchCalculator = new StretchCalculator - (m_sampleRate, m_increment, - !(m_options & OptionTransientsSmooth)); - - m_stretchCalculator->setDebugLevel(m_debugLevel); - m_inputDuration = 0; - - // Prepare the inbufs with half a chunk of emptiness. The centre - // point of the first processing chunk for the onset detector - // should be the first sample of the audio, and we continue until - // we can no longer centre a chunk within the input audio. The - // number of onset detector chunks will be the number of audio - // samples input, divided by the input increment, plus one. - - // In real-time mode, we don't do this prefill -- it's better to - // start with a swoosh than introduce more latency, and we don't - // want gaps when the ratio changes. - - if (!m_realtime) { - for (size_t c = 0; c < m_channels; ++c) { - m_channelData[c]->reset(); - m_channelData[c]->inbuf->zero(m_windowSize/2); - } - } -} - - -void -RubberBandStretcher::Impl::reconfigure() -{ - if (!m_realtime) { - if (m_mode == Studying) { - // stop and calculate the stretch curve so far, then reset - // the df vectors - calculateStretch(); - m_phaseResetDf.clear(); - m_stretchDf.clear(); - m_silence.clear(); - m_inputDuration = 0; - } - configure(); - } - - size_t prevWindowSize = m_windowSize; - size_t prevOutbufSize = m_outbufSize; - - calculateSizes(); - - // There are various allocations in this function, but they should - // never happen in normal use -- they just recover from the case - // where not all of the things we need were correctly created when - // we first configured (for whatever reason). This is intended to - // be "effectively" realtime safe. The same goes for - // ChannelData::setOutbufSize and setWindowSize. - - if (m_windowSize != prevWindowSize) { - - if (m_windows.find(m_windowSize) == m_windows.end()) { - std::cerr << "WARNING: reconfigure(): window allocation (size " << m_windowSize << ") required in RT mode" << std::endl; - m_windows[m_windowSize] = new Window<float>(HanningWindow, m_windowSize); - } - m_window = m_windows[m_windowSize]; - - for (size_t c = 0; c < m_channels; ++c) { - m_channelData[c]->setWindowSize(m_windowSize); - } - } - - if (m_outbufSize != prevOutbufSize) { - for (size_t c = 0; c < m_channels; ++c) { - m_channelData[c]->setOutbufSize(m_outbufSize); - } - } - - if (m_pitchScale != 1.0) { - for (size_t c = 0; c < m_channels; ++c) { - - if (m_channelData[c]->resampler) continue; - - std::cerr << "WARNING: reconfigure(): resampler construction required in RT mode" << std::endl; - - m_channelData[c]->resampler = - new Resampler(Resampler::FastestTolerable, 1, m_windowSize, - m_debugLevel); - - m_channelData[c]->setResampleBufSize - (lrintf(ceil((m_increment * m_timeRatio * 2) / m_pitchScale))); - } - } - - if (m_windowSize != prevWindowSize) { - m_phaseResetAudioCurve->setWindowSize(m_windowSize); - } -} - -size_t -RubberBandStretcher::Impl::getLatency() const -{ - if (!m_realtime) return 0; - return int((m_windowSize/2) / m_pitchScale + 1); -} - -void -RubberBandStretcher::Impl::setTransientsOption(Options options) -{ - if (!m_realtime) { - cerr << "RubberBandStretcher::Impl::setTransientsOption: Not permissible in non-realtime mode" << endl; - return; - } - int mask = (OptionTransientsMixed | OptionTransientsSmooth | OptionTransientsCrisp); - m_options &= ~mask; - options &= mask; - m_options |= options; - - m_stretchCalculator->setUseHardPeaks - (!(m_options & OptionTransientsSmooth)); -} - -void -RubberBandStretcher::Impl::setPhaseOption(Options options) -{ - int mask = (OptionPhaseLaminar | OptionPhaseIndependent); - m_options &= ~mask; - options &= mask; - m_options |= options; -} - -void -RubberBandStretcher::Impl::setFormantOption(Options options) -{ - int mask = (OptionFormantShifted | OptionFormantPreserved); - m_options &= ~mask; - options &= mask; - m_options |= options; -} - -void -RubberBandStretcher::Impl::setPitchOption(Options options) -{ - if (!m_realtime) { - cerr << "RubberBandStretcher::Impl::setPitchOption: Pitch option is not used in non-RT mode" << endl; - return; - } - - Options prior = m_options; - - int mask = (OptionPitchHighQuality | - OptionPitchHighSpeed | - OptionPitchHighConsistency); - m_options &= ~mask; - options &= mask; - m_options |= options; - - if (prior != m_options) reconfigure(); -} - -void -RubberBandStretcher::Impl::study(const float *const *input, size_t samples, bool final) -{ - Profiler profiler("RubberBandStretcher::Impl::study"); - - if (m_realtime) { - if (m_debugLevel > 1) { - cerr << "RubberBandStretcher::Impl::study: Not meaningful in realtime mode" << endl; - } - return; - } - - if (m_mode == Processing || m_mode == Finished) { - cerr << "RubberBandStretcher::Impl::study: Cannot study after processing" << endl; - return; - } - m_mode = Studying; - - size_t consumed = 0; - - ChannelData &cd = *m_channelData[0]; - RingBuffer<float> &inbuf = *cd.inbuf; - - const float *mixdown; - float *mdalloc = 0; - - if (m_channels > 1 || final) { - // mix down into a single channel for analysis - mdalloc = new float[samples]; - for (size_t i = 0; i < samples; ++i) { - if (i < samples) { - mdalloc[i] = input[0][i]; - } else { - mdalloc[i] = 0.f; - } - } - for (size_t c = 1; c < m_channels; ++c) { - for (size_t i = 0; i < samples; ++i) { - mdalloc[i] += input[c][i]; - } - } - for (size_t i = 0; i < samples; ++i) { - mdalloc[i] /= m_channels; - } - mixdown = mdalloc; - } else { - mixdown = input[0]; - } - - while (consumed < samples) { - - size_t writable = inbuf.getWriteSpace(); - writable = min(writable, samples - consumed); - - if (writable == 0) { - // warn - cerr << "WARNING: writable == 0 (consumed = " << consumed << ", samples = " << samples << ")" << endl; - } else { - inbuf.write(mixdown + consumed, writable); - consumed += writable; - } - - while ((inbuf.getReadSpace() >= int(m_windowSize)) || - (final && (inbuf.getReadSpace() >= int(m_windowSize/2)))) { - - // We know we have at least m_windowSize samples available - // in m_inbuf. We need to peek m_windowSize of them for - // processing, and then skip m_increment to advance the - // read pointer. - - // cd.accumulator is not otherwise used during studying, - // so we can use it as a temporary buffer here - -#ifdef NDEBUG - inbuf.peek(cd.accumulator, m_windowSize); -#else - size_t got = inbuf.peek(cd.accumulator, m_windowSize); -#endif - assert(final || got == m_windowSize); - - m_window->cut(cd.accumulator); - - // We don't need the fftshift for studying, as we're only - // interested in magnitude - - m_studyFFT->forwardMagnitude(cd.accumulator, cd.fltbuf); - - float df = m_phaseResetAudioCurve->process(cd.fltbuf, m_increment); - m_phaseResetDf.push_back(df); - -// cout << m_phaseResetDf.size() << " [" << final << "] -> " << df << " \t: "; - - df = m_stretchAudioCurve->process(cd.fltbuf, m_increment); - m_stretchDf.push_back(df); - - df = m_silentAudioCurve->process(cd.fltbuf, m_increment); - bool silent = (df > 0.f); - if (silent && m_debugLevel > 1) { - cerr << "silence found at " << m_inputDuration << endl; - } - m_silence.push_back(silent); - -// cout << df << endl; - - // We have augmented the input by m_windowSize/2 so - // that the first chunk is centred on the first audio - // sample. We want to ensure that m_inputDuration - // contains the exact input duration without including - // this extra bit. We just add up all the increments - // here, and deduct the extra afterwards. - - m_inputDuration += m_increment; -// cerr << "incr input duration by increment: " << m_increment << " -> " << m_inputDuration << endl; - inbuf.skip(m_increment); - } - } - - if (final) { - int rs = inbuf.getReadSpace(); - m_inputDuration += rs; -// cerr << "incr input duration by read space: " << rs << " -> " << m_inputDuration << endl; - - if (m_inputDuration > m_windowSize/2) { // deducting the extra - m_inputDuration -= m_windowSize/2; - } - } - - if (m_channels > 1) delete[] mdalloc; -} - -vector<int> -RubberBandStretcher::Impl::getOutputIncrements() const -{ - if (!m_realtime) { - return m_outputIncrements; - } else { - vector<int> increments; - while (m_lastProcessOutputIncrements.getReadSpace() > 0) { - increments.push_back(m_lastProcessOutputIncrements.readOne()); - } - return increments; - } -} - -vector<float> -RubberBandStretcher::Impl::getPhaseResetCurve() const -{ - if (!m_realtime) { - return m_phaseResetDf; - } else { - vector<float> df; - while (m_lastProcessPhaseResetDf.getReadSpace() > 0) { - df.push_back(m_lastProcessPhaseResetDf.readOne()); - } - return df; - } -} - -vector<int> -RubberBandStretcher::Impl::getExactTimePoints() const -{ - std::vector<int> points; - if (!m_realtime) { - std::vector<StretchCalculator::Peak> peaks = - m_stretchCalculator->getLastCalculatedPeaks(); - for (size_t i = 0; i < peaks.size(); ++i) { - points.push_back(peaks[i].chunk); - } - } - return points; -} - -void -RubberBandStretcher::Impl::calculateStretch() -{ - Profiler profiler("RubberBandStretcher::Impl::calculateStretch"); - - size_t inputDuration = m_inputDuration; - - if (!m_realtime && m_expectedInputDuration > 0) { - if (m_expectedInputDuration != inputDuration) { - std::cerr << "RubberBandStretcher: WARNING: Actual study() duration differs from duration set by setExpectedInputDuration (" << m_inputDuration << " vs " << m_expectedInputDuration << ", diff = " << (m_expectedInputDuration - m_inputDuration) << "), using the latter for calculation" << std::endl; - inputDuration = m_expectedInputDuration; - } - } - - std::vector<int> increments = m_stretchCalculator->calculate - (getEffectiveRatio(), - inputDuration, - m_phaseResetDf, - m_stretchDf); - - int history = 0; - for (size_t i = 0; i < increments.size(); ++i) { - if (i >= m_silence.size()) break; - if (m_silence[i]) ++history; - else history = 0; - if (history >= int(m_windowSize / m_increment) && increments[i] >= 0) { - increments[i] = -increments[i]; - if (m_debugLevel > 1) { - std::cerr << "phase reset on silence (silent history == " - << history << ")" << std::endl; - } - } - } - - if (m_outputIncrements.empty()) m_outputIncrements = increments; - else { - for (size_t i = 0; i < increments.size(); ++i) { - m_outputIncrements.push_back(increments[i]); - } - } - - return; -} - -void -RubberBandStretcher::Impl::setDebugLevel(int level) -{ - m_debugLevel = level; - if (m_stretchCalculator) m_stretchCalculator->setDebugLevel(level); -} - -size_t -RubberBandStretcher::Impl::getSamplesRequired() const -{ - Profiler profiler("RubberBandStretcher::Impl::getSamplesRequired"); - - size_t reqd = 0; - - for (size_t c = 0; c < m_channels; ++c) { - - size_t reqdHere = 0; - - ChannelData &cd = *m_channelData[c]; - RingBuffer<float> &inbuf = *cd.inbuf; - - size_t rs = inbuf.getReadSpace(); - - // See notes in testInbufReadSpace - - if (rs < m_windowSize && !cd.draining) { - - if (cd.inputSize == -1) { - reqdHere = m_windowSize - rs; - if (reqdHere > reqd) reqd = reqdHere; - continue; - } - - if (rs == 0) { - reqdHere = m_windowSize; - if (reqdHere > reqd) reqd = reqdHere; - continue; - } - } - } - - return reqd; -} - -void -RubberBandStretcher::Impl::process(const float *const *input, size_t samples, bool final) -{ - Profiler profiler("RubberBandStretcher::Impl::process"); - - if (m_mode == Finished) { - cerr << "RubberBandStretcher::Impl::process: Cannot process again after final chunk" << endl; - return; - } - - if (m_mode == JustCreated || m_mode == Studying) { - - if (m_mode == Studying) { - calculateStretch(); - } - - for (size_t c = 0; c < m_channels; ++c) { - m_channelData[c]->reset(); - m_channelData[c]->inbuf->zero(m_windowSize/2); - } - - if (m_threaded) { - MutexLocker locker(&m_threadSetMutex); - - for (size_t c = 0; c < m_channels; ++c) { - ProcessThread *thread = new ProcessThread(this, c); - m_threadSet.insert(thread); - thread->start(); - } - - if (m_debugLevel > 0) { - cerr << m_channels << " threads created" << endl; - } - } - - m_mode = Processing; - } - - bool allConsumed = false; - - size_t *consumed = (size_t *)alloca(m_channels * sizeof(size_t)); - for (size_t c = 0; c < m_channels; ++c) { - consumed[c] = 0; - } - - while (!allConsumed) { - -//#ifndef NO_THREADING -// if (m_threaded) { -// pthread_mutex_lock(&m_inputProcessedMutex); -// } -//#endif - - // In a threaded mode, our "consumed" counters only indicate - // the number of samples that have been taken into the input - // ring buffers waiting to be processed by the process thread. - // In non-threaded mode, "consumed" counts the number that - // have actually been processed. - - allConsumed = true; - - for (size_t c = 0; c < m_channels; ++c) { - consumed[c] += consumeChannel(c, - input[c] + consumed[c], - samples - consumed[c], - final); - if (consumed[c] < samples) { - allConsumed = false; -// cerr << "process: waiting on input consumption for channel " << c << endl; - } else { - if (final) { - m_channelData[c]->inputSize = m_channelData[c]->inCount; - } -// cerr << "process: happy with channel " << c << endl; - } - if (!m_threaded && !m_realtime) { - bool any = false, last = false; - processChunks(c, any, last); - } - } - - if (m_realtime) { - // When running in real time, we need to process both - // channels in step because we will need to use the sum of - // their frequency domain representations as the input to - // the realtime onset detector - processOneChunk(); - } - - if (m_threaded) { - for (ThreadSet::iterator i = m_threadSet.begin(); - i != m_threadSet.end(); ++i) { - (*i)->signalDataAvailable(); - } - if (!allConsumed) { - m_spaceAvailable.wait(500); - } -/* - } else { - if (!allConsumed) { - cerr << "RubberBandStretcher::Impl::process: ERROR: Too much data provided to process() call -- either call setMaxProcessSize() beforehand, or provide only getSamplesRequired() frames at a time" << endl; - for (size_t c = 0; c < m_channels; ++c) { - cerr << "channel " << c << ": " << samples << " provided, " << consumed[c] << " consumed" << endl; - } -// break; - } -*/ - } - -// if (!allConsumed) cerr << "process looping" << endl; - - } - -// cerr << "process returning" << endl; - - if (final) m_mode = Finished; -} - - -} - diff --git a/libs/rubberband/src/StretcherImpl.h b/libs/rubberband/src/StretcherImpl.h deleted file mode 100644 index 996c61b7ef..0000000000 --- a/libs/rubberband/src/StretcherImpl.h +++ /dev/null @@ -1,202 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#ifndef _RUBBERBAND_STRETCHERIMPL_H_ -#define _RUBBERBAND_STRETCHERIMPL_H_ - -#include "RubberBandStretcher.h" - -#include "Window.h" -#include "Thread.h" -#include "RingBuffer.h" -#include "FFT.h" -#include "sysutils.h" - -#include <set> - -namespace RubberBand -{ - -class AudioCurve; -class StretchCalculator; - -class RubberBandStretcher::Impl -{ -public: - Impl(size_t sampleRate, size_t channels, Options options, - double initialTimeRatio, double initialPitchScale); - ~Impl(); - - void reset(); - void setTimeRatio(double ratio); - void setPitchScale(double scale); - - double getTimeRatio() const; - double getPitchScale() const; - - size_t getLatency() const; - - void setTransientsOption(Options); - void setPhaseOption(Options); - void setFormantOption(Options); - void setPitchOption(Options); - - void setExpectedInputDuration(size_t samples); - void setMaxProcessSize(size_t samples); - - size_t getSamplesRequired() const; - - void study(const float *const *input, size_t samples, bool final); - void process(const float *const *input, size_t samples, bool final); - - int available() const; - size_t retrieve(float *const *output, size_t samples) const; - - float getFrequencyCutoff(int n) const; - void setFrequencyCutoff(int n, float f); - - size_t getInputIncrement() const { - return m_increment; - } - - std::vector<int> getOutputIncrements() const; - std::vector<float> getPhaseResetCurve() const; - std::vector<int> getExactTimePoints() const; - - size_t getChannelCount() const { - return m_channels; - } - - void calculateStretch(); - - void setDebugLevel(int level); - static void setDefaultDebugLevel(int level) { m_defaultDebugLevel = level; } - -protected: - size_t m_sampleRate; - size_t m_channels; - - size_t consumeChannel(size_t channel, const float *input, - size_t samples, bool final); - void processChunks(size_t channel, bool &any, bool &last); - bool processOneChunk(); // across all channels, for real time use - bool processChunkForChannel(size_t channel, size_t phaseIncrement, - size_t shiftIncrement, bool phaseReset); - bool testInbufReadSpace(size_t channel); - void calculateIncrements(size_t &phaseIncrement, - size_t &shiftIncrement, bool &phaseReset); - bool getIncrements(size_t channel, size_t &phaseIncrement, - size_t &shiftIncrement, bool &phaseReset); - void analyseChunk(size_t channel); - void modifyChunk(size_t channel, size_t outputIncrement, bool phaseReset); - void formantShiftChunk(size_t channel); - void synthesiseChunk(size_t channel); - void writeChunk(size_t channel, size_t shiftIncrement, bool last); - - void calculateSizes(); - void configure(); - void reconfigure(); - - double getEffectiveRatio() const; - - size_t roundUp(size_t value); // to next power of two - - bool resampleBeforeStretching() const; - - double m_timeRatio; - double m_pitchScale; - - size_t m_windowSize; - size_t m_increment; - size_t m_outbufSize; - - size_t m_maxProcessSize; - size_t m_expectedInputDuration; - - bool m_threaded; - bool m_realtime; - Options m_options; - int m_debugLevel; - - enum ProcessMode { - JustCreated, - Studying, - Processing, - Finished - }; - - ProcessMode m_mode; - - std::map<size_t, Window<float> *> m_windows; - Window<float> *m_window; - FFT *m_studyFFT; - - Condition m_spaceAvailable; - - class ProcessThread : public Thread - { - public: - 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; - typedef std::set<ProcessThread *> ThreadSet; - ThreadSet m_threadSet; - - - size_t m_inputDuration; - std::vector<float> m_phaseResetDf; - std::vector<float> m_stretchDf; - std::vector<bool> m_silence; - int m_silentHistory; - - class ChannelData; - std::vector<ChannelData *> m_channelData; - - std::vector<int> m_outputIncrements; - - mutable RingBuffer<int> m_lastProcessOutputIncrements; - mutable RingBuffer<float> m_lastProcessPhaseResetDf; - - AudioCurve *m_phaseResetAudioCurve; - AudioCurve *m_stretchAudioCurve; - AudioCurve *m_silentAudioCurve; - StretchCalculator *m_stretchCalculator; - - float m_freq0; - float m_freq1; - float m_freq2; - - size_t m_baseWindowSize; - float m_rateMultiple; - - void writeOutput(RingBuffer<float> &to, float *from, - size_t qty, size_t &outCount, size_t theoreticalOut); - - static int m_defaultDebugLevel; - static const size_t m_defaultIncrement; - static const size_t m_defaultWindowSize; -}; - -} - -#endif diff --git a/libs/rubberband/src/StretcherProcess.cpp b/libs/rubberband/src/StretcherProcess.cpp deleted file mode 100644 index 3b832e09e1..0000000000 --- a/libs/rubberband/src/StretcherProcess.cpp +++ /dev/null @@ -1,1177 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#include "StretcherImpl.h" -#include "PercussiveAudioCurve.h" -#include "HighFrequencyAudioCurve.h" -#include "ConstantAudioCurve.h" -#include "StretchCalculator.h" -#include "StretcherChannelData.h" -#include "Resampler.h" -#include "Profiler.h" - -#include <cstring> -#include <cassert> -#include <cmath> -#include <set> -#include <map> -#include <deque> - - -using std::cerr; -using std::endl; - -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_abandoning(false) -{ } - -void -RubberBandStretcher::Impl::ProcessThread::run() -{ - if (m_s->m_debugLevel > 1) { - cerr << "thread " << m_channel << " getting going" << endl; - } - - ChannelData &cd = *m_s->m_channelData[m_channel]; - - while (cd.inputSize == -1 || - cd.inbuf->getReadSpace() > 0) { - -// if (cd.inputSize != -1) { -// cerr << "inputSize == " << cd.inputSize -// << ", readSpace == " << cd.inbuf->getReadSpace() << endl; -// } - - bool any = false, last = false; - m_s->processChunks(m_channel, any, last); - - if (last) break; - - if (any) m_s->m_spaceAvailable.signal(); - - m_dataAvailable.lock(); - if (!m_s->testInbufReadSpace(m_channel) && !m_abandoning) { - m_dataAvailable.wait(50000); // bounded in case of abandonment - } 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; - m_s->processChunks(m_channel, any, last); - m_s->m_spaceAvailable.signal(); - - if (m_s->m_debugLevel > 1) { - cerr << "thread " << m_channel << " done" << endl; - } -} - -void -RubberBandStretcher::Impl::ProcessThread::signalDataAvailable() -{ - m_dataAvailable.signal(); -} - -void -RubberBandStretcher::Impl::ProcessThread::abandon() -{ - m_abandoning = true; -} - -bool -RubberBandStretcher::Impl::resampleBeforeStretching() const -{ - // We can't resample before stretching in offline mode, because - // the stretch calculation is based on doing it the other way - // around. It would take more work (and testing) to enable this. - if (!m_realtime) return false; - - if (m_options & OptionPitchHighQuality) { - return (m_pitchScale < 1.0); // better sound - } else if (m_options & OptionPitchHighConsistency) { - return false; - } else { - return (m_pitchScale > 1.0); // better performance - } -} - -size_t -RubberBandStretcher::Impl::consumeChannel(size_t c, const float *input, - size_t samples, bool final) -{ - Profiler profiler("RubberBandStretcher::Impl::consumeChannel"); - - ChannelData &cd = *m_channelData[c]; - RingBuffer<float> &inbuf = *cd.inbuf; - - size_t toWrite = samples; - size_t writable = inbuf.getWriteSpace(); - - bool resampling = resampleBeforeStretching(); - - if (resampling) { - - toWrite = int(ceil(samples / m_pitchScale)); - if (writable < toWrite) { - samples = int(floor(writable * m_pitchScale)); - if (samples == 0) return 0; - } - - size_t reqSize = int(ceil(samples / m_pitchScale)); - if (reqSize > cd.resamplebufSize) { - cerr << "WARNING: RubberBandStretcher::Impl::consumeChannel: resizing resampler buffer from " - << cd.resamplebufSize << " to " << reqSize << endl; - cd.setResampleBufSize(reqSize); - } - - - toWrite = cd.resampler->resample(&input, - &cd.resamplebuf, - samples, - 1.0 / m_pitchScale, - final); - - } - - if (writable < toWrite) { - if (resampling) { - return 0; - } - toWrite = writable; - } - - if (resampling) { - inbuf.write(cd.resamplebuf, toWrite); - cd.inCount += samples; - return samples; - } else { - inbuf.write(input, toWrite); - cd.inCount += toWrite; - return toWrite; - } -} - -void -RubberBandStretcher::Impl::processChunks(size_t c, bool &any, bool &last) -{ - Profiler profiler("RubberBandStretcher::Impl::processChunks"); - - // Process as many chunks as there are available on the input - // buffer for channel c. This requires that the increments have - // already been calculated. - - ChannelData &cd = *m_channelData[c]; - - last = false; - any = false; - - while (!last) { - - if (!testInbufReadSpace(c)) { -// cerr << "not enough input" << endl; - break; - } - - any = true; - - if (!cd.draining) { - size_t got = cd.inbuf->peek(cd.fltbuf, m_windowSize); - assert(got == m_windowSize || cd.inputSize >= 0); - got = 0; - cd.inbuf->skip(m_increment); - analyseChunk(c); - } - - bool phaseReset = false; - size_t phaseIncrement, shiftIncrement; - getIncrements(c, phaseIncrement, shiftIncrement, phaseReset); - - last = processChunkForChannel(c, phaseIncrement, shiftIncrement, phaseReset); - cd.chunkCount++; - if (m_debugLevel > 2) { - cerr << "channel " << c << ": last = " << last << ", chunkCount = " << cd.chunkCount << endl; - } - } -} - -bool -RubberBandStretcher::Impl::processOneChunk() -{ - Profiler profiler("RubberBandStretcher::Impl::processOneChunk"); - - // Process a single chunk for all channels, provided there is - // enough data on each channel for at least one chunk. This is - // able to calculate increments as it goes along. - - for (size_t c = 0; c < m_channels; ++c) { - if (!testInbufReadSpace(c)) return false; - ChannelData &cd = *m_channelData[c]; - if (!cd.draining) { - size_t got = cd.inbuf->peek(cd.fltbuf, m_windowSize); - got = 0; - assert(got == m_windowSize || cd.inputSize >= 0); - cd.inbuf->skip(m_increment); - analyseChunk(c); - } - } - - bool phaseReset = false; - size_t phaseIncrement, shiftIncrement; - if (!getIncrements(0, phaseIncrement, shiftIncrement, phaseReset)) { - calculateIncrements(phaseIncrement, shiftIncrement, phaseReset); - } - - bool last = false; - for (size_t c = 0; c < m_channels; ++c) { - last = processChunkForChannel(c, phaseIncrement, shiftIncrement, phaseReset); - m_channelData[c]->chunkCount++; - } - - return last; -} - -bool -RubberBandStretcher::Impl::testInbufReadSpace(size_t c) -{ - Profiler profiler("RubberBandStretcher::Impl::testInbufReadSpace"); - - ChannelData &cd = *m_channelData[c]; - RingBuffer<float> &inbuf = *cd.inbuf; - - size_t rs = inbuf.getReadSpace(); - - if (rs < m_windowSize && !cd.draining) { - - if (cd.inputSize == -1) { - - // Not all the input data has been written to the inbuf - // (that's why the input size is not yet set). We can't - // process, because we don't have a full chunk of data, so - // our process chunk would contain some empty padding in - // its input -- and that would give incorrect output, as - // we know there is more input to come. - - if (!m_threaded) { -// cerr << "WARNING: RubberBandStretcher: read space < chunk size (" -// << inbuf.getReadSpace() << " < " << m_windowSize -// << ") when not all input written, on processChunks for channel " << c << endl; - } - return false; - } - - if (rs == 0) { - - if (m_debugLevel > 1) { - cerr << "read space = 0, giving up" << endl; - } - return false; - - } else if (rs < m_windowSize/2) { - - if (m_debugLevel > 1) { - cerr << "read space = " << rs << ", setting draining true" << endl; - } - - cd.draining = true; - } - } - - return true; -} - -bool -RubberBandStretcher::Impl::processChunkForChannel(size_t c, - size_t phaseIncrement, - size_t shiftIncrement, - bool phaseReset) -{ - Profiler profiler("RubberBandStretcher::Impl::processChunkForChannel"); - - // Process a single chunk on a single channel. This assumes - // enough input data is available; caller must have tested this - // using e.g. testInbufReadSpace first. Return true if this is - // the last chunk on the channel. - - if (phaseReset && (m_debugLevel > 1)) { - cerr << "processChunkForChannel: phase reset found, incrs " - << phaseIncrement << ":" << shiftIncrement << endl; - } - - ChannelData &cd = *m_channelData[c]; - - if (!cd.draining) { - - // This is the normal processing case -- draining is only - // set when all the input has been used and we only need - // to write from the existing accumulator into the output. - - // We know we have enough samples available in m_inbuf -- - // this is usually m_windowSize, but we know that if fewer - // are available, it's OK to use zeroes for the rest - // (which the ring buffer will provide) because we've - // reached the true end of the data. - - // We need to peek m_windowSize samples for processing, and - // then skip m_increment to advance the read pointer. - - modifyChunk(c, phaseIncrement, phaseReset); - synthesiseChunk(c); // reads from cd.mag, cd.phase - - if (m_debugLevel > 2) { - if (phaseReset) { - for (int i = 0; i < 10; ++i) { - cd.accumulator[i] = 1.2f - (i % 3) * 1.2f; - } - } - } - } - - bool last = false; - - if (cd.draining) { - if (m_debugLevel > 1) { - cerr << "draining: accumulator fill = " << cd.accumulatorFill << " (shiftIncrement = " << shiftIncrement << ")" << endl; - } - if (shiftIncrement == 0) { - cerr << "WARNING: draining: shiftIncrement == 0, can't handle that in this context: setting to " << m_increment << endl; - shiftIncrement = m_increment; - } - if (cd.accumulatorFill <= shiftIncrement) { - if (m_debugLevel > 1) { - cerr << "reducing shift increment from " << shiftIncrement - << " to " << cd.accumulatorFill - << " and marking as last" << endl; - } - shiftIncrement = cd.accumulatorFill; - last = true; - } - } - - if (m_threaded) { - - int required = shiftIncrement; - - if (m_pitchScale != 1.0) { - required = int(required / m_pitchScale) + 1; - } - - if (cd.outbuf->getWriteSpace() < required) { - if (m_debugLevel > 0) { - cerr << "Buffer overrun on output for channel " << c << endl; - } - - //!!! The only correct thing we can do here is resize the - // buffer. We can't wait for the client thread to read - // some data out from the buffer so as to make more space, - // because the client thread is probably stuck in a - // process() call waiting for us to stow away enough input - // increments to allow the process() call to complete. - - } - } - - writeChunk(c, shiftIncrement, last); - return last; -} - -void -RubberBandStretcher::Impl::calculateIncrements(size_t &phaseIncrementRtn, - size_t &shiftIncrementRtn, - bool &phaseReset) -{ - Profiler profiler("RubberBandStretcher::Impl::calculateIncrements"); - -// cerr << "calculateIncrements" << endl; - - // Calculate the next upcoming phase and shift increment, on the - // basis that both channels are in sync. This is in contrast to - // getIncrements, which requires that all the increments have been - // calculated in advance but can then return increments - // corresponding to different chunks in different channels. - - // Requires frequency domain representations of channel data in - // the mag and phase buffers in the channel. - - // This function is only used in real-time mode. - - phaseIncrementRtn = m_increment; - shiftIncrementRtn = m_increment; - phaseReset = false; - - if (m_channels == 0) return; - - ChannelData &cd = *m_channelData[0]; - - size_t bc = cd.chunkCount; - for (size_t c = 1; c < m_channels; ++c) { - if (m_channelData[c]->chunkCount != bc) { - cerr << "ERROR: RubberBandStretcher::Impl::calculateIncrements: Channels are not in sync" << endl; - return; - } - } - - const int hs = m_windowSize/2 + 1; - - // Normally we would mix down the time-domain signal and apply a - // single FFT, or else mix down the Cartesian form of the - // frequency-domain signal. Both of those would be inefficient - // from this position. Fortunately, the onset detectors should - // work reasonably well (maybe even better?) if we just sum the - // magnitudes of the frequency-domain channel signals and forget - // about phase entirely. Normally we don't expect the channel - // phases to cancel each other, and broadband effects will still - // be apparent. - - float df = 0.f; - bool silent = false; - - if (m_channels == 1) { - - df = m_phaseResetAudioCurve->processDouble(cd.mag, m_increment); - silent = (m_silentAudioCurve->processDouble(cd.mag, m_increment) > 0.f); - - } else { - - double *tmp = (double *)alloca(hs * sizeof(double)); - - for (int i = 0; i < hs; ++i) { - tmp[i] = 0.0; - } - for (size_t c = 0; c < m_channels; ++c) { - for (int i = 0; i < hs; ++i) { - tmp[i] += m_channelData[c]->mag[i]; - } - } - - df = m_phaseResetAudioCurve->processDouble(tmp, m_increment); - silent = (m_silentAudioCurve->processDouble(tmp, m_increment) > 0.f); - } - - int incr = m_stretchCalculator->calculateSingle - (getEffectiveRatio(), df, m_increment); - - m_lastProcessPhaseResetDf.write(&df, 1); - m_lastProcessOutputIncrements.write(&incr, 1); - - if (incr < 0) { - phaseReset = true; - incr = -incr; - } - - // The returned increment is the phase increment. The shift - // increment for one chunk is the same as the phase increment for - // the following chunk (see comment below). This means we don't - // actually know the shift increment until we see the following - // phase increment... which is a bit of a problem. - - // This implies we should use this increment for the shift - // increment, and make the following phase increment the same as - // it. This means in RT mode we'll be one chunk later with our - // phase reset than we would be in non-RT mode. The sensitivity - // of the broadband onset detector may mean that this isn't a - // problem -- test it and see. - - shiftIncrementRtn = incr; - - if (cd.prevIncrement == 0) { - phaseIncrementRtn = shiftIncrementRtn; - } else { - phaseIncrementRtn = cd.prevIncrement; - } - - cd.prevIncrement = shiftIncrementRtn; - - if (silent) ++m_silentHistory; - else m_silentHistory = 0; - - if (m_silentHistory >= int(m_windowSize / m_increment) && !phaseReset) { - phaseReset = true; - if (m_debugLevel > 1) { - cerr << "calculateIncrements: phase reset on silence (silent history == " - << m_silentHistory << ")" << endl; - } - } -} - -bool -RubberBandStretcher::Impl::getIncrements(size_t channel, - size_t &phaseIncrementRtn, - size_t &shiftIncrementRtn, - bool &phaseReset) -{ - Profiler profiler("RubberBandStretcher::Impl::getIncrements"); - - if (channel >= m_channels) { - phaseIncrementRtn = m_increment; - shiftIncrementRtn = m_increment; - phaseReset = false; - return false; - } - - // There are two relevant output increments here. The first is - // the phase increment which we use when recalculating the phases - // for the current chunk; the second is the shift increment used - // to determine how far to shift the processing buffer after - // writing the chunk. The shift increment for one chunk is the - // same as the phase increment for the following chunk. - - // When an onset occurs for which we need to reset phases, the - // increment given will be negative. - - // When we reset phases, the previous shift increment (and so - // current phase increments) must have been m_increment to ensure - // consistency. - - // m_outputIncrements stores phase increments. - - ChannelData &cd = *m_channelData[channel]; - bool gotData = true; - - if (cd.chunkCount >= m_outputIncrements.size()) { -// cerr << "WARNING: RubberBandStretcher::Impl::getIncrements:" -// << " chunk count " << cd.chunkCount << " >= " -// << m_outputIncrements.size() << endl; - if (m_outputIncrements.size() == 0) { - phaseIncrementRtn = m_increment; - shiftIncrementRtn = m_increment; - phaseReset = false; - return false; - } else { - cd.chunkCount = m_outputIncrements.size()-1; - gotData = false; - } - } - - int phaseIncrement = m_outputIncrements[cd.chunkCount]; - - int shiftIncrement = phaseIncrement; - if (cd.chunkCount + 1 < m_outputIncrements.size()) { - shiftIncrement = m_outputIncrements[cd.chunkCount + 1]; - } - - if (phaseIncrement < 0) { - phaseIncrement = -phaseIncrement; - phaseReset = true; - } - - if (shiftIncrement < 0) { - shiftIncrement = -shiftIncrement; - } - - if (shiftIncrement >= int(m_windowSize)) { - cerr << "*** ERROR: RubberBandStretcher::Impl::processChunks: shiftIncrement " << shiftIncrement << " >= windowSize " << m_windowSize << " at " << cd.chunkCount << " (of " << m_outputIncrements.size() << ")" << endl; - shiftIncrement = m_windowSize; - } - - phaseIncrementRtn = phaseIncrement; - shiftIncrementRtn = shiftIncrement; - if (cd.chunkCount == 0) phaseReset = true; // don't mess with the first chunk - return gotData; -} - -void -RubberBandStretcher::Impl::analyseChunk(size_t channel) -{ - Profiler profiler("RubberBandStretcher::Impl::analyseChunk"); - - int i; - - ChannelData &cd = *m_channelData[channel]; - - double *const R__ dblbuf = cd.dblbuf; - float *const R__ fltbuf = cd.fltbuf; - - int sz = m_windowSize; - int hs = m_windowSize/2; - - // cd.fltbuf is known to contain m_windowSize samples - - m_window->cut(fltbuf); - - if (cd.oversample > 1) { - - 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 { - for (i = 0; i < hs; ++i) { - dblbuf[i] = fltbuf[i + hs]; - dblbuf[i + hs] = fltbuf[i]; - } - } - - cd.fft->forwardPolar(dblbuf, cd.mag, cd.phase); -} - -static inline double mod(double x, double y) { return x - (y * floor(x / y)); } -static inline double princarg(double a) { return mod(a + M_PI, -2.0 * M_PI) + M_PI; } - -void -RubberBandStretcher::Impl::modifyChunk(size_t channel, - size_t outputIncrement, - bool phaseReset) -{ - Profiler profiler("RubberBandStretcher::Impl::modifyChunk"); - - ChannelData &cd = *m_channelData[channel]; - - if (phaseReset && m_debugLevel > 1) { - cerr << "phase reset: leaving phases unmodified" << endl; - } - - const double rate = m_sampleRate; - const int sz = m_windowSize; - const int count = (sz * cd.oversample) / 2; - - bool unchanged = cd.unchanged && (outputIncrement == m_increment); - bool fullReset = phaseReset; - bool laminar = !(m_options & OptionPhaseIndependent); - bool bandlimited = (m_options & OptionTransientsMixed); - int bandlow = lrint((150 * sz * cd.oversample) / rate); - int bandhigh = lrint((1000 * sz * cd.oversample) / rate); - - float freq0 = m_freq0; - float freq1 = m_freq1; - float freq2 = m_freq2; - - if (laminar) { - float r = getEffectiveRatio(); - if (r > 1) { - float rf0 = 600 + (600 * ((r-1)*(r-1)*(r-1)*2)); - float f1ratio = freq1 / freq0; - float f2ratio = freq2 / freq0; - freq0 = std::max(freq0, rf0); - freq1 = freq0 * f1ratio; - freq2 = freq0 * f2ratio; - } - } - - int limit0 = lrint((freq0 * sz * cd.oversample) / rate); - int limit1 = lrint((freq1 * sz * cd.oversample) / rate); - int limit2 = lrint((freq2 * sz * cd.oversample) / rate); - - if (limit1 < limit0) limit1 = limit0; - if (limit2 < limit1) limit2 = limit1; - - double prevInstability = 0.0; - bool prevDirection = false; - - double distance = 0.0; - const double maxdist = 8.0; - - const int lookback = 1; - - double distacc = 0.0; - - for (int i = count; i >= 0; i -= lookback) { - - bool resetThis = phaseReset; - - if (bandlimited) { - if (resetThis) { - if (i > bandlow && i < bandhigh) { - resetThis = false; - fullReset = false; - } - } - } - - double p = cd.phase[i]; - double perr = 0.0; - double outphase = p; - - double mi = maxdist; - if (i <= limit0) mi = 0.0; - else if (i <= limit1) mi = 1.0; - else if (i <= limit2) mi = 3.0; - - if (!resetThis) { - - double omega = (2 * M_PI * m_increment * i) / (sz * cd.oversample); - - double pp = cd.prevPhase[i]; - double ep = pp + omega; - perr = princarg(p - ep); - - double instability = fabs(perr - cd.prevError[i]); - bool direction = (perr > cd.prevError[i]); - - bool inherit = false; - - if (laminar) { - if (distance >= mi || i == count) { - inherit = false; - } else if (bandlimited && (i == bandhigh || i == bandlow)) { - inherit = false; - } else if (instability > prevInstability && - direction == prevDirection) { - inherit = true; - } - } - - double advance = outputIncrement * ((omega + perr) / m_increment); - - if (inherit) { - double inherited = - cd.unwrappedPhase[i + lookback] - cd.prevPhase[i + lookback]; - advance = ((advance * distance) + - (inherited * (maxdist - distance))) - / maxdist; - outphase = p + advance; - distacc += distance; - distance += 1.0; - } else { - outphase = cd.unwrappedPhase[i] + advance; - distance = 0.0; - } - - prevInstability = instability; - prevDirection = direction; - - } else { - distance = 0.0; - } - - cd.prevError[i] = perr; - cd.prevPhase[i] = p; - cd.phase[i] = outphase; - cd.unwrappedPhase[i] = outphase; - } - - if (m_debugLevel > 1) { - cerr << "mean inheritance distance = " << distacc / count << endl; - } - - if (fullReset) unchanged = true; - cd.unchanged = unchanged; - - if (unchanged && m_debugLevel > 1) { - cerr << "frame unchanged on channel " << channel << endl; - } -} - - -void -RubberBandStretcher::Impl::formantShiftChunk(size_t channel) -{ - Profiler profiler("RubberBandStretcher::Impl::formantShiftChunk"); - - ChannelData &cd = *m_channelData[channel]; - - double *const R__ mag = cd.mag; - double *const R__ envelope = cd.envelope; - double *const R__ dblbuf = cd.dblbuf; - - const int sz = m_windowSize; - const int hs = m_windowSize/2; - const double denom = sz; - - - cd.fft->inverseCepstral(mag, dblbuf); - - for (int i = 0; i < sz; ++i) { - dblbuf[i] /= denom; - } - - const int cutoff = m_sampleRate / 700; - -// cerr <<"cutoff = "<< cutoff << ", m_sampleRate/cutoff = " << m_sampleRate/cutoff << endl; - - dblbuf[0] /= 2; - dblbuf[cutoff-1] /= 2; - - for (int i = cutoff; i < sz; ++i) { - dblbuf[i] = 0.0; - } - - cd.fft->forward(dblbuf, envelope, 0); - - - for (int i = 0; i <= hs; ++i) { - envelope[i] = exp(envelope[i]); - } - for (int i = 0; i <= hs; ++i) { - mag[i] /= envelope[i]; - } - - if (m_pitchScale > 1.0) { - // scaling up, we want a new envelope that is lower by the pitch factor - for (int target = 0; target <= hs; ++target) { - int source = lrint(target * m_pitchScale); - if (source > int(m_windowSize)) { - envelope[target] = 0.0; - } else { - envelope[target] = envelope[source]; - } - } - } else { - // scaling down, we want a new envelope that is higher by the pitch factor - for (int target = hs; target > 0; ) { - --target; - int source = lrint(target * m_pitchScale); - envelope[target] = envelope[source]; - } - } - - for (int i = 0; i <= hs; ++i) { - mag[i] *= envelope[i]; - } - - cd.unchanged = false; -} - -void -RubberBandStretcher::Impl::synthesiseChunk(size_t channel) -{ - Profiler profiler("RubberBandStretcher::Impl::synthesiseChunk"); - - - if ((m_options & OptionFormantPreserved) && - (m_pitchScale != 1.0)) { - formantShiftChunk(channel); - } - - ChannelData &cd = *m_channelData[channel]; - - double *const R__ dblbuf = cd.dblbuf; - float *const R__ fltbuf = cd.fltbuf; - float *const R__ accumulator = cd.accumulator; - float *const R__ windowAccumulator = cd.windowAccumulator; - - int sz = m_windowSize; - int hs = m_windowSize/2; - int i; - - - if (!cd.unchanged) { - - cd.fft->inversePolar(cd.mag, cd.phase, cd.dblbuf); - - if (cd.oversample > 1) { - - int bufsiz = sz * cd.oversample; - 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 { - for (i = 0; i < hs; ++i) { - fltbuf[i] = float(dblbuf[i + hs]); - } - for (i = 0; i < hs; ++i) { - fltbuf[i + hs] = float(dblbuf[i]); - } - } - - float denom = float(sz * cd.oversample); - - // our ffts produced unscaled results - for (i = 0; i < sz; ++i) { - fltbuf[i] = fltbuf[i] / denom; - } - } - - m_window->cut(fltbuf); - - for (i = 0; i < sz; ++i) { - accumulator[i] += fltbuf[i]; - } - - cd.accumulatorFill = m_windowSize; - - float fixed = m_window->getArea() * 1.5f; - - for (i = 0; i < sz; ++i) { - float val = m_window->getValue(i); - windowAccumulator[i] += val * fixed; - } -} - -void -RubberBandStretcher::Impl::writeChunk(size_t channel, size_t shiftIncrement, bool last) -{ - Profiler profiler("RubberBandStretcher::Impl::writeChunk"); - - ChannelData &cd = *m_channelData[channel]; - - float *const R__ accumulator = cd.accumulator; - float *const R__ windowAccumulator = cd.windowAccumulator; - - const int sz = m_windowSize; - const int si = shiftIncrement; - - int i; - - if (m_debugLevel > 2) { - cerr << "writeChunk(" << channel << ", " << shiftIncrement << ", " << last << ")" << endl; - } - - for (i = 0; i < si; ++i) { - if (windowAccumulator[i] > 0.f) { - accumulator[i] /= windowAccumulator[i]; - } - } - - // for exact sample scaling (probably not meaningful if we - // were running in RT mode) - size_t theoreticalOut = 0; - if (cd.inputSize >= 0) { - theoreticalOut = lrint(cd.inputSize * m_timeRatio); - } - - bool resampledAlready = resampleBeforeStretching(); - - if (!resampledAlready && - (m_pitchScale != 1.0 || m_options & OptionPitchHighConsistency) && - cd.resampler) { - - size_t reqSize = int(ceil(si / m_pitchScale)); - if (reqSize > cd.resamplebufSize) { - // This shouldn't normally happen -- the buffer is - // supposed to be initialised with enough space in the - // first place. But we retain this check in case the - // pitch scale has changed since then, or the stretch - // calculator has gone mad, or something. - cerr << "WARNING: RubberBandStretcher::Impl::writeChunk: resizing resampler buffer from " - << cd.resamplebufSize << " to " << reqSize << endl; - cd.setResampleBufSize(reqSize); - } - - - size_t outframes = cd.resampler->resample(&cd.accumulator, - &cd.resamplebuf, - si, - 1.0 / m_pitchScale, - last); - - - writeOutput(*cd.outbuf, cd.resamplebuf, - outframes, cd.outCount, theoreticalOut); - - } else { - writeOutput(*cd.outbuf, accumulator, - si, cd.outCount, theoreticalOut); - } - - for (i = 0; i < sz - si; ++i) { - accumulator[i] = accumulator[i + si]; - } - - for (i = sz - si; i < sz; ++i) { - accumulator[i] = 0.0f; - } - - for (i = 0; i < sz - si; ++i) { - windowAccumulator[i] = windowAccumulator[i + si]; - } - - for (i = sz - si; i < sz; ++i) { - windowAccumulator[i] = 0.0f; - } - - if (int(cd.accumulatorFill) > si) { - cd.accumulatorFill -= si; - } else { - cd.accumulatorFill = 0; - if (cd.draining) { - if (m_debugLevel > 1) { - cerr << "RubberBandStretcher::Impl::processChunks: setting outputComplete to true" << endl; - } - cd.outputComplete = true; - } - } -} - -void -RubberBandStretcher::Impl::writeOutput(RingBuffer<float> &to, float *from, size_t qty, size_t &outCount, size_t theoreticalOut) -{ - Profiler profiler("RubberBandStretcher::Impl::writeOutput"); - - // In non-RT mode, we don't want to write the first startSkip - // samples, because the first chunk is centred on the start of the - // output. In RT mode we didn't apply any pre-padding in - // configure(), so we don't want to remove any here. - - size_t startSkip = 0; - if (!m_realtime) { - startSkip = lrintf((m_windowSize/2) / m_pitchScale); - } - - if (outCount > startSkip) { - - // this is the normal case - - if (theoreticalOut > 0) { - if (m_debugLevel > 1) { - cerr << "theoreticalOut = " << theoreticalOut - << ", outCount = " << outCount - << ", startSkip = " << startSkip - << ", qty = " << qty << endl; - } - if (outCount - startSkip <= theoreticalOut && - outCount - startSkip + qty > theoreticalOut) { - qty = theoreticalOut - (outCount - startSkip); - if (m_debugLevel > 1) { - cerr << "reduce qty to " << qty << endl; - } - } - } - - if (m_debugLevel > 2) { - cerr << "writing " << qty << endl; - } - - size_t written = to.write(from, qty); - - if (written < qty) { - cerr << "WARNING: RubberBandStretcher::Impl::writeOutput: " - << "Buffer overrun on output: wrote " << written - << " of " << qty << " samples" << endl; - } - - outCount += written; - return; - } - - // the rest of this is only used during the first startSkip samples - - if (outCount + qty <= startSkip) { - if (m_debugLevel > 1) { - cerr << "qty = " << qty << ", startSkip = " - << startSkip << ", outCount = " << outCount - << ", discarding" << endl; - } - outCount += qty; - return; - } - - size_t off = startSkip - outCount; - if (m_debugLevel > 1) { - cerr << "qty = " << qty << ", startSkip = " - << startSkip << ", outCount = " << outCount - << ", writing " << qty - off - << " from start offset " << off << endl; - } - to.write(from + off, qty - off); - outCount += qty; -} - -int -RubberBandStretcher::Impl::available() const -{ - Profiler profiler("RubberBandStretcher::Impl::available"); - - if (m_threaded) { - MutexLocker locker(&m_threadSetMutex); - if (m_channelData.empty()) return 0; - } else { - if (m_channelData.empty()) return 0; - } - - if (!m_threaded) { - for (size_t c = 0; c < m_channels; ++c) { - if (m_channelData[c]->inputSize >= 0) { -// cerr << "available: m_done true" << endl; - if (m_channelData[c]->inbuf->getReadSpace() > 0) { -// cerr << "calling processChunks(" << c << ") from available" << endl; - //!!! do we ever actually do this? if so, this method should not be const - // ^^^ yes, we do sometimes -- e.g. when fed a very short file - bool any = false, last = false; - ((RubberBandStretcher::Impl *)this)->processChunks(c, any, last); - } - } - } - } - - size_t min = 0; - bool consumed = true; - bool haveResamplers = false; - - for (size_t i = 0; i < m_channels; ++i) { - size_t availIn = m_channelData[i]->inbuf->getReadSpace(); - size_t availOut = m_channelData[i]->outbuf->getReadSpace(); - if (m_debugLevel > 2) { - cerr << "available on channel " << i << ": " << availOut << " (waiting: " << availIn << ")" << endl; - } - if (i == 0 || availOut < min) min = availOut; - if (!m_channelData[i]->outputComplete) consumed = false; - if (m_channelData[i]->resampler) haveResamplers = true; - } - - if (min == 0 && consumed) return -1; - if (m_pitchScale == 1.0) return min; - - if (haveResamplers) return min; // resampling has already happened - return int(floor(min / m_pitchScale)); -} - -size_t -RubberBandStretcher::Impl::retrieve(float *const *output, size_t samples) const -{ - Profiler profiler("RubberBandStretcher::Impl::retrieve"); - - size_t got = samples; - - for (size_t c = 0; c < m_channels; ++c) { - size_t gotHere = m_channelData[c]->outbuf->read(output[c], got); - if (gotHere < got) { - if (c > 0) { - if (m_debugLevel > 0) { - cerr << "RubberBandStretcher::Impl::retrieve: WARNING: channel imbalance detected" << endl; - } - } - got = gotHere; - } - } - - return got; -} - -} - diff --git a/libs/rubberband/src/Thread.cpp b/libs/rubberband/src/Thread.cpp deleted file mode 100644 index 49f75b5b65..0000000000 --- a/libs/rubberband/src/Thread.cpp +++ /dev/null @@ -1,583 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#include "Thread.h" - -#include <cstdlib> -#include <iostream> -#include <cstdlib> - -#include <cstdlib> -#include <sys/time.h> -#include <time.h> - -using std::cerr; -using std::endl; -using std::string; - -namespace RubberBand -{ - -#ifdef _WIN32 - -Thread::Thread() : - m_id(0), - m_extant(false) -{ -#ifdef DEBUG_THREAD - cerr << "THREAD DEBUG: Created thread object " << this << endl; -#endif -} - -Thread::~Thread() -{ -#ifdef DEBUG_THREAD - cerr << "THREAD DEBUG: Destroying thread object " << this << ", id " << m_id << endl; -#endif - if (m_extant) { - WaitForSingleObject(m_id, INFINITE); - } -#ifdef DEBUG_THREAD - cerr << "THREAD DEBUG: Destroyed thread object " << this << endl; -#endif -} - -void -Thread::start() -{ - m_id = CreateThread(NULL, 0, staticRun, this, 0, 0); - if (!m_id) { - cerr << "ERROR: thread creation failed" << endl; - exit(1); - } else { -#ifdef DEBUG_THREAD - cerr << "THREAD DEBUG: Created thread " << m_id << " for thread object " << this << endl; -#endif - m_extant = true; - } -} - -void -Thread::wait() -{ - if (m_extant) { -#ifdef DEBUG_THREAD - cerr << "THREAD DEBUG: Waiting on thread " << m_id << " for thread object " << this << endl; -#endif - WaitForSingleObject(m_id, INFINITE); -#ifdef DEBUG_THREAD - cerr << "THREAD DEBUG: Waited on thread " << m_id << " for thread object " << this << endl; -#endif - m_extant = false; - } -} - -Thread::Id -Thread::id() -{ - return m_id; -} - -bool -Thread::threadingAvailable() -{ - return true; -} - -DWORD -Thread::staticRun(LPVOID arg) -{ - Thread *thread = static_cast<Thread *>(arg); -#ifdef DEBUG_THREAD - cerr << "THREAD DEBUG: " << (void *)GetCurrentThreadId() << ": Running thread " << thread->m_id << " for thread object " << thread << endl; -#endif - thread->run(); - return 0; -} - -Mutex::Mutex() -#ifndef NO_THREAD_CHECKS - : - m_lockedBy(-1) -#endif -{ - m_mutex = CreateMutex(NULL, FALSE, NULL); -#ifdef DEBUG_MUTEX - cerr << "MUTEX DEBUG: " << (void *)GetCurrentThreadId() << ": Initialised mutex " << &m_mutex << endl; -#endif -} - -Mutex::~Mutex() -{ -#ifdef DEBUG_MUTEX - cerr << "MUTEX DEBUG: " << (void *)GetCurrentThreadId() << ": Destroying mutex " << &m_mutex << endl; -#endif - CloseHandle(m_mutex); -} - -void -Mutex::lock() -{ -#ifndef NO_THREAD_CHECKS - DWORD tid = GetCurrentThreadId(); - if (m_lockedBy == tid) { - cerr << "ERROR: Deadlock on mutex " << &m_mutex << endl; - } -#endif -#ifdef DEBUG_MUTEX - cerr << "MUTEX DEBUG: " << (void *)tid << ": Want to lock mutex " << &m_mutex << endl; -#endif - WaitForSingleObject(m_mutex, INFINITE); -#ifndef NO_THREAD_CHECKS - m_lockedBy = tid; -#endif -#ifdef DEBUG_MUTEX - cerr << "MUTEX DEBUG: " << (void *)tid << ": Locked mutex " << &m_mutex << endl; -#endif -} - -void -Mutex::unlock() -{ -#ifndef NO_THREAD_CHECKS - DWORD tid = GetCurrentThreadId(); - if (m_lockedBy != tid) { - cerr << "ERROR: Mutex " << &m_mutex << " not owned by unlocking thread" << endl; - return; - } -#endif -#ifdef DEBUG_MUTEX - cerr << "MUTEX DEBUG: " << (void *)tid << ": Unlocking mutex " << &m_mutex << endl; -#endif -#ifndef NO_THREAD_CHECKS - m_lockedBy = -1; -#endif - ReleaseMutex(m_mutex); -} - -bool -Mutex::trylock() -{ -#ifndef NO_THREAD_CHECKS - DWORD tid = GetCurrentThreadId(); -#endif - DWORD result = WaitForSingleObject(m_mutex, 0); - if (result == WAIT_TIMEOUT || result == WAIT_FAILED) { -#ifdef DEBUG_MUTEX - cerr << "MUTEX DEBUG: " << (void *)tid << ": Mutex " << &m_mutex << " unavailable" << endl; -#endif - return false; - } else { -#ifndef NO_THREAD_CHECKS - m_lockedBy = tid; -#endif -#ifdef DEBUG_MUTEX - cerr << "MUTEX DEBUG: " << (void *)tid << ": Locked mutex " << &m_mutex << " (from trylock)" << endl; -#endif - return true; - } -} - -Condition::Condition(string name) : - m_locked(false) -#ifdef DEBUG_CONDITION - , m_name(name) -#endif -{ - m_mutex = CreateMutex(NULL, FALSE, NULL); - m_condition = CreateEvent(NULL, FALSE, FALSE, NULL); -#ifdef DEBUG_CONDITION - cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Initialised condition " << &m_condition << " \"" << m_name << "\"" << endl; -#endif -} - -Condition::~Condition() -{ -#ifdef DEBUG_CONDITION - cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Destroying condition " << &m_condition << " \"" << m_name << "\"" << endl; -#endif - if (m_locked) ReleaseMutex(m_mutex); - CloseHandle(m_condition); - CloseHandle(m_mutex); -} - -void -Condition::lock() -{ - if (m_locked) { -#ifdef DEBUG_CONDITION - cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Already locked " << &m_condition << " \"" << m_name << "\"" << endl; -#endif - return; - } -#ifdef DEBUG_CONDITION - cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Want to lock " << &m_condition << " \"" << m_name << "\"" << endl; -#endif - WaitForSingleObject(m_mutex, INFINITE); - m_locked = true; -#ifdef DEBUG_CONDITION - cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Locked " << &m_condition << " \"" << m_name << "\"" << endl; -#endif -} - -void -Condition::unlock() -{ - if (!m_locked) { -#ifdef DEBUG_CONDITION - cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Not locked " << &m_condition << " \"" << m_name << "\"" << endl; -#endif - return; - } -#ifdef DEBUG_CONDITION - cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Unlocking " << &m_condition << " \"" << m_name << "\"" << endl; -#endif - m_locked = false; - ReleaseMutex(m_mutex); -} - -void -Condition::wait(int us) -{ - if (!m_locked) lock(); - - if (us == 0) { - -#ifdef DEBUG_CONDITION - cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Waiting on " << &m_condition << " \"" << m_name << "\"" << endl; -#endif - SignalObjectAndWait(m_mutex, m_condition, INFINITE, FALSE); - WaitForSingleObject(m_mutex, INFINITE); - - } else { - - DWORD ms = us / 1000; - if (us > 0 && ms == 0) ms = 1; - -#ifdef DEBUG_CONDITION - cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Timed waiting on " << &m_condition << " \"" << m_name << "\"" << endl; -#endif - SignalObjectAndWait(m_mutex, m_condition, ms, FALSE); - WaitForSingleObject(m_mutex, INFINITE); - } - - ReleaseMutex(m_mutex); - -#ifdef DEBUG_CONDITION - cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Wait done on " << &m_condition << " \"" << m_name << "\"" << endl; -#endif - m_locked = false; -} - -void -Condition::signal() -{ -#ifdef DEBUG_CONDITION - cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Signalling " << &m_condition << " \"" << m_name << "\"" << endl; -#endif - SetEvent(m_condition); -} - -#else /* !_WIN32 */ - - -Thread::Thread() : - m_id(0), - m_extant(false) -{ -#ifdef DEBUG_THREAD - cerr << "THREAD DEBUG: Created thread object " << this << endl; -#endif -} - -Thread::~Thread() -{ -#ifdef DEBUG_THREAD - cerr << "THREAD DEBUG: Destroying thread object " << this << ", id " << m_id << endl; -#endif - if (m_extant) { - pthread_join(m_id, 0); - } -#ifdef DEBUG_THREAD - cerr << "THREAD DEBUG: Destroyed thread object " << this << endl; -#endif -} - -void -Thread::start() -{ - if (pthread_create(&m_id, 0, staticRun, this)) { - cerr << "ERROR: thread creation failed" << endl; - exit(1); - } else { -#ifdef DEBUG_THREAD - cerr << "THREAD DEBUG: Created thread " << m_id << " for thread object " << this << endl; -#endif - m_extant = true; - } -} - -void -Thread::wait() -{ - if (m_extant) { -#ifdef DEBUG_THREAD - cerr << "THREAD DEBUG: Waiting on thread " << m_id << " for thread object " << this << endl; -#endif - pthread_join(m_id, 0); -#ifdef DEBUG_THREAD - cerr << "THREAD DEBUG: Waited on thread " << m_id << " for thread object " << this << endl; -#endif - m_extant = false; - } -} - -Thread::Id -Thread::id() -{ - return m_id; -} - -bool -Thread::threadingAvailable() -{ - return true; -} - -void * -Thread::staticRun(void *arg) -{ - Thread *thread = static_cast<Thread *>(arg); -#ifdef DEBUG_THREAD - cerr << "THREAD DEBUG: " << (void *)pthread_self() << ": Running thread " << thread->m_id << " for thread object " << thread << endl; -#endif - thread->run(); - return 0; -} - -Mutex::Mutex() -#ifndef NO_THREAD_CHECKS - : - m_lockedBy(0), - m_locked(false) -#endif -{ - pthread_mutex_init(&m_mutex, 0); -#ifdef DEBUG_MUTEX - cerr << "MUTEX DEBUG: " << (void *)pthread_self() << ": Initialised mutex " << &m_mutex << endl; -#endif -} - -Mutex::~Mutex() -{ -#ifdef DEBUG_MUTEX - cerr << "MUTEX DEBUG: " << (void *)pthread_self() << ": Destroying mutex " << &m_mutex << endl; -#endif - pthread_mutex_destroy(&m_mutex); -} - -void -Mutex::lock() -{ -#ifndef NO_THREAD_CHECKS - pthread_t tid = pthread_self(); - if (m_locked && m_lockedBy == tid) { - cerr << "ERROR: Deadlock on mutex " << &m_mutex << endl; - } -#endif -#ifdef DEBUG_MUTEX - cerr << "MUTEX DEBUG: " << (void *)tid << ": Want to lock mutex " << &m_mutex << endl; -#endif - pthread_mutex_lock(&m_mutex); -#ifndef NO_THREAD_CHECKS - m_lockedBy = tid; - m_locked = true; -#endif -#ifdef DEBUG_MUTEX - cerr << "MUTEX DEBUG: " << (void *)tid << ": Locked mutex " << &m_mutex << endl; -#endif -} - -void -Mutex::unlock() -{ -#ifndef NO_THREAD_CHECKS - pthread_t tid = pthread_self(); - if (!m_locked) { - cerr << "ERROR: Mutex " << &m_mutex << " not locked in unlock" << endl; - return; - } else if (m_lockedBy != tid) { - cerr << "ERROR: Mutex " << &m_mutex << " not owned by unlocking thread" << endl; - return; - } -#endif -#ifdef DEBUG_MUTEX - cerr << "MUTEX DEBUG: " << (void *)tid << ": Unlocking mutex " << &m_mutex << endl; -#endif -#ifndef NO_THREAD_CHECKS - m_locked = false; -#endif - pthread_mutex_unlock(&m_mutex); -} - -bool -Mutex::trylock() -{ -#ifndef NO_THREAD_CHECKS - pthread_t tid = pthread_self(); -#endif - if (pthread_mutex_trylock(&m_mutex)) { -#ifdef DEBUG_MUTEX - cerr << "MUTEX DEBUG: " << (void *)tid << ": Mutex " << &m_mutex << " unavailable" << endl; -#endif - return false; - } else { -#ifndef NO_THREAD_CHECKS - m_lockedBy = tid; - m_locked = true; -#endif -#ifdef DEBUG_MUTEX - cerr << "MUTEX DEBUG: " << (void *)tid << ": Locked mutex " << &m_mutex << " (from trylock)" << endl; -#endif - return true; - } -} - -Condition::Condition(string /*name*/) : - m_locked(false) -#ifdef DEBUG_CONDITION - , m_name(name) -#endif -{ - pthread_mutex_init(&m_mutex, 0); - pthread_cond_init(&m_condition, 0); -#ifdef DEBUG_CONDITION - cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Initialised condition " << &m_condition << " \"" << m_name << "\"" << endl; -#endif -} - -Condition::~Condition() -{ -#ifdef DEBUG_CONDITION - cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Destroying condition " << &m_condition << " \"" << m_name << "\"" << endl; -#endif - if (m_locked) pthread_mutex_unlock(&m_mutex); - pthread_cond_destroy(&m_condition); - pthread_mutex_destroy(&m_mutex); -} - -void -Condition::lock() -{ - if (m_locked) { -#ifdef DEBUG_CONDITION - cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Already locked " << &m_condition << " \"" << m_name << "\"" << endl; -#endif - return; - } -#ifdef DEBUG_CONDITION - cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Want to lock " << &m_condition << " \"" << m_name << "\"" << endl; -#endif - pthread_mutex_lock(&m_mutex); - m_locked = true; -#ifdef DEBUG_CONDITION - cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Locked " << &m_condition << " \"" << m_name << "\"" << endl; -#endif -} - -void -Condition::unlock() -{ - if (!m_locked) { -#ifdef DEBUG_CONDITION - cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Not locked " << &m_condition << " \"" << m_name << "\"" << endl; -#endif - return; - } -#ifdef DEBUG_CONDITION - cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Unlocking " << &m_condition << " \"" << m_name << "\"" << endl; -#endif - m_locked = false; - pthread_mutex_unlock(&m_mutex); -} - -void -Condition::wait(int us) -{ - if (!m_locked) lock(); - - if (us == 0) { - -#ifdef DEBUG_CONDITION - cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Waiting on " << &m_condition << " \"" << m_name << "\"" << endl; -#endif - pthread_cond_wait(&m_condition, &m_mutex); - - } else { - - struct timeval now; - gettimeofday(&now, 0); - - now.tv_usec += us; - while (now.tv_usec > 1000000) { - now.tv_usec -= 1000000; - ++now.tv_sec; - } - - struct timespec timeout; - timeout.tv_sec = now.tv_sec; - timeout.tv_nsec = now.tv_usec * 1000; - -#ifdef DEBUG_CONDITION - cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Timed waiting on " << &m_condition << " \"" << m_name << "\"" << endl; -#endif - pthread_cond_timedwait(&m_condition, &m_mutex, &timeout); - } - - pthread_mutex_unlock(&m_mutex); - -#ifdef DEBUG_CONDITION - cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Wait done on " << &m_condition << " \"" << m_name << "\"" << endl; -#endif - m_locked = false; -} - -void -Condition::signal() -{ -#ifdef DEBUG_CONDITION - cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Signalling " << &m_condition << " \"" << m_name << "\"" << endl; -#endif - pthread_cond_signal(&m_condition); -} - -#endif /* !_WIN32 */ - -MutexLocker::MutexLocker(Mutex *mutex) : - m_mutex(mutex) -{ - if (m_mutex) { - m_mutex->lock(); - } -} - -MutexLocker::~MutexLocker() -{ - if (m_mutex) { - m_mutex->unlock(); - } -} - -} - diff --git a/libs/rubberband/src/Thread.h b/libs/rubberband/src/Thread.h deleted file mode 100644 index 061469297e..0000000000 --- a/libs/rubberband/src/Thread.h +++ /dev/null @@ -1,142 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#ifndef _RUBBERBAND_THREAD_H_ -#define _RUBBERBAND_THREAD_H_ - -#ifdef _WIN32 -#include <windows.h> -#else /* !_WIN32 */ -#include <pthread.h> -#endif /* !_WIN32 */ - -#include <string> - -//#define DEBUG_THREAD 1 -//#define DEBUG_MUTEX 1 -//#define DEBUG_CONDITION 1 - -namespace RubberBand -{ - -class Thread -{ -public: -#ifdef _WIN32 - typedef HANDLE Id; -#else - typedef pthread_t Id; -#endif - - Thread(); - virtual ~Thread(); - - Id id(); - - void start(); - void wait(); - - static bool threadingAvailable(); - -protected: - virtual void run() = 0; - -private: -#ifdef _WIN32 - HANDLE m_id; - bool m_extant; - static DWORD WINAPI staticRun(LPVOID lpParam); -#else - pthread_t m_id; - bool m_extant; - static void *staticRun(void *); -#endif -}; - -class Mutex -{ -public: - Mutex(); - ~Mutex(); - - void lock(); - void unlock(); - bool trylock(); - -private: -#ifdef _WIN32 - HANDLE m_mutex; -#ifndef NO_THREAD_CHECKS - DWORD m_lockedBy; -#endif -#else - pthread_mutex_t m_mutex; -#ifndef NO_THREAD_CHECKS - pthread_t m_lockedBy; - bool m_locked; -#endif -#endif -}; - -class MutexLocker -{ -public: - MutexLocker(Mutex *); - ~MutexLocker(); - -private: - Mutex *m_mutex; -}; - -class Condition -{ -public: - Condition(std::string name); - ~Condition(); - - // To wait on a condition, either simply call wait(), or call - // lock() and then wait() (perhaps testing some state in between). - // To signal a condition, call signal(). - - // Although any thread may signal on a given condition, only one - // thread should ever wait on any given condition object -- - // otherwise there will be a race conditions in the logic that - // avoids the thread code having to track whether the condition's - // mutex is locked or not. If that is your requirement, this - // Condition wrapper is not for you. - void lock(); - void unlock(); - void wait(int us = 0); - - void signal(); - -private: - -#ifdef _WIN32 - HANDLE m_mutex; - HANDLE m_condition; - bool m_locked; -#else - pthread_mutex_t m_mutex; - pthread_cond_t m_condition; - bool m_locked; -#endif -#ifdef DEBUG_CONDITION - std::string m_name; -#endif -}; - -} - -#endif diff --git a/libs/rubberband/src/Window.cpp b/libs/rubberband/src/Window.cpp deleted file mode 100644 index 106faa7b62..0000000000 --- a/libs/rubberband/src/Window.cpp +++ /dev/null @@ -1,17 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#include "Window.h" - - diff --git a/libs/rubberband/src/Window.h b/libs/rubberband/src/Window.h deleted file mode 100644 index 6916b6fb5f..0000000000 --- a/libs/rubberband/src/Window.h +++ /dev/null @@ -1,183 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#ifndef _RUBBERBAND_WINDOW_H_ -#define _RUBBERBAND_WINDOW_H_ - -#include <cstdlib> -#include <cmath> -#include <cstdlib> -#include <iostream> -#include <cstdlib> -#include <map> - -#include "sysutils.h" - -namespace RubberBand { - -enum WindowType { - RectangularWindow, - BartlettWindow, - HammingWindow, - HanningWindow, - BlackmanWindow, - GaussianWindow, - ParzenWindow, - NuttallWindow, - BlackmanHarrisWindow -}; - -template <typename T> -class Window -{ -public: - /** - * Construct a windower of the given type. - */ - Window(WindowType type, int size) : m_type(type), m_size(size) { encache(); } - Window(const Window &w) : m_type(w.m_type), m_size(w.m_size) { encache(); } - Window &operator=(const Window &w) { - if (&w == this) return *this; - m_type = w.m_type; - m_size = w.m_size; - encache(); - return *this; - } - virtual ~Window() { delete[] m_cache; } - - void cut(T *R__ src) const - { - const int sz = m_size; - for (int i = 0; i < sz; ++i) { - src[i] *= m_cache[i]; - } - } - - void cut(T *R__ src, T *dst) const { - const int sz = m_size; - for (int i = 0; i < sz; ++i) { - dst[i] = src[i]; - } - for (int i = 0; i < sz; ++i) { - dst[i] *= m_cache[i]; - } - } - - T getArea() { return m_area; } - T getValue(int i) { return m_cache[i]; } - - WindowType getType() const { return m_type; } - int getSize() const { return m_size; } - -protected: - WindowType m_type; - int m_size; - T *R__ m_cache; - T m_area; - - void encache(); - void cosinewin(T *, T, T, T, T); -}; - -template <typename T> -void Window<T>::encache() -{ - int n = int(m_size); - T *mult = new T[n]; - int i; - for (i = 0; i < n; ++i) mult[i] = 1.0; - - switch (m_type) { - - case RectangularWindow: - for (i = 0; i < n; ++i) { - mult[i] *= 0.5; - } - break; - - case BartlettWindow: - for (i = 0; i < n/2; ++i) { - mult[i] *= (i / T(n/2)); - mult[i + n/2] *= (1.0 - (i / T(n/2))); - } - break; - - case HammingWindow: - cosinewin(mult, 0.54, 0.46, 0.0, 0.0); - break; - - case HanningWindow: - cosinewin(mult, 0.50, 0.50, 0.0, 0.0); - break; - - case BlackmanWindow: - cosinewin(mult, 0.42, 0.50, 0.08, 0.0); - break; - - case GaussianWindow: - for (i = 0; i < n; ++i) { - mult[i] *= pow(2, - pow((i - (n-1)/2.0) / ((n-1)/2.0 / 3), 2)); - } - break; - - case ParzenWindow: - { - int N = n-1; - for (i = 0; i < N/4; ++i) { - T m = 2 * pow(1.0 - (T(N)/2 - i) / (T(N)/2), 3); - mult[i] *= m; - mult[N-i] *= m; - } - for (i = N/4; i <= N/2; ++i) { - int wn = i - N/2; - T m = 1.0 - 6 * pow(wn / (T(N)/2), 2) * (1.0 - abs(wn) / (T(N)/2)); - mult[i] *= m; - mult[N-i] *= m; - } - break; - } - - case NuttallWindow: - cosinewin(mult, 0.3635819, 0.4891775, 0.1365995, 0.0106411); - break; - - case BlackmanHarrisWindow: - cosinewin(mult, 0.35875, 0.48829, 0.14128, 0.01168); - break; - } - - m_cache = mult; - - m_area = 0; - for (int i = 0; i < n; ++i) { - m_area += m_cache[i]; - } - m_area /= n; -} - -template <typename T> -void Window<T>::cosinewin(T *mult, T a0, T a1, T a2, T a3) -{ - int n = int(m_size); - for (int i = 0; i < n; ++i) { - mult[i] *= (a0 - - a1 * cos(2 * M_PI * i / n) - + a2 * cos(4 * M_PI * i / n) - - a3 * cos(6 * M_PI * i / n)); - } -} - -} - -#endif diff --git a/libs/rubberband/src/bsd-3rdparty/float_cast/float_cast.h b/libs/rubberband/src/bsd-3rdparty/float_cast/float_cast.h deleted file mode 100644 index 1ba0e03bdc..0000000000 --- a/libs/rubberband/src/bsd-3rdparty/float_cast/float_cast.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -** Copyright (C) 2001 Erik de Castro Lopo <erikd AT mega-nerd DOT com> -** -** Permission to use, copy, modify, distribute, and sell this file for any -** purpose is hereby granted without fee, provided that the above copyright -** and this permission notice appear in all copies. No representations are -** made about the suitability of this software for any purpose. It is -** provided "as is" without express or implied warranty. -*/ - -/* Version 1.1 */ - - -/*============================================================================ -** On Intel Pentium processors (especially PIII and probably P4), converting -** from float to int is very slow. To meet the C specs, the code produced by -** most C compilers targeting Pentium needs to change the FPU rounding mode -** before the float to int conversion is performed. -** -** Changing the FPU rounding mode causes the FPU pipeline to be flushed. It -** is this flushing of the pipeline which is so slow. -** -** Fortunately the ISO C99 specifications define the functions lrint, lrintf, -** llrint and llrintf which fix this problem as a side effect. -** -** On Unix-like systems, the configure process should have detected the -** presence of these functions. If they weren't found we have to replace them -** here with a standard C cast. -*/ - -/* -** The C99 prototypes for lrint and lrintf are as follows: -** -** long int lrintf (float x) ; -** long int lrint (double x) ; -*/ - -#if (defined (WIN32) || defined (_WIN32)) - - #include <math.h> - - /* Win32 doesn't seem to have these functions. - ** Therefore implement inline versions of these functions here. - */ - - __inline long int - lrint (double flt) - { int intgr; - - _asm - { fld flt - fistp intgr - } ; - - return intgr ; - } - - __inline long int - lrintf (float flt) - { int intgr; - - _asm - { fld flt - fistp intgr - } ; - - return intgr ; - } - -#endif - - - diff --git a/libs/rubberband/src/bsd-3rdparty/getopt/getopt.c b/libs/rubberband/src/bsd-3rdparty/getopt/getopt.c deleted file mode 100644 index ce9abb3cce..0000000000 --- a/libs/rubberband/src/bsd-3rdparty/getopt/getopt.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 1987, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -int opterr = 1, /* if error message should be printed */ - optind = 1, /* index into parent argv vector */ - optopt, /* character checked for validity */ - optreset; /* reset getopt */ -char *optarg; /* argument associated with option */ - -#define BADCH (int)'?' -#define BADARG (int)':' -#define EMSG "" - -/* - * getopt -- - * Parse argc/argv argument vector. - */ -int -getopt(nargc, nargv, ostr) - int nargc; - char * const *nargv; - const char *ostr; -{ - static char *place = EMSG; /* option letter processing */ - char *oli; /* option letter list index */ - - if (optreset || !*place) { /* update scanning pointer */ - optreset = 0; - if (optind >= nargc || *(place = nargv[optind]) != '-') { - place = EMSG; - return (-1); - } - if (place[1] && *++place == '-') { /* found "--" */ - ++optind; - place = EMSG; - return (-1); - } - } /* option letter okay? */ - if ((optopt = (int)*place++) == (int)':' || - !(oli = strchr(ostr, optopt))) { - /* - * if the user didn't specify '-' as an option, - * assume it means -1. - */ - if (optopt == (int)'-') - return (-1); - if (!*place) - ++optind; - if (opterr && *ostr != ':' && optopt != BADCH) - (void)fprintf(stderr, "%s: illegal option -- %c\n", - "progname", optopt); - return (BADCH); - } - if (*++oli != ':') { /* don't need argument */ - optarg = NULL; - if (!*place) - ++optind; - } - else { /* need an argument */ - if (*place) /* no white space */ - optarg = place; - else if (nargc <= ++optind) { /* no arg */ - place = EMSG; - if (*ostr == ':') - return (BADARG); - if (opterr) - (void)fprintf(stderr, - "%s: option requires an argument -- %c\n", - "progname", optopt); - return (BADCH); - } - else /* white space */ - optarg = nargv[optind]; - place = EMSG; - ++optind; - } - return (optopt); /* dump back option letter */ -} diff --git a/libs/rubberband/src/bsd-3rdparty/getopt/getopt.h b/libs/rubberband/src/bsd-3rdparty/getopt/getopt.h deleted file mode 100644 index d95d6cf8f8..0000000000 --- a/libs/rubberband/src/bsd-3rdparty/getopt/getopt.h +++ /dev/null @@ -1,110 +0,0 @@ -/* $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $ */ -/* $FreeBSD: src/include/getopt.h,v 1.1 2002/09/29 04:14:30 eric Exp $ */ - -/*- - * Copyright (c) 2000 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Dieter Baron and Thomas Klausner. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _GETOPT_H_ -#define _GETOPT_H_ - -#ifdef _WIN32 -/* from <sys/cdefs.h> */ -# ifdef __cplusplus -# define __BEGIN_DECLS extern "C" { -# define __END_DECLS } -# else -# define __BEGIN_DECLS -# define __END_DECLS -# endif -# define __P(args) args -#endif - -/*#ifndef _WIN32 -#include <sys/cdefs.h> -#include <unistd.h> -#endif*/ - -#ifdef _WIN32 -# if !defined(GETOPT_API) -# define GETOPT_API __declspec(dllimport) -# endif -#endif - -/* - * Gnu like getopt_long() and BSD4.4 getsubopt()/optreset extensions - */ -#if !defined(_POSIX_SOURCE) && !defined(_XOPEN_SOURCE) -#define no_argument 0 -#define required_argument 1 -#define optional_argument 2 - -struct option { - /* name of long option */ - const char *name; - /* - * one of no_argument, required_argument, and optional_argument: - * whether option takes an argument - */ - int has_arg; - /* if not NULL, set *flag to val when option found */ - int *flag; - /* if flag not NULL, value to set *flag to; else return value */ - int val; -}; - -__BEGIN_DECLS -GETOPT_API int getopt_long __P((int, char * const *, const char *, - const struct option *, int *)); -__END_DECLS -#endif - -#ifdef _WIN32 -/* These are global getopt variables */ -__BEGIN_DECLS - -GETOPT_API extern int opterr, /* if error message should be printed */ - optind, /* index into parent argv vector */ - optopt, /* character checked for validity */ - optreset; /* reset getopt */ -GETOPT_API extern char* optarg; /* argument associated with option */ - -/* Original getopt */ -GETOPT_API int getopt __P((int, char * const *, const char *)); - -__END_DECLS -#endif - -#endif /* !_GETOPT_H_ */ diff --git a/libs/rubberband/src/bsd-3rdparty/getopt/getopt_long.c b/libs/rubberband/src/bsd-3rdparty/getopt/getopt_long.c deleted file mode 100644 index 1f92449a06..0000000000 --- a/libs/rubberband/src/bsd-3rdparty/getopt/getopt_long.c +++ /dev/null @@ -1,547 +0,0 @@ -/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ -/* $FreeBSD: src/lib/libc/stdlib/getopt_long.c,v 1.2 2002/10/16 22:18:42 alfred Exp $ */ - -/*- - * Copyright (c) 2000 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Dieter Baron and Thomas Klausner. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - - -#include <stdlib.h> -#include <string.h> - -#ifdef _WIN32 - -/* Windows needs warnx(). We change the definition though: - * 1. (another) global is defined, opterrmsg, which holds the error message - * 2. errors are always printed out on stderr w/o the program name - * Note that opterrmsg always gets set no matter what opterr is set to. The - * error message will not be printed if opterr is 0 as usual. - */ - -#include "getopt.h" -#include <stdio.h> -#include <stdarg.h> - -GETOPT_API extern char opterrmsg[128]; -char opterrmsg[128]; /* last error message is stored here */ - -static void warnx(int print_error, const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - if (fmt != NULL) - _vsnprintf(opterrmsg, 128, fmt, ap); - else - opterrmsg[0]='\0'; - va_end(ap); - if (print_error) { - fprintf(stderr, opterrmsg); - fprintf(stderr, "\n"); - } -} - -#endif /*_WIN32*/ - -/* not part of the original file */ -#ifndef _DIAGASSERT -#define _DIAGASSERT(X) -#endif - -#if HAVE_CONFIG_H && !HAVE_GETOPT_LONG && !HAVE_DECL_OPTIND -#define REPLACE_GETOPT -#endif - -#ifdef REPLACE_GETOPT -#ifdef __weak_alias -__weak_alias(getopt,_getopt) -#endif -int opterr = 1; /* if error message should be printed */ -int optind = 1; /* index into parent argv vector */ -int optopt = '?'; /* character checked for validity */ -int optreset; /* reset getopt */ -char *optarg; /* argument associated with option */ -#elif HAVE_CONFIG_H && !HAVE_DECL_OPTRESET -static int optreset; -#endif - -#ifdef __weak_alias -__weak_alias(getopt_long,_getopt_long) -#endif - -#if !HAVE_GETOPT_LONG -#define IGNORE_FIRST (*options == '-' || *options == '+') -#define PRINT_ERROR ((opterr) && ((*options != ':') \ - || (IGNORE_FIRST && options[1] != ':'))) -#define IS_POSIXLY_CORRECT (getenv("POSIXLY_CORRECT") != NULL) -#define PERMUTE (!IS_POSIXLY_CORRECT && !IGNORE_FIRST) -/* XXX: GNU ignores PC if *options == '-' */ -#define IN_ORDER (!IS_POSIXLY_CORRECT && *options == '-') - -/* return values */ -#define BADCH (int)'?' -#define BADARG ((IGNORE_FIRST && options[1] == ':') \ - || (*options == ':') ? (int)':' : (int)'?') -#define INORDER (int)1 - -#define EMSG "" - -static int getopt_internal(int, char * const *, const char *); -static int gcd(int, int); -static void permute_args(int, int, int, char * const *); - -static char *place = EMSG; /* option letter processing */ - -/* XXX: set optreset to 1 rather than these two */ -static int nonopt_start = -1; /* first non option argument (for permute) */ -static int nonopt_end = -1; /* first option after non options (for permute) */ - -/* Error messages */ -static const char recargchar[] = "option requires an argument -- %c"; -static const char recargstring[] = "option requires an argument -- %s"; -static const char ambig[] = "ambiguous option -- %.*s"; -static const char noarg[] = "option doesn't take an argument -- %.*s"; -static const char illoptchar[] = "unknown option -- %c"; -static const char illoptstring[] = "unknown option -- %s"; - - -/* - * Compute the greatest common divisor of a and b. - */ -static int -gcd(a, b) - int a; - int b; -{ - int c; - - c = a % b; - while (c != 0) { - a = b; - b = c; - c = a % b; - } - - return b; -} - -/* - * Exchange the block from nonopt_start to nonopt_end with the block - * from nonopt_end to opt_end (keeping the same order of arguments - * in each block). - */ -static void -permute_args(panonopt_start, panonopt_end, opt_end, nargv) - int panonopt_start; - int panonopt_end; - int opt_end; - char * const *nargv; -{ - int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; - char *swap; - - _DIAGASSERT(nargv != NULL); - - /* - * compute lengths of blocks and number and size of cycles - */ - nnonopts = panonopt_end - panonopt_start; - nopts = opt_end - panonopt_end; - ncycle = gcd(nnonopts, nopts); - cyclelen = (opt_end - panonopt_start) / ncycle; - - for (i = 0; i < ncycle; i++) { - cstart = panonopt_end+i; - pos = cstart; - for (j = 0; j < cyclelen; j++) { - if (pos >= panonopt_end) - pos -= nnonopts; - else - pos += nopts; - swap = nargv[pos]; - /* LINTED const cast */ - ((char **) nargv)[pos] = nargv[cstart]; - /* LINTED const cast */ - ((char **)nargv)[cstart] = swap; - } - } -} - -/* - * getopt_internal -- - * Parse argc/argv argument vector. Called by user level routines. - * Returns -2 if -- is found (can be long option or end of options marker). - */ -static int -getopt_internal(nargc, nargv, options) - int nargc; - char * const *nargv; - const char *options; -{ - char *oli; /* option letter list index */ - int optchar; - - _DIAGASSERT(nargv != NULL); - _DIAGASSERT(options != NULL); - - optarg = NULL; - - /* - * XXX Some programs (like rsyncd) expect to be able to - * XXX re-initialize optind to 0 and have getopt_long(3) - * XXX properly function again. Work around this braindamage. - */ - if (optind == 0) - optind = 1; - - if (optreset) - nonopt_start = nonopt_end = -1; -start: - if (optreset || !*place) { /* update scanning pointer */ - optreset = 0; - if (optind >= nargc) { /* end of argument vector */ - place = EMSG; - if (nonopt_end != -1) { - /* do permutation, if we have to */ - permute_args(nonopt_start, nonopt_end, - optind, nargv); - optind -= nonopt_end - nonopt_start; - } - else if (nonopt_start != -1) { - /* - * If we skipped non-options, set optind - * to the first of them. - */ - optind = nonopt_start; - } - nonopt_start = nonopt_end = -1; - return -1; - } - if ((*(place = nargv[optind]) != '-') - || (place[1] == '\0')) { /* found non-option */ - place = EMSG; - if (IN_ORDER) { - /* - * GNU extension: - * return non-option as argument to option 1 - */ - optarg = nargv[optind++]; - return INORDER; - } - if (!PERMUTE) { - /* - * if no permutation wanted, stop parsing - * at first non-option - */ - return -1; - } - /* do permutation */ - if (nonopt_start == -1) - nonopt_start = optind; - else if (nonopt_end != -1) { - permute_args(nonopt_start, nonopt_end, - optind, nargv); - nonopt_start = optind - - (nonopt_end - nonopt_start); - nonopt_end = -1; - } - optind++; - /* process next argument */ - goto start; - } - if (nonopt_start != -1 && nonopt_end == -1) - nonopt_end = optind; - if (place[1] && *++place == '-') { /* found "--" */ - place++; - return -2; - } - } - if ((optchar = (int)*place++) == (int)':' || - (oli = strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) { - /* option letter unknown or ':' */ - if (!*place) - ++optind; -#ifndef _WIN32 - if (PRINT_ERROR) - warnx(illoptchar, optchar); -#else - warnx(PRINT_ERROR, illoptchar, optchar); -#endif - optopt = optchar; - return BADCH; - } - if (optchar == 'W' && oli[1] == ';') { /* -W long-option */ - /* XXX: what if no long options provided (called by getopt)? */ - if (*place) - return -2; - - if (++optind >= nargc) { /* no arg */ - place = EMSG; -#ifndef _WIN32 - if (PRINT_ERROR) - warnx(recargchar, optchar); -#else - warnx(PRINT_ERROR, recargchar, optchar); -#endif - optopt = optchar; - return BADARG; - } else /* white space */ - place = nargv[optind]; - /* - * Handle -W arg the same as --arg (which causes getopt to - * stop parsing). - */ - return -2; - } - if (*++oli != ':') { /* doesn't take argument */ - if (!*place) - ++optind; - } else { /* takes (optional) argument */ - optarg = NULL; - if (*place) /* no white space */ - optarg = place; - /* XXX: disable test for :: if PC? (GNU doesn't) */ - else if (oli[1] != ':') { /* arg not optional */ - if (++optind >= nargc) { /* no arg */ - place = EMSG; -#ifndef _WIN32 - if (PRINT_ERROR) - warnx(recargchar, optchar); -#else - warnx(PRINT_ERROR, recargchar, optchar); -#endif - optopt = optchar; - return BADARG; - } else - optarg = nargv[optind]; - } - place = EMSG; - ++optind; - } - /* dump back option letter */ - return optchar; -} - -#ifdef REPLACE_GETOPT -/* - * getopt -- - * Parse argc/argv argument vector. - * - * [eventually this will replace the real getopt] - */ -int -getopt(nargc, nargv, options) - int nargc; - char * const *nargv; - const char *options; -{ - int retval; - - _DIAGASSERT(nargv != NULL); - _DIAGASSERT(options != NULL); - - if ((retval = getopt_internal(nargc, nargv, options)) == -2) { - ++optind; - /* - * We found an option (--), so if we skipped non-options, - * we have to permute. - */ - if (nonopt_end != -1) { - permute_args(nonopt_start, nonopt_end, optind, - nargv); - optind -= nonopt_end - nonopt_start; - } - nonopt_start = nonopt_end = -1; - retval = -1; - } - return retval; -} -#endif - -/* - * getopt_long -- - * Parse argc/argv argument vector. - */ -int -getopt_long(nargc, nargv, options, long_options, idx) - int nargc; - char * const *nargv; - const char *options; - const struct option *long_options; - int *idx; -{ - int retval; - - _DIAGASSERT(nargv != NULL); - _DIAGASSERT(options != NULL); - _DIAGASSERT(long_options != NULL); - /* idx may be NULL */ - - if ((retval = getopt_internal(nargc, nargv, options)) == -2) { - char *current_argv, *has_equal; - size_t current_argv_len; - int i, match; - - current_argv = place; - match = -1; - - optind++; - place = EMSG; - - if (*current_argv == '\0') { /* found "--" */ - /* - * We found an option (--), so if we skipped - * non-options, we have to permute. - */ - if (nonopt_end != -1) { - permute_args(nonopt_start, nonopt_end, - optind, nargv); - optind -= nonopt_end - nonopt_start; - } - nonopt_start = nonopt_end = -1; - return -1; - } - if ((has_equal = strchr(current_argv, '=')) != NULL) { - /* argument found (--option=arg) */ - current_argv_len = has_equal - current_argv; - has_equal++; - } else - current_argv_len = strlen(current_argv); - - for (i = 0; long_options[i].name; i++) { - /* find matching long option */ - if (strncmp(current_argv, long_options[i].name, - current_argv_len)) - continue; - - if (strlen(long_options[i].name) == - (unsigned)current_argv_len) { - /* exact match */ - match = i; - break; - } - if (match == -1) /* partial match */ - match = i; - else { - /* ambiguous abbreviation */ -#ifndef _WIN32 - if (PRINT_ERROR) - warnx(ambig, (int)current_argv_len, - current_argv); -#else - warnx(PRINT_ERROR, ambig, (int)current_argv_len, - current_argv); -#endif - optopt = 0; - return BADCH; - } - } - if (match != -1) { /* option found */ - if (long_options[match].has_arg == no_argument - && has_equal) { -#ifndef _WIN32 - if (PRINT_ERROR) - warnx(noarg, (int)current_argv_len, - current_argv); -#else - warnx(PRINT_ERROR, noarg, (int)current_argv_len, - current_argv); -#endif - /* - * XXX: GNU sets optopt to val regardless of - * flag - */ - if (long_options[match].flag == NULL) - optopt = long_options[match].val; - else - optopt = 0; - return BADARG; - } - if (long_options[match].has_arg == required_argument || - long_options[match].has_arg == optional_argument) { - if (has_equal) - optarg = has_equal; - else if (long_options[match].has_arg == - required_argument) { - /* - * optional argument doesn't use - * next nargv - */ - optarg = nargv[optind++]; - } - } - if ((long_options[match].has_arg == required_argument) - && (optarg == NULL)) { - /* - * Missing argument; leading ':' - * indicates no error should be generated - */ -#ifndef _WIN32 - if (PRINT_ERROR) - warnx(recargstring, current_argv); -#else - warnx(PRINT_ERROR, recargstring, current_argv); -#endif - /* - * XXX: GNU sets optopt to val regardless - * of flag - */ - if (long_options[match].flag == NULL) - optopt = long_options[match].val; - else - optopt = 0; - --optind; - return BADARG; - } - } else { /* unknown option */ -#ifndef _WIN32 - if (PRINT_ERROR) - warnx(illoptstring, current_argv); -#else - warnx(PRINT_ERROR, illoptstring, current_argv); -#endif - optopt = 0; - return BADCH; - } - if (long_options[match].flag) { - *long_options[match].flag = long_options[match].val; - retval = 0; - } else - retval = long_options[match].val; - if (idx) - *idx = match; - } - return retval; -} -#endif /* !GETOPT_LONG */ diff --git a/libs/rubberband/src/bsd-3rdparty/getopt/unistd.h b/libs/rubberband/src/bsd-3rdparty/getopt/unistd.h deleted file mode 100644 index e69de29bb2..0000000000 --- a/libs/rubberband/src/bsd-3rdparty/getopt/unistd.h +++ /dev/null diff --git a/libs/rubberband/src/ladspa/RubberBandPitchShifter.cpp b/libs/rubberband/src/ladspa/RubberBandPitchShifter.cpp deleted file mode 100644 index 6839124921..0000000000 --- a/libs/rubberband/src/ladspa/RubberBandPitchShifter.cpp +++ /dev/null @@ -1,554 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#include "RubberBandPitchShifter.h" - -#include "RubberBandStretcher.h" - -#include <iostream> -#include <cmath> - -using namespace RubberBand; - -using std::cout; -using std::cerr; -using std::endl; -using std::min; - -const char *const -RubberBandPitchShifter::portNamesMono[PortCountMono] = -{ - "latency", - "Cents", - "Semitones", - "Octaves", - "Crispness", - "Formant Preserving", - "Faster", - "Input", - "Output" -}; - -const char *const -RubberBandPitchShifter::portNamesStereo[PortCountStereo] = -{ - "latency", - "Cents", - "Semitones", - "Octaves", - "Crispness", - "Formant Preserving", - "Faster", - "Input L", - "Output L", - "Input R", - "Output R" -}; - -const LADSPA_PortDescriptor -RubberBandPitchShifter::portsMono[PortCountMono] = -{ - LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL, - LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, - LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, - LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, - LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, - LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, - LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, - LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO, - LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO -}; - -const LADSPA_PortDescriptor -RubberBandPitchShifter::portsStereo[PortCountStereo] = -{ - LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL, - LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, - LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, - LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, - LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, - LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, - LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, - LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO, - LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO, - LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO, - LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO -}; - -const LADSPA_PortRangeHint -RubberBandPitchShifter::hintsMono[PortCountMono] = -{ - { 0, 0, 0 }, // latency - { LADSPA_HINT_DEFAULT_0 | // cents - LADSPA_HINT_BOUNDED_BELOW | - LADSPA_HINT_BOUNDED_ABOVE, - -100.0, 100.0 }, - { LADSPA_HINT_DEFAULT_0 | // semitones - LADSPA_HINT_BOUNDED_BELOW | - LADSPA_HINT_BOUNDED_ABOVE | - LADSPA_HINT_INTEGER, - -12.0, 12.0 }, - { LADSPA_HINT_DEFAULT_0 | // octaves - LADSPA_HINT_BOUNDED_BELOW | - LADSPA_HINT_BOUNDED_ABOVE | - LADSPA_HINT_INTEGER, - -3.0, 3.0 }, - { LADSPA_HINT_DEFAULT_MAXIMUM | // crispness - LADSPA_HINT_BOUNDED_BELOW | - LADSPA_HINT_BOUNDED_ABOVE | - LADSPA_HINT_INTEGER, - 0.0, 3.0 }, - { LADSPA_HINT_DEFAULT_0 | // formant preserving - LADSPA_HINT_BOUNDED_BELOW | - LADSPA_HINT_BOUNDED_ABOVE | - LADSPA_HINT_TOGGLED, - 0.0, 1.0 }, - { LADSPA_HINT_DEFAULT_0 | // fast - LADSPA_HINT_BOUNDED_BELOW | - LADSPA_HINT_BOUNDED_ABOVE | - LADSPA_HINT_TOGGLED, - 0.0, 1.0 }, - { 0, 0, 0 }, - { 0, 0, 0 } -}; - -const LADSPA_PortRangeHint -RubberBandPitchShifter::hintsStereo[PortCountStereo] = -{ - { 0, 0, 0 }, // latency - { LADSPA_HINT_DEFAULT_0 | // cents - LADSPA_HINT_BOUNDED_BELOW | - LADSPA_HINT_BOUNDED_ABOVE, - -100.0, 100.0 }, - { LADSPA_HINT_DEFAULT_0 | // semitones - LADSPA_HINT_BOUNDED_BELOW | - LADSPA_HINT_BOUNDED_ABOVE | - LADSPA_HINT_INTEGER, - -12.0, 12.0 }, - { LADSPA_HINT_DEFAULT_0 | // octaves - LADSPA_HINT_BOUNDED_BELOW | - LADSPA_HINT_BOUNDED_ABOVE | - LADSPA_HINT_INTEGER, - -3.0, 3.0 }, - { LADSPA_HINT_DEFAULT_MAXIMUM | // crispness - LADSPA_HINT_BOUNDED_BELOW | - LADSPA_HINT_BOUNDED_ABOVE | - LADSPA_HINT_INTEGER, - 0.0, 3.0 }, - { LADSPA_HINT_DEFAULT_0 | // formant preserving - LADSPA_HINT_BOUNDED_BELOW | - LADSPA_HINT_BOUNDED_ABOVE | - LADSPA_HINT_TOGGLED, - 0.0, 1.0 }, - { LADSPA_HINT_DEFAULT_0 | // fast - LADSPA_HINT_BOUNDED_BELOW | - LADSPA_HINT_BOUNDED_ABOVE | - LADSPA_HINT_TOGGLED, - 0.0, 1.0 }, - { 0, 0, 0 }, - { 0, 0, 0 }, - { 0, 0, 0 }, - { 0, 0, 0 } -}; - -const LADSPA_Properties -RubberBandPitchShifter::properties = LADSPA_PROPERTY_HARD_RT_CAPABLE; - -const LADSPA_Descriptor -RubberBandPitchShifter::ladspaDescriptorMono = -{ - 2979, // "Unique" ID - "rubberband-pitchshifter-mono", // Label - properties, - "Rubber Band Mono Pitch Shifter", // Name - "Breakfast Quay", - "GPL", - PortCountMono, - portsMono, - portNamesMono, - hintsMono, - 0, // Implementation data - instantiate, - connectPort, - activate, - run, - 0, // Run adding - 0, // Set run adding gain - deactivate, - cleanup -}; - -const LADSPA_Descriptor -RubberBandPitchShifter::ladspaDescriptorStereo = -{ - 9792, // "Unique" ID - "rubberband-pitchshifter-stereo", // Label - properties, - "Rubber Band Stereo Pitch Shifter", // Name - "Breakfast Quay", - "GPL", - PortCountStereo, - portsStereo, - portNamesStereo, - hintsStereo, - 0, // Implementation data - instantiate, - connectPort, - activate, - run, - 0, // Run adding - 0, // Set run adding gain - deactivate, - cleanup -}; - -const LADSPA_Descriptor * -RubberBandPitchShifter::getDescriptor(unsigned long index) -{ - if (index == 0) return &ladspaDescriptorMono; - if (index == 1) return &ladspaDescriptorStereo; - else return 0; -} - -RubberBandPitchShifter::RubberBandPitchShifter(int sampleRate, size_t channels) : - m_latency(0), - m_cents(0), - m_semitones(0), - m_octaves(0), - m_crispness(0), - m_formant(0), - m_fast(0), - m_ratio(1.0), - m_prevRatio(1.0), - m_currentCrispness(-1), - m_currentFormant(false), - m_currentFast(false), - m_blockSize(1024), - m_reserve(1024), - m_minfill(0), - m_stretcher(new RubberBandStretcher - (sampleRate, channels, - RubberBandStretcher::OptionProcessRealTime | - RubberBandStretcher::OptionPitchHighConsistency)), - m_sampleRate(sampleRate), - m_channels(channels) -{ - for (size_t c = 0; c < m_channels; ++c) { - - m_input[c] = 0; - m_output[c] = 0; - - int bufsize = m_blockSize + m_reserve + 8192; - - m_outputBuffer[c] = new RingBuffer<float>(bufsize); - - m_scratch[c] = new float[bufsize]; - for (int i = 0; i < bufsize; ++i) m_scratch[c][i] = 0.f; - } - - activateImpl(); -} - -RubberBandPitchShifter::~RubberBandPitchShifter() -{ - delete m_stretcher; - for (size_t c = 0; c < m_channels; ++c) { - delete m_outputBuffer[c]; - delete[] m_scratch[c]; - } -} - -LADSPA_Handle -RubberBandPitchShifter::instantiate(const LADSPA_Descriptor *desc, unsigned long rate) -{ - if (desc->PortCount == ladspaDescriptorMono.PortCount) { - return new RubberBandPitchShifter(rate, 1); - } else if (desc->PortCount == ladspaDescriptorStereo.PortCount) { - return new RubberBandPitchShifter(rate, 2); - } - return 0; -} - -void -RubberBandPitchShifter::connectPort(LADSPA_Handle handle, - unsigned long port, LADSPA_Data *location) -{ - RubberBandPitchShifter *shifter = (RubberBandPitchShifter *)handle; - - float **ports[PortCountStereo] = { - &shifter->m_latency, - &shifter->m_cents, - &shifter->m_semitones, - &shifter->m_octaves, - &shifter->m_crispness, - &shifter->m_formant, - &shifter->m_fast, - &shifter->m_input[0], - &shifter->m_output[0], - &shifter->m_input[1], - &shifter->m_output[1] - }; - - if (shifter->m_channels == 1) { - if (port >= PortCountMono) return; - } else { - if (port >= PortCountStereo) return; - } - - *ports[port] = (float *)location; - - if (shifter->m_latency) { - *(shifter->m_latency) = - float(shifter->m_stretcher->getLatency() + shifter->m_reserve); - } -} - -void -RubberBandPitchShifter::activate(LADSPA_Handle handle) -{ - RubberBandPitchShifter *shifter = (RubberBandPitchShifter *)handle; - shifter->activateImpl(); -} - -void -RubberBandPitchShifter::activateImpl() -{ - updateRatio(); - m_prevRatio = m_ratio; - m_stretcher->reset(); - m_stretcher->setPitchScale(m_ratio); - - for (size_t c = 0; c < m_channels; ++c) { - m_outputBuffer[c]->reset(); - m_outputBuffer[c]->zero(m_reserve); - } - - m_minfill = 0; - - // prime stretcher -// for (int i = 0; i < 8; ++i) { -// int reqd = m_stretcher->getSamplesRequired(); -// m_stretcher->process(m_scratch, reqd, false); -// int avail = m_stretcher->available(); -// if (avail > 0) { -// m_stretcher->retrieve(m_scratch, avail); -// } -// } -} - -void -RubberBandPitchShifter::run(LADSPA_Handle handle, unsigned long samples) -{ - RubberBandPitchShifter *shifter = (RubberBandPitchShifter *)handle; - shifter->runImpl(samples); -} - -void -RubberBandPitchShifter::updateRatio() -{ - double oct = (m_octaves ? *m_octaves : 0.0); - oct += (m_semitones ? *m_semitones : 0.0) / 12; - oct += (m_cents ? *m_cents : 0.0) / 1200; - m_ratio = pow(2.0, oct); -} - -void -RubberBandPitchShifter::updateCrispness() -{ - if (!m_crispness) return; - - int c = lrintf(*m_crispness); - if (c == m_currentCrispness) return; - if (c < 0 || c > 3) return; - RubberBandStretcher *s = m_stretcher; - - switch (c) { - case 0: - s->setPhaseOption(RubberBandStretcher::OptionPhaseIndependent); - s->setTransientsOption(RubberBandStretcher::OptionTransientsSmooth); - break; - case 1: - s->setPhaseOption(RubberBandStretcher::OptionPhaseLaminar); - s->setTransientsOption(RubberBandStretcher::OptionTransientsSmooth); - break; - case 2: - s->setPhaseOption(RubberBandStretcher::OptionPhaseLaminar); - s->setTransientsOption(RubberBandStretcher::OptionTransientsMixed); - break; - case 3: - s->setPhaseOption(RubberBandStretcher::OptionPhaseLaminar); - s->setTransientsOption(RubberBandStretcher::OptionTransientsCrisp); - break; - } - - m_currentCrispness = c; -} - -void -RubberBandPitchShifter::updateFormant() -{ - if (!m_formant) return; - - bool f = (*m_formant > 0.5f); - if (f == m_currentFormant) return; - - RubberBandStretcher *s = m_stretcher; - - s->setFormantOption(f ? - RubberBandStretcher::OptionFormantPreserved : - RubberBandStretcher::OptionFormantShifted); - - m_currentFormant = f; -} - -void -RubberBandPitchShifter::updateFast() -{ - if (!m_fast) return; - - bool f = (*m_fast > 0.5f); - if (f == m_currentFast) return; - - RubberBandStretcher *s = m_stretcher; - - s->setPitchOption(f ? - RubberBandStretcher::OptionPitchHighSpeed : - RubberBandStretcher::OptionPitchHighConsistency); - - m_currentFast = f; -} - -void -RubberBandPitchShifter::runImpl(unsigned long insamples) -{ - unsigned long offset = 0; - - // We have to break up the input into chunks like this because - // insamples could be arbitrarily large and our output buffer is - // of limited size - - while (offset < insamples) { - - unsigned long block = (unsigned long)m_blockSize; - if (block + offset > insamples) block = insamples - offset; - - runImpl(block, offset); - - offset += block; - } -} - -void -RubberBandPitchShifter::runImpl(unsigned long insamples, unsigned long offset) -{ -// cerr << "RubberBandPitchShifter::runImpl(" << insamples << ")" << endl; - -// static int incount = 0, outcount = 0; - - updateRatio(); - if (m_ratio != m_prevRatio) { - m_stretcher->setPitchScale(m_ratio); - m_prevRatio = m_ratio; - } - - if (m_latency) { - *m_latency = float(m_stretcher->getLatency() + m_reserve); -// cerr << "latency = " << *m_latency << endl; - } - - updateCrispness(); - updateFormant(); - updateFast(); - - const int samples = insamples; - int processed = 0; - size_t outTotal = 0; - - float *ptrs[2]; - - int rs = m_outputBuffer[0]->getReadSpace(); - if (rs < int(m_minfill)) { -// cerr << "temporary expansion (have " << rs << ", want " << m_reserve << ")" << endl; - m_stretcher->setTimeRatio(1.1); // fill up temporarily - } else if (rs > 8192) { -// cerr << "temporary reduction (have " << rs << ", want " << m_reserve << ")" << endl; - m_stretcher->setTimeRatio(0.9); // reduce temporarily - } else { - m_stretcher->setTimeRatio(1.0); - } - - while (processed < samples) { - - // never feed more than the minimum necessary number of - // samples at a time; ensures nothing will overflow internally - // and we don't need to call setMaxProcessSize - - int toCauseProcessing = m_stretcher->getSamplesRequired(); - int inchunk = min(samples - processed, toCauseProcessing); - for (size_t c = 0; c < m_channels; ++c) { - ptrs[c] = &(m_input[c][offset + processed]); - } - m_stretcher->process(ptrs, inchunk, false); - processed += inchunk; - - int avail = m_stretcher->available(); - int writable = m_outputBuffer[0]->getWriteSpace(); - int outchunk = min(avail, writable); - size_t actual = m_stretcher->retrieve(m_scratch, outchunk); - outTotal += actual; - -// incount += inchunk; -// outcount += actual; - -// cout << "avail: " << avail << ", outchunk = " << outchunk; -// if (actual != outchunk) cout << " (" << actual << ")"; -// cout << endl; - - outchunk = actual; - - for (size_t c = 0; c < m_channels; ++c) { - if (int(m_outputBuffer[c]->getWriteSpace()) < outchunk) { - cerr << "RubberBandPitchShifter::runImpl: buffer overrun: chunk = " << outchunk << ", space = " << m_outputBuffer[c]->getWriteSpace() << endl; - } - m_outputBuffer[c]->write(m_scratch[c], outchunk); - } - } - - for (size_t c = 0; c < m_channels; ++c) { - int toRead = m_outputBuffer[c]->getReadSpace(); - if (toRead < samples && c == 0) { - cerr << "RubberBandPitchShifter::runImpl: buffer underrun: required = " << samples << ", available = " << toRead << endl; - } - int chunk = min(toRead, samples); - m_outputBuffer[c]->read(&(m_output[c][offset]), chunk); - } - - if (m_minfill == 0) { - m_minfill = m_outputBuffer[0]->getReadSpace(); -// cerr << "minfill = " << m_minfill << endl; - } -} - -void -RubberBandPitchShifter::deactivate(LADSPA_Handle handle) -{ - activate(handle); // both functions just reset the plugin -} - -void -RubberBandPitchShifter::cleanup(LADSPA_Handle handle) -{ - delete (RubberBandPitchShifter *)handle; -} - diff --git a/libs/rubberband/src/ladspa/RubberBandPitchShifter.h b/libs/rubberband/src/ladspa/RubberBandPitchShifter.h deleted file mode 100644 index f2f351bff6..0000000000 --- a/libs/rubberband/src/ladspa/RubberBandPitchShifter.h +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#ifndef _RUBBERBAND_PITCH_SHIFTER_H_ -#define _RUBBERBAND_PITCH_SHIFTER_H_ - -#include <ladspa.h> - -#include "RingBuffer.h" - -namespace RubberBand { -class RubberBandStretcher; -} - -class RubberBandPitchShifter -{ -public: - static const LADSPA_Descriptor *getDescriptor(unsigned long index); - -protected: - RubberBandPitchShifter(int sampleRate, size_t channels); - ~RubberBandPitchShifter(); - - enum { - LatencyPort = 0, - OctavesPort = 1, - SemitonesPort = 2, - CentsPort = 3, - CrispnessPort = 4, - FormantPort = 5, - FastPort = 6, - InputPort1 = 7, - OutputPort1 = 8, - PortCountMono = OutputPort1 + 1, - InputPort2 = 9, - OutputPort2 = 10, - PortCountStereo = OutputPort2 + 1 - }; - - static const char *const portNamesMono[PortCountMono]; - static const LADSPA_PortDescriptor portsMono[PortCountMono]; - static const LADSPA_PortRangeHint hintsMono[PortCountMono]; - - static const char *const portNamesStereo[PortCountStereo]; - static const LADSPA_PortDescriptor portsStereo[PortCountStereo]; - static const LADSPA_PortRangeHint hintsStereo[PortCountStereo]; - - static const LADSPA_Properties properties; - - static const LADSPA_Descriptor ladspaDescriptorMono; - static const LADSPA_Descriptor ladspaDescriptorStereo; - - static LADSPA_Handle instantiate(const LADSPA_Descriptor *, unsigned long); - static void connectPort(LADSPA_Handle, unsigned long, LADSPA_Data *); - static void activate(LADSPA_Handle); - static void run(LADSPA_Handle, unsigned long); - static void deactivate(LADSPA_Handle); - static void cleanup(LADSPA_Handle); - - void activateImpl(); - void runImpl(unsigned long); - void runImpl(unsigned long, unsigned long offset); - void updateRatio(); - void updateCrispness(); - void updateFormant(); - void updateFast(); - - float *m_input[2]; - float *m_output[2]; - float *m_latency; - float *m_cents; - float *m_semitones; - float *m_octaves; - float *m_crispness; - float *m_formant; - float *m_fast; - double m_ratio; - double m_prevRatio; - int m_currentCrispness; - bool m_currentFormant; - bool m_currentFast; - - size_t m_blockSize; - size_t m_reserve; - size_t m_minfill; - - RubberBand::RubberBandStretcher *m_stretcher; - RubberBand::RingBuffer<float> *m_outputBuffer[2]; - float *m_scratch[2]; - - int m_sampleRate; - size_t m_channels; -}; - - -#endif diff --git a/libs/rubberband/src/ladspa/ladspa-rubberband.cat b/libs/rubberband/src/ladspa/ladspa-rubberband.cat deleted file mode 100644 index 438e9a3909..0000000000 --- a/libs/rubberband/src/ladspa/ladspa-rubberband.cat +++ /dev/null @@ -1,2 +0,0 @@ -ladspa:ladspa-rubberband:rubberband-pitchshifter-mono::Frequency > Pitch shifters -ladspa:ladspa-rubberband:rubberband-pitchshifter-stereo::Frequency > Pitch shifters diff --git a/libs/rubberband/src/ladspa/libmain.cpp b/libs/rubberband/src/ladspa/libmain.cpp deleted file mode 100644 index d949e81898..0000000000 --- a/libs/rubberband/src/ladspa/libmain.cpp +++ /dev/null @@ -1,26 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#include "RubberBandPitchShifter.h" - -#include <stdio.h> - -extern "C" { - -const LADSPA_Descriptor *ladspa_descriptor(unsigned long index) -{ - return RubberBandPitchShifter::getDescriptor(index); -} - -} diff --git a/libs/rubberband/src/main.cpp b/libs/rubberband/src/main.cpp deleted file mode 100644 index 1c80696180..0000000000 --- a/libs/rubberband/src/main.cpp +++ /dev/null @@ -1,531 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#include "RubberBandStretcher.h" - -#include <cstring> -#include <iostream> -#include <sndfile.h> -#include <cmath> -#include <time.h> -#include <cstdlib> -#include <cstring> -#include "sysutils.h" - -#ifdef __MSVC__ -#include "bsd-3rdparty/getopt/getopt.h" -#else -#include <getopt.h> -#include <sys/time.h> -#include <unistd.h> -#endif - -#include "Profiler.h" - -using namespace std; -using namespace RubberBand; - -#ifdef _WIN32 -using RubberBand::gettimeofday; -using RubberBand::usleep; -#endif - -double tempo_convert(const char *str) -{ - const char *d = strchr(str, ':'); - - if (!d || !*d) { - double m = atof(str); - if (m != 0.0) return 1.0 / m; - else return 1.0; - } - - char *a = strdup(str); - char *b = strdup(d+1); - a[d-str] = '\0'; - double m = atof(a); - double n = atof(b); - free(a); - free(b); - if (n != 0.0 && m != 0.0) return m / n; - else return 1.0; -} - -int main(int argc, char **argv) -{ - int c; - - double ratio = 1.0; - double duration = 0.0; - double pitchshift = 0.0; - double frequencyshift = 1.0; - int debug = 0; - bool realtime = false; - bool precise = false; - int threading = 0; - bool lamination = true; - bool longwin = false; - bool shortwin = false; - bool hqpitch = false; - bool formant = false; - bool crispchanged = false; - int crispness = -1; - bool help = false; - bool version = false; - bool quiet = false; - - bool haveRatio = false; - - enum { - NoTransients, - BandLimitedTransients, - Transients - } transients = Transients; - - while (1) { - int optionIndex = 0; - - static struct option longOpts[] = { - { "help", 0, 0, 'h' }, - { "version", 0, 0, 'V' }, - { "time", 1, 0, 't' }, - { "tempo", 1, 0, 'T' }, - { "duration", 1, 0, 'D' }, - { "pitch", 1, 0, 'p' }, - { "frequency", 1, 0, 'f' }, - { "crisp", 1, 0, 'c' }, - { "crispness", 1, 0, 'c' }, - { "debug", 1, 0, 'd' }, - { "realtime", 0, 0, 'R' }, - { "precise", 0, 0, 'P' }, - { "formant", 0, 0, 'F' }, - { "no-threads", 0, 0, '0' }, - { "no-transients", 0, 0, '1' }, - { "no-lamination", 0, 0, '2' }, - { "window-long", 0, 0, '3' }, - { "window-short", 0, 0, '4' }, - { "bl-transients", 0, 0, '8' }, - { "pitch-hq", 0, 0, '%' }, - { "threads", 0, 0, '@' }, - { "quiet", 0, 0, 'q' }, - { 0, 0, 0, '\0' } - }; - - c = getopt_long(argc, argv, "t:p:d:RPFc:f:T:D:qhV", longOpts, &optionIndex); - if (c == -1) break; - - switch (c) { - case 'h': help = true; break; - case 'V': version = true; break; - case 't': ratio *= atof(optarg); haveRatio = true; break; - case 'T': ratio *= tempo_convert(optarg); haveRatio = true; break; - case 'D': duration = atof(optarg); haveRatio = true; break; - case 'p': pitchshift = atof(optarg); haveRatio = true; break; - case 'f': frequencyshift = atof(optarg); haveRatio = true; break; - case 'd': debug = atoi(optarg); break; - case 'R': realtime = true; break; - case 'P': precise = true; break; - case 'F': formant = true; break; - case '0': threading = 1; break; - case '@': threading = 2; break; - case '1': transients = NoTransients; crispchanged = true; break; - case '2': lamination = false; crispchanged = true; break; - case '3': longwin = true; crispchanged = true; break; - case '4': shortwin = true; crispchanged = true; break; - case '8': transients = BandLimitedTransients; crispchanged = true; break; - case '%': hqpitch = true; break; - case 'c': crispness = atoi(optarg); break; - case 'q': quiet = true; break; - default: help = true; break; - } - } - - if (version) { - cerr << RUBBERBAND_VERSION << endl; - return 0; - } - - if (help || !haveRatio || optind + 2 != argc) { - cerr << endl; - cerr << "Rubber Band" << endl; - cerr << "An audio time-stretching and pitch-shifting library and utility program." << endl; - cerr << "Copyright 2008 Chris Cannam. Distributed under the GNU General Public License." << endl; - cerr << endl; - cerr << " Usage: " << argv[0] << " [options] <infile.wav> <outfile.wav>" << endl; - cerr << endl; - cerr << "You must specify at least one of the following time and pitch ratio options." << endl; - cerr << endl; - cerr << " -t<X>, --time <X> Stretch to X times original duration, or" << endl; - cerr << " -T<X>, --tempo <X> Change tempo by multiple X (same as --time 1/X), or" << endl; - cerr << " -T<X>, --tempo <X>:<Y> Change tempo from X to Y (same as --time X/Y), or" << endl; - cerr << " -D<X>, --duration <X> Stretch or squash to make output file X seconds long" << endl; - cerr << endl; - cerr << " -p<X>, --pitch <X> Raise pitch by X semitones, or" << endl; - cerr << " -f<X>, --frequency <X> Change frequency by multiple X" << endl; - cerr << endl; - cerr << "The following options provide a simple way to adjust the sound. See below" << endl; - cerr << "for more details." << endl; - cerr << endl; - cerr << " -c<N>, --crisp <N> Crispness (N = 0,1,2,3,4,5); default 4 (see below)" << endl; - cerr << " -F, --formant Enable formant preservation when pitch shifting" << endl; - cerr << endl; - cerr << "The remaining options fine-tune the processing mode and stretch algorithm." << endl; - cerr << "These are mostly included for test purposes; the default settings and standard" << endl; - cerr << "crispness parameter are intended to provide the best sounding set of options" << endl; - cerr << "for most situations. The default is to use none of these options." << endl; - cerr << endl; - cerr << " -P, --precise Aim for minimal time distortion (implied by -R)" << endl; - cerr << " -R, --realtime Select realtime mode (implies -P --no-threads)" << endl; - cerr << " --no-threads No extra threads regardless of CPU and channel count" << endl; - cerr << " --threads Assume multi-CPU even if only one CPU is identified" << endl; - cerr << " --no-transients Disable phase resynchronisation at transients" << endl; - cerr << " --bl-transients Band-limit phase resync to extreme frequencies" << endl; - cerr << " --no-lamination Disable phase lamination" << endl; - cerr << " --window-long Use longer processing window (actual size may vary)" << endl; - cerr << " --window-short Use shorter processing window" << endl; - cerr << " --pitch-hq In RT mode, use a slower, higher quality pitch shift" << endl; - cerr << endl; - cerr << " -d<N>, --debug <N> Select debug level (N = 0,1,2,3); default 0, full 3" << endl; - cerr << " (N.B. debug level 3 includes audible ticks in output)" << endl; - cerr << " -q, --quiet Suppress progress output" << endl; - cerr << endl; - cerr << " -V, --version Show version number and exit" << endl; - cerr << " -h, --help Show this help" << endl; - cerr << endl; - cerr << "\"Crispness\" levels:" << endl; - cerr << " -c 0 equivalent to --no-transients --no-lamination --window-long" << endl; - cerr << " -c 1 equivalent to --no-transients --no-lamination" << endl; - cerr << " -c 2 equivalent to --no-transients" << endl; - cerr << " -c 3 equivalent to --bl-transients" << endl; - cerr << " -c 4 default processing options" << endl; - cerr << " -c 5 equivalent to --no-lamination --window-short (may be good for drums)" << endl; - cerr << endl; - return 2; - } - - if (crispness >= 0 && crispchanged) { - cerr << "WARNING: Both crispness option and transients, lamination or window options" << endl; - cerr << " provided -- crispness will override these other options" << endl; - } - - switch (crispness) { - case -1: crispness = 4; break; - case 0: transients = NoTransients; lamination = false; longwin = true; shortwin = false; break; - case 1: transients = NoTransients; lamination = false; longwin = false; shortwin = false; break; - case 2: transients = NoTransients; lamination = true; longwin = false; shortwin = false; break; - case 3: transients = BandLimitedTransients; lamination = true; longwin = false; shortwin = false; break; - case 4: transients = Transients; lamination = true; longwin = false; shortwin = false; break; - case 5: transients = Transients; lamination = false; longwin = false; shortwin = true; break; - }; - - if (!quiet) { - cerr << "Using crispness level: " << crispness << " ("; - switch (crispness) { - case 0: cerr << "Mushy"; break; - case 1: cerr << "Smooth"; break; - case 2: cerr << "Balanced multitimbral mixture"; break; - case 3: cerr << "Unpitched percussion with stable notes"; break; - case 4: cerr << "Crisp monophonic instrumental"; break; - case 5: cerr << "Unpitched solo percussion"; break; - } - cerr << ")" << endl; - } - - char *fileName = strdup(argv[optind++]); - char *fileNameOut = strdup(argv[optind++]); - - SNDFILE *sndfile; - SNDFILE *sndfileOut; - SF_INFO sfinfo; - SF_INFO sfinfoOut; - memset(&sfinfo, 0, sizeof(SF_INFO)); - - sndfile = sf_open(fileName, SFM_READ, &sfinfo); - if (!sndfile) { - cerr << "ERROR: Failed to open input file \"" << fileName << "\": " - << sf_strerror(sndfile) << endl; - return 1; - } - - if (duration != 0.0) { - if (sfinfo.frames == 0 || sfinfo.samplerate == 0) { - cerr << "ERROR: File lacks frame count or sample rate in header, cannot use --duration" << endl; - return 1; - } - double induration = double(sfinfo.frames) / double(sfinfo.samplerate); - if (induration != 0.0) ratio = duration / induration; - } - - sfinfoOut.channels = sfinfo.channels; - sfinfoOut.format = sfinfo.format; - sfinfoOut.frames = int(sfinfo.frames * ratio + 0.1); - sfinfoOut.samplerate = sfinfo.samplerate; - sfinfoOut.sections = sfinfo.sections; - sfinfoOut.seekable = sfinfo.seekable; - - sndfileOut = sf_open(fileNameOut, SFM_WRITE, &sfinfoOut) ; - if (!sndfileOut) { - cerr << "ERROR: Failed to open output file \"" << fileNameOut << "\" for writing: " - << sf_strerror(sndfileOut) << endl; - return 1; - } - - int ibs = 1024; - size_t channels = sfinfo.channels; - - RubberBandStretcher::Options options = 0; - if (realtime) options |= RubberBandStretcher::OptionProcessRealTime; - if (precise) options |= RubberBandStretcher::OptionStretchPrecise; - if (!lamination) options |= RubberBandStretcher::OptionPhaseIndependent; - if (longwin) options |= RubberBandStretcher::OptionWindowLong; - if (shortwin) options |= RubberBandStretcher::OptionWindowShort; - if (formant) options |= RubberBandStretcher::OptionFormantPreserved; - if (hqpitch) options |= RubberBandStretcher::OptionPitchHighQuality; - - switch (threading) { - case 0: - options |= RubberBandStretcher::OptionThreadingAuto; - break; - case 1: - options |= RubberBandStretcher::OptionThreadingNever; - break; - case 2: - options |= RubberBandStretcher::OptionThreadingAlways; - break; - } - - switch (transients) { - case NoTransients: - options |= RubberBandStretcher::OptionTransientsSmooth; - break; - case BandLimitedTransients: - options |= RubberBandStretcher::OptionTransientsMixed; - break; - case Transients: - options |= RubberBandStretcher::OptionTransientsCrisp; - break; - } - - if (pitchshift != 0.0) { - frequencyshift *= pow(2.0, pitchshift / 12); - } - - cerr << "Using time ratio " << ratio; - cerr << " and frequency ratio " << frequencyshift << endl; - -#ifdef _WIN32 - RubberBand:: -#endif - timeval tv; - (void)gettimeofday(&tv, 0); - - RubberBandStretcher::setDefaultDebugLevel(debug); - - RubberBandStretcher ts(sfinfo.samplerate, channels, options, - ratio, frequencyshift); - - ts.setExpectedInputDuration(sfinfo.frames); - - float *fbuf = new float[channels * ibs]; - float **ibuf = new float *[channels]; - for (size_t i = 0; i < channels; ++i) ibuf[i] = new float[ibs]; - - int frame = 0; - int percent = 0; - - sf_seek(sndfile, 0, SEEK_SET); - - if (!realtime) { - - if (!quiet) { - cerr << "Pass 1: Studying..." << endl; - } - - while (frame < sfinfo.frames) { - - int count = -1; - - if ((count = sf_readf_float(sndfile, fbuf, ibs)) <= 0) break; - - for (size_t c = 0; c < channels; ++c) { - for (int i = 0; i < count; ++i) { - float value = fbuf[i * channels + c]; - ibuf[c][i] = value; - } - } - - bool final = (frame + ibs >= sfinfo.frames); - - ts.study(ibuf, count, final); - - int p = int((double(frame) * 100.0) / sfinfo.frames); - if (p > percent || frame == 0) { - percent = p; - if (!quiet) { - cerr << "\r" << percent << "% "; - } - } - - frame += ibs; - } - - if (!quiet) { - cerr << "\rCalculating profile..." << endl; - } - - sf_seek(sndfile, 0, SEEK_SET); - } - - frame = 0; - percent = 0; - - size_t countIn = 0, countOut = 0; - - while (frame < sfinfo.frames) { - - int count = -1; - - if ((count = sf_readf_float(sndfile, fbuf, ibs)) < 0) break; - - countIn += count; - - for (size_t c = 0; c < channels; ++c) { - for (int i = 0; i < count; ++i) { - float value = fbuf[i * channels + c]; - ibuf[c][i] = value; - } - } - - bool final = (frame + ibs >= sfinfo.frames); - - ts.process(ibuf, count, final); - - int avail = ts.available(); - if (debug > 1) cerr << "available = " << avail << endl; - - if (avail > 0) { - float **obf = new float *[channels]; - for (size_t i = 0; i < channels; ++i) { - obf[i] = new float[avail]; - } - ts.retrieve(obf, avail); - countOut += avail; - float *fobf = new float[channels * avail]; - for (size_t c = 0; c < channels; ++c) { - for (int i = 0; i < avail; ++i) { - float value = obf[c][i]; - if (value > 1.f) value = 1.f; - if (value < -1.f) value = -1.f; - fobf[i * channels + c] = value; - } - } -// cout << "fobf mean: "; -// double d = 0; -// for (int i = 0; i < avail; ++i) { -// d += fobf[i]; -// } -// d /= avail; -// cout << d << endl; - sf_writef_float(sndfileOut, fobf, avail); - delete[] fobf; - for (size_t i = 0; i < channels; ++i) { - delete[] obf[i]; - } - delete[] obf; - } - - if (frame == 0 && !realtime && !quiet) { - cerr << "Pass 2: Processing..." << endl; - } - - int p = int((double(frame) * 100.0) / sfinfo.frames); - if (p > percent || frame == 0) { - percent = p; - if (!quiet) { - cerr << "\r" << percent << "% "; - } - } - - frame += ibs; - } - - if (!quiet) { - cerr << "\r " << endl; - } - int avail; - - while ((avail = ts.available()) >= 0) { - - if (debug > 1) { - cerr << "(completing) available = " << avail << endl; - } - - if (avail > 0) { - float **obf = new float *[channels]; - for (size_t i = 0; i < channels; ++i) { - obf[i] = new float[avail]; - } - ts.retrieve(obf, avail); - countOut += avail; - float *fobf = new float[channels * avail]; - for (size_t c = 0; c < channels; ++c) { - for (int i = 0; i < avail; ++i) { - float value = obf[c][i]; - if (value > 1.f) value = 1.f; - if (value < -1.f) value = -1.f; - fobf[i * channels + c] = value; - } - } - - sf_writef_float(sndfileOut, fobf, avail); - delete[] fobf; - for (size_t i = 0; i < channels; ++i) { - delete[] obf[i]; - } - delete[] obf; - } else { - usleep(10000); - } - } - - sf_close(sndfile); - sf_close(sndfileOut); - - if (!quiet) { - - cerr << "in: " << countIn << ", out: " << countOut << ", ratio: " << float(countOut)/float(countIn) << ", ideal output: " << lrint(countIn * ratio) << ", error: " << abs(lrint(countIn * ratio) - int(countOut)) << endl; - -#ifdef _WIN32 - RubberBand:: -#endif - timeval etv; - (void)gettimeofday(&etv, 0); - - etv.tv_sec -= tv.tv_sec; - if (etv.tv_usec < tv.tv_usec) { - etv.tv_usec += 1000000; - etv.tv_sec -= 1; - } - etv.tv_usec -= tv.tv_usec; - - double sec = double(etv.tv_sec) + (double(etv.tv_usec) / 1000000.0); - cerr << "elapsed time: " << sec << " sec, in frames/sec: " << countIn/sec << ", out frames/sec: " << countOut/sec << endl; - } - - Profiler::dump(); - - return 0; -} - - diff --git a/libs/rubberband/src/rubberband-c.cpp b/libs/rubberband/src/rubberband-c.cpp deleted file mode 100644 index 7bdd701ddf..0000000000 --- a/libs/rubberband/src/rubberband-c.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#include "rubberband-c.h" -#include "RubberBandStretcher.h" - -struct RubberBandState_ -{ - RubberBand::RubberBandStretcher *m_s; -}; - -RubberBandState rubberband_new(unsigned int sampleRate, - unsigned int channels, - RubberBandOptions options, - double initialTimeRatio, - double initialPitchScale) -{ - RubberBandState_ *state = new RubberBandState_(); - state->m_s = new RubberBand::RubberBandStretcher - (sampleRate, channels, options, - initialTimeRatio, initialPitchScale); - return state; -} - -void rubberband_delete(RubberBandState state) -{ - delete state->m_s; - delete state; -} - -void rubberband_reset(RubberBandState state) -{ - state->m_s->reset(); -} - -void rubberband_set_time_ratio(RubberBandState state, double ratio) -{ - state->m_s->setTimeRatio(ratio); -} - -void rubberband_set_pitch_scale(RubberBandState state, double scale) -{ - state->m_s->setPitchScale(scale); -} - -double rubberband_get_time_ratio(const RubberBandState state) -{ - return state->m_s->getTimeRatio(); -} - -double rubberband_get_pitch_scale(const RubberBandState state) -{ - return state->m_s->getPitchScale(); -} - -unsigned int rubberband_get_latency(const RubberBandState state) -{ - return state->m_s->getLatency(); -} - -void rubberband_set_transients_option(RubberBandState state, RubberBandOptions options) -{ - state->m_s->setTransientsOption(options); -} - -void rubberband_set_phase_option(RubberBandState state, RubberBandOptions options) -{ - state->m_s->setPhaseOption(options); -} - -void rubberband_set_formant_option(RubberBandState state, RubberBandOptions options) -{ - state->m_s->setFormantOption(options); -} - -void rubberband_set_pitch_option(RubberBandState state, RubberBandOptions options) -{ - state->m_s->setPitchOption(options); -} - -void rubberband_set_expected_input_duration(RubberBandState state, unsigned int samples) -{ - state->m_s->setExpectedInputDuration(samples); -} - -unsigned int rubberband_get_samples_required(const RubberBandState state) -{ - return state->m_s->getSamplesRequired(); -} - -void rubberband_set_max_process_size(RubberBandState state, unsigned int samples) -{ - state->m_s->setMaxProcessSize(samples); -} - -void rubberband_study(RubberBandState state, const float *const *input, unsigned int samples, int final) -{ - state->m_s->study(input, samples, final != 0); -} - -void rubberband_process(RubberBandState state, const float *const *input, unsigned int samples, int final) -{ - state->m_s->process(input, samples, final != 0); -} - -int rubberband_available(const RubberBandState state) -{ - return state->m_s->available(); -} - -unsigned int rubberband_retrieve(const RubberBandState state, float *const *output, unsigned int samples) -{ - return state->m_s->retrieve(output, samples); -} - -unsigned int rubberband_get_channel_count(const RubberBandState state) -{ - return state->m_s->getChannelCount(); -} - -void rubberband_calculate_stretch(RubberBandState state) -{ - state->m_s->calculateStretch(); -} - -void rubberband_set_debug_level(RubberBandState state, int level) -{ - state->m_s->setDebugLevel(level); -} - -void rubberband_set_default_debug_level(int level) -{ - RubberBand::RubberBandStretcher::setDefaultDebugLevel(level); -} - diff --git a/libs/rubberband/src/sysutils.cpp b/libs/rubberband/src/sysutils.cpp deleted file mode 100644 index 902b1267ab..0000000000 --- a/libs/rubberband/src/sysutils.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#include "sysutils.h" - -#ifdef _WIN32 -#include <windows.h> -#else /* !_WIN32 */ -#ifdef __APPLE__ -#include <sys/sysctl.h> -#else /* !__APPLE__, !_WIN32 */ -#include <cstdio> -#include <cstring> -#endif /* !__APPLE__, !_WIN32 */ -#endif /* !_WIN32 */ - -#include <cstdlib> -#include <iostream> - -namespace RubberBand { - -bool -system_is_multiprocessor() -{ - static bool tested = false, mp = false; - - if (tested) return mp; - int count = 0; - -#ifdef _WIN32 - - SYSTEM_INFO sysinfo; - GetSystemInfo(&sysinfo); - count = sysinfo.dwNumberOfProcessors; - -#else /* !_WIN32 */ -#ifdef __APPLE__ - - size_t sz = sizeof(count); - if (sysctlbyname("hw.ncpu", &count, &sz, NULL, 0)) { - mp = false; - } else { - mp = (count > 1); - } - -#else /* !__APPLE__, !_WIN32 */ - - //... - - FILE *cpuinfo = fopen("/proc/cpuinfo", "r"); - if (!cpuinfo) return false; - - char buf[256]; - while (!feof(cpuinfo)) { - fgets(buf, 256, cpuinfo); - if (!strncmp(buf, "processor", 9)) { - ++count; - } - if (count > 1) break; - } - - fclose(cpuinfo); - -#endif /* !__APPLE__, !_WIN32 */ -#endif /* !_WIN32 */ - - mp = (count > 1); - tested = true; - return mp; -} - -#ifdef _WIN32 - -int gettimeofday(struct timeval *tv, void *tz) -{ - union { - long long ns100; - FILETIME ft; - } now; - - ::GetSystemTimeAsFileTime(&now.ft); - tv->tv_usec = (long)((now.ns100 / 10LL) % 1000000LL); - tv->tv_sec = (long)((now.ns100 - 116444736000000000LL) / 10000000LL); - return 0; -} - -void usleep(unsigned long usec) -{ - ::Sleep(usec == 0 ? 0 : usec < 1000 ? 1 : usec / 1000); -} - -#endif - - -float *allocFloat(float *ptr, int count) -{ - if (ptr) free((void *)ptr); - void *allocated; -#ifndef _WIN32 -#ifndef __APPLE__ - if (posix_memalign(&allocated, 16, count * sizeof(float))) -#endif -#endif - allocated = malloc(count * sizeof(float)); - for (int i = 0; i < count; ++i) ((float *)allocated)[i] = 0.f; - return (float *)allocated; -} - -float *allocFloat(int count) -{ - return allocFloat(0, count); -} - -void freeFloat(float *ptr) -{ - if (ptr) free(ptr); -} - -double *allocDouble(double *ptr, int count) -{ - if (ptr) free((void *)ptr); - void *allocated; -#ifndef _WIN32 -#ifndef __APPLE__ - if (posix_memalign(&allocated, 16, count * sizeof(double))) -#endif -#endif - allocated = malloc(count * sizeof(double)); - for (int i = 0; i < count; ++i) ((double *)allocated)[i] = 0.f; - return (double *)allocated; -} - -double *allocDouble(int count) -{ - return allocDouble(0, count); -} - -void freeDouble(double *ptr) -{ - if (ptr) free(ptr); -} - - -} - - - diff --git a/libs/rubberband/src/sysutils.h b/libs/rubberband/src/sysutils.h deleted file mode 100644 index a529afde0d..0000000000 --- a/libs/rubberband/src/sysutils.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#ifndef _RUBBERBAND_SYSINFO_H_ -#define _RUBBERBAND_SYSINFO_H_ - -#ifdef __MSVC__ -#include "bsd-3rdparty/float_cast/float_cast.h" -#define R__ __restrict -#endif - -#ifdef __GNUC__ -#define R__ __restrict__ -#endif - -#ifndef R__ -#define R__ -#endif - -#ifdef __MINGW32__ -#include <malloc.h> -#endif - -#ifdef __MSVC__ -#define alloca _alloca -#endif - -namespace RubberBand { - -extern bool system_is_multiprocessor(); - -#ifdef _WIN32 - -struct timeval { long tv_sec; long tv_usec; }; -int gettimeofday(struct timeval *p, void *tz); - -void usleep(unsigned long); - -#endif - -extern float *allocFloat(int); -extern float *allocFloat(float *, int); -extern void freeFloat(float *); - -extern double *allocDouble(int); -extern double *allocDouble(double *, int); -extern void freeDouble(double *); - -} - -#endif diff --git a/libs/rubberband/src/vamp/RubberBandVampPlugin.cpp b/libs/rubberband/src/vamp/RubberBandVampPlugin.cpp deleted file mode 100644 index feb5bfa6bb..0000000000 --- a/libs/rubberband/src/vamp/RubberBandVampPlugin.cpp +++ /dev/null @@ -1,648 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#include "RubberBandVampPlugin.h" - -#include "StretchCalculator.h" -#include "sysutils.h" - -#include <cmath> - -using std::string; -using std::vector; -using std::cerr; -using std::endl; - -class RubberBandVampPlugin::Impl -{ -public: - size_t m_stepSize; - size_t m_blockSize; - size_t m_sampleRate; - - float m_timeRatio; - float m_pitchRatio; - - bool m_realtime; - bool m_elasticTiming; - int m_transientMode; - bool m_phaseIndependent; - int m_windowLength; - - RubberBand::RubberBandStretcher *m_stretcher; - - int m_incrementsOutput; - int m_aggregateIncrementsOutput; - int m_divergenceOutput; - int m_phaseResetDfOutput; - int m_smoothedPhaseResetDfOutput; - int m_phaseResetPointsOutput; - int m_timeSyncPointsOutput; - - size_t m_counter; - size_t m_accumulatedIncrement; - - float **m_outputDump; - - FeatureSet processOffline(const float *const *inputBuffers, - Vamp::RealTime timestamp); - - FeatureSet getRemainingFeaturesOffline(); - - FeatureSet processRealTime(const float *const *inputBuffers, - Vamp::RealTime timestamp); - - FeatureSet getRemainingFeaturesRealTime(); - - FeatureSet createFeatures(size_t inputIncrement, - std::vector<int> &outputIncrements, - std::vector<float> &phaseResetDf, - std::vector<int> &exactPoints, - std::vector<float> &smoothedDf, - size_t baseCount, - bool includeFinal); -}; - - -RubberBandVampPlugin::RubberBandVampPlugin(float inputSampleRate) : - Plugin(inputSampleRate) -{ - m_d = new Impl(); - m_d->m_stepSize = 0; - m_d->m_timeRatio = 1.f; - m_d->m_pitchRatio = 1.f; - m_d->m_realtime = false; - m_d->m_elasticTiming = true; - m_d->m_transientMode = 0; - m_d->m_phaseIndependent = false; - m_d->m_windowLength = 0; - m_d->m_stretcher = 0; - m_d->m_sampleRate = lrintf(m_inputSampleRate); -} - -RubberBandVampPlugin::~RubberBandVampPlugin() -{ - if (m_d->m_outputDump) { - for (size_t i = 0; i < m_d->m_stretcher->getChannelCount(); ++i) { - delete[] m_d->m_outputDump[i]; - } - delete[] m_d->m_outputDump; - } - delete m_d->m_stretcher; - delete m_d; -} - -string -RubberBandVampPlugin::getIdentifier() const -{ - return "rubberband"; -} - -string -RubberBandVampPlugin::getName() const -{ - return "Rubber Band Timestretch Analysis"; -} - -string -RubberBandVampPlugin::getDescription() const -{ - return "Carry out analysis phases of time stretcher process"; -} - -string -RubberBandVampPlugin::getMaker() const -{ - return "Breakfast Quay"; -} - -int -RubberBandVampPlugin::getPluginVersion() const -{ - return 1; -} - -string -RubberBandVampPlugin::getCopyright() const -{ - return "";//!!! -} - -RubberBandVampPlugin::OutputList -RubberBandVampPlugin::getOutputDescriptors() const -{ - OutputList list; - - size_t rate = 0; - if (m_d->m_stretcher) { - rate = lrintf(m_inputSampleRate / m_d->m_stretcher->getInputIncrement()); - } - - OutputDescriptor d; - d.identifier = "increments"; - d.name = "Output Increments"; - d.description = "Output time increment for each input step"; - d.unit = "samples"; - d.hasFixedBinCount = true; - d.binCount = 1; - d.hasKnownExtents = false; - d.isQuantized = true; - d.quantizeStep = 1.0; - d.sampleType = OutputDescriptor::VariableSampleRate; - d.sampleRate = float(rate); - m_d->m_incrementsOutput = list.size(); - list.push_back(d); - - d.identifier = "aggregate_increments"; - d.name = "Accumulated Output Increments"; - d.description = "Accumulated output time increments"; - d.sampleRate = 0; - m_d->m_aggregateIncrementsOutput = list.size(); - list.push_back(d); - - d.identifier = "divergence"; - d.name = "Divergence from Linear"; - d.description = "Difference between actual output time and the output time for a theoretical linear stretch"; - d.isQuantized = false; - d.sampleRate = 0; - m_d->m_divergenceOutput = list.size(); - list.push_back(d); - - d.identifier = "phaseresetdf"; - d.name = "Phase Reset Detection Function"; - d.description = "Curve whose peaks are used to identify transients for phase reset points"; - d.unit = ""; - d.sampleRate = float(rate); - m_d->m_phaseResetDfOutput = list.size(); - list.push_back(d); - - d.identifier = "smoothedphaseresetdf"; - d.name = "Smoothed Phase Reset Detection Function"; - d.description = "Phase reset curve smoothed for peak picking"; - d.unit = ""; - m_d->m_smoothedPhaseResetDfOutput = list.size(); - list.push_back(d); - - d.identifier = "phaseresetpoints"; - d.name = "Phase Reset Points"; - d.description = "Points estimated as transients at which phase reset occurs"; - d.unit = ""; - d.hasFixedBinCount = true; - d.binCount = 0; - d.hasKnownExtents = false; - d.isQuantized = false; - d.sampleRate = 0; - m_d->m_phaseResetPointsOutput = list.size(); - list.push_back(d); - - d.identifier = "timesyncpoints"; - d.name = "Time Sync Points"; - d.description = "Salient points which stretcher aims to place with strictly correct timing"; - d.unit = ""; - d.hasFixedBinCount = true; - d.binCount = 0; - d.hasKnownExtents = false; - d.isQuantized = false; - d.sampleRate = 0; - m_d->m_timeSyncPointsOutput = list.size(); - list.push_back(d); - - return list; -} - -RubberBandVampPlugin::ParameterList -RubberBandVampPlugin::getParameterDescriptors() const -{ - ParameterList list; - - ParameterDescriptor d; - d.identifier = "timeratio"; - d.name = "Time Ratio"; - d.description = "Ratio to modify overall duration by"; - d.unit = "%"; - d.minValue = 1; - d.maxValue = 500; - d.defaultValue = 100; - d.isQuantized = false; - list.push_back(d); - - d.identifier = "pitchratio"; - d.name = "Pitch Scale Ratio"; - d.description = "Frequency ratio to modify pitch by"; - d.unit = "%"; - d.minValue = 1; - d.maxValue = 500; - d.defaultValue = 100; - d.isQuantized = false; - list.push_back(d); - - d.identifier = "mode"; - d.name = "Processing Mode"; - d.description = ""; //!!! - d.unit = ""; - d.minValue = 0; - d.maxValue = 1; - d.defaultValue = 0; - d.isQuantized = true; - d.quantizeStep = 1; - d.valueNames.clear(); - d.valueNames.push_back("Offline"); - d.valueNames.push_back("Real Time"); - list.push_back(d); - - d.identifier = "stretchtype"; - d.name = "Stretch Flexibility"; - d.description = ""; //!!! - d.unit = ""; - d.minValue = 0; - d.maxValue = 1; - d.defaultValue = 0; - d.isQuantized = true; - d.quantizeStep = 1; - d.valueNames.clear(); - d.valueNames.push_back("Elastic"); - d.valueNames.push_back("Precise"); - list.push_back(d); - - d.identifier = "transientmode"; - d.name = "Transient Handling"; - d.description = ""; //!!! - d.unit = ""; - d.minValue = 0; - d.maxValue = 2; - d.defaultValue = 0; - d.isQuantized = true; - d.quantizeStep = 1; - d.valueNames.clear(); - d.valueNames.push_back("Mixed"); - d.valueNames.push_back("Smooth"); - d.valueNames.push_back("Crisp"); - list.push_back(d); - - d.identifier = "phasemode"; - d.name = "Phase Handling"; - d.description = ""; //!!! - d.unit = ""; - d.minValue = 0; - d.maxValue = 1; - d.defaultValue = 0; - d.isQuantized = true; - d.quantizeStep = 1; - d.valueNames.clear(); - d.valueNames.push_back("Peak Locked"); - d.valueNames.push_back("Independent"); - list.push_back(d); - - d.identifier = "windowmode"; - d.name = "Window Length"; - d.description = ""; //!!! - d.unit = ""; - d.minValue = 0; - d.maxValue = 2; - d.defaultValue = 0; - d.isQuantized = true; - d.quantizeStep = 1; - d.valueNames.clear(); - d.valueNames.push_back("Standard"); - d.valueNames.push_back("Short"); - d.valueNames.push_back("Long"); - list.push_back(d); - - return list; -} - -float -RubberBandVampPlugin::getParameter(std::string id) const -{ - if (id == "timeratio") return m_d->m_timeRatio * 100.f; - if (id == "pitchratio") return m_d->m_pitchRatio * 100.f; - if (id == "mode") return m_d->m_realtime ? 1.f : 0.f; - if (id == "stretchtype") return m_d->m_elasticTiming ? 0.f : 1.f; - if (id == "transientmode") return float(m_d->m_transientMode); - if (id == "phasemode") return m_d->m_phaseIndependent ? 1.f : 0.f; - if (id == "windowmode") return float(m_d->m_windowLength); - return 0.f; -} - -void -RubberBandVampPlugin::setParameter(std::string id, float value) -{ - if (id == "timeratio") { - m_d->m_timeRatio = value / 100; - } else if (id == "pitchratio") { - m_d->m_pitchRatio = value / 100; - } else { - bool set = (value > 0.5); - if (id == "mode") m_d->m_realtime = set; - else if (id == "stretchtype") m_d->m_elasticTiming = !set; - else if (id == "transientmode") m_d->m_transientMode = int(value + 0.5); - else if (id == "phasemode") m_d->m_phaseIndependent = set; - else if (id == "windowmode") m_d->m_windowLength = int(value + 0.5); - } -} - -bool -RubberBandVampPlugin::initialise(size_t channels, size_t stepSize, size_t blockSize) -{ - if (channels < getMinChannelCount() || - channels > getMaxChannelCount()) return false; - - m_d->m_stepSize = std::min(stepSize, blockSize); - m_d->m_blockSize = stepSize; - - RubberBand::RubberBandStretcher::Options options = 0; - - if (m_d->m_realtime) - options |= RubberBand::RubberBandStretcher::OptionProcessRealTime; - else options |= RubberBand::RubberBandStretcher::OptionProcessOffline; - - if (m_d->m_elasticTiming) - options |= RubberBand::RubberBandStretcher::OptionStretchElastic; - else options |= RubberBand::RubberBandStretcher::OptionStretchPrecise; - - if (m_d->m_transientMode == 0) - options |= RubberBand::RubberBandStretcher::OptionTransientsMixed; - else if (m_d->m_transientMode == 1) - options |= RubberBand::RubberBandStretcher::OptionTransientsSmooth; - else options |= RubberBand::RubberBandStretcher::OptionTransientsCrisp; - - if (m_d->m_phaseIndependent) - options |= RubberBand::RubberBandStretcher::OptionPhaseIndependent; - else options |= RubberBand::RubberBandStretcher::OptionPhaseLaminar; - - if (m_d->m_windowLength == 0) - options |= RubberBand::RubberBandStretcher::OptionWindowStandard; - else if (m_d->m_windowLength == 1) - options |= RubberBand::RubberBandStretcher::OptionWindowShort; - else options |= RubberBand::RubberBandStretcher::OptionWindowLong; - - delete m_d->m_stretcher; - m_d->m_stretcher = new RubberBand::RubberBandStretcher - (m_d->m_sampleRate, channels, options); - m_d->m_stretcher->setDebugLevel(1); - m_d->m_stretcher->setTimeRatio(m_d->m_timeRatio); - m_d->m_stretcher->setPitchScale(m_d->m_pitchRatio); - - m_d->m_counter = 0; - m_d->m_accumulatedIncrement = 0; - - m_d->m_outputDump = 0; - - return true; -} - -void -RubberBandVampPlugin::reset() -{ -// delete m_stretcher; //!!! or just if (m_stretcher) m_stretcher->reset(); -// m_stretcher = new RubberBand::RubberBandStretcher(lrintf(m_inputSampleRate), channels); - if (m_d->m_stretcher) m_d->m_stretcher->reset(); -} - -RubberBandVampPlugin::FeatureSet -RubberBandVampPlugin::process(const float *const *inputBuffers, - Vamp::RealTime timestamp) -{ - if (m_d->m_realtime) { - return m_d->processRealTime(inputBuffers, timestamp); - } else { - return m_d->processOffline(inputBuffers, timestamp); - } -} - -RubberBandVampPlugin::FeatureSet -RubberBandVampPlugin::getRemainingFeatures() -{ - if (m_d->m_realtime) { - return m_d->getRemainingFeaturesRealTime(); - } else { - return m_d->getRemainingFeaturesOffline(); - } -} - -RubberBandVampPlugin::FeatureSet -RubberBandVampPlugin::Impl::processOffline(const float *const *inputBuffers, - Vamp::RealTime timestamp) -{ - if (!m_stretcher) { - cerr << "ERROR: RubberBandVampPlugin::processOffline: " - << "RubberBandVampPlugin has not been initialised" - << endl; - return FeatureSet(); - } - - m_stretcher->study(inputBuffers, m_blockSize, false); - return FeatureSet(); -} - -RubberBandVampPlugin::FeatureSet -RubberBandVampPlugin::Impl::getRemainingFeaturesOffline() -{ - m_stretcher->study(0, 0, true); - - m_stretcher->calculateStretch(); - - int rate = m_sampleRate; - - RubberBand::StretchCalculator sc(rate, - m_stretcher->getInputIncrement(), - true); - - size_t inputIncrement = m_stretcher->getInputIncrement(); - std::vector<int> outputIncrements = m_stretcher->getOutputIncrements(); - std::vector<float> phaseResetDf = m_stretcher->getPhaseResetCurve(); - std::vector<int> peaks = m_stretcher->getExactTimePoints(); - std::vector<float> smoothedDf = sc.smoothDF(phaseResetDf); - - FeatureSet features = createFeatures - (inputIncrement, outputIncrements, phaseResetDf, peaks, smoothedDf, - 0, true); - - return features; -} - -RubberBandVampPlugin::FeatureSet -RubberBandVampPlugin::Impl::processRealTime(const float *const *inputBuffers, - Vamp::RealTime timestamp) -{ - // This function is not in any way a real-time function (i.e. it - // has no requirement to be RT safe); it simply operates the - // stretcher in RT mode. - - if (!m_stretcher) { - cerr << "ERROR: RubberBandVampPlugin::processRealTime: " - << "RubberBandVampPlugin has not been initialised" - << endl; - return FeatureSet(); - } - - m_stretcher->process(inputBuffers, m_blockSize, false); - - size_t inputIncrement = m_stretcher->getInputIncrement(); - std::vector<int> outputIncrements = m_stretcher->getOutputIncrements(); - std::vector<float> phaseResetDf = m_stretcher->getPhaseResetCurve(); - std::vector<float> smoothedDf; // not meaningful in RT mode - std::vector<int> dummyPoints; - FeatureSet features = createFeatures - (inputIncrement, outputIncrements, phaseResetDf, dummyPoints, smoothedDf, - m_counter, false); - m_counter += outputIncrements.size(); - - int available = 0; - while ((available = m_stretcher->available()) > 0) { - if (!m_outputDump) { - m_outputDump = new float *[m_stretcher->getChannelCount()]; - for (size_t i = 0; i < m_stretcher->getChannelCount(); ++i) { - m_outputDump[i] = new float[m_blockSize]; - } - } - m_stretcher->retrieve(m_outputDump, - std::min(int(m_blockSize), available)); - } - - return features; -} - -RubberBandVampPlugin::FeatureSet -RubberBandVampPlugin::Impl::getRemainingFeaturesRealTime() -{ - return FeatureSet(); -} - -RubberBandVampPlugin::FeatureSet -RubberBandVampPlugin::Impl::createFeatures(size_t inputIncrement, - std::vector<int> &outputIncrements, - std::vector<float> &phaseResetDf, - std::vector<int> &exactPoints, - std::vector<float> &smoothedDf, - size_t baseCount, - bool includeFinal) -{ - size_t actual = m_accumulatedIncrement; - - double overallRatio = m_timeRatio * m_pitchRatio; - - char label[200]; - - FeatureSet features; - - int rate = m_sampleRate; - - size_t epi = 0; - - for (size_t i = 0; i < outputIncrements.size(); ++i) { - - size_t frame = (baseCount + i) * inputIncrement; - - int oi = outputIncrements[i]; - bool hard = false; - bool soft = false; - - if (oi < 0) { - oi = -oi; - hard = true; - } - - if (epi < exactPoints.size() && int(i) == exactPoints[epi]) { - soft = true; - ++epi; - } - - double linear = (frame * overallRatio); - - Vamp::RealTime t = Vamp::RealTime::frame2RealTime(frame, rate); - - Feature feature; - feature.hasTimestamp = true; - feature.timestamp = t; - feature.values.push_back(float(oi)); - feature.label = Vamp::RealTime::frame2RealTime(oi, rate).toText(); - features[m_incrementsOutput].push_back(feature); - - feature.values.clear(); - feature.values.push_back(float(actual)); - feature.label = Vamp::RealTime::frame2RealTime(actual, rate).toText(); - features[m_aggregateIncrementsOutput].push_back(feature); - - feature.values.clear(); - feature.values.push_back(actual - linear); - - sprintf(label, "expected %ld, actual %ld, difference %ld (%s ms)", - long(linear), long(actual), long(actual - linear), - // frame2RealTime expects an integer frame number, - // hence our multiplication factor - (Vamp::RealTime::frame2RealTime - (lrintf((actual - linear) * 1000), rate) / 1000) - .toText().c_str()); - feature.label = label; - - features[m_divergenceOutput].push_back(feature); - actual += oi; - - char buf[30]; - - if (i < phaseResetDf.size()) { - feature.values.clear(); - feature.values.push_back(phaseResetDf[i]); - sprintf(buf, "%d", int(baseCount + i)); - feature.label = buf; - features[m_phaseResetDfOutput].push_back(feature); - } - - if (i < smoothedDf.size()) { - feature.values.clear(); - feature.values.push_back(smoothedDf[i]); - features[m_smoothedPhaseResetDfOutput].push_back(feature); - } - - if (hard) { - feature.values.clear(); - feature.label = "Phase Reset"; - features[m_phaseResetPointsOutput].push_back(feature); - } - - if (hard || soft) { - feature.values.clear(); - feature.label = "Time Sync"; - features[m_timeSyncPointsOutput].push_back(feature); - } - } - - if (includeFinal) { - Vamp::RealTime t = Vamp::RealTime::frame2RealTime - (inputIncrement * (baseCount + outputIncrements.size()), rate); - Feature feature; - feature.hasTimestamp = true; - feature.timestamp = t; - feature.label = Vamp::RealTime::frame2RealTime(actual, rate).toText(); - feature.values.clear(); - feature.values.push_back(float(actual)); - features[m_aggregateIncrementsOutput].push_back(feature); - - float linear = ((baseCount + outputIncrements.size()) - * inputIncrement * overallRatio); - feature.values.clear(); - feature.values.push_back(actual - linear); - feature.label = // see earlier comment - (Vamp::RealTime::frame2RealTime //!!! update this as earlier label - (lrintf((actual - linear) * 1000), rate) / 1000) - .toText(); - features[m_divergenceOutput].push_back(feature); - } - - m_accumulatedIncrement = actual; - - return features; -} - diff --git a/libs/rubberband/src/vamp/RubberBandVampPlugin.h b/libs/rubberband/src/vamp/RubberBandVampPlugin.h deleted file mode 100644 index 67cf1dfba4..0000000000 --- a/libs/rubberband/src/vamp/RubberBandVampPlugin.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#ifndef _RUBBERBAND_VAMP_PLUGIN_H_ -#define _RUBBERBAND_VAMP_PLUGIN_H_ - -#include "vamp-sdk/Plugin.h" - -#include "RubberBandStretcher.h" - -class RubberBandVampPlugin : public Vamp::Plugin -{ -public: - RubberBandVampPlugin(float inputSampleRate); - virtual ~RubberBandVampPlugin(); - - bool initialise(size_t channels, size_t stepSize, size_t blockSize); - void reset(); - - InputDomain getInputDomain() const { return TimeDomain; } - - std::string getIdentifier() const; - std::string getName() const; - std::string getDescription() const; - std::string getMaker() const; - int getPluginVersion() const; - std::string getCopyright() const; - - ParameterList getParameterDescriptors() const; - float getParameter(std::string id) const; - void setParameter(std::string id, float value); - - OutputList getOutputDescriptors() const; - - FeatureSet process(const float *const *inputBuffers, - Vamp::RealTime timestamp); - - FeatureSet getRemainingFeatures(); - -protected: - class Impl; - Impl *m_d; -}; - -#endif diff --git a/libs/rubberband/src/vamp/libmain.cpp b/libs/rubberband/src/vamp/libmain.cpp deleted file mode 100644 index 1b4185130d..0000000000 --- a/libs/rubberband/src/vamp/libmain.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#include <vamp/vamp.h> -#include <vamp-sdk/PluginAdapter.h> - -#include "RubberBandVampPlugin.h" - -static Vamp::PluginAdapter<RubberBandVampPlugin> rubberBandAdapter; - -const VampPluginDescriptor *vampGetPluginDescriptor(unsigned int version, - unsigned int index) -{ - if (version < 1) return 0; - - switch (index) { - case 0: return rubberBandAdapter.getDescriptor(); - default: return 0; - } -} - diff --git a/libs/rubberband/src/vamp/vamp-rubberband.cat b/libs/rubberband/src/vamp/vamp-rubberband.cat deleted file mode 100644 index d1ef2caba8..0000000000 --- a/libs/rubberband/src/vamp/vamp-rubberband.cat +++ /dev/null @@ -1 +0,0 @@ -vamp:vamp-rubberband:rubberband::Time > Timestretch Analysis |