@@ -173,21 +173,6 @@ PaulstretchpluginAudioProcessorEditor::PaulstretchpluginAudioProcessorEditor(Pau | |||||
}; | }; | ||||
m_spec_order_ed.ModuleOrderOrEnabledChangedCallback = [this]() | m_spec_order_ed.ModuleOrderOrEnabledChangedCallback = [this]() | ||||
{ | { | ||||
/* | |||||
const auto& specord = processor.getStretchSource()->getSpectrumProcessOrder(); | |||||
for (int i = 0; i < specord.size(); ++i) | |||||
{ | |||||
int grtofind = specord[i].m_index; | |||||
for (int j = 0; j < m_parcomps.size(); ++j) | |||||
{ | |||||
int gid = m_parcomps[j]->m_group_id; | |||||
if (gid == grtofind) | |||||
{ | |||||
m_parcomps[j]->setEnabled(specord[i].m_enabled); | |||||
} | |||||
} | |||||
} | |||||
*/ | |||||
processor.setDirty(); | processor.setDirty(); | ||||
}; | }; | ||||
@@ -244,8 +229,9 @@ PaulstretchpluginAudioProcessorEditor::PaulstretchpluginAudioProcessorEditor(Pau | |||||
m_wavefilter_tab.addTab("Waveform", Colours::white, m_wave_container, true); | m_wavefilter_tab.addTab("Waveform", Colours::white, m_wave_container, true); | ||||
m_wavefilter_tab.addTab("Ratio mixer", Colours::white, &m_ratiomixeditor, false); | m_wavefilter_tab.addTab("Ratio mixer", Colours::white, &m_ratiomixeditor, false); | ||||
m_wavefilter_tab.addTab("Free filter", Colours::white, &m_free_filter_component, false); | m_wavefilter_tab.addTab("Free filter", Colours::white, &m_free_filter_component, false); | ||||
addAndMakeVisible(&m_wavefilter_tab); | |||||
m_wavefilter_tab.addTab("Spectrum", Colours::white, &m_sonogram, false); | |||||
addAndMakeVisible(&m_wavefilter_tab); | |||||
setSize (1200, 320+14*25); | setSize (1200, 320+14*25); | ||||
startTimer(1, 100); | startTimer(1, 100); | ||||
startTimer(2, 1000); | startTimer(2, 1000); | ||||
@@ -265,6 +265,122 @@ private: | |||||
}; | }; | ||||
class SimpleFFTComponent : public Component, | |||||
private Timer | |||||
{ | |||||
public: | |||||
SimpleFFTComponent() : | |||||
forwardFFT(fftOrder), | |||||
spectrogramImage(Image::RGB, 512, 512, true) | |||||
{ | |||||
setOpaque(true); | |||||
startTimerHz(60); | |||||
} | |||||
~SimpleFFTComponent() | |||||
{ | |||||
} | |||||
void addAudioBlock(const AudioBuffer<float>& bufferToFill) | |||||
{ | |||||
if (bufferToFill.getNumChannels() > 0) | |||||
{ | |||||
const auto* channelData = bufferToFill.getReadPointer(0); | |||||
for (auto i = 0; i < bufferToFill.getNumSamples(); ++i) | |||||
pushNextSampleIntoFifo(channelData[i]); | |||||
} | |||||
} | |||||
void resized() override | |||||
{ | |||||
spectrogramImage = Image(Image::RGB, getWidth(), getHeight(), true); | |||||
} | |||||
void paint(Graphics& g) override | |||||
{ | |||||
g.fillAll(Colours::black); | |||||
g.setOpacity(1.0f); | |||||
g.drawImage(spectrogramImage, getLocalBounds().toFloat()); | |||||
} | |||||
void timerCallback() override | |||||
{ | |||||
if (nextFFTBlockReady) | |||||
{ | |||||
drawNextLineOfSpectrogram(); | |||||
nextFFTBlockReady = false; | |||||
repaint(); | |||||
} | |||||
} | |||||
void pushNextSampleIntoFifo(float sample) noexcept | |||||
{ | |||||
// if the fifo contains enough data, set a flag to say | |||||
// that the next line should now be rendered.. | |||||
if (fifoIndex == fftSize) | |||||
{ | |||||
if (!nextFFTBlockReady) | |||||
{ | |||||
zeromem(fftData, sizeof(fftData)); | |||||
memcpy(fftData, fifo, sizeof(fifo)); | |||||
nextFFTBlockReady = true; | |||||
} | |||||
fifoIndex = 0; | |||||
} | |||||
fifo[fifoIndex++] = sample; | |||||
} | |||||
void drawNextLineOfSpectrogram() | |||||
{ | |||||
auto rightHandEdge = spectrogramImage.getWidth() - 1; | |||||
auto imageHeight = spectrogramImage.getHeight(); | |||||
// first, shuffle our image leftwards by 1 pixel.. | |||||
spectrogramImage.moveImageSection(0, 0, 1, 0, rightHandEdge, imageHeight); | |||||
// then render our FFT data.. | |||||
forwardFFT.performFrequencyOnlyForwardTransform(fftData); | |||||
// find the range of values produced, so we can scale our rendering to | |||||
// show up the detail clearly | |||||
auto maxLevel = FloatVectorOperations::findMinAndMax(fftData, fftSize / 2); | |||||
for (auto y = 1; y < imageHeight; ++y) | |||||
{ | |||||
auto skewedProportionY = 1.0f - std::exp(std::log(y / (float)imageHeight) * 0.2f); | |||||
auto fftDataIndex = jlimit(0, fftSize / 2, (int)(skewedProportionY * fftSize / 2)); | |||||
auto level = jmap(fftData[fftDataIndex], 0.0f, jmax(maxLevel.getEnd(), 1e-5f), 0.0f, 1.0f); | |||||
spectrogramImage.setPixelAt(rightHandEdge, y, Colour::fromHSV(level, 1.0f, level, 1.0f)); | |||||
} | |||||
} | |||||
enum | |||||
{ | |||||
fftOrder = 10, | |||||
fftSize = 1 << fftOrder | |||||
}; | |||||
private: | |||||
dsp::FFT forwardFFT; | |||||
Image spectrogramImage; | |||||
float fifo[fftSize]; | |||||
float fftData[8 * fftSize]; | |||||
int fifoIndex = 0; | |||||
bool nextFFTBlockReady = false; | |||||
}; | |||||
class AudioFilePreviewComponent : public FilePreviewComponent | class AudioFilePreviewComponent : public FilePreviewComponent | ||||
{ | { | ||||
public: | public: | ||||
@@ -319,7 +435,7 @@ public: | |||||
void chooseFile(); | void chooseFile(); | ||||
void showRenderDialog(); | void showRenderDialog(); | ||||
void executeModalMenuAction(int menuid, int actionid); | void executeModalMenuAction(int menuid, int actionid); | ||||
SimpleFFTComponent m_sonogram; | |||||
private: | private: | ||||
PaulstretchpluginAudioProcessor& processor; | PaulstretchpluginAudioProcessor& processor; | ||||
uptrvec<ParameterComponent> m_parcomps; | uptrvec<ParameterComponent> m_parcomps; | ||||
@@ -337,6 +453,7 @@ private: | |||||
zoom_scrollbar m_zs; | zoom_scrollbar m_zs; | ||||
RatioMixerEditor m_ratiomixeditor{ 8 }; | RatioMixerEditor m_ratiomixeditor{ 8 }; | ||||
FreeFilterComponent m_free_filter_component; | FreeFilterComponent m_free_filter_component; | ||||
MyTabComponent m_wavefilter_tab; | MyTabComponent m_wavefilter_tab; | ||||
Component* m_wave_container=nullptr; | Component* m_wave_container=nullptr; | ||||
void showAbout(); | void showAbout(); | ||||
@@ -811,6 +811,11 @@ void PaulstretchpluginAudioProcessor::processBlock (AudioSampleBuffer& buffer, M | |||||
{ | { | ||||
buffer.clear(); | buffer.clear(); | ||||
} | } | ||||
auto ed = dynamic_cast<PaulstretchpluginAudioProcessorEditor*>(getActiveEditor()); | |||||
if (ed != nullptr) | |||||
{ | |||||
ed->m_sonogram.addAudioBlock(buffer); | |||||
} | |||||
} | } | ||||
//============================================================================== | //============================================================================== | ||||
@@ -11,7 +11,7 @@ | |||||
pluginWantsMidiIn="0" pluginProducesMidiOut="0" pluginIsMidiEffectPlugin="0" | pluginWantsMidiIn="0" pluginProducesMidiOut="0" pluginIsMidiEffectPlugin="0" | ||||
pluginEditorRequiresKeys="0" pluginAUExportPrefix="paulxstretchAU" | pluginEditorRequiresKeys="0" pluginAUExportPrefix="paulxstretchAU" | ||||
aaxIdentifier="com.yourcompany.paulstretchplugin" pluginAAXCategory="2" | aaxIdentifier="com.yourcompany.paulstretchplugin" pluginAAXCategory="2" | ||||
jucerVersion="5.3.2" headerPath=" " pluginFormats="buildVST,buildVST3,buildAU,buildStandalone"> | |||||
jucerVersion="5.4.1" headerPath=" " pluginFormats="buildVST,buildVST3,buildAU,buildStandalone"> | |||||
<MAINGROUP id="nozXHl" name="PaulXStretch"> | <MAINGROUP id="nozXHl" name="PaulXStretch"> | ||||
<GROUP id="{03DA6B32-F666-FF60-F168-4385D0847058}" name="Source"> | <GROUP id="{03DA6B32-F666-FF60-F168-4385D0847058}" name="Source"> | ||||
<FILE id="RanaVV" name="RenderSettingsComponent.cpp" compile="1" resource="0" | <FILE id="RanaVV" name="RenderSettingsComponent.cpp" compile="1" resource="0" | ||||
@@ -50,8 +50,7 @@ | |||||
</GROUP> | </GROUP> | ||||
</MAINGROUP> | </MAINGROUP> | ||||
<EXPORTFORMATS> | <EXPORTFORMATS> | ||||
<XCODE_MAC targetFolder="Builds/MacOSX" extraLinkerFlags="/usr/local/Cellar/fftw/3.3.8/lib/libfftw3f.a " | |||||
vst3Folder=""> | |||||
<XCODE_MAC targetFolder="Builds/MacOSX" extraLinkerFlags="/usr/local/Cellar/fftw/3.3.8/lib/libfftw3f.a "> | |||||
<CONFIGURATIONS> | <CONFIGURATIONS> | ||||
<CONFIGURATION name="Debug" enablePluginBinaryCopyStep="1" isDebug="1" optimisation="1" | <CONFIGURATION name="Debug" enablePluginBinaryCopyStep="1" isDebug="1" optimisation="1" | ||||
linkTimeOptimisation="0" targetName="PaulXStretch" headerPath="Source/PS_Source Source/WDL /Users/teemu/codeprojects/JUCE/modules/vst2.x " | linkTimeOptimisation="0" targetName="PaulXStretch" headerPath="Source/PS_Source Source/WDL /Users/teemu/codeprojects/JUCE/modules/vst2.x " | ||||
@@ -77,10 +76,11 @@ | |||||
<MODULEPATH id="juce_audio_processors" path="../JUCE/modules"/> | <MODULEPATH id="juce_audio_processors" path="../JUCE/modules"/> | ||||
<MODULEPATH id="juce_audio_plugin_client" path="../JUCE/modules"/> | <MODULEPATH id="juce_audio_plugin_client" path="../JUCE/modules"/> | ||||
<MODULEPATH id="juce_audio_utils" path="../JUCE/modules"/> | <MODULEPATH id="juce_audio_utils" path="../JUCE/modules"/> | ||||
<MODULEPATH id="juce_dsp" path="../gitrepos/JUCE/modules"/> | |||||
</MODULEPATHS> | </MODULEPATHS> | ||||
</XCODE_MAC> | </XCODE_MAC> | ||||
<VS2017 targetFolder="Builds/VisualStudio2017" externalLibraries="C:\ProgrammingProjects\fftw-3.3.6-pl2\fftw-3.3-libs\x64\Static-Release\libfftwf-3.3.lib" | <VS2017 targetFolder="Builds/VisualStudio2017" externalLibraries="C:\ProgrammingProjects\fftw-3.3.6-pl2\fftw-3.3-libs\x64\Static-Release\libfftwf-3.3.lib" | ||||
extraDefs="" vst3Folder=""> | |||||
extraDefs=""> | |||||
<CONFIGURATIONS> | <CONFIGURATIONS> | ||||
<CONFIGURATION name="Debug" winWarningLevel="4" generateManifest="1" winArchitecture="x64" | <CONFIGURATION name="Debug" winWarningLevel="4" generateManifest="1" winArchitecture="x64" | ||||
debugInformationFormat="ProgramDatabase" enablePluginBinaryCopyStep="1" | debugInformationFormat="ProgramDatabase" enablePluginBinaryCopyStep="1" | ||||
@@ -107,6 +107,7 @@ | |||||
<MODULEPATH id="juce_audio_processors" path="../JUCE/modules"/> | <MODULEPATH id="juce_audio_processors" path="../JUCE/modules"/> | ||||
<MODULEPATH id="juce_audio_plugin_client" path="../JUCE/modules"/> | <MODULEPATH id="juce_audio_plugin_client" path="../JUCE/modules"/> | ||||
<MODULEPATH id="juce_audio_utils" path="../JUCE/modules"/> | <MODULEPATH id="juce_audio_utils" path="../JUCE/modules"/> | ||||
<MODULEPATH id="juce_dsp" path="../gitrepos/JUCE/modules"/> | |||||
</MODULEPATHS> | </MODULEPATHS> | ||||
</VS2017> | </VS2017> | ||||
<LINUX_MAKE targetFolder="Builds/LinuxMakefile" extraDefs="JUCE_WEB_BROWSER=0 "> | <LINUX_MAKE targetFolder="Builds/LinuxMakefile" extraDefs="JUCE_WEB_BROWSER=0 "> | ||||
@@ -130,6 +131,7 @@ | |||||
<MODULEPATH id="juce_audio_processors" path="../JUCE/modules"/> | <MODULEPATH id="juce_audio_processors" path="../JUCE/modules"/> | ||||
<MODULEPATH id="juce_audio_plugin_client" path="../JUCE/modules"/> | <MODULEPATH id="juce_audio_plugin_client" path="../JUCE/modules"/> | ||||
<MODULEPATH id="juce_audio_utils" path="../JUCE/modules"/> | <MODULEPATH id="juce_audio_utils" path="../JUCE/modules"/> | ||||
<MODULEPATH id="juce_dsp" path="../gitrepos/JUCE/modules"/> | |||||
</MODULEPATHS> | </MODULEPATHS> | ||||
</LINUX_MAKE> | </LINUX_MAKE> | ||||
</EXPORTFORMATS> | </EXPORTFORMATS> | ||||
@@ -144,6 +146,7 @@ | |||||
<MODULE id="juce_core" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/> | <MODULE id="juce_core" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/> | ||||
<MODULE id="juce_cryptography" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/> | <MODULE id="juce_cryptography" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/> | ||||
<MODULE id="juce_data_structures" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/> | <MODULE id="juce_data_structures" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/> | ||||
<MODULE id="juce_dsp" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/> | |||||
<MODULE id="juce_events" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/> | <MODULE id="juce_events" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/> | ||||
<MODULE id="juce_graphics" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/> | <MODULE id="juce_graphics" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/> | ||||
<MODULE id="juce_gui_basics" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/> | <MODULE id="juce_gui_basics" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/> | ||||