andrewm@0: /* andrewm@0: This code accompanies the textbook: andrewm@0: andrewm@0: Digital Audio Effects: Theory, Implementation and Application andrewm@0: Joshua D. Reiss and Andrew P. McPherson andrewm@0: andrewm@0: --- andrewm@0: andrewm@0: PVOC Passthrough: phase vocoder structure which passes input andrewm@0: to output without performing any processing andrewm@0: andrewm@0: See textbook Chapter 8: The Phase Vocoder andrewm@0: andrewm@0: Code by Andrew McPherson, Brecht De Man and Joshua Reiss andrewm@0: andrewm@0: This code requires the fftw library version 3 to compile: andrewm@0: http://fftw.org andrewm@0: andrewm@0: --- andrewm@0: andrewm@0: This program is free software: you can redistribute it and/or modify andrewm@0: it under the terms of the GNU General Public License as published by andrewm@0: the Free Software Foundation, either version 3 of the License, or andrewm@0: (at your option) any later version. andrewm@0: andrewm@0: This program is distributed in the hope that it will be useful, andrewm@0: but WITHOUT ANY WARRANTY; without even the implied warranty of andrewm@0: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the andrewm@0: GNU General Public License for more details. andrewm@0: andrewm@0: You should have received a copy of the GNU General Public License andrewm@0: along with this program. If not, see . andrewm@0: */ andrewm@0: andrewm@0: #ifndef __PLUGINPROCESSOR_H_4693CB6E__ andrewm@0: #define __PLUGINPROCESSOR_H_4693CB6E__ andrewm@0: andrewm@0: #include "../JuceLibraryCode/JuceHeader.h" andrewm@0: #include andrewm@0: andrewm@0: //============================================================================== andrewm@0: /** andrewm@0: */ andrewm@0: class PVOCPassthroughAudioProcessor : public AudioProcessor andrewm@0: { andrewm@0: public: andrewm@0: //============================================================================== andrewm@0: PVOCPassthroughAudioProcessor(); andrewm@0: ~PVOCPassthroughAudioProcessor(); andrewm@0: andrewm@0: //============================================================================== andrewm@0: void prepareToPlay (double sampleRate, int samplesPerBlock); andrewm@0: void releaseResources(); andrewm@0: andrewm@0: void processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages); andrewm@0: andrewm@0: //============================================================================== andrewm@0: AudioProcessorEditor* createEditor(); andrewm@0: bool hasEditor() const; andrewm@0: andrewm@0: //============================================================================== andrewm@0: const String getName() const; andrewm@0: andrewm@0: int getNumParameters(); andrewm@0: andrewm@0: float getParameter (int index); andrewm@0: void setParameter (int index, float newValue); andrewm@0: andrewm@0: const String getParameterName (int index); andrewm@0: const String getParameterText (int index); andrewm@0: andrewm@0: const String getInputChannelName (int channelIndex) const; andrewm@0: const String getOutputChannelName (int channelIndex) const; andrewm@0: bool isInputChannelStereoPair (int index) const; andrewm@0: bool isOutputChannelStereoPair (int index) const; andrewm@0: andrewm@0: bool silenceInProducesSilenceOut() const; andrewm@0: double getTailLengthSeconds() const; andrewm@0: bool acceptsMidi() const; andrewm@0: bool producesMidi() const; andrewm@0: andrewm@0: //============================================================================== andrewm@0: int getNumPrograms(); andrewm@0: int getCurrentProgram(); andrewm@0: void setCurrentProgram (int index); andrewm@0: const String getProgramName (int index); andrewm@0: void changeProgramName (int index, const String& newName); andrewm@0: andrewm@0: //============================================================================== andrewm@0: void getStateInformation (MemoryBlock& destData); andrewm@0: void setStateInformation (const void* data, int sizeInBytes); andrewm@0: andrewm@0: //============================================================================== andrewm@0: andrewm@0: // these are used to persist the UI's size - the values are stored along with the andrewm@0: // filter's other parameters, and the UI component will update them when it gets andrewm@0: // resized. andrewm@0: int lastUIWidth_, lastUIHeight_; andrewm@0: andrewm@0: enum Parameters andrewm@0: { andrewm@0: kFFTSizeParam = 0, andrewm@0: kHopSizeParam, andrewm@0: kWindowTypeParam, andrewm@0: kNumParameters andrewm@0: }; andrewm@0: andrewm@0: enum Window andrewm@0: { andrewm@0: kWindowRectangular = 1, andrewm@0: kWindowBartlett, andrewm@0: kWindowHann, andrewm@0: kWindowHamming andrewm@0: }; andrewm@0: andrewm@0: enum HopSize andrewm@0: { andrewm@0: kHopSize1Window = 1, andrewm@0: kHopSize1_2Window, andrewm@0: kHopSize1_4Window, andrewm@0: kHopSize1_8Window andrewm@0: }; andrewm@0: andrewm@0: // This parameter indicates the FFT size for phase vocoder computation. It is selected andrewm@0: // by the GUI and may temporarily differ from the actual size used in calculations. andrewm@0: int fftSelectedSize_; andrewm@0: int hopSelectedSize_; // Hop size, chosen from one of the options above andrewm@0: int windowType_; // Type of window used andrewm@0: andrewm@0: private: andrewm@0: // Methods to initialise and de-initialise the FFT machinery andrewm@0: void initFFT(int length); andrewm@0: void deinitFFT(); andrewm@0: andrewm@0: // Methods to initialise and de-initialise the window andrewm@0: void initWindow(int length, int windowType); andrewm@0: void deinitWindow(); andrewm@0: andrewm@0: // Methods to update the buffering for the given hop size and the output scaling andrewm@0: void updateHopSize(); andrewm@0: void updateScaleFactor(); andrewm@0: andrewm@0: // Whether the FFT has been initialised and is therefore ready to go andrewm@0: bool fftInitialised_; andrewm@0: andrewm@0: // Variables for calculating the FFT and IFFT: complex data structures and the andrewm@0: // "plan" used by the fftw library to calculate the transforms. andrewm@0: fftw_complex *fftTimeDomain_, *fftFrequencyDomain_; andrewm@0: fftw_plan fftForwardPlan_, fftBackwardPlan_; andrewm@0: andrewm@0: // Size of the FFT (generally a power of two) and the hop size (in samples, generally a fraction of FFT size) andrewm@0: int fftActualTransformSize_; andrewm@0: int hopActualSize_; andrewm@0: andrewm@0: // Amount by which to scale the inverse FFT to return to original amplitude: depends on the andrewm@0: // transform size (because of fftw implementation) and the hop size (because of inherent overlap) andrewm@0: double fftScaleFactor_; andrewm@0: andrewm@0: // Circular buffer gathers audio samples from the input until enough are available andrewm@0: // for the FFT calculation andrewm@0: AudioSampleBuffer inputBuffer_; andrewm@0: int inputBufferLength_; andrewm@0: int inputBufferWritePosition_; andrewm@0: andrewm@0: // Circular buffer that collects output samples from the FFT overlap-add process andrewm@0: // before they are ready to be sent to the output stream andrewm@0: AudioSampleBuffer outputBuffer_; andrewm@0: int outputBufferLength_; andrewm@0: int outputBufferReadPosition_, outputBufferWritePosition_; andrewm@0: andrewm@0: // How many samples since the last FFT? andrewm@0: int samplesSinceLastFFT_; andrewm@0: andrewm@0: // Stored window function for pre-processing input frames andrewm@0: double *windowBuffer_; andrewm@0: int windowBufferLength_; andrewm@0: andrewm@0: // Whether or not prepareToPlay() has been called, i.e. that resources are in use andrewm@0: bool preparedToPlay_; andrewm@0: andrewm@0: // Spin lock that prevents the FFT settings from changing in the middle of the audio andrewm@0: // thread. andrewm@0: SpinLock fftSpinLock_; andrewm@0: andrewm@0: //============================================================================== andrewm@0: JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PVOCPassthroughAudioProcessor); andrewm@0: }; andrewm@0: andrewm@0: #endif // __PLUGINPROCESSOR_H_4693CB6E__