update to support juce 6.1. added mute audio while processing capture option. added a mac specific priority fix. use async popup menus and browsers where needed.

This commit is contained in:
essej 2022-04-02 12:45:02 -04:00
parent 86f1a8c594
commit 8c4a20ecd6
10 changed files with 188 additions and 81 deletions

View File

@ -0,0 +1,14 @@
// SPDX-License-Identifier: GPLv3-or-later WITH Appstore-exception
// Copyright (C) 2020 Jesse Chappell
#pragma once
void getSafeAreaInsets(void * component, float & top, float & bottom, float & left, float & right);
#if JUCE_MAC
void disableAppNap();
#endif

View File

@ -0,0 +1,46 @@
// SPDX-License-Identifier: GPLv3-or-later WITH Appstore-exception
// Copyright (C) 2020 Jesse Chappell
#include "CrossPlatformUtils.h"
//#include "../JuceLibraryCode/JuceHeader.h"
#define JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED 1
#include <juce_core/system/juce_TargetPlatform.h>
#if JUCE_MAC
//#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
void getSafeAreaInsets(void * component, float & top, float & bottom, float & left, float & right)
{
top = bottom = left = right = 0;
}
void disableAppNap() {
// Does the App Nap API even exist on this Mac?
if ([[NSProcessInfo processInfo] respondsToSelector:@selector(beginActivityWithOptions:reason:)]) {
// If the API exists, then disable App Nap...
// From NSProcessInfo.h:
// NSActivityIdleSystemSleepDisabled = (1ULL << 20),
// NSActivityUserInitiated = (0x00FFFFFFULL | NSActivityIdleSystemSleepDisabled),
// NSActivityLatencyCritical = 0xFF00000000ULL
uint64_t options = (0x00FFFFFFULL | (1ULL << 20)) | 0xFF00000000ULL;
// NSActivityLatencyCritical | NSActivityUserInitiated
[[NSProcessInfo processInfo] beginActivityWithOptions:options
reason:@"avoiding audio hiccups and reducing latency"];
}
}
#endif

View File

