Chris@0: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@0: Chris@0: /* Chris@0: Sonic Visualiser Chris@0: An audio file viewer and annotation editor. Chris@0: Centre for Digital Music, Queen Mary, University of London. Chris@0: This file copyright 2006 Chris Cannam. Chris@0: Chris@0: This program is free software; you can redistribute it and/or Chris@0: modify it under the terms of the GNU General Public License as Chris@0: published by the Free Software Foundation; either version 2 of the Chris@0: License, or (at your option) any later version. See the file Chris@0: COPYING included with this distribution for more information. Chris@0: */ Chris@0: Chris@0: #ifndef _INTEGER_TIME_STRETCHER_H_ Chris@0: #define _INTEGER_TIME_STRETCHER_H_ Chris@0: Chris@0: #include "base/Window.h" Chris@0: #include "base/RingBuffer.h" Chris@0: Chris@0: #include Chris@0: Chris@0: /** Chris@0: * A time stretcher that slows down audio by an integer multiple of Chris@0: * its original duration, preserving pitch. This uses the simple Chris@0: * phase vocoder technique from DAFX pp275-276, adding a block-based Chris@0: * stream oriented API. Chris@0: * Chris@0: * Causes significant transient smearing, but sounds good for steady Chris@0: * notes and is generally predictable. Chris@0: */ Chris@0: Chris@0: class IntegerTimeStretcher Chris@0: { Chris@0: public: Chris@12: IntegerTimeStretcher(float ratio, Chris@0: size_t maxProcessInputBlockSize, Chris@0: size_t inputIncrement = 64, Chris@0: size_t windowSize = 2048, Chris@0: WindowType windowType = HanningWindow); Chris@0: virtual ~IntegerTimeStretcher(); Chris@0: Chris@12: /** Chris@12: * Process a block. The input array contains the given number of Chris@12: * samples; the output has enough space for samples * m_ratio. Chris@12: */ Chris@0: void process(float *input, float *output, size_t samples); Chris@0: Chris@0: /** Chris@0: * Get the hop size for input. Smaller values may produce better Chris@0: * results, at a cost in processing time. Larger values are Chris@0: * faster but increase the likelihood of echo-like effects. The Chris@0: * default is 64, which is usually pretty good, though heavy on Chris@0: * processor power. Chris@0: */ Chris@0: size_t getInputIncrement() const { return m_n1; } Chris@0: Chris@0: /** Chris@0: * Get the window size for FFT processing. Must be larger than Chris@0: * the input and output increments. The default is 2048. Chris@0: */ Chris@0: size_t getWindowSize() const { return m_wlen; } Chris@0: Chris@0: /** Chris@0: * Get the window type. The default is a Hanning window. Chris@0: */ Chris@0: WindowType getWindowType() const { return m_window->getType(); } Chris@0: Chris@12: float getRatio() const { return m_ratio; } Chris@0: size_t getOutputIncrement() const { return getInputIncrement() * getRatio(); } Chris@0: size_t getProcessingLatency() const; Chris@0: Chris@0: protected: Chris@0: void processBlock(float *in, float *out); Chris@0: Chris@12: float m_ratio; Chris@0: size_t m_n1; Chris@0: size_t m_n2; Chris@0: size_t m_wlen; Chris@0: Window *m_window; Chris@0: Chris@0: fftwf_complex *m_time; Chris@0: fftwf_complex *m_freq; Chris@0: float *m_dbuf; Chris@12: float *m_prevPhase; Chris@12: float *m_prevAdjustedPhase; Chris@0: Chris@0: fftwf_plan m_plan; Chris@0: fftwf_plan m_iplan; Chris@0: Chris@0: RingBuffer m_inbuf; Chris@0: RingBuffer m_outbuf; Chris@0: float *m_mashbuf; Chris@0: }; Chris@0: Chris@0: #endif