From c70480bb3c1f32ec3c37394f4aa7a225d16efda4 Mon Sep 17 00:00:00 2001 From: Chris Cannam Date: Tue, 1 Jul 2008 10:25:17 +0000 Subject: [PATCH] * Update for newer take on the C wrapper API * Add library versioning and DESTDIR support --- Makefile.in | 74 +++++---- configure.ac | 2 +- rubberband.pc.in | 2 +- rubberband/RubberBandStretcher.h | 112 ++++--------- rubberband/{rubberband.h => rubberband-c.h} | 21 ++- src/RubberBandStretcher.cpp | 174 +++++++++++++------- src/StretcherChannelData.cpp | 16 +- src/StretcherChannelData.h | 2 +- src/StretcherImpl.cpp | 135 ++++++++------- src/StretcherImpl.h | 14 +- src/StretcherProcess.cpp | 102 ++++++------ src/bsd-3rdparty/float_cast/float_cast.h | 4 - src/ladspa/RubberBandPitchShifter.cpp | 20 ++- src/ladspa/ladspa-rubberband.rdf | 12 ++ src/rubberband-c.cpp | 146 ++++++++++++++++ 15 files changed, 516 insertions(+), 320 deletions(-) rename rubberband/{rubberband.h => rubberband-c.h} (88%) create mode 100644 src/ladspa/ladspa-rubberband.rdf create mode 100644 src/rubberband-c.cpp diff --git a/Makefile.in b/Makefile.in index 2966c98..fd36f1b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -12,12 +12,15 @@ LADSPA_PLUGIN_LIBS := $(LIBRARY_LIBS) MKDIR := mkdir AR := ar -DYNAMIC_LDFLAGS := -shared -Wl,-Bsymbolic DYNAMIC_EXTENSION := .so +DYNAMIC_FULL_VERSION := .2.0.0 +DYNAMIC_ABI_VERSION := .2 +DYNAMIC_LIBNAME := librubberband$(DYNAMIC_EXTENSION) +DYNAMIC_LDFLAGS := -shared -Wl,-Bsymbolic -Wl,-soname=$(DYNAMIC_LIBNAME)$(DYNAMIC_ABI_VERSION) PROGRAM_TARGET := bin/rubberband STATIC_TARGET := lib/librubberband.a -DYNAMIC_TARGET := lib/librubberband$(DYNAMIC_EXTENSION) +DYNAMIC_TARGET := lib/$(DYNAMIC_LIBNAME) VAMP_TARGET := lib/vamp-rubberband$(DYNAMIC_EXTENSION) LADSPA_TARGET := lib/ladspa-rubberband$(DYNAMIC_EXTENSION) @@ -26,6 +29,7 @@ INSTALL_INCDIR := @prefix@/include/rubberband INSTALL_LIBDIR := @prefix@/lib INSTALL_VAMPDIR := @prefix@/lib/vamp INSTALL_LADSPADIR := @prefix@/lib/ladspa +INSTALL_LRDFDIR := @prefix@/share/ladspa/rdf INSTALL_PKGDIR := @prefix@/lib/pkgconfig all: bin lib $(PROGRAM_TARGET) $(STATIC_TARGET) $(DYNAMIC_TARGET) $(VAMP_TARGET) $(LADSPA_TARGET) @@ -38,7 +42,7 @@ vamp: $(VAMP_TARGET) ladspa: $(LADSPA_TARGET) PUBLIC_INCLUDES := \ - rubberband/rubberband.h \ + rubberband/rubberband-c.h \ rubberband/RubberBandStretcher.h LIBRARY_INCLUDES := \ @@ -67,6 +71,7 @@ LIBRARY_SOURCES := \ src/PercussiveAudioCurve.cpp \ src/Profiler.cpp \ src/Resampler.cpp \ + src/rubberband-c.cpp \ src/RubberBandStretcher.cpp \ src/SpectralDifferenceAudioCurve.cpp \ src/StretchCalculator.cpp \ @@ -102,7 +107,7 @@ VAMP_OBJECTS := $(VAMP_SOURCES:.cpp=.o) LADSPA_OBJECTS := $(LADSPA_SOURCES:.cpp=.o) $(PROGRAM_TARGET): $(LIBRARY_OBJECTS) $(PROGRAM_OBJECTS) - $(CXX) -o $@ $^ $(PROGRAM_LIBS) $(PROGRAM_LIBS) $(LDFLAGS) + $(CXX) -o $@ $^ $(PROGRAM_LIBS) $(LDFLAGS) $(STATIC_TARGET): $(LIBRARY_OBJECTS) $(AR) rsc $@ $^ @@ -122,22 +127,28 @@ lib: $(MKDIR) $@ install: all - $(MKDIR) -p $(INSTALL_BINDIR) - $(MKDIR) -p $(INSTALL_INCDIR) - $(MKDIR) -p $(INSTALL_LIBDIR) - $(MKDIR) -p $(INSTALL_VAMPDIR) - $(MKDIR) -p $(INSTALL_LADSPADIR) - $(MKDIR) -p $(INSTALL_PKGDIR) - cp $(PROGRAM_TARGET) $(INSTALL_BINDIR) - cp $(PUBLIC_INCLUDES) $(INSTALL_INCDIR) - cp $(STATIC_TARGET) $(INSTALL_LIBDIR) - cp $(DYNAMIC_TARGET) $(INSTALL_LIBDIR) - cp $(VAMP_TARGET) $(INSTALL_VAMPDIR) - cp src/vamp/vamp-rubberband.cat $(INSTALL_VAMPDIR) - cp $(LADSPA_TARGET) $(INSTALL_LADSPADIR) - cp src/ladspa/ladspa-rubberband.cat $(INSTALL_LADSPADIR) + $(MKDIR) -p $(DESTDIR)$(INSTALL_BINDIR) + $(MKDIR) -p $(DESTDIR)$(INSTALL_INCDIR) + $(MKDIR) -p $(DESTDIR)$(INSTALL_LIBDIR) + $(MKDIR) -p $(DESTDIR)$(INSTALL_VAMPDIR) + $(MKDIR) -p $(DESTDIR)$(INSTALL_LADSPADIR) + $(MKDIR) -p $(DESTDIR)$(INSTALL_LRDFDIR) + $(MKDIR) -p $(DESTDIR)$(INSTALL_PKGDIR) + cp $(PROGRAM_TARGET) $(DESTDIR)$(INSTALL_BINDIR) + cp $(PUBLIC_INCLUDES) $(DESTDIR)$(INSTALL_INCDIR) + cp $(STATIC_TARGET) $(DESTDIR)$(INSTALL_LIBDIR) + rm -f $(DESTDIR)$(INSTALL_LIBDIR)/$(DYNAMIC_LIBNAME)$(DYNAMIC_ABI_VERSION) + rm -f $(DESTDIR)$(INSTALL_LIBDIR)/$(DYNAMIC_LIBNAME) + cp $(DYNAMIC_TARGET) $(DESTDIR)$(INSTALL_LIBDIR)/$(DYNAMIC_LIBNAME)$(DYNAMIC_FULL_VERSION) + test -n "$(DYNAMIC_FULL_VERSION)" && ln -s $(DYNAMIC_LIBNAME)$(DYNAMIC_FULL_VERSION) $(DESTDIR)$(INSTALL_LIBDIR)/$(DYNAMIC_LIBNAME)$(DYNAMIC_ABI_VERSION) + test -n "$(DYNAMIC_FULL_VERSION)" && ln -s $(DYNAMIC_LIBNAME)$(DYNAMIC_FULL_VERSION) $(DESTDIR)$(INSTALL_LIBDIR)/$(DYNAMIC_LIBNAME) + cp $(VAMP_TARGET) $(DESTDIR)$(INSTALL_VAMPDIR) + cp src/vamp/vamp-rubberband.cat $(DESTDIR)$(INSTALL_VAMPDIR) + cp $(LADSPA_TARGET) $(DESTDIR)$(INSTALL_LADSPADIR) + cp src/ladspa/ladspa-rubberband.cat $(DESTDIR)$(INSTALL_LADSPADIR) + cp src/ladspa/ladspa-rubberband.rdf $(DESTDIR)$(INSTALL_LRDFDIR) sed "s,%PREFIX%,@prefix@," rubberband.pc.in \ - > $(INSTALL_PKGDIR)/rubberband.pc + > $(DESTDIR)$(INSTALL_PKGDIR)/rubberband.pc clean: rm -f $(LIBRARY_OBJECTS) $(PROGRAM_OBJECTS) $(LADSPA_OBJECTS) $(VAMP_OBJECTS) @@ -153,7 +164,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/rubberband.h +src/main.o: rubberband/RubberBandStretcher.h rubberband/rubberband-c.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 +174,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/rubberband.h src/Window.h +src/RubberBandStretcher.o: rubberband/rubberband-c.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 +183,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/rubberband.h src/Window.h +src/StretcherChannelData.o: rubberband/rubberband-c.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/rubberband.h src/Window.h src/sysutils.h +src/StretcherImpl.o: rubberband/rubberband-c.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 +196,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/rubberband.h src/Window.h +src/StretcherProcess.o: rubberband/rubberband-c.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 +206,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/rubberband.h +rubberband/RubberBandStretcher.o: rubberband/rubberband-c.h src/AudioCurve.o: src/sysutils.h src/ConstantAudioCurve.o: src/AudioCurve.h src/sysutils.h src/FFT.o: src/sysutils.h @@ -209,13 +220,14 @@ 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/rubberband.h src/Window.h +src/StretcherChannelData.o: rubberband/rubberband-c.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/rubberband.h src/Window.h src/sysutils.h +src/StretcherImpl.o: rubberband/rubberband-c.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/rubberband-c.o: rubberband/RubberBandStretcher.h rubberband/rubberband-c.h src/Window.o: src/sysutils.h src/ladspa/libmain.o: src/ladspa/RubberBandPitchShifter.h src/ladspa/libmain.o: src/RingBuffer.h src/Scavenger.h src/Thread.h @@ -225,16 +237,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/rubberband.h +src/ladspa/RubberBandPitchShifter.o: rubberband/rubberband-c.h src/vamp/libmain.o: src/vamp/RubberBandVampPlugin.h src/vamp/libmain.o: rubberband/RubberBandStretcher.h -src/vamp/libmain.o: rubberband/rubberband.h +src/vamp/libmain.o: rubberband/rubberband-c.h src/vamp/RubberBandVampPlugin.o: src/vamp/RubberBandVampPlugin.h src/vamp/RubberBandVampPlugin.o: rubberband/RubberBandStretcher.h -src/vamp/RubberBandVampPlugin.o: rubberband/rubberband.h +src/vamp/RubberBandVampPlugin.o: rubberband/rubberband-c.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/rubberband.h +src/vamp/RubberBandVampPlugin.o: rubberband/rubberband-c.h diff --git a/configure.ac b/configure.ac index 87bb0df..bdf4e63 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ -AC_INIT(RubberBand, 1.1, cannam@all-day-breakfast.com) +AC_INIT(RubberBand, 1.2, cannam@all-day-breakfast.com) AC_CONFIG_SRCDIR(src/StretcherImpl.h) AC_PROG_CXX diff --git a/rubberband.pc.in b/rubberband.pc.in index 580fea3..3ab0a99 100644 --- a/rubberband.pc.in +++ b/rubberband.pc.in @@ -4,7 +4,7 @@ libdir=${exec_prefix}/lib includedir=${prefix}/include Name: rubberband -Version: 1.0 +Version: 1.2 Description: Libs: -L${libdir} -lrubberband Cflags: -I${includedir} diff --git a/rubberband/RubberBandStretcher.h b/rubberband/RubberBandStretcher.h index 6af71f1..6820516 100644 --- a/rubberband/RubberBandStretcher.h +++ b/rubberband/RubberBandStretcher.h @@ -15,14 +15,12 @@ #ifndef _RUBBERBANDSTRETCHER_H_ #define _RUBBERBANDSTRETCHER_H_ -#include "rubberband.h" - #include /** * @mainpage RubberBand * - * The Rubber Band C++ API is contained in the single class + * The Rubber Band API is contained in the single class * RubberBand::RubberBandStretcher. */ @@ -33,10 +31,10 @@ class RubberBandStretcher { public: /** - * 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. + * 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. * * 1. Flags prefixed \c OptionProcess determine how the timestretcher * will be invoked. These options may not be changed after @@ -188,8 +186,6 @@ public: enum Option { - //!!! sort out this duplication - OptionProcessOffline = 0x00000000, OptionProcessRealTime = 0x00000001, @@ -223,7 +219,7 @@ public: enum PresetOption { DefaultOptions = 0x00000000, - PercussiveOptions = (OptionWindowShort | OptionPhaseIndependent) + PercussiveOptions = 0x00102000 }; /** @@ -238,22 +234,15 @@ public: size_t channels, Options options = DefaultOptions, double initialTimeRatio = 1.0, - double initialPitchScale = 1.0) : - r(rubberband_new(sampleRate, channels, options, - initialTimeRatio, initialPitchScale)) { } - - ~RubberBandStretcher() { - rubberband_delete(r); - } + double initialPitchScale = 1.0); + ~RubberBandStretcher(); /** * 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). */ - void reset() { - rubberband_reset(r); - } + void reset(); /** * Set the time ratio for the stretcher. This is the ratio of @@ -276,9 +265,7 @@ public: * mechanism to ensure that setTimeRatio and process() cannot be * run at once (there is no internal mutex for this purpose). */ - void setTimeRatio(double ratio) { - rubberband_set_time_ratio(r, ratio); - } + void setTimeRatio(double ratio); /** * Set the pitch scaling ratio for the stretcher. This is the @@ -305,25 +292,19 @@ public: * mechanism to ensure that setPitchScale and process() cannot be * run at once (there is no internal mutex for this purpose). */ - void setPitchScale(double scale) { - rubberband_set_pitch_scale(r, scale); - } + void setPitchScale(double scale); /** * Return the last time ratio value that was set (either on * construction or with setTimeRatio()). */ - double getTimeRatio() const { - return rubberband_get_time_ratio(r); - } + double getTimeRatio() const; /** * Return the last pitch scaling ratio value that was set (either * on construction or with setPitchScale()). */ - double getPitchScale() const { - return rubberband_get_pitch_scale(r); - } + double getPitchScale() const; /** * Return the processing latency of the stretcher. This is the @@ -334,9 +315,7 @@ public: * In RealTime mode, the latency may depend on the time and pitch * ratio and other options. */ - size_t getLatency() const { - return rubberband_get_latency(r); - } + size_t getLatency() const; /** * Change an OptionTransients configuration setting. This may be @@ -344,9 +323,7 @@ public: * Offline mode (for which the transients option is fixed on * construction). */ - void setTransientsOption(Options options) { - rubberband_set_transients_option(r, options); - } + void setTransientsOption(Options options); /** * Change an OptionPhase configuration setting. This may be @@ -356,9 +333,7 @@ public: * may not take effect immediately if processing is already under * way when this function is called. */ - void setPhaseOption(Options options) { - rubberband_set_phase_option(r, options); - } + void setPhaseOption(Options options); /** * Change an OptionFormant configuration setting. This may be @@ -368,9 +343,7 @@ public: * may not take effect immediately if processing is already under * way when this function is called. */ - void setFormantOption(Options options) { - rubberband_set_formant_option(r, options); - } + void setFormantOption(Options options); /** * Change an OptionPitch configuration setting. This may be @@ -378,9 +351,7 @@ public: * Offline mode (for which the transients option is fixed on * construction). */ - void setPitchOption(Options options) { - rubberband_set_pitch_option(r, options); - } + void setPitchOption(Options options); /** * Tell the stretcher exactly how many input samples it will @@ -389,9 +360,7 @@ public: * exactly correct. In RealTime mode no such guarantee is * possible and this value is ignored. */ - void setExpectedInputDuration(size_t samples) { - rubberband_set_expected_input_duration(r, samples); - } + void setExpectedInputDuration(size_t samples); /** * Ask the stretcher how many audio sample frames should be @@ -405,9 +374,7 @@ public: * study() (to which you may pass any number of samples at a time, * and from which there is no output). */ - size_t getSamplesRequired() const { - return rubberband_get_samples_required(r); - } + size_t getSamplesRequired() const; /** * Tell the stretcher the maximum number of sample frames that you @@ -424,9 +391,7 @@ public: * study() (to which you may pass any number of samples at a time, * and from which there is no output). */ - void setMaxProcessSize(size_t samples) { - rubberband_set_max_process_size(r, samples); - } + void setMaxProcessSize(size_t samples); /** * Provide a block of "samples" sample frames for the stretcher to @@ -445,9 +410,7 @@ public: * Set "final" to true if this is the last block of data that will * be provided to study() before the first process() call. */ - void study(const float *const *input, size_t samples, bool final) { - rubberband_study(r, input, samples, final); - } + void study(const float *const *input, size_t samples, bool final); /** * Provide a block of "samples" sample frames for processing. @@ -455,9 +418,7 @@ public: * * Set "final" to true if this is the last block of input data. */ - void process(const float *const *input, size_t samples, bool final) { - rubberband_process(r, input, samples, final); - } + void process(const float *const *input, size_t samples, bool final); /** * Ask the stretcher how many audio sample frames of output data @@ -472,9 +433,7 @@ public: * This function returns -1 if all data has been fully processed * and all output read, and the stretch process is now finished. */ - int available() const { - return rubberband_available(r); - } + int available() const; /** * Obtain some processed output data from the stretcher. Up to @@ -483,9 +442,7 @@ public: * The return value is the actual number of sample frames * retrieved. */ - size_t retrieve(float *const *output, size_t samples) const { - return rubberband_retrieve(r, output, samples); - } + size_t retrieve(float *const *output, size_t samples) const; /** * Return the value of internal frequency cutoff value n. @@ -544,9 +501,7 @@ public: * Return the number of channels this stretcher was constructed * with. */ - size_t getChannelCount() const { - return rubberband_get_channel_count(r); - } + size_t getChannelCount() const; /** * Force the stretcher to calculate a stretch profile. Normally @@ -555,9 +510,7 @@ public: * * This function is provided for diagnostic purposes only. */ - void calculateStretch() { - rubberband_calculate_stretch(r); - } + void calculateStretch(); /** * Set the level of debug output. The value may be from 0 (errors @@ -566,9 +519,7 @@ public: * using setDefaultDebugLevel, or 0 if that function has not been * called. */ - void setDebugLevel(int level) { - rubberband_set_debug_level(r, level); - } + void setDebugLevel(int level); /** * Set the default level of debug output for subsequently @@ -576,12 +527,11 @@ public: * * @see setDebugLevel */ - static void setDefaultDebugLevel(int level) { - rubberband_set_default_debug_level(level); - } + static void setDefaultDebugLevel(int level); protected: - RubberBandState r; + class Impl; + Impl *m_d; }; } diff --git a/rubberband/rubberband.h b/rubberband/rubberband-c.h similarity index 88% rename from rubberband/rubberband.h rename to rubberband/rubberband-c.h index 0d99b6c..bcf13f0 100644 --- a/rubberband/rubberband.h +++ b/rubberband/rubberband-c.h @@ -12,17 +12,28 @@ COPYING included with this distribution for more information. */ -#ifndef _RUBBERBAND_H_ -#define _RUBBERBAND_H_ +#ifndef _RUBBERBAND_C_API_H_ +#define _RUBBERBAND_C_API_H_ #ifdef __cplusplus extern "C" { #endif +/** + * This is a C-linkage interface to the Rubber Band time stretcher. + * + * This is a wrapper interface: the primary interface is in C++ and is + * defined and documented in RubberBandStretcher.h. The library + * itself is implemented in C++, and requires C++ standard library + * support even when using the C-linkage API. + * + * Please see RubberBandStretcher.h for documentation. + * + * If you are writing to the C++ API, do not include this header. + */ + enum RubberBandOption { - //!!! sort out this duplication - RubberBandOptionProcessOffline = 0x00000000, RubberBandOptionProcessRealTime = 0x00000001, @@ -59,7 +70,7 @@ typedef struct RubberBandState_ *RubberBandState; extern RubberBandState rubberband_new(unsigned int sampleRate, unsigned int channels, - RubberBandOptions options, //!!! sort out RubberBand namespacing + RubberBandOptions options, double initialTimeRatio, double initialPitchScale); diff --git a/src/RubberBandStretcher.cpp b/src/RubberBandStretcher.cpp index 8bc54e4..7e249c6 100644 --- a/src/RubberBandStretcher.cpp +++ b/src/RubberBandStretcher.cpp @@ -14,133 +14,187 @@ #include "StretcherImpl.h" -#include "rubberband.h" +namespace RubberBand { -struct RubberBandState_ -{ - RubberBand::StretcherImpl *m_impl; -}; -RubberBandState rubberband_new(unsigned int sampleRate, - unsigned int channels, - RubberBandOptions options, //!!! sort out RubberBand namespacing - double initialTimeRatio, - double initialPitchScale) +RubberBandStretcher::RubberBandStretcher(size_t sampleRate, + size_t channels, + Options options, + double initialTimeRatio, + double initialPitchScale) : + m_d(new Impl(sampleRate, channels, options, + initialTimeRatio, initialPitchScale)) { - RubberBandState_ *state = new RubberBandState_(); - state->m_impl = new RubberBand::StretcherImpl - (sampleRate, channels, options, - initialTimeRatio, initialPitchScale); - return state; } -void rubberband_delete(RubberBandState state) +RubberBandStretcher::~RubberBandStretcher() { - delete state->m_impl; - delete state; + delete m_d; } -void rubberband_reset(RubberBandState state) +void +RubberBandStretcher::reset() { - state->m_impl->reset(); + m_d->reset(); } -void rubberband_set_time_ratio(RubberBandState state, double ratio) +void +RubberBandStretcher::setTimeRatio(double ratio) { - state->m_impl->setTimeRatio(ratio); + m_d->setTimeRatio(ratio); } -void rubberband_set_pitch_scale(RubberBandState state, double scale) +void +RubberBandStretcher::setPitchScale(double scale) { - state->m_impl->setPitchScale(scale); + m_d->setPitchScale(scale); } -double rubberband_get_time_ratio(const RubberBandState state) +double +RubberBandStretcher::getTimeRatio() const { - return state->m_impl->getTimeRatio(); + return m_d->getTimeRatio(); } -double rubberband_get_pitch_scale(const RubberBandState state) +double +RubberBandStretcher::getPitchScale() const { - return state->m_impl->getPitchScale(); + return m_d->getPitchScale(); } -unsigned int rubberband_get_latency(const RubberBandState state) +size_t +RubberBandStretcher::getLatency() const { - return state->m_impl->getLatency(); + return m_d->getLatency(); } -void rubberband_set_transients_option(RubberBandState state, RubberBandOptions options) +void +RubberBandStretcher::setTransientsOption(Options options) { - state->m_impl->setTransientsOption(options); + m_d->setTransientsOption(options); } -void rubberband_set_phase_option(RubberBandState state, RubberBandOptions options) +void +RubberBandStretcher::setPhaseOption(Options options) { - state->m_impl->setPhaseOption(options); + m_d->setPhaseOption(options); } -void rubberband_set_formant_option(RubberBandState state, RubberBandOptions options) +void +RubberBandStretcher::setFormantOption(Options options) { - state->m_impl->setFormantOption(options); + m_d->setFormantOption(options); } -void rubberband_set_pitch_option(RubberBandState state, RubberBandOptions options) +void +RubberBandStretcher::setPitchOption(Options options) { - state->m_impl->setPitchOption(options); + m_d->setPitchOption(options); } -void rubberband_set_expected_input_duration(RubberBandState state, unsigned int samples) +void +RubberBandStretcher::setExpectedInputDuration(size_t samples) { - state->m_impl->setExpectedInputDuration(samples); + m_d->setExpectedInputDuration(samples); } -unsigned int rubberband_get_samples_required(const RubberBandState state) +void +RubberBandStretcher::setMaxProcessSize(size_t samples) { - return state->m_impl->getSamplesRequired(); + m_d->setMaxProcessSize(samples); } -void rubberband_set_max_process_size(RubberBandState state, unsigned int samples) +size_t +RubberBandStretcher::getSamplesRequired() const { - state->m_impl->setMaxProcessSize(samples); + return m_d->getSamplesRequired(); } -void rubberband_study(RubberBandState state, const float *const *input, unsigned int samples, int final) +void +RubberBandStretcher::study(const float *const *input, size_t samples, + bool final) { - state->m_impl->study(input, samples, final != 0); + m_d->study(input, samples, final); } -void rubberband_process(RubberBandState state, const float *const *input, unsigned int samples, int final) +void +RubberBandStretcher::process(const float *const *input, size_t samples, + bool final) { - state->m_impl->process(input, samples, final != 0); + m_d->process(input, samples, final); } -int rubberband_available(const RubberBandState state) +int +RubberBandStretcher::available() const { - return state->m_impl->available(); + return m_d->available(); } -unsigned int rubberband_retrieve(const RubberBandState state, float *const *output, unsigned int samples) +size_t +RubberBandStretcher::retrieve(float *const *output, size_t samples) const { - return state->m_impl->retrieve(output, samples); + return m_d->retrieve(output, samples); } -unsigned int rubberband_get_channel_count(const RubberBandState state) +float +RubberBandStretcher::getFrequencyCutoff(int n) const { - return state->m_impl->getChannelCount(); + return m_d->getFrequencyCutoff(n); } -void rubberband_calculate_stretch(RubberBandState state) +void +RubberBandStretcher::setFrequencyCutoff(int n, float f) { - state->m_impl->calculateStretch(); + m_d->setFrequencyCutoff(n, f); } -void rubberband_set_debug_level(RubberBandState state, int level) +size_t +RubberBandStretcher::getInputIncrement() const { - state->m_impl->setDebugLevel(level); + return m_d->getInputIncrement(); } -void rubberband_set_default_debug_level(int level) +std::vector +RubberBandStretcher::getOutputIncrements() const { - RubberBand::StretcherImpl::setDefaultDebugLevel(level); + return m_d->getOutputIncrements(); } + +std::vector +RubberBandStretcher::getPhaseResetCurve() const +{ + return m_d->getPhaseResetCurve(); +} + +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 a581adc..2a8fe40 100644 --- a/src/StretcherChannelData.cpp +++ b/src/StretcherChannelData.cpp @@ -20,7 +20,7 @@ namespace RubberBand { -StretcherImpl::ChannelData::ChannelData(size_t windowSize, +RubberBandStretcher::Impl::ChannelData::ChannelData(size_t windowSize, int overSample, size_t outbufSize) : oversample(overSample) @@ -29,7 +29,7 @@ StretcherImpl::ChannelData::ChannelData(size_t windowSize, construct(s, windowSize, outbufSize); } -StretcherImpl::ChannelData::ChannelData(const std::set &windowSizes, +RubberBandStretcher::Impl::ChannelData::ChannelData(const std::set &windowSizes, int overSample, size_t initialWindowSize, size_t outbufSize) : @@ -39,7 +39,7 @@ StretcherImpl::ChannelData::ChannelData(const std::set &windowSizes, } void -StretcherImpl::ChannelData::construct(const std::set &windowSizes, +RubberBandStretcher::Impl::ChannelData::construct(const std::set &windowSizes, size_t initialWindowSize, size_t outbufSize) { @@ -117,7 +117,7 @@ StretcherImpl::ChannelData::construct(const std::set &windowSizes, } void -StretcherImpl::ChannelData::setWindowSize(size_t windowSize) +RubberBandStretcher::Impl::ChannelData::setWindowSize(size_t windowSize) { size_t oldSize = inbuf->getSize(); size_t realSize = (windowSize * oversample) / 2 + 1; @@ -236,7 +236,7 @@ StretcherImpl::ChannelData::setWindowSize(size_t windowSize) } void -StretcherImpl::ChannelData::setOutbufSize(size_t outbufSize) +RubberBandStretcher::Impl::ChannelData::setOutbufSize(size_t outbufSize) { size_t oldSize = outbuf->getSize(); @@ -254,7 +254,7 @@ StretcherImpl::ChannelData::setOutbufSize(size_t outbufSize) } void -StretcherImpl::ChannelData::setResampleBufSize(size_t sz) +RubberBandStretcher::Impl::ChannelData::setResampleBufSize(size_t sz) { if (!resamplebuf) { resamplebuf = new float[sz]; @@ -268,7 +268,7 @@ StretcherImpl::ChannelData::setResampleBufSize(size_t sz) resamplebufSize = sz; } -StretcherImpl::ChannelData::~ChannelData() +RubberBandStretcher::Impl::ChannelData::~ChannelData() { delete resampler; @@ -296,7 +296,7 @@ StretcherImpl::ChannelData::~ChannelData() } void -StretcherImpl::ChannelData::reset() +RubberBandStretcher::Impl::ChannelData::reset() { inbuf->reset(); outbuf->reset(); diff --git a/src/StretcherChannelData.h b/src/StretcherChannelData.h index 5916970..5020568 100644 --- a/src/StretcherChannelData.h +++ b/src/StretcherChannelData.h @@ -26,7 +26,7 @@ namespace RubberBand class Resampler; -class StretcherImpl::ChannelData +class RubberBandStretcher::Impl::ChannelData { public: /** diff --git a/src/StretcherImpl.cpp b/src/StretcherImpl.cpp index 3af4af8..cca8c32 100644 --- a/src/StretcherImpl.cpp +++ b/src/StretcherImpl.cpp @@ -39,22 +39,21 @@ using std::min; namespace RubberBand { const size_t -StretcherImpl::m_defaultIncrement = 256; +RubberBandStretcher::Impl::m_defaultIncrement = 256; const size_t -StretcherImpl::m_defaultWindowSize = 2048; +RubberBandStretcher::Impl::m_defaultWindowSize = 2048; int -StretcherImpl::m_defaultDebugLevel = 0; +RubberBandStretcher::Impl::m_defaultDebugLevel = 0; -StretcherImpl::StretcherImpl(size_t sampleRate, - size_t channels, - //!!! sort out this crapness with Options namespace - RubberBandStretcher::Options options, - double initialTimeRatio, - double initialPitchScale) : +RubberBandStretcher::Impl::Impl(size_t sampleRate, + size_t channels, + Options options, + double initialTimeRatio, + double initialPitchScale) : m_sampleRate(sampleRate), m_channels(channels), m_timeRatio(initialTimeRatio), @@ -85,7 +84,7 @@ StretcherImpl::StretcherImpl(size_t sampleRate, { if (m_debugLevel > 0) { - cerr << "StretcherImpl::Impl: rate = " << m_sampleRate << ", options = " << options << endl; + cerr << "RubberBandStretcher::Impl::Impl: rate = " << m_sampleRate << ", options = " << options << endl; } // Window size will vary according to the audio sample rate, but @@ -94,15 +93,15 @@ StretcherImpl::StretcherImpl(size_t sampleRate, if (m_rateMultiple < 1.f) m_rateMultiple = 1.f; m_baseWindowSize = roundUp(int(m_defaultWindowSize * m_rateMultiple)); - 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) { + 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 & RubberBandStretcher::OptionWindowLong) { + } else if (options & OptionWindowLong) { m_baseWindowSize = m_baseWindowSize * 2; if (m_debugLevel > 0) { cerr << "setting baseWindowSize to " << m_baseWindowSize << endl; @@ -113,12 +112,12 @@ StretcherImpl::StretcherImpl(size_t sampleRate, m_maxProcessSize = m_baseWindowSize; } - if (m_options & RubberBandStretcher::OptionProcessRealTime) { + if (m_options & OptionProcessRealTime) { m_realtime = true; - if (!(m_options & RubberBandStretcher::OptionStretchPrecise)) { - m_options |= RubberBandStretcher::OptionStretchPrecise; + if (!(m_options & OptionStretchPrecise)) { + m_options |= OptionStretchPrecise; } } @@ -128,9 +127,9 @@ StretcherImpl::StretcherImpl(size_t sampleRate, if (m_realtime) { m_threaded = false; - } else if (m_options & RubberBandStretcher::OptionThreadingNever) { + } else if (m_options & OptionThreadingNever) { m_threaded = false; - } else if (!(m_options & RubberBandStretcher::OptionThreadingAlways) && + } else if (!(m_options & OptionThreadingAlways) && !system_is_multiprocessor()) { m_threaded = false; } @@ -143,7 +142,7 @@ StretcherImpl::StretcherImpl(size_t sampleRate, configure(); } -StretcherImpl::~StretcherImpl() +RubberBandStretcher::Impl::~Impl() { if (m_threaded) { MutexLocker locker(&m_threadSetMutex); @@ -174,7 +173,7 @@ StretcherImpl::~StretcherImpl() } void -StretcherImpl::reset() +RubberBandStretcher::Impl::reset() { if (m_threaded) { m_threadSetMutex.lock(); @@ -205,11 +204,11 @@ StretcherImpl::reset() } void -StretcherImpl::setTimeRatio(double ratio) +RubberBandStretcher::Impl::setTimeRatio(double ratio) { if (!m_realtime) { if (m_mode == Studying || m_mode == Processing) { - cerr << "StretcherImpl::setTimeRatio: Cannot set ratio while studying or processing in non-RT mode" << endl; + cerr << "RubberBandStretcher::Impl::setTimeRatio: Cannot set ratio while studying or processing in non-RT mode" << endl; return; } } @@ -221,11 +220,11 @@ StretcherImpl::setTimeRatio(double ratio) } void -StretcherImpl::setPitchScale(double fs) +RubberBandStretcher::Impl::setPitchScale(double fs) { if (!m_realtime) { if (m_mode == Studying || m_mode == Processing) { - cerr << "StretcherImpl::setPitchScale: Cannot set ratio while studying or processing in non-RT mode" << endl; + cerr << "RubberBandStretcher::Impl::setPitchScale: Cannot set ratio while studying or processing in non-RT mode" << endl; return; } } @@ -237,19 +236,19 @@ StretcherImpl::setPitchScale(double fs) } double -StretcherImpl::getTimeRatio() const +RubberBandStretcher::Impl::getTimeRatio() const { return m_timeRatio; } double -StretcherImpl::getPitchScale() const +RubberBandStretcher::Impl::getPitchScale() const { return m_pitchScale; } void -StretcherImpl::setExpectedInputDuration(size_t samples) +RubberBandStretcher::Impl::setExpectedInputDuration(size_t samples) { if (samples == m_expectedInputDuration) return; m_expectedInputDuration = samples; @@ -258,7 +257,7 @@ StretcherImpl::setExpectedInputDuration(size_t samples) } void -StretcherImpl::setMaxProcessSize(size_t samples) +RubberBandStretcher::Impl::setMaxProcessSize(size_t samples) { if (samples <= m_maxProcessSize) return; m_maxProcessSize = samples; @@ -267,7 +266,7 @@ StretcherImpl::setMaxProcessSize(size_t samples) } float -StretcherImpl::getFrequencyCutoff(int n) const +RubberBandStretcher::Impl::getFrequencyCutoff(int n) const { switch (n) { case 0: return m_freq0; @@ -278,7 +277,7 @@ StretcherImpl::getFrequencyCutoff(int n) const } void -StretcherImpl::setFrequencyCutoff(int n, float f) +RubberBandStretcher::Impl::setFrequencyCutoff(int n, float f) { switch (n) { case 0: m_freq0 = f; break; @@ -288,7 +287,7 @@ StretcherImpl::setFrequencyCutoff(int n, float f) } double -StretcherImpl::getEffectiveRatio() const +RubberBandStretcher::Impl::getEffectiveRatio() const { // Returns the ratio that the internal time stretcher needs to // achieve, not the resulting duration ratio of the output (which @@ -305,7 +304,7 @@ StretcherImpl::getEffectiveRatio() const } size_t -StretcherImpl::roundUp(size_t value) +RubberBandStretcher::Impl::roundUp(size_t value) { if (!(value & (value - 1))) return value; int bits = 0; @@ -315,7 +314,7 @@ StretcherImpl::roundUp(size_t value) } void -StretcherImpl::calculateSizes() +RubberBandStretcher::Impl::calculateSizes() { size_t inputIncrement = m_defaultIncrement; size_t windowSize = m_baseWindowSize; @@ -457,7 +456,7 @@ StretcherImpl::calculateSizes() } void -StretcherImpl::configure() +RubberBandStretcher::Impl::configure() { // std::cerr << "configure[" << this << "]: realtime = " << m_realtime << ", pitch scale = " // << m_pitchScale << ", channels = " << m_channels << std::endl; @@ -554,7 +553,7 @@ StretcherImpl::configure() if (!m_realtime) { delete m_stretchAudioCurve; - if (!(m_options & RubberBandStretcher::OptionStretchPrecise)) { + if (!(m_options & OptionStretchPrecise)) { m_stretchAudioCurve = new SpectralDifferenceAudioCurve (m_sampleRate, m_windowSize); } else { @@ -566,7 +565,7 @@ StretcherImpl::configure() delete m_stretchCalculator; m_stretchCalculator = new StretchCalculator (m_sampleRate, m_increment, - !(m_options & RubberBandStretcher::OptionTransientsSmooth)); + !(m_options & OptionTransientsSmooth)); m_stretchCalculator->setDebugLevel(m_debugLevel); m_inputDuration = 0; @@ -592,7 +591,7 @@ StretcherImpl::configure() void -StretcherImpl::reconfigure() +RubberBandStretcher::Impl::reconfigure() { if (!m_realtime) { if (m_mode == Studying) { @@ -659,57 +658,57 @@ StretcherImpl::reconfigure() } size_t -StretcherImpl::getLatency() const +RubberBandStretcher::Impl::getLatency() const { if (!m_realtime) return 0; return int((m_windowSize/2) / m_pitchScale + 1); } void -StretcherImpl::setTransientsOption(RubberBandStretcher::Options options) +RubberBandStretcher::Impl::setTransientsOption(Options options) { if (!m_realtime) { - cerr << "StretcherImpl::setTransientsOption: Not permissible in non-realtime mode" << endl; + cerr << "RubberBandStretcher::Impl::setTransientsOption: Not permissible in non-realtime mode" << endl; return; } - int mask = (RubberBandStretcher::OptionTransientsMixed | RubberBandStretcher::OptionTransientsSmooth | RubberBandStretcher::OptionTransientsCrisp); + int mask = (OptionTransientsMixed | OptionTransientsSmooth | OptionTransientsCrisp); m_options &= ~mask; options &= mask; m_options |= options; m_stretchCalculator->setUseHardPeaks - (!(m_options & RubberBandStretcher::OptionTransientsSmooth)); + (!(m_options & OptionTransientsSmooth)); } void -StretcherImpl::setPhaseOption(RubberBandStretcher::Options options) +RubberBandStretcher::Impl::setPhaseOption(Options options) { - int mask = (RubberBandStretcher::OptionPhaseAdaptive | RubberBandStretcher::OptionPhasePeakLocked | RubberBandStretcher::OptionPhaseIndependent); + int mask = (OptionPhaseAdaptive | OptionPhasePeakLocked | OptionPhaseIndependent); m_options &= ~mask; options &= mask; m_options |= options; } void -StretcherImpl::setFormantOption(RubberBandStretcher::Options options) +RubberBandStretcher::Impl::setFormantOption(Options options) { - int mask = (RubberBandStretcher::OptionFormantShifted | RubberBandStretcher::OptionFormantPreserved); + int mask = (OptionFormantShifted | OptionFormantPreserved); m_options &= ~mask; options &= mask; m_options |= options; } void -StretcherImpl::setPitchOption(RubberBandStretcher::Options options) +RubberBandStretcher::Impl::setPitchOption(Options options) { if (!m_realtime) { - cerr << "StretcherImpl::setPitchOption: Pitch option is not used in non-RT mode" << endl; + cerr << "RubberBandStretcher::Impl::setPitchOption: Pitch option is not used in non-RT mode" << endl; return; } - RubberBandStretcher::Options prior = m_options; + Options prior = m_options; - int mask = (RubberBandStretcher::OptionPitchHighQuality | RubberBandStretcher::OptionPitchHighSpeed); + int mask = (OptionPitchHighQuality | OptionPitchHighSpeed); m_options &= ~mask; options &= mask; m_options |= options; @@ -718,19 +717,19 @@ StretcherImpl::setPitchOption(RubberBandStretcher::Options options) } void -StretcherImpl::study(const float *const *input, size_t samples, bool final) +RubberBandStretcher::Impl::study(const float *const *input, size_t samples, bool final) { - Profiler profiler("StretcherImpl::study"); + Profiler profiler("RubberBandStretcher::Impl::study"); if (m_realtime) { if (m_debugLevel > 1) { - cerr << "StretcherImpl::study: Not meaningful in realtime mode" << endl; + cerr << "RubberBandStretcher::Impl::study: Not meaningful in realtime mode" << endl; } return; } if (m_mode == Processing || m_mode == Finished) { - cerr << "StretcherImpl::study: Cannot study after processing" << endl; + cerr << "RubberBandStretcher::Impl::study: Cannot study after processing" << endl; return; } m_mode = Studying; @@ -837,7 +836,7 @@ StretcherImpl::study(const float *const *input, size_t samples, bool final) } vector -StretcherImpl::getOutputIncrements() const +RubberBandStretcher::Impl::getOutputIncrements() const { if (!m_realtime) { return m_outputIncrements; @@ -851,7 +850,7 @@ StretcherImpl::getOutputIncrements() const } vector -StretcherImpl::getPhaseResetCurve() const +RubberBandStretcher::Impl::getPhaseResetCurve() const { if (!m_realtime) { return m_phaseResetDf; @@ -865,7 +864,7 @@ StretcherImpl::getPhaseResetCurve() const } vector -StretcherImpl::getExactTimePoints() const +RubberBandStretcher::Impl::getExactTimePoints() const { std::vector points; if (!m_realtime) { @@ -879,9 +878,9 @@ StretcherImpl::getExactTimePoints() const } void -StretcherImpl::calculateStretch() +RubberBandStretcher::Impl::calculateStretch() { - Profiler profiler("StretcherImpl::calculateStretch"); + Profiler profiler("RubberBandStretcher::Impl::calculateStretch"); std::vector increments = m_stretchCalculator->calculate (getEffectiveRatio(), @@ -900,16 +899,16 @@ StretcherImpl::calculateStretch() } void -StretcherImpl::setDebugLevel(int level) +RubberBandStretcher::Impl::setDebugLevel(int level) { m_debugLevel = level; if (m_stretchCalculator) m_stretchCalculator->setDebugLevel(level); } size_t -StretcherImpl::getSamplesRequired() const +RubberBandStretcher::Impl::getSamplesRequired() const { - Profiler profiler("StretcherImpl::getSamplesRequired"); + Profiler profiler("RubberBandStretcher::Impl::getSamplesRequired"); size_t reqd = 0; @@ -944,12 +943,12 @@ StretcherImpl::getSamplesRequired() const } void -StretcherImpl::process(const float *const *input, size_t samples, bool final) +RubberBandStretcher::Impl::process(const float *const *input, size_t samples, bool final) { - Profiler profiler("StretcherImpl::process"); + Profiler profiler("RubberBandStretcher::Impl::process"); if (m_mode == Finished) { - cerr << "StretcherImpl::process: Cannot process again after final chunk" << endl; + cerr << "RubberBandStretcher::Impl::process: Cannot process again after final chunk" << endl; return; } @@ -1045,7 +1044,7 @@ StretcherImpl::process(const float *const *input, size_t samples, bool final) /* } else { if (!allConsumed) { - cerr << "StretcherImpl::process: ERROR: Too much data provided to process() call -- either call setMaxProcessSize() beforehand, or provide only getSamplesRequired() frames at a time" << endl; + 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; } diff --git a/src/StretcherImpl.h b/src/StretcherImpl.h index d06b5c4..9601205 100644 --- a/src/StretcherImpl.h +++ b/src/StretcherImpl.h @@ -31,14 +31,12 @@ namespace RubberBand class AudioCurve; class StretchCalculator; -class StretcherImpl +class RubberBandStretcher::Impl { public: - typedef RubberBandStretcher::Options Options; - - StretcherImpl(size_t sampleRate, size_t channels, Options options, - double initialTimeRatio, double initialPitchScale); - ~StretcherImpl(); + Impl(size_t sampleRate, size_t channels, Options options, + double initialTimeRatio, double initialPitchScale); + ~Impl(); void reset(); void setTimeRatio(double ratio); @@ -149,12 +147,12 @@ protected: class ProcessThread : public Thread { public: - ProcessThread(StretcherImpl *s, size_t c); + ProcessThread(Impl *s, size_t c); void run(); void signalDataAvailable(); void abandon(); private: - StretcherImpl *m_s; + Impl *m_s; size_t m_channel; Condition m_dataAvailable; bool m_abandoning; diff --git a/src/StretcherProcess.cpp b/src/StretcherProcess.cpp index 986afd1..c848376 100644 --- a/src/StretcherProcess.cpp +++ b/src/StretcherProcess.cpp @@ -33,7 +33,7 @@ using std::endl; namespace RubberBand { -StretcherImpl::ProcessThread::ProcessThread(StretcherImpl *s, size_t c) : +RubberBandStretcher::Impl::ProcessThread::ProcessThread(Impl *s, size_t c) : m_s(s), m_channel(c), m_dataAvailable(std::string("data ") + char('A' + c)), @@ -41,7 +41,7 @@ StretcherImpl::ProcessThread::ProcessThread(StretcherImpl *s, size_t c) : { } void -StretcherImpl::ProcessThread::run() +RubberBandStretcher::Impl::ProcessThread::run() { if (m_s->m_debugLevel > 1) { cerr << "thread " << m_channel << " getting going" << endl; @@ -89,26 +89,26 @@ StretcherImpl::ProcessThread::run() } void -StretcherImpl::ProcessThread::signalDataAvailable() +RubberBandStretcher::Impl::ProcessThread::signalDataAvailable() { m_dataAvailable.signal(); } void -StretcherImpl::ProcessThread::abandon() +RubberBandStretcher::Impl::ProcessThread::abandon() { m_abandoning = true; } bool -StretcherImpl::resampleBeforeStretching() const +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 & RubberBandStretcher::OptionPitchHighQuality) { + if (m_options & OptionPitchHighQuality) { return (m_pitchScale < 1.0); // better sound } else { return (m_pitchScale > 1.0); // better performance @@ -116,10 +116,10 @@ StretcherImpl::resampleBeforeStretching() const } size_t -StretcherImpl::consumeChannel(size_t c, const float *input, +RubberBandStretcher::Impl::consumeChannel(size_t c, const float *input, size_t samples, bool final) { - Profiler profiler("StretcherImpl::consumeChannel"); + Profiler profiler("RubberBandStretcher::Impl::consumeChannel"); ChannelData &cd = *m_channelData[c]; RingBuffer &inbuf = *cd.inbuf; @@ -139,7 +139,7 @@ StretcherImpl::consumeChannel(size_t c, const float *input, size_t reqSize = int(ceil(samples / m_pitchScale)); if (reqSize > cd.resamplebufSize) { - cerr << "WARNING: StretcherImpl::consumeChannel: resizing resampler buffer from " + cerr << "WARNING: RubberBandStretcher::Impl::consumeChannel: resizing resampler buffer from " << cd.resamplebufSize << " to " << reqSize << endl; cd.setResampleBufSize(reqSize); } @@ -172,9 +172,9 @@ StretcherImpl::consumeChannel(size_t c, const float *input, } void -StretcherImpl::processChunks(size_t c, bool &any, bool &last) +RubberBandStretcher::Impl::processChunks(size_t c, bool &any, bool &last) { - Profiler profiler("StretcherImpl::processChunks"); + 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 @@ -214,9 +214,9 @@ StretcherImpl::processChunks(size_t c, bool &any, bool &last) } bool -StretcherImpl::processOneChunk() +RubberBandStretcher::Impl::processOneChunk() { - Profiler profiler("StretcherImpl::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 @@ -249,9 +249,9 @@ StretcherImpl::processOneChunk() } bool -StretcherImpl::testInbufReadSpace(size_t c) +RubberBandStretcher::Impl::testInbufReadSpace(size_t c) { - Profiler profiler("StretcherImpl::testInbufReadSpace"); + Profiler profiler("RubberBandStretcher::Impl::testInbufReadSpace"); ChannelData &cd = *m_channelData[c]; RingBuffer &inbuf = *cd.inbuf; @@ -298,12 +298,12 @@ StretcherImpl::testInbufReadSpace(size_t c) } bool -StretcherImpl::processChunkForChannel(size_t c, +RubberBandStretcher::Impl::processChunkForChannel(size_t c, size_t phaseIncrement, size_t shiftIncrement, bool phaseReset) { - Profiler profiler("StretcherImpl::processChunkForChannel"); + 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 @@ -393,11 +393,11 @@ StretcherImpl::processChunkForChannel(size_t c, } void -StretcherImpl::calculateIncrements(size_t &phaseIncrementRtn, +RubberBandStretcher::Impl::calculateIncrements(size_t &phaseIncrementRtn, size_t &shiftIncrementRtn, bool &phaseReset) { - Profiler profiler("StretcherImpl::calculateIncrements"); + Profiler profiler("RubberBandStretcher::Impl::calculateIncrements"); // cerr << "calculateIncrements" << endl; @@ -423,7 +423,7 @@ StretcherImpl::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: StretcherImpl::calculateIncrements: Channels are not in sync" << endl; + cerr << "ERROR: RubberBandStretcher::Impl::calculateIncrements: Channels are not in sync" << endl; return; } } @@ -498,12 +498,12 @@ StretcherImpl::calculateIncrements(size_t &phaseIncrementRtn, } bool -StretcherImpl::getIncrements(size_t channel, +RubberBandStretcher::Impl::getIncrements(size_t channel, size_t &phaseIncrementRtn, size_t &shiftIncrementRtn, bool &phaseReset) { - Profiler profiler("StretcherImpl::getIncrements"); + Profiler profiler("RubberBandStretcher::Impl::getIncrements"); if (channel >= m_channels) { phaseIncrementRtn = m_increment; @@ -532,7 +532,7 @@ StretcherImpl::getIncrements(size_t channel, bool gotData = true; if (cd.chunkCount >= m_outputIncrements.size()) { -// cerr << "WARNING: StretcherImpl::getIncrements:" +// cerr << "WARNING: RubberBandStretcher::Impl::getIncrements:" // << " chunk count " << cd.chunkCount << " >= " // << m_outputIncrements.size() << endl; if (m_outputIncrements.size() == 0) { @@ -563,7 +563,7 @@ StretcherImpl::getIncrements(size_t channel, } if (shiftIncrement >= int(m_windowSize)) { - cerr << "*** ERROR: StretcherImpl::processChunks: shiftIncrement " << shiftIncrement << " >= windowSize " << m_windowSize << " at " << cd.chunkCount << " (of " << m_outputIncrements.size() << ")" << endl; + cerr << "*** ERROR: RubberBandStretcher::Impl::processChunks: shiftIncrement " << shiftIncrement << " >= windowSize " << m_windowSize << " at " << cd.chunkCount << " (of " << m_outputIncrements.size() << ")" << endl; shiftIncrement = m_windowSize; } @@ -574,9 +574,9 @@ StretcherImpl::getIncrements(size_t channel, } void -StretcherImpl::analyseChunk(size_t channel) +RubberBandStretcher::Impl::analyseChunk(size_t channel) { - Profiler profiler("StretcherImpl::analyseChunk"); + Profiler profiler("RubberBandStretcher::Impl::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 -StretcherImpl::modifyChunk(size_t channel, size_t outputIncrement, +RubberBandStretcher::Impl::modifyChunk(size_t channel, size_t outputIncrement, bool phaseReset) { - Profiler profiler("StretcherImpl::modifyChunk"); + Profiler profiler("RubberBandStretcher::Impl::modifyChunk"); ChannelData &cd = *m_channelData[channel]; @@ -648,7 +648,7 @@ StretcherImpl::modifyChunk(size_t channel, size_t outputIncrement, bool unchanged = cd.unchanged && (outputIncrement == m_increment); bool fullReset = phaseReset; - if (!(m_options & RubberBandStretcher::OptionPhaseIndependent)) { + if (!(m_options & OptionPhaseIndependent)) { cd.freqPeak[0] = 0; @@ -664,7 +664,7 @@ StretcherImpl::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 & RubberBandStretcher::OptionPhasePeakLocked)) { + if (!(m_options & OptionPhasePeakLocked)) { float r = getEffectiveRatio(); if (r > 1) { float rf0 = 600 + (600 * ((r-1)*(r-1)*(r-1)*2)); @@ -744,7 +744,7 @@ StretcherImpl::modifyChunk(size_t channel, size_t outputIncrement, cd.freqPeak[count] = count; } - Profiler profiler2("StretcherImpl::modifyChunk part 2"); + Profiler profiler2("RubberBandStretcher::Impl::modifyChunk part 2"); double peakInPhase = 0.0; double peakOutPhase = 0.0; @@ -753,7 +753,7 @@ StretcherImpl::modifyChunk(size_t channel, size_t outputIncrement, for (int i = 0; i <= count; ++i) { - if (m_options & RubberBandStretcher::OptionPhaseIndependent) { + if (m_options & OptionPhaseIndependent) { p = i; pp = i-1; } else { @@ -763,7 +763,7 @@ StretcherImpl::modifyChunk(size_t channel, size_t outputIncrement, bool resetThis = phaseReset; - if (m_options & RubberBandStretcher::OptionTransientsMixed) { + if (m_options & OptionTransientsMixed) { int low = lrint((150 * sz * cd.oversample) / rate); int high = lrint((1000 * sz * cd.oversample) / rate); if (resetThis) { @@ -827,9 +827,9 @@ StretcherImpl::modifyChunk(size_t channel, size_t outputIncrement, void -StretcherImpl::formantShiftChunk(size_t channel) +RubberBandStretcher::Impl::formantShiftChunk(size_t channel) { - Profiler profiler("StretcherImpl::formantShiftChunk"); + Profiler profiler("RubberBandStretcher::Impl::formantShiftChunk"); ChannelData &cd = *m_channelData[channel]; @@ -893,12 +893,12 @@ StretcherImpl::formantShiftChunk(size_t channel) } void -StretcherImpl::synthesiseChunk(size_t channel) +RubberBandStretcher::Impl::synthesiseChunk(size_t channel) { - Profiler profiler("StretcherImpl::synthesiseChunk"); + Profiler profiler("RubberBandStretcher::Impl::synthesiseChunk"); - if ((m_options & RubberBandStretcher::OptionFormantPreserved) && + if ((m_options & OptionFormantPreserved) && (m_pitchScale != 1.0)) { formantShiftChunk(channel); } @@ -969,9 +969,9 @@ StretcherImpl::synthesiseChunk(size_t channel) } void -StretcherImpl::writeChunk(size_t channel, size_t shiftIncrement, bool last) +RubberBandStretcher::Impl::writeChunk(size_t channel, size_t shiftIncrement, bool last) { - Profiler profiler("StretcherImpl::writeChunk"); + Profiler profiler("RubberBandStretcher::Impl::writeChunk"); ChannelData &cd = *m_channelData[channel]; @@ -1011,7 +1011,7 @@ StretcherImpl::writeChunk(size_t channel, size_t shiftIncrement, bool last) // 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: StretcherImpl::writeChunk: resizing resampler buffer from " + cerr << "WARNING: RubberBandStretcher::Impl::writeChunk: resizing resampler buffer from " << cd.resamplebufSize << " to " << reqSize << endl; cd.setResampleBufSize(reqSize); } @@ -1054,7 +1054,7 @@ StretcherImpl::writeChunk(size_t channel, size_t shiftIncrement, bool last) cd.accumulatorFill = 0; if (cd.draining) { if (m_debugLevel > 1) { - cerr << "StretcherImpl::processChunks: setting outputComplete to true" << endl; + cerr << "RubberBandStretcher::Impl::processChunks: setting outputComplete to true" << endl; } cd.outputComplete = true; } @@ -1062,9 +1062,9 @@ StretcherImpl::writeChunk(size_t channel, size_t shiftIncrement, bool last) } void -StretcherImpl::writeOutput(RingBuffer &to, float *from, size_t qty, size_t &outCount, size_t theoreticalOut) +RubberBandStretcher::Impl::writeOutput(RingBuffer &to, float *from, size_t qty, size_t &outCount, size_t theoreticalOut) { - Profiler profiler("StretcherImpl::writeOutput"); + 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 @@ -1103,7 +1103,7 @@ StretcherImpl::writeOutput(RingBuffer &to, float *from, size_t qty, size_ size_t written = to.write(from, qty); if (written < qty) { - cerr << "WARNING: StretcherImpl::writeOutput: " + cerr << "WARNING: RubberBandStretcher::Impl::writeOutput: " << "Buffer overrun on output: wrote " << written << " of " << qty << " samples" << endl; } @@ -1136,9 +1136,9 @@ StretcherImpl::writeOutput(RingBuffer &to, float *from, size_t qty, size_ } int -StretcherImpl::available() const +RubberBandStretcher::Impl::available() const { - Profiler profiler("StretcherImpl::available"); + Profiler profiler("RubberBandStretcher::Impl::available"); if (m_threaded) { MutexLocker locker(&m_threadSetMutex); @@ -1156,7 +1156,7 @@ StretcherImpl::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; - ((StretcherImpl *)this)->processChunks(c, any, last); + ((RubberBandStretcher::Impl *)this)->processChunks(c, any, last); } } } @@ -1185,9 +1185,9 @@ StretcherImpl::available() const } size_t -StretcherImpl::retrieve(float *const *output, size_t samples) const +RubberBandStretcher::Impl::retrieve(float *const *output, size_t samples) const { - Profiler profiler("StretcherImpl::retrieve"); + Profiler profiler("RubberBandStretcher::Impl::retrieve"); size_t got = samples; @@ -1196,7 +1196,7 @@ StretcherImpl::retrieve(float *const *output, size_t samples) const if (gotHere < got) { if (c > 0) { if (m_debugLevel > 0) { - cerr << "StretcherImpl::retrieve: WARNING: channel imbalance detected" << endl; + cerr << "RubberBandStretcher::Impl::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 c149bbd..1ba0e03 100644 --- a/src/bsd-3rdparty/float_cast/float_cast.h +++ b/src/bsd-3rdparty/float_cast/float_cast.h @@ -37,8 +37,6 @@ #if (defined (WIN32) || defined (_WIN32)) -#ifndef MINGW32 - #include /* Win32 doesn't seem to have these functions. @@ -71,7 +69,5 @@ #endif -#endif - diff --git a/src/ladspa/RubberBandPitchShifter.cpp b/src/ladspa/RubberBandPitchShifter.cpp index 3be8dfd..4c41721 100644 --- a/src/ladspa/RubberBandPitchShifter.cpp +++ b/src/ladspa/RubberBandPitchShifter.cpp @@ -213,7 +213,9 @@ RubberBandPitchShifter::RubberBandPitchShifter(int sampleRate, size_t channels) 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_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_extraLatency(512), //!!! 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_extraLatency(128), //!!! 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, RubberBandStretcher::OptionProcessRealTime)), @@ -228,6 +230,16 @@ RubberBandPitchShifter::RubberBandPitchShifter(int sampleRate, size_t channels) m_outputBuffer[c]->zero(m_extraLatency); //!!! size must be at least max process size: m_scratch[c] = new float[16384];//!!! + for (int i = 0; i < 16384; ++i) { + m_scratch[c][i] = 0.f; + } + } + int reqd = m_stretcher->getSamplesRequired(); + m_stretcher->process(m_scratch, reqd, false); + int avail = m_stretcher->available(); + std::cerr << "construction: reqd = " << reqd << ", available = " << avail << std::endl; + if (avail > 0) { + m_stretcher->retrieve(m_scratch, avail); } } @@ -353,6 +365,8 @@ RubberBandPitchShifter::runImpl(unsigned long insamples) { // std::cerr << "RubberBandPitchShifter::runImpl(" << insamples << ")" << std::endl; + static int incount = 0, outcount = 0; + updateRatio(); if (m_ratio != m_prevRatio) { m_stretcher->setPitchScale(m_ratio); @@ -387,12 +401,14 @@ RubberBandPitchShifter::runImpl(unsigned long insamples) } m_stretcher->process(ptrs, inchunk, false); processed += inchunk; + incount += inchunk; //!!! int avail = m_stretcher->available(); int writable = m_outputBuffer[0]->getWriteSpace(); int outchunk = std::min(avail, writable); size_t actual = m_stretcher->retrieve(m_scratch, outchunk); outTotal += actual; + outcount += actual; // std::cout << ", avail: " << avail << ", outchunk = " << outchunk; // if (actual != outchunk) std::cout << " (" << actual << ")"; @@ -408,6 +424,8 @@ RubberBandPitchShifter::runImpl(unsigned long insamples) } } + std::cout << "in: " << incount << ", out: " << outcount << ", loss: " << incount - outcount << std::endl; + // std::cout << "processed = " << processed << " in, " << outTotal << " out" << ", fill = " << m_outputBuffer[0]->getReadSpace() << " of " << m_outputBuffer[0]->getSize() << std::endl; for (size_t c = 0; c < m_channels; ++c) { diff --git a/src/ladspa/ladspa-rubberband.rdf b/src/ladspa/ladspa-rubberband.rdf new file mode 100644 index 0000000..c2df663 --- /dev/null +++ b/src/ladspa/ladspa-rubberband.rdf @@ -0,0 +1,12 @@ + + + + +]> + + + + + + diff --git a/src/rubberband-c.cpp b/src/rubberband-c.cpp new file mode 100644 index 0000000..7bdd701 --- /dev/null +++ b/src/rubberband-c.cpp @@ -0,0 +1,146 @@ +/* -*- 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); +} +