2010-01-23 19:44:49 +00:00
|
|
|
/**********************************************************************
|
|
|
|
|
|
|
|
Audacity: A Digital Audio Editor
|
|
|
|
|
|
|
|
ToneGen.cpp
|
|
|
|
|
|
|
|
Steve Jolly
|
|
|
|
James Crook (Adapted for 'Chirps')
|
|
|
|
|
|
|
|
This class implements a tone generator effect.
|
|
|
|
|
|
|
|
*******************************************************************//**
|
|
|
|
|
|
|
|
\class EffectToneGen
|
|
|
|
\brief An Effect that can generate a sine, square or sawtooth wave.
|
|
|
|
An extended mode of EffectToneGen supports 'chirps' where the
|
|
|
|
frequency changes smoothly during the tone.
|
|
|
|
|
|
|
|
*//*******************************************************************/
|
|
|
|
|
|
|
|
#include "../Audacity.h"
|
2015-06-18 14:24:36 +00:00
|
|
|
#include "ToneGen.h"
|
2019-01-17 23:31:08 +00:00
|
|
|
#include "LoadEffects.h"
|
2015-04-17 03:53:42 +00:00
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
#include <float.h>
|
|
|
|
|
2019-01-22 11:57:30 +00:00
|
|
|
#include <wx/choice.h>
|
2015-04-17 03:53:42 +00:00
|
|
|
#include <wx/intl.h>
|
2015-04-18 17:34:35 +00:00
|
|
|
#include <wx/valgen.h>
|
2015-04-17 03:53:42 +00:00
|
|
|
|
2010-01-23 19:44:49 +00:00
|
|
|
#include "../Project.h"
|
2019-05-29 15:31:40 +00:00
|
|
|
#include "../ProjectSettings.h"
|
2019-02-06 18:44:52 +00:00
|
|
|
#include "../Shuttle.h"
|
2015-06-18 14:24:36 +00:00
|
|
|
#include "../ShuttleGui.h"
|
2015-04-17 03:53:42 +00:00
|
|
|
#include "../widgets/valnum.h"
|
2019-03-30 19:53:54 +00:00
|
|
|
#include "../widgets/NumericTextCtrl.h"
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2015-04-17 03:53:42 +00:00
|
|
|
enum kInterpolations
|
|
|
|
{
|
|
|
|
kLinear,
|
|
|
|
kLogarithmic,
|
2018-02-09 19:12:25 +00:00
|
|
|
nInterpolations
|
2015-04-17 03:53:42 +00:00
|
|
|
};
|
|
|
|
|
2019-02-28 18:16:09 +00:00
|
|
|
static const EnumValueSymbol kInterStrings[nInterpolations] =
|
2015-04-17 03:53:42 +00:00
|
|
|
{
|
2018-03-27 18:17:23 +00:00
|
|
|
// These are acceptable dual purpose internal/visible names
|
2018-03-27 02:03:45 +00:00
|
|
|
{ XO("Linear") },
|
|
|
|
{ XO("Logarithmic") }
|
2015-04-17 03:53:42 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
enum kWaveforms
|
|
|
|
{
|
|
|
|
kSine,
|
|
|
|
kSquare,
|
|
|
|
kSawtooth,
|
|
|
|
kSquareNoAlias,
|
2018-02-09 19:12:25 +00:00
|
|
|
nWaveforms
|
2015-04-17 03:53:42 +00:00
|
|
|
};
|
|
|
|
|
2019-02-28 18:16:09 +00:00
|
|
|
static const EnumValueSymbol kWaveStrings[nWaveforms] =
|
2015-04-17 03:53:42 +00:00
|
|
|
{
|
2018-03-27 02:03:45 +00:00
|
|
|
{ XO("Sine") },
|
|
|
|
{ XO("Square") },
|
|
|
|
{ XO("Sawtooth") },
|
2018-07-05 13:51:24 +00:00
|
|
|
{ XO("Square, no alias") }
|
2015-04-17 03:53:42 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// Define keys, defaults, minimums, and maximums for the effect parameters
|
|
|
|
//
|
2015-04-19 03:49:05 +00:00
|
|
|
// Name Type Key Def Min Max Scale
|
2017-10-03 22:07:04 +00:00
|
|
|
Param( StartFreq, double, wxT("StartFreq"), 440.0, 1.0, DBL_MAX, 1 );
|
|
|
|
Param( EndFreq, double, wxT("EndFreq"), 1320.0, 1.0, DBL_MAX, 1 );
|
|
|
|
Param( StartAmp, double, wxT("StartAmp"), 0.8, 0.0, 1.0, 1 );
|
|
|
|
Param( EndAmp, double, wxT("EndAmp"), 0.1, 0.0, 1.0, 1 );
|
|
|
|
Param( Frequency, double, wxT("Frequency"), 440.0, 1.0, DBL_MAX, 1 );
|
|
|
|
Param( Amplitude, double, wxT("Amplitude"), 0.8, 0.0, 1.0, 1 );
|
2018-02-09 19:12:25 +00:00
|
|
|
Param( Waveform, int, wxT("Waveform"), 0, 0, nWaveforms - 1, 1 );
|
|
|
|
Param( Interp, int, wxT("Interpolation"), 0, 0, nInterpolations - 1, 1 );
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// EffectToneGen
|
|
|
|
//
|
|
|
|
|
2019-01-17 22:33:49 +00:00
|
|
|
const ComponentInterfaceSymbol EffectChirp::Symbol
|
|
|
|
{ XO("Chirp") };
|
|
|
|
|
2019-01-17 23:31:08 +00:00
|
|
|
namespace{ BuiltinEffectsModule::Registration< EffectChirp > reg; }
|
|
|
|
|
2019-01-17 22:33:49 +00:00
|
|
|
const ComponentInterfaceSymbol EffectTone::Symbol
|
|
|
|
{ XO("Tone") };
|
|
|
|
|
2019-01-17 23:31:08 +00:00
|
|
|
namespace{ BuiltinEffectsModule::Registration< EffectTone > reg2; }
|
|
|
|
|
2015-04-17 03:53:42 +00:00
|
|
|
BEGIN_EVENT_TABLE(EffectToneGen, wxEvtHandler)
|
|
|
|
EVT_TEXT(wxID_ANY, EffectToneGen::OnControlUpdate)
|
|
|
|
END_EVENT_TABLE();
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2015-04-17 03:53:42 +00:00
|
|
|
EffectToneGen::EffectToneGen(bool isChirp)
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
2018-02-09 19:12:25 +00:00
|
|
|
wxASSERT(nWaveforms == WXSIZEOF(kWaveStrings));
|
|
|
|
wxASSERT(nInterpolations == WXSIZEOF(kInterStrings));
|
2011-12-20 00:05:54 +00:00
|
|
|
|
2015-04-17 03:53:42 +00:00
|
|
|
mChirp = isChirp;
|
|
|
|
|
|
|
|
mWaveform = DEF_Waveform;
|
|
|
|
mFrequency[0] = DEF_StartFreq;
|
|
|
|
mFrequency[1] = DEF_EndFreq;
|
|
|
|
mAmplitude[0] = DEF_StartAmp;
|
|
|
|
mAmplitude[1] = DEF_EndAmp;
|
|
|
|
mInterpolation = DEF_Interp;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2015-05-15 11:47:51 +00:00
|
|
|
// Chirp varies over time so must use selected duration.
|
|
|
|
// TODO: When previewing, calculate only the first 'preview length'.
|
|
|
|
if (isChirp)
|
|
|
|
SetLinearEffectFlag(false);
|
|
|
|
else
|
|
|
|
SetLinearEffectFlag(true);
|
2010-01-23 19:44:49 +00:00
|
|
|
}
|
|
|
|
|
2015-04-17 03:53:42 +00:00
|
|
|
EffectToneGen::~EffectToneGen()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2018-11-02 15:31:44 +00:00
|
|
|
// ComponentInterface implementation
|
2015-04-17 03:53:42 +00:00
|
|
|
|
2018-11-02 15:31:44 +00:00
|
|
|
ComponentInterfaceSymbol EffectToneGen::GetSymbol()
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
2015-04-17 03:53:42 +00:00
|
|
|
return mChirp
|
2019-01-17 22:33:49 +00:00
|
|
|
? EffectChirp::Symbol
|
|
|
|
: EffectTone::Symbol;
|
2015-04-17 03:53:42 +00:00
|
|
|
}
|
|
|
|
|
2019-12-08 18:53:48 +00:00
|
|
|
TranslatableString EffectToneGen::GetDescription()
|
2015-04-17 03:53:42 +00:00
|
|
|
{
|
|
|
|
return mChirp
|
2019-12-08 18:53:48 +00:00
|
|
|
? XO("Generates an ascending or descending tone of one of four types")
|
|
|
|
: XO("Generates a constant frequency tone of one of four types");
|
2015-04-17 03:53:42 +00:00
|
|
|
}
|
|
|
|
|
2017-05-20 13:40:09 +00:00
|
|
|
wxString EffectToneGen::ManualPage()
|
|
|
|
{
|
|
|
|
return mChirp
|
2017-09-01 16:42:02 +00:00
|
|
|
? wxT("Chirp")
|
|
|
|
: wxT("Tone");
|
2017-05-20 13:40:09 +00:00
|
|
|
}
|
|
|
|
|
Automation: AudacityCommand
This is a squash of 50 commits.
This merges the capabilities of BatchCommands and Effects using a new
AudacityCommand class. AudacityCommand provides one function to specify the
parameters, and then we leverage that one function in automation, whether by chains,
mod-script-pipe or (future) Nyquist.
- Now have AudacityCommand which is using the same mechanism as Effect
- Has configurable parameters
- Has data-entry GUI (built using shuttle GUI)
- Registers with PluginManager.
- Menu commands now provided in chains, and to python batch.
- Tested with Zoom Toggle.
- ShuttleParams now can set, get, set defaults, validate and specify
the parameters.
- Bugfix: Don't overwrite values with defaults first time out.
- Add DefineParams function for all built-in effects.
- Extend CommandContext to carry output channels for results.
We abuse EffectsManager. It handles both Effects and
AudacityCommands now. In time an Effect should become a special case of
AudacityCommand and we'll split and rename the EffectManager class.
- Don't use 'default' as a parameter name.
- Massive renaming for CommandDefinitionInterface
- EffectIdentInterface becomes EffectDefinitionInterface
- EffectAutomationParameters becomes CommandAutomationParameters
- PluginType is now a bit field.
This way we can search for related types at the same time.
- Most old batch commands made into AudacityCommands.
The ones that weren't are for a reason. They are used by mod-script-pipe
to carry commands and responses across from a non-GUI thread to the GUI
thread.
- Major tidy up of ScreenshotCommand
- Reworking of SelectCommand
- GetPreferenceCommand and SetPreferenceCommand
- GetTrackInfo and SetTrackInfo
- GetInfoCommand
- Help, Open, Save, Import and Export commands.
- Removed obsolete commands ExecMenu, GetProjectInfo and SetProjectInfo
which are now better handled by other commands.
- JSONify "GetInfo: Commands" output, i.e. commas in the right places.
- General work on better Doxygen.
- Lyrics -> LyricsPanel
- Meter -> MeterPanel
- Updated Linux makefile.
- Scripting commands added into Extra menu.
- Distinct names for previously duplicated find-clipping parameters.
- Fixed longstanding error with erroneous status field number which
previously caused an ASSERT in debug.
- Sensible formatting of numbers in Chains, 0.1 not 0.1000000000137
2018-01-14 18:51:41 +00:00
|
|
|
// EffectDefinitionInterface implementation
|
2015-04-17 03:53:42 +00:00
|
|
|
|
|
|
|
EffectType EffectToneGen::GetType()
|
|
|
|
{
|
|
|
|
return EffectTypeGenerate;
|
|
|
|
}
|
|
|
|
|
|
|
|
// EffectClientInterface implementation
|
|
|
|
|
2016-09-02 19:53:09 +00:00
|
|
|
unsigned EffectToneGen::GetAudioOutCount()
|
2015-04-17 03:53:42 +00:00
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool EffectToneGen::ProcessInitialize(sampleCount WXUNUSED(totalLen), ChannelNames WXUNUSED(chanMap))
|
|
|
|
{
|
|
|
|
mPositionInCycles = 0.0;
|
|
|
|
mSample = 0;
|
|
|
|
|
2010-01-23 19:44:49 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-09-06 13:19:27 +00:00
|
|
|
size_t EffectToneGen::ProcessBlock(float **WXUNUSED(inBlock), float **outBlock, size_t blockLen)
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
2015-04-17 03:53:42 +00:00
|
|
|
float *buffer = outBlock[0];
|
2010-01-23 19:44:49 +00:00
|
|
|
double throwaway = 0; //passed to modf but never used
|
|
|
|
double f = 0.0;
|
2015-04-17 03:53:42 +00:00
|
|
|
double a, b;
|
2013-05-19 10:00:12 +00:00
|
|
|
int k;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2013-05-19 10:00:20 +00:00
|
|
|
double frequencyQuantum;
|
2010-01-23 19:44:49 +00:00
|
|
|
double BlendedFrequency;
|
|
|
|
double BlendedAmplitude;
|
2015-04-17 03:53:42 +00:00
|
|
|
double BlendedLogFrequency = 0.0;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
// calculate delta, and reposition from where we left
|
2016-08-25 12:53:59 +00:00
|
|
|
auto doubleSampleCount = mSampleCnt.as_double();
|
|
|
|
auto doubleSample = mSample.as_double();
|
|
|
|
double amplitudeQuantum =
|
|
|
|
(mAmplitude[1] - mAmplitude[0]) / doubleSampleCount;
|
|
|
|
BlendedAmplitude = mAmplitude[0] +
|
|
|
|
amplitudeQuantum * doubleSample;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
// precalculations:
|
2015-04-17 03:53:42 +00:00
|
|
|
double pre2PI = 2.0 * M_PI;
|
|
|
|
double pre4divPI = 4.0 / M_PI;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2013-05-19 10:00:20 +00:00
|
|
|
// initial setup should calculate deltas
|
2015-04-17 03:53:42 +00:00
|
|
|
if (mInterpolation == kLogarithmic)
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
2013-05-19 10:00:20 +00:00
|
|
|
// this for log interpolation
|
2015-04-17 03:53:42 +00:00
|
|
|
mLogFrequency[0] = log10(mFrequency[0]);
|
|
|
|
mLogFrequency[1] = log10(mFrequency[1]);
|
2010-01-23 19:44:49 +00:00
|
|
|
// calculate delta, and reposition from where we left
|
2016-08-25 12:53:59 +00:00
|
|
|
frequencyQuantum = (mLogFrequency[1] - mLogFrequency[0]) / doubleSampleCount;
|
|
|
|
BlendedLogFrequency = mLogFrequency[0] + frequencyQuantum * doubleSample;
|
2015-04-17 03:53:42 +00:00
|
|
|
BlendedFrequency = pow(10.0, BlendedLogFrequency);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-01-23 19:44:49 +00:00
|
|
|
// this for regular case, linear interpolation
|
2016-08-25 12:53:59 +00:00
|
|
|
frequencyQuantum = (mFrequency[1] - mFrequency[0]) / doubleSampleCount;
|
|
|
|
BlendedFrequency = mFrequency[0] + frequencyQuantum * doubleSample;
|
2013-05-19 10:00:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// synth loop
|
2016-08-24 15:24:26 +00:00
|
|
|
for (decltype(blockLen) i = 0; i < blockLen; i++)
|
2015-04-17 03:53:42 +00:00
|
|
|
{
|
|
|
|
switch (mWaveform)
|
|
|
|
{
|
|
|
|
case kSine:
|
|
|
|
f = sin(pre2PI * mPositionInCycles / mSampleRate);
|
2013-05-19 10:00:20 +00:00
|
|
|
break;
|
2015-04-17 03:53:42 +00:00
|
|
|
case kSquare:
|
|
|
|
f = (modf(mPositionInCycles / mSampleRate, &throwaway) < 0.5) ? 1.0 : -1.0;
|
2013-05-19 10:00:20 +00:00
|
|
|
break;
|
2015-04-17 03:53:42 +00:00
|
|
|
case kSawtooth:
|
|
|
|
f = (2.0 * modf(mPositionInCycles / mSampleRate + 0.5, &throwaway)) - 1.0;
|
2013-05-19 10:00:20 +00:00
|
|
|
break;
|
2015-04-17 03:53:42 +00:00
|
|
|
case kSquareNoAlias: // Good down to 110Hz @ 44100Hz sampling.
|
2013-05-19 10:00:20 +00:00
|
|
|
//do fundamental (k=1) outside loop
|
2015-04-17 03:53:42 +00:00
|
|
|
b = (1.0 + cos((pre2PI * BlendedFrequency) / mSampleRate)) / pre4divPI; //scaling
|
|
|
|
f = pre4divPI * sin(pre2PI * mPositionInCycles / mSampleRate);
|
|
|
|
for (k = 3; (k < 200) && (k * BlendedFrequency < mSampleRate / 2.0); k += 2)
|
|
|
|
{
|
2019-03-14 10:10:20 +00:00
|
|
|
//Hann Window in freq domain
|
2015-04-17 03:53:42 +00:00
|
|
|
a = 1.0 + cos((pre2PI * k * BlendedFrequency) / mSampleRate);
|
|
|
|
//calc harmonic, apply window, scale to amplitude of fundamental
|
|
|
|
f += a * sin(pre2PI * mPositionInCycles / mSampleRate * k) / (b * k);
|
|
|
|
}
|
2013-05-19 10:00:20 +00:00
|
|
|
}
|
|
|
|
// insert value in buffer
|
2015-04-17 03:53:42 +00:00
|
|
|
buffer[i] = (float) (BlendedAmplitude * f);
|
2013-05-19 10:00:20 +00:00
|
|
|
// update freq,amplitude
|
|
|
|
mPositionInCycles += BlendedFrequency;
|
|
|
|
BlendedAmplitude += amplitudeQuantum;
|
2015-04-17 03:53:42 +00:00
|
|
|
if (mInterpolation == kLogarithmic)
|
|
|
|
{
|
2013-05-19 10:00:20 +00:00
|
|
|
BlendedLogFrequency += frequencyQuantum;
|
2015-04-17 03:53:42 +00:00
|
|
|
BlendedFrequency = pow(10.0, BlendedLogFrequency);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-01-23 19:44:49 +00:00
|
|
|
BlendedFrequency += frequencyQuantum;
|
|
|
|
}
|
|
|
|
}
|
2013-05-19 10:00:20 +00:00
|
|
|
|
2010-01-23 19:44:49 +00:00
|
|
|
// update external placeholder
|
2015-04-17 03:53:42 +00:00
|
|
|
mSample += blockLen;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2015-04-17 03:53:42 +00:00
|
|
|
return blockLen;
|
2010-01-23 19:44:49 +00:00
|
|
|
}
|
|
|
|
|
Automation: AudacityCommand
This is a squash of 50 commits.
This merges the capabilities of BatchCommands and Effects using a new
AudacityCommand class. AudacityCommand provides one function to specify the
parameters, and then we leverage that one function in automation, whether by chains,
mod-script-pipe or (future) Nyquist.
- Now have AudacityCommand which is using the same mechanism as Effect
- Has configurable parameters
- Has data-entry GUI (built using shuttle GUI)
- Registers with PluginManager.
- Menu commands now provided in chains, and to python batch.
- Tested with Zoom Toggle.
- ShuttleParams now can set, get, set defaults, validate and specify
the parameters.
- Bugfix: Don't overwrite values with defaults first time out.
- Add DefineParams function for all built-in effects.
- Extend CommandContext to carry output channels for results.
We abuse EffectsManager. It handles both Effects and
AudacityCommands now. In time an Effect should become a special case of
AudacityCommand and we'll split and rename the EffectManager class.
- Don't use 'default' as a parameter name.
- Massive renaming for CommandDefinitionInterface
- EffectIdentInterface becomes EffectDefinitionInterface
- EffectAutomationParameters becomes CommandAutomationParameters
- PluginType is now a bit field.
This way we can search for related types at the same time.
- Most old batch commands made into AudacityCommands.
The ones that weren't are for a reason. They are used by mod-script-pipe
to carry commands and responses across from a non-GUI thread to the GUI
thread.
- Major tidy up of ScreenshotCommand
- Reworking of SelectCommand
- GetPreferenceCommand and SetPreferenceCommand
- GetTrackInfo and SetTrackInfo
- GetInfoCommand
- Help, Open, Save, Import and Export commands.
- Removed obsolete commands ExecMenu, GetProjectInfo and SetProjectInfo
which are now better handled by other commands.
- JSONify "GetInfo: Commands" output, i.e. commas in the right places.
- General work on better Doxygen.
- Lyrics -> LyricsPanel
- Meter -> MeterPanel
- Updated Linux makefile.
- Scripting commands added into Extra menu.
- Distinct names for previously duplicated find-clipping parameters.
- Fixed longstanding error with erroneous status field number which
previously caused an ASSERT in debug.
- Sensible formatting of numbers in Chains, 0.1 not 0.1000000000137
2018-01-14 18:51:41 +00:00
|
|
|
bool EffectToneGen::DefineParams( ShuttleParams & S ){
|
|
|
|
if( mChirp ){
|
|
|
|
S.SHUTTLE_PARAM( mFrequency[0], StartFreq );
|
|
|
|
S.SHUTTLE_PARAM( mFrequency[1], EndFreq );
|
|
|
|
S.SHUTTLE_PARAM( mAmplitude[0], StartAmp );
|
|
|
|
S.SHUTTLE_PARAM( mAmplitude[1], EndAmp );
|
|
|
|
} else {
|
|
|
|
S.SHUTTLE_PARAM( mFrequency[0], Frequency );
|
|
|
|
S.SHUTTLE_PARAM( mAmplitude[0], Amplitude );
|
2018-02-16 12:49:47 +00:00
|
|
|
// Slightly hacky way to set freq and ampl
|
|
|
|
// since we do this whatever query to params was made.
|
|
|
|
mFrequency[1] = mFrequency[0];
|
|
|
|
mAmplitude[1] = mAmplitude[0];
|
Automation: AudacityCommand
This is a squash of 50 commits.
This merges the capabilities of BatchCommands and Effects using a new
AudacityCommand class. AudacityCommand provides one function to specify the
parameters, and then we leverage that one function in automation, whether by chains,
mod-script-pipe or (future) Nyquist.
- Now have AudacityCommand which is using the same mechanism as Effect
- Has configurable parameters
- Has data-entry GUI (built using shuttle GUI)
- Registers with PluginManager.
- Menu commands now provided in chains, and to python batch.
- Tested with Zoom Toggle.
- ShuttleParams now can set, get, set defaults, validate and specify
the parameters.
- Bugfix: Don't overwrite values with defaults first time out.
- Add DefineParams function for all built-in effects.
- Extend CommandContext to carry output channels for results.
We abuse EffectsManager. It handles both Effects and
AudacityCommands now. In time an Effect should become a special case of
AudacityCommand and we'll split and rename the EffectManager class.
- Don't use 'default' as a parameter name.
- Massive renaming for CommandDefinitionInterface
- EffectIdentInterface becomes EffectDefinitionInterface
- EffectAutomationParameters becomes CommandAutomationParameters
- PluginType is now a bit field.
This way we can search for related types at the same time.
- Most old batch commands made into AudacityCommands.
The ones that weren't are for a reason. They are used by mod-script-pipe
to carry commands and responses across from a non-GUI thread to the GUI
thread.
- Major tidy up of ScreenshotCommand
- Reworking of SelectCommand
- GetPreferenceCommand and SetPreferenceCommand
- GetTrackInfo and SetTrackInfo
- GetInfoCommand
- Help, Open, Save, Import and Export commands.
- Removed obsolete commands ExecMenu, GetProjectInfo and SetProjectInfo
which are now better handled by other commands.
- JSONify "GetInfo: Commands" output, i.e. commas in the right places.
- General work on better Doxygen.
- Lyrics -> LyricsPanel
- Meter -> MeterPanel
- Updated Linux makefile.
- Scripting commands added into Extra menu.
- Distinct names for previously duplicated find-clipping parameters.
- Fixed longstanding error with erroneous status field number which
previously caused an ASSERT in debug.
- Sensible formatting of numbers in Chains, 0.1 not 0.1000000000137
2018-01-14 18:51:41 +00:00
|
|
|
}
|
2018-03-27 01:06:35 +00:00
|
|
|
S.SHUTTLE_ENUM_PARAM( mWaveform, Waveform, kWaveStrings, nWaveforms );
|
|
|
|
S.SHUTTLE_ENUM_PARAM( mInterpolation, Interp, kInterStrings, nInterpolations );
|
Automation: AudacityCommand
This is a squash of 50 commits.
This merges the capabilities of BatchCommands and Effects using a new
AudacityCommand class. AudacityCommand provides one function to specify the
parameters, and then we leverage that one function in automation, whether by chains,
mod-script-pipe or (future) Nyquist.
- Now have AudacityCommand which is using the same mechanism as Effect
- Has configurable parameters
- Has data-entry GUI (built using shuttle GUI)
- Registers with PluginManager.
- Menu commands now provided in chains, and to python batch.
- Tested with Zoom Toggle.
- ShuttleParams now can set, get, set defaults, validate and specify
the parameters.
- Bugfix: Don't overwrite values with defaults first time out.
- Add DefineParams function for all built-in effects.
- Extend CommandContext to carry output channels for results.
We abuse EffectsManager. It handles both Effects and
AudacityCommands now. In time an Effect should become a special case of
AudacityCommand and we'll split and rename the EffectManager class.
- Don't use 'default' as a parameter name.
- Massive renaming for CommandDefinitionInterface
- EffectIdentInterface becomes EffectDefinitionInterface
- EffectAutomationParameters becomes CommandAutomationParameters
- PluginType is now a bit field.
This way we can search for related types at the same time.
- Most old batch commands made into AudacityCommands.
The ones that weren't are for a reason. They are used by mod-script-pipe
to carry commands and responses across from a non-GUI thread to the GUI
thread.
- Major tidy up of ScreenshotCommand
- Reworking of SelectCommand
- GetPreferenceCommand and SetPreferenceCommand
- GetTrackInfo and SetTrackInfo
- GetInfoCommand
- Help, Open, Save, Import and Export commands.
- Removed obsolete commands ExecMenu, GetProjectInfo and SetProjectInfo
which are now better handled by other commands.
- JSONify "GetInfo: Commands" output, i.e. commas in the right places.
- General work on better Doxygen.
- Lyrics -> LyricsPanel
- Meter -> MeterPanel
- Updated Linux makefile.
- Scripting commands added into Extra menu.
- Distinct names for previously duplicated find-clipping parameters.
- Fixed longstanding error with erroneous status field number which
previously caused an ASSERT in debug.
- Sensible formatting of numbers in Chains, 0.1 not 0.1000000000137
2018-01-14 18:51:41 +00:00
|
|
|
|
|
|
|
|
2019-05-21 18:38:43 +00:00
|
|
|
// double freqMax = (FindProject() ? FindProject()->GetRate() : 44100.0) / 2.0;
|
Automation: AudacityCommand
This is a squash of 50 commits.
This merges the capabilities of BatchCommands and Effects using a new
AudacityCommand class. AudacityCommand provides one function to specify the
parameters, and then we leverage that one function in automation, whether by chains,
mod-script-pipe or (future) Nyquist.
- Now have AudacityCommand which is using the same mechanism as Effect
- Has configurable parameters
- Has data-entry GUI (built using shuttle GUI)
- Registers with PluginManager.
- Menu commands now provided in chains, and to python batch.
- Tested with Zoom Toggle.
- ShuttleParams now can set, get, set defaults, validate and specify
the parameters.
- Bugfix: Don't overwrite values with defaults first time out.
- Add DefineParams function for all built-in effects.
- Extend CommandContext to carry output channels for results.
We abuse EffectsManager. It handles both Effects and
AudacityCommands now. In time an Effect should become a special case of
AudacityCommand and we'll split and rename the EffectManager class.
- Don't use 'default' as a parameter name.
- Massive renaming for CommandDefinitionInterface
- EffectIdentInterface becomes EffectDefinitionInterface
- EffectAutomationParameters becomes CommandAutomationParameters
- PluginType is now a bit field.
This way we can search for related types at the same time.
- Most old batch commands made into AudacityCommands.
The ones that weren't are for a reason. They are used by mod-script-pipe
to carry commands and responses across from a non-GUI thread to the GUI
thread.
- Major tidy up of ScreenshotCommand
- Reworking of SelectCommand
- GetPreferenceCommand and SetPreferenceCommand
- GetTrackInfo and SetTrackInfo
- GetInfoCommand
- Help, Open, Save, Import and Export commands.
- Removed obsolete commands ExecMenu, GetProjectInfo and SetProjectInfo
which are now better handled by other commands.
- JSONify "GetInfo: Commands" output, i.e. commas in the right places.
- General work on better Doxygen.
- Lyrics -> LyricsPanel
- Meter -> MeterPanel
- Updated Linux makefile.
- Scripting commands added into Extra menu.
- Distinct names for previously duplicated find-clipping parameters.
- Fixed longstanding error with erroneous status field number which
previously caused an ASSERT in debug.
- Sensible formatting of numbers in Chains, 0.1 not 0.1000000000137
2018-01-14 18:51:41 +00:00
|
|
|
// mFrequency[1] = TrapDouble(mFrequency[1], MIN_EndFreq, freqMax);
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-02-21 14:24:25 +00:00
|
|
|
bool EffectToneGen::GetAutomationParameters(CommandParameters & parms)
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
2015-04-17 03:53:42 +00:00
|
|
|
if (mChirp)
|
|
|
|
{
|
|
|
|
parms.Write(KEY_StartFreq, mFrequency[0]);
|
|
|
|
parms.Write(KEY_EndFreq, mFrequency[1]);
|
|
|
|
parms.Write(KEY_StartAmp, mAmplitude[0]);
|
|
|
|
parms.Write(KEY_EndAmp, mAmplitude[1]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
parms.Write(KEY_Frequency, mFrequency[0]);
|
|
|
|
parms.Write(KEY_Amplitude, mAmplitude[0]);
|
|
|
|
}
|
|
|
|
|
2018-03-27 02:03:45 +00:00
|
|
|
parms.Write(KEY_Waveform, kWaveStrings[mWaveform].Internal());
|
|
|
|
parms.Write(KEY_Interp, kInterStrings[mInterpolation].Internal());
|
2015-04-17 03:53:42 +00:00
|
|
|
|
|
|
|
return true;
|
2010-01-23 19:44:49 +00:00
|
|
|
}
|
|
|
|
|
2018-02-21 14:24:25 +00:00
|
|
|
bool EffectToneGen::SetAutomationParameters(CommandParameters & parms)
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
2018-03-27 01:06:35 +00:00
|
|
|
ReadAndVerifyEnum(Waveform, kWaveStrings, nWaveforms);
|
|
|
|
ReadAndVerifyEnum(Interp, kInterStrings, nInterpolations);
|
2015-04-17 03:53:42 +00:00
|
|
|
if (mChirp)
|
|
|
|
{
|
|
|
|
ReadAndVerifyDouble(StartFreq);
|
|
|
|
ReadAndVerifyDouble(EndFreq);
|
|
|
|
ReadAndVerifyDouble(StartAmp);
|
|
|
|
ReadAndVerifyDouble(EndAmp);
|
|
|
|
mFrequency[0] = StartFreq;
|
|
|
|
mFrequency[1] = EndFreq;
|
|
|
|
mAmplitude[0] = StartAmp;
|
|
|
|
mAmplitude[1] = EndAmp;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ReadAndVerifyDouble(Frequency);
|
|
|
|
ReadAndVerifyDouble(Amplitude);
|
|
|
|
mFrequency[0] = Frequency;
|
|
|
|
mFrequency[1] = Frequency;
|
|
|
|
mAmplitude[0] = Amplitude;
|
|
|
|
mAmplitude[1] = Amplitude;
|
|
|
|
}
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2015-04-17 03:53:42 +00:00
|
|
|
mWaveform = Waveform;
|
|
|
|
mInterpolation = Interp;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2019-05-27 14:17:16 +00:00
|
|
|
double freqMax =
|
2019-05-21 18:38:43 +00:00
|
|
|
(FindProject()
|
|
|
|
? ProjectSettings::Get( *FindProject() ).GetRate()
|
2019-05-27 14:17:16 +00:00
|
|
|
: 44100.0)
|
|
|
|
/ 2.0;
|
2015-04-17 03:53:42 +00:00
|
|
|
mFrequency[1] = TrapDouble(mFrequency[1], MIN_EndFreq, freqMax);
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2015-04-17 03:53:42 +00:00
|
|
|
return true;
|
|
|
|
}
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2015-04-17 03:53:42 +00:00
|
|
|
// Effect implementation
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2015-04-17 03:53:42 +00:00
|
|
|
void EffectToneGen::PopulateOrExchange(ShuttleGui & S)
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
2015-04-17 03:53:42 +00:00
|
|
|
wxTextCtrl *t;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
S.StartMultiColumn(2, wxCENTER);
|
|
|
|
{
|
2017-10-30 16:23:41 +00:00
|
|
|
S.Validator<wxGenericValidator>(&mWaveform)
|
2020-05-11 15:28:14 +00:00
|
|
|
.AddChoice(XXO("&Waveform:"),
|
2019-12-18 03:52:42 +00:00
|
|
|
Msgids( kWaveStrings, nWaveforms ) );
|
2015-04-17 03:53:42 +00:00
|
|
|
|
|
|
|
if (mChirp)
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
2017-09-28 01:20:14 +00:00
|
|
|
S.AddFixedText( {} );
|
2015-04-17 03:53:42 +00:00
|
|
|
S.StartHorizontalLay(wxEXPAND);
|
|
|
|
{
|
|
|
|
S.StartHorizontalLay(wxLEFT, 50);
|
|
|
|
{
|
2019-12-22 23:14:40 +00:00
|
|
|
S.AddTitle(XO("Start"));
|
2015-04-17 03:53:42 +00:00
|
|
|
}
|
|
|
|
S.EndHorizontalLay();
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2015-04-17 03:53:42 +00:00
|
|
|
S.StartHorizontalLay(wxLEFT, 50);
|
|
|
|
{
|
2019-12-22 23:14:40 +00:00
|
|
|
S.AddTitle(XO("End"));
|
2015-04-17 03:53:42 +00:00
|
|
|
}
|
|
|
|
S.EndHorizontalLay();
|
|
|
|
}
|
|
|
|
S.EndHorizontalLay();
|
|
|
|
|
2020-05-11 15:28:14 +00:00
|
|
|
S.AddPrompt(XXO("&Frequency (Hz):"));
|
2015-04-17 03:53:42 +00:00
|
|
|
S.StartHorizontalLay(wxEXPAND);
|
|
|
|
{
|
|
|
|
S.StartHorizontalLay(wxLEFT, 50);
|
|
|
|
{
|
2017-10-29 14:27:23 +00:00
|
|
|
t = S.Name(XO("Frequency Hertz Start"))
|
2017-10-30 16:23:41 +00:00
|
|
|
.Validator<FloatingPointValidator<double>>(
|
|
|
|
6, &mFrequency[0],
|
|
|
|
NumValidatorStyle::NO_TRAILING_ZEROES,
|
|
|
|
MIN_StartFreq,
|
2020-01-07 19:28:48 +00:00
|
|
|
mProjectRate / 2.0
|
2017-10-30 16:23:41 +00:00
|
|
|
)
|
|
|
|
.AddTextBox( {}, wxT(""), 12);
|
2015-04-17 03:53:42 +00:00
|
|
|
}
|
|
|
|
S.EndHorizontalLay();
|
|
|
|
|
|
|
|
S.StartHorizontalLay(wxLEFT, 50);
|
|
|
|
{
|
2017-10-29 14:27:23 +00:00
|
|
|
t = S.Name(XO("Frequency Hertz End"))
|
2017-10-30 16:23:41 +00:00
|
|
|
.Validator<FloatingPointValidator<double>>(
|
|
|
|
6, &mFrequency[1],
|
|
|
|
NumValidatorStyle::NO_TRAILING_ZEROES,
|
|
|
|
MIN_EndFreq,
|
2020-01-07 19:28:48 +00:00
|
|
|
mProjectRate / 2.0
|
2017-10-30 16:23:41 +00:00
|
|
|
)
|
|
|
|
.AddTextBox( {}, wxT(""), 12);
|
2015-04-17 03:53:42 +00:00
|
|
|
}
|
|
|
|
S.EndHorizontalLay();
|
|
|
|
}
|
|
|
|
S.EndHorizontalLay();
|
|
|
|
|
2020-05-11 15:28:14 +00:00
|
|
|
S.AddPrompt(XXO("&Amplitude (0-1):"));
|
2015-04-17 03:53:42 +00:00
|
|
|
S.StartHorizontalLay(wxEXPAND);
|
|
|
|
{
|
|
|
|
S.StartHorizontalLay(wxLEFT, 50);
|
|
|
|
{
|
2017-10-29 14:27:23 +00:00
|
|
|
t = S.Name(XO("Amplitude Start"))
|
2017-10-30 16:23:41 +00:00
|
|
|
.Validator<FloatingPointValidator<double>>(
|
|
|
|
6, &mAmplitude[0], NumValidatorStyle::NO_TRAILING_ZEROES,
|
|
|
|
MIN_StartAmp, MAX_StartAmp
|
|
|
|
)
|
|
|
|
.AddTextBox( {}, wxT(""), 12);
|
2015-04-17 03:53:42 +00:00
|
|
|
}
|
|
|
|
S.EndHorizontalLay();
|
|
|
|
|
|
|
|
S.StartHorizontalLay(wxLEFT, 50);
|
|
|
|
{
|
2017-10-29 14:27:23 +00:00
|
|
|
t = S.Name(XO("Amplitude End"))
|
2017-10-30 16:23:41 +00:00
|
|
|
.Validator<FloatingPointValidator<double>>(
|
|
|
|
6, &mAmplitude[1], NumValidatorStyle::NO_TRAILING_ZEROES,
|
|
|
|
MIN_EndAmp, MAX_EndAmp
|
|
|
|
)
|
|
|
|
.AddTextBox( {}, wxT(""), 12);
|
2015-04-17 03:53:42 +00:00
|
|
|
}
|
|
|
|
S.EndHorizontalLay();
|
|
|
|
}
|
|
|
|
S.EndHorizontalLay();
|
2015-04-18 17:34:35 +00:00
|
|
|
|
2017-10-30 16:23:41 +00:00
|
|
|
S.Validator<wxGenericValidator>(&mInterpolation)
|
2020-05-11 15:28:14 +00:00
|
|
|
.AddChoice(XXO("I&nterpolation:"),
|
2019-12-18 03:52:42 +00:00
|
|
|
Msgids( kInterStrings, nInterpolations ) );
|
2015-04-17 03:53:42 +00:00
|
|
|
}
|
|
|
|
else
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
2017-10-30 16:23:41 +00:00
|
|
|
t = S.Validator<FloatingPointValidator<double>>(
|
|
|
|
6, &mFrequency[0], NumValidatorStyle::NO_TRAILING_ZEROES,
|
|
|
|
MIN_Frequency,
|
2020-01-07 19:28:48 +00:00
|
|
|
mProjectRate / 2.0
|
2017-10-30 16:23:41 +00:00
|
|
|
)
|
2020-05-11 15:28:14 +00:00
|
|
|
.AddTextBox(XXO("&Frequency (Hz):"), wxT(""), 12);
|
2017-10-30 16:23:41 +00:00
|
|
|
|
|
|
|
t = S.Validator<FloatingPointValidator<double>>(
|
|
|
|
6, &mAmplitude[0], NumValidatorStyle::NO_TRAILING_ZEROES,
|
|
|
|
MIN_Amplitude, MAX_Amplitude
|
|
|
|
)
|
2020-05-11 15:28:14 +00:00
|
|
|
.AddTextBox(XXO("&Amplitude (0-1):"), wxT(""), 12);
|
2010-01-23 19:44:49 +00:00
|
|
|
}
|
2015-04-17 03:53:42 +00:00
|
|
|
|
2020-05-11 15:28:14 +00:00
|
|
|
S.AddPrompt(XXO("&Duration:"));
|
2016-02-14 07:54:25 +00:00
|
|
|
mToneDurationT = safenew
|
2017-10-27 23:14:48 +00:00
|
|
|
NumericTextCtrl(S.GetParent(), wxID_ANY,
|
|
|
|
NumericConverter::TIME,
|
2015-05-27 13:42:15 +00:00
|
|
|
GetDurationFormat(),
|
|
|
|
GetDuration(),
|
|
|
|
mProjectRate,
|
2017-10-27 23:14:48 +00:00
|
|
|
NumericTextCtrl::Options{}
|
|
|
|
.AutoPos(true));
|
2017-10-29 14:27:23 +00:00
|
|
|
S.Name(XO("Duration"))
|
2017-10-31 23:44:00 +00:00
|
|
|
.Position(wxALIGN_LEFT | wxALL)
|
|
|
|
.AddWindow(mToneDurationT);
|
2010-01-23 19:44:49 +00:00
|
|
|
}
|
|
|
|
S.EndMultiColumn();
|
|
|
|
|
2015-04-17 03:53:42 +00:00
|
|
|
return;
|
2010-01-23 19:44:49 +00:00
|
|
|
}
|
|
|
|
|
2015-04-17 03:53:42 +00:00
|
|
|
bool EffectToneGen::TransferDataToWindow()
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
2015-04-17 03:53:42 +00:00
|
|
|
if (!mUIParent->TransferDataToWindow())
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2015-04-20 00:44:10 +00:00
|
|
|
mToneDurationT->SetValue(GetDuration());
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-04-17 03:53:42 +00:00
|
|
|
bool EffectToneGen::TransferDataFromWindow()
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
2015-04-17 03:53:42 +00:00
|
|
|
if (!mUIParent->Validate() || !mUIParent->TransferDataFromWindow())
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2015-04-17 03:53:42 +00:00
|
|
|
if (!mChirp)
|
|
|
|
{
|
|
|
|
mFrequency[1] = mFrequency[0];
|
|
|
|
mAmplitude[1] = mAmplitude[0];
|
|
|
|
}
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2015-04-20 00:44:10 +00:00
|
|
|
SetDuration(mToneDurationT->GetValue());
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-04-17 03:53:42 +00:00
|
|
|
// EffectToneGen implementation
|
|
|
|
|
|
|
|
void EffectToneGen::OnControlUpdate(wxCommandEvent & WXUNUSED(evt))
|
|
|
|
{
|
|
|
|
if (!EnableApply(mUIParent->TransferDataFromWindow()))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2010-01-23 19:44:49 +00:00
|
|
|
}
|