Skip to content

Commit

Permalink
EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT redone with constexpr if
Browse files Browse the repository at this point in the history
  • Loading branch information
Paul-Licameli committed Apr 3, 2024
1 parent 9d33508 commit de3bc87
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 125 deletions.
93 changes: 50 additions & 43 deletions libraries/lib-audio-io/AudioIO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ time warp info and AudioIOListener and whether the playback is looped.

#include "float_cast.h"
#include "DeviceManager.h"
#include "Experimental.h"

#include <cfloat>
#include <math.h>
Expand Down Expand Up @@ -115,11 +116,6 @@ time warp info and AudioIOListener and whether the playback is looped.

#include "Gain.h"

#ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
#define LOWER_BOUND 0.0
#define UPPER_BOUND 1.0
#endif

using std::max;
using std::min;

Expand Down Expand Up @@ -257,10 +253,6 @@ AudioIO::AudioIO()

mNumPauseFrames = 0;

#ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
mAILAActive = false;
#endif

mLastPaError = paNoError;

mLastRecordingOffset = 0.0;
Expand Down Expand Up @@ -1003,9 +995,8 @@ int AudioIO::StartStream(const TransportSequences &sequences,
mpTransportState = std::make_unique<TransportState>(mOwningProject,
mPlaybackSequences, mNumPlaybackChannels, mRate);

#ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
AILASetStartTime();
#endif
if constexpr(Experimental::AILA)
AILASetStartTime();

if (pStartTime)
{
Expand Down Expand Up @@ -2322,19 +2313,25 @@ void AudioIoCallback::SetListener(
}

// Automated Input Level Adjustment - Automatically tries to find an acceptable input volume
#ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT

#include "ProjectStatus.h"

void AudioIO::AILAInitialize() {
if constexpr(Experimental::AILA) {
gPrefs->Read(wxT("/AudioIO/AutomatedInputLevelAdjustment"), &mAILAActive, false);
gPrefs->Read(wxT("/AudioIO/TargetPeak"), &mAILAGoalPoint, AILA_DEF_TARGET_PEAK);
gPrefs->Read(wxT("/AudioIO/DeltaPeakVolume"), &mAILAGoalDelta, AILA_DEF_DELTA_PEAK);
gPrefs->Read(wxT("/AudioIO/AnalysisTime"), &mAILAAnalysisTime, AILA_DEF_ANALYSIS_TIME);

int goalPoint;
gPrefs->Read(wxT("/AudioIO/TargetPeak"), &goalPoint, AILA_DEF_TARGET_PEAK);
mAILAGoalPoint = goalPoint / 100.0;

int goalDelta;
gPrefs->Read(wxT("/AudioIO/DeltaPeakVolume"), &goalDelta, AILA_DEF_DELTA_PEAK);
mAILAGoalDelta = goalDelta / 100.0;

int analysisTime;
gPrefs->Read(wxT("/AudioIO/AnalysisTime"), &analysisTime, AILA_DEF_ANALYSIS_TIME);
mAILAAnalysisTime = analysisTime / 1000.0;

gPrefs->Read(wxT("/AudioIO/NumberAnalysis"), &mAILATotalAnalysis, AILA_DEF_NUMBER_ANALYSIS);
mAILAGoalDelta /= 100.0;
mAILAGoalPoint /= 100.0;
mAILAAnalysisTime /= 1000.0;
mAILAMax = 0.0;
mAILALastStartTime = max(0.0, mPlaybackSchedule.mT0);
mAILAClipped = false;
Expand All @@ -2343,29 +2340,35 @@ void AudioIO::AILAInitialize() {
mAILALastChangeType = 0;
mAILATopLevel = 1.0;
mAILAAnalysisEndTime = -1.0;
}
}}

void AudioIO::AILADisable() {
if constexpr(Experimental::AILA) {
mAILAActive = false;
}
}}

bool AudioIO::AILAIsActive() {
return mAILAActive;
return Experimental::AILA && mAILAActive;
}

void AudioIO::AILASetStartTime() {
if constexpr(Experimental::AILA) {
mAILAAbsolutStartTime = Pa_GetStreamTime(mPortStreamV19);
wxPrintf("START TIME %f\n\n", mAILAAbsolutStartTime);
}
}}

