* C API version

This commit is contained in:
Chris Cannam
2008-06-09 20:46:37 +00:00
parent 1a9f2f6c98
commit 160143461d
15 changed files with 444 additions and 372 deletions

View File

@@ -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

View File

@@ -15,29 +15,28 @@
#ifndef _RUBBERBANDSTRETCHER_H_
#define _RUBBERBANDSTRETCHER_H_
#include "TimeStretcher.h"
#include "rubberband.h"
#include <vector>
/**
* @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<int> getOutputIncrements() const;
std::vector<int> 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<float> getPhaseResetCurve() const;
std::vector<float> 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<int> getExactTimePoints() const;
std::vector<int> 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;
};
}

View File

@@ -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 <sys/types.h>
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

106
rubberband/rubberband.h Normal file
View File

@@ -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

View File

@@ -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

View File

@@ -76,7 +76,7 @@ protected:
class Profiler
{
public:
Profiler(const char *, bool = false) { }
Profiler(const char *) { }
~Profiler() { }
void update() const { }

View File

@@ -14,188 +14,133 @@
#include "StretcherImpl.h"
namespace RubberBand {
#include "rubberband.h"
struct RubberBandState_
{
RubberBand::StretcherImpl *m_impl;
};
RubberBandStretcher::RubberBandStretcher(size_t sampleRate,
size_t channels,
Options options,
RubberBandState rubberband_new(unsigned int sampleRate,
unsigned int channels,
RubberBandOptions options, //!!! sort out RubberBand namespacing
double initialTimeRatio,
double initialPitchScale) :
TimeStretcher(sampleRate, channels),
m_d(new Impl(this, sampleRate, channels, options,
initialTimeRatio, initialPitchScale))
double initialPitchScale)
{
RubberBandState_ *state = new RubberBandState_();
state->m_impl = new RubberBand::StretcherImpl
(sampleRate, channels, options,
initialTimeRatio, initialPitchScale);
return state;
}
RubberBandStretcher::~RubberBandStretcher()
void rubberband_delete(RubberBandState state)
{
delete m_d;
delete state->m_impl;
delete state;
}
void
RubberBandStretcher::reset()
void rubberband_reset(RubberBandState state)
{
m_d->reset();
state->m_impl->reset();
}
void
RubberBandStretcher::setTimeRatio(double ratio)
void rubberband_set_time_ratio(RubberBandState state, double ratio)
{
m_d->setTimeRatio(ratio);
state->m_impl->setTimeRatio(ratio);
}
void
RubberBandStretcher::setPitchScale(double scale)
void rubberband_set_pitch_scale(RubberBandState state, double scale)
{
m_d->setPitchScale(scale);
state->m_impl->setPitchScale(scale);
}
double
RubberBandStretcher::getTimeRatio() const
double rubberband_get_time_ratio(const RubberBandState state)
{
return m_d->getTimeRatio();
return state->m_impl->getTimeRatio();
}
double
RubberBandStretcher::getPitchScale() const
double rubberband_get_pitch_scale(const RubberBandState state)
{
return m_d->getPitchScale();
return state->m_impl->getPitchScale();
}
size_t
RubberBandStretcher::getLatency() const
unsigned int rubberband_get_latency(const RubberBandState state)
{
return m_d->getLatency();
return state->m_impl->getLatency();
}
void
RubberBandStretcher::setTransientsOption(Options options)
void rubberband_set_transients_option(RubberBandState state, RubberBandOptions options)
{
m_d->setTransientsOption(options);
state->m_impl->setTransientsOption(options);
}
void
RubberBandStretcher::setPhaseOption(Options options)
void rubberband_set_phase_option(RubberBandState state, RubberBandOptions options)
{
m_d->setPhaseOption(options);
state->m_impl->setPhaseOption(options);
}
void
RubberBandStretcher::setFormantOption(Options options)
void rubberband_set_formant_option(RubberBandState state, RubberBandOptions options)
{
m_d->setFormantOption(options);
state->m_impl->setFormantOption(options);
}
void
RubberBandStretcher::setPitchOption(Options options)
void rubberband_set_pitch_option(RubberBandState state, RubberBandOptions options)
{
m_d->setPitchOption(options);
state->m_impl->setPitchOption(options);
}
void
RubberBandStretcher::setExpectedInputDuration(size_t samples)
void rubberband_set_expected_input_duration(RubberBandState state, unsigned int samples)
{
m_d->setExpectedInputDuration(samples);
state->m_impl->setExpectedInputDuration(samples);
}
void
RubberBandStretcher::setMaxProcessSize(size_t samples)
unsigned int rubberband_get_samples_required(const RubberBandState state)
{
m_d->setMaxProcessSize(samples);
return state->m_impl->getSamplesRequired();
}
size_t
RubberBandStretcher::getSamplesRequired() const
void rubberband_set_max_process_size(RubberBandState state, unsigned int samples)
{
return m_d->getSamplesRequired();
state->m_impl->setMaxProcessSize(samples);
}
void
RubberBandStretcher::study(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->study(input, samples, final);
state->m_impl->study(input, samples, final != 0);
}
void
RubberBandStretcher::process(const float *const *input, size_t samples,
bool final)
void rubberband_process(RubberBandState state, const float *const *input, unsigned int samples, int final)
{
m_d->process(input, samples, final);
state->m_impl->process(input, samples, final != 0);
}
int
RubberBandStretcher::available() const
int rubberband_available(const RubberBandState state)
{
return m_d->available();
return state->m_impl->available();
}
size_t
RubberBandStretcher::retrieve(float *const *output, size_t samples) const
unsigned int rubberband_retrieve(const RubberBandState state, float *const *output, unsigned int samples)
{
return m_d->retrieve(output, samples);
return state->m_impl->retrieve(output, samples);
}
float
RubberBandStretcher::getFrequencyCutoff(int n) const
unsigned int rubberband_get_channel_count(const RubberBandState state)
{
return m_d->getFrequencyCutoff(n);
return state->m_impl->getChannelCount();
}
void
RubberBandStretcher::setFrequencyCutoff(int n, float f)
void rubberband_calculate_stretch(RubberBandState state)
{
m_d->setFrequencyCutoff(n, f);
state->m_impl->calculateStretch();
}
size_t
RubberBandStretcher::getInputIncrement() const
void rubberband_set_debug_level(RubberBandState state, int level)
{
return m_d->getInputIncrement();
state->m_impl->setDebugLevel(level);
}
std::vector<int>
RubberBandStretcher::getOutputIncrements() const
void rubberband_set_default_debug_level(int level)
{
return m_d->getOutputIncrements();
RubberBand::StretcherImpl::setDefaultDebugLevel(level);
}
std::vector<float>
RubberBandStretcher::getPhaseResetCurve() const
{
return m_d->getPhaseResetCurve();
}
std::vector<int>
RubberBandStretcher::getExactTimePoints() const
{
return m_d->getExactTimePoints();
}
size_t
RubberBandStretcher::getChannelCount() const
{
return m_d->getChannelCount();
}
void
RubberBandStretcher::calculateStretch()
{
m_d->calculateStretch();
}
void
RubberBandStretcher::setDebugLevel(int level)
{
m_d->setDebugLevel(level);
}
void
RubberBandStretcher::setDefaultDebugLevel(int level)
{
Impl::setDefaultDebugLevel(level);
}
}

View File

@@ -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<size_t> &windowSizes,
StretcherImpl::ChannelData::ChannelData(const std::set<size_t> &windowSizes,
int overSample,
size_t initialWindowSize,
size_t outbufSize) :
@@ -39,7 +39,7 @@ RubberBandStretcher::Impl::ChannelData::ChannelData(const std::set<size_t> &wind
}
void
RubberBandStretcher::Impl::ChannelData::construct(const std::set<size_t> &windowSizes,
StretcherImpl::ChannelData::construct(const std::set<size_t> &windowSizes,
size_t initialWindowSize,
size_t outbufSize)
{
@@ -117,7 +117,7 @@ RubberBandStretcher::Impl::ChannelData::construct(const std::set<size_t> &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();

View File

@@ -26,7 +26,7 @@ namespace RubberBand
class Resampler;
class RubberBandStretcher::Impl::ChannelData
class StretcherImpl::ChannelData
{
public:
/**

View File

@@ -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,
StretcherImpl::StretcherImpl(size_t sampleRate,
size_t channels,
Options options,
//!!! sort out this crapness with Options namespace
RubberBandStretcher::Options options,
double initialTimeRatio,
double initialPitchScale) :
m_stretcher(stretcher),
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<int>
RubberBandStretcher::Impl::getOutputIncrements() const
StretcherImpl::getOutputIncrements() const
{
if (!m_realtime) {
return m_outputIncrements;
@@ -851,7 +851,7 @@ RubberBandStretcher::Impl::getOutputIncrements() const
}
vector<float>
RubberBandStretcher::Impl::getPhaseResetCurve() const
StretcherImpl::getPhaseResetCurve() const
{
if (!m_realtime) {
return m_phaseResetDf;
@@ -865,7 +865,7 @@ RubberBandStretcher::Impl::getPhaseResetCurve() const
}
vector<int>
RubberBandStretcher::Impl::getExactTimePoints() const
StretcherImpl::getExactTimePoints() const
{
std::vector<int> 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<int> 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;
}

View File

@@ -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,
typedef RubberBandStretcher::Options Options;
StretcherImpl(size_t sampleRate, size_t channels, Options options,
double initialTimeRatio, double initialPitchScale);
~Impl();
~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;

View File

@@ -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<float> &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<float> &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<float> &to, float *from, size_t qty, size_t &outCount, size_t theoreticalOut)
StretcherImpl::writeOutput(RingBuffer<float> &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<float> &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<float> &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;

View File

@@ -37,6 +37,8 @@
#if (defined (WIN32) || defined (_WIN32))
#ifndef MINGW32
#include <math.h>
/* Win32 doesn't seem to have these functions.
@@ -69,5 +71,7 @@
#endif
#endif

View File

@@ -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;

View File

@@ -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;