Free EffectManager and EffectRack from the big s.c.c. ...

... though in a small cycle with each other, by moving RealtimeEffectManager to
new files, which remain in the big component.

Net loss of 1, the big component now has 27 files
This commit is contained in:
Paul Licameli 2019-06-23 22:48:32 -04:00
parent 04a3ed9d04
commit ab5a98003a
15 changed files with 506 additions and 425 deletions

View File

@ -427,6 +427,8 @@ src/effects/Paulstretch.cpp
src/effects/Paulstretch.h
src/effects/Phaser.cpp
src/effects/Phaser.h
src/effects/RealtimeEffectManager.cpp
src/effects/RealtimeEffectManager.h
src/effects/Repair.cpp
src/effects/Repair.h
src/effects/Repeat.cpp

View File

@ -1235,6 +1235,7 @@
5E19D655217D51190024D0B1 /* PluginMenus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E19D64C217D51190024D0B1 /* PluginMenus.cpp */; };
5E19F59922A9665500E3F88E /* AutoRecoveryDialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E19F59722A9665500E3F88E /* AutoRecoveryDialog.cpp */; };
5E2A19941EED688500217B58 /* SelectionState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E2A19921EED688500217B58 /* SelectionState.cpp */; };
5E2B3E6222BF9621005042E1 /* RealtimeEffectManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E2B3E6022BF9621005042E1 /* RealtimeEffectManager.cpp */; };
5E2BF3852193A2A500995694 /* TrackView.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E2BF3832193A2A500995694 /* TrackView.cpp */; };
5E2BF3882193A2BD00995694 /* TimeTrackView.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E2BF3862193A2BD00995694 /* TimeTrackView.cpp */; };
5E2BF38B2193A2E400995694 /* WaveTrackView.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E2BF3892193A2E400995694 /* WaveTrackView.cpp */; };
@ -3237,6 +3238,8 @@
5E19F59822A9665500E3F88E /* AutoRecoveryDialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AutoRecoveryDialog.h; sourceTree = "<group>"; };
5E2A19921EED688500217B58 /* SelectionState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SelectionState.cpp; sourceTree = "<group>"; };
5E2A19931EED688500217B58 /* SelectionState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SelectionState.h; sourceTree = "<group>"; };
5E2B3E6022BF9621005042E1 /* RealtimeEffectManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RealtimeEffectManager.cpp; sourceTree = "<group>"; };
5E2B3E6122BF9621005042E1 /* RealtimeEffectManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RealtimeEffectManager.h; sourceTree = "<group>"; };
5E2BF3832193A2A500995694 /* TrackView.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TrackView.cpp; sourceTree = "<group>"; };
5E2BF3842193A2A500995694 /* TrackView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrackView.h; sourceTree = "<group>"; };
5E2BF3862193A2BD00995694 /* TimeTrackView.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TimeTrackView.cpp; sourceTree = "<group>"; };
@ -4716,10 +4719,12 @@
1790B03209883BFD008A330A /* Normalize.cpp */,
1790B03309883BFD008A330A /* Normalize.h */,
1790B03409883BFD008A330A /* nyquist */,
1790B03A09883BFD008A330A /* Phaser.cpp */,
1790B03B09883BFD008A330A /* Phaser.h */,
EDF3B7AF1588C0D50032D35F /* Paulstretch.cpp */,
EDF3B7AE1588C0D50032D35F /* Paulstretch.h */,
1790B03A09883BFD008A330A /* Phaser.cpp */,
1790B03B09883BFD008A330A /* Phaser.h */,
5E2B3E6022BF9621005042E1 /* RealtimeEffectManager.cpp */,
5E2B3E6122BF9621005042E1 /* RealtimeEffectManager.h */,
28EBA7FA0A78FADE00C8BB1F /* Repair.cpp */,
28EBA7FB0A78FADE00C8BB1F /* Repair.h */,
1790B03E09883BFD008A330A /* Repeat.cpp */,
@ -8477,6 +8482,7 @@
1790B19009883BFD008A330A /* Sequence.cpp in Sources */,
5E36A0AF217FA2430068E082 /* ViewMenus.cpp in Sources */,
1790B19109883BFD008A330A /* Shuttle.cpp in Sources */,
5E2B3E6222BF9621005042E1 /* RealtimeEffectManager.cpp in Sources */,
1790B19209883BFD008A330A /* Spectrum.cpp in Sources */,
1790B19309883BFD008A330A /* Tags.cpp in Sources */,
1790B19409883BFD008A330A /* TimeTrack.cpp in Sources */,

View File

@ -459,7 +459,7 @@ time warp info and AudioIOListener and whether the playback is looped.
#include "WaveTrack.h"
#include "AutoRecovery.h"
#include "effects/EffectManager.h"
#include "effects/RealtimeEffectManager.h"
#include "prefs/QualityPrefs.h"
#include "prefs/RecordingPrefs.h"
#include "toolbars/ControlToolBar.h"

View File