double AudioIO::AILAGetLastDecisionTime() {
return mAILAAnalysisEndTime;
}

void AudioIO::AILAProcess(double maxPeak) {
if constexpr(Experimental::AILA) {
constexpr auto LOWER_BOUND = 0.0, UPPER_BOUND = 1.0;
auto &audioIO = *this;
const auto proj = mOwningProject.lock();
const auto pInputMeter = mInputMeter.lock();
if (proj && mAILAActive) {
if (mInputMeter && mInputMeter->IsClipping()) {
if (pInputMeter && pInputMeter->IsClipping()) {
mAILAClipped = true;
wxPrintf("clipped");
}
Expand All @@ -2380,8 +2383,10 @@ void AudioIO::AILAProcess(double maxPeak) {
};

putchar('\n');
mAILAMax = mInputMeter ? ToLinearIfDB(mAILAMax, mInputMeter->GetDBRange()) : 0.0;
double iv = (double) Px_GetInputVolume(mPortMixer);
mAILAMax = pInputMeter ? ToLinearIfDB(mAILAMax, pInputMeter->GetDBRange()) : 0.0;
auto settings = audioIO.GetMixer();
auto &[_, inputVolume, __] = settings;
const double iv = inputVolume;
unsigned short changetype = 0; //0 - no change, 1 - increase change, 2 - decrease change
wxPrintf("mAILAAnalysisCounter:%d\n", mAILAAnalysisCounter);
wxPrintf("\tmAILAClipped:%d\n", mAILAClipped);
Expand All @@ -2406,14 +2411,16 @@ void AudioIO::AILAProcess(double maxPeak) {
wxPrintf("\talready min vol:%f\n", iv);
}
else {
float vol = (float) max(LOWER_BOUND, iv+(mAILAGoalPoint-mAILAMax)*mAILAChangeFactor);
Px_SetInputVolume(mPortMixer, vol);
inputVolume = max<float>(LOWER_BOUND,
iv + (mAILAGoalPoint - mAILAMax) * mAILAChangeFactor);
audioIO.SetMixer(settings);
auto msg = XO(
"Automated Recording Level Adjustment decreased the volume to %f.").Format( vol );
"Automated Recording Level Adjustment decreased the volume to %f.")
.Format(inputVolume);
ProjectStatus::Get( *proj ).Set(msg);
changetype = 1;
wxPrintf("\tnew vol:%f\n", vol);
float check = Px_GetInputVolume(mPortMixer);
wxPrintf("\tnew vol:%f\n", inputVolume);
auto [_, check, __] = audioIO.GetMixer();
wxPrintf("\tverified %f\n", check);
}
}
Expand All @@ -2431,19 +2438,20 @@ void AudioIO::AILAProcess(double maxPeak) {
wxPrintf("\talready max vol:%f\n", iv);
}
else {
float vol = (float) min(UPPER_BOUND, iv+(mAILAGoalPoint-mAILAMax)*mAILAChangeFactor);
if (vol > mAILATopLevel) {
vol = (iv + mAILATopLevel)/2.0;
wxPrintf("\tTruncated vol:%f\n", vol);
inputVolume = min<float>(UPPER_BOUND,
iv + (mAILAGoalPoint - mAILAMax) * mAILAChangeFactor);
if (inputVolume > mAILATopLevel) {
inputVolume = (iv + mAILATopLevel) / 2.0;
wxPrintf("\tTruncated vol:%f\n", inputVolume);
}
Px_SetInputVolume(mPortMixer, vol);
audioIO.SetMixer(settings);
auto msg = XO(
"Automated Recording Level Adjustment increased the volume to %.2f.")
.Format( vol );
.Format(inputVolume);
ProjectStatus::Get( *proj ).Set(msg);
changetype = 2;
wxPrintf("\tnew vol:%f\n", vol);
float check = Px_GetInputVolume(mPortMixer);
wxPrintf("\tnew vol:%f\n", inputVolume);
auto [_, check, __] = audioIO.GetMixer();
wxPrintf("\tverified %f\n", check);
}
}
Expand Down Expand Up @@ -2483,13 +2491,12 @@ void AudioIO::AILAProcess(double maxPeak) {
else {
auto msg = XO(
"Automated Recording Level Adjustment stopped. %.2f seems an acceptable volume.")
.Format( Px_GetInputVolume(mPortMixer) );
.Format(audioIO.GetMixer().inputVolume);
ProjectStatus::Get( *proj ).Set(msg);
}
}
}
}
#endif
}}

