23#include <wx/valtext.h>
24#include <wx/stattext.h>
27#include "../ShuttleGui.h"
28#include "../widgets/NumericTextCtrl.h"
29#include "../widgets/valnum.h"
43 if (s.dtmfSequence.find_first_not_of(
AllSymbols())
58 wxT(
"0"), wxT(
"1"), wxT(
"2"), wxT(
"3"),
59 wxT(
"4"), wxT(
"5"), wxT(
"6"), wxT(
"7"),
60 wxT(
"8"), wxT(
"9"), wxT(
"*"), wxT(
"#"),
61 wxT(
"A"), wxT(
"B"), wxT(
"C"), wxT(
"D"),
62 wxT(
"a"), wxT(
"b"), wxT(
"c"), wxT(
"d"),
63 wxT(
"e"), wxT(
"f"), wxT(
"g"), wxT(
"h"),
64 wxT(
"i"), wxT(
"j"), wxT(
"k"), wxT(
"l"),
65 wxT(
"m"), wxT(
"n"), wxT(
"o"), wxT(
"p"),
66 wxT(
"q"), wxT(
"r"), wxT(
"s"), wxT(
"t"),
67 wxT(
"u"), wxT(
"v"), wxT(
"w"), wxT(
"x"),
75 for (
unsigned int i = 0; i < WXSIZEOF(
kSymbols); ++i)
107 return XO(
"Generates dual-tone multi-frequency (DTMF) tones like those produced by the keypad on telephones");
112 return L
"DTMF_Tones";
140 const float *
const *inBlock,
float *
const *outBlock,
size_t blockLen)
162 if (dtmfSettings.dtmfNTones == 0) {
165 XO(
"DTMF sequence empty.\nCheck ALL settings for this effect."),
171 double duration =
settings.extra.GetDuration();
193 while (
diff > 2 * dtmfSettings.dtmfNTones - 1) {
199 wxASSERT(dtmfSettings.dtmfNTones > 1);
215 const float *
const *,
float *
const *outbuf,
size_t size)
218 float *buffer = outbuf[0];
219 decltype(
size) processed = 0;
240 if (numRemaining == 0)
247 numRemaining = numSamplesTone;
252 numRemaining = numSamplesSilence;
257 numRemaining += (diff-- > 0 ? 1 : 0);
266 dtmfSettings.dtmfSequence[curSeqPos], curTonePos, numSamplesTone,
267 dtmfSettings.dtmfAmplitude);
272 memset(buffer, 0,
sizeof(
float) * len);
324 auto &dtmfSettings = mSettings;
338 S.StartMultiColumn(2, wxCENTER);
342 .Validator([&dtmfSettings]{
343 wxTextValidator vldDtmf(
344 wxFILTER_INCLUDE_CHAR_LIST, &dtmfSettings.dtmfSequence);
348 .AddTextBox(
XXO(
"DTMF &sequence:"), wxT(
""), 10);
354 .Validator<FloatingPointValidator<double>>(
355 3, &dtmfSettings.dtmfAmplitude, NumValidatorStyle::NO_TRAILING_ZEROES,
357 .AddTextBox(
XXO(
"&Amplitude (0-1):"), wxT(
""), 10);
359 S.AddPrompt(
XXO(
"&Duration:"));
364 extra.GetDurationFormat(),
369 S.Name(
XO(
"Duration"))
370 .AddWindow(mDtmfDurationT);
373 S.AddFixedText(
XO(
"&Tone/silence ratio:"),
false);
376 .Style(wxSL_HORIZONTAL | wxEXPAND)
377 .MinSize( { -1, -1 } )
386 S.StartMultiColumn(2, wxCENTER);
388 S.AddFixedText(
XO(
"Duty cycle:"),
false);
390 S.AddVariableText(
XO(
"%.1f %%")
391 .
Format( dtmfSettings.dtmfDutyCycle ),
false);
393 S.AddFixedText(
XO(
"Tone duration:"),
false);
396 S.AddVariableText(
XO(
"%.0f ms")
397 .
Format( dtmfSettings.dtmfTone * 1000.0 ),
false);
399 S.AddFixedText(
XO(
"Silence duration:"),
false);
402 S.AddVariableText(
XO(
"%0.f ms")
403 .
Format( dtmfSettings.dtmfSilence * 1000.0 ),
false);
415 auto result = std::make_unique<Validator>(*
this, access, dtmfSettings);
424 return std::make_shared<Instance>(*
this,
mT0);
429 const auto &
settings = mAccess.Get();
430 auto &dtmfSettings = mSettings;
435 mDtmfDutyCycleS->SetValue(dtmfSettings.dtmfDutyCycle *
DutyCycle.
scale);
437 mDtmfDurationT->SetValue(
settings.extra.GetDuration());
447 auto &dtmfSettings = mSettings;
448 dtmfSettings.dtmfDutyCycle =
450 settings.extra.SetDuration(mDtmfDurationT->GetValue());
469 dtmfNTones = dtmfSequence.length();
475 extra.SetDuration(0.0);
481 dtmfTone = extra.GetDuration();
493 double slot = extra.GetDuration()
494 / ((double)dtmfNTones + (dtmfDutyCycle / 100.0) - 1);
495 dtmfTone = slot * (dtmfDutyCycle / 100.0);
496 dtmfSilence = slot * (1.0 - (dtmfDutyCycle / 100.0));
553 case '1':
case '2':
case '3':
case 'A':
554 case 'a':
case 'b':
case 'c':
555 case 'd':
case 'e':
case 'f':
558 case '4':
case '5':
case '6':
case 'B':
559 case 'g':
case 'h':
case 'i':
560 case 'j':
case 'k':
case 'l':
561 case 'm':
case 'n':
case 'o':
564 case '7':
case '8':
case '9':
case 'C':
565 case 'p':
case 'q':
case 'r':
case 's':
566 case 't':
case 'u':
case 'v':
567 case 'w':
case 'x':
case 'y':
case 'z':
570 case '*':
case '0':
case '#':
case 'D':
579 case '1':
case '4':
case '7':
case '*':
580 case 'g':
case 'h':
case 'i':
581 case 'p':
case 'q':
case 'r':
case 's':
584 case '2':
case '5':
case '8':
case '0':
585 case 'a':
case 'b':
case 'c':
586 case 'j':
case 'k':
case 'l':
587 case 't':
case 'u':
case 'v':
590 case '3':
case '6':
case '9':
case '#':
591 case 'd':
case 'e':
case 'f':
592 case 'm':
case 'n':
case 'o':
593 case 'w':
case 'x':
case 'y':
case 'z':
596 case 'A':
case 'B':
case 'C':
case 'D':
610 for(
decltype(len) i = 0; i < len; i++) {
611 buffer[i] = amplitude * 0.5 *
612 (sin(
A * (i + last).as_double() ) +
613 sin( B * (i + last).as_double() ));
619 for(
size_t i = 0; i <
A; i++) {
625 if (last >= total - len) {
629 size_t offset = len -
A;
630 wxASSERT(offset >= 0);
631 for(
size_t i = 0; i <
A; i++) {
632 buffer[i + offset] *= (1 - (i /
A));
641 auto &dtmfSettings = mSettings;
644 ->SetLabel(wxString::Format(wxT(
"%.1f %%"), dtmfSettings.dtmfDutyCycle));
645 mDtmfDutyT->SetName(mDtmfDutyT->GetLabel());
648 ->SetLabel(wxString::Format(
_(
"%.0f ms"), dtmfSettings.dtmfTone * 1000.0));
649 mDtmfSilenceT->SetName(mDtmfSilenceT->GetLabel());
652 ->SetLabel(wxString::Format(
_(
"%.0f ms"), dtmfSettings.dtmfSilence * 1000.0));
653 mDtmfToneT->SetName(mDtmfToneT->GetLabel());
659 auto &dtmfSettings = mSettings;
660 dtmfSettings.dtmfSequence = mDtmfSequenceT->GetValue();
669 auto &dtmfSettings = mSettings;
670 auto &effect = GetEffect();
671 settings.extra.SetDuration(mDtmfDurationT->GetValue());
680 auto &dtmfSettings = mSettings;
681 dtmfSettings.dtmfDutyCycle = (double) evt.GetInt() /
DutyCycle.
scale;
static const wxChar * kSymbols[]
static const double kFadeInOut
enum ChannelName * ChannelNames
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
static Settings & settings()
Generates EffectParameterMethods overrides from variadic template arguments.
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
An effect that generates DTMF tones.
const EffectParameterMethods & Parameters() const override
TranslatableString GetDescription() const override
static constexpr EffectParameter Amplitude
static const ComponentInterfaceSymbol Symbol
unsigned GetAudioOutCount() const override
How many output buffers to allocate at once.
ManualPageID ManualPage() const override
Name of a page in the Audacity alpha manual, default is empty.
EffectType GetType() const override
Type determines how it behaves.
std::shared_ptr< EffectInstance > MakeInstance() const override
Make an object maintaining short-term state of an Effect.
std::unique_ptr< EffectUIValidator > PopulateOrExchange(ShuttleGui &S, EffectInstance &instance, EffectSettingsAccess &access) override
Add controls to effect panel; always succeeds.
static bool MakeDtmfTone(float *buffer, size_t len, float fs, wxChar tone, sampleCount last, sampleCount total, float amplitude)
static constexpr EffectParameter Sequence
ComponentInterfaceSymbol GetSymbol() const override
static constexpr EffectParameter DutyCycle
Base class for many of the effects in Audacity.
int MessageBox(const TranslatableString &message, long style=DefaultMessageBoxStyle, const TranslatableString &titleStr={}) const
Performs effect computation.
Inherit to add a state variable to an EffectInstance subclass.
Interface for manipulations of an Effect's settings.
virtual const EffectSettings & Get()=0
EffectUIClientInterface is an abstract base class to populate a UI and validate UI values....
Interface for transferring values from a panel of effect controls.
EffectUIClientInterface & mEffect
static DtmfSettings & GetSettings(EffectSettings &settings)
Assume settings originated from MakeSettings() and copies thereof.
const PerTrackEffect & mProcessor
Base class for many of the effects in Audacity.
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Holds a msgid for the translation catalog; may also bind format arguments.
Positions or offsets within audio files need a wide type.
BuiltinEffectsModule::Registration< EffectDtmf > reg
void Recalculate(EffectSettings &settings)
Temporary state of the computation.
sampleCount numSamplesTone
sampleCount numSamplesSequence
sampleCount numSamplesSilence
Instance(const PerTrackEffect &effect, double t0)
size_t ProcessBlock(EffectSettings &settings, const float *const *inBlock, float *const *outBlock, size_t blockLen) override
Called for destructive effect computation.
bool ProcessInitialize(EffectSettings &settings, double sampleRate, sampleCount totalLen, ChannelNames chanMap) override
wxStaticText * mDtmfToneT
void PopulateOrExchange(ShuttleGui &S, const EffectSettings &settings, double projectRate)
wxStaticText * mDtmfSilenceT
Validator(EffectUIClientInterface &effect, EffectSettingsAccess &access, const DtmfSettings &settings)
wxStaticText * mDtmfDutyT
wxTextCtrl * mDtmfSequenceT
NumericTextCtrl * mDtmfDurationT
void OnSequence(wxCommandEvent &evt)
bool ValidateUI() override
Get settings data from the panel; may make error dialogs and return false.
virtual ~Validator()=default
wxSlider * mDtmfDutyCycleS
bool UpdateUI() override
Update appearance of the panel for changes in settings.
Effect & GetEffect() const
void OnDuration(wxCommandEvent &evt)
void OnDutyCycle(wxCommandEvent &evt)
const Type scale
Scaling factor, for slider control.
const Type min
Minimum value.
const Type max
Maximum value.
Externalized state of a plug-in.
Options & AutoPos(bool enable)