diff --git a/bufferoverride/bufferoverridedef.h b/bufferoverride/bufferoverridedef.h index ff41d21f..3ed9ca2e 100644 --- a/bufferoverride/bufferoverridedef.h +++ b/bufferoverride/bufferoverridedef.h @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ -Copyright (C) 2002-2021 Sophia Poirier +Copyright (C) 2002-2022 Sophia Poirier This file is part of Buffer Override. @@ -31,14 +31,13 @@ To contact the author, use the contact form at http://destroyfx.org/ #define PLUGIN_VERSION_MINOR 7 #define PLUGIN_VERSION_BUGFIX 1 #define PLUGIN_CLASS_NAME BufferOverride -#define PLUGIN_ENTRY_POINT "BufferOverrideEntry" #define TARGET_PLUGIN_USES_MIDI 1 #define TARGET_PLUGIN_IS_INSTRUMENT 0 #define TARGET_PLUGIN_USES_DSPCORE 0 #define TARGET_PLUGIN_HAS_GUI 1 #define PLUGIN_BACKGROUND_IMAGE_FILENAME "buffer-override-background.png" #define PLUGIN_BUNDLE_IDENTIFIER DESTROYFX_BUNDLE_ID_PREFIX "BufferOverride" DFX_BUNDLE_ID_SUFFIX -#define PLUGIN_COPYRIGHT_YEAR_STRING "2001-2021" +#define PLUGIN_COPYRIGHT_YEAR_STRING "2001-2022" #define VST_NUM_CHANNELS 2 diff --git a/dfx-library/dfxplugin-audiounit.cpp b/dfx-library/dfxplugin-audiounit.cpp index cc97e16d..e21d0437 100644 --- a/dfx-library/dfxplugin-audiounit.cpp +++ b/dfx-library/dfxplugin-audiounit.cpp @@ -114,18 +114,17 @@ void DfxPlugin::PreDestructor() // this is where DSP-specific resources should be allocated OSStatus DfxPlugin::Initialize() { - OSStatus status = noErr; - #if TARGET_PLUGIN_IS_INSTRUMENT // if this AU supports only specific I/O channel count configs, then check whether the current format is allowed AUSDK_Require(ischannelcountsupported(getnuminputs(), getnumoutputs()), kAudioUnitErr_FormatNotSupported); -#else - // call the inherited class' Initialize routine - status = TARGET_API_BASE_CLASS::Initialize(); #endif -// TARGET_PLUGIN_IS_INSTRUMENT - // call our initialize routine +#if TARGET_PLUGIN_USES_DSPCORE + cacheDSPCoreParameterValues(); +#endif + + auto status = TARGET_API_BASE_CLASS::Initialize(); + if (status == noErr) { status = do_initialize(); @@ -146,7 +145,7 @@ void DfxPlugin::Cleanup() } //----------------------------------------------------------------------------- -// this is called when an audio stream is broken somehow +// this is called when an audio stream timeline is broken somehow // (playback stop/restart, change of playback position, etc.) // any DSP state variables should be reset here // (contents of buffers, position trackers, IIR filter histories, etc.) @@ -1514,8 +1513,7 @@ OSStatus DfxPlugin::RestoreState(CFPropertyListRef inData) } if (!success) { -#endif -// TARGET_PLUGIN_USES_MIDI +#endif // TARGET_PLUGIN_USES_MIDI // XXX should we rethink this and load parameter settings always before mDfxSettings->restore()? // load the parameter settings that were restored @@ -1663,8 +1661,7 @@ OSStatus DfxPlugin::Render(AudioUnitRenderActionFlags& ioActionFlags, return noErr; } -#else -// !TARGET_PLUGIN_IS_INSTRUMENT +#else // !TARGET_PLUGIN_IS_INSTRUMENT //----------------------------------------------------------------------------- // this is the audio processing routine @@ -1672,7 +1669,7 @@ OSStatus DfxPlugin::ProcessBufferLists(AudioUnitRenderActionFlags& ioActionFlags AudioBufferList const& inBuffer, AudioBufferList& outBuffer, UInt32 inFramesToProcess) { - OSStatus result = noErr; + OSStatus status = noErr; // do any pre-DSP prep preprocessaudio(); @@ -1703,7 +1700,7 @@ OSStatus DfxPlugin::ProcessBufferLists(AudioUnitRenderActionFlags& ioActionFlags // if the plugin uses DSP cores, then we just call the // inherited base class implementation, which handles "Kernels" - result = TARGET_API_BASE_CLASS::ProcessBufferLists(ioActionFlags, *inputBufferPtr, outBuffer, inFramesToProcess); + status = TARGET_API_BASE_CLASS::ProcessBufferLists(ioActionFlags, *inputBufferPtr, outBuffer, inFramesToProcess); #else auto const numInputBuffers = inBuffer.mNumberBuffers; @@ -1721,8 +1718,7 @@ OSStatus DfxPlugin::ProcessBufferLists(AudioUnitRenderActionFlags& ioActionFlags // now do the processing processaudio(mInputAudioStreams_au.data(), mOutputAudioStreams_au.data(), inFramesToProcess); -#endif -// end of if/else TARGET_PLUGIN_USES_DSPCORE +#endif // end of if/else TARGET_PLUGIN_USES_DSPCORE // TODO: allow effects to communicate their output silence status, or calculate time-out from tail size and latency? bool const effectHasTail = !SupportsTail() || (gettailsize_samples() > 0) || (getlatency_samples() > 0); @@ -1734,10 +1730,9 @@ OSStatus DfxPlugin::ProcessBufferLists(AudioUnitRenderActionFlags& ioActionFlags // do any post-DSP stuff postprocessaudio(); - return result; + return status; } -#endif -// TARGET_PLUGIN_IS_INSTRUMENT +#endif // TARGET_PLUGIN_IS_INSTRUMENT @@ -1823,8 +1818,6 @@ OSStatus DfxPlugin::StopNote(MusicDeviceGroupID inGroupID, handlemidi_noteoff(inGroupID, inNoteInstanceID, 0, inOffsetSampleFrame); return noErr; } -#endif -// TARGET_PLUGIN_IS_INSTRUMENT +#endif // TARGET_PLUGIN_IS_INSTRUMENT -#endif -// TARGET_PLUGIN_USES_MIDI +#endif // TARGET_PLUGIN_USES_MIDI diff --git a/dfx-library/dfxplugin.cpp b/dfx-library/dfxplugin.cpp index 5d113cf6..aa51d504 100644 --- a/dfx-library/dfxplugin.cpp +++ b/dfx-library/dfxplugin.cpp @@ -163,6 +163,9 @@ DfxPlugin::DfxPlugin( mParametersChangedAsOfPreProcess(inNumParameters, false), mParametersTouchedAsOfPreProcess(inNumParameters, false), mParametersChangedInProcessHavePosted(inNumParameters) +#if TARGET_PLUGIN_USES_DSPCORE + , mDSPCoreParameterValuesCache(inNumParameters) +#endif { updatesamplerate(); // XXX have it set to something here? @@ -320,7 +323,9 @@ long DfxPlugin::do_initialize() #endif } -#ifndef TARGET_API_AUDIOUNIT + #ifndef TARGET_API_AUDIOUNIT + cacheDSPCoreParameterValues(); // AU handles this in its Initialize override, since it must occur before the AU SDK base class' implementation + // regenerate the DSP core instances whenever the audio I/O format changes mDSPCores.clear(); mDSPCores.reserve(getnumoutputs()); @@ -328,7 +333,7 @@ long DfxPlugin::do_initialize() { mDSPCores.emplace_back(dspCoreFactory(ch)); } -#endif + #endif #endif // TARGET_PLUGIN_USES_DSPCORE std::for_each(mSmoothedAudioValues.cbegin(), mSmoothedAudioValues.cend(), @@ -380,6 +385,10 @@ void DfxPlugin::do_cleanup() // non-virtual function that calls reset() and insures that some stuff happens void DfxPlugin::do_reset() { +#if TARGET_PLUGIN_USES_DSPCORE + cacheDSPCoreParameterValues(); +#endif + #ifdef TARGET_API_AUDIOUNIT // no need to do this if we're not even in Initialized state // because this will basically happen when we become initialized @@ -388,10 +397,7 @@ void DfxPlugin::do_reset() { // return; } - #if !TARGET_PLUGIN_IS_INSTRUMENT - // resets the kernels, if any TARGET_API_BASE_CLASS::Reset(kAudioUnitScope_Global, AudioUnitElement(0)); - #endif #endif mIsFirstRenderSinceReset = true; @@ -406,7 +412,7 @@ void DfxPlugin::do_reset() { if (dspCore) { - dspCore->do_reset(); + dspCore->reset(); } } #endif @@ -691,20 +697,25 @@ DfxParam::Value DfxPlugin::getparameter(long inParameterIndex) const //----------------------------------------------------------------------------- // return a (hopefully) 0 to 1 scalar version of the parameter's current value double DfxPlugin::getparameter_scalar(long inParameterIndex) const +{ + return getparameter_scalar(inParameterIndex, getparameter_f(inParameterIndex)); +} + +//----------------------------------------------------------------------------- +double DfxPlugin::getparameter_scalar(long inParameterIndex, double inValue) const { if (parameterisvalid(inParameterIndex)) { - auto const& parameter = mParameters[inParameterIndex]; switch (getparameterunit(inParameterIndex)) { case DfxParam::Unit::Percent: case DfxParam::Unit::DryWetMix: - return parameter.get_f() * 0.01; + return inValue * 0.01; case DfxParam::Unit::Scalar: - return parameter.get_f(); + return inValue; // XXX should we not just use contractparametervalue() here? default: - return parameter.get_f() / parameter.getmax_f(); + return inValue / mParameters[inParameterIndex].getmax_f(); } } return 0.0; @@ -858,6 +869,7 @@ std::string DfxPlugin::getparametergroupname(size_t inGroupIndex) const //----------------------------------------------------------------------------- bool DfxPlugin::getparameterchanged(long inParameterIndex) const { + assert(std::this_thread::get_id() == mAudioRenderThreadID); // only valid during audio rendering if (parameterisvalid(inParameterIndex)) { return mParametersChangedAsOfPreProcess[inParameterIndex]; @@ -868,6 +880,7 @@ bool DfxPlugin::getparameterchanged(long inParameterIndex) const //----------------------------------------------------------------------------- bool DfxPlugin::getparametertouched(long inParameterIndex) const { + assert(std::this_thread::get_id() == mAudioRenderThreadID); // only valid during audio rendering if (parameterisvalid(inParameterIndex)) { return mParametersTouchedAsOfPreProcess[inParameterIndex]; @@ -1935,6 +1948,10 @@ void DfxPlugin::preprocessaudio() mMidiState.preprocessEvents(); #endif +#if TARGET_PLUGIN_USES_DSPCORE + cacheDSPCoreParameterValues(); +#endif + // fetch the latest musical tempo/time/location information from the host processtimeinfo(); @@ -1978,6 +1995,35 @@ void DfxPlugin::do_processparameters() } #if TARGET_PLUGIN_USES_DSPCORE +//----------------------------------------------------------------------------- +double DfxPlugin::getdspcoreparameter_gen(long inParameterIndex) const +{ + if (parameterisvalid(inParameterIndex)) + { + return contractparametervalue(inParameterIndex, mParameters[inParameterIndex].derive_f(mDSPCoreParameterValuesCache[inParameterIndex])); + } + return 0.; +} + +//----------------------------------------------------------------------------- +double DfxPlugin::getdspcoreparameter_scalar(long inParameterIndex) const +{ + if (parameterisvalid(inParameterIndex)) + { + getparameter_scalar(inParameterIndex, mParameters[inParameterIndex].derive_f(mDSPCoreParameterValuesCache[inParameterIndex])); + } + return 0.; +} + +//----------------------------------------------------------------------------- +void DfxPlugin::cacheDSPCoreParameterValues() +{ + for (long i = 0; i < getnumparameters(); i++) + { + mDSPCoreParameterValuesCache[i] = getparameter(i); + } +} + //----------------------------------------------------------------------------- DfxPluginCore* DfxPlugin::getplugincore(unsigned long inChannel) const { diff --git a/dfx-library/dfxplugin.h b/dfx-library/dfxplugin.h index b7e5a639..2398c2b8 100644 --- a/dfx-library/dfxplugin.h +++ b/dfx-library/dfxplugin.h @@ -115,10 +115,6 @@ TARGET_PLUGIN_HAS_GUI TARGET_API_AUDIOUNIT TARGET_API_VST - necessary for Audio Unit: -PLUGIN_ENTRY_POINT - a C string of the base plugin class name with "Entry" appended - necessary for VST: VST_NUM_INPUTS VST_NUM_OUTPUTS @@ -645,6 +641,23 @@ class DfxPlugin : public TARGET_API_BASE_CLASS virtual void settings_crisisAlert(DfxSettings::CrisisReasonFlags /*inFlags*/) {} #endif +#if TARGET_PLUGIN_USES_DSPCORE + double getdspcoreparameter_f(long inParameterIndex) const + { + return parameterisvalid(inParameterIndex) ? mParameters[inParameterIndex].derive_f(mDSPCoreParameterValuesCache[inParameterIndex]) : 0.; + } + int64_t getdspcoreparameter_i(long inParameterIndex) const + { + return parameterisvalid(inParameterIndex) ? mParameters[inParameterIndex].derive_i(mDSPCoreParameterValuesCache[inParameterIndex]) : 0; + } + bool getdspcoreparameter_b(long inParameterIndex) const + { + return parameterisvalid(inParameterIndex) ? mParameters[inParameterIndex].derive_b(mDSPCoreParameterValuesCache[inParameterIndex]) : false; + } + double getdspcoreparameter_gen(long inParameterIndex) const; + double getdspcoreparameter_scalar(long inParameterIndex) const; +#endif + // handling of AU properties specific to Logic #if defined(TARGET_API_AUDIOUNIT) && LOGIC_AU_PROPERTIES_AVAILABLE UInt32 getSupportedLogicNodeOperationMode() const noexcept @@ -744,6 +757,7 @@ class DfxPlugin : public TARGET_API_BASE_CLASS void setparameter(long inParameterIndex, DfxParam::Value inValue); DfxParam::Value getparameter(long inParameterIndex) const; + double getparameter_scalar(long inParameterIndex, double inValue) const; // synchronize the underlying API/preset/etc. parameter value representation to the current value in DfxPlugin void update_parameter(long inParameterIndex); @@ -784,14 +798,22 @@ class DfxPlugin : public TARGET_API_BASE_CLASS #if TARGET_PLUGIN_USES_DSPCORE template [[nodiscard]] std::unique_ptr dspCoreFactory(); -#ifdef TARGET_API_AUDIOUNIT + + // updates the parameter value cache used by DSP cores + // this prevents potential later parameter value updates being visible to higher channel number DSP cores + // (must call this immediately before any call path that leads to DSP core operations) + void cacheDSPCoreParameterValues(); + + std::vector mDSPCoreParameterValuesCache; + + #ifdef TARGET_API_AUDIOUNIT ausdk::AUBufferList mAsymmetricalInputBufferList; -#else + #else [[nodiscard]] std::unique_ptr dspCoreFactory(unsigned long inChannel); std::vector> mDSPCores; // we have to manage this ourselves outside of the AU SDK std::vector mAsymmetricalInputAudioBuffer; -#endif -#endif + #endif +#endif // TARGET_PLUGIN_USES_DSPCORE #ifdef TARGET_API_AUDIOUNIT bool mAUElementsHaveBeenCreated = false; @@ -856,44 +878,44 @@ class DfxPlugin : public TARGET_API_BASE_CLASS public: #ifdef TARGET_API_AUDIOUNIT - void PostConstructor() override; - void PreDestructor() override; - OSStatus Initialize() override; - void Cleanup() override; - OSStatus Reset(AudioUnitScope inScope, AudioUnitElement inElement) override; + void PostConstructor() final; + void PreDestructor() final; + OSStatus Initialize() final; + void Cleanup() final; + OSStatus Reset(AudioUnitScope inScope, AudioUnitElement inElement) final; #if TARGET_PLUGIN_IS_INSTRUMENT OSStatus Render(AudioUnitRenderActionFlags& ioActionFlags, - AudioTimeStamp const& inTimeStamp, UInt32 inFramesToProcess) override; + AudioTimeStamp const& inTimeStamp, UInt32 inFramesToProcess) final; #else OSStatus ProcessBufferLists(AudioUnitRenderActionFlags& ioActionFlags, AudioBufferList const& inBuffer, AudioBufferList& outBuffer, - UInt32 inFramesToProcess) override; + UInt32 inFramesToProcess) final; #endif #if TARGET_PLUGIN_USES_DSPCORE - std::unique_ptr NewKernel() override; + std::unique_ptr NewKernel() final; #endif OSStatus GetPropertyInfo(AudioUnitPropertyID inPropertyID, AudioUnitScope inScope, AudioUnitElement inElement, - UInt32& outDataSize, bool& outWritable) override; + UInt32& outDataSize, bool& outWritable) final; OSStatus GetProperty(AudioUnitPropertyID inPropertyID, AudioUnitScope inScope, AudioUnitElement inElement, - void* outData) override; + void* outData) final; OSStatus SetProperty(AudioUnitPropertyID inPropertyID, AudioUnitScope inScope, AudioUnitElement inElement, - void const* inData, UInt32 inDataSize) override; + void const* inData, UInt32 inDataSize) final; void PropertyChanged(AudioUnitPropertyID inPropertyID, - AudioUnitScope inScope, AudioUnitElement inElement) override; + AudioUnitScope inScope, AudioUnitElement inElement) final; - UInt32 SupportedNumChannels(AUChannelInfo const** outInfo) override; - Float64 GetLatency() override; - Float64 GetTailTime() override; - bool SupportsTail() override + UInt32 SupportedNumChannels(AUChannelInfo const** outInfo) final; + Float64 GetLatency() final; + Float64 GetTailTime() final; + bool SupportsTail() final { return true; } - CFURLRef CopyIconLocation() override; + CFURLRef CopyIconLocation() final; OSStatus GetParameterInfo(AudioUnitScope inScope, AudioUnitParameterID inParameterID, @@ -904,35 +926,35 @@ class DfxPlugin : public TARGET_API_BASE_CLASS UInt32 inDesiredNameLength, CFStringRef* outClumpName) override; OSStatus SetParameter(AudioUnitParameterID inParameterID, AudioUnitScope inScope, AudioUnitElement inElement, - Float32 inValue, UInt32 inBufferOffsetInFrames) override; + Float32 inValue, UInt32 inBufferOffsetInFrames) final; OSStatus ChangeStreamFormat(AudioUnitScope inScope, AudioUnitElement inElement, AudioStreamBasicDescription const& inPrevFormat, - AudioStreamBasicDescription const& inNewFormat) override; + AudioStreamBasicDescription const& inNewFormat) final; OSStatus SaveState(CFPropertyListRef* outData) override; OSStatus RestoreState(CFPropertyListRef inData) override; - OSStatus GetPresets(CFArrayRef* outData) const override; - OSStatus NewFactoryPresetSet(AUPreset const& inNewFactoryPreset) override; + OSStatus GetPresets(CFArrayRef* outData) const final; + OSStatus NewFactoryPresetSet(AUPreset const& inNewFactoryPreset) final; #if TARGET_PLUGIN_USES_MIDI - OSStatus HandleNoteOn(UInt8 inChannel, UInt8 inNoteNumber, UInt8 inVelocity, UInt32 inStartFrame) override; - OSStatus HandleNoteOff(UInt8 inChannel, UInt8 inNoteNumber, UInt8 inVelocity, UInt32 inStartFrame) override; - OSStatus HandleAllNotesOff(UInt8 inChannel) override; - OSStatus HandleControlChange(UInt8 inChannel, UInt8 inController, UInt8 inValue, UInt32 inStartFrame) override; - OSStatus HandlePitchWheel(UInt8 inChannel, UInt8 inPitchLSB, UInt8 inPitchMSB, UInt32 inStartFrame) override; - OSStatus HandleChannelPressure(UInt8 inChannel, UInt8 inValue, UInt32 inStartFrame) override; - OSStatus HandleProgramChange(UInt8 inChannel, UInt8 inProgramNum) override; - OSStatus HandlePolyPressure(UInt8 inChannel, UInt8 inKey, UInt8 inValue, UInt32 inStartFrame) override + OSStatus HandleNoteOn(UInt8 inChannel, UInt8 inNoteNumber, UInt8 inVelocity, UInt32 inStartFrame) final; + OSStatus HandleNoteOff(UInt8 inChannel, UInt8 inNoteNumber, UInt8 inVelocity, UInt32 inStartFrame) final; + OSStatus HandleAllNotesOff(UInt8 inChannel) final; + OSStatus HandleControlChange(UInt8 inChannel, UInt8 inController, UInt8 inValue, UInt32 inStartFrame) final; + OSStatus HandlePitchWheel(UInt8 inChannel, UInt8 inPitchLSB, UInt8 inPitchMSB, UInt32 inStartFrame) final; + OSStatus HandleChannelPressure(UInt8 inChannel, UInt8 inValue, UInt32 inStartFrame) final; + OSStatus HandleProgramChange(UInt8 inChannel, UInt8 inProgramNum) final; + OSStatus HandlePolyPressure(UInt8 inChannel, UInt8 inKey, UInt8 inValue, UInt32 inStartFrame) final { return noErr; } - OSStatus HandleResetAllControllers(UInt8 inChannel) override + OSStatus HandleResetAllControllers(UInt8 inChannel) final { return noErr; } - OSStatus HandleAllSoundOff(UInt8 inChannel) override + OSStatus HandleAllSoundOff(UInt8 inChannel) final { return noErr; } @@ -940,9 +962,9 @@ class DfxPlugin : public TARGET_API_BASE_CLASS #if TARGET_PLUGIN_IS_INSTRUMENT OSStatus StartNote(MusicDeviceInstrumentID inInstrument, MusicDeviceGroupID inGroupID, NoteInstanceID* outNoteInstanceID, - UInt32 inOffsetSampleFrame, MusicDeviceNoteParams const& inParams) override; + UInt32 inOffsetSampleFrame, MusicDeviceNoteParams const& inParams) final; OSStatus StopNote(MusicDeviceGroupID inGroupID, - NoteInstanceID inNoteInstanceID, UInt32 inOffsetSampleFrame) override; + NoteInstanceID inNoteInstanceID, UInt32 inOffsetSampleFrame) final; // this is a convenience function swiped from AUEffectBase, but not included in MusicDeviceBase Float64 GetSampleRate() @@ -950,11 +972,11 @@ class DfxPlugin : public TARGET_API_BASE_CLASS return Output(0).GetStreamFormat().mSampleRate; } // this is handled by AUEffectBase, but not in MusicDeviceBase - bool StreamFormatWritable(AudioUnitScope inScope, AudioUnitElement inElement) override + bool StreamFormatWritable(AudioUnitScope inScope, AudioUnitElement inElement) final { return !IsInitialized(); } - bool CanScheduleParameters() const override + [[nodiscard]] bool CanScheduleParameters() const final { return true; } @@ -964,60 +986,60 @@ class DfxPlugin : public TARGET_API_BASE_CLASS #ifdef TARGET_API_VST - void close() override; + void close() final; - void processReplacing(float** inputs, float** outputs, VstInt32 sampleFrames) override; + void processReplacing(float** inputs, float** outputs, VstInt32 sampleFrames) final; - void suspend() override; - void resume() override; - void setSampleRate(float newRate) override; + void suspend() final; + void resume() final; + void setSampleRate(float newRate) final; // Note typo (getGet) from VST SDK. - VstInt32 getGetTailSize() override; - bool getInputProperties(VstInt32 index, VstPinProperties* properties) override; - bool getOutputProperties(VstInt32 index, VstPinProperties* properties) override; + VstInt32 getGetTailSize() final; + bool getInputProperties(VstInt32 index, VstPinProperties* properties) final; + bool getOutputProperties(VstInt32 index, VstPinProperties* properties) final; - void setProgram(VstInt32 inProgramNum) override; - void setProgramName(char* inName) override; - void getProgramName(char* outText) override; - bool getProgramNameIndexed(VstInt32 inCategory, VstInt32 inIndex, char* outText) override; + void setProgram(VstInt32 inProgramNum) final; + void setProgramName(char* inName) final; + void getProgramName(char* outText) final; + bool getProgramNameIndexed(VstInt32 inCategory, VstInt32 inIndex, char* outText) final; - void setParameter(VstInt32 index, float value) override; - float getParameter(VstInt32 index) override; - void getParameterName(VstInt32 index, char* name) override; - void getParameterDisplay(VstInt32 index, char* text) override; - void getParameterLabel(VstInt32 index, char* label) override; - bool getParameterProperties(VstInt32 index, VstParameterProperties* properties) override; + void setParameter(VstInt32 index, float value) final; + float getParameter(VstInt32 index) final; + void getParameterName(VstInt32 index, char* name) final; + void getParameterDisplay(VstInt32 index, char* text) final; + void getParameterLabel(VstInt32 index, char* label) final; + bool getParameterProperties(VstInt32 index, VstParameterProperties* properties) final; - bool getEffectName(char* outText) override; - VstInt32 getVendorVersion() override; - bool getVendorString(char* outText) override; - bool getProductString(char* outText) override; + bool getEffectName(char* outText) final; + VstInt32 getVendorVersion() final; + bool getVendorString(char* outText) final; + bool getProductString(char* outText) final; - VstInt32 canDo(char* text) override; + VstInt32 canDo(char* text) final; #if TARGET_PLUGIN_USES_MIDI - VstInt32 processEvents(VstEvents* events) override; - VstInt32 setChunk(void* data, VstInt32 byteSize, bool isPreset) override; - VstInt32 getChunk(void** data, bool isPreset) override; + VstInt32 processEvents(VstEvents* events) final; + VstInt32 setChunk(void* data, VstInt32 byteSize, bool isPreset) final; + VstInt32 getChunk(void** data, bool isPreset) final; #endif #endif // end of VST API methods #ifdef TARGET_API_RTAS - void Free() override; - ComponentResult ResetPlugInState() override; - ComponentResult Prime(Boolean inPriming) override; - void UpdateControlValueInAlgorithm(long inParameterIndex) override; - ComponentResult IsControlAutomatable(long inControlIndex, short* outItIs) override; - ComponentResult GetControlNameOfLength(long inParameterIndex, char* outName, long inNameLength, OSType inControllerType, FicBoolean* outReverseHighlight) override; - ComponentResult GetValueString(long inParameterIndex, long inValue, StringPtr outValueString, long inMaxLength) override; - ComponentResult SetChunk(OSType inChunkID, SFicPlugInChunk* chunk) override; - void DoTokenIdle() override; - CPlugInView* CreateCPlugInView() override; + void Free() final; + ComponentResult ResetPlugInState() final; + ComponentResult Prime(Boolean inPriming) final; + void UpdateControlValueInAlgorithm(long inParameterIndex) final; + ComponentResult IsControlAutomatable(long inControlIndex, short* outItIs) final; + ComponentResult GetControlNameOfLength(long inParameterIndex, char* outName, long inNameLength, OSType inControllerType, FicBoolean* outReverseHighlight) final; + ComponentResult GetValueString(long inParameterIndex, long inValue, StringPtr outValueString, long inMaxLength) final; + ComponentResult SetChunk(OSType inChunkID, SFicPlugInChunk* chunk) final; + void DoTokenIdle() final; + CPlugInView* CreateCPlugInView() final; #ifdef TARGET_API_AUDIOSUITE - void SetViewOrigin(Point anOrigin) override; + void SetViewOrigin(Point anOrigin) final; #endif // AU->RTAS glue convenience functions @@ -1026,31 +1048,31 @@ class DfxPlugin : public TARGET_API_BASE_CLASS bool GetParameter_b_FromRTAS(long inParameterID); #if TARGET_PLUGIN_HAS_GUI - void SetViewPort(GrafPtr inPort) override; - void GetViewRect(Rect* outViewRect) override; - long SetControlValue(long inControlIndex, long inValue) override; - long GetControlValue(long inControlIndex, long* aValue) override; - long GetControlDefaultValue(long inControlIndex, long* outValue) override; + void SetViewPort(GrafPtr inPort) final; + void GetViewRect(Rect* outViewRect) final; + long SetControlValue(long inControlIndex, long inValue) final; + long GetControlValue(long inControlIndex, long* aValue) final; + long GetControlDefaultValue(long inControlIndex, long* outValue) final; ComponentResult UpdateControlGraphic(long inControlIndex, long inValue); ComponentResult SetControlHighliteInfo(long inControlIndex, short inIsHighlighted, short inColor); ComponentResult ChooseControl(Point inLocalCoord, long* outControlIndex); - void setEditor(void* inEditor) override + void setEditor(void* inEditor) final { mCustomUI_p = static_cast(inEditor); } - int ProcessTouchControl(long inControlIndex) override; - int ProcessReleaseControl(long inControlIndex) override; - void ProcessDoIdle() override; - void* ProcessGetModuleHandle() override + int ProcessTouchControl(long inControlIndex) final; + int ProcessReleaseControl(long inControlIndex) final; + void ProcessDoIdle() final; + void* ProcessGetModuleHandle() final { return mModuleHandle_p; } - short ProcessUseResourceFile() override + short ProcessUseResourceFile() final { return fProcessType->GetProcessGroup()->UseResourceFile(); } - void ProcessRestoreResourceFile(short resFile) override + void ProcessRestoreResourceFile(short resFile) final { fProcessType->GetProcessGroup()->RestoreResourceFile(resFile); } @@ -1064,11 +1086,11 @@ class DfxPlugin : public TARGET_API_BASE_CLASS protected: #ifdef TARGET_API_RTAS - void EffectInit() override; + void EffectInit() final; #ifdef TARGET_API_AUDIOSUITE - UInt32 ProcessAudio(bool inIsGlobalBypassed) override; + UInt32 ProcessAudio(bool inIsGlobalBypassed) final; #endif - void RenderAudio(float** inAudioStreams, float** outAudioStreams, long inNumFramesToProcess) override; + void RenderAudio(float** inAudioStreams, float** outAudioStreams, long inNumFramesToProcess) final; #endif }; static_assert(std::has_virtual_destructor_v); @@ -1102,23 +1124,24 @@ class DfxPluginCore mDfxPlugin->unregisterAllSmoothedAudioValues(this); } + DfxPluginCore(DfxPluginCore const&) = delete; + DfxPluginCore(DfxPluginCore&&) = delete; + DfxPluginCore& operator=(DfxPluginCore const&) = delete; + DfxPluginCore& operator=(DfxPluginCore&&) = delete; + void dfxplugincore_postconstructor() { - do_reset(); + reset(); } virtual void process(float const* inStream, float* outStream, unsigned long inNumFrames) = 0; - void do_reset() - { - reset(); - } virtual void reset() {} // NOTE: a weakness of the processparameters design, and then subsequent snapping of // all smoothed values if it is the first audio render since audio reset, is that you // initially miss that snap if you getValue a smoothed value within processparameters virtual void processparameters() {} - auto const getplugin() const noexcept + auto getplugin() const noexcept { return mDfxPlugin; } @@ -1132,43 +1155,43 @@ class DfxPluginCore } double getparameter_f(long inParameterIndex) const { - return mDfxPlugin->getparameter_f(inParameterIndex); + return mDfxPlugin->getdspcoreparameter_f(inParameterIndex); } int64_t getparameter_i(long inParameterIndex) const { - return mDfxPlugin->getparameter_i(inParameterIndex); + return mDfxPlugin->getdspcoreparameter_i(inParameterIndex); } bool getparameter_b(long inParameterIndex) const { - return mDfxPlugin->getparameter_b(inParameterIndex); + return mDfxPlugin->getdspcoreparameter_b(inParameterIndex); } double getparameter_scalar(long inParameterIndex) const { - return mDfxPlugin->getparameter_scalar(inParameterIndex); + return mDfxPlugin->getdspcoreparameter_scalar(inParameterIndex); } double getparameter_gen(long inParameterIndex) const { - return mDfxPlugin->getparameter_gen(inParameterIndex); + return mDfxPlugin->getdspcoreparameter_gen(inParameterIndex); } - auto getparameterifchanged_f(long inParameterIndex) const + std::optional getparameterifchanged_f(long inParameterIndex) const { - return mDfxPlugin->getparameterifchanged_f(inParameterIndex); + return getparameterchanged(inParameterIndex) ? std::make_optional(getparameter_f(inParameterIndex)) : std::nullopt; } - auto getparameterifchanged_i(long inParameterIndex) const + std::optional getparameterifchanged_i(long inParameterIndex) const { - return mDfxPlugin->getparameterifchanged_i(inParameterIndex); + return getparameterchanged(inParameterIndex) ? std::make_optional(getparameter_i(inParameterIndex)) : std::nullopt; } - auto getparameterifchanged_b(long inParameterIndex) const + std::optional getparameterifchanged_b(long inParameterIndex) const { - return mDfxPlugin->getparameterifchanged_b(inParameterIndex); + return getparameterchanged(inParameterIndex) ? std::make_optional(getparameter_b(inParameterIndex)) : std::nullopt; } - auto getparameterifchanged_scalar(long inParameterIndex) const + std::optional getparameterifchanged_gen(long inParameterIndex) const { - return mDfxPlugin->getparameterifchanged_scalar(inParameterIndex); + return getparameterchanged(inParameterIndex) ? std::make_optional(getparameter_gen(inParameterIndex)) : std::nullopt; } - auto getparameterifchanged_gen(long inParameterIndex) const + std::optional getparameterifchanged_scalar(long inParameterIndex) const { - return mDfxPlugin->getparameterifchanged_gen(inParameterIndex); + return getparameterchanged(inParameterIndex) ? std::make_optional(getparameter_scalar(inParameterIndex)) : std::nullopt; } double getparametermin_f(long inParameterIndex) const { @@ -1190,10 +1213,6 @@ class DfxPluginCore { return mDfxPlugin->getparameterchanged(inParameterIndex); } - bool getparametertouched(long inParameterIndex) const - { - return mDfxPlugin->getparametertouched(inParameterIndex); - } void registerSmoothedAudioValue(dfx::ISmoothedValue* smoothedValue) { mDfxPlugin->registerSmoothedAudioValue(smoothedValue, this); @@ -1205,20 +1224,20 @@ class DfxPluginCore } #ifdef TARGET_API_AUDIOUNIT - void Process(Float32 const* inStream, Float32* outStream, UInt32 inNumFrames, bool& ioSilence) override + void Process(Float32 const* inStream, Float32* outStream, UInt32 inNumFrames, bool& ioSilence) final { process(inStream, outStream, inNumFrames); ioSilence = false; // TODO: allow DSP cores to communicate their output silence status } - void Reset() override + void Reset() final { - do_reset(); + reset(); } #else // Mimic what AUKernelBase does here. The channel is just the index // in the mDSPCores vector. void SetChannelNum(unsigned long inChannel) noexcept { mChannelNumber = inChannel; } - unsigned long GetChannelNum() const noexcept { return mChannelNumber; } + [[nodiscard]] unsigned long GetChannelNum() const noexcept { return mChannelNumber; } #endif @@ -1244,7 +1263,7 @@ static_assert(std::has_virtual_destructor_v); //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -class DfxEffectGroup : public CEffectGroup +class DfxEffectGroup final : public CEffectGroup { public: DfxEffectGroup(); @@ -1267,7 +1286,7 @@ class DfxEffectGroup : public CEffectGroup //----------------------------------------------------------------------------- -class CPluginControl_DfxCurved : virtual public CPluginControl_Continuous +class CPluginControl_DfxCurved final : virtual public CPluginControl_Continuous { public: CPluginControl_DfxCurved(OSType id, char const* name, double min, double max, @@ -1291,7 +1310,7 @@ class CPluginControl_DfxCurved : virtual public CPluginControl_Continuous //----------------------------------------------------------------------------- -class CPluginControl_DfxCurvedFrequency : public CPluginControl_Frequency, public CPluginControl_DfxCurved +class CPluginControl_DfxCurvedFrequency final : public CPluginControl_Frequency, public CPluginControl_DfxCurved { public: CPluginControl_DfxCurvedFrequency(OSType id, char const* name, double min, double max, diff --git a/dfx-library/dfxplugindef-template.h b/dfx-library/dfxplugindef-template.h index 95e845fa..6450accd 100644 --- a/dfx-library/dfxplugindef-template.h +++ b/dfx-library/dfxplugindef-template.h @@ -1,7 +1,7 @@ /*------------------------------------------------------------------------ Destroy FX Library is a collection of foundation code for creating audio processing plug-ins. -Copyright (C) 2002-2021 Sophia Poirier and Tom Murphy 7 +Copyright (C) 2002-2022 Sophia Poirier and Tom Murphy 7 This file is part of the Destroy FX Library (version 1.0). @@ -38,7 +38,6 @@ To contact the author, use the contact form at http://destroyfx.org/ #define PLUGIN_VERSION_MINOR 0 #define PLUGIN_VERSION_BUGFIX 0 #define PLUGIN_CLASS_NAME CoolPlugin -#define PLUGIN_ENTRY_POINT "Entry" // required if PLUGIN_NAME_STRING contains whitespace #define PLUGIN_BUNDLE_IDENTIFIER DESTROYFX_BUNDLE_ID_PREFIX "" DFX_BUNDLE_ID_SUFFIX #define PLUGIN_COPYRIGHT_YEAR_STRING "20XX" diff --git a/dfx-library/xcode/dfxplugin-release.xcconfig b/dfx-library/xcode/dfxplugin-release.xcconfig index 0eaa7de3..05f9c61f 100644 --- a/dfx-library/xcode/dfxplugin-release.xcconfig +++ b/dfx-library/xcode/dfxplugin-release.xcconfig @@ -1,5 +1,4 @@ DEAD_CODE_STRIPPING = YES -PRESERVE_DEAD_CODE_INITS_AND_TERMS = YES DEPLOYMENT_POSTPROCESSING = YES COPY_PHASE_STRIP = YES DEBUG_INFORMATION_FORMAT = dwarf-with-dsym diff --git a/dfxgui/dfxgui-fontfactory.h b/dfxgui/dfxgui-fontfactory.h index 3a281664..00c71a05 100644 --- a/dfxgui/dfxgui-fontfactory.h +++ b/dfxgui/dfxgui-fontfactory.h @@ -1,7 +1,7 @@ /*------------------------------------------------------------------------ Destroy FX Library is a collection of foundation code for creating audio processing plug-ins. -Copyright (C) 2002-2021 Sophia Poirier and Tom Murphy VII +Copyright (C) 2002-2022 Sophia Poirier and Tom Murphy VII This file is part of the Destroy FX Library (version 1.0). @@ -50,7 +50,7 @@ class FontFactory { virtual ~FontFactory() = default; FontFactory(FontFactory const&) = delete; - void operator=(FontFactory const&) = delete; + FontFactory& operator=(FontFactory const&) = delete; FontFactory(FontFactory&&) = delete; FontFactory& operator=(FontFactory&&) = delete; diff --git a/dfxgui/dfxguicontrol.h b/dfxgui/dfxguicontrol.h index 6beef164..ee92aed3 100644 --- a/dfxgui/dfxguicontrol.h +++ b/dfxgui/dfxguicontrol.h @@ -1,7 +1,7 @@ /*------------------------------------------------------------------------ Destroy FX Library is a collection of foundation code for creating audio processing plug-ins. -Copyright (C) 2003-2021 Sophia Poirier +Copyright (C) 2003-2022 Sophia Poirier This file is part of the Destroy FX Library (version 1.0). @@ -211,11 +211,11 @@ class DGMultiControl : /*public IDGMultiControl,*/ public DGControl public: using DGControl::DGControl; - std::vector getChildren() override + std::vector getChildren() final { return {mChildren.cbegin(), mChildren.cend()}; } - std::vector getChildren() const override + std::vector getChildren() const final { return {mChildren.cbegin(), mChildren.cend()}; } diff --git a/dfxgui/dfxguieditor.h b/dfxgui/dfxguieditor.h index f6a06557..cc7f9613 100644 --- a/dfxgui/dfxguieditor.h +++ b/dfxgui/dfxguieditor.h @@ -133,6 +133,11 @@ class DfxGuiEditor : public TARGET_API_EDITOR_BASE_CLASS, explicit DfxGuiEditor(DGEditorListenerInstance inInstance); virtual ~DfxGuiEditor(); + DfxGuiEditor(DfxGuiEditor const&) = delete; + DfxGuiEditor(DfxGuiEditor&&) = delete; + DfxGuiEditor& operator=(DfxGuiEditor const&) = delete; + DfxGuiEditor& operator=(DfxGuiEditor&&) = delete; + // VSTGUI overrides bool open(void* inWindow) final; void close() final; diff --git a/eqsync/eqsyncdef.h b/eqsync/eqsyncdef.h index e42da9e9..c07f8871 100644 --- a/eqsync/eqsyncdef.h +++ b/eqsync/eqsyncdef.h @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ -Copyright (C) 2002-2021 Sophia Poirier +Copyright (C) 2002-2022 Sophia Poirier This file is part of EQ Sync. @@ -32,14 +32,13 @@ To contact the author, use the contact form at http://destroyfx.org/ #define PLUGIN_VERSION_MINOR 1 #define PLUGIN_VERSION_BUGFIX 1 #define PLUGIN_CLASS_NAME EQSync -#define PLUGIN_ENTRY_POINT "EQSyncEntry" #define TARGET_PLUGIN_USES_MIDI 0 #define TARGET_PLUGIN_IS_INSTRUMENT 0 #define TARGET_PLUGIN_USES_DSPCORE 0 #define TARGET_PLUGIN_HAS_GUI 1 #define PLUGIN_BACKGROUND_IMAGE_FILENAME "eq-sync-background-panther.png" #define PLUGIN_BUNDLE_IDENTIFIER DESTROYFX_BUNDLE_ID_PREFIX "EQSync" DFX_BUNDLE_ID_SUFFIX -#define PLUGIN_COPYRIGHT_YEAR_STRING "2001-2021" +#define PLUGIN_COPYRIGHT_YEAR_STRING "2001-2022" #define VST_NUM_CHANNELS 2 diff --git a/exemplar/exemplardefs.h b/exemplar/exemplardefs.h index ac5a8a52..ff9b5c48 100644 --- a/exemplar/exemplardefs.h +++ b/exemplar/exemplardefs.h @@ -2,15 +2,29 @@ /* You need to redefine this stuff in order to make your plugin. see dfxplugin.h for details. */ +#ifndef DFX_EXEMPLAR_DEF_H +#define DFX_EXEMPLAR_DEF_H + + +#include "dfxplugin-prefix.h" + #define PLUGIN_NAME_STRING "DFX EXEMPLAR" #define PLUGIN_ID FOURCC('D', 'F', 'e', 'x') -#define PLUGIN_VERSION 0x00010100 -#define PLUGIN_ENTRY_POINT "ExemplarEntry" +#define PLUGIN_VERSION_MAJOR 1 +#define PLUGIN_VERSION_MINOR 1 +#define PLUGIN_VERSION_BUGFIX 0 #define TARGET_PLUGIN_USES_MIDI 1 #define TARGET_PLUGIN_IS_INSTRUMENT 0 #define TARGET_PLUGIN_USES_DSPCORE 1 +#define PLUGIN_COPYRIGHT_YEAR_STRING "2006-2022" + +#define VST_NUM_CHANNELS 2 + #ifndef TARGET_PLUGIN_HAS_GUI #define TARGET_PLUGIN_HAS_GUI 0 #endif + + +#endif diff --git a/fonttest/fonttestdef.h b/fonttest/fonttestdef.h index 4d07bee9..f9802643 100644 --- a/fonttest/fonttestdef.h +++ b/fonttest/fonttestdef.h @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ -Copyright (C) 2021 Tom Murphy 7 and Sophia Poirier +Copyright (C) 2021-2022 Tom Murphy 7 and Sophia Poirier This file is part of FontTest. @@ -33,7 +33,6 @@ To contact the author, use the contact form at http://destroyfx.org/ #define PLUGIN_VERSION_MINOR 0 #define PLUGIN_VERSION_BUGFIX 0 #define PLUGIN_CLASS_NAME FontTest -#define PLUGIN_ENTRY_POINT "FontTestEntry" #define TARGET_PLUGIN_USES_MIDI 0 #define TARGET_PLUGIN_IS_INSTRUMENT 0 #define TARGET_PLUGIN_USES_DSPCORE 0 @@ -41,7 +40,7 @@ To contact the author, use the contact form at http://destroyfx.org/ #define PLUGIN_BACKGROUND_IMAGE_FILENAME "fonttest-background.png" -#define PLUGIN_COPYRIGHT_YEAR_STRING "2021" +#define PLUGIN_COPYRIGHT_YEAR_STRING "2021-2022" #define VST_NUM_CHANNELS 2 diff --git a/geometer/geometerdef.h b/geometer/geometerdef.h index e4212afd..448f4398 100644 --- a/geometer/geometerdef.h +++ b/geometer/geometerdef.h @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ -Copyright (C) 2002-2021 Tom Murphy 7 and Sophia Poirier +Copyright (C) 2002-2022 Tom Murphy 7 and Sophia Poirier This file is part of Geometer. @@ -32,14 +32,13 @@ To contact the author, use the contact form at http://destroyfx.org/ #define PLUGIN_VERSION_MINOR 2 #define PLUGIN_VERSION_BUGFIX 1 #define PLUGIN_CLASS_NAME Geometer -#define PLUGIN_ENTRY_POINT "GeometerEntry" #define TARGET_PLUGIN_USES_MIDI 1 #define TARGET_PLUGIN_IS_INSTRUMENT 0 #define TARGET_PLUGIN_USES_DSPCORE 1 #define TARGET_PLUGIN_HAS_GUI 1 #define PLUGIN_BACKGROUND_IMAGE_FILENAME "geometer-background.png" #define PLUGIN_BUNDLE_IDENTIFIER DESTROYFX_BUNDLE_ID_PREFIX PLUGIN_NAME_STRING DFX_BUNDLE_ID_SUFFIX -#define PLUGIN_COPYRIGHT_YEAR_STRING "2002-2021" +#define PLUGIN_COPYRIGHT_YEAR_STRING "2002-2022" #define VST_NUM_CHANNELS 2 diff --git a/midigater/midigaterdef.h b/midigater/midigaterdef.h index 38a8e0eb..8aaab09a 100644 --- a/midigater/midigaterdef.h +++ b/midigater/midigaterdef.h @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ -Copyright (C) 2002-2021 Sophia Poirier +Copyright (C) 2002-2022 Sophia Poirier This file is part of MIDI Gater. @@ -32,14 +32,13 @@ To contact the author, use the contact form at http://destroyfx.org/ #define PLUGIN_VERSION_MINOR 0 #define PLUGIN_VERSION_BUGFIX 1 #define PLUGIN_CLASS_NAME MIDIGater -#define PLUGIN_ENTRY_POINT "MIDIGaterEntry" #define TARGET_PLUGIN_USES_MIDI 1 #define TARGET_PLUGIN_IS_INSTRUMENT 0 #define TARGET_PLUGIN_USES_DSPCORE 0 #define TARGET_PLUGIN_HAS_GUI 1 #define PLUGIN_BACKGROUND_IMAGE_FILENAME "midi-gater-background.png" #define PLUGIN_BUNDLE_IDENTIFIER DESTROYFX_BUNDLE_ID_PREFIX "MIDIGater" DFX_BUNDLE_ID_SUFFIX -#define PLUGIN_COPYRIGHT_YEAR_STRING "2001-2021" +#define PLUGIN_COPYRIGHT_YEAR_STRING "2001-2022" #define VST_NUM_CHANNELS 2 diff --git a/monomaker/monomakerdef.h b/monomaker/monomakerdef.h index 4d6c5496..89b792a3 100644 --- a/monomaker/monomakerdef.h +++ b/monomaker/monomakerdef.h @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ -Copyright (C) 2002-2021 Sophia Poirier +Copyright (C) 2002-2022 Sophia Poirier This file is part of Monomaker. @@ -32,14 +32,13 @@ To contact the author, use the contact form at http://destroyfx.org/ #define PLUGIN_VERSION_MINOR 1 #define PLUGIN_VERSION_BUGFIX 1 #define PLUGIN_CLASS_NAME Monomaker -#define PLUGIN_ENTRY_POINT "MonomakerEntry" #define TARGET_PLUGIN_USES_MIDI 0 #define TARGET_PLUGIN_IS_INSTRUMENT 0 #define TARGET_PLUGIN_USES_DSPCORE 0 #define TARGET_PLUGIN_HAS_GUI 1 #define PLUGIN_BACKGROUND_IMAGE_FILENAME "background.png" #define PLUGIN_BUNDLE_IDENTIFIER DESTROYFX_BUNDLE_ID_PREFIX PLUGIN_NAME_STRING DFX_BUNDLE_ID_SUFFIX -#define PLUGIN_COPYRIGHT_YEAR_STRING "2001-2021" +#define PLUGIN_COPYRIGHT_YEAR_STRING "2001-2022" #define VST_NUM_CHANNELS 2 diff --git a/polarizer/polarizerdef.h b/polarizer/polarizerdef.h index c4bd8c9f..af56dc1b 100644 --- a/polarizer/polarizerdef.h +++ b/polarizer/polarizerdef.h @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ -Copyright (C) 2002-2021 Sophia Poirier +Copyright (C) 2002-2022 Sophia Poirier This file is part of Polarizer. @@ -32,14 +32,13 @@ To contact the author, use the contact form at http://destroyfx.org/ #define PLUGIN_VERSION_MINOR 1 #define PLUGIN_VERSION_BUGFIX 1 #define PLUGIN_CLASS_NAME Polarizer -#define PLUGIN_ENTRY_POINT "PolarizerEntry" #define TARGET_PLUGIN_USES_MIDI 0 #define TARGET_PLUGIN_IS_INSTRUMENT 0 #define TARGET_PLUGIN_USES_DSPCORE 1 #define TARGET_PLUGIN_HAS_GUI 1 #define PLUGIN_BACKGROUND_IMAGE_FILENAME "polarizer-background.png" #define PLUGIN_BUNDLE_IDENTIFIER DESTROYFX_BUNDLE_ID_PREFIX PLUGIN_NAME_STRING DFX_BUNDLE_ID_SUFFIX -#define PLUGIN_COPYRIGHT_YEAR_STRING "2001-2021" +#define PLUGIN_COPYRIGHT_YEAR_STRING "2001-2022" #define VST_NUM_CHANNELS 2 diff --git a/rezsynth/rezsynthdef.h b/rezsynth/rezsynthdef.h index aa269407..05573a14 100644 --- a/rezsynth/rezsynthdef.h +++ b/rezsynth/rezsynthdef.h @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ -Copyright (C) 2002-2021 Sophia Poirier +Copyright (C) 2002-2022 Sophia Poirier This file is part of Rez Synth. @@ -32,14 +32,13 @@ To contact the author, use the contact form at http://destroyfx.org/ #define PLUGIN_VERSION_MINOR 0 #define PLUGIN_VERSION_BUGFIX 1 #define PLUGIN_CLASS_NAME RezSynth -#define PLUGIN_ENTRY_POINT "RezSynthEntry" #define TARGET_PLUGIN_USES_MIDI 1 #define TARGET_PLUGIN_IS_INSTRUMENT 0 #define TARGET_PLUGIN_USES_DSPCORE 0 #define TARGET_PLUGIN_HAS_GUI 1 #define PLUGIN_BACKGROUND_IMAGE_FILENAME "background.png" #define PLUGIN_BUNDLE_IDENTIFIER DESTROYFX_BUNDLE_ID_PREFIX "RezSynth" DFX_BUNDLE_ID_SUFFIX -#define PLUGIN_COPYRIGHT_YEAR_STRING "2001-2021" +#define PLUGIN_COPYRIGHT_YEAR_STRING "2001-2022" #define VST_NUM_CHANNELS 2 diff --git a/scrubby/scrubbydef.h b/scrubby/scrubbydef.h index ecc13d75..854b5391 100644 --- a/scrubby/scrubbydef.h +++ b/scrubby/scrubbydef.h @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ -Copyright (C) 2002-2021 Sophia Poirier +Copyright (C) 2002-2022 Sophia Poirier This file is part of Scrubby. @@ -32,14 +32,13 @@ To contact the author, use the contact form at http://destroyfx.org/ #define PLUGIN_VERSION_MINOR 1 #define PLUGIN_VERSION_BUGFIX 1 #define PLUGIN_CLASS_NAME Scrubby -#define PLUGIN_ENTRY_POINT "ScrubbyEntry" #define TARGET_PLUGIN_USES_MIDI 1 #define TARGET_PLUGIN_IS_INSTRUMENT 0 #define TARGET_PLUGIN_USES_DSPCORE 0 #define TARGET_PLUGIN_HAS_GUI 1 #define PLUGIN_BACKGROUND_IMAGE_FILENAME "scrubby-background.png" #define PLUGIN_BUNDLE_IDENTIFIER DESTROYFX_BUNDLE_ID_PREFIX PLUGIN_NAME_STRING DFX_BUNDLE_ID_SUFFIX -#define PLUGIN_COPYRIGHT_YEAR_STRING "2002-2021" +#define PLUGIN_COPYRIGHT_YEAR_STRING "2002-2022" #define VST_NUM_CHANNELS 2 diff --git a/skidder/skidderdef.h b/skidder/skidderdef.h index 8fde9968..9604bb0c 100644 --- a/skidder/skidderdef.h +++ b/skidder/skidderdef.h @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ -Copyright (C) 2002-2021 Sophia Poirier +Copyright (C) 2002-2022 Sophia Poirier This file is part of Skidder. @@ -32,14 +32,13 @@ To contact the author, use the contact form at http://destroyfx.org/ #define PLUGIN_VERSION_MINOR 0 #define PLUGIN_VERSION_BUGFIX 1 #define PLUGIN_CLASS_NAME Skidder -#define PLUGIN_ENTRY_POINT "SkidderEntry" #define TARGET_PLUGIN_USES_MIDI 1 #define TARGET_PLUGIN_IS_INSTRUMENT 0 #define TARGET_PLUGIN_USES_DSPCORE 0 #define TARGET_PLUGIN_HAS_GUI 1 #define PLUGIN_BACKGROUND_IMAGE_FILENAME "background.png" #define PLUGIN_BUNDLE_IDENTIFIER DESTROYFX_BUNDLE_ID_PREFIX PLUGIN_NAME_STRING DFX_BUNDLE_ID_SUFFIX -#define PLUGIN_COPYRIGHT_YEAR_STRING "2000-2021" +#define PLUGIN_COPYRIGHT_YEAR_STRING "2000-2022" #define VST_NUM_CHANNELS 2 diff --git a/slowft/slowftdefs.h b/slowft/slowftdefs.h index cffaa2d3..f9f5cb97 100644 --- a/slowft/slowftdefs.h +++ b/slowft/slowftdefs.h @@ -2,15 +2,29 @@ /* You need to redefine this stuff in order to make your plugin. see dfxplugin.h for details. */ +#ifndef DFX_SLOWFT_DEF_H +#define DFX_SLOWFT_DEF_H + + +#include "dfxplugin-prefix.h" + #define PLUGIN_NAME_STRING "SLOWFT" #define PLUGIN_ID FOURCC('D', 'F', 's', 'f') -#define PLUGIN_VERSION 0x00010100 -#define PLUGIN_ENTRY_POINT "SlowftEntry" +#define PLUGIN_VERSION_MAJOR 1 +#define PLUGIN_VERSION_MINOR 1 +#define PLUGIN_VERSION_BUGFIX 0 #define TARGET_PLUGIN_USES_MIDI 1 #define TARGET_PLUGIN_IS_INSTRUMENT 0 #define TARGET_PLUGIN_USES_DSPCORE 1 +#define PLUGIN_COPYRIGHT_YEAR_STRING "2005-2022" + +#define VST_NUM_CHANNELS 2 + #ifndef TARGET_PLUGIN_HAS_GUI #define TARGET_PLUGIN_HAS_GUI 0 #endif + + +#endif diff --git a/stub-dfxplugin/dfxplugin-stub-def.h b/stub-dfxplugin/dfxplugin-stub-def.h index cd90ae34..42e56337 100644 --- a/stub-dfxplugin/dfxplugin-stub-def.h +++ b/stub-dfxplugin/dfxplugin-stub-def.h @@ -1,7 +1,7 @@ /*------------------------------------------------------------------------ Destroy FX Library is a collection of foundation code for creating audio processing plug-ins. -Copyright (C) 2002-2021 Sophia Poirier +Copyright (C) 2002-2022 Sophia Poirier This file is part of the Destroy FX Library (version 1.0). @@ -44,11 +44,10 @@ or somehow define this stuff another way (in compiler settings, or whatever). // your subclass of DfxPlugin #define PLUGIN_CLASS_NAME DfxStub // Audio Unit entry point: plugin class name appended with "Entry" -#define PLUGIN_ENTRY_POINT "DfxStubEntry" // macOS bundle identifier #define PLUGIN_BUNDLE_IDENTIFIER DESTROYFX_BUNDLE_ID_PREFIX "DfxStub" DFX_BUNDLE_ID_SUFFIX // copyright year(s) published in versioning metadata -#define PLUGIN_COPYRIGHT_YEAR_STRING "2002-2021" +#define PLUGIN_COPYRIGHT_YEAR_STRING "2002-2022" // 0 or 1 #define TARGET_PLUGIN_USES_MIDI 1 // 0 or 1 (1 implied 1 is also true for TARGET_PLUGIN_USES_MIDI) diff --git a/thrush/thrushdef.h b/thrush/thrushdef.h index 188a9d31..f284226d 100644 --- a/thrush/thrushdef.h +++ b/thrush/thrushdef.h @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ -Copyright (C) 2001-2021 Sophia Poirier and Keith Fullerton Whitman +Copyright (C) 2001-2022 Sophia Poirier and Keith Fullerton Whitman This file is part of Thrush. @@ -31,13 +31,12 @@ To contact the author, use the contact form at http://destroyfx.org/ #define PLUGIN_VERSION_MINOR 0 #define PLUGIN_VERSION_BUGFIX 0 #define PLUGIN_CLASS_NAME Thrush -#define PLUGIN_ENTRY_POINT "ThrushFactory" #define TARGET_PLUGIN_USES_MIDI 0 #define TARGET_PLUGIN_IS_INSTRUMENT 0 #define TARGET_PLUGIN_USES_DSPCORE 0 #define TARGET_PLUGIN_HAS_GUI 0 //#define PLUGIN_BACKGROUND_IMAGE_FILENAME "thrush-background.png" -#define PLUGIN_COPYRIGHT_YEAR_STRING "2001-2021" +#define PLUGIN_COPYRIGHT_YEAR_STRING "2001-2022" #define VST_NUM_CHANNELS 2 diff --git a/transverb/transverb-base.h b/transverb/transverb-base.h index 969ea82a..27a64631 100644 --- a/transverb/transverb-base.h +++ b/transverb/transverb-base.h @@ -47,6 +47,7 @@ enum kTomsound, kFreeze, kAttenuateFeedbackByMixLevel, + kDistChangeMode, kNumParameters }; @@ -65,6 +66,8 @@ enum { kQualityMode_DirtFi, kQualityMode_HiFi, kQualityMode_UltraHiFi, kQualityM enum { kSpeedMode_Fine, kSpeedMode_Semitone, kSpeedMode_Octave, kSpeedMode_NumModes }; static constexpr dfx::PropertyID kTransverbProperty_SpeedModeBase = dfx::kPluginProperty_EndOfList; +enum { kDistChangeMode_Reverse, kDistChangeMode_AdHocVarispeed, kDistChangeMode_DistanceVarispeed, kDistChangeMode_BufferVarispeed, kDistChangeMode_LoopingBufferVarispeed, kDistChangeMode_Count }; + dfx::PropertyID speedModeIndexToPropertyID(size_t inIndex) noexcept; size_t speedModePropertyIDToIndex(dfx::PropertyID inPropertyID) noexcept; diff --git a/transverb/transverb.h b/transverb/transverb.h index 7d8724a5..9340a5df 100644 --- a/transverb/transverb.h +++ b/transverb/transverb.h @@ -25,6 +25,7 @@ To contact the author, use the contact form at http://destroyfx.org/ #include #include #include +#include #include #include "dfxplugin.h" @@ -56,6 +57,8 @@ class TransverbDSP final : public DfxPluginCore { dfx::SmoothedValue mix, feed; double read = 0.; + std::optional targetdist; + double distspeedfactor = 1.; std::vector buf; dfx::IIRFilter filter; @@ -82,17 +85,23 @@ class TransverbDSP final : public DfxPluginCore { static constexpr int mod_bipolar(int value, int modulo); static inline double fmod_bipolar(double value, double modulo); + // distance in samples of a read position from the current write position + double getdist(double read) const; + void processdist(double distnormalized, Head& head); + // these store the parameter values int bsize = 0; dfx::SmoothedValue drymix; - long quality = 0; - bool tomsound = false; + int distchangemode {}; int writer = 0; std::array heads; int const MAXBUF; // the size of the audio buffer (dependent on sampling rate) + bool firstrendersincereset = false; + std::vector& buftemp; + std::vector const firCoefficientsWindow; }; @@ -115,6 +124,10 @@ class Transverb final : public DfxPlugin { long dfx_SetProperty(dfx::PropertyID inPropertyID, dfx::Scope inScope, unsigned long inItemIndex, void const* inData, size_t inDataSize) override; + auto& getscratchbuffer() noexcept { + return buftemp; + } + protected: size_t settings_sizeOfExtendedData() const noexcept override; void settings_saveExtendedData(void* outData, bool isPreset) override; @@ -131,6 +144,7 @@ class Transverb final : public DfxPlugin { } std::array speedModeStates {}; + std::vector buftemp; // shared between all DSP cores (memory optimization) }; diff --git a/transverb/transverbdef.h b/transverb/transverbdef.h index fff812eb..b147f4d3 100644 --- a/transverb/transverbdef.h +++ b/transverb/transverbdef.h @@ -33,7 +33,6 @@ To contact the author, use the contact form at http://destroyfx.org/ #define PLUGIN_VERSION_MINOR 5 #define PLUGIN_VERSION_BUGFIX 3 #define PLUGIN_CLASS_NAME Transverb -#define PLUGIN_ENTRY_POINT "TransverbEntry" #define TARGET_PLUGIN_USES_MIDI 1 #define TARGET_PLUGIN_IS_INSTRUMENT 0 #define TARGET_PLUGIN_USES_DSPCORE 1 @@ -41,7 +40,7 @@ To contact the author, use the contact form at http://destroyfx.org/ #define PLUGIN_BACKGROUND_IMAGE_FILENAME "transverb-background.png" -#define PLUGIN_COPYRIGHT_YEAR_STRING "2001-2021" +#define PLUGIN_COPYRIGHT_YEAR_STRING "2001-2022" #define VST_NUM_CHANNELS 2 diff --git a/transverb/transverbformalities.cpp b/transverb/transverbformalities.cpp index e87b1079..93947a8b 100644 --- a/transverb/transverbformalities.cpp +++ b/transverb/transverbformalities.cpp @@ -57,6 +57,7 @@ Transverb::Transverb(TARGET_API_BASE_INSTANCE_TYPE inInstance) initparameter_b(kTomsound, {"TOMSOUND", "TomSnd", "Tom7"}, false); initparameter_b(kFreeze, dfx::MakeParameterNames(dfx::kParameterNames_Freeze), false); initparameter_b(kAttenuateFeedbackByMixLevel, {"attenuate feedback by mix level", "AtnFdbk", "AtnFdb", "-fdb"}, false); + initparameter_list(kDistChangeMode, {"distance change mode", "DistMod", "DstMod", "DMod"}, kDistChangeMode_Reverse, kDistChangeMode_Reverse, kDistChangeMode_Count); setparameterenforcevaluelimits(kBsize, true); setparameterenforcevaluelimits(kDist1, true); @@ -66,10 +67,12 @@ Transverb::Transverb(TARGET_API_BASE_INSTANCE_TYPE inInstance) setparametervaluestring(kQuality, kQualityMode_HiFi, "hi-fi"); setparametervaluestring(kQuality, kQualityMode_UltraHiFi, "ultra hi-fi"); - // distance parameters only have meaningful effect at zero speed which probably will never occur randomly, - // and otherwise all they do is glitch a lot, so omit them - addparameterattributes(kDist1, DfxParam::kAttribute_OmitFromRandomizeAll); - addparameterattributes(kDist2, DfxParam::kAttribute_OmitFromRandomizeAll); + setparametervaluestring(kDistChangeMode, kDistChangeMode_Reverse, "reverse"); + setparametervaluestring(kDistChangeMode, kDistChangeMode_AdHocVarispeed, "ad hoc varispeed"); + setparametervaluestring(kDistChangeMode, kDistChangeMode_DistanceVarispeed, "distance varispeed"); + setparametervaluestring(kDistChangeMode, kDistChangeMode_BufferVarispeed, "buffer varispeed"); + setparametervaluestring(kDistChangeMode, kDistChangeMode_LoopingBufferVarispeed, "looping buffer varispeed"); + addparameterattributes(kFreeze, DfxParam::kAttribute_OmitFromRandomizeAll); addparameterattributes(kAttenuateFeedbackByMixLevel, DfxParam::kAttribute_OmitFromRandomizeAll); @@ -108,8 +111,11 @@ void Transverb::dfx_PostConstructor() { TransverbDSP::TransverbDSP(DfxPlugin* inDfxPlugin) : DfxPluginCore(inDfxPlugin), MAXBUF(static_cast(getparametermax_f(kBsize) * 0.001 * getsamplerate())), + buftemp(dynamic_cast(inDfxPlugin)->getscratchbuffer()), firCoefficientsWindow(dfx::FIRFilter::generateKaiserWindow(kNumFIRTaps, 60.0f)) { + buftemp.assign(MAXBUF, 0.f); + registerSmoothedAudioValue(&drymix); for (auto& head : heads) { @@ -125,12 +131,15 @@ TransverbDSP::TransverbDSP(DfxPlugin* inDfxPlugin) void TransverbDSP::reset() { std::for_each(heads.begin(), heads.end(), [](Head& head){ head.reset(); }); + + firstrendersincereset = true; } void TransverbDSP::Head::reset() { smoothcount = 0; lastdelayval = 0.f; + targetdist.reset(); filter.reset(); speedHasChanged = true; @@ -163,8 +172,6 @@ void TransverbDSP::processparameters() { heads[head].feed = *value; } } - quality = getparameter_i(kQuality); - tomsound = getparameter_b(kTomsound); if (auto const value = getparameterifchanged_f(kBsize)) { @@ -192,12 +199,12 @@ void TransverbDSP::processparameters() { std::for_each(heads.begin(), heads.end(), [bsize_f](Head& head){ head.read = fmod_bipolar(head.read, bsize_f); }); } + distchangemode = getparameter_i(kDistChangeMode); for (size_t head = 0; head < kNumDelays; head++) { if (auto const dist = getparameterifchanged_f(kDistParameters[head])) { - auto const bsize_f = static_cast(bsize); - heads[head].read = fmod_bipolar(static_cast(writer) - (*dist * bsize_f), bsize_f); + processdist(*dist, heads[head]); } } @@ -220,6 +227,64 @@ void TransverbDSP::processparameters() { heads[0].mix.setValueNow(getparametermin_f(kMix1)); } } + + firstrendersincereset = false; +} + +double TransverbDSP::getdist(double read) const { + + return fmod_bipolar(static_cast(writer) - read, static_cast(bsize)); +} + +void TransverbDSP::processdist(double distnormalized, Head& head) { + + auto const bsize_f = static_cast(bsize); + auto const distsamples = distnormalized * bsize_f; + auto const targetread = fmod_bipolar(static_cast(writer) - distsamples, bsize_f); + + if (firstrendersincereset) + { + head.read = targetread; + } + else + { + if (distchangemode == kDistChangeMode_Reverse) + { + head.targetdist = distsamples; + } + else if (auto const resamplerate = getdist(head.read) / std::max(distsamples, 1.); distchangemode == kDistChangeMode_AdHocVarispeed) + { + head.targetdist = distsamples; + head.distspeedfactor = resamplerate; + head.speedHasChanged = true; + } + else + { + constexpr double modulationthresholdsamples = 1.; + if (std::fabs(targetread - head.read) >= modulationthresholdsamples) + { + auto const bsizesteps = bsize_f / resamplerate; + bool const subslice = (distchangemode == kDistChangeMode_DistanceVarispeed); + bool const looping = (distchangemode == kDistChangeMode_LoopingBufferVarispeed); + auto const copylength_f = subslice ? distsamples : (looping ? bsize_f : std::min(bsize_f, bsizesteps)); + auto const copylength = static_cast(std::lround(copylength_f)); + assert(copylength <= buftemp.size()); + assert(static_cast(copylength) <= bsize); + auto const sourcestart = subslice ? head.read : fmod_bipolar(static_cast(writer) - (copylength_f * resamplerate), bsize_f); + for (size_t i = 0; i < copylength; i++) + { + auto const sourcepos = std::fmod(sourcestart + (resamplerate * static_cast(i)), bsize_f); + buftemp[i] = interpolateHermite(head.buf.data(), sourcepos, bsize, writer); + } + auto const destinationstart = subslice ? std::lround(targetread) : mod_bipolar(writer - static_cast(copylength), bsize); + auto const copylength1 = std::min(static_cast(bsize - destinationstart), copylength); + auto const copylength2 = copylength - copylength1; + std::copy_n(buftemp.cbegin(), copylength1, std::next(head.buf.begin(), destinationstart)); + std::copy_n(std::next(buftemp.cbegin(), copylength1), copylength2, head.buf.begin()); + } + head.read = targetread; + } + } } diff --git a/transverb/transverbprocess.cpp b/transverb/transverbprocess.cpp index 65fd9316..b41575b4 100644 --- a/transverb/transverbprocess.cpp +++ b/transverb/transverbprocess.cpp @@ -35,11 +35,13 @@ using namespace dfx::TV; void TransverbDSP::process(float const* inAudio, float* outAudio, unsigned long numSampleFrames) { - std::array delayvals {}; // delay buffer output values auto const bsize_float = static_cast(bsize); // cut down on casting + auto const quality = getparameter_i(kQuality); + auto const tomsound = getparameter_b(kTomsound); auto const freeze = getparameter_b(kFreeze); int const writerIncrement = freeze ? 0 : 1; auto const attenuateFeedbackByMixLevel = getparameter_b(kAttenuateFeedbackByMixLevel); + std::array delayvals {}; // delay buffer output values ///////////// S O P H I A S O U N D ////////////// @@ -68,6 +70,9 @@ void TransverbDSP::process(float const* inAudio, float* outAudio, unsigned long for (size_t h = 0; h < kNumDelays; h++) // delay heads loop { auto const read_int = static_cast(heads[h].read); + auto const reverseread = (distchangemode == kDistChangeMode_Reverse) && heads[h].targetdist.has_value(); + auto const distcatchup = (distchangemode == kDistChangeMode_AdHocVarispeed) && heads[h].targetdist.has_value(); + auto const speed = heads[h].speed.getValue() * (distcatchup ? heads[h].distspeedfactor : 1.); // filter setup if (quality == kQualityMode_UltraHiFi) @@ -76,20 +81,20 @@ void TransverbDSP::process(float const* inAudio, float* outAudio, unsigned long { lowpasspos[h] = read_int; // check to see if we need to lowpass the first delay head and init coefficients if so - if (heads[h].speed.getValue() > kUnitySpeed) + if (speed > kUnitySpeed) { filtermodes[h] = FilterMode::LowpassIIR; - speed_ints[h] = static_cast(heads[h].speed.getValue()); + speed_ints[h] = static_cast(speed); // it becomes too costly to try to IIR at higher speeds, so switch to FIR filtering - if (heads[h].speed.getValue() >= kFIRSpeedThreshold) + if (speed >= kFIRSpeedThreshold) { filtermodes[h] = FilterMode::LowpassFIR; // compensate for gain lost from filtering - mugs[h] = static_cast(std::pow(heads[h].speed.getValue() / kFIRSpeedThreshold, 0.78)); + mugs[h] = static_cast(std::pow(speed / kFIRSpeedThreshold, 0.78)); // update the coefficients only if necessary if (std::exchange(heads[h].speedHasChanged, false)) { - dfx::FIRFilter::calculateIdealLowpassCoefficients((samplerate / heads[h].speed.getValue()) * dfx::FIRFilter::kShelfStartLowpass, + dfx::FIRFilter::calculateIdealLowpassCoefficients((samplerate / speed) * dfx::FIRFilter::kShelfStartLowpass, samplerate, kNumFIRTaps, heads[h].firCoefficients.data(), firCoefficientsWindow.data()); heads[h].filter.reset(); @@ -97,7 +102,7 @@ void TransverbDSP::process(float const* inAudio, float* outAudio, unsigned long } else if (std::exchange(heads[h].speedHasChanged, false)) { - heads[h].filter.setLowpassCoefficients((samplerate / heads[h].speed.getValue()) * dfx::IIRFilter::kShelfStartLowpass); + heads[h].filter.setLowpassCoefficients((samplerate / speed) * dfx::IIRFilter::kShelfStartLowpass); } } // we need to highpass the delay head to remove mega sub bass @@ -106,7 +111,7 @@ void TransverbDSP::process(float const* inAudio, float* outAudio, unsigned long filtermodes[h] = FilterMode::Highpass; if (std::exchange(heads[h].speedHasChanged, false)) { - heads[h].filter.setHighpassCoefficients(kHighpassFilterCutoff / heads[h].speed.getValue()); + heads[h].filter.setHighpassCoefficients(kHighpassFilterCutoff / speed); } } } @@ -173,18 +178,18 @@ void TransverbDSP::process(float const* inAudio, float* outAudio, unsigned long // start smoothing if the writer has passed a reader or vice versa, // though not if reader and writer move at the same speed // (check the positions before wrapping around the heads) - auto const nextRead = static_cast(heads[h].read + heads[h].speed.getValue()); + auto const nextRead = static_cast(heads[h].read + speed); auto const nextWrite = writer + 1; bool const readCrossingAhead = (read_int < writer) && (nextRead >= nextWrite); bool const readCrossingBehind = (read_int >= writer) && (nextRead <= nextWrite); - bool const speedIsUnity = heads[h].speed.getValue() == kUnitySpeed; + bool const speedIsUnity = (speed == kUnitySpeed); if ((readCrossingAhead || readCrossingBehind) && !speedIsUnity) { // check because, at slow speeds, it's possible to go into this twice or more in a row if (heads[h].smoothcount <= 0) { // store the most recent output as the head's smoothing sample heads[h].lastdelayval = delayvals[h]; // truncate the smoothing duration if we're using too small of a buffer size - auto const bufferReadSteps = static_cast(bsize_float / heads[h].speed.getValue()); + auto const bufferReadSteps = static_cast(bsize_float / speed); auto const smoothdur = std::min(bufferReadSteps, kAudioSmoothingDur_samples); heads[h].smoothstep = 1.f / static_cast(smoothdur); // the scalar step value heads[h].smoothcount = smoothdur; // set the counter to the total duration @@ -192,9 +197,21 @@ void TransverbDSP::process(float const* inAudio, float* outAudio, unsigned long } // update read heads, wrapping around if they have gone past the end of the buffer - heads[h].read += heads[h].speed.getValue(); - if (heads[h].read >= bsize_float) { - heads[h].read = fmod_bipolar(heads[h].read, bsize_float); + if (reverseread) { + heads[h].read -= speed; + while (heads[h].read < 0.) { + heads[h].read += bsize_float; + } + } else { + heads[h].read += speed; + if (heads[h].read >= bsize_float) { + heads[h].read = fmod_bipolar(heads[h].read, bsize_float); + } + } + if (distcatchup || reverseread) { + if (std::fabs(getdist(heads[h].read) - *heads[h].targetdist) < speed) { + heads[h].targetdist.reset(); + } } // if we're doing IIR lowpass filtering, @@ -204,40 +221,47 @@ void TransverbDSP::process(float const* inAudio, float* outAudio, unsigned long if (filtermodes[h] == FilterMode::LowpassIIR) { int lowpasscount = 0; + int const direction = reverseread ? -1 : 1; while (lowpasscount < speed_ints[h]) { switch (speed_ints[h] - lowpasscount) { case 1: heads[h].filter.processToCacheH1(heads[h].buf[lowpasspos[h]]); - lowpasspos[h] = (lowpasspos[h] + 1) % bsize; + lowpasspos[h] = mod_bipolar(lowpasspos[h] + (1 * direction), bsize); lowpasscount++; break; case 2: heads[h].filter.processToCacheH2(heads[h].buf.data(), lowpasspos[h], bsize); - lowpasspos[h] = (lowpasspos[h] + 2) % bsize; + lowpasspos[h] = mod_bipolar(lowpasspos[h] + (2 * direction), bsize); lowpasscount += 2; break; case 3: heads[h].filter.processToCacheH3(heads[h].buf.data(), lowpasspos[h], bsize); - lowpasspos[h] = (lowpasspos[h] + 3) % bsize; + lowpasspos[h] = mod_bipolar(lowpasspos[h] + (3 * direction), bsize); lowpasscount += 3; break; default: heads[h].filter.processToCacheH4(heads[h].buf.data(), lowpasspos[h], bsize); - lowpasspos[h] = (lowpasspos[h] + 4) % bsize; + lowpasspos[h] = mod_bipolar(lowpasspos[h] + (4 * direction), bsize); lowpasscount += 4; break; } } auto const nextread_int = static_cast(heads[h].read); // check whether we need to consume one more sample - bool const extrasample = ((lowpasspos[h] < nextread_int) && ((lowpasspos[h] + 1) == nextread_int)) || - ((lowpasspos[h] == (bsize - 1)) && (nextread_int == 0)); + bool const extrasample = [=] { + if (reverseread) { + return ((lowpasspos[h] > nextread_int) && ((lowpasspos[h] - 1) == nextread_int)) || + ((lowpasspos[h] == 0) && (nextread_int == (bsize - 1))); + } + return ((lowpasspos[h] < nextread_int) && ((lowpasspos[h] + 1) == nextread_int)) || + ((lowpasspos[h] == (bsize - 1)) && (nextread_int == 0)); + }(); if (extrasample) { heads[h].filter.processToCacheH1(heads[h].buf[lowpasspos[h]]); - lowpasspos[h] = (lowpasspos[h] + 1) % bsize; + lowpasspos[h] = mod_bipolar(lowpasspos[h] + (1 * direction), bsize); } } // it's simpler for highpassing; diff --git a/turntablist/turntablist.cpp b/turntablist/turntablist.cpp index 725d5aa6..c654c8e3 100644 --- a/turntablist/turntablist.cpp +++ b/turntablist/turntablist.cpp @@ -326,7 +326,7 @@ OSStatus Turntablist::SaveState(CFPropertyListRef* outData) CFDictionarySetValue(dict, kTurntablistPreset_AudioFileAliasKey, aliasCFData.get()); } } - DisposeHandle((Handle)aliasHandle); + DisposeHandle(reinterpret_cast(aliasHandle)); } } @@ -418,7 +418,7 @@ OSStatus Turntablist::RestoreState(CFPropertyListRef inData) } } } - DisposeHandle((Handle)aliasHandle); + DisposeHandle(reinterpret_cast(aliasHandle)); } } } @@ -464,121 +464,107 @@ OSStatus Turntablist::PostNotification_AudioFileNotFound(CFStringRef inFileName) } //----------------------------------------------------------------------------- -OSStatus Turntablist::GetPropertyInfo(AudioUnitPropertyID inPropertyID, - AudioUnitScope inScope, AudioUnitElement inElement, - UInt32& outDataSize, bool& outWritable) +long Turntablist::dfx_GetPropertyInfo(dfx::PropertyID inPropertyID, + dfx::Scope inScope, unsigned long inItemIndex, + size_t& outDataSize, dfx::PropertyFlags& outFlags) { - OSStatus status = noErr; - switch (inPropertyID) { case kTurntablistProperty_Play: outDataSize = sizeof(Boolean); - outWritable = true; - break; + outFlags = dfx::kPropertyFlag_Readable | dfx::kPropertyFlag_Writable; + return dfx::kStatus_NoError; case kTurntablistProperty_AudioFile: - if (FSIsFSRefValid(&m_fsAudioFile)) + { + if (!FSIsFSRefValid(&m_fsAudioFile)) { - AliasHandle alias = nullptr; - Size aliasSize = 0; - status = createAudioFileAlias(&alias, &aliasSize); - if (status == noErr) - { - outDataSize = aliasSize; - outWritable = true; - DisposeHandle((Handle)alias); - } + return errFSBadFSRef; } - else + AliasHandle alias = nullptr; + Size aliasSize = 0; + auto const status = createAudioFileAlias(&alias, &aliasSize); + if (status != noErr) { - status = errFSBadFSRef; + return status; } - break; + outDataSize = aliasSize; + outFlags = dfx::kPropertyFlag_Readable | dfx::kPropertyFlag_Writable; + DisposeHandle(reinterpret_cast(alias)); + return dfx::kStatus_NoError; + } default: - status = DfxPlugin::GetPropertyInfo(inPropertyID, inScope, inElement, outDataSize, outWritable); - break; + return DfxPlugin::dfx_GetPropertyInfo(inPropertyID, inScope, inItemIndex, outDataSize, outFlags); } - - return status; } //----------------------------------------------------------------------------- -OSStatus Turntablist::GetProperty(AudioUnitPropertyID inPropertyID, - AudioUnitScope inScope, AudioUnitElement inElement, +long Turntablist::dfx_GetProperty(dfx::PropertyID inPropertyID, + dfx::Scope inScope, unsigned long inItemIndex, void* outData) { - OSStatus status = noErr; - switch (inPropertyID) { case kTurntablistProperty_Play: *static_cast(outData) = m_bPlay; - break; + return dfx::kStatus_NoError; case kTurntablistProperty_AudioFile: - if (FSIsFSRefValid(&m_fsAudioFile)) + { + if (!FSIsFSRefValid(&m_fsAudioFile)) { - AliasHandle alias = nullptr; - Size aliasSize = 0; - status = createAudioFileAlias(&alias, &aliasSize); - if (status == noErr) - { - memcpy(outData, *alias, aliasSize); - DisposeHandle((Handle)alias); - } + return errFSBadFSRef; } - else + AliasHandle alias = nullptr; + Size aliasSize = 0; + auto const status = createAudioFileAlias(&alias, &aliasSize); + if (status != noErr) { - status = errFSBadFSRef; + return status; } - break; + memcpy(outData, *alias, aliasSize); + DisposeHandle(reinterpret_cast(alias)); + return dfx::kStatus_NoError; + } default: - status = DfxPlugin::GetProperty(inPropertyID, inScope, inElement, outData); - break; + return DfxPlugin::dfx_GetProperty(inPropertyID, inScope, inItemIndex, outData); } - - return status; } //----------------------------------------------------------------------------- -OSStatus Turntablist::SetProperty(AudioUnitPropertyID inPropertyID, - AudioUnitScope inScope, AudioUnitElement inElement, - void const* inData, UInt32 inDataSize) +long Turntablist::dfx_SetProperty(dfx::PropertyID inPropertyID, + dfx::Scope inScope, unsigned long inItemIndex, + void const* inData, size_t inDataSize) { - OSStatus status = noErr; - switch (inPropertyID) { case kTurntablistProperty_Play: m_bPlay = *static_cast(inData); playNote(m_bPlay); - break; + return dfx::kStatus_NoError; case kTurntablistProperty_AudioFile: + { + AliasHandle alias = nullptr; + auto status = PtrToHand(inData, (Handle*)(&alias), inDataSize); + if (status != noErr) { - AliasHandle alias = nullptr; - status = PtrToHand(inData, (Handle*)(&alias), inDataSize); - if ((status == noErr) && alias) - { - status = resolveAudioFileAlias(alias); - DisposeHandle((Handle)alias); - } - else - { - status = memFullErr; - } + return status; } - break; + if (!alias) + { + return memFullErr; + } + status = resolveAudioFileAlias(alias); + DisposeHandle(reinterpret_cast(alias)); + return status; + } default: - status = DfxPlugin::SetProperty(inPropertyID, inScope, inElement, inData, inDataSize); - break; + return DfxPlugin::dfx_SetProperty(inPropertyID, inScope, inItemIndex, inData, inDataSize); } - - return status; } //----------------------------------------------------------------------------------------- diff --git a/turntablist/turntablist.h b/turntablist/turntablist.h index fa7efdc5..3c16066c 100644 --- a/turntablist/turntablist.h +++ b/turntablist/turntablist.h @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ -Copyright (c) 2004 bioroid media development & Copyright (C) 2004-2021 Sophia Poirier +Copyright (c) 2004 bioroid media development & Copyright (C) 2004-2022 Sophia Poirier All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. @@ -142,19 +142,16 @@ class Turntablist final : public DfxPlugin void processaudio(float const* const* inAudio, float* const* outAudio, unsigned long inNumFrames) override; void processparameters() override; + long dfx_GetPropertyInfo(dfx::PropertyID inPropertyID, dfx::Scope inScope, unsigned long inItemIndex, + size_t& outDataSize, dfx::PropertyFlags& outFlags) override; + long dfx_GetProperty(dfx::PropertyID inPropertyID, dfx::Scope inScope, unsigned long inItemIndex, + void* outData) override; + long dfx_SetProperty(dfx::PropertyID inPropertyID, dfx::Scope inScope, unsigned long inItemIndex, + void const* inData, size_t inDataSize) override; + OSStatus SaveState(CFPropertyListRef* outData) override; OSStatus RestoreState(CFPropertyListRef inData) override; - OSStatus GetPropertyInfo(AudioUnitPropertyID inPropertyID, - AudioUnitScope inScope, AudioUnitElement inElement, - UInt32& outDataSize, bool& outWritable) override; - OSStatus GetProperty(AudioUnitPropertyID inPropertyID, - AudioUnitScope inScope, AudioUnitElement inElement, - void* outData) override; - OSStatus SetProperty(AudioUnitPropertyID inPropertyID, - AudioUnitScope inScope, AudioUnitElement inElement, - void const* inData, UInt32 inDataSize) override; - OSStatus GetParameterInfo(AudioUnitScope inScope, AudioUnitParameterID inParameterID, AudioUnitParameterInfo& outParameterInfo) override; diff --git a/turntablist/turntablistdef.h b/turntablist/turntablistdef.h index cb1ec07c..215ef727 100644 --- a/turntablist/turntablistdef.h +++ b/turntablist/turntablistdef.h @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------ -Copyright (C) 2004-2021 Sophia Poirier +Copyright (C) 2004-2022 Sophia Poirier This file is part of Turntablist. @@ -32,14 +32,13 @@ To contact the author, use the contact form at http://destroyfx.org/ #define PLUGIN_VERSION_MINOR 1 #define PLUGIN_VERSION_BUGFIX 0 #define PLUGIN_CLASS_NAME Turntablist -#define PLUGIN_ENTRY_POINT "TurntablistEntry" #define TARGET_PLUGIN_USES_MIDI 1 #define TARGET_PLUGIN_IS_INSTRUMENT 1 #define TARGET_PLUGIN_USES_DSPCORE 0 #define TARGET_PLUGIN_HAS_GUI 1 #define PLUGIN_BACKGROUND_IMAGE_FILENAME "background.png" #define PLUGIN_BUNDLE_IDENTIFIER DESTROYFX_BUNDLE_ID_PREFIX PLUGIN_NAME_STRING DFX_BUNDLE_ID_SUFFIX -#define PLUGIN_COPYRIGHT_YEAR_STRING "2004-2021" +#define PLUGIN_COPYRIGHT_YEAR_STRING "2004-2022" #endif diff --git a/windowingstub/windowingstub.cpp b/windowingstub/windowingstub.cpp index 92dc880f..4258a9c3 100644 --- a/windowingstub/windowingstub.cpp +++ b/windowingstub/windowingstub.cpp @@ -4,12 +4,13 @@ #include "windowingstub.h" -#include +#include +#include +#include +#include #if defined(TARGET_API_VST) && TARGET_PLUGIN_HAS_GUI - #ifndef _DFX_WINDOWINGSTUBEDITOR_H #include "windowingstubeditor.hpp" - #endif #endif /* this macro does boring entry point stuff for us */ @@ -23,22 +24,21 @@ PLUGIN::PLUGIN(TARGET_API_BASE_INSTANCE_TYPE inInstance) initparameter_indexed(P_BUFSIZE, {"wsize"}, 9, 9, BUFFERSIZESSIZE, kDfxParamUnit_samples); initparameter_indexed(P_SHAPE, {"wshape"}, WINDOW_TRIANGLE, WINDOW_TRIANGLE, MAX_WINDOWSHAPES); - long i; /* set up values for windowing */ - char bufstr[64]; - for (i=0; i < BUFFERSIZESSIZE; i++) { + for (long i = 0; i < BUFFERSIZESSIZE; i++) { + std::array bufstr {}; if (buffersizes[i] > 1000) - sprintf(bufstr, "%ld,%03ld", buffersizes[i]/1000, buffersizes[i]%1000); + snprintf(bufstr.data(), bufstr.size(), "%ld,%03ld", buffersizes[i] / 1000, buffersizes[i] % 1000); else - sprintf(bufstr, "%ld", buffersizes[i]); - setparametervaluestring(P_BUFSIZE, i, bufstr); + snprintf(bufstr.data(), bufstr.size(), "%ld", buffersizes[i]); + setparametervaluestring(P_BUFSIZE, i, bufstr.data()); } setparametervaluestring(P_SHAPE, WINDOW_TRIANGLE, "linear"); setparametervaluestring(P_SHAPE, WINDOW_ARROW, "arrow"); setparametervaluestring(P_SHAPE, WINDOW_WEDGE, "wedge"); setparametervaluestring(P_SHAPE, WINDOW_COS, "best"); - for (i=NUM_WINDOWSHAPES; i < MAX_WINDOWSHAPES; i++) + for (long i = NUM_WINDOWSHAPES; i < MAX_WINDOWSHAPES; i++) setparametervaluestring(P_SHAPE, i, "???"); long delay_samples = buffersizes[getparameter_i(P_BUFSIZE)]; @@ -49,52 +49,25 @@ PLUGIN::PLUGIN(TARGET_API_BASE_INSTANCE_TYPE inInstance) makepresets(); /* allow MIDI keys to be used to control parameters */ - dfxsettings->setAllowPitchbendEvents(true); - dfxsettings->setAllowNoteEvents(true); + getsettings()->setAllowPitchbendEvents(true); + getsettings()->setAllowNoteEvents(true); #if !TARGET_PLUGIN_USES_DSPCORE addchannelconfig(1, 1); /* mono */ #endif - - #ifdef TARGET_API_VST - /* if you have a GUI, need an Editor class... */ - #if TARGET_PLUGIN_HAS_GUI - editor = new WindowingstubEditor(this); - #endif - #endif -} - -PLUGIN::~PLUGIN() { - -#ifdef TARGET_API_VST - /* VST doesn't have initialize and cleanup methods like Audio Unit does, - so we need to call this manually here */ - do_cleanup(); -#endif } PLUGINCORE::PLUGINCORE(DfxPlugin * inInstance) : DfxPluginCore(inInstance) { /* determine the size of the largest window size */ - long maxframe = 0; - for (int i = 0; i < BUFFERSIZESSIZE; i++) - maxframe = (buffersizes[i] > maxframe) ? buffersizes[i] : maxframe; + auto const maxframe = *std::max_element(std::cbegin(buffersizes), std::cend(buffersizes)); /* add some leeway? */ - in0 = (float*)malloc(maxframe * sizeof (float)); - out0 = (float*)malloc(maxframe * 2 * sizeof (float)); + in0.assign(maxframe, 0.f); + out0.assign(maxframe * 2, 0.f); /* prevmix is only a single third long */ - prevmix = (float*)malloc((maxframe / 2) * sizeof (float)); -} - - -PLUGINCORE::~PLUGINCORE() { - /* windowing buffers */ - free (in0); - free (out0); - - free (prevmix); + prevmix.assign(maxframe / 2, 0.f); } void PLUGINCORE::reset() { @@ -104,24 +77,20 @@ void PLUGINCORE::reset() { bufsize = third * 3; /* set up buffers. Prevmix and first frame of output are always - filled with zeros. XXX memset */ + filled with zeros. */ - for (int i = 0; i < third; i ++) { - prevmix[i] = 0.0f; - } - for (int j = 0; j < framesize; j ++) { - out0[j] = 0.0f; - } + std::fill_n(prevmix.begin(), third, 0.f); + std::fill_n(out0.begin(), framesize, 0.f); /* start input at beginning. Output has a frame of silence. */ insize = 0; outstart = 0; outsize = framesize; - dfxplugin->setlatency_samples(framesize); + getplugin()->setlatency_samples(framesize); /* tail is the same as delay, of course */ - dfxplugin->settailsize_samples(framesize); + getplugin()->settailsize_samples(framesize); } void PLUGINCORE::processparameters() { @@ -132,7 +101,7 @@ void PLUGINCORE::processparameters() { /* this tells the host to call a suspend()-resume() pair, which updates initialDelay value */ if (getparameterchanged(P_BUFSIZE)) - dfxplugin->setlatencychanged(true); + getplugin()->setlatencychanged(true); #endif } @@ -140,10 +109,9 @@ void PLUGINCORE::processparameters() { write your DSP, and it will be always called with the same sample size (as long as the block size parameter stays the same) and automatically overlapped. */ -void PLUGINCORE::processw(float * in, float * out, long samples) { +void PLUGINCORE::processw(float const * in, float * out, long samples) { memmove(out, in, samples * sizeof (float)); - } @@ -172,28 +140,25 @@ void PLUGINCORE::processw(float * in, float * out, long samples) { */ /* to improve: - - use memcpy and arithmetic instead of - sample-by-sample copy - can we use tail of out0 as prevmix, instead of copying? - can we use circular buffers instead of memmoving a lot? (probably not) */ -void PLUGINCORE::process(const float *tin, float *tout, unsigned long samples, bool replacing) { - int z = 0; +void PLUGINCORE::process(float const *tin, float *tout, unsigned long samples) { - for (unsigned long ii = 0; ii < samples; ii++) { + for (unsigned long i = 0; i < samples; i++) { /* copy sample in */ - in0[insize] = tin[ii]; + in0[insize] = tin[i]; insize ++; if (insize == framesize) { /* frame is full! */ /* in0 -> process -> out0(first free space) */ - processw(in0, out0+outstart+outsize, framesize); + processw(in0.data(), out0.data()+outstart+outsize, framesize); float oneDivThird = 1.0f / (float)third; /* apply envelope */ @@ -201,13 +166,13 @@ void PLUGINCORE::process(const float *tin, float *tout, unsigned long samples, b switch(shape) { case WINDOW_TRIANGLE: - for(z = 0; z < third; z++) { + for(int z = 0; z < third; z++) { out0[z+outstart+outsize] *= ((float)z * oneDivThird); out0[z+outstart+outsize+third] *= (1.0f - ((float)z * oneDivThird)); } break; case WINDOW_ARROW: - for(z = 0; z < third; z++) { + for(int z = 0; z < third; z++) { float p = (float)z * oneDivThird; p *= p; out0[z+outstart+outsize] *= p; @@ -215,15 +180,15 @@ void PLUGINCORE::process(const float *tin, float *tout, unsigned long samples, b } break; case WINDOW_WEDGE: - for(z = 0; z < third; z++) { - float p = sqrtf((float)z * oneDivThird); + for(int z = 0; z < third; z++) { + float p = std::sqrt((float)z * oneDivThird); out0[z+outstart+outsize] *= p; out0[z+outstart+outsize+third] *= (1.0f - p); } break; case WINDOW_COS: - for(z = 0; z < third; z ++) { - float p = 0.5f * (-cosf(PI * ((float)z * oneDivThird)) + 1.0f); + for(int z = 0; z < third; z ++) { + float p = 0.5f * (-std::cos(PI * ((float)z * oneDivThird)) + 1.0f); out0[z+outstart+outsize] *= p; out0[z+outstart+outsize+third] *= (1.0f - p); } @@ -235,11 +200,11 @@ void PLUGINCORE::process(const float *tin, float *tout, unsigned long samples, b out0[u+outstart+outsize] += prevmix[u]; /* prevmix becomes out1 */ - memcpy(prevmix, out0 + outstart + outsize + third, third * sizeof (float)); + std::copy_n(std::next(out0.cbegin(), outstart + outsize + third), third, prevmix.begin()); /* copy 2nd third of input over in0 (need to re-use it for next frame), now insize = third */ - memcpy(in0, in0 + third, third * sizeof (float)); + std::copy_n(std::next(in0.cbegin(), third), third, in0.begin()); insize = third; @@ -247,20 +212,14 @@ void PLUGINCORE::process(const float *tin, float *tout, unsigned long samples, b } /* send sample out */ - #ifdef TARGET_API_VST - if (replacing) - #endif - tout[ii] = out0[outstart]; - #ifdef TARGET_API_VST - else tout[ii] += out0[outstart]; - #endif + tout[i] = out0[outstart]; outstart ++; outsize --; /* make sure there is always enough room for a frame in out buffer */ if (outstart == third) { - memmove(out0, out0 + outstart, outsize * sizeof (float)); + memmove(out0.data(), out0.data() + outstart, outsize * sizeof (float)); outstart = 0; } } diff --git a/windowingstub/windowingstub.h b/windowingstub/windowingstub.h index 7f4a6856..f34ea759 100644 --- a/windowingstub/windowingstub.h +++ b/windowingstub/windowingstub.h @@ -1,23 +1,22 @@ /* Windowingstub, starring the Super Destroy FX Windowing System! */ -#ifndef _DFX_WINDOWINGSTUB_H -#define _DFX_WINDOWINGSTUB_H +#pragma once #include "dfxplugin.h" +#include + /* change these for your plugins */ #define PLUGIN Windowingstub -#define NUM_PRESETS 16 +#define PLUGINCORE WindowingstubDSP -#define BUFFERSIZESSIZE 14 -const long buffersizes[BUFFERSIZESSIZE] = { + +static constexpr long buffersizes[] = { 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, }; - - -#define PLUGINCORE WindowingstubDSP +static constexpr long BUFFERSIZESSIZE = std::size(buffersizes); /* the types of window shapes available for smoothity */ enum { WINDOW_TRIANGLE, @@ -34,55 +33,53 @@ enum { P_BUFSIZE, P_SHAPE, }; -class PLUGIN : public DfxPlugin { +class PLUGIN final : public DfxPlugin { public: - PLUGIN(TARGET_API_BASE_INSTANCE_TYPE inInstance); - virtual ~PLUGIN(); + explicit PLUGIN(TARGET_API_BASE_INSTANCE_TYPE inInstance); private: + static constexpr long NUM_PRESETS = 16; + /* set up the built-in presets */ void makepresets(); }; -class PLUGINCORE : public DfxPluginCore { +class PLUGINCORE final : public DfxPluginCore { public: - PLUGINCORE(DfxPlugin * inInstance); - virtual ~PLUGINCORE(); + explicit PLUGINCORE(DfxPlugin * inInstance); - virtual void reset(); - virtual void processparameters(); - virtual void process(const float *in, float *out, unsigned long inNumFrames, bool replacing=true); + void reset() override; + void processparameters() override; + void process(float const * in, float * out, unsigned long inNumFrames) override; - long getwindowsize() { return third; } + long getwindowsize() const noexcept { return third; } private: /* input and output buffers. out is framesize*2 samples long, in is framesize samples long. (for maximum framesize) */ - float * in0, * out0; + std::vector in0, out0; /* bufsize is 3 * third, framesize is 2 * third bufsize is used for outbuf. */ - long bufsize, framesize, third; + long bufsize = 0, framesize = 0, third = 0; - void processw(float * in, float * out, long samples); + void processw(float const * in, float * out, long samples); - int shape; + int shape = 0; /* third-sized tail of previous processed frame. already has mixing envelope applied. */ - float * prevmix; + std::vector prevmix; /* number of samples in in0 */ - int insize; + int insize = 0; /* number of samples and starting position of valid samples in out0 */ - int outsize; - int outstart; + int outsize = 0; + int outstart = 0; }; - -#endif diff --git a/windowingstub/windowingstubdefs.h b/windowingstub/windowingstubdefs.h index 519fdeb1..052e753e 100644 --- a/windowingstub/windowingstubdefs.h +++ b/windowingstub/windowingstubdefs.h @@ -3,15 +3,29 @@ see dfxplugin.h for details. */ +#ifndef DFX_WINDOWING_STUB_DEF_H +#define DFX_WINDOWING_STUB_DEF_H + + +#include "dfxplugin-prefix.h" + #define PLUGIN_NAME_STRING "WINDOWINGSTUB" #define PLUGIN_ID FOURCC('D', 'F', 'w', 's') -#define PLUGIN_VERSION 0x00010100 -#define PLUGIN_ENTRY_POINT "WindowingstubEntry" +#define PLUGIN_VERSION_MAJOR 1 +#define PLUGIN_VERSION_MINOR 1 +#define PLUGIN_VERSION_BUGFIX 0 #define TARGET_PLUGIN_USES_MIDI 1 #define TARGET_PLUGIN_IS_INSTRUMENT 0 #define TARGET_PLUGIN_USES_DSPCORE 1 +#define PLUGIN_COPYRIGHT_YEAR_STRING "2002-2022" + +#define VST_NUM_CHANNELS 2 + #ifndef TARGET_PLUGIN_HAS_GUI #define TARGET_PLUGIN_HAS_GUI 0 #endif + + +#endif