@ -157,7 +157,7 @@ void StretchAudioSource::setAudioBufferAsInputSource(AudioBuffer<float>* buf, in
ScopedLock locker(m_cs);
m_inputfile->setAudioBuffer(buf, sr, len);
m_seekpos = 0.0;
m_audiobuffer_is_source = true;
m_curfile = File();
if (m_playrange.isEmpty())
setPlayRange({ 0.0,1.0 });
@ -512,6 +512,7 @@ String StretchAudioSource::setAudioFile(File file)
{
m_curfile = file;
m_firstbuffer = true;
m_audiobuffer_is_source = false;
return String();
}
return "Could not open file";

View File

@ -99,6 +99,7 @@ public:
void setLoopingEnabled(bool b);
void setMaxLoops(int64_t numloops) { m_maxloops = numloops; }
void setAudioBufferAsInputSource(AudioBuffer<float>* buf, int sr, int len);
bool isAudioBufferInputSource() const { return m_audiobuffer_is_source; }
void setMainVolume(double decibels);
double getMainVolume() const { return m_main_volume; }
//void setSpectralModulesEnabled(const std::array<AudioParameterBool*, 9>& params);
@ -148,6 +149,7 @@ private:
bool m_stream_end_reached = false;
int64_t m_output_silence_counter = 0;
File m_curfile;
bool m_audiobuffer_is_source = false;
int64_t m_maxloops = 0;
std::unique_ptr<WDL_Resampler> m_resampler;
std::vector<double> m_resampler_outbuf;

View File

@ -21,6 +21,8 @@ www.gnu.org/licenses
#include <array>
#include "RenderSettingsComponent.h"
#include "CrossPlatformUtils.h"
static void handleSettingsMenuModalCallback(int choice, PaulstretchpluginAudioProcessorEditor* ed)
{
ed->executeModalMenuAction(0,choice);
@ -242,7 +244,15 @@ PaulstretchpluginAudioProcessorEditor::PaulstretchpluginAudioProcessorEditor(Pau
startTimer(2, 1000);
startTimer(3, 200);
m_wavecomponent.startTimer(100);
setResizeLimits(320, 14*25 + 120, 40000, 4000);
setResizable(true, !JUCEApplicationBase::isStandaloneApp());
#if JUCE_MAC
disableAppNap();
#endif
}
PaulstretchpluginAudioProcessorEditor::~PaulstretchpluginAudioProcessorEditor()
@ -277,6 +287,10 @@ void PaulstretchpluginAudioProcessorEditor::executeModalMenuAction(int menuid, i
{
toggleBool(processor.m_mute_while_capturing);
}
if (r == 10)
{
toggleBool(processor.m_mute_processed_while_capturing);
}
if (r == 4)
{
processor.resetParameters();
@ -537,7 +551,8 @@ void PaulstretchpluginAudioProcessorEditor::showSettingsMenu()
m_settings_menu.addItem(5, "Load file with plugin state", true, processor.m_load_file_with_state);
m_settings_menu.addItem(1, "Play when host transport running", true, processor.m_play_when_host_plays);
m_settings_menu.addItem(2, "Capture when host transport running", true, processor.m_capture_when_host_plays);
m_settings_menu.addItem(8, "Mute audio while capturing", true, processor.m_mute_while_capturing);
m_settings_menu.addItem(8, "Mute passthrough while capturing", true, processor.m_mute_while_capturing);
m_settings_menu.addItem(10, "Mute processed audio output while capturing", true, processor.m_mute_processed_while_capturing);
m_settings_menu.addItem(9, "Save captured audio to disk", true, processor.m_save_captured_audio);
int capturelen = *processor.getFloatParameter(cpi_max_capture_len);
PopupMenu capturelenmenu;
@ -1362,14 +1377,18 @@ void PerfMeterComponent::mouseDown(const MouseEvent & ev)
bufferingmenu.addItem(103, "Large", true, curbufamount == 3);
bufferingmenu.addItem(104, "Very large", true, curbufamount == 4);
bufferingmenu.addItem(105, "Huge", true, curbufamount == 5);
int r = bufferingmenu.show();
if (r >= 100 && r < 200)
{
if (r == 100)
m_proc->m_use_backgroundbuffering = false;
if (r > 100)
m_proc->setPreBufferAmount(r - 100);
}
auto opts = PopupMenu::Options();
bufferingmenu.showMenuAsync(opts, [this](int r) {
if (r >= 100 && r < 200)
{
if (r == 100)
m_proc->m_use_backgroundbuffering = false;
if (r > 100)
m_proc->setPreBufferAmount(r - 100);
}
});
}
void PerfMeterComponent::timerCallback()

View File

@ -58,7 +58,8 @@ inline AudioParameterFloat* make_floatpar(String id, String name, float minv, fl
//==============================================================================
PaulstretchpluginAudioProcessor::PaulstretchpluginAudioProcessor(bool is_stand_alone_offline)
: m_is_stand_alone_offline(is_stand_alone_offline), m_bufferingthread("pspluginprebufferthread")
: AudioProcessor(PaulstretchpluginAudioProcessor::BusesProperties().withInput("Main In", AudioChannelSet::stereo(), true).withOutput ("Main Out", AudioChannelSet::stereo(), true)),
m_is_stand_alone_offline(is_stand_alone_offline), m_bufferingthread("pspluginprebufferthread")
{
m_filechoose_callback = [this](const FileChooser& chooser)
{
@ -214,6 +215,8 @@ PaulstretchpluginAudioProcessor::PaulstretchpluginAudioProcessor(bool is_stand_a
PaulstretchpluginAudioProcessor::~PaulstretchpluginAudioProcessor()
{
stopTimer(1);
//Logger::writeToLog("PaulX AudioProcessor destroyed");
if (m_thumb)
m_thumb->removeAllChangeListeners();
@ -281,7 +284,7 @@ ValueTree PaulstretchpluginAudioProcessor::getStateTree(bool ignoreoptions, bool
paramtree.setProperty("loadfilewithstate", m_load_file_with_state, nullptr);
storeToTreeProperties(paramtree, nullptr, "playwhenhostrunning", m_play_when_host_plays,
"capturewhenhostrunning", m_capture_when_host_plays,"savecapturedaudio",m_save_captured_audio,
"mutewhilecapturing",m_mute_while_capturing);
"mutewhilecapturing",m_mute_while_capturing, "muteprocwhilecapturing",m_mute_processed_while_capturing);
}
storeToTreeProperties(paramtree, nullptr, "tabaindex", m_cur_tab_index);
storeToTreeProperties(paramtree, nullptr, "waveviewrange", m_wave_view_range);
@ -301,7 +304,7 @@ void PaulstretchpluginAudioProcessor::setStateFromTree(ValueTree tree)
m_load_file_with_state = tree.getProperty("loadfilewithstate", true);
getFromTreeProperties(tree, "playwhenhostrunning", m_play_when_host_plays,
"capturewhenhostrunning", m_capture_when_host_plays,"mutewhilecapturing",m_mute_while_capturing,
"savecapturedaudio",m_save_captured_audio);
"savecapturedaudio",m_save_captured_audio, "muteprocwhilecapturing",m_mute_processed_while_capturing);
getFromTreeProperties(tree, "tabaindex", m_cur_tab_index);
if (tree.hasProperty("numspectralstagesb"))
{
@ -526,6 +529,8 @@ void PaulstretchpluginAudioProcessor::saveCaptureBuffer()
inchans, 32, {}, 0));
if (writer != nullptr)
{
outstream.release(); // the writer takes ownership
auto sourcebuffer = getStretchSource()->getSourceAudioBuffer();
jassert(sourcebuffer->getNumChannels() == inchans);
jassert(sourcebuffer->getNumSamples() > 0);
@ -596,28 +601,34 @@ String PaulstretchpluginAudioProcessor::offlineRender(OfflineRenderParams render
{
//delete outstream;
jassert(false);
}
AudioBuffer<float> renderbuffer{ numoutchans, blocksize };
MidiBuffer dummymidi;
double outlensecs = sc->getOutputDurationSecondsForRange(sc->getPlayRange(),sc->getFFTSize());
int64_t outlenframes = outlensecs * outsr;
int64_t outcounter{ 0 };
m_offline_render_state = 0;
m_offline_render_cancel_requested = false;
while (outcounter < outlenframes)
{
if (m_offline_render_cancel_requested == true)
break;
processor->processBlock(renderbuffer, dummymidi);
int64 framesToWrite = std::min<int64>(blocksize, outlenframes - outcounter);
writer->writeFromAudioSampleBuffer(renderbuffer, 0, framesToWrite);
outcounter += blocksize;
m_offline_render_state = 100.0 / outlenframes * outcounter;
}
m_offline_render_state = 200;
Logger::writeToLog("Rendered ok!");
m_offline_render_state = 200;
Logger::writeToLog("Render failed, could not open file!");
return;
} else {
outstream.release(); // the writer takes ownership
AudioBuffer<float> renderbuffer{ numoutchans, blocksize };
MidiBuffer dummymidi;
double outlensecs = sc->getOutputDurationSecondsForRange(sc->getPlayRange(),sc->getFFTSize());
int64_t outlenframes = outlensecs * outsr;
int64_t outcounter{ 0 };
m_offline_render_state = 0;
m_offline_render_cancel_requested = false;
while (outcounter < outlenframes)
{
if (m_offline_render_cancel_requested == true)
break;
processor->processBlock(renderbuffer, dummymidi);
int64 framesToWrite = std::min<int64>(blocksize, outlenframes - outcounter);
writer->writeFromAudioSampleBuffer(renderbuffer, 0, framesToWrite);
outcounter += blocksize;
m_offline_render_state = 100.0 / outlenframes * outcounter;
}
m_offline_render_state = 200;
Logger::writeToLog("Rendered ok!");
}
};
std::thread th(rendertask);
th.detach();
@ -768,7 +779,9 @@ void PaulstretchpluginAudioProcessor::processBlock (AudioSampleBuffer& buffer, M
m_recorded_range = { 0, m_rec_count };
if (m_mute_while_capturing == true)
buffer.clear();
return;
if (m_mute_processed_while_capturing == true)
return;
}
jassert(m_buffering_source != nullptr);
jassert(m_bufferingthread.isThreadRunning());

View File

@ -207,6 +207,7 @@ public:
bool m_play_when_host_plays = false;
bool m_capture_when_host_plays = false;
bool m_mute_while_capturing = false;
bool m_mute_processed_while_capturing = false;
bool m_use_backgroundbuffering = true;
void resetParameters();
void setPreBufferAmount(int x);

View File

@ -186,10 +186,9 @@ void RenderSettingsComponent::buttonClicked (Button* buttonThatWasClicked)
FileChooser myChooser("Please select audio file to render...",
lastexportfolder,
"*.wav");
if (myChooser.browseForFileToSave(true))
{
outfileNameEditor.setText(myChooser.getResult().getFullPathName(), dontSendNotification);
}
myChooser.launchAsync(FileBrowserComponent::saveMode, [this](const FileChooser &chooser) {
outfileNameEditor.setText(chooser.getResult().getFullPathName(), dontSendNotification);
});
}
}

View File

@ -225,34 +225,40 @@ void EnvelopeComponent::mouseDown(const MouseEvent & ev)
if (ev.mods.isRightButtonDown() == true)
{
PopupMenu menu;
PopupMenu::Options opts;
menu.addItem(1, "Reset");
menu.addItem(2, "Invert");
menu.addItem(3, "Wrap envelope X transform", true, m_envelope->m_transform_wrap_x);
menu.addItem(4, "Envelope Y random linear interpolation", true, m_envelope->m_transform_y_random_linear_interpolation);
int r = menu.show();
if (r == 1)
{
ScopedLock locker(*m_cs);
m_envelope->ResetEnvelope();
}
if (r == 2)
{
for (int i = 0; i < m_envelope->GetNumPoints(); ++i)
{
double val = 1.0 - m_envelope->GetNodeAtIndex(i).pt_y;
m_envelope->GetNodeAtIndex(i).pt_y = val;
}
}
if (r == 3)
{
toggleBool(m_envelope->m_transform_wrap_x);
}
if (r == 4)
{
toggleBool(m_envelope->m_transform_y_random_linear_interpolation);
}
repaint();
return;
auto callback = [this] (int r) {
if (r == 1)
{
ScopedLock locker(*m_cs);
m_envelope->ResetEnvelope();
}
if (r == 2)
{
for (int i = 0; i < m_envelope->GetNumPoints(); ++i)
{
double val = 1.0 - m_envelope->GetNodeAtIndex(i).pt_y;
m_envelope->GetNodeAtIndex(i).pt_y = val;
}
}
if (r == 3)
{
toggleBool(m_envelope->m_transform_wrap_x);
}
if (r == 4)
{
toggleBool(m_envelope->m_transform_y_random_linear_interpolation);
}
repaint();
};
menu.showMenuAsync(opts, callback);
return;
}
m_node_to_drag = find_hot_envelope_point(ev.x, ev.y);
m_mouse_down = true;

View File

@ -1,20 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<JUCERPROJECT id="fn1Rg8" name="PaulXStretch" displaySplashScreen="0" reportAppUsage="0"
splashScreenColour="Dark" projectType="audioplug" version="1.0.0"
splashScreenColour="Dark" projectType="audioplug" version="1.2.5"
bundleIdentifier="com.xenakios.paulxstretch" includeBinaryInAppConfig="1"
cppLanguageStandard="latest" companyCopyright="" buildVST="1"
cppLanguageStandard="latest" companyCopyright="" buildVST="0"
buildVST3="1" 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}, {8,8} " pluginIsSynth="0"
pluginWantsMidiIn="0" pluginProducesMidiOut="0" pluginIsMidiEffectPlugin="0"
pluginEditorRequiresKeys="0" pluginAUExportPrefix="paulxstretchAU"
pluginIsSynth="0" pluginWantsMidiIn="0" pluginProducesMidiOut="0"
pluginIsMidiEffectPlugin="0" pluginEditorRequiresKeys="0" pluginAUExportPrefix="paulxstretchAU"
aaxIdentifier="com.yourcompany.paulstretchplugin" pluginAAXCategory="2"
headerPath="&#10;&#10;" pluginFormats="buildVST,buildVST3,buildAU,buildStandalone"
headerPath="&#10;&#10;" pluginFormats="buildAU,buildStandalone,buildVST3"
jucerFormatVersion="1">
<MAINGROUP id="nozXHl" name="PaulXStretch">
<GROUP id="{03DA6B32-F666-FF60-F168-4385D0847058}" name="Source">
<FILE id="zvau5B" name="CrossPlatformUtils.h" compile="0" resource="0"
file="Source/CrossPlatformUtils.h"/>
<FILE id="fjYsFD" name="CrossPlatformUtilsMac.mm" compile="1" resource="0"
file="Source/CrossPlatformUtilsMac.mm"/>
<FILE id="RanaVV" name="RenderSettingsComponent.cpp" compile="1" resource="0"
file="Source/RenderSettingsComponent.cpp"/>
<FILE id="Mz5aVb" name="envelope_component.cpp" compile="1" resource="0"
@ -51,19 +54,22 @@
</GROUP>
</MAINGROUP>
<EXPORTFORMATS>
<XCODE_MAC targetFolder="Builds/MacOSX" extraLinkerFlags="/usr/local/Cellar/fftw/3.3.8/lib/libfftw3f.a&#10;">
<XCODE_MAC targetFolder="Builds/MacOSX" externalLibraries="fftw3f" microphonePermissionNeeded="1"
microphonePermissionsText="This application requires audio input to capture live audio for processing"
hardenedRuntime="1" hardenedRuntimeOptions="com.apple.security.device.audio-input"
xcodeValidArchs="arm64,x86_64" buildNumber="100">
<CONFIGURATIONS>
<CONFIGURATION name="Debug" enablePluginBinaryCopyStep="1" isDebug="1" optimisation="1"
linkTimeOptimisation="0" targetName="PaulXStretch" headerPath="Source/PS_Source&#10;Source/WDL&#10;/Users/teemu/codeprojects/JUCE/modules/vst2.x&#10;"
libraryPath="/usr/local/Cellar/fftw/3.3.8/lib" cppLibType="libc++"
osxArchitecture="64BitIntel" osxCompatibility="10.9 SDK" defines="JUCE_NO_DEPRECATION_WARNINGS"
macOSDeploymentTarget="10.9"/>
<CONFIGURATION name="Release" enablePluginBinaryCopyStep="1" isDebug="0" optimisation="3"
linkTimeOptimisation="0" targetName="PaulXStretch" headerPath="Source/PS_Source&#10;Source/WDL&#10;/Users/teemu/codeprojects/JUCE/modules/vst2.x&#10;"
osxCompatibility="10.9 SDK" osxArchitecture="64BitIntel" cppLibType="libc++"
libraryPath="/usr/local/Cellar/fftw/3.3.8/lib" defines="JUCE_NO_DEPRECATION_WARNINGS"
linkTimeOptimisation="0" targetName="PaulXStretch" headerPath="Source/PS_Source&#10;Source/WDL&#10;${HOME}/devstatic/include&#10;"
libraryPath="${HOME}/devstatic/lib&#10;" cppLibType="libc++"
osxArchitecture="64BitIntel" osxCompatibility="10.10 SDK" defines="JUCE_NO_DEPRECATION_WARNINGS"
macOSDeploymentTarget="10.10"/>
<CONFIGURATION name="Release" enablePluginBinaryCopyStep="0" isDebug="0" optimisation="3"
linkTimeOptimisation="0" targetName="PaulXStretch" headerPath="Source/PS_Source&#10;Source/WDL&#10;${HOME}/devstatic/include&#10;"
osxCompatibility="10.10 SDK" osxArchitecture="64BitIntel" cppLibType="libc++"
libraryPath="${HOME}/devstatic/lib&#10;" defines="JUCE_NO_DEPRECATION_WARNINGS"
auBinaryLocation="$(HOME)/Library/Audio/Plug-Ins/Components"
macOSDeploymentTarget="10.9"/>
macOSDeploymentTarget="10.10"/>
</CONFIGURATIONS>
<MODULEPATHS>
<MODULEPATH id="juce_core" path="../JUCE/modules"/>