/* -*- 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 Chris Cannam. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. See the file COPYING included with this distribution for more information. */ #ifndef _RUBBERBAND_STRETCHERIMPL_H_ #define _RUBBERBAND_STRETCHERIMPL_H_ #include "RubberBandStretcher.h" #include "Window.h" #include "Thread.h" #include "RingBuffer.h" #include "FFT.h" #include "sysutils.h" #include namespace RubberBand { class AudioCurve; class StretchCalculator; class RubberBandStretcher::Impl { public: Impl(RubberBandStretcher *stretcher, size_t sampleRate, size_t channels, Options options, double initialTimeRatio, double initialPitchScale); ~Impl(); void reset(); void setTimeRatio(double ratio); void setPitchScale(double scale); double getTimeRatio() const; double getPitchScale() const; size_t getLatency() const; void setTransientsOption(Options); void setPhaseOption(Options); void setExpectedInputDuration(size_t samples); void setMaxProcessBlockSize(size_t samples); size_t getSamplesRequired() const; void study(const float *const *input, size_t samples, bool final); void process(const float *const *input, size_t samples, bool final); int available() const; size_t retrieve(float *const *output, size_t samples) const; float getFrequencyCutoff(int n) const; void setFrequencyCutoff(int n, float f); size_t getInputIncrement() const { return m_increment; } std::vector getOutputIncrements() const; std::vector getLockCurve() const; size_t getChannelCount() const { return m_channels; } void calculateStretch(); void setDebugLevel(int level); protected: RubberBandStretcher *m_stretcher; size_t m_channels; size_t consumeChannel(size_t channel, const float *input, size_t samples); bool processChunks(size_t channel); // returns "last" bool processOneChunk(); // across all channels, for real time use bool processChunkForChannel(size_t channel, size_t phaseIncrement, size_t shiftIncrement, bool lock); bool testInbufReadSpace(size_t channel); void calculateIncrements(size_t &phaseIncrement, size_t &shiftIncrement, bool &lock); bool getIncrements(size_t channel, size_t &phaseIncrement, size_t &shiftIncrement, bool &lock); void analyseChunk(size_t channel); void modifyChunk(size_t channel, size_t outputIncrement, bool lock); void synthesiseChunk(size_t channel); void writeChunk(size_t channel, size_t shiftIncrement, bool last); void calculateSizes(); void configure(); void reconfigure(); double getEffectiveRatio() const; size_t roundUp(size_t value); // to next power of two double m_timeRatio; double m_pitchScale; size_t m_blockSize; size_t m_outbufSize; size_t m_increment; size_t m_maxProcessBlockSize; size_t m_expectedInputDuration; bool m_threaded; bool m_realtime; Options m_options; int m_debugLevel; enum ProcessMode { JustCreated, Studying, Processing, Finished }; ProcessMode m_mode; std::map *> m_windows; Window *m_window; FFT *m_studyFFT; Condition m_dataAvailable; Condition m_spaceAvailable; class ProcessThread : public Thread { public: ProcessThread(Impl *s, size_t c) : m_s(s), m_channel(c) { } void run(); private: Impl *m_s; size_t m_channel; }; mutable Mutex m_threadSetMutex; std::set m_threadSet; size_t m_inputDuration; std::vector m_lockDf; std::vector m_stretchDf; class ChannelData; std::vector m_channelData; std::vector m_outputIncrements; mutable RingBuffer m_lastProcessOutputIncrements; mutable RingBuffer m_lastProcessLockDf; AudioCurve *m_lockAudioCurve; AudioCurve *m_stretchAudioCurve; StretchCalculator *m_stretchCalculator; float m_freq0; float m_freq1; float m_freq2; size_t m_baseBlockSize; void writeOutput(RingBuffer &to, float *from, size_t qty, size_t &outCount, size_t theoreticalOut); }; } #endif