| @@ -52,8 +52,9 @@ PaulstretchpluginAudioProcessorEditor::PaulstretchpluginAudioProcessorEditor(Pau | |||
| AudioProcessorParameterWithID* parid = dynamic_cast<AudioProcessorParameterWithID*>(pars[i]); | |||
| jassert(parid); | |||
| bool notifyonlyonrelease = false; | |||
| if (parid->paramID.startsWith("fftsize") || parid->paramID.startsWith("numoutchans")) | |||
| notifyonlyonrelease = true; | |||
| if (parid->paramID.startsWith("fftsize") || parid->paramID.startsWith("numoutchans") | |||
| || parid->paramID.startsWith("numinchans")) | |||
| notifyonlyonrelease = true; | |||
| m_parcomps.push_back(std::make_shared<ParameterComponent>(pars[i],notifyonlyonrelease)); | |||
| int group_id = -1; | |||
| if (i == cpi_harmonicsbw || i == cpi_harmonicsfreq || i == cpi_harmonicsgauss || i == cpi_numharmonics) | |||
| @@ -149,10 +150,13 @@ void PaulstretchpluginAudioProcessorEditor::resized() | |||
| m_parcomps[cpi_freeze]->setBounds(xoffs, yoffs, div - 1, 24); | |||
| xoffs = 1; | |||
| yoffs += 25; | |||
| div = w / 2; | |||
| div = w / 3; | |||
| m_parcomps[cpi_main_volume]->setBounds(xoffs, yoffs, div-1, 24); | |||
| xoffs += div; | |||
| m_parcomps[cpi_num_inchans]->setBounds(xoffs, yoffs, div - 1, 24); | |||
| xoffs += div; | |||
| m_parcomps[cpi_num_outchans]->setBounds(xoffs, yoffs, div-1, 24); | |||
| div = w / 2; | |||
| xoffs = 1; | |||
| yoffs += 25; | |||
| m_parcomps[cpi_fftsize]->setBounds(xoffs, yoffs, div - 1, 24); | |||
| @@ -239,6 +243,7 @@ void PaulstretchpluginAudioProcessorEditor::timerCallback(int id) | |||
| infotext += " (offline rendering)"; | |||
| if (processor.m_playposinfo.isPlaying) | |||
| infotext += " "+String(processor.m_playposinfo.timeInSeconds,1); | |||
| infotext += " " + String(m_wavecomponent.m_image_init_count) + " " + String(m_wavecomponent.m_image_update_count); | |||
| m_info_label.setText(infotext, dontSendNotification); | |||
| m_perfmeter.repaint(); | |||
| } | |||
| @@ -390,8 +395,21 @@ WaveformComponent::~WaveformComponent() | |||
| void WaveformComponent::changeListenerCallback(ChangeBroadcaster * /*cb*/) | |||
| { | |||
| m_waveimage = Image(); | |||
| repaint(); | |||
| jassert(MessageManager::getInstance()->isThisTheMessageThread()); | |||
| m_image_dirty = true; | |||
| //repaint(); | |||
| } | |||
| void WaveformComponent::updateCachedImage() | |||
| { | |||
| Graphics tempg(m_waveimage); | |||
| tempg.fillAll(Colours::black); | |||
| tempg.setColour(Colours::darkgrey); | |||
| double thumblen = m_thumbnail->getTotalLength(); | |||
| m_thumbnail->drawChannels(tempg, { 0,0,getWidth(),getHeight() - m_topmargin }, | |||
| thumblen*m_view_range.getStart(), thumblen*m_view_range.getEnd(), 1.0f); | |||
| m_image_dirty = false; | |||
| ++m_image_update_count; | |||
| } | |||
| void WaveformComponent::paint(Graphics & g) | |||
| @@ -421,16 +439,17 @@ void WaveformComponent::paint(Graphics & g) | |||
| bool m_use_cached_image = true; | |||
| if (m_use_cached_image == true) | |||
| { | |||
| if (m_waveimage.isValid() == false || m_waveimage.getWidth() != getWidth() | |||
| if (m_image_dirty == true || m_waveimage.getWidth() != getWidth() | |||
| || m_waveimage.getHeight() != getHeight() - m_topmargin) | |||
| { | |||
| //Logger::writeToLog("updating cached waveform image"); | |||
| m_waveimage = Image(Image::ARGB, getWidth(), getHeight() - m_topmargin, true); | |||
| Graphics tempg(m_waveimage); | |||
| tempg.fillAll(Colours::black); | |||
| tempg.setColour(Colours::darkgrey); | |||
| m_thumbnail->drawChannels(tempg, { 0,0,getWidth(),getHeight() - m_topmargin }, | |||
| thumblen*m_view_range.getStart(), thumblen*m_view_range.getEnd(), 1.0f); | |||
| if (m_waveimage.getWidth() != getWidth() | |||
| || m_waveimage.getHeight() != getHeight() - m_topmargin) | |||
| { | |||
| m_waveimage = Image(Image::ARGB, getWidth(), getHeight() - m_topmargin, true); | |||
| ++m_image_init_count; | |||
| } | |||
| updateCachedImage(); | |||
| } | |||
| g.drawImage(m_waveimage, 0, m_topmargin, getWidth(), getHeight() - m_topmargin, 0, 0, getWidth(), getHeight() - m_topmargin); | |||
| @@ -115,6 +115,8 @@ public: | |||
| void setViewRange(Range<double> rng); | |||
| Value ShowFileCacheRange; | |||
| void setRecordingPosition(double pos) { m_rec_pos = pos; } | |||
| int m_image_init_count = 0; | |||
| int m_image_update_count = 0; | |||
| private: | |||
| AudioThumbnail* m_thumbnail = nullptr; | |||
| Range<double> m_view_range{ 0.0,1.0 }; | |||
| @@ -128,13 +130,14 @@ private: | |||
| int m_topmargin = 0; | |||
| int getTimeSelectionEdge(int x, int y); | |||
| std::pair<Range<double>, Range<double>> m_file_cached; | |||
| bool m_image_dirty = false; | |||
| Image m_waveimage; | |||
| OpenGLContext m_ogl; | |||
| bool m_use_opengl = false; | |||
| double m_rec_pos = 0.0; | |||
| bool m_lock_timesel_set = false; | |||
| bool m_using_audio_buffer = false; | |||
| void updateCachedImage(); | |||
| }; | |||
| class SpectralChainEditor : public Component | |||
| @@ -140,6 +140,8 @@ PaulstretchpluginAudioProcessor::PaulstretchpluginAudioProcessor() | |||
| addParameter(new AudioParameterFloat("maxcapturelen_0", "Max capture length", 1.0f, 120.0f, 10.0f)); // 29 | |||
| addParameter(new AudioParameterBool("passthrough0", "Pass input through", false)); // 30 | |||
| addParameter(new AudioParameterBool("markdirty0", "Internal (don't use)", false)); // 31 | |||
| m_inchansparam = new AudioParameterInt("numinchans0", "Num input channels", 2, 8, 2); // 32 | |||
| addParameter(m_inchansparam); // 32 | |||
| auto& pars = getParameters(); | |||
| for (const auto& p : pars) | |||
| m_reset_pars.push_back(p->getValue()); | |||
| @@ -394,7 +396,7 @@ void PaulstretchpluginAudioProcessor::prepareToPlay(double sampleRate, int sampl | |||
| ScopedLock locker(m_cs); | |||
| m_cur_sr = sampleRate; | |||
| m_curmaxblocksize = samplesPerBlock; | |||
| m_input_buffer.setSize(2, samplesPerBlock); | |||
| m_input_buffer.setSize(getMainBusNumInputChannels(), samplesPerBlock); | |||
| int numoutchans = *m_outchansparam; | |||
| if (numoutchans != m_cur_num_out_chans) | |||
| m_prebuffering_inited = false; | |||
| @@ -623,7 +625,7 @@ void PaulstretchpluginAudioProcessor::setRecordingEnabled(bool b) | |||
| { | |||
| m_using_memory_buffer = true; | |||
| m_current_file = File(); | |||
| m_recbuffer.setSize(2, m_max_reclen*getSampleRateChecked()+4096,false,false,true); | |||
| m_recbuffer.setSize(getMainBusNumInputChannels(), m_max_reclen*getSampleRateChecked()+4096,false,false,true); | |||
| m_recbuffer.clear(); | |||
| m_rec_pos = 0; | |||
| m_thumb->reset(m_recbuffer.getNumChannels(), getSampleRateChecked(), lenbufframes); | |||
| @@ -57,6 +57,7 @@ const int cpi_pause_enabled = 28; | |||
| const int cpi_max_capture_len = 29; | |||
| const int cpi_passthrough = 30; | |||
| const int cpi_markdirty = 31; | |||
| const int cpi_num_inchans = 32; | |||
| class MyPropertiesFile | |||
| { | |||
| @@ -192,6 +193,7 @@ private: | |||
| void startplay(Range<double> playrange, int numoutchans, int maxBlockSize, String& err); | |||
| SharedResourcePointer<MyThumbCache> m_thumbcache; | |||
| AudioParameterInt* m_outchansparam = nullptr; | |||
| AudioParameterInt* m_inchansparam = nullptr; | |||
| int m_curmaxblocksize = 0; | |||
| double m_cur_sr = 0.0; | |||
| bool m_last_host_playing = false; | |||
| @@ -7,9 +7,10 @@ | |||
| buildVST3="0" buildAU="1" buildAUv3="0" buildRTAS="0" buildAAX="0" | |||
| buildStandalone="1" enableIAA="0" pluginName="PaulXStretch" pluginDesc="PaulXStretch" | |||
| pluginManufacturer="Xenakios" pluginManufacturerCode="XenS" pluginCode="Fn1r" | |||
| pluginChannelConfigs="{2,2},{2,4}, {2,8}" pluginIsSynth="0" pluginWantsMidiIn="0" | |||
| pluginProducesMidiOut="0" pluginIsMidiEffectPlugin="0" pluginEditorRequiresKeys="0" | |||
| pluginAUExportPrefix="paulxstretchAU" pluginRTASCategory="" aaxIdentifier="com.yourcompany.paulstretchplugin" | |||
| pluginChannelConfigs="{2,4}, {2,8}, {8,8}, {2,2}" pluginIsSynth="0" | |||
| pluginWantsMidiIn="0" pluginProducesMidiOut="0" pluginIsMidiEffectPlugin="0" | |||
| pluginEditorRequiresKeys="0" pluginAUExportPrefix="paulxstretchAU" | |||
| pluginRTASCategory="" aaxIdentifier="com.yourcompany.paulstretchplugin" | |||
| pluginAAXCategory="AAX_ePlugInCategory_Dynamics" jucerVersion="5.2.1" | |||
| headerPath=" "> | |||
| <MAINGROUP id="nozXHl" name="PaulXStretch"> | |||
| @@ -8,6 +8,9 @@ Released under GNU General Public License v.2 license. | |||
| History : | |||
| 02-12-2018 1.0.1 | |||
| -Increased maximum number of input channels to 8 | |||
| -GUI performance improvement/bug fix during capture mode | |||
| 02-09-2018 1.0.0 | |||
| -Control/Command click on waveform seeks (if click within active play range) | |||
| -Moved prebuffering amount menu to prebuffering meter (click to show) | |||