@ -454,6 +454,8 @@ audacity_SOURCES = \
effects/Paulstretch.h \
effects/Phaser.cpp \
effects/Phaser.h \
effects/RealtimeEffectManager.cpp \
effects/RealtimeEffectManager.h \
effects/Repair.cpp \
effects/Repair.h \
effects/Repeat.cpp \

View File

@ -412,23 +412,25 @@ am__audacity_SOURCES_DIST = BlockFile.cpp BlockFile.h DirManager.cpp \
effects/NoiseRemoval.h effects/Normalize.cpp \
effects/Normalize.h effects/Paulstretch.cpp \
effects/Paulstretch.h effects/Phaser.cpp effects/Phaser.h \
effects/Repair.cpp effects/Repair.h effects/Repeat.cpp \
effects/Repeat.h effects/Reverb.cpp effects/Reverb.h \
effects/Reverb_libSoX.h effects/Reverse.cpp effects/Reverse.h \
effects/SBSMSEffect.cpp effects/SBSMSEffect.h \
effects/ScienFilter.cpp effects/ScienFilter.h \
effects/Silence.cpp effects/Silence.h effects/SimpleMono.cpp \
effects/SimpleMono.h effects/SoundTouchEffect.cpp \
effects/SoundTouchEffect.h effects/StereoToMono.cpp \
effects/StereoToMono.h effects/TimeScale.cpp \
effects/TimeScale.h effects/TimeWarper.cpp \
effects/TimeWarper.h effects/ToneGen.cpp effects/ToneGen.h \
effects/TruncSilence.cpp effects/TruncSilence.h \
effects/TwoPassSimpleMono.cpp effects/TwoPassSimpleMono.h \
effects/Wahwah.cpp effects/Wahwah.h export/Export.cpp \
export/Export.h export/ExportCL.cpp export/ExportCL.h \
export/ExportFLAC.cpp export/ExportFLAC.h export/ExportMP2.cpp \
export/ExportMP2.h export/ExportMP3.cpp export/ExportMP3.h \
effects/RealtimeEffectManager.cpp \
effects/RealtimeEffectManager.h effects/Repair.cpp \
effects/Repair.h effects/Repeat.cpp effects/Repeat.h \
effects/Reverb.cpp effects/Reverb.h effects/Reverb_libSoX.h \
effects/Reverse.cpp effects/Reverse.h effects/SBSMSEffect.cpp \
effects/SBSMSEffect.h effects/ScienFilter.cpp \
effects/ScienFilter.h effects/Silence.cpp effects/Silence.h \
effects/SimpleMono.cpp effects/SimpleMono.h \
effects/SoundTouchEffect.cpp effects/SoundTouchEffect.h \
effects/StereoToMono.cpp effects/StereoToMono.h \
effects/TimeScale.cpp effects/TimeScale.h \
effects/TimeWarper.cpp effects/TimeWarper.h \
effects/ToneGen.cpp effects/ToneGen.h effects/TruncSilence.cpp \
effects/TruncSilence.h effects/TwoPassSimpleMono.cpp \
effects/TwoPassSimpleMono.h effects/Wahwah.cpp \
effects/Wahwah.h export/Export.cpp export/Export.h \
export/ExportCL.cpp export/ExportCL.h export/ExportFLAC.cpp \
export/ExportFLAC.h export/ExportMP2.cpp export/ExportMP2.h \
export/ExportMP3.cpp export/ExportMP3.h \
export/ExportMultiple.cpp export/ExportMultiple.h \
export/ExportOGG.cpp export/ExportOGG.h export/ExportPCM.cpp \
export/ExportPCM.h import/Import.cpp import/Import.h \
@ -776,6 +778,7 @@ am_audacity_OBJECTS = $(am__objects_1) audacity-AboutDialog.$(OBJEXT) \
effects/audacity-Normalize.$(OBJEXT) \
effects/audacity-Paulstretch.$(OBJEXT) \
effects/audacity-Phaser.$(OBJEXT) \
effects/audacity-RealtimeEffectManager.$(OBJEXT) \
effects/audacity-Repair.$(OBJEXT) \
effects/audacity-Repeat.$(OBJEXT) \
effects/audacity-Reverb.$(OBJEXT) \
@ -1510,23 +1513,25 @@ audacity_SOURCES = $(libaudacity_la_SOURCES) AboutDialog.cpp \
effects/NoiseRemoval.h effects/Normalize.cpp \
effects/Normalize.h effects/Paulstretch.cpp \
effects/Paulstretch.h effects/Phaser.cpp effects/Phaser.h \
effects/Repair.cpp effects/Repair.h effects/Repeat.cpp \
effects/Repeat.h effects/Reverb.cpp effects/Reverb.h \
effects/Reverb_libSoX.h effects/Reverse.cpp effects/Reverse.h \
effects/SBSMSEffect.cpp effects/SBSMSEffect.h \
effects/ScienFilter.cpp effects/ScienFilter.h \
effects/Silence.cpp effects/Silence.h effects/SimpleMono.cpp \
effects/SimpleMono.h effects/SoundTouchEffect.cpp \
effects/SoundTouchEffect.h effects/StereoToMono.cpp \
effects/StereoToMono.h effects/TimeScale.cpp \
effects/TimeScale.h effects/TimeWarper.cpp \
effects/TimeWarper.h effects/ToneGen.cpp effects/ToneGen.h \
effects/TruncSilence.cpp effects/TruncSilence.h \
effects/TwoPassSimpleMono.cpp effects/TwoPassSimpleMono.h \
effects/Wahwah.cpp effects/Wahwah.h export/Export.cpp \
export/Export.h export/ExportCL.cpp export/ExportCL.h \
export/ExportFLAC.cpp export/ExportFLAC.h export/ExportMP2.cpp \
export/ExportMP2.h export/ExportMP3.cpp export/ExportMP3.h \
effects/RealtimeEffectManager.cpp \
effects/RealtimeEffectManager.h effects/Repair.cpp \
effects/Repair.h effects/Repeat.cpp effects/Repeat.h \
effects/Reverb.cpp effects/Reverb.h effects/Reverb_libSoX.h \
effects/Reverse.cpp effects/Reverse.h effects/SBSMSEffect.cpp \
effects/SBSMSEffect.h effects/ScienFilter.cpp \
effects/ScienFilter.h effects/Silence.cpp effects/Silence.h \
effects/SimpleMono.cpp effects/SimpleMono.h \
effects/SoundTouchEffect.cpp effects/SoundTouchEffect.h \
effects/StereoToMono.cpp effects/StereoToMono.h \
effects/TimeScale.cpp effects/TimeScale.h \
effects/TimeWarper.cpp effects/TimeWarper.h \
effects/ToneGen.cpp effects/ToneGen.h effects/TruncSilence.cpp \
effects/TruncSilence.h effects/TwoPassSimpleMono.cpp \
effects/TwoPassSimpleMono.h effects/Wahwah.cpp \
effects/Wahwah.h export/Export.cpp export/Export.h \
export/ExportCL.cpp export/ExportCL.h export/ExportFLAC.cpp \
export/ExportFLAC.h export/ExportMP2.cpp export/ExportMP2.h \
export/ExportMP3.cpp export/ExportMP3.h \
export/ExportMultiple.cpp export/ExportMultiple.h \
export/ExportOGG.cpp export/ExportOGG.h export/ExportPCM.cpp \
export/ExportPCM.h import/Import.cpp import/Import.h \
@ -2009,6 +2014,8 @@ effects/audacity-Paulstretch.$(OBJEXT): effects/$(am__dirstamp) \
effects/$(DEPDIR)/$(am__dirstamp)
effects/audacity-Phaser.$(OBJEXT): effects/$(am__dirstamp) \
effects/$(DEPDIR)/$(am__dirstamp)
effects/audacity-RealtimeEffectManager.$(OBJEXT): \
effects/$(am__dirstamp) effects/$(DEPDIR)/$(am__dirstamp)
effects/audacity-Repair.$(OBJEXT): effects/$(am__dirstamp) \
effects/$(DEPDIR)/$(am__dirstamp)
effects/audacity-Repeat.$(OBJEXT): effects/$(am__dirstamp) \
@ -2760,6 +2767,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@effects/$(DEPDIR)/audacity-Normalize.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@effects/$(DEPDIR)/audacity-Paulstretch.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@effects/$(DEPDIR)/audacity-Phaser.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@effects/$(DEPDIR)/audacity-RealtimeEffectManager.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@effects/$(DEPDIR)/audacity-Repair.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@effects/$(DEPDIR)/audacity-Repeat.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@effects/$(DEPDIR)/audacity-Reverb.Po@am__quote@
@ -5639,6 +5647,20 @@ effects/audacity-Phaser.obj: effects/Phaser.cpp
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -c -o effects/audacity-Phaser.obj `if test -f 'effects/Phaser.cpp'; then $(CYGPATH_W) 'effects/Phaser.cpp'; else $(CYGPATH_W) '$(srcdir)/effects/Phaser.cpp'; fi`
effects/audacity-RealtimeEffectManager.o: effects/RealtimeEffectManager.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -MT effects/audacity-RealtimeEffectManager.o -MD -MP -MF effects/$(DEPDIR)/audacity-RealtimeEffectManager.Tpo -c -o effects/audacity-RealtimeEffectManager.o `test -f 'effects/RealtimeEffectManager.cpp' || echo '$(srcdir)/'`effects/RealtimeEffectManager.cpp
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) effects/$(DEPDIR)/audacity-RealtimeEffectManager.Tpo effects/$(DEPDIR)/audacity-RealtimeEffectManager.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='effects/RealtimeEffectManager.cpp' object='effects/audacity-RealtimeEffectManager.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -c -o effects/audacity-RealtimeEffectManager.o `test -f 'effects/RealtimeEffectManager.cpp' || echo '$(srcdir)/'`effects/RealtimeEffectManager.cpp
effects/audacity-RealtimeEffectManager.obj: effects/RealtimeEffectManager.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -MT effects/audacity-RealtimeEffectManager.obj -MD -MP -MF effects/$(DEPDIR)/audacity-RealtimeEffectManager.Tpo -c -o effects/audacity-RealtimeEffectManager.obj `if test -f 'effects/RealtimeEffectManager.cpp'; then $(CYGPATH_W) 'effects/RealtimeEffectManager.cpp'; else $(CYGPATH_W) '$(srcdir)/effects/RealtimeEffectManager.cpp'; fi`
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) effects/$(DEPDIR)/audacity-RealtimeEffectManager.Tpo effects/$(DEPDIR)/audacity-RealtimeEffectManager.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='effects/RealtimeEffectManager.cpp' object='effects/audacity-RealtimeEffectManager.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -c -o effects/audacity-RealtimeEffectManager.obj `if test -f 'effects/RealtimeEffectManager.cpp'; then $(CYGPATH_W) 'effects/RealtimeEffectManager.cpp'; else $(CYGPATH_W) '$(srcdir)/effects/RealtimeEffectManager.cpp'; fi`
effects/audacity-Repair.o: effects/Repair.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -MT effects/audacity-Repair.o -MD -MP -MF effects/$(DEPDIR)/audacity-Repair.Tpo -c -o effects/audacity-Repair.o `test -f 'effects/Repair.cpp' || echo '$(srcdir)/'`effects/Repair.cpp
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) effects/$(DEPDIR)/audacity-Repair.Tpo effects/$(DEPDIR)/audacity-Repair.Po

