From 5b54b15ba6d4f62a7b696012cecf1f553d0baceb Mon Sep 17 00:00:00 2001 From: xenakios Date: Tue, 21 Nov 2017 00:39:07 +0200 Subject: [PATCH] Finally removed the Control class, the same stuff can be done in the AudioProcessor subclass...The Control source files are still in the repo in case they need to be looked at, but will eventually remove those too. --- Source/PS_Source/PaulStretchControl.cpp | 3 +- Source/PS_Source/PaulStretchControl.h | 3 +- Source/PluginEditor.cpp | 4 +- Source/PluginProcessor.cpp | 161 +++++++++++++++++++----- Source/PluginProcessor.h | 20 ++- paulstretchplugin.jucer | 4 - 6 files changed, 152 insertions(+), 43 deletions(-) diff --git a/Source/PS_Source/PaulStretchControl.cpp b/Source/PS_Source/PaulStretchControl.cpp index 67ffc8b..9783864 100644 --- a/Source/PS_Source/PaulStretchControl.cpp +++ b/Source/PS_Source/PaulStretchControl.cpp @@ -28,7 +28,7 @@ #endif using namespace std; - +#ifdef USEPSCONTROL Control::Control(AudioFormatManager* afm) : m_afm(afm), m_bufferingthread("stretchbufferingthread") { m_stretch_source = std::make_unique(2,m_afm); @@ -619,3 +619,4 @@ void Control::update_process_parameters() //if (player) // player->set_process_parameters(&ppar,&bbpar); }; +#endif diff --git a/Source/PS_Source/PaulStretchControl.h b/Source/PS_Source/PaulStretchControl.h index ef51239..01039ae 100644 --- a/Source/PS_Source/PaulStretchControl.h +++ b/Source/PS_Source/PaulStretchControl.h @@ -54,7 +54,7 @@ public: bool clipFloatOutput = true; std::function completion_callback; }; - +#ifdef USEPSCONTROL class Control { public: @@ -149,3 +149,4 @@ private: double m_last_in_pos = 0.0; std::vector m_bufamounts{ 4096,8192,16384,32768,65536,262144 }; }; +#endif diff --git a/Source/PluginEditor.cpp b/Source/PluginEditor.cpp index 0306233..26fef6f 100644 --- a/Source/PluginEditor.cpp +++ b/Source/PluginEditor.cpp @@ -51,7 +51,7 @@ PaulstretchpluginAudioProcessorEditor::PaulstretchpluginAudioProcessorEditor (Pa }; m_wavecomponent.CursorPosCallback = [this]() { - return processor.m_control->getLivePlayPosition(); + return processor.getStretchSource()->getInfilePositionPercent(); }; m_wavecomponent.ShowFileCacheRange = true; startTimer(1, 100); @@ -98,7 +98,7 @@ void PaulstretchpluginAudioProcessorEditor::timerCallback(int id) m_wavecomponent.setRecordingPosition(processor.getRecordingPositionPercent()); } else m_wavecomponent.setRecordingPosition(-1.0); - String infotext = String(processor.m_control->getPreBufferingPercent(), 1) + " " + String(processor.m_control->getStretchAudioSource()->m_param_change_count); + String infotext = String(processor.getPreBufferingPercent(), 1) + " " + String(processor.getStretchSource()->m_param_change_count); m_info_label.setText(infotext, dontSendNotification); } if (id == 2) diff --git a/Source/PluginProcessor.cpp b/Source/PluginProcessor.cpp index 04dfb83..75d0969 100644 --- a/Source/PluginProcessor.cpp +++ b/Source/PluginProcessor.cpp @@ -30,8 +30,35 @@ void callGUI(AudioProcessor* ap, F&& f, bool async) } } +int get_optimized_updown(int n, bool up) { + int orig_n = n; + while (true) { + n = orig_n; + + while (!(n % 11)) n /= 11; + while (!(n % 7)) n /= 7; + + while (!(n % 5)) n /= 5; + while (!(n % 3)) n /= 3; + while (!(n % 2)) n /= 2; + if (n<2) break; + if (up) orig_n++; + else orig_n--; + if (orig_n<4) return 4; + }; + return orig_n; +}; + +int optimizebufsize(int n) { + int n1 = get_optimized_updown(n, false); + int n2 = get_optimized_updown(n, true); + if ((n - n1)<(n2 - n)) return n1; + else return n2; +}; + //============================================================================== PaulstretchpluginAudioProcessor::PaulstretchpluginAudioProcessor() + : m_bufferingthread("pspluginprebufferthread") #ifndef JucePlugin_PreferredChannelConfigurations : AudioProcessor (BusesProperties() #if ! JucePlugin_IsMidiEffect @@ -48,12 +75,13 @@ PaulstretchpluginAudioProcessor::PaulstretchpluginAudioProcessor() m_recbuffer.clear(); m_afm = std::make_unique(); m_afm->registerBasicFormats(); - m_control = std::make_unique(m_afm.get()); - m_control->setPreBufferAmount(2); - m_control->ppar.pitch_shift.enabled = true; - m_control->ppar.freq_shift.enabled = true; - m_control->setOnsetDetection(0.0); - m_control->getStretchAudioSource()->setLoopingEnabled(true); + m_stretch_source = std::make_unique(2, m_afm.get()); + + setPreBufferAmount(2); + m_ppar.pitch_shift.enabled = true; + m_ppar.freq_shift.enabled = true; + m_stretch_source->setOnsetDetection(0.0); + m_stretch_source->setLoopingEnabled(true); addParameter(new AudioParameterFloat("mainvolume0", "Main volume", -24.0f, 12.0f, -3.0f)); // 0 addParameter(new AudioParameterFloat("stretchamount0", "Stretch amount", 0.1f, 128.0f, 1.0f)); // 1 addParameter(new AudioParameterFloat("fftsize0", "FFT size", 0.0f, 1.0f, 0.7f)); // 2 @@ -67,7 +95,17 @@ PaulstretchpluginAudioProcessor::PaulstretchpluginAudioProcessor() PaulstretchpluginAudioProcessor::~PaulstretchpluginAudioProcessor() { g_activeprocessors.erase(this); - m_control->stopplay(); + m_bufferingthread.stopThread(1000); +} + +void PaulstretchpluginAudioProcessor::setPreBufferAmount(int x) +{ + int temp = jlimit(0, 5, x); + if (temp != m_prebuffer_amount) + { + m_prebuffer_amount = temp; + m_recreate_buffering_source = true; + } } //============================================================================== @@ -132,7 +170,41 @@ void PaulstretchpluginAudioProcessor::changeProgramName (int index, const String { } -//============================================================================== +void PaulstretchpluginAudioProcessor::setFFTSize(double size) +{ + if (m_prebuffer_amount == 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 + int optim = optimizebufsize(m_fft_size_to_use); + m_fft_size_to_use = optim; + m_stretch_source->setFFTSize(optim); + //Logger::writeToLog(String(m_fft_size_to_use)); +} + +void PaulstretchpluginAudioProcessor::startplay(Range playrange, int numoutchans, String& err) +{ + m_stretch_source->setPlayRange(playrange, m_stretch_source->isLoopingEnabled()); + + int bufamt = m_bufamounts[m_prebuffer_amount]; + + if (m_buffering_source != nullptr && numoutchans != m_buffering_source->getNumberOfChannels()) + m_recreate_buffering_source = true; + if (m_recreate_buffering_source == true) + { + m_buffering_source = std::make_unique(m_stretch_source.get(), + m_bufferingthread, false, bufamt, numoutchans, false); + m_recreate_buffering_source = false; + } + if (m_bufferingthread.isThreadRunning() == false) + m_bufferingthread.startThread(); + m_stretch_source->setNumOutChannels(numoutchans); + m_stretch_source->setFFTSize(m_fft_size_to_use); + m_stretch_source->setProcessParameters(&m_ppar); + m_last_outpos_pos = 0.0; + m_last_in_pos = playrange.getStart()*m_stretch_source->getInfileLengthSeconds(); + m_buffering_source->prepareToPlay(1024, 44100.0); +}; + void PaulstretchpluginAudioProcessor::prepareToPlay(double sampleRate, int samplesPerBlock) { if (getNumOutputChannels() != m_cur_num_out_chans) @@ -140,20 +212,18 @@ void PaulstretchpluginAudioProcessor::prepareToPlay(double sampleRate, int sampl if (m_using_memory_buffer == true) { int len = jlimit(100,m_recbuffer.getNumSamples(), m_rec_pos); - m_control->getStretchAudioSource()->setAudioBufferAsInputSource(&m_recbuffer, + m_stretch_source->setAudioBufferAsInputSource(&m_recbuffer, getSampleRate(), len); callGUI(this,[this,len](auto ed) { ed->setAudioBuffer(&m_recbuffer, getSampleRate(), len); },false); } if (m_ready_to_play == false) { - m_control->setFFTSize(0.5); - m_control->update_player_stretch(); - m_control->update_process_parameters(); + setFFTSize(0.5); + m_stretch_source->setProcessParameters(&m_ppar); String err; - m_control->startplay(false, true, - { *getFloatParameter(5),*getFloatParameter(6) }, + startplay({ *getFloatParameter(5),*getFloatParameter(6) }, 2, err); m_cur_num_out_chans = getNumOutputChannels(); m_ready_to_play = true; @@ -231,23 +301,26 @@ void PaulstretchpluginAudioProcessor::processBlock (AudioSampleBuffer& buffer, M m_rec_pos = (m_rec_pos + buffer.getNumSamples()) % recbuflenframes; return; } - - m_control->getStretchAudioSource()->val_MainVolume = (float)*getFloatParameter(0); - m_control->getStretchAudioSource()->setRate(*getFloatParameter(1)); - m_control->getStretchAudioSource()->val_XFadeLen = 0.1; - m_control->setFFTSize(*getFloatParameter(2)); - m_control->ppar.pitch_shift.cents = *getFloatParameter(3) * 100.0; - m_control->ppar.freq_shift.Hz = *getFloatParameter(4); + jassert(m_buffering_source != nullptr); + jassert(m_bufferingthread.isThreadRunning()); + m_stretch_source->val_MainVolume = (float)*getFloatParameter(0); + m_stretch_source->setRate(*getFloatParameter(1)); + m_stretch_source->val_XFadeLen = 0.1; + setFFTSize(*getFloatParameter(2)); + m_ppar.pitch_shift.cents = *getFloatParameter(3) * 100.0; + m_ppar.freq_shift.Hz = *getFloatParameter(4); double t0 = *getFloatParameter(5); double t1 = *getFloatParameter(6); if (t0 > t1) std::swap(t0, t1); if (t1 - t0 < 0.001) t1 = t0 + 0.001; - m_control->getStretchAudioSource()->setPlayRange({ t0,t1 }, true); - m_control->getStretchAudioSource()->setFreezing(getParameter(7)); - m_control->update_process_parameters(); - m_control->processAudio(buffer); + m_stretch_source->setPlayRange({ t0,t1 }, true); + m_stretch_source->setFreezing(getParameter(7)); + m_stretch_source->setProcessParameters(&m_ppar); + + AudioSourceChannelInfo aif(buffer); + m_buffering_source->getNextAudioBlock(aif); } //============================================================================== @@ -341,13 +414,28 @@ double PaulstretchpluginAudioProcessor::getRecordingPositionPercent() String PaulstretchpluginAudioProcessor::setAudioFile(File f) { std::lock_guard locker(m_mutex); - m_control->set_input_file(f, [this,f](String) + auto ai = unique_from_raw(m_afm->createReaderFor(f)); + if (ai != nullptr) { - - }); - m_current_file = f; - m_using_memory_buffer = false; - return String(); + if (ai->numChannels > 32) + { + //MessageManager::callAsync([cb, file]() { cb("Too many channels in file " + file.getFullPathName()); }); + return "Too many channels in file "+f.getFullPathName(); + } + if (ai->bitsPerSample>32) + { + //MessageManager::callAsync([cb, file]() { cb("Too high bit depth in file " + file.getFullPathName()); }); + return "Too high bit depth in file " + f.getFullPathName(); + } + m_current_file = f; + m_using_memory_buffer = false; + m_stretch_source->setAudioFile(f); + return String(); + //MessageManager::callAsync([cb, file]() { cb(String()); }); + + } + + return "Could not open file " + f.getFullPathName(); } Range PaulstretchpluginAudioProcessor::getTimeSelection() @@ -355,11 +443,18 @@ Range PaulstretchpluginAudioProcessor::getTimeSelection() return { *getFloatParameter(5),*getFloatParameter(6) }; } +double PaulstretchpluginAudioProcessor::getPreBufferingPercent() +{ + if (m_buffering_source==nullptr) + return 0.0; + return m_buffering_source->getPercentReady(); +} + void PaulstretchpluginAudioProcessor::finishRecording(int lenrecording) { m_is_recording = false; - m_control->getStretchAudioSource()->setAudioBufferAsInputSource(&m_recbuffer, getSampleRate(), lenrecording); - m_control->getStretchAudioSource()->setPlayRange({ *getFloatParameter(5),*getFloatParameter(6) }, true); + m_stretch_source->setAudioBufferAsInputSource(&m_recbuffer, getSampleRate(), lenrecording); + m_stretch_source->setPlayRange({ *getFloatParameter(5),*getFloatParameter(6) }, true); auto ed = dynamic_cast(getActiveEditor()); if (ed) { diff --git a/Source/PluginProcessor.h b/Source/PluginProcessor.h index 461c026..963b32b 100644 --- a/Source/PluginProcessor.h +++ b/Source/PluginProcessor.h @@ -66,7 +66,8 @@ public: File getAudioFile() { return m_current_file; } Range getTimeSelection(); std::unique_ptr m_afm; - std::unique_ptr m_control; + StretchAudioSource* getStretchSource() { return m_stretch_source.get(); } + double getPreBufferingPercent(); private: @@ -80,7 +81,22 @@ private: int m_cur_num_out_chans = 2; std::mutex m_mutex; File m_current_file; - double m_phase = 0.0; + + + TimeSliceThread m_bufferingthread; + std::unique_ptr m_stretch_source; + std::unique_ptr m_buffering_source; + int m_prebuffer_amount = 1; + bool m_recreate_buffering_source = true; + + int m_fft_size_to_use = 1024; + double m_last_outpos_pos = 0.0; + double m_last_in_pos = 0.0; + std::vector m_bufamounts{ 4096,8192,16384,32768,65536,262144 }; + ProcessParameters m_ppar; + void setPreBufferAmount(int x); + void setFFTSize(double size); + void startplay(Range playrange, int numoutchans, String& err); //============================================================================== JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PaulstretchpluginAudioProcessor) }; diff --git a/paulstretchplugin.jucer b/paulstretchplugin.jucer index 166aeb9..1a5d50c 100644 --- a/paulstretchplugin.jucer +++ b/paulstretchplugin.jucer @@ -22,16 +22,12 @@ - -