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@14: #ifndef _PHASE_VOCODER_TIME_STRETCHER_H_ Chris@14: #define _PHASE_VOCODER_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@14: * A time stretcher that alters the performance speed of audio, Chris@14: * preserving pitch. This uses the simple phase vocoder technique Chris@14: * from DAFX pp275-276, adding a block-based 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@14: class PhaseVocoderTimeStretcher Chris@0: { Chris@0: public: Chris@15: PhaseVocoderTimeStretcher(float ratio, size_t maxProcessInputBlockSize); Chris@14: virtual ~PhaseVocoderTimeStretcher(); Chris@0: Chris@12: /** Chris@12: * Process a block. The input array contains the given number of Chris@15: * samples; the output must have space for lrintf(samples * m_ratio). Chris@12: */ Chris@0: void process(float *input, float *output, size_t samples); Chris@0: Chris@0: /** Chris@15: * Get the hop size for input. Chris@0: */ Chris@0: size_t getInputIncrement() const { return m_n1; } Chris@0: Chris@0: /** Chris@15: * Get the hop size for output. Chris@15: */ Chris@15: size_t getOutputIncrement() const { return getInputIncrement() * getRatio(); } Chris@15: Chris@15: /** Chris@15: * Get the window size for FFT processing. Chris@0: */ Chris@0: size_t getWindowSize() const { return m_wlen; } Chris@0: Chris@0: /** Chris@15: * Get the window type. Chris@0: */ Chris@0: WindowType getWindowType() const { return m_window->getType(); } Chris@0: Chris@15: /** Chris@15: * Get the stretch ratio set in the constructor. Chris@15: */ Chris@12: float getRatio() const { return m_ratio; } Chris@15: Chris@15: /** Chris@15: * Get the latency added by the time stretcher, in sample frames. Chris@15: */ Chris@0: size_t getProcessingLatency() const; Chris@0: Chris@0: protected: Chris@13: /** Chris@13: * Process a single phase vocoder frame. Chris@13: * Chris@13: * Take m_wlen time-domain source samples from in, perform an FFT, Chris@13: * phase shift, and IFFT, and add the results to out (presumably Chris@13: * overlapping parts of existing data from prior frames). Chris@13: * Chris@13: * Also add to the modulation output the results of windowing a Chris@13: * set of 1s with the resynthesis window -- this can then be used Chris@13: * to ensure the output has the correct magnitude in cases where Chris@13: * the window overlap varies or otherwise results in something Chris@13: * other than a flat sum. Chris@13: */ Chris@13: void processBlock(float *in, float *out, float *modulation); 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@15: RingBuffer *m_inbuf; Chris@15: RingBuffer *m_outbuf; Chris@0: float *m_mashbuf; Chris@13: float *m_modulationbuf; Chris@0: }; Chris@0: Chris@0: #endif