View File

@ -47,7 +47,7 @@ greater use in future.
#include "audacity/ConfigInterface.h"
#include "EffectManager.h"
#include "RealtimeEffectManager.h"
#include "../AudioIO.h"
#include "../CommonCommandFlags.h"
#include "../LabelTrack.h"

View File

@ -52,25 +52,6 @@ EffectManager & EffectManager::Get()
return em;
}
RealtimeEffectManager & RealtimeEffectManager::Get()
{
static RealtimeEffectManager rem;
return rem;
}
RealtimeEffectManager::RealtimeEffectManager()
{
mRealtimeLock.Enter();
mRealtimeActive = false;
mRealtimeSuspended = true;
mRealtimeLatency = 0;
mRealtimeLock.Leave();
}
RealtimeEffectManager::~RealtimeEffectManager()
{
}
EffectManager::EffectManager()
{
mSkipStateFlag = false;
@ -526,337 +507,8 @@ void EffectManager::ShowRack()
{
GetRack()->Show(!GetRack()->IsShown());
}
void RealtimeEffectManager::RealtimeSetEffects(const EffectArray & effects)
{
// Block RealtimeProcess()
RealtimeSuspend();
// Tell any effects no longer in the chain to clean up
for (auto e: mRealtimeEffects)
{
// Scan the NEW chain for the effect
for (auto e1: effects)
{
// Found it so we're done
if (e == e1)
{
e = NULL;
break;
}
}
// Must not have been in the NEW chain, so tell it to cleanup
if (e && mRealtimeActive)
{
e->RealtimeFinalize();
}
}
// Tell any NEW effects to get ready
for (auto e : effects)
{
// Scan the old chain for the effect
for (auto e1 : mRealtimeEffects)
{
// Found it so tell effect to get ready
if (e == e1)
{
e = NULL;
break;
}
}
// Must not have been in the old chain, so tell it to initialize
if (e && mRealtimeActive)
{
e->RealtimeInitialize();
}
}
// Get rid of the old chain
// And install the NEW one
mRealtimeEffects = effects;
// Allow RealtimeProcess() to, well, process
RealtimeResume();
}
#endif
bool RealtimeEffectManager::RealtimeIsActive()
{
return mRealtimeEffects.size() != 0;
}
bool RealtimeEffectManager::RealtimeIsSuspended()
{
return mRealtimeSuspended;
}
void RealtimeEffectManager::RealtimeAddEffect(Effect *effect)
{
// Block RealtimeProcess()
RealtimeSuspend();
// Initialize effect if realtime is already active
if (mRealtimeActive)
{
// Initialize realtime processing
effect->RealtimeInitialize();
// Add the required processors
for (size_t i = 0, cnt = mRealtimeChans.size(); i < cnt; i++)
{
effect->RealtimeAddProcessor(i, mRealtimeChans[i], mRealtimeRates[i]);
}
}
// Add to list of active effects
mRealtimeEffects.push_back(effect);
// Allow RealtimeProcess() to, well, process
RealtimeResume();
}
void RealtimeEffectManager::RealtimeRemoveEffect(Effect *effect)
{
// Block RealtimeProcess()
RealtimeSuspend();
if (mRealtimeActive)
{
// Cleanup realtime processing
effect->RealtimeFinalize();
}
// Remove from list of active effects
auto end = mRealtimeEffects.end();
auto found = std::find(mRealtimeEffects.begin(), end, effect);
if (found != end)
mRealtimeEffects.erase(found);
// Allow RealtimeProcess() to, well, process
RealtimeResume();
}
void RealtimeEffectManager::RealtimeInitialize(double rate)
{
// The audio thread should not be running yet, but protect anyway
RealtimeSuspend();
// (Re)Set processor parameters
mRealtimeChans.clear();
mRealtimeRates.clear();
// RealtimeAdd/RemoveEffect() needs to know when we're active so it can
// initialize newly added effects
mRealtimeActive = true;
// Tell each effect to get ready for action
for (auto e : mRealtimeEffects) {
e->SetSampleRate(rate);
e->RealtimeInitialize();
}
// Get things moving
RealtimeResume();
}
void RealtimeEffectManager::RealtimeAddProcessor(int group, unsigned chans, float rate)
{
for (auto e : mRealtimeEffects)
e->RealtimeAddProcessor(group, chans, rate);
mRealtimeChans.push_back(chans);
mRealtimeRates.push_back(rate);
}
void RealtimeEffectManager::RealtimeFinalize()
{
// Make sure nothing is going on
RealtimeSuspend();
// It is now safe to clean up
mRealtimeLatency = 0;
// Tell each effect to clean up as well
for (auto e : mRealtimeEffects)
e->RealtimeFinalize();
// Reset processor parameters
mRealtimeChans.clear();
mRealtimeRates.clear();
// No longer active
mRealtimeActive = false;
}
void RealtimeEffectManager::RealtimeSuspend()
{
mRealtimeLock.Enter();
// Already suspended...bail
if (mRealtimeSuspended)
{
mRealtimeLock.Leave();
return;
}
// Show that we aren't going to be doing anything
mRealtimeSuspended = true;
// And make sure the effects don't either
for (auto e : mRealtimeEffects)
e->RealtimeSuspend();
mRealtimeLock.Leave();
}
void RealtimeEffectManager::RealtimeResume()
{
mRealtimeLock.Enter();
// Already running...bail
if (!mRealtimeSuspended)
{
mRealtimeLock.Leave();
return;
}
// Tell the effects to get ready for more action
for (auto e : mRealtimeEffects)
e->RealtimeResume();
// And we should too
mRealtimeSuspended = false;
mRealtimeLock.Leave();
}
//
// This will be called in a different thread than the main GUI thread.
//
void RealtimeEffectManager::RealtimeProcessStart()
{
// Protect ourselves from the main thread
mRealtimeLock.Enter();
// Can be suspended because of the audio stream being paused or because effects
// have been suspended.
if (!mRealtimeSuspended)
{
for (auto e : mRealtimeEffects)
{
if (e->IsRealtimeActive())
e->RealtimeProcessStart();
}
}
mRealtimeLock.Leave();
}
//
// This will be called in a different thread than the main GUI thread.
//
size_t RealtimeEffectManager::RealtimeProcess(int group, unsigned chans, float **buffers, size_t numSamples)
{
// Protect ourselves from the main thread
mRealtimeLock.Enter();
// Can be suspended because of the audio stream being paused or because effects
// have been suspended, so allow the samples to pass as-is.
if (mRealtimeSuspended || mRealtimeEffects.empty())
{
mRealtimeLock.Leave();
return numSamples;
}
// Remember when we started so we can calculate the amount of latency we
// are introducing
wxMilliClock_t start = wxGetUTCTimeMillis();
// Allocate the in/out buffer arrays
float **ibuf = (float **) alloca(chans * sizeof(float *));
float **obuf = (float **) alloca(chans * sizeof(float *));
// And populate the input with the buffers we've been given while allocating
// NEW output buffers
for (unsigned int i = 0; i < chans; i++)
{
ibuf[i] = buffers[i];
obuf[i] = (float *) alloca(numSamples * sizeof(float));
}
// Now call each effect in the chain while swapping buffer pointers to feed the
// output of one effect as the input to the next effect
size_t called = 0;
for (auto e : mRealtimeEffects)
{
if (e->IsRealtimeActive())
{
e->RealtimeProcess(group, chans, ibuf, obuf, numSamples);
called++;
}
for (unsigned int j = 0; j < chans; j++)
{
float *temp;
temp = ibuf[j];
ibuf[j] = obuf[j];
obuf[j] = temp;
}
}
// Once we're done, we might wind up with the last effect storing its results
// in the temporary buffers. If that's the case, we need to copy it over to
// the caller's buffers. This happens when the number of effects proccessed
// is odd.
if (called & 1)
{
for (unsigned int i = 0; i < chans; i++)
{
memcpy(buffers[i], ibuf[i], numSamples * sizeof(float));
}
}
// Remember the latency
mRealtimeLatency = (int) (wxGetUTCTimeMillis() - start).GetValue();
mRealtimeLock.Leave();
//
// This is wrong...needs to handle tails
//
return numSamples;
}
//
// This will be called in a different thread than the main GUI thread.
//
void RealtimeEffectManager::RealtimeProcessEnd()
{
// Protect ourselves from the main thread
mRealtimeLock.Enter();
// Can be suspended because of the audio stream being paused or because effects
// have been suspended.
if (!mRealtimeSuspended)
{
for (auto e : mRealtimeEffects)
{
if (e->IsRealtimeActive())
e->RealtimeProcessEnd();
}
}
mRealtimeLock.Leave();
}
int RealtimeEffectManager::GetRealtimeLatency()
{
return mRealtimeLatency;
}
Effect *EffectManager::GetEffect(const PluginID & ID)
{
// Must have a "valid" ID

View File

@ -18,7 +18,6 @@
#include <vector>
#include <unordered_map>
#include <wx/thread.h>
#include "audacity/Types.h"
class AudacityCommand;
@ -32,7 +31,6 @@ class SelectedRegion;
class wxString;
typedef wxString PluginID;
using EffectArray = std::vector <Effect*> ;
using EffectMap = std::unordered_map<wxString, Effect *>;
using AudacityCommandMap = std::unordered_map<wxString, AudacityCommand *>;
using EffectOwnerMap = std::unordered_map< wxString, std::shared_ptr<Effect> >;
@ -163,40 +161,4 @@ private:
};
class AUDACITY_DLL_API RealtimeEffectManager final
{
public:
/** Get the singleton instance of the RealtimeEffectManager. **/
static RealtimeEffectManager & Get();
// Realtime effect processing
bool RealtimeIsActive();
bool RealtimeIsSuspended();
void RealtimeAddEffect(Effect *effect);
void RealtimeRemoveEffect(Effect *effect);
void RealtimeSetEffects(const EffectArray & mActive);
void RealtimeInitialize(double rate);
void RealtimeAddProcessor(int group, unsigned chans, float rate);
void RealtimeFinalize();
void RealtimeSuspend();
void RealtimeResume();
void RealtimeProcessStart();
size_t RealtimeProcess(int group, unsigned chans, float **buffers, size_t numSamples);
void RealtimeProcessEnd();
int GetRealtimeLatency();
private:
RealtimeEffectManager();
~RealtimeEffectManager();
wxCriticalSection mRealtimeLock;
EffectArray mRealtimeEffects;
int mRealtimeLatency;
bool mRealtimeSuspended;
bool mRealtimeActive;
std::vector<unsigned> mRealtimeChans;
std::vector<double> mRealtimeRates;
};
#endif

View File

@ -18,6 +18,7 @@
#include "Effect.h"
#include "EffectManager.h"
#include "RealtimeEffectManager.h"
#if defined(EXPERIMENTAL_EFFECTS_RACK)

View File

@ -0,0 +1,368 @@
/**********************************************************************
Audacity: A Digital Audio Editor
RealtimeEffectManager.cpp
Paul Licameli split from EffectManager.cpp
**********************************************************************/
#include "../Audacity.h"
#include "RealtimeEffectManager.h"
#include "../Experimental.h"
#include "Effect.h"
#include <wx/time.h>
RealtimeEffectManager & RealtimeEffectManager::Get()
{
static RealtimeEffectManager rem;
return rem;
}
RealtimeEffectManager::RealtimeEffectManager()
{
mRealtimeLock.Enter();
mRealtimeActive = false;
mRealtimeSuspended = true;
mRealtimeLatency = 0;
mRealtimeLock.Leave();
}
RealtimeEffectManager::~RealtimeEffectManager()
{
}
#if defined(EXPERIMENTAL_EFFECTS_RACK)
void RealtimeEffectManager::RealtimeSetEffects(const EffectArray & effects)
{
// Block RealtimeProcess()
RealtimeSuspend();
// Tell any effects no longer in the chain to clean up
for (auto e: mRealtimeEffects)
{
// Scan the NEW chain for the effect
for (auto e1: effects)
{
// Found it so we're done
if (e == e1)
{
e = NULL;
break;
}
}
// Must not have been in the NEW chain, so tell it to cleanup
if (e && mRealtimeActive)
{
e->RealtimeFinalize();
}
}
// Tell any NEW effects to get ready
for (auto e : effects)
{
// Scan the old chain for the effect
for (auto e1 : mRealtimeEffects)
{
// Found it so tell effect to get ready
if (e == e1)
{
e = NULL;
break;
}
}
// Must not have been in the old chain, so tell it to initialize
if (e && mRealtimeActive)
{
e->RealtimeInitialize();
}
}
// Get rid of the old chain
// And install the NEW one
mRealtimeEffects = effects;
// Allow RealtimeProcess() to, well, process
RealtimeResume();
}
#endif
bool RealtimeEffectManager::RealtimeIsActive()
{
return mRealtimeEffects.size() != 0;
}
bool RealtimeEffectManager::RealtimeIsSuspended()
{
return mRealtimeSuspended;
}
void RealtimeEffectManager::RealtimeAddEffect(Effect *effect)
{
// Block RealtimeProcess()
RealtimeSuspend();
// Initialize effect if realtime is already active
if (mRealtimeActive)
{
// Initialize realtime processing
effect->RealtimeInitialize();
// Add the required processors
for (size_t i = 0, cnt = mRealtimeChans.size(); i < cnt; i++)
{
effect->RealtimeAddProcessor(i, mRealtimeChans[i], mRealtimeRates[i]);
}
}
// Add to list of active effects
mRealtimeEffects.push_back(effect);
// Allow RealtimeProcess() to, well, process
RealtimeResume();
}
void RealtimeEffectManager::RealtimeRemoveEffect(Effect *effect)
{
// Block RealtimeProcess()
RealtimeSuspend();
if (mRealtimeActive)
{
// Cleanup realtime processing
effect->RealtimeFinalize();
}
// Remove from list of active effects
auto end = mRealtimeEffects.end();
auto found = std::find(mRealtimeEffects.begin(), end, effect);
if (found != end)
mRealtimeEffects.erase(found);
// Allow RealtimeProcess() to, well, process
RealtimeResume();
}
void RealtimeEffectManager::RealtimeInitialize(double rate)
{
// The audio thread should not be running yet, but protect anyway
RealtimeSuspend();
// (Re)Set processor parameters
mRealtimeChans.clear();
mRealtimeRates.clear();
// RealtimeAdd/RemoveEffect() needs to know when we're active so it can
// initialize newly added effects
mRealtimeActive = true;
// Tell each effect to get ready for action
for (auto e : mRealtimeEffects) {
e->SetSampleRate(rate);
e->RealtimeInitialize();
}
// Get things moving
RealtimeResume();
}
void RealtimeEffectManager::RealtimeAddProcessor(int group, unsigned chans, float rate)
{
for (auto e : mRealtimeEffects)
e->RealtimeAddProcessor(group, chans, rate);
mRealtimeChans.push_back(chans);
mRealtimeRates.push_back(rate);
}
void RealtimeEffectManager::RealtimeFinalize()
{
// Make sure nothing is going on
RealtimeSuspend();
// It is now safe to clean up
mRealtimeLatency = 0;
// Tell each effect to clean up as well
for (auto e : mRealtimeEffects)
e->RealtimeFinalize();
// Reset processor parameters
mRealtimeChans.clear();
mRealtimeRates.clear();
// No longer active
mRealtimeActive = false;
}
void RealtimeEffectManager::RealtimeSuspend()
{
mRealtimeLock.Enter();
// Already suspended...bail
if (mRealtimeSuspended)
{
mRealtimeLock.Leave();
return;
}
// Show that we aren't going to be doing anything
mRealtimeSuspended = true;
// And make sure the effects don't either
for (auto e : mRealtimeEffects)
e->RealtimeSuspend();
mRealtimeLock.Leave();
}
void RealtimeEffectManager::RealtimeResume()
{
mRealtimeLock.Enter();
// Already running...bail
if (!mRealtimeSuspended)
{
mRealtimeLock.Leave();
return;
}
// Tell the effects to get ready for more action
for (auto e : mRealtimeEffects)
e->RealtimeResume();
// And we should too
mRealtimeSuspended = false;
mRealtimeLock.Leave();
}
//
// This will be called in a different thread than the main GUI thread.
//
void RealtimeEffectManager::RealtimeProcessStart()
{
// Protect ourselves from the main thread
mRealtimeLock.Enter();
// Can be suspended because of the audio stream being paused or because effects
// have been suspended.
if (!mRealtimeSuspended)
{
for (auto e : mRealtimeEffects)
{
if (e->IsRealtimeActive())
e->RealtimeProcessStart();
}
}
mRealtimeLock.Leave();
}
//
// This will be called in a different thread than the main GUI thread.
//
size_t RealtimeEffectManager::RealtimeProcess(int group, unsigned chans, float **buffers, size_t numSamples)
{
// Protect ourselves from the main thread
mRealtimeLock.Enter();
// Can be suspended because of the audio stream being paused or because effects
// have been suspended, so allow the samples to pass as-is.
if (mRealtimeSuspended || mRealtimeEffects.empty())
{
mRealtimeLock.Leave();
return numSamples;
}
// Remember when we started so we can calculate the amount of latency we
// are introducing
wxMilliClock_t start = wxGetUTCTimeMillis();
// Allocate the in/out buffer arrays
float **ibuf = (float **) alloca(chans * sizeof(float *));
float **obuf = (float **) alloca(chans * sizeof(float *));
// And populate the input with the buffers we've been given while allocating
// NEW output buffers
for (unsigned int i = 0; i < chans; i++)
{
ibuf[i] = buffers[i];
obuf[i] = (float *) alloca(numSamples * sizeof(float));
}
// Now call each effect in the chain while swapping buffer pointers to feed the
// output of one effect as the input to the next effect
size_t called = 0;
for (auto e : mRealtimeEffects)
{
if (e->IsRealtimeActive())
{
e->RealtimeProcess(group, chans, ibuf, obuf, numSamples);
called++;
}
for (unsigned int j = 0; j < chans; j++)
{
float *temp;
temp = ibuf[j];
ibuf[j] = obuf[j];
obuf[j] = temp;
}
}
// Once we're done, we might wind up with the last effect storing its results
// in the temporary buffers. If that's the case, we need to copy it over to
// the caller's buffers. This happens when the number of effects proccessed
// is odd.
if (called & 1)
{
for (unsigned int i = 0; i < chans; i++)
{
memcpy(buffers[i], ibuf[i], numSamples * sizeof(float));
}
}
// Remember the latency
mRealtimeLatency = (int) (wxGetUTCTimeMillis() - start).GetValue();
mRealtimeLock.Leave();
//
// This is wrong...needs to handle tails
//
return numSamples;
}
//
// This will be called in a different thread than the main GUI thread.
//
void RealtimeEffectManager::RealtimeProcessEnd()
{
// Protect ourselves from the main thread
mRealtimeLock.Enter();
// Can be suspended because of the audio stream being paused or because effects
// have been suspended.
if (!mRealtimeSuspended)
{
for (auto e : mRealtimeEffects)
{
if (e->IsRealtimeActive())
e->RealtimeProcessEnd();
}
}
mRealtimeLock.Leave();
}
int RealtimeEffectManager::GetRealtimeLatency()
{
return mRealtimeLatency;
}

View File

@ -0,0 +1,57 @@
/**********************************************************************
Audacity: A Digital Audio Editor
RealtimeEffectManager.h
Paul Licameli split from EffectManager.h
**********************************************************************/
#ifndef __AUDACITY_REALTIME_EFFECT_MANAGER__
#define __AUDACITY_REALTIME_EFFECT_MANAGER__
#include <memory>
#include <vector>
#include <wx/thread.h>
class Effect;
using EffectArray = std::vector <Effect*> ;
class AUDACITY_DLL_API RealtimeEffectManager final
{
public:
/** Get the singleton instance of the RealtimeEffectManager. **/
static RealtimeEffectManager & Get();
// Realtime effect processing
bool RealtimeIsActive();
bool RealtimeIsSuspended();
void RealtimeAddEffect(Effect *effect);
void RealtimeRemoveEffect(Effect *effect);
void RealtimeSetEffects(const EffectArray & mActive);
void RealtimeInitialize(double rate);
void RealtimeAddProcessor(int group, unsigned chans, float rate);
void RealtimeFinalize();
void RealtimeSuspend();
void RealtimeResume();
void RealtimeProcessStart();
size_t RealtimeProcess(int group, unsigned chans, float **buffers, size_t numSamples);
void RealtimeProcessEnd();
int GetRealtimeLatency();
private:
RealtimeEffectManager();
~RealtimeEffectManager();
wxCriticalSection mRealtimeLock;
EffectArray mRealtimeEffects;
int mRealtimeLatency;
bool mRealtimeSuspended;
bool mRealtimeActive;
std::vector<unsigned> mRealtimeChans;
std::vector<double> mRealtimeRates;
};
#endif

View File

@ -23,6 +23,7 @@
#include "../commands/ScreenshotCommand.h"
#include "../effects/Contrast.h"
#include "../effects/EffectManager.h"
#include "../effects/RealtimeEffectManager.h"
// private helper classes and functions
namespace {

View File

@ -28,7 +28,7 @@ Paul Licameli split from TrackPanel.cpp
#include "../../../../TrackPanelMouseEvent.h"
#include "../../../../WaveTrack.h"
#include "../../../../widgets/PopupMenuTable.h"
#include "../../../../effects/EffectManager.h"
#include "../../../../effects/RealtimeEffectManager.h"
#include "../../../../ondemand/ODManager.h"
#include "../../../../prefs/PrefsDialog.h"
#include "../../../../prefs/SpectrumPrefs.h"

View File

@ -358,6 +358,7 @@
<ClCompile Include="..\..\..\src\effects\NoiseRemoval.cpp" />
<ClCompile Include="..\..\..\src\effects\Normalize.cpp" />
<ClCompile Include="..\..\..\src\effects\Paulstretch.cpp" />
<ClCompile Include="..\..\..\src\effects\RealtimeEffectManager.cpp" />
<ClCompile Include="..\..\..\src\effects\Repair.cpp" />
<ClCompile Include="..\..\..\src\effects\Repeat.cpp" />
<ClCompile Include="..\..\..\src\effects\Reverb.cpp" />
@ -747,6 +748,7 @@
<ClInclude Include="..\..\..\src\effects\NoiseRemoval.h" />
<ClInclude Include="..\..\..\src\effects\Normalize.h" />
<ClInclude Include="..\..\..\src\effects\Paulstretch.h" />
<ClInclude Include="..\..\..\src\effects\RealtimeEffectManager.h" />
<ClInclude Include="..\..\..\src\effects\Repair.h" />
<ClInclude Include="..\..\..\src\effects\Repeat.h" />
<ClInclude Include="..\..\..\src\effects\Reverb.h" />

View File

@ -461,6 +461,9 @@
<ClCompile Include="..\..\..\src\effects\Paulstretch.cpp">
<Filter>src\effects</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\effects\RealtimeEffectManager.cpp">
<Filter>src\effects</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\effects\Repair.cpp">
<Filter>src\effects</Filter>
</ClCompile>
@ -1588,6 +1591,9 @@
<ClInclude Include="..\..\..\src\effects\Paulstretch.h">
<Filter>src\effects</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\effects\RealtimeEffectManager.h">
<Filter>src\effects</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\effects\Repair.h">
<Filter>src\effects</Filter>
</ClInclude>