separated AAX from normal build so that pffft could be used instead for licensing purposes. prevent file position jump when changing prebuffering. eliminate unecessary fft size calculations

This commit is contained in:
essej 2022-04-26 17:58:45 -04:00
parent cc80d951ea
commit 774031a7a9
13 changed files with 2253 additions and 36 deletions

View File

@ -100,7 +100,7 @@ if (AAX_SDK_PATH)
juce_set_aax_sdk_path (${AAX_SDK_PATH}) juce_set_aax_sdk_path (${AAX_SDK_PATH})
if (APPLE OR (NOT ("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "Win32"))) if (APPLE OR (NOT ("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "Win32")))
list (APPEND FormatsToBuild AAX) list (APPEND AaxFormatsToBuild AAX)
endif() endif()
endif() endif()
@ -135,7 +135,7 @@ set (MacPList "<plist version=\"1.0\">
# the formats specified by the FORMATS arguments. This function accepts many optional arguments. # the formats specified by the FORMATS arguments. This function accepts many optional arguments.
# Check the readme at `docs/CMake API.md` in the JUCE repo for the full list. # Check the readme at `docs/CMake API.md` in the JUCE repo for the full list.
function(sono_add_custom_plugin_target target_name product_name formats is_instrument plugincode) function(sono_add_custom_plugin_target target_name product_name formats is_instrument no_fftw plugincode)
if (is_instrument) if (is_instrument)
set (vst3cats Instrument Network) set (vst3cats Instrument Network)
@ -197,11 +197,23 @@ function(sono_add_custom_plugin_target target_name product_name formats is_instr
) )
set (FFTW_DEPLIBS "")
# platform specific stuff # platform specific stuff
if (APPLE) if (APPLE)
list (APPEND HEADER_INCLUDES deps/mac/include) list (APPEND HEADER_INCLUDES deps/mac/include)
list (APPEND LIB_PATHS ${CMAKE_CURRENT_SOURCE_DIR}/deps/mac/lib) list (APPEND LIB_PATHS ${CMAKE_CURRENT_SOURCE_DIR}/deps/mac/lib)
list (APPEND PlatSourceFiles Source/CrossPlatformUtilsMac.mm) list (APPEND PlatSourceFiles Source/CrossPlatformUtilsMac.mm)
if (no_fftw)
# use vDSP
list (APPEND PLAT_COMPILE_DEFS
PS_USE_VDSP_FFT=1
)
else()
list (APPEND FFTW_DEPLIBS fftw3f)
endif()
elseif (WIN32) elseif (WIN32)
list (APPEND HEADER_INCLUDES deps/windows ../asiosdk/common) list (APPEND HEADER_INCLUDES deps/windows ../asiosdk/common)
list (APPEND PlatSourceFiles Source/CrossPlatformUtilsWindows.cpp) list (APPEND PlatSourceFiles Source/CrossPlatformUtilsWindows.cpp)
@ -225,11 +237,36 @@ function(sono_add_custom_plugin_target target_name product_name formats is_instr
WINVER=0x0601 WINVER=0x0601
_WIN32_WINNT=0x0601 _WIN32_WINNT=0x0601
NOMINMAX) NOMINMAX)
if (no_fftw)
# use pffft
list (APPEND PLAT_COMPILE_DEFS
PS_USE_PFFFT=1
)
else()
list (APPEND FFTW_DEPLIBS
fftw3f
mingwex
gcc
mingw32
msvcrt
)
endif()
else() else()
# Linux # Linux
list (APPEND PlatSourceFiles Source/CrossPlatformUtilsLinux.cpp) list (APPEND PlatSourceFiles Source/CrossPlatformUtilsLinux.cpp)
list ( APPEND PLAT_COMPILE_DEFS list ( APPEND PLAT_COMPILE_DEFS
JUCE_USE_MP3AUDIOFORMAT=1 ) JUCE_USE_MP3AUDIOFORMAT=1 )
if (no_fftw)
# use pffft
list (APPEND PLAT_COMPILE_DEFS
PS_USE_PFFFT=1
)
else()
list (APPEND FFTW_DEPLIBS fftw3f)
endif()
endif() endif()
@ -278,6 +315,8 @@ function(sono_add_custom_plugin_target target_name product_name formats is_instr
Source/WDL/wdltypes.h Source/WDL/wdltypes.h
Source/WDL/denormal.h Source/WDL/denormal.h
Source/WDL/heapbuf.h Source/WDL/heapbuf.h
Source/pffft/pffft.h
Source/pffft/pffft.c
) )
target_sources("${target_name}" PRIVATE target_sources("${target_name}" PRIVATE
@ -369,6 +408,8 @@ function(sono_add_custom_plugin_target target_name product_name formats is_instr
set_target_properties(${target_name}_PSData PROPERTIES FOLDER "Targets") set_target_properties(${target_name}_PSData PROPERTIES FOLDER "Targets")
if (UNIX AND NOT APPLE) if (UNIX AND NOT APPLE)
target_compile_options("${target_name}_PSData" target_compile_options("${target_name}_PSData"
PRIVATE PRIVATE
@ -413,11 +454,7 @@ function(sono_add_custom_plugin_target target_name product_name formats is_instr
${target_name}_PSData ${target_name}_PSData
fftw3f ${FFTW_DEPLIBS}
$<$<PLATFORM_ID:Windows>:mingwex>
$<$<PLATFORM_ID:Windows>:gcc>
$<$<PLATFORM_ID:Windows>:mingw32>
$<$<PLATFORM_ID:Windows>:msvcrt>
PUBLIC PUBLIC
juce::juce_recommended_config_flags juce::juce_recommended_config_flags
@ -428,7 +465,12 @@ function(sono_add_custom_plugin_target target_name product_name formats is_instr
endfunction() endfunction()
# most of the targets # most of the targets
sono_add_custom_plugin_target(PaulXStretch PaulXStretch "${FormatsToBuild}" FALSE "Pxst") sono_add_custom_plugin_target(PaulXStretch PaulXStretch "${FormatsToBuild}" FALSE FALSE "Pxst")
if (AaxFormatsToBuild)
# AAX builds without fftw
sono_add_custom_plugin_target(PaulXStretchAAX PaulXStretch "${AaxFormatsToBuild}" FALSE TRUE "Pxst")
endif()
# Mobile targets # Mobile targets
#sono_add_custom_plugin_target(PaulXStretch "AUv3 Standalone" FALSE "NBus") #sono_add_custom_plugin_target(PaulXStretch "AUv3 Standalone" FALSE "NBus")

View File

@ -58,6 +58,13 @@ FFT::FFT(int nsamples_, bool no_inverse)
m_workReal.resize(nsamples,false); m_workReal.resize(nsamples,false);
m_workImag.resize(nsamples,false); m_workImag.resize(nsamples,false);
//Logger::writeToLog("fftsize: " + String(nsamples) + " log2N: " + String(log2N));
#elif PS_USE_PFFFT
planpffft = pffft_new_setup(nsamples, PFFFT_REAL);
m_work.resize(2*nsamples,false);
//Logger::writeToLog("fftsize: " + String(nsamples) + " log2N: " + String(log2N)); //Logger::writeToLog("fftsize: " + String(nsamples) + " log2N: " + String(log2N));
#else #else
@ -88,6 +95,10 @@ FFT::~FFT()
{ {
#if PS_USE_VDSP_FFT #if PS_USE_VDSP_FFT
vDSP_destroy_fftsetup((FFTSetup)planfft); vDSP_destroy_fftsetup((FFTSetup)planfft);
#elif PS_USE_PFFFT
if (planpffft) {
pffft_destroy_setup(planpffft);
}
#else #else
fftwf_destroy_plan(planfftw); fftwf_destroy_plan(planfftw);
if (planifftw!=nullptr) if (planifftw!=nullptr)
@ -139,6 +150,24 @@ void FFT::smp2freq()
freq[0] = 0.0; freq[0] = 0.0;
#elif PS_USE_PFFFT
const int halfsamples = nsamples / 2;
auto * databuf = data.data();
pffft_transform_ordered(planpffft, smp.data(), databuf, m_work.data(), PFFFT_FORWARD);
data[1] = 0.0f;
// compute magnitude
FloatVectorOperations::multiply(databuf, databuf, nsamples);
for (int k=1, l=2; k < halfsamples; ++k, l+=2) {
freq[k] = sqrt(databuf[l] + databuf[l+1]);
}
freq[0] = 0.0;
#else #else
for (int i=0;i<nsamples;i++) for (int i=0;i<nsamples;i++)
@ -192,7 +221,29 @@ void FFT::freq2smp()
vDSP_vsmul(data.data(), 1, &scale, smp.data(), 1, nsamples); vDSP_vsmul(data.data(), 1, &scale, smp.data(), 1, nsamples);
#elif PS_USE_PFFFT
const int halfsamples = nsamples / 2;
auto * databuf = data.data();
for (int i=1; i < halfsamples; ++i)
{
unsigned int rand = m_randdist(m_randgen);
REALTYPE phase=rand*inv_2p15_2pi;
data[i*2] = freq[i]*cos(phase);
data[i*2+1] = freq[i]*sin(phase);
};
data[0] = data[1] = 0.0;
pffft_transform_ordered(planpffft, databuf, smp.data(), m_work.data(), PFFFT_BACKWARD);
// post scale
float scale = 1.f / nsamples;
FloatVectorOperations::multiply(smp.data(), scale, nsamples);
#else #else
for (int i=1;i<nsamples/2;i++) for (int i=1;i<nsamples/2;i++)
{ {
unsigned int rand = m_randdist(m_randgen); unsigned int rand = m_randdist(m_randgen);
@ -204,8 +255,11 @@ void FFT::freq2smp()
data[0]=data[nsamples/2+1]=data[nsamples/2]=0.0; data[0]=data[nsamples/2+1]=data[nsamples/2]=0.0;
fftwf_execute(planifftw); fftwf_execute(planifftw);
for (int i=0;i<nsamples;i++)
smp[i]=data[i]/nsamples; // post scale
float scale = 1.f / nsamples;
FloatVectorOperations::multiply(smp.data(), data.data(), scale, nsamples);
#endif #endif
}; };

View File

@ -26,11 +26,19 @@
#define PS_USE_VDSP_FFT 0 #define PS_USE_VDSP_FFT 0
#endif #endif
#ifndef PS_USE_PFFFT
#define PS_USE_PFFFT 0
#endif
#if PS_USE_VDSP_FFT #if PS_USE_VDSP_FFT
#elif PS_USE_PFFFT
#include "../pffft/pffft.h"
#else #else
#include "fftw3.h" #include "fftw3.h"
#endif #endif
#include "../JuceLibraryCode/JuceHeader.h" #include "../JuceLibraryCode/JuceHeader.h"
#include <random> #include <random>
#include <type_traits> #include <type_traits>
@ -107,6 +115,11 @@ private:
buf = (float*)malloc(size*sizeof(float)); buf = (float*)malloc(size*sizeof(float));
else else
buf = (double*)malloc(size * sizeof(double)); buf = (double*)malloc(size * sizeof(double));
#elif PS_USE_PFFFT
if constexpr (std::is_same<T,float>::value)
buf = (float*)pffft_aligned_malloc(size*sizeof(float));
else
buf = (double*)pffft_aligned_malloc(size * sizeof(double));
#else #else
if constexpr (std::is_same<T,float>::value) if constexpr (std::is_same<T,float>::value)
buf = (float*)fftwf_malloc(size*sizeof(float)); buf = (float*)fftwf_malloc(size*sizeof(float));
@ -123,6 +136,11 @@ private:
free(buf); free(buf);
else else
free(buf); free(buf);
#elif PS_USE_PFFFT
if constexpr (std::is_same<T, float>::value)
pffft_aligned_free(buf);
else
pffft_aligned_free(buf);
#else #else
if constexpr (std::is_same<T, float>::value) if constexpr (std::is_same<T, float>::value)
fftwf_free(buf); fftwf_free(buf);
@ -159,6 +177,9 @@ class FFT
int log2N; int log2N;
FFTWBuffer<REALTYPE> m_workReal; FFTWBuffer<REALTYPE> m_workReal;
FFTWBuffer<REALTYPE> m_workImag; FFTWBuffer<REALTYPE> m_workImag;
#elif PS_USE_PFFFT
PFFFT_Setup *planpffft = nullptr;
FFTWBuffer<REALTYPE> m_work;
#else #else
fftwf_plan planfftw,planifftw; fftwf_plan planfftw,planifftw;
#endif #endif

View File

@ -599,6 +599,14 @@ void StretchAudioSource::playDrySound(const AudioSourceChannelInfo & bufferToFil
bufs[i][j + bufferToFill.startSample] = maingain * m_resampler_outbuf[j*m_num_outchans + i]; bufs[i][j + bufferToFill.startSample] = maingain * m_resampler_outbuf[j*m_num_outchans + i];
} }
double StretchAudioSource::getLastSourcePositionPercent()
{
if (m_inputfile == nullptr || m_inputfile->info.nsamples == 0)
return 0.0;
return (1.0/m_inputfile->info.nsamples)*m_last_filepos;
}
double StretchAudioSource::getInfilePositionPercent() double StretchAudioSource::getInfilePositionPercent()
{ {
if (m_inputfile == nullptr || m_inputfile->info.nsamples == 0) if (m_inputfile == nullptr || m_inputfile->info.nsamples == 0)
@ -686,6 +694,8 @@ void StretchAudioSource::setFFTSize(int size, bool force)
jassert(size>0); jassert(size>0);
if (force || (m_xfadetask.state == 0 && (m_process_fftsize == 0 || size != m_process_fftsize))) if (force || (m_xfadetask.state == 0 && (m_process_fftsize == 0 || size != m_process_fftsize)))
{ {
DBG("Using FFT size: " << size);
ScopedLock locker(m_cs); ScopedLock locker(m_cs);
if (m_xfadetask.buffer.getNumChannels() < m_num_outchans) if (m_xfadetask.buffer.getNumChannels() < m_num_outchans)
{ {
@ -705,6 +715,7 @@ void StretchAudioSource::setFFTSize(int size, bool force)
initObjects(); initObjects();
} }
++m_param_change_count; ++m_param_change_count;
} }
} }

View File

@ -100,6 +100,8 @@ public:
double getLastSeekPos() const { return m_seekpos; } double getLastSeekPos() const { return m_seekpos; }
CriticalSection* getMutex() { return &m_cs; } CriticalSection* getMutex() { return &m_cs; }
int64_t getLastSourcePosition() const { return m_last_filepos; } int64_t getLastSourcePosition() const { return m_last_filepos; }
double getLastSourcePositionPercent();
int m_prebuffersize = 0; int m_prebuffersize = 0;
void setSpectralOrderPreset(int id); void setSpectralOrderPreset(int id);

View File

@ -288,7 +288,7 @@ inline String secondsToString2(double secs)
result.preallocateBytes(32); result.preallocateBytes(32);
bool empty = true; bool empty = true;
if ((int)rt.inHours()>0) if ((int)rt.inHours()>0)
result << String((int)rt.inHours() % 24).paddedLeft('0', empty ? 1 : 2) << ':'; result << String((int)rt.inHours()).paddedLeft('0', empty ? 1 : 2) << ':';
result << String((int)rt.inMinutes() % 60).paddedLeft('0', 2) << ':'; result << String((int)rt.inMinutes() % 60).paddedLeft('0', 2) << ':';
result << String((int)rt.inSeconds() % 60).paddedLeft('0', 2); result << String((int)rt.inSeconds() % 60).paddedLeft('0', 2);
auto millis = (int)rt.inMilliseconds() % 1000; auto millis = (int)rt.inMilliseconds() % 1000;

View File

@ -554,7 +554,7 @@ void PaulstretchpluginAudioProcessorEditor::showRenderDialog()
int prefh = jmin(contentraw->getPreferredHeight(), getHeight() - 10); int prefh = jmin(contentraw->getPreferredHeight(), getHeight() - 10);
contentraw->setSize(prefw, prefh); contentraw->setSize(prefw, prefh);
std::unique_ptr<Component> content(contentraw); std::unique_ptr<Component> content(contentraw);
auto & cb = CallOutBox::launchAsynchronously(std::move(content), m_render_button.getBounds(), this); auto & cb = CallOutBox::launchAsynchronously(std::move(content), m_render_button.getBounds(), this, false);
cb.setDismissalMouseClicksAreAlwaysConsumed(true); cb.setDismissalMouseClicksAreAlwaysConsumed(true);
} }
@ -1247,7 +1247,11 @@ void PaulstretchpluginAudioProcessorEditor::showSettingsMenu()
void PaulstretchpluginAudioProcessorEditor::showAbout() void PaulstretchpluginAudioProcessorEditor::showAbout()
{ {
String fftlib; String fftlib;
#if !PS_USE_VDSP_FFT #if PS_USE_VDSP_FFT
fftlib = "vDSP";
#elif PS_USE_PFFFT
fftlib = "pffft";
#else
fftlib = fftwf_version; fftlib = fftwf_version;
#endif #endif
String juceversiontxt = String("JUCE ") + String(JUCE_MAJOR_VERSION) + "." + String(JUCE_MINOR_VERSION); String juceversiontxt = String("JUCE ") + String(JUCE_MAJOR_VERSION) + "." + String(JUCE_MINOR_VERSION);
@ -1272,11 +1276,17 @@ void PaulstretchpluginAudioProcessorEditor::showAbout()
if (fftlib.isNotEmpty()) if (fftlib.isNotEmpty())
text += String("Using ") + fftlib + String(" for FFT\n\n"); text += String("Using ") + fftlib + String(" for FFT\n\n");
#if !JUCE_IOS #if !JUCE_IOS
if (PluginHostType::getPluginLoadedAs() == AudioProcessor::wrapperType_AAX) {
text += juceversiontxt + String("\n\n");
}
else {
text += juceversiontxt + String(" used under the GPL license.\n\n"); text += juceversiontxt + String(" used under the GPL license.\n\n");
}
#endif #endif
// text += String("GPL licensed source code for this plugin at : https://bitbucket.org/xenakios/paulstretchplugin/overview\n"); text += String("GPL licensed source code at : https://github.com/essej/paulxstretch\n");
if (host.type != juce::PluginHostType::UnknownHost) { if (host.type != juce::PluginHostType::UnknownHost) {
text += String("Running in : ") + host.getHostDescription()+ String("\n"); text += String("Running in : ") + host.getHostDescription()+ String("\n");
@ -1300,7 +1310,7 @@ void PaulstretchpluginAudioProcessorEditor::showAbout()
wrap->setSize(jmin(defWidth, getWidth() - 20), jmin(defHeight, getHeight() - 24)); wrap->setSize(jmin(defWidth, getWidth() - 20), jmin(defHeight, getHeight() - 24));
auto bounds = getLocalArea(nullptr, m_settings_button.getScreenBounds()); auto bounds = getLocalArea(nullptr, m_settings_button.getScreenBounds());
auto & cb = CallOutBox::launchAsynchronously(std::move(wrap), bounds, this); auto & cb = CallOutBox::launchAsynchronously(std::move(wrap), bounds, this, false);
cb.setDismissalMouseClicksAreAlwaysConsumed(true); cb.setDismissalMouseClicksAreAlwaysConsumed(true);
} }
@ -1496,6 +1506,7 @@ void WaveformComponent::paint(Graphics & g)
g.setColour(Colours::white); g.setColour(Colours::white);
if (CursorPosCallback) if (CursorPosCallback)
{ {
/*
double timediff = (Time::getMillisecondCounterHiRes() - m_last_source_pos_update_time)*(1.0/m_sas->getRate()); double timediff = (Time::getMillisecondCounterHiRes() - m_last_source_pos_update_time)*(1.0/m_sas->getRate());
double curpos = ((double)m_last_source_pos / m_sas->getOutputSamplerate()); double curpos = ((double)m_last_source_pos / m_sas->getOutputSamplerate());
double prebufoffset = (double)m_sas->m_prebuffersize / m_sas->getOutputSamplerate(); double prebufoffset = (double)m_sas->m_prebuffersize / m_sas->getOutputSamplerate();
@ -1503,6 +1514,7 @@ void WaveformComponent::paint(Graphics & g)
curpos = 1.0 / m_sas->getInfileLengthSeconds()*(curpos+(timediff / 1000.0)); curpos = 1.0 / m_sas->getInfileLengthSeconds()*(curpos+(timediff / 1000.0));
//g.fillRect(normalizedToViewX<int>(curpos), m_topmargin, 1, getHeight() - m_topmargin); //g.fillRect(normalizedToViewX<int>(curpos), m_topmargin, 1, getHeight() - m_topmargin);
//g.drawText(String(curpos), 1, 30, 200,30, Justification::left); //g.drawText(String(curpos), 1, 30, 200,30, Justification::left);
*/
g.fillRect(normalizedToViewX<int>(CursorPosCallback()), m_topmargin, 1, getHeight() - m_topmargin); g.fillRect(normalizedToViewX<int>(CursorPosCallback()), m_topmargin, 1, getHeight() - m_topmargin);
} }
if (m_rec_pos >= 0.0) if (m_rec_pos >= 0.0)

View File

@ -20,8 +20,11 @@ int get_optimized_updown(int n, bool up) {
while (true) { while (true) {
n = orig_n; n = orig_n;
#if PS_USE_VDSP_FFT
// only powers of two allowed if using VDSP FFT // only powers of two allowed if using VDSP FFT
#if !PS_USE_VDSP_FFT #elif PS_USE_PFFFT
// only powers of two allowed if using pffft
#else
while (!(n % 11)) n /= 11; while (!(n % 11)) n /= 11;
while (!(n % 7)) n /= 7; while (!(n % 7)) n /= 7;
while (!(n % 5)) n /= 5; while (!(n % 5)) n /= 5;
@ -320,8 +323,10 @@ void PaulstretchpluginAudioProcessor::setPreBufferAmount(int x)
m_cur_num_out_chans = *m_outchansparam; m_cur_num_out_chans = *m_outchansparam;
//Logger::writeToLog("Switching to use " + String(m_cur_num_out_chans) + " out channels"); //Logger::writeToLog("Switching to use " + String(m_cur_num_out_chans) + " out channels");
String err; String err;
setFFTSize(*getFloatParameter(cpi_fftsize), true);
startplay({ *getFloatParameter(cpi_soundstart),*getFloatParameter(cpi_soundend) }, startplay({ *getFloatParameter(cpi_soundstart),*getFloatParameter(cpi_soundend) },
m_cur_num_out_chans, m_curmaxblocksize, err); m_cur_num_out_chans, m_curmaxblocksize, err);
m_stretch_source->seekPercent(m_stretch_source->getLastSourcePositionPercent());
m_prebuffering_inited = true; m_prebuffering_inited = true;
} }
@ -545,16 +550,21 @@ void PaulstretchpluginAudioProcessor::parameterGestureChanged(int parameterIndex
{ {
} }
void PaulstretchpluginAudioProcessor::setFFTSize(double size, bool force) void PaulstretchpluginAudioProcessor::setFFTSize(float size, bool force)
{ {
if (fabsf(m_last_fftsizeparamval - size) > 0.00001f || force) {
if (m_prebuffer_amount == 5) if (m_prebuffer_amount == 5)
m_fft_size_to_use = pow(2, 7.0 + size * 14.5); m_fft_size_to_use = pow(2, 7.0 + size * 14.5);
else m_fft_size_to_use = pow(2, 7.0 + size * 10.0); // chicken out from allowing huge FFT sizes if not enough prebuffering else m_fft_size_to_use = pow(2, 7.0 + size * 10.0); // chicken out from allowing huge FFT sizes if not enough prebuffering
int optim = optimizebufsize(m_fft_size_to_use); int optim = optimizebufsize(m_fft_size_to_use);
m_fft_size_to_use = optim; m_fft_size_to_use = optim;
m_stretch_source->setFFTSize(optim, force); m_stretch_source->setFFTSize(optim, force);
m_last_fftsizeparamval = size;
//Logger::writeToLog(String(m_fft_size_to_use)); //Logger::writeToLog(String(m_fft_size_to_use));
} }
}
void PaulstretchpluginAudioProcessor::startplay(Range<double> playrange, int numoutchans, int maxBlockSize, String& err) void PaulstretchpluginAudioProcessor::startplay(Range<double> playrange, int numoutchans, int maxBlockSize, String& err)
{ {
@ -575,7 +585,7 @@ void PaulstretchpluginAudioProcessor::startplay(Range<double> playrange, int num
m_bufferingthread.startThread(); m_bufferingthread.startThread();
} }
m_stretch_source->setNumOutChannels(numoutchans); m_stretch_source->setNumOutChannels(numoutchans);
m_stretch_source->setFFTSize(m_fft_size_to_use); m_stretch_source->setFFTSize(m_fft_size_to_use, true);
m_stretch_source->setProcessParameters(&m_ppar); m_stretch_source->setProcessParameters(&m_ppar);
m_stretch_source->m_prebuffersize = bufamt; m_stretch_source->m_prebuffersize = bufamt;
@ -854,7 +864,7 @@ void PaulstretchpluginAudioProcessor::prepareToPlay(double sampleRate, int sampl
} }
if (m_prebuffering_inited == false) if (m_prebuffering_inited == false)
{ {
setFFTSize(*getFloatParameter(cpi_fftsize)); setFFTSize(*getFloatParameter(cpi_fftsize), true);
m_stretch_source->setProcessParameters(&m_ppar); m_stretch_source->setProcessParameters(&m_ppar);
m_stretch_source->setFFTWindowingType(1); m_stretch_source->setFFTWindowingType(1);
String err; String err;

View File

@ -276,6 +276,7 @@ private:
double m_smoothed_prebuffer_ready = 0.0; double m_smoothed_prebuffer_ready = 0.0;
SignalSmoother m_prebufsmoother; SignalSmoother m_prebufsmoother;
int m_fft_size_to_use = 1024; int m_fft_size_to_use = 1024;
float m_last_fftsizeparamval = -1.0f;
double m_last_outpos_pos = 0.0; double m_last_outpos_pos = 0.0;
double m_last_in_pos = 0.0; double m_last_in_pos = 0.0;
std::vector<int> m_bufamounts{ 4096,8192,16384,32768,65536,262144 }; std::vector<int> m_bufamounts{ 4096,8192,16384,32768,65536,262144 };
@ -283,7 +284,7 @@ private:
int mPluginWindowWidth = 820; int mPluginWindowWidth = 820;
int mPluginWindowHeight = 710; int mPluginWindowHeight = 710;
void setFFTSize(double size, bool force=false); void setFFTSize(float size, bool force=false);
void startplay(Range<double> playrange, int numoutchans, int maxBlockSize, String& err); void startplay(Range<double> playrange, int numoutchans, int maxBlockSize, String& err);
SharedResourcePointer<MyThumbCache> m_thumbcache; SharedResourcePointer<MyThumbCache> m_thumbcache;
AudioParameterInt* m_outchansparam = nullptr; AudioParameterInt* m_outchansparam = nullptr;

1884
Source/pffft/pffft.c Normal file

File diff suppressed because it is too large Load Diff

177
Source/pffft/pffft.h Normal file
View File

@ -0,0 +1,177 @@
/* Copyright (c) 2013 Julien Pommier ( pommier@modartt.com )
Based on original fortran 77 code from FFTPACKv4 from NETLIB,
authored by Dr Paul Swarztrauber of NCAR, in 1985.
As confirmed by the NCAR fftpack software curators, the following
FFTPACKv5 license applies to FFTPACKv4 sources. My changes are
released under the same terms.
FFTPACK license:
http://www.cisl.ucar.edu/css/software/fftpack5/ftpk.html
Copyright (c) 2004 the University Corporation for Atmospheric
Research ("UCAR"). All rights reserved. Developed by NCAR's
Computational and Information Systems Laboratory, UCAR,
www.cisl.ucar.edu.
Redistribution and use of the Software in source and binary forms,
with or without modification, is permitted provided that the
following conditions are met:
- Neither the names of NCAR's Computational and Information Systems
Laboratory, the University Corporation for Atmospheric Research,
nor the names of its sponsors or contributors may be used to
endorse or promote products derived from this Software without
specific prior written permission.
- Redistributions of source code must retain the above copyright
notices, this list of conditions, and the disclaimer below.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions, and the disclaimer below in the
documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
SOFTWARE.
*/
/*
PFFFT : a Pretty Fast FFT.
This is basically an adaptation of the single precision fftpack
(v4) as found on netlib taking advantage of SIMD instruction found
on cpus such as intel x86 (SSE1), powerpc (Altivec), and arm (NEON).
For architectures where no SIMD instruction is available, the code
falls back to a scalar version.
Restrictions:
- 1D transforms only, with 32-bit single precision.
- supports only transforms for inputs of length N of the form
N=(2^a)*(3^b)*(5^c), a >= 5, b >=0, c >= 0 (32, 48, 64, 96, 128,
144, 160, etc are all acceptable lengths). Performance is best for
128<=N<=8192.
- all (float*) pointers in the functions below are expected to
have an "simd-compatible" alignment, that is 16 bytes on x86 and
powerpc CPUs.
You can allocate such buffers with the functions
pffft_aligned_malloc / pffft_aligned_free (or with stuff like
posix_memalign..)
*/
#ifndef PFFFT_H
#define PFFFT_H
#include <stddef.h> // for size_t
#ifdef __cplusplus
extern "C" {
#endif
/* opaque struct holding internal stuff (precomputed twiddle factors)
this struct can be shared by many threads as it contains only
read-only data.
*/
typedef struct PFFFT_Setup PFFFT_Setup;
/* direction of the transform */
typedef enum { PFFFT_FORWARD, PFFFT_BACKWARD } pffft_direction_t;
/* type of transform */
typedef enum { PFFFT_REAL, PFFFT_COMPLEX } pffft_transform_t;
/*
prepare for performing transforms of size N -- the returned
PFFFT_Setup structure is read-only so it can safely be shared by
multiple concurrent threads.
*/
PFFFT_Setup *pffft_new_setup(int N, pffft_transform_t transform);
void pffft_destroy_setup(PFFFT_Setup *);
/*
Perform a Fourier transform , The z-domain data is stored in the
most efficient order for transforming it back, or using it for
convolution. If you need to have its content sorted in the
"usual" way, that is as an array of interleaved complex numbers,
either use pffft_transform_ordered , or call pffft_zreorder after
the forward fft, and before the backward fft.
Transforms are not scaled: PFFFT_BACKWARD(PFFFT_FORWARD(x)) = N*x.
Typically you will want to scale the backward transform by 1/N.
The 'work' pointer should point to an area of N (2*N for complex
fft) floats, properly aligned. If 'work' is NULL, then stack will
be used instead (this is probably the best strategy for small
FFTs, say for N < 16384).
input and output may alias.
*/
void pffft_transform(PFFFT_Setup *setup, const float *input, float *output, float *work, pffft_direction_t direction);
/*
Similar to pffft_transform, but makes sure that the output is
ordered as expected (interleaved complex numbers). This is
similar to calling pffft_transform and then pffft_zreorder.
input and output may alias.
*/
void pffft_transform_ordered(PFFFT_Setup *setup, const float *input, float *output, float *work, pffft_direction_t direction);
/*
call pffft_zreorder(.., PFFFT_FORWARD) after pffft_transform(...,
PFFFT_FORWARD) if you want to have the frequency components in
the correct "canonical" order, as interleaved complex numbers.
(for real transforms, both 0-frequency and half frequency
components, which are real, are assembled in the first entry as
F(0)+i*F(n/2+1). Note that the original fftpack did place
F(n/2+1) at the end of the arrays).
input and output should not alias.
*/
void pffft_zreorder(PFFFT_Setup *setup, const float *input, float *output, pffft_direction_t direction);
/*
Perform a multiplication of the frequency components of dft_a and
dft_b and accumulate them into dft_ab. The arrays should have
been obtained with pffft_transform(.., PFFFT_FORWARD) and should
*not* have been reordered with pffft_zreorder (otherwise just
perform the operation yourself as the dft coefs are stored as
interleaved complex numbers).
the operation performed is: dft_ab += (dft_a * fdt_b)*scaling
The dft_a, dft_b and dft_ab pointers may alias.
*/
void pffft_zconvolve_accumulate(PFFFT_Setup *setup, const float *dft_a, const float *dft_b, float *dft_ab, float scaling);
/*
the float buffers must have the correct alignment (16-byte boundary
on intel and powerpc). This function may be used to obtain such
correctly aligned buffers.
*/
void *pffft_aligned_malloc(size_t nb_bytes);
void pffft_aligned_free(void *);
/* return 4 or 1 wether support SSE/Altivec instructions was enable when building pffft.c */
int pffft_simd_size(void);
#ifdef __cplusplus
}
#endif
#endif // PFFFT_H

View File

@ -12,7 +12,7 @@ MAINNAME="PaulXStretch"
#BUILDDIR=../Builds/MacOSX/build/Release #BUILDDIR=../Builds/MacOSX/build/Release
BUILDDIR=../build/${MAINNAME}_artefacts/Release BUILDDIR=../build/${MAINNAME}_artefacts/Release
#INSTBUILDDIR=../build/${MAINNAME}Inst_artefacts/Release AAXBUILDDIR=../build/${MAINNAME}AAX_artefacts/Release
rm -rf ${MAINNAME} rm -rf ${MAINNAME}
@ -24,7 +24,8 @@ mkdir -p ${MAINNAME}
cp -pLRv ${BUILDDIR}/Standalone/${MAINNAME}.app ${MAINNAME}/ cp -pLRv ${BUILDDIR}/Standalone/${MAINNAME}.app ${MAINNAME}/
cp -pLRv ${BUILDDIR}/AU/${MAINNAME}.component ${MAINNAME}/ cp -pLRv ${BUILDDIR}/AU/${MAINNAME}.component ${MAINNAME}/
cp -pLRv ${BUILDDIR}/VST3/${MAINNAME}.vst3 ${MAINNAME}/ cp -pLRv ${BUILDDIR}/VST3/${MAINNAME}.vst3 ${MAINNAME}/
cp -pRHv ${BUILDDIR}/AAX/${MAINNAME}.aaxplugin ${MAINNAME}/
cp -pRHv ${AAXBUILDDIR}/AAX/${MAINNAME}.aaxplugin ${MAINNAME}/
#cp -pLRv ${BUILDDIR}/${MAINNAME}.app ${MAINNAME}/ #cp -pLRv ${BUILDDIR}/${MAINNAME}.app ${MAINNAME}/
#cp -pLRv ${BUILDDIR}/${MAINNAME}.component ${MAINNAME}/ #cp -pLRv ${BUILDDIR}/${MAINNAME}.component ${MAINNAME}/

View File

@ -17,6 +17,7 @@ if [ -z "$CERTFILE" ] ; then
fi fi
BUILDDIR="../build/${BASENAME}_artefacts/Release" BUILDDIR="../build/${BASENAME}_artefacts/Release"
AAXBUILDDIR="../build/${BASENAME}AAX_artefacts/Release"
BUILDDIR32="../build32/${BASENAME}_artefacts/Release" BUILDDIR32="../build32/${BASENAME}_artefacts/Release"
#BUILDDIR='../Builds/VisualStudio2019/x64/Release' #BUILDDIR='../Builds/VisualStudio2019/x64/Release'
@ -30,7 +31,8 @@ mkdir -p ${BASENAME}/Plugins/AAX
cp -v ${BUILDDIR}/Standalone/${BASENAME}.exe ${BASENAME}/ cp -v ${BUILDDIR}/Standalone/${BASENAME}.exe ${BASENAME}/
cp -pHLRv ${BUILDDIR}/VST3/${BASENAME}.vst3 ${BASENAME}/Plugins/VST3/ cp -pHLRv ${BUILDDIR}/VST3/${BASENAME}.vst3 ${BASENAME}/Plugins/VST3/
#cp -v ${BUILDDIR}/VST/SonoBus.dll ${BASENAME}/Plugins/ #cp -v ${BUILDDIR}/VST/SonoBus.dll ${BASENAME}/Plugins/
cp -pHLRv ${BUILDDIR}/AAX/${BASENAME}.aaxplugin ${BASENAME}/Plugins/AAX/
cp -pHLRv ${AAXBUILDDIR}/AAX/${BASENAME}.aaxplugin ${BASENAME}/Plugins/AAX/
#mkdir -p SonoBus/Plugins32 #mkdir -p SonoBus/Plugins32