From 160143461df25b06496b79fc16fd3290ae2eba2e Mon Sep 17 00:00:00 2001 From: Chris Cannam Date: Mon, 9 Jun 2008 20:46:37 +0000 Subject: [PATCH] * C API version --- Makefile.in | 26 ++-- rubberband/RubberBandStretcher.h | 127 +++++++++++------ rubberband/TimeStretcher.h | 58 -------- rubberband/rubberband.h | 106 ++++++++++++++ src/FFT.cpp | 4 +- src/Profiler.h | 2 +- src/RubberBandStretcher.cpp | 173 ++++++++--------------- src/StretcherChannelData.cpp | 16 +-- src/StretcherChannelData.h | 2 +- src/StretcherImpl.cpp | 148 +++++++++---------- src/StretcherImpl.h | 17 +-- src/StretcherProcess.cpp | 106 +++++++------- src/bsd-3rdparty/float_cast/float_cast.h | 4 + src/ladspa/RubberBandPitchShifter.cpp | 23 +++ src/ladspa/RubberBandPitchShifter.h | 4 + 15 files changed, 444 insertions(+), 372 deletions(-) delete mode 100644 rubberband/TimeStretcher.h create mode 100644 rubberband/rubberband.h diff --git a/Makefile.in b/Makefile.in index 0b1a5f2..2966c98 100644 --- a/Makefile.in +++ b/Makefile.in @@ -38,7 +38,7 @@ vamp: $(VAMP_TARGET) ladspa: $(LADSPA_TARGET) PUBLIC_INCLUDES := \ - rubberband/TimeStretcher.h \ + rubberband/rubberband.h \ rubberband/RubberBandStretcher.h LIBRARY_INCLUDES := \ @@ -153,7 +153,7 @@ src/ConstantAudioCurve.o: src/sysutils.h src/FFT.o: src/FFT.h src/sysutils.h src/Thread.h src/Profiler.h src/HighFrequencyAudioCurve.o: src/HighFrequencyAudioCurve.h src/AudioCurve.h src/HighFrequencyAudioCurve.o: src/sysutils.h src/Window.h -src/main.o: rubberband/RubberBandStretcher.h rubberband/TimeStretcher.h +src/main.o: rubberband/RubberBandStretcher.h rubberband/rubberband.h src/main.o: src/sysutils.h src/Profiler.h src/PercussiveAudioCurve.o: src/PercussiveAudioCurve.h src/AudioCurve.h src/PercussiveAudioCurve.o: src/sysutils.h @@ -163,7 +163,7 @@ src/RingBuffer.o: src/RingBuffer.h src/Scavenger.h src/Thread.h src/RingBuffer.o: src/sysutils.h src/Profiler.h src/RubberBandStretcher.o: src/StretcherImpl.h src/RubberBandStretcher.o: rubberband/RubberBandStretcher.h -src/RubberBandStretcher.o: rubberband/TimeStretcher.h src/Window.h +src/RubberBandStretcher.o: rubberband/rubberband.h src/Window.h src/RubberBandStretcher.o: src/sysutils.h src/Thread.h src/RingBuffer.h src/RubberBandStretcher.o: src/Scavenger.h src/Profiler.h src/FFT.h src/SpectralDifferenceAudioCurve.o: src/SpectralDifferenceAudioCurve.h @@ -172,12 +172,12 @@ src/SpectralDifferenceAudioCurve.o: src/Window.h src/StretchCalculator.o: src/StretchCalculator.h src/sysutils.h src/StretcherChannelData.o: src/StretcherChannelData.h src/StretcherImpl.h src/StretcherChannelData.o: rubberband/RubberBandStretcher.h -src/StretcherChannelData.o: rubberband/TimeStretcher.h src/Window.h +src/StretcherChannelData.o: rubberband/rubberband.h src/Window.h src/StretcherChannelData.o: src/sysutils.h src/Thread.h src/RingBuffer.h src/StretcherChannelData.o: src/Scavenger.h src/Profiler.h src/FFT.h src/StretcherChannelData.o: src/Resampler.h src/StretcherImpl.o: src/StretcherImpl.h rubberband/RubberBandStretcher.h -src/StretcherImpl.o: rubberband/TimeStretcher.h src/Window.h src/sysutils.h +src/StretcherImpl.o: rubberband/rubberband.h src/Window.h src/sysutils.h src/StretcherImpl.o: src/Thread.h src/RingBuffer.h src/Scavenger.h src/StretcherImpl.o: src/Profiler.h src/FFT.h src/PercussiveAudioCurve.h src/StretcherImpl.o: src/AudioCurve.h src/HighFrequencyAudioCurve.h @@ -185,7 +185,7 @@ src/StretcherImpl.o: src/SpectralDifferenceAudioCurve.h src/StretcherImpl.o: src/ConstantAudioCurve.h src/StretchCalculator.h src/StretcherImpl.o: src/StretcherChannelData.h src/Resampler.h src/StretcherProcess.o: src/StretcherImpl.h rubberband/RubberBandStretcher.h -src/StretcherProcess.o: rubberband/TimeStretcher.h src/Window.h +src/StretcherProcess.o: rubberband/rubberband.h src/Window.h src/StretcherProcess.o: src/sysutils.h src/Thread.h src/RingBuffer.h src/StretcherProcess.o: src/Scavenger.h src/Profiler.h src/FFT.h src/StretcherProcess.o: src/PercussiveAudioCurve.h src/AudioCurve.h @@ -195,7 +195,7 @@ src/StretcherProcess.o: src/StretcherChannelData.h src/Resampler.h src/sysutils.o: src/sysutils.h src/Thread.o: src/Thread.h src/Window.o: src/Window.h src/sysutils.h -rubberband/RubberBandStretcher.o: rubberband/TimeStretcher.h +rubberband/RubberBandStretcher.o: rubberband/rubberband.h src/AudioCurve.o: src/sysutils.h src/ConstantAudioCurve.o: src/AudioCurve.h src/sysutils.h src/FFT.o: src/sysutils.h @@ -209,11 +209,11 @@ src/SpectralDifferenceAudioCurve.o: src/AudioCurve.h src/sysutils.h src/SpectralDifferenceAudioCurve.o: src/Window.h src/StretcherChannelData.o: src/StretcherImpl.h src/StretcherChannelData.o: rubberband/RubberBandStretcher.h -src/StretcherChannelData.o: rubberband/TimeStretcher.h src/Window.h +src/StretcherChannelData.o: rubberband/rubberband.h src/Window.h src/StretcherChannelData.o: src/sysutils.h src/Thread.h src/RingBuffer.h src/StretcherChannelData.o: src/Scavenger.h src/Profiler.h src/FFT.h src/StretcherImpl.o: rubberband/RubberBandStretcher.h -src/StretcherImpl.o: rubberband/TimeStretcher.h src/Window.h src/sysutils.h +src/StretcherImpl.o: rubberband/rubberband.h src/Window.h src/sysutils.h src/StretcherImpl.o: src/Thread.h src/RingBuffer.h src/Scavenger.h src/StretcherImpl.o: src/Profiler.h src/FFT.h src/Window.o: src/sysutils.h @@ -225,16 +225,16 @@ src/ladspa/RubberBandPitchShifter.o: src/RingBuffer.h src/ladspa/RubberBandPitchShifter.o: src/Scavenger.h src/Thread.h src/ladspa/RubberBandPitchShifter.o: src/sysutils.h src/Profiler.h src/ladspa/RubberBandPitchShifter.o: rubberband/RubberBandStretcher.h -src/ladspa/RubberBandPitchShifter.o: rubberband/TimeStretcher.h +src/ladspa/RubberBandPitchShifter.o: rubberband/rubberband.h src/vamp/libmain.o: src/vamp/RubberBandVampPlugin.h src/vamp/libmain.o: rubberband/RubberBandStretcher.h -src/vamp/libmain.o: rubberband/TimeStretcher.h +src/vamp/libmain.o: rubberband/rubberband.h src/vamp/RubberBandVampPlugin.o: src/vamp/RubberBandVampPlugin.h src/vamp/RubberBandVampPlugin.o: rubberband/RubberBandStretcher.h -src/vamp/RubberBandVampPlugin.o: rubberband/TimeStretcher.h +src/vamp/RubberBandVampPlugin.o: rubberband/rubberband.h src/vamp/RubberBandVampPlugin.o: src/StretchCalculator.h src/ladspa/RubberBandPitchShifter.o: src/RingBuffer.h src/ladspa/RubberBandPitchShifter.o: src/Scavenger.h src/Thread.h src/ladspa/RubberBandPitchShifter.o: src/sysutils.h src/Profiler.h src/vamp/RubberBandVampPlugin.o: rubberband/RubberBandStretcher.h -src/vamp/RubberBandVampPlugin.o: rubberband/TimeStretcher.h +src/vamp/RubberBandVampPlugin.o: rubberband/rubberband.h diff --git a/rubberband/RubberBandStretcher.h b/rubberband/RubberBandStretcher.h index 9b34714..6af71f1 100644 --- a/rubberband/RubberBandStretcher.h +++ b/rubberband/RubberBandStretcher.h @@ -15,29 +15,28 @@ #ifndef _RUBBERBANDSTRETCHER_H_ #define _RUBBERBANDSTRETCHER_H_ -#include "TimeStretcher.h" +#include "rubberband.h" #include /** * @mainpage RubberBand * - * The Rubber Band API is contained in the single class + * The Rubber Band C++ API is contained in the single class * RubberBand::RubberBandStretcher. */ namespace RubberBand { -class RubberBandStretcher : public TimeStretcher +class RubberBandStretcher { public: - /** - * Processing options for the timestretcher. The preferred - * options should normally be set in the constructor, as a bitwise - * OR of the option flags. The default value (DefaultOptions) is - * intended to give good results in most situations. + * Processing options for the Rubber Band audio timestretcher. The + * preferred options should normally be set in the constructor, as a + * bitwise OR of the option flags. The default value (DefaultOptions) + * is intended to give good results in most situations. * * 1. Flags prefixed \c OptionProcess determine how the timestretcher * will be invoked. These options may not be changed after @@ -189,6 +188,8 @@ public: enum Option { + //!!! sort out this duplication + OptionProcessOffline = 0x00000000, OptionProcessRealTime = 0x00000001, @@ -222,7 +223,7 @@ public: enum PresetOption { DefaultOptions = 0x00000000, - PercussiveOptions = 0x00102000 + PercussiveOptions = (OptionWindowShort | OptionPhaseIndependent) }; /** @@ -237,15 +238,22 @@ public: size_t channels, Options options = DefaultOptions, double initialTimeRatio = 1.0, - double initialPitchScale = 1.0); - virtual ~RubberBandStretcher(); + double initialPitchScale = 1.0) : + r(rubberband_new(sampleRate, channels, options, + initialTimeRatio, initialPitchScale)) { } + + ~RubberBandStretcher() { + rubberband_delete(r); + } /** * Reset the stretcher's internal buffers. The stretcher should * subsequently behave as if it had just been constructed * (although retaining the current time and pitch ratio). */ - virtual void reset(); + void reset() { + rubberband_reset(r); + } /** * Set the time ratio for the stretcher. This is the ratio of @@ -268,7 +276,9 @@ public: * mechanism to ensure that setTimeRatio and process() cannot be * run at once (there is no internal mutex for this purpose). */ - virtual void setTimeRatio(double ratio); + void setTimeRatio(double ratio) { + rubberband_set_time_ratio(r, ratio); + } /** * Set the pitch scaling ratio for the stretcher. This is the @@ -295,19 +305,25 @@ public: * mechanism to ensure that setPitchScale and process() cannot be * run at once (there is no internal mutex for this purpose). */ - virtual void setPitchScale(double scale); + void setPitchScale(double scale) { + rubberband_set_pitch_scale(r, scale); + } /** * Return the last time ratio value that was set (either on * construction or with setTimeRatio()). */ - virtual double getTimeRatio() const; + double getTimeRatio() const { + return rubberband_get_time_ratio(r); + } /** * Return the last pitch scaling ratio value that was set (either * on construction or with setPitchScale()). */ - virtual double getPitchScale() const; + double getPitchScale() const { + return rubberband_get_pitch_scale(r); + } /** * Return the processing latency of the stretcher. This is the @@ -318,7 +334,9 @@ public: * In RealTime mode, the latency may depend on the time and pitch * ratio and other options. */ - virtual size_t getLatency() const; + size_t getLatency() const { + return rubberband_get_latency(r); + } /** * Change an OptionTransients configuration setting. This may be @@ -326,7 +344,9 @@ public: * Offline mode (for which the transients option is fixed on * construction). */ - virtual void setTransientsOption(Options options); + void setTransientsOption(Options options) { + rubberband_set_transients_option(r, options); + } /** * Change an OptionPhase configuration setting. This may be @@ -336,7 +356,9 @@ public: * may not take effect immediately if processing is already under * way when this function is called. */ - virtual void setPhaseOption(Options options); + void setPhaseOption(Options options) { + rubberband_set_phase_option(r, options); + } /** * Change an OptionFormant configuration setting. This may be @@ -346,7 +368,9 @@ public: * may not take effect immediately if processing is already under * way when this function is called. */ - virtual void setFormantOption(Options options); + void setFormantOption(Options options) { + rubberband_set_formant_option(r, options); + } /** * Change an OptionPitch configuration setting. This may be @@ -354,7 +378,9 @@ public: * Offline mode (for which the transients option is fixed on * construction). */ - virtual void setPitchOption(Options options); + void setPitchOption(Options options) { + rubberband_set_pitch_option(r, options); + } /** * Tell the stretcher exactly how many input samples it will @@ -363,7 +389,9 @@ public: * exactly correct. In RealTime mode no such guarantee is * possible and this value is ignored. */ - virtual void setExpectedInputDuration(size_t samples); + void setExpectedInputDuration(size_t samples) { + rubberband_set_expected_input_duration(r, samples); + } /** * Ask the stretcher how many audio sample frames should be @@ -377,7 +405,9 @@ public: * study() (to which you may pass any number of samples at a time, * and from which there is no output). */ - virtual size_t getSamplesRequired() const; + size_t getSamplesRequired() const { + return rubberband_get_samples_required(r); + } /** * Tell the stretcher the maximum number of sample frames that you @@ -394,7 +424,9 @@ public: * study() (to which you may pass any number of samples at a time, * and from which there is no output). */ - virtual void setMaxProcessSize(size_t samples); + void setMaxProcessSize(size_t samples) { + rubberband_set_max_process_size(r, samples); + } /** * Provide a block of "samples" sample frames for the stretcher to @@ -413,7 +445,9 @@ public: * Set "final" to true if this is the last block of data that will * be provided to study() before the first process() call. */ - virtual void study(const float *const *input, size_t samples, bool final); + void study(const float *const *input, size_t samples, bool final) { + rubberband_study(r, input, samples, final); + } /** * Provide a block of "samples" sample frames for processing. @@ -421,7 +455,9 @@ public: * * Set "final" to true if this is the last block of input data. */ - virtual void process(const float *const *input, size_t samples, bool final); + void process(const float *const *input, size_t samples, bool final) { + rubberband_process(r, input, samples, final); + } /** * Ask the stretcher how many audio sample frames of output data @@ -436,7 +472,9 @@ public: * This function returns -1 if all data has been fully processed * and all output read, and the stretch process is now finished. */ - virtual int available() const; + int available() const { + return rubberband_available(r); + } /** * Obtain some processed output data from the stretcher. Up to @@ -445,28 +483,30 @@ public: * The return value is the actual number of sample frames * retrieved. */ - virtual size_t retrieve(float *const *output, size_t samples) const; + size_t retrieve(float *const *output, size_t samples) const { + return rubberband_retrieve(r, output, samples); + } /** * Return the value of internal frequency cutoff value n. * * This function is not for general use. */ - virtual float getFrequencyCutoff(int n) const; + float getFrequencyCutoff(int n) const; /** * Set the value of internal frequency cutoff n to f Hz. * * This function is not for general use. */ - virtual void setFrequencyCutoff(int n, float f); + void setFrequencyCutoff(int n, float f); /** * Retrieve the value of the internal input block increment value. * * This function is provided for diagnostic purposes only. */ - virtual size_t getInputIncrement() const; + size_t getInputIncrement() const; /** * In offline mode, retrieve the sequence of internal block @@ -477,7 +517,7 @@ public: * * This function is provided for diagnostic purposes only. */ - virtual std::vector getOutputIncrements() const; + std::vector getOutputIncrements() const; /** * In offline mode, retrieve the sequence of internal phase reset @@ -488,7 +528,7 @@ public: * * This function is provided for diagnostic purposes only. */ - virtual std::vector getPhaseResetCurve() const; + std::vector getPhaseResetCurve() const; /** * In offline mode, retrieve the sequence of internal frames for @@ -498,13 +538,15 @@ public: * * This function is provided for diagnostic purposes only. */ - virtual std::vector getExactTimePoints() const; + std::vector getExactTimePoints() const; /** * Return the number of channels this stretcher was constructed * with. */ - virtual size_t getChannelCount() const; + size_t getChannelCount() const { + return rubberband_get_channel_count(r); + } /** * Force the stretcher to calculate a stretch profile. Normally @@ -513,7 +555,9 @@ public: * * This function is provided for diagnostic purposes only. */ - virtual void calculateStretch(); + void calculateStretch() { + rubberband_calculate_stretch(r); + } /** * Set the level of debug output. The value may be from 0 (errors @@ -522,7 +566,9 @@ public: * using setDefaultDebugLevel, or 0 if that function has not been * called. */ - virtual void setDebugLevel(int level); + void setDebugLevel(int level) { + rubberband_set_debug_level(r, level); + } /** * Set the default level of debug output for subsequently @@ -530,11 +576,12 @@ public: * * @see setDebugLevel */ - static void setDefaultDebugLevel(int level); + static void setDefaultDebugLevel(int level) { + rubberband_set_default_debug_level(level); + } protected: - class Impl; - Impl *m_d; + RubberBandState r; }; } diff --git a/rubberband/TimeStretcher.h b/rubberband/TimeStretcher.h deleted file mode 100644 index 99d8810..0000000 --- a/rubberband/TimeStretcher.h +++ /dev/null @@ -1,58 +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_TIMESTRETCHER_H_ -#define _RUBBERBAND_TIMESTRETCHER_H_ - -#include - -namespace RubberBand -{ - -/** - * Base class for time stretchers. RubberBand currently provides only - * a single subclass implementation. - * - * @see RubberBandStretcher - */ -class TimeStretcher -{ -public: - TimeStretcher(size_t sampleRate, size_t channels) : - m_sampleRate(sampleRate), - m_channels(channels) - { } - virtual ~TimeStretcher() - { } - - virtual void reset() = 0; - virtual void setTimeRatio(double ratio) = 0; - virtual void setPitchScale(double scale) = 0; - virtual size_t getLatency() const = 0; - - virtual void study(const float *const *input, size_t samples, bool final) = 0; - virtual size_t getSamplesRequired() const = 0; - virtual void process(const float *const *input, size_t samples, bool final) = 0; - virtual int available() const = 0; - virtual size_t retrieve(float *const *output, size_t samples) const = 0; - -protected: - size_t m_sampleRate; - size_t m_channels; -}; - -} - -#endif - diff --git a/rubberband/rubberband.h b/rubberband/rubberband.h new file mode 100644 index 0000000..0d99b6c --- /dev/null +++ b/rubberband/rubberband.h @@ -0,0 +1,106 @@ +/* -*- 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_H_ +#define _RUBBERBAND_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +enum RubberBandOption { + + //!!! sort out this duplication + + RubberBandOptionProcessOffline = 0x00000000, + RubberBandOptionProcessRealTime = 0x00000001, + + RubberBandOptionStretchElastic = 0x00000000, + RubberBandOptionStretchPrecise = 0x00000010, + + RubberBandOptionTransientsCrisp = 0x00000000, + RubberBandOptionTransientsMixed = 0x00000100, + RubberBandOptionTransientsSmooth = 0x00000200, + + RubberBandOptionPhaseAdaptive = 0x00000000, + RubberBandOptionPhasePeakLocked = 0x00001000, + RubberBandOptionPhaseIndependent = 0x00002000, + + RubberBandOptionThreadingAuto = 0x00000000, + RubberBandOptionThreadingNever = 0x00010000, + RubberBandOptionThreadingAlways = 0x00020000, + + RubberBandOptionWindowStandard = 0x00000000, + RubberBandOptionWindowShort = 0x00100000, + RubberBandOptionWindowLong = 0x00200000, + + RubberBandOptionFormantShifted = 0x00000000, + RubberBandOptionFormantPreserved = 0x01000000, + + RubberBandOptionPitchHighQuality = 0x00000000, + RubberBandOptionPitchHighSpeed = 0x02000000 +}; + +typedef int RubberBandOptions; + +struct RubberBandState_; +typedef struct RubberBandState_ *RubberBandState; + +extern RubberBandState rubberband_new(unsigned int sampleRate, + unsigned int channels, + RubberBandOptions options, //!!! sort out RubberBand namespacing + double initialTimeRatio, + double initialPitchScale); + +extern void rubberband_delete(RubberBandState); + +extern void rubberband_reset(RubberBandState); + +extern void rubberband_set_time_ratio(RubberBandState, double ratio); +extern void rubberband_set_pitch_scale(RubberBandState, double scale); + +extern double rubberband_get_time_ratio(const RubberBandState); +extern double rubberband_get_pitch_scale(const RubberBandState); + +extern unsigned int rubberband_get_latency(const RubberBandState); + +extern void rubberband_set_transients_option(RubberBandState, RubberBandOptions options); +extern void rubberband_set_phase_option(RubberBandState, RubberBandOptions options); +extern void rubberband_set_formant_option(RubberBandState, RubberBandOptions options); +extern void rubberband_set_pitch_option(RubberBandState, RubberBandOptions options); + +extern void rubberband_set_expected_input_duration(RubberBandState, unsigned int samples); + +extern unsigned int rubberband_get_samples_required(const RubberBandState); + +extern void rubberband_set_max_process_size(RubberBandState, unsigned int samples); + +extern void rubberband_study(RubberBandState, const float *const *input, unsigned int samples, int final); +extern void rubberband_process(RubberBandState, const float *const *input, unsigned int samples, int final); + +extern int rubberband_available(const RubberBandState); +extern unsigned int rubberband_retrieve(const RubberBandState, float *const *output, unsigned int samples); + +extern unsigned int rubberband_get_channel_count(const RubberBandState); + +extern void rubberband_calculate_stretch(RubberBandState); + +extern void rubberband_set_debug_level(RubberBandState, int level); +extern void rubberband_set_default_debug_level(int level); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/FFT.cpp b/src/FFT.cpp index 49c1a71..adc3746 100644 --- a/src/FFT.cpp +++ b/src/FFT.cpp @@ -482,7 +482,7 @@ public: void inverseCepstral(const double *R__ magIn, double *R__ cepOut) { if (!m_dplanf) initDouble(); fft_double_type *const R__ dbuf = m_dbuf; - fftwf_complex *const R__ dpacked = m_dpacked; + 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); @@ -545,7 +545,7 @@ public: for (int i = 0; i <= hs; ++i) { fpacked[i][1] = 0.f; } - fftw_execute(m_fplani); + fftwf_execute(m_fplani); const int sz = m_size; fft_float_type *const R__ fbuf = m_fbuf; #ifndef FFTW_DOUBLE_ONLY diff --git a/src/Profiler.h b/src/Profiler.h index 947eb82..616a553 100644 --- a/src/Profiler.h +++ b/src/Profiler.h @@ -76,7 +76,7 @@ protected: class Profiler { public: - Profiler(const char *, bool = false) { } + Profiler(const char *) { } ~Profiler() { } void update() const { } diff --git a/src/RubberBandStretcher.cpp b/src/RubberBandStretcher.cpp index 9236fbd..8bc54e4 100644 --- a/src/RubberBandStretcher.cpp +++ b/src/RubberBandStretcher.cpp @@ -14,188 +14,133 @@ #include "StretcherImpl.h" -namespace RubberBand { +#include "rubberband.h" - -RubberBandStretcher::RubberBandStretcher(size_t sampleRate, - size_t channels, - Options options, - double initialTimeRatio, - double initialPitchScale) : - TimeStretcher(sampleRate, channels), - m_d(new Impl(this, sampleRate, channels, options, - initialTimeRatio, initialPitchScale)) +struct RubberBandState_ { -} + RubberBand::StretcherImpl *m_impl; +}; -RubberBandStretcher::~RubberBandStretcher() +RubberBandState rubberband_new(unsigned int sampleRate, + unsigned int channels, + RubberBandOptions options, //!!! sort out RubberBand namespacing + double initialTimeRatio, + double initialPitchScale) { - delete m_d; + RubberBandState_ *state = new RubberBandState_(); + state->m_impl = new RubberBand::StretcherImpl + (sampleRate, channels, options, + initialTimeRatio, initialPitchScale); + return state; } -void -RubberBandStretcher::reset() +void rubberband_delete(RubberBandState state) { - m_d->reset(); + delete state->m_impl; + delete state; } -void -RubberBandStretcher::setTimeRatio(double ratio) +void rubberband_reset(RubberBandState state) { - m_d->setTimeRatio(ratio); + state->m_impl->reset(); } -void -RubberBandStretcher::setPitchScale(double scale) +void rubberband_set_time_ratio(RubberBandState state, double ratio) { - m_d->setPitchScale(scale); + state->m_impl->setTimeRatio(ratio); } -double -RubberBandStretcher::getTimeRatio() const +void rubberband_set_pitch_scale(RubberBandState state, double scale) { - return m_d->getTimeRatio(); + state->m_impl->setPitchScale(scale); } -double -RubberBandStretcher::getPitchScale() const +double rubberband_get_time_ratio(const RubberBandState state) { - return m_d->getPitchScale(); + return state->m_impl->getTimeRatio(); } -size_t -RubberBandStretcher::getLatency() const +double rubberband_get_pitch_scale(const RubberBandState state) { - return m_d->getLatency(); + return state->m_impl->getPitchScale(); } -void -RubberBandStretcher::setTransientsOption(Options options) +unsigned int rubberband_get_latency(const RubberBandState state) { - m_d->setTransientsOption(options); + return state->m_impl->getLatency(); } -void -RubberBandStretcher::setPhaseOption(Options options) +void rubberband_set_transients_option(RubberBandState state, RubberBandOptions options) { - m_d->setPhaseOption(options); + state->m_impl->setTransientsOption(options); } -void -RubberBandStretcher::setFormantOption(Options options) +void rubberband_set_phase_option(RubberBandState state, RubberBandOptions options) { - m_d->setFormantOption(options); + state->m_impl->setPhaseOption(options); } -void -RubberBandStretcher::setPitchOption(Options options) +void rubberband_set_formant_option(RubberBandState state, RubberBandOptions options) { - m_d->setPitchOption(options); + state->m_impl->setFormantOption(options); } -void -RubberBandStretcher::setExpectedInputDuration(size_t samples) +void rubberband_set_pitch_option(RubberBandState state, RubberBandOptions options) { - m_d->setExpectedInputDuration(samples); + state->m_impl->setPitchOption(options); } -void -RubberBandStretcher::setMaxProcessSize(size_t samples) +void rubberband_set_expected_input_duration(RubberBandState state, unsigned int samples) { - m_d->setMaxProcessSize(samples); + state->m_impl->setExpectedInputDuration(samples); } -size_t -RubberBandStretcher::getSamplesRequired() const +unsigned int rubberband_get_samples_required(const RubberBandState state) { - return m_d->getSamplesRequired(); + return state->m_impl->getSamplesRequired(); } -void -RubberBandStretcher::study(const float *const *input, size_t samples, - bool final) +void rubberband_set_max_process_size(RubberBandState state, unsigned int samples) { - m_d->study(input, samples, final); + state->m_impl->setMaxProcessSize(samples); } -void -RubberBandStretcher::process(const float *const *input, size_t samples, - bool final) +void rubberband_study(RubberBandState state, const float *const *input, unsigned int samples, int final) { - m_d->process(input, samples, final); + state->m_impl->study(input, samples, final != 0); } -int -RubberBandStretcher::available() const +void rubberband_process(RubberBandState state, const float *const *input, unsigned int samples, int final) { - return m_d->available(); + state->m_impl->process(input, samples, final != 0); } -size_t -RubberBandStretcher::retrieve(float *const *output, size_t samples) const +int rubberband_available(const RubberBandState state) { - return m_d->retrieve(output, samples); + return state->m_impl->available(); } -float -RubberBandStretcher::getFrequencyCutoff(int n) const +unsigned int rubberband_retrieve(const RubberBandState state, float *const *output, unsigned int samples) { - return m_d->getFrequencyCutoff(n); + return state->m_impl->retrieve(output, samples); } -void -RubberBandStretcher::setFrequencyCutoff(int n, float f) +unsigned int rubberband_get_channel_count(const RubberBandState state) { - m_d->setFrequencyCutoff(n, f); + return state->m_impl->getChannelCount(); } -size_t -RubberBandStretcher::getInputIncrement() const +void rubberband_calculate_stretch(RubberBandState state) { - return m_d->getInputIncrement(); + state->m_impl->calculateStretch(); } -std::vector -RubberBandStretcher::getOutputIncrements() const +void rubberband_set_debug_level(RubberBandState state, int level) { - return m_d->getOutputIncrements(); + state->m_impl->setDebugLevel(level); } -std::vector -RubberBandStretcher::getPhaseResetCurve() const +void rubberband_set_default_debug_level(int level) { - return m_d->getPhaseResetCurve(); + RubberBand::StretcherImpl::setDefaultDebugLevel(level); } - -std::vector -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/src/StretcherChannelData.cpp b/src/StretcherChannelData.cpp index 2a8fe40..a581adc 100644 --- a/src/StretcherChannelData.cpp +++ b/src/StretcherChannelData.cpp @@ -20,7 +20,7 @@ namespace RubberBand { -RubberBandStretcher::Impl::ChannelData::ChannelData(size_t windowSize, +StretcherImpl::ChannelData::ChannelData(size_t windowSize, int overSample, size_t outbufSize) : oversample(overSample) @@ -29,7 +29,7 @@ RubberBandStretcher::Impl::ChannelData::ChannelData(size_t windowSize, construct(s, windowSize, outbufSize); } -RubberBandStretcher::Impl::ChannelData::ChannelData(const std::set &windowSizes, +StretcherImpl::ChannelData::ChannelData(const std::set &windowSizes, int overSample, size_t initialWindowSize, size_t outbufSize) : @@ -39,7 +39,7 @@ RubberBandStretcher::Impl::ChannelData::ChannelData(const std::set &wind } void -RubberBandStretcher::Impl::ChannelData::construct(const std::set &windowSizes, +StretcherImpl::ChannelData::construct(const std::set &windowSizes, size_t initialWindowSize, size_t outbufSize) { @@ -117,7 +117,7 @@ RubberBandStretcher::Impl::ChannelData::construct(const std::set &window } void -RubberBandStretcher::Impl::ChannelData::setWindowSize(size_t windowSize) +StretcherImpl::ChannelData::setWindowSize(size_t windowSize) { size_t oldSize = inbuf->getSize(); size_t realSize = (windowSize * oversample) / 2 + 1; @@ -236,7 +236,7 @@ RubberBandStretcher::Impl::ChannelData::setWindowSize(size_t windowSize) } void -RubberBandStretcher::Impl::ChannelData::setOutbufSize(size_t outbufSize) +StretcherImpl::ChannelData::setOutbufSize(size_t outbufSize) { size_t oldSize = outbuf->getSize(); @@ -254,7 +254,7 @@ RubberBandStretcher::Impl::ChannelData::setOutbufSize(size_t outbufSize) } void -RubberBandStretcher::Impl::ChannelData::setResampleBufSize(size_t sz) +StretcherImpl::ChannelData::setResampleBufSize(size_t sz) { if (!resamplebuf) { resamplebuf = new float[sz]; @@ -268,7 +268,7 @@ RubberBandStretcher::Impl::ChannelData::setResampleBufSize(size_t sz) resamplebufSize = sz; } -RubberBandStretcher::Impl::ChannelData::~ChannelData() +StretcherImpl::ChannelData::~ChannelData() { delete resampler; @@ -296,7 +296,7 @@ RubberBandStretcher::Impl::ChannelData::~ChannelData() } void -RubberBandStretcher::Impl::ChannelData::reset() +StretcherImpl::ChannelData::reset() { inbuf->reset(); outbuf->reset(); diff --git a/src/StretcherChannelData.h b/src/StretcherChannelData.h index 5020568..5916970 100644 --- a/src/StretcherChannelData.h +++ b/src/StretcherChannelData.h @@ -26,7 +26,7 @@ namespace RubberBand class Resampler; -class RubberBandStretcher::Impl::ChannelData +class StretcherImpl::ChannelData { public: /** diff --git a/src/StretcherImpl.cpp b/src/StretcherImpl.cpp index 3a0960e..3af4af8 100644 --- a/src/StretcherImpl.cpp +++ b/src/StretcherImpl.cpp @@ -39,23 +39,23 @@ using std::min; namespace RubberBand { const size_t -RubberBandStretcher::Impl::m_defaultIncrement = 256; +StretcherImpl::m_defaultIncrement = 256; const size_t -RubberBandStretcher::Impl::m_defaultWindowSize = 2048; +StretcherImpl::m_defaultWindowSize = 2048; int -RubberBandStretcher::Impl::m_defaultDebugLevel = 0; +StretcherImpl::m_defaultDebugLevel = 0; -RubberBandStretcher::Impl::Impl(RubberBandStretcher *stretcher, - size_t sampleRate, - size_t channels, - Options options, - double initialTimeRatio, - double initialPitchScale) : - m_stretcher(stretcher), +StretcherImpl::StretcherImpl(size_t sampleRate, + size_t channels, + //!!! sort out this crapness with Options namespace + RubberBandStretcher::Options options, + double initialTimeRatio, + double initialPitchScale) : + m_sampleRate(sampleRate), m_channels(channels), m_timeRatio(initialTimeRatio), m_pitchScale(initialPitchScale), @@ -85,24 +85,24 @@ RubberBandStretcher::Impl::Impl(RubberBandStretcher *stretcher, { if (m_debugLevel > 0) { - cerr << "RubberBandStretcher::Impl::Impl: rate = " << m_stretcher->m_sampleRate << ", options = " << options << endl; + cerr << "StretcherImpl::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_stretcher->m_sampleRate) / 48000.f; + 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) { + if ((options & RubberBandStretcher::OptionWindowShort) || (options & RubberBandStretcher::OptionWindowLong)) { + if ((options & RubberBandStretcher::OptionWindowShort) && (options & RubberBandStretcher::OptionWindowLong)) { + cerr << "StretcherImpl::Impl: Cannot specify OptionWindowLong and OptionWindowShort together; falling back to OptionWindowStandard" << endl; + } else if (options & RubberBandStretcher::OptionWindowShort) { m_baseWindowSize = m_baseWindowSize / 2; if (m_debugLevel > 0) { cerr << "setting baseWindowSize to " << m_baseWindowSize << endl; } - } else if (options & OptionWindowLong) { + } else if (options & RubberBandStretcher::OptionWindowLong) { m_baseWindowSize = m_baseWindowSize * 2; if (m_debugLevel > 0) { cerr << "setting baseWindowSize to " << m_baseWindowSize << endl; @@ -113,12 +113,12 @@ RubberBandStretcher::Impl::Impl(RubberBandStretcher *stretcher, m_maxProcessSize = m_baseWindowSize; } - if (m_options & OptionProcessRealTime) { + if (m_options & RubberBandStretcher::OptionProcessRealTime) { m_realtime = true; - if (!(m_options & OptionStretchPrecise)) { - m_options |= OptionStretchPrecise; + if (!(m_options & RubberBandStretcher::OptionStretchPrecise)) { + m_options |= RubberBandStretcher::OptionStretchPrecise; } } @@ -128,9 +128,9 @@ RubberBandStretcher::Impl::Impl(RubberBandStretcher *stretcher, if (m_realtime) { m_threaded = false; - } else if (m_options & OptionThreadingNever) { + } else if (m_options & RubberBandStretcher::OptionThreadingNever) { m_threaded = false; - } else if (!(m_options & OptionThreadingAlways) && + } else if (!(m_options & RubberBandStretcher::OptionThreadingAlways) && !system_is_multiprocessor()) { m_threaded = false; } @@ -143,7 +143,7 @@ RubberBandStretcher::Impl::Impl(RubberBandStretcher *stretcher, configure(); } -RubberBandStretcher::Impl::~Impl() +StretcherImpl::~StretcherImpl() { if (m_threaded) { MutexLocker locker(&m_threadSetMutex); @@ -174,7 +174,7 @@ RubberBandStretcher::Impl::~Impl() } void -RubberBandStretcher::Impl::reset() +StretcherImpl::reset() { if (m_threaded) { m_threadSetMutex.lock(); @@ -205,11 +205,11 @@ RubberBandStretcher::Impl::reset() } void -RubberBandStretcher::Impl::setTimeRatio(double ratio) +StretcherImpl::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; + cerr << "StretcherImpl::setTimeRatio: Cannot set ratio while studying or processing in non-RT mode" << endl; return; } } @@ -221,11 +221,11 @@ RubberBandStretcher::Impl::setTimeRatio(double ratio) } void -RubberBandStretcher::Impl::setPitchScale(double fs) +StretcherImpl::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; + cerr << "StretcherImpl::setPitchScale: Cannot set ratio while studying or processing in non-RT mode" << endl; return; } } @@ -237,19 +237,19 @@ RubberBandStretcher::Impl::setPitchScale(double fs) } double -RubberBandStretcher::Impl::getTimeRatio() const +StretcherImpl::getTimeRatio() const { return m_timeRatio; } double -RubberBandStretcher::Impl::getPitchScale() const +StretcherImpl::getPitchScale() const { return m_pitchScale; } void -RubberBandStretcher::Impl::setExpectedInputDuration(size_t samples) +StretcherImpl::setExpectedInputDuration(size_t samples) { if (samples == m_expectedInputDuration) return; m_expectedInputDuration = samples; @@ -258,7 +258,7 @@ RubberBandStretcher::Impl::setExpectedInputDuration(size_t samples) } void -RubberBandStretcher::Impl::setMaxProcessSize(size_t samples) +StretcherImpl::setMaxProcessSize(size_t samples) { if (samples <= m_maxProcessSize) return; m_maxProcessSize = samples; @@ -267,7 +267,7 @@ RubberBandStretcher::Impl::setMaxProcessSize(size_t samples) } float -RubberBandStretcher::Impl::getFrequencyCutoff(int n) const +StretcherImpl::getFrequencyCutoff(int n) const { switch (n) { case 0: return m_freq0; @@ -278,7 +278,7 @@ RubberBandStretcher::Impl::getFrequencyCutoff(int n) const } void -RubberBandStretcher::Impl::setFrequencyCutoff(int n, float f) +StretcherImpl::setFrequencyCutoff(int n, float f) { switch (n) { case 0: m_freq0 = f; break; @@ -288,7 +288,7 @@ RubberBandStretcher::Impl::setFrequencyCutoff(int n, float f) } double -RubberBandStretcher::Impl::getEffectiveRatio() const +StretcherImpl::getEffectiveRatio() const { // Returns the ratio that the internal time stretcher needs to // achieve, not the resulting duration ratio of the output (which @@ -305,7 +305,7 @@ RubberBandStretcher::Impl::getEffectiveRatio() const } size_t -RubberBandStretcher::Impl::roundUp(size_t value) +StretcherImpl::roundUp(size_t value) { if (!(value & (value - 1))) return value; int bits = 0; @@ -315,7 +315,7 @@ RubberBandStretcher::Impl::roundUp(size_t value) } void -RubberBandStretcher::Impl::calculateSizes() +StretcherImpl::calculateSizes() { size_t inputIncrement = m_defaultIncrement; size_t windowSize = m_baseWindowSize; @@ -457,7 +457,7 @@ RubberBandStretcher::Impl::calculateSizes() } void -RubberBandStretcher::Impl::configure() +StretcherImpl::configure() { // std::cerr << "configure[" << this << "]: realtime = " << m_realtime << ", pitch scale = " // << m_pitchScale << ", channels = " << m_channels << std::endl; @@ -546,7 +546,7 @@ RubberBandStretcher::Impl::configure() } delete m_phaseResetAudioCurve; - m_phaseResetAudioCurve = new PercussiveAudioCurve(m_stretcher->m_sampleRate, + m_phaseResetAudioCurve = new PercussiveAudioCurve(m_sampleRate, m_windowSize); // stretchAudioCurve unused in RT mode; phaseResetAudioCurve and @@ -554,19 +554,19 @@ RubberBandStretcher::Impl::configure() if (!m_realtime) { delete m_stretchAudioCurve; - if (!(m_options & OptionStretchPrecise)) { + if (!(m_options & RubberBandStretcher::OptionStretchPrecise)) { m_stretchAudioCurve = new SpectralDifferenceAudioCurve - (m_stretcher->m_sampleRate, m_windowSize); + (m_sampleRate, m_windowSize); } else { m_stretchAudioCurve = new ConstantAudioCurve - (m_stretcher->m_sampleRate, m_windowSize); + (m_sampleRate, m_windowSize); } } delete m_stretchCalculator; m_stretchCalculator = new StretchCalculator - (m_stretcher->m_sampleRate, m_increment, - !(m_options & OptionTransientsSmooth)); + (m_sampleRate, m_increment, + !(m_options & RubberBandStretcher::OptionTransientsSmooth)); m_stretchCalculator->setDebugLevel(m_debugLevel); m_inputDuration = 0; @@ -592,7 +592,7 @@ RubberBandStretcher::Impl::configure() void -RubberBandStretcher::Impl::reconfigure() +StretcherImpl::reconfigure() { if (!m_realtime) { if (m_mode == Studying) { @@ -659,57 +659,57 @@ RubberBandStretcher::Impl::reconfigure() } size_t -RubberBandStretcher::Impl::getLatency() const +StretcherImpl::getLatency() const { if (!m_realtime) return 0; return int((m_windowSize/2) / m_pitchScale + 1); } void -RubberBandStretcher::Impl::setTransientsOption(Options options) +StretcherImpl::setTransientsOption(RubberBandStretcher::Options options) { if (!m_realtime) { - cerr << "RubberBandStretcher::Impl::setTransientsOption: Not permissible in non-realtime mode" << endl; + cerr << "StretcherImpl::setTransientsOption: Not permissible in non-realtime mode" << endl; return; } - int mask = (OptionTransientsMixed | OptionTransientsSmooth | OptionTransientsCrisp); + int mask = (RubberBandStretcher::OptionTransientsMixed | RubberBandStretcher::OptionTransientsSmooth | RubberBandStretcher::OptionTransientsCrisp); m_options &= ~mask; options &= mask; m_options |= options; m_stretchCalculator->setUseHardPeaks - (!(m_options & OptionTransientsSmooth)); + (!(m_options & RubberBandStretcher::OptionTransientsSmooth)); } void -RubberBandStretcher::Impl::setPhaseOption(Options options) +StretcherImpl::setPhaseOption(RubberBandStretcher::Options options) { - int mask = (OptionPhaseAdaptive | OptionPhasePeakLocked | OptionPhaseIndependent); + int mask = (RubberBandStretcher::OptionPhaseAdaptive | RubberBandStretcher::OptionPhasePeakLocked | RubberBandStretcher::OptionPhaseIndependent); m_options &= ~mask; options &= mask; m_options |= options; } void -RubberBandStretcher::Impl::setFormantOption(Options options) +StretcherImpl::setFormantOption(RubberBandStretcher::Options options) { - int mask = (OptionFormantShifted | OptionFormantPreserved); + int mask = (RubberBandStretcher::OptionFormantShifted | RubberBandStretcher::OptionFormantPreserved); m_options &= ~mask; options &= mask; m_options |= options; } void -RubberBandStretcher::Impl::setPitchOption(Options options) +StretcherImpl::setPitchOption(RubberBandStretcher::Options options) { if (!m_realtime) { - cerr << "RubberBandStretcher::Impl::setPitchOption: Pitch option is not used in non-RT mode" << endl; + cerr << "StretcherImpl::setPitchOption: Pitch option is not used in non-RT mode" << endl; return; } - Options prior = m_options; + RubberBandStretcher::Options prior = m_options; - int mask = (OptionPitchHighQuality | OptionPitchHighSpeed); + int mask = (RubberBandStretcher::OptionPitchHighQuality | RubberBandStretcher::OptionPitchHighSpeed); m_options &= ~mask; options &= mask; m_options |= options; @@ -718,19 +718,19 @@ RubberBandStretcher::Impl::setPitchOption(Options options) } void -RubberBandStretcher::Impl::study(const float *const *input, size_t samples, bool final) +StretcherImpl::study(const float *const *input, size_t samples, bool final) { - Profiler profiler("RubberBandStretcher::Impl::study"); + Profiler profiler("StretcherImpl::study"); if (m_realtime) { if (m_debugLevel > 1) { - cerr << "RubberBandStretcher::Impl::study: Not meaningful in realtime mode" << endl; + cerr << "StretcherImpl::study: Not meaningful in realtime mode" << endl; } return; } if (m_mode == Processing || m_mode == Finished) { - cerr << "RubberBandStretcher::Impl::study: Cannot study after processing" << endl; + cerr << "StretcherImpl::study: Cannot study after processing" << endl; return; } m_mode = Studying; @@ -837,7 +837,7 @@ RubberBandStretcher::Impl::study(const float *const *input, size_t samples, bool } vector -RubberBandStretcher::Impl::getOutputIncrements() const +StretcherImpl::getOutputIncrements() const { if (!m_realtime) { return m_outputIncrements; @@ -851,7 +851,7 @@ RubberBandStretcher::Impl::getOutputIncrements() const } vector -RubberBandStretcher::Impl::getPhaseResetCurve() const +StretcherImpl::getPhaseResetCurve() const { if (!m_realtime) { return m_phaseResetDf; @@ -865,7 +865,7 @@ RubberBandStretcher::Impl::getPhaseResetCurve() const } vector -RubberBandStretcher::Impl::getExactTimePoints() const +StretcherImpl::getExactTimePoints() const { std::vector points; if (!m_realtime) { @@ -879,9 +879,9 @@ RubberBandStretcher::Impl::getExactTimePoints() const } void -RubberBandStretcher::Impl::calculateStretch() +StretcherImpl::calculateStretch() { - Profiler profiler("RubberBandStretcher::Impl::calculateStretch"); + Profiler profiler("StretcherImpl::calculateStretch"); std::vector increments = m_stretchCalculator->calculate (getEffectiveRatio(), @@ -900,16 +900,16 @@ RubberBandStretcher::Impl::calculateStretch() } void -RubberBandStretcher::Impl::setDebugLevel(int level) +StretcherImpl::setDebugLevel(int level) { m_debugLevel = level; if (m_stretchCalculator) m_stretchCalculator->setDebugLevel(level); } size_t -RubberBandStretcher::Impl::getSamplesRequired() const +StretcherImpl::getSamplesRequired() const { - Profiler profiler("RubberBandStretcher::Impl::getSamplesRequired"); + Profiler profiler("StretcherImpl::getSamplesRequired"); size_t reqd = 0; @@ -944,12 +944,12 @@ RubberBandStretcher::Impl::getSamplesRequired() const } void -RubberBandStretcher::Impl::process(const float *const *input, size_t samples, bool final) +StretcherImpl::process(const float *const *input, size_t samples, bool final) { - Profiler profiler("RubberBandStretcher::Impl::process"); + Profiler profiler("StretcherImpl::process"); if (m_mode == Finished) { - cerr << "RubberBandStretcher::Impl::process: Cannot process again after final chunk" << endl; + cerr << "StretcherImpl::process: Cannot process again after final chunk" << endl; return; } @@ -1045,7 +1045,7 @@ RubberBandStretcher::Impl::process(const float *const *input, size_t samples, bo /* } 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; + cerr << "StretcherImpl::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; } diff --git a/src/StretcherImpl.h b/src/StretcherImpl.h index f743129..d06b5c4 100644 --- a/src/StretcherImpl.h +++ b/src/StretcherImpl.h @@ -31,13 +31,14 @@ namespace RubberBand class AudioCurve; class StretchCalculator; -class RubberBandStretcher::Impl +class StretcherImpl { public: - Impl(RubberBandStretcher *stretcher, - size_t sampleRate, size_t channels, Options options, - double initialTimeRatio, double initialPitchScale); - ~Impl(); + typedef RubberBandStretcher::Options Options; + + StretcherImpl(size_t sampleRate, size_t channels, Options options, + double initialTimeRatio, double initialPitchScale); + ~StretcherImpl(); void reset(); void setTimeRatio(double ratio); @@ -85,7 +86,7 @@ public: static void setDefaultDebugLevel(int level) { m_defaultDebugLevel = level; } protected: - RubberBandStretcher *m_stretcher; + size_t m_sampleRate; size_t m_channels; size_t consumeChannel(size_t channel, const float *input, @@ -148,12 +149,12 @@ protected: class ProcessThread : public Thread { public: - ProcessThread(Impl *s, size_t c); + ProcessThread(StretcherImpl *s, size_t c); void run(); void signalDataAvailable(); void abandon(); private: - Impl *m_s; + StretcherImpl *m_s; size_t m_channel; Condition m_dataAvailable; bool m_abandoning; diff --git a/src/StretcherProcess.cpp b/src/StretcherProcess.cpp index eb7bcc6..986afd1 100644 --- a/src/StretcherProcess.cpp +++ b/src/StretcherProcess.cpp @@ -33,7 +33,7 @@ using std::endl; namespace RubberBand { -RubberBandStretcher::Impl::ProcessThread::ProcessThread(Impl *s, size_t c) : +StretcherImpl::ProcessThread::ProcessThread(StretcherImpl *s, size_t c) : m_s(s), m_channel(c), m_dataAvailable(std::string("data ") + char('A' + c)), @@ -41,7 +41,7 @@ RubberBandStretcher::Impl::ProcessThread::ProcessThread(Impl *s, size_t c) : { } void -RubberBandStretcher::Impl::ProcessThread::run() +StretcherImpl::ProcessThread::run() { if (m_s->m_debugLevel > 1) { cerr << "thread " << m_channel << " getting going" << endl; @@ -89,26 +89,26 @@ RubberBandStretcher::Impl::ProcessThread::run() } void -RubberBandStretcher::Impl::ProcessThread::signalDataAvailable() +StretcherImpl::ProcessThread::signalDataAvailable() { m_dataAvailable.signal(); } void -RubberBandStretcher::Impl::ProcessThread::abandon() +StretcherImpl::ProcessThread::abandon() { m_abandoning = true; } bool -RubberBandStretcher::Impl::resampleBeforeStretching() const +StretcherImpl::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) { + if (m_options & RubberBandStretcher::OptionPitchHighQuality) { return (m_pitchScale < 1.0); // better sound } else { return (m_pitchScale > 1.0); // better performance @@ -116,10 +116,10 @@ RubberBandStretcher::Impl::resampleBeforeStretching() const } size_t -RubberBandStretcher::Impl::consumeChannel(size_t c, const float *input, +StretcherImpl::consumeChannel(size_t c, const float *input, size_t samples, bool final) { - Profiler profiler("RubberBandStretcher::Impl::consumeChannel"); + Profiler profiler("StretcherImpl::consumeChannel"); ChannelData &cd = *m_channelData[c]; RingBuffer &inbuf = *cd.inbuf; @@ -139,7 +139,7 @@ RubberBandStretcher::Impl::consumeChannel(size_t c, const float *input, size_t reqSize = int(ceil(samples / m_pitchScale)); if (reqSize > cd.resamplebufSize) { - cerr << "WARNING: RubberBandStretcher::Impl::consumeChannel: resizing resampler buffer from " + cerr << "WARNING: StretcherImpl::consumeChannel: resizing resampler buffer from " << cd.resamplebufSize << " to " << reqSize << endl; cd.setResampleBufSize(reqSize); } @@ -172,9 +172,9 @@ RubberBandStretcher::Impl::consumeChannel(size_t c, const float *input, } void -RubberBandStretcher::Impl::processChunks(size_t c, bool &any, bool &last) +StretcherImpl::processChunks(size_t c, bool &any, bool &last) { - Profiler profiler("RubberBandStretcher::Impl::processChunks"); + Profiler profiler("StretcherImpl::processChunks"); // Process as many chunks as there are available on the input // buffer for channel c. This requires that the increments have @@ -214,9 +214,9 @@ RubberBandStretcher::Impl::processChunks(size_t c, bool &any, bool &last) } bool -RubberBandStretcher::Impl::processOneChunk() +StretcherImpl::processOneChunk() { - Profiler profiler("RubberBandStretcher::Impl::processOneChunk"); + Profiler profiler("StretcherImpl::processOneChunk"); // Process a single chunk for all channels, provided there is // enough data on each channel for at least one chunk. This is @@ -249,9 +249,9 @@ RubberBandStretcher::Impl::processOneChunk() } bool -RubberBandStretcher::Impl::testInbufReadSpace(size_t c) +StretcherImpl::testInbufReadSpace(size_t c) { - Profiler profiler("RubberBandStretcher::Impl::testInbufReadSpace"); + Profiler profiler("StretcherImpl::testInbufReadSpace"); ChannelData &cd = *m_channelData[c]; RingBuffer &inbuf = *cd.inbuf; @@ -298,12 +298,12 @@ RubberBandStretcher::Impl::testInbufReadSpace(size_t c) } bool -RubberBandStretcher::Impl::processChunkForChannel(size_t c, +StretcherImpl::processChunkForChannel(size_t c, size_t phaseIncrement, size_t shiftIncrement, bool phaseReset) { - Profiler profiler("RubberBandStretcher::Impl::processChunkForChannel"); + Profiler profiler("StretcherImpl::processChunkForChannel"); // Process a single chunk on a single channel. This assumes // enough input data is available; caller must have tested this @@ -393,11 +393,11 @@ RubberBandStretcher::Impl::processChunkForChannel(size_t c, } void -RubberBandStretcher::Impl::calculateIncrements(size_t &phaseIncrementRtn, +StretcherImpl::calculateIncrements(size_t &phaseIncrementRtn, size_t &shiftIncrementRtn, bool &phaseReset) { - Profiler profiler("RubberBandStretcher::Impl::calculateIncrements"); + Profiler profiler("StretcherImpl::calculateIncrements"); // cerr << "calculateIncrements" << endl; @@ -423,7 +423,7 @@ RubberBandStretcher::Impl::calculateIncrements(size_t &phaseIncrementRtn, 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; + cerr << "ERROR: StretcherImpl::calculateIncrements: Channels are not in sync" << endl; return; } } @@ -498,12 +498,12 @@ RubberBandStretcher::Impl::calculateIncrements(size_t &phaseIncrementRtn, } bool -RubberBandStretcher::Impl::getIncrements(size_t channel, +StretcherImpl::getIncrements(size_t channel, size_t &phaseIncrementRtn, size_t &shiftIncrementRtn, bool &phaseReset) { - Profiler profiler("RubberBandStretcher::Impl::getIncrements"); + Profiler profiler("StretcherImpl::getIncrements"); if (channel >= m_channels) { phaseIncrementRtn = m_increment; @@ -532,7 +532,7 @@ RubberBandStretcher::Impl::getIncrements(size_t channel, bool gotData = true; if (cd.chunkCount >= m_outputIncrements.size()) { -// cerr << "WARNING: RubberBandStretcher::Impl::getIncrements:" +// cerr << "WARNING: StretcherImpl::getIncrements:" // << " chunk count " << cd.chunkCount << " >= " // << m_outputIncrements.size() << endl; if (m_outputIncrements.size() == 0) { @@ -563,7 +563,7 @@ RubberBandStretcher::Impl::getIncrements(size_t channel, } if (shiftIncrement >= int(m_windowSize)) { - cerr << "*** ERROR: RubberBandStretcher::Impl::processChunks: shiftIncrement " << shiftIncrement << " >= windowSize " << m_windowSize << " at " << cd.chunkCount << " (of " << m_outputIncrements.size() << ")" << endl; + cerr << "*** ERROR: StretcherImpl::processChunks: shiftIncrement " << shiftIncrement << " >= windowSize " << m_windowSize << " at " << cd.chunkCount << " (of " << m_outputIncrements.size() << ")" << endl; shiftIncrement = m_windowSize; } @@ -574,9 +574,9 @@ RubberBandStretcher::Impl::getIncrements(size_t channel, } void -RubberBandStretcher::Impl::analyseChunk(size_t channel) +StretcherImpl::analyseChunk(size_t channel) { - Profiler profiler("RubberBandStretcher::Impl::analyseChunk"); + Profiler profiler("StretcherImpl::analyseChunk"); int i; @@ -627,10 +627,10 @@ 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, +StretcherImpl::modifyChunk(size_t channel, size_t outputIncrement, bool phaseReset) { - Profiler profiler("RubberBandStretcher::Impl::modifyChunk"); + Profiler profiler("StretcherImpl::modifyChunk"); ChannelData &cd = *m_channelData[channel]; @@ -639,7 +639,7 @@ RubberBandStretcher::Impl::modifyChunk(size_t channel, size_t outputIncrement, } int pfp = 0; - double rate = m_stretcher->m_sampleRate; + double rate = m_sampleRate; int sz = m_windowSize; @@ -648,7 +648,7 @@ RubberBandStretcher::Impl::modifyChunk(size_t channel, size_t outputIncrement, bool unchanged = cd.unchanged && (outputIncrement == m_increment); bool fullReset = phaseReset; - if (!(m_options & OptionPhaseIndependent)) { + if (!(m_options & RubberBandStretcher::OptionPhaseIndependent)) { cd.freqPeak[0] = 0; @@ -664,7 +664,7 @@ RubberBandStretcher::Impl::modifyChunk(size_t channel, size_t outputIncrement, // We only do this if the phase option is OptionPhaseAdaptive // (the default), i.e. not Independent or PeakLocked. - if (!(m_options & OptionPhasePeakLocked)) { + if (!(m_options & RubberBandStretcher::OptionPhasePeakLocked)) { float r = getEffectiveRatio(); if (r > 1) { float rf0 = 600 + (600 * ((r-1)*(r-1)*(r-1)*2)); @@ -744,7 +744,7 @@ RubberBandStretcher::Impl::modifyChunk(size_t channel, size_t outputIncrement, cd.freqPeak[count] = count; } - Profiler profiler2("RubberBandStretcher::Impl::modifyChunk part 2"); + Profiler profiler2("StretcherImpl::modifyChunk part 2"); double peakInPhase = 0.0; double peakOutPhase = 0.0; @@ -753,7 +753,7 @@ RubberBandStretcher::Impl::modifyChunk(size_t channel, size_t outputIncrement, for (int i = 0; i <= count; ++i) { - if (m_options & OptionPhaseIndependent) { + if (m_options & RubberBandStretcher::OptionPhaseIndependent) { p = i; pp = i-1; } else { @@ -763,7 +763,7 @@ RubberBandStretcher::Impl::modifyChunk(size_t channel, size_t outputIncrement, bool resetThis = phaseReset; - if (m_options & OptionTransientsMixed) { + if (m_options & RubberBandStretcher::OptionTransientsMixed) { int low = lrint((150 * sz * cd.oversample) / rate); int high = lrint((1000 * sz * cd.oversample) / rate); if (resetThis) { @@ -827,9 +827,9 @@ RubberBandStretcher::Impl::modifyChunk(size_t channel, size_t outputIncrement, void -RubberBandStretcher::Impl::formantShiftChunk(size_t channel) +StretcherImpl::formantShiftChunk(size_t channel) { - Profiler profiler("RubberBandStretcher::Impl::formantShiftChunk"); + Profiler profiler("StretcherImpl::formantShiftChunk"); ChannelData &cd = *m_channelData[channel]; @@ -848,7 +848,7 @@ RubberBandStretcher::Impl::formantShiftChunk(size_t channel) } //!!! calculate this value -- the divisor should be the highest fundamental frequency we expect to find, plus a bit - const int cutoff = m_stretcher->m_sampleRate / 700; + const int cutoff = m_sampleRate / 700; dblbuf[0] /= 2; dblbuf[cutoff-1] /= 2; @@ -893,12 +893,12 @@ RubberBandStretcher::Impl::formantShiftChunk(size_t channel) } void -RubberBandStretcher::Impl::synthesiseChunk(size_t channel) +StretcherImpl::synthesiseChunk(size_t channel) { - Profiler profiler("RubberBandStretcher::Impl::synthesiseChunk"); + Profiler profiler("StretcherImpl::synthesiseChunk"); - if ((m_options & OptionFormantPreserved) && + if ((m_options & RubberBandStretcher::OptionFormantPreserved) && (m_pitchScale != 1.0)) { formantShiftChunk(channel); } @@ -969,9 +969,9 @@ RubberBandStretcher::Impl::synthesiseChunk(size_t channel) } void -RubberBandStretcher::Impl::writeChunk(size_t channel, size_t shiftIncrement, bool last) +StretcherImpl::writeChunk(size_t channel, size_t shiftIncrement, bool last) { - Profiler profiler("RubberBandStretcher::Impl::writeChunk"); + Profiler profiler("StretcherImpl::writeChunk"); ChannelData &cd = *m_channelData[channel]; @@ -1011,7 +1011,7 @@ RubberBandStretcher::Impl::writeChunk(size_t channel, size_t shiftIncrement, boo // 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 " + cerr << "WARNING: StretcherImpl::writeChunk: resizing resampler buffer from " << cd.resamplebufSize << " to " << reqSize << endl; cd.setResampleBufSize(reqSize); } @@ -1054,7 +1054,7 @@ RubberBandStretcher::Impl::writeChunk(size_t channel, size_t shiftIncrement, boo cd.accumulatorFill = 0; if (cd.draining) { if (m_debugLevel > 1) { - cerr << "RubberBandStretcher::Impl::processChunks: setting outputComplete to true" << endl; + cerr << "StretcherImpl::processChunks: setting outputComplete to true" << endl; } cd.outputComplete = true; } @@ -1062,9 +1062,9 @@ RubberBandStretcher::Impl::writeChunk(size_t channel, size_t shiftIncrement, boo } void -RubberBandStretcher::Impl::writeOutput(RingBuffer &to, float *from, size_t qty, size_t &outCount, size_t theoreticalOut) +StretcherImpl::writeOutput(RingBuffer &to, float *from, size_t qty, size_t &outCount, size_t theoreticalOut) { - Profiler profiler("RubberBandStretcher::Impl::writeOutput"); + Profiler profiler("StretcherImpl::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 @@ -1103,7 +1103,7 @@ RubberBandStretcher::Impl::writeOutput(RingBuffer &to, float *from, size_ size_t written = to.write(from, qty); if (written < qty) { - cerr << "WARNING: RubberBandStretcher::Impl::writeOutput: " + cerr << "WARNING: StretcherImpl::writeOutput: " << "Buffer overrun on output: wrote " << written << " of " << qty << " samples" << endl; } @@ -1136,9 +1136,9 @@ RubberBandStretcher::Impl::writeOutput(RingBuffer &to, float *from, size_ } int -RubberBandStretcher::Impl::available() const +StretcherImpl::available() const { - Profiler profiler("RubberBandStretcher::Impl::available"); + Profiler profiler("StretcherImpl::available"); if (m_threaded) { MutexLocker locker(&m_threadSetMutex); @@ -1156,7 +1156,7 @@ RubberBandStretcher::Impl::available() const //!!! 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); + ((StretcherImpl *)this)->processChunks(c, any, last); } } } @@ -1185,9 +1185,9 @@ RubberBandStretcher::Impl::available() const } size_t -RubberBandStretcher::Impl::retrieve(float *const *output, size_t samples) const +StretcherImpl::retrieve(float *const *output, size_t samples) const { - Profiler profiler("RubberBandStretcher::Impl::retrieve"); + Profiler profiler("StretcherImpl::retrieve"); size_t got = samples; @@ -1196,7 +1196,7 @@ RubberBandStretcher::Impl::retrieve(float *const *output, size_t samples) const if (gotHere < got) { if (c > 0) { if (m_debugLevel > 0) { - cerr << "RubberBandStretcher::Impl::retrieve: WARNING: channel imbalance detected" << endl; + cerr << "StretcherImpl::retrieve: WARNING: channel imbalance detected" << endl; } } got = gotHere; diff --git a/src/bsd-3rdparty/float_cast/float_cast.h b/src/bsd-3rdparty/float_cast/float_cast.h index 1ba0e03..c149bbd 100644 --- a/src/bsd-3rdparty/float_cast/float_cast.h +++ b/src/bsd-3rdparty/float_cast/float_cast.h @@ -37,6 +37,8 @@ #if (defined (WIN32) || defined (_WIN32)) +#ifndef MINGW32 + #include /* Win32 doesn't seem to have these functions. @@ -69,5 +71,7 @@ #endif +#endif + diff --git a/src/ladspa/RubberBandPitchShifter.cpp b/src/ladspa/RubberBandPitchShifter.cpp index bd66bfd..3be8dfd 100644 --- a/src/ladspa/RubberBandPitchShifter.cpp +++ b/src/ladspa/RubberBandPitchShifter.cpp @@ -29,6 +29,7 @@ RubberBandPitchShifter::portNamesMono[PortCountMono] = "Semitones", "Octaves", "Crispness", + "Formant Preservation", "Input", "Output" }; @@ -41,6 +42,7 @@ RubberBandPitchShifter::portNamesStereo[PortCountStereo] = "Semitones", "Octaves", "Crispness", + "Formant Preservation", "Input L", "Output L", "Input R", @@ -206,9 +208,11 @@ RubberBandPitchShifter::RubberBandPitchShifter(int sampleRate, size_t channels) m_semitones(0), m_octaves(0), m_crispness(0), + m_formant(0), m_ratio(1.0), m_prevRatio(1.0), m_currentCrispness(-1), + m_currentFormant(false), m_extraLatency(8192), //!!! this should be at least the maximum possible displacement from linear at input rates, divided by the pitch scale factor. It could be very large m_stretcher(new RubberBandStretcher (sampleRate, channels, @@ -259,6 +263,7 @@ RubberBandPitchShifter::connectPort(LADSPA_Handle handle, &shifter->m_semitones, &shifter->m_octaves, &shifter->m_crispness, + &shifter->m_formant, &shifter->m_input[0], &shifter->m_output[0], &shifter->m_input[1], @@ -326,6 +331,23 @@ RubberBandPitchShifter::updateCrispness() 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::runImpl(unsigned long insamples) { @@ -343,6 +365,7 @@ RubberBandPitchShifter::runImpl(unsigned long insamples) } updateCrispness(); + updateFormant(); int samples = insamples; int processed = 0; diff --git a/src/ladspa/RubberBandPitchShifter.h b/src/ladspa/RubberBandPitchShifter.h index 520b14b..e490573 100644 --- a/src/ladspa/RubberBandPitchShifter.h +++ b/src/ladspa/RubberBandPitchShifter.h @@ -38,6 +38,7 @@ protected: SemitonesPort = 2, CentsPort = 3, CrispnessPort = 4, + FormantPort = 5, InputPort1 = 6, OutputPort1 = 7, PortCountMono = OutputPort1 + 1, @@ -69,6 +70,7 @@ protected: void runImpl(unsigned long); void updateRatio(); void updateCrispness(); + void updateFormant(); float *m_input[2]; float *m_output[2]; @@ -77,9 +79,11 @@ protected: float *m_semitones; float *m_octaves; float *m_crispness; + float *m_formant; double m_ratio; double m_prevRatio; int m_currentCrispness; + bool m_currentFormant; size_t m_extraLatency;