static void DoSoftwarePlaythrough(constSamplePtr inputBuffer,
sampleFormat inputFormat,
Expand Down
50 changes: 26 additions & 24 deletions libraries/lib-audio-io/AudioIO.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@
#include "SampleCount.h"
#include "SampleFormat.h"

// Constants for Experimental::AILA
constexpr auto AILA_DEF_TARGET_PEAK = 92;
constexpr auto AILA_DEF_DELTA_PEAK = 2;
constexpr auto AILA_DEF_ANALYSIS_TIME = 1000;
constexpr auto AILA_DEF_NUMBER_ANALYSIS = 5;

class wxArrayString;
class AudioIOBase;
class AudioIO;
Expand Down Expand Up @@ -246,22 +252,20 @@ class AUDIO_IO_API AudioIoCallback /* not final */
/// How many frames of zeros were output due to pauses?
long mNumPauseFrames;

#ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
bool mAILAActive;
bool mAILAClipped;
int mAILATotalAnalysis;
int mAILAAnalysisCounter;
double mAILAMax;
double mAILAGoalPoint;
double mAILAGoalDelta;
double mAILAAnalysisTime;
double mAILALastStartTime;
double mAILAChangeFactor;
double mAILATopLevel;
double mAILAAnalysisEndTime;
double mAILAAbsolutStartTime;
unsigned short mAILALastChangeType; //0 - no change, 1 - increase change, 2 - decrease change
#endif
bool mAILAActive{ false };
bool mAILAClipped{};
int mAILATotalAnalysis{};
int mAILAAnalysisCounter{};
double mAILAMax{};
double mAILAGoalPoint{};
double mAILAGoalDelta{};
double mAILAAnalysisTime{};
double mAILALastStartTime{};
double mAILAChangeFactor{};
double mAILATopLevel{};
double mAILAAnalysisEndTime{};
double mAILAAbsolutStartTime{};
unsigned short mAILALastChangeType{}; //0 - no change, 1 - increase change, 2 - decrease change

std::thread mAudioThread;
std::atomic<bool> mFinishAudioThread{ false };
Expand Down Expand Up @@ -551,14 +555,12 @@ class AUDIO_IO_API AudioIO final
/** \brief Function to automatically set an acceptable volume
*
*/
#ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
void AILAInitialize();
void AILADisable();
bool AILAIsActive();
void AILAProcess(double maxPeak);
void AILASetStartTime();
double AILAGetLastDecisionTime();
#endif
void AILAInitialize();
void AILADisable();
bool AILAIsActive();
void AILAProcess(double maxPeak);
void AILASetStartTime();
double AILAGetLastDecisionTime();

bool IsAvailable(AudacityProject &project) const;

Expand Down
3 changes: 3 additions & 0 deletions libraries/lib-utility/Experimental.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ constexpr bool FftYGrid = false;
Edward Hui 1 Jul 2021
*/
constexpr bool SpectralBrushTool = false;

// Automatic Input Level Adjustment tries to find an acceptable input volume
constexpr bool AILA = false;
}

#endif
3 changes: 0 additions & 3 deletions src/Experimental.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@ set( EXPERIMENTAL_OPTIONS_LIST
# USE_MIDI must be defined in order for SCOREALIGN to work
#SCOREALIGN

#Automatically tries to find an acceptable input volume
#AUTOMATED_INPUT_LEVEL_ADJUSTMENT

# Define to make the meters look like a row of LEDs
#METER_LED_STYLE

Expand Down
7 changes: 3 additions & 4 deletions src/ProjectAudioManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Paul Licameli split from ProjectManager.cpp
#include "CommandManager.h"
#include "CommonCommandFlags.h"
#include "DefaultPlaybackPolicy.h"
#include "Experimental.h"
#include "Meter.h"
#include "Mix.h"
#include "Project.h"
Expand Down Expand Up @@ -536,9 +537,8 @@ void ProjectAudioManager::Stop(bool stopStream /* = true*/)
projectAudioManager.SetLooping( false );
projectAudioManager.SetCutting( false );

#ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
if constexpr (Experimental::AILA)
gAudioIO->AILADisable();
#endif

projectAudioManager.SetPausedOff();
//Make sure you tell gAudioIO to unpause
Expand Down Expand Up @@ -961,9 +961,8 @@ bool ProjectAudioManager::DoRecord(AudacityProject &project,
}

//Automated Input Level Adjustment Initialization
#ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
if constexpr (Experimental::AILA)
gAudioIO->AILAInitialize();
#endif

int token =
gAudioIO->StartStream(transportSequences, t0, t1, t1, options);
Expand Down
42 changes: 21 additions & 21 deletions src/menus/TransportMenus.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include "AudioIO.h"
#include "../CommonCommandFlags.h"
#include "ConditionallyPresent.h"
#include "DeviceManager.h"
#include "Experimental.h"
#include "../LabelTrack.h"
#include "Prefs.h"
#include "Project.h"
Expand Down Expand Up @@ -437,18 +439,17 @@ void OnToggleSWPlaythrough(const CommandContext &WXUNUSED(context) )
ToolManager::ModifyAllProjectToolbarMenus();
}

#ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
void OnToggleAutomatedInputLevelAdjustment(
const CommandContext &WXUNUSED(context) )
void OnToggleAutomatedInputLevelAdjustment(const CommandContext &)
{
bool AVEnabled;
gPrefs->Read(
wxT("/AudioIO/AutomatedInputLevelAdjustment"), &AVEnabled, false);
gPrefs->Write(wxT("/AudioIO/AutomatedInputLevelAdjustment"), !AVEnabled);
gPrefs->Flush();
ToolManager::ModifyAllProjectToolbarMenus();
if constexpr (Experimental::AILA) {
bool AVEnabled;
gPrefs->Read(
wxT("/AudioIO/AutomatedInputLevelAdjustment"), &AVEnabled, false);
gPrefs->Write(wxT("/AudioIO/AutomatedInputLevelAdjustment"), !AVEnabled);
gPrefs->Flush();
ToolManager::ModifyAllProjectToolbarMenus();
}
}
#endif

void OnStop(const CommandContext &context)
{
Expand Down Expand Up @@ -828,17 +829,6 @@ auto TransportMenu()
OnToggleSWPlaythrough,
AudioIONotBusyFlag() | CanStopAudioStreamFlag(),
Options{}.CheckTest( wxT("/AudioIO/SWPlaythrough"), false ) )


#ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
,
Command( wxT("AutomatedInputLevelAdjustmentOnOff"),
XXO("A&utomated Recording Level Adjustment (on/off)"),
OnToggleAutomatedInputLevelAdjustment,
AudioIONotBusyFlag() | CanStopAudioStreamFlag(),
Options{}.CheckTest(
wxT("/AudioIO/AutomatedInputLevelAdjustment"), false ) )
#endif
)
)
)
Expand All @@ -848,6 +838,16 @@ auto TransportMenu()

AttachedItem sAttachment1{ Indirect(TransportMenu()) };

ConditionallyPresent<AttachedItem, Experimental::AILA>
sAttachment1_1{
Command(wxT("AutomatedInputLevelAdjustmentOnOff"),
XXO("A&utomated Recording Level Adjustment (on/off)"),
OnToggleAutomatedInputLevelAdjustment,
AudioIONotBusyFlag() | CanStopAudioStreamFlag(),
Options{}.CheckTest(L"/AudioIO/AutomatedInputLevelAdjustment", false)),
wxT("Transport/Other/Options/Part2")
};

auto ExtraTransportMenu()
{
static auto menu = std::shared_ptr{
Expand Down
Loading

0 comments on commit de3bc87

Please sign in to comment.