22#include <wx/valtext.h>
23#include <wx/stattext.h>
26#include "../ShuttleGui.h"
27#include "../widgets/NumericTextCtrl.h"
28#include "../widgets/valnum.h"
42 if (s.dtmfSequence.find_first_not_of(
AllSymbols())
74 for (
unsigned int i = 0; i < WXSIZEOF(
kSymbols); ++i)
106 return XO(
"Generates dual-tone multi-frequency (DTMF) tones like those produced by the keypad on telephones");
111 return L
"DTMF_Tones";
134 const float *
const *inBlock,
float *
const *outBlock,
size_t blockLen)
166 if (dtmfSettings.dtmfNTones == 0) {
169 XO(
"DTMF sequence empty.\nCheck ALL settings for this effect."),
175 double duration =
settings.extra.GetDuration();
197 while (
diff > 2 * dtmfSettings.dtmfNTones - 1) {
203 wxASSERT(dtmfSettings.dtmfNTones > 1);
219 const float *
const *,
float *
const *outbuf,
size_t size)
222 float *buffer = outbuf[0];
223 decltype(
size) processed = 0;
244 if (numRemaining == 0)
251 numRemaining = numSamplesTone;
256 numRemaining = numSamplesSilence;
261 numRemaining += (diff-- > 0 ? 1 : 0);
269 assert(curSeqPos < dtmfSettings.dtmfNTones) ;
271 dtmfSettings.dtmfSequence[curSeqPos], curTonePos, numSamplesTone,
272 dtmfSettings.dtmfAmplitude);
277 memset(buffer, 0,
sizeof(
float) * len);
329 auto &dtmfSettings = mSettings;
343 S.StartMultiColumn(2, wxCENTER);
347 .Validator([&dtmfSettings]{
348 wxTextValidator vldDtmf(
349 wxFILTER_INCLUDE_CHAR_LIST, &dtmfSettings.dtmfSequence);
353 .AddTextBox(
XXO(
"DTMF &sequence:"),
wxT(
""), 10);
359 .Validator<FloatingPointValidator<double>>(
360 3, &dtmfSettings.dtmfAmplitude, NumValidatorStyle::NO_TRAILING_ZEROES,
362 .AddTextBox(
XXO(
"&Amplitude (0-1):"),
wxT(
""), 10);
364 S.AddPrompt(
XXO(
"&Duration:"));
369 extra.GetDurationFormat(),
374 S.Name(
XO(
"Duration"))
375 .AddWindow(mDtmfDurationT);
378 S.AddFixedText(
XO(
"&Tone/silence ratio:"),
false);
381 .Style(wxSL_HORIZONTAL | wxEXPAND)
382 .MinSize( { -1, -1 } )
391 S.StartMultiColumn(2, wxCENTER);
393 S.AddFixedText(
XO(
"Duty cycle:"),
false);
395 S.AddVariableText(
XO(
"%.1f %%")
396 .
Format( dtmfSettings.dtmfDutyCycle ),
false);
398 S.AddFixedText(
XO(
"Tone duration:"),
false);
401 S.AddVariableText(
XO(
"%.0f ms")
402 .
Format( dtmfSettings.dtmfTone * 1000.0 ),
false);
404 S.AddFixedText(
XO(
"Silence duration:"),
false);
407 S.AddVariableText(
XO(
"%0.f ms")
408 .
Format( dtmfSettings.dtmfSilence * 1000.0 ),
false);
421 auto result = std::make_unique<Validator>(*
this, access, dtmfSettings);
430 return std::make_shared<Instance>(*
this,
mT0);
435 const auto &
settings = mAccess.Get();
436 auto &dtmfSettings = mSettings;
441 mDtmfDutyCycleS->SetValue(dtmfSettings.dtmfDutyCycle *
DutyCycle.
scale);
443 mDtmfDurationT->SetValue(
settings.extra.GetDuration());
453 auto &dtmfSettings = mSettings;
454 dtmfSettings.dtmfDutyCycle =
456 settings.extra.SetDuration(mDtmfDurationT->GetValue());
476 dtmfNTones = dtmfSequence.length();
482 extra.SetDuration(0.0);
488 dtmfTone = extra.GetDuration();
500 double slot = extra.GetDuration()
501 / ((double)dtmfNTones + (dtmfDutyCycle / 100.0) - 1);
502 dtmfTone = slot * (dtmfDutyCycle / 100.0);
503 dtmfSilence = slot * (1.0 - (dtmfDutyCycle / 100.0));
560 case '1':
case '2':
case '3':
case 'A':
561 case 'a':
case 'b':
case 'c':
562 case 'd':
case 'e':
case 'f':
565 case '4':
case '5':
case '6':
case 'B':
566 case 'g':
case 'h':
case 'i':
567 case 'j':
case 'k':
case 'l':
568 case 'm':
case 'n':
case 'o':
571 case '7':
case '8':
case '9':
case 'C':
572 case 'p':
case 'q':
case 'r':
case 's':
573 case 't':
case 'u':
case 'v':
574 case 'w':
case 'x':
case 'y':
case 'z':
577 case '*':
case '0':
case '#':
case 'D':
586 case '1':
case '4':
case '7':
case '*':
587 case 'g':
case 'h':
case 'i':
588 case 'p':
case 'q':
case 'r':
case 's':
591 case '2':
case '5':
case '8':
case '0':
592 case 'a':
case 'b':
case 'c':
593 case 'j':
case 'k':
case 'l':
594 case 't':
case 'u':
case 'v':
597 case '3':
case '6':
case '9':
case '#':
598 case 'd':
case 'e':
case 'f':
599 case 'm':
case 'n':
case 'o':
600 case 'w':
case 'x':
case 'y':
case 'z':
603 case 'A':
case 'B':
case 'C':
case 'D':
617 for(
decltype(len) i = 0; i < len; i++) {
618 buffer[i] = amplitude * 0.5 *
619 (sin(
A * (i + last).as_double() ) +
620 sin( B * (i + last).as_double() ));
626 for(
size_t i = 0; i <
A; i++) {
632 if (last >= total - len) {
636 size_t offset = len -
A;
637 wxASSERT(offset >= 0);
638 for(
size_t i = 0; i <
A; i++) {
639 buffer[i + offset] *= (1 - (i /
A));
648 auto &dtmfSettings = mSettings;
651 ->SetLabel(wxString::Format(
wxT(
"%.1f %%"), dtmfSettings.dtmfDutyCycle));
652 mDtmfDutyT->SetName(mDtmfDutyT->GetLabel());
655 ->SetLabel(wxString::Format(
_(
"%.0f ms"), dtmfSettings.dtmfTone * 1000.0));
656 mDtmfSilenceT->SetName(mDtmfSilenceT->GetLabel());
659 ->SetLabel(wxString::Format(
_(
"%.0f ms"), dtmfSettings.dtmfSilence * 1000.0));
660 mDtmfToneT->SetName(mDtmfToneT->GetLabel());
666 auto &dtmfSettings = mSettings;
667 dtmfSettings.dtmfSequence = mDtmfSequenceT->GetValue();
677 auto &dtmfSettings = mSettings;
678 auto &effect = GetEffect();
679 settings.extra.SetDuration(mDtmfDurationT->GetValue());
689 auto &dtmfSettings = mSettings;
690 dtmfSettings.dtmfDutyCycle = (double) evt.GetInt() /
DutyCycle.
scale;
static const wxChar * kSymbols[]
static const double kFadeInOut
XXO("&Cut/Copy/Paste Toolbar")
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
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.
static bool MakeDtmfTone(float *buffer, size_t len, float fs, wxChar tone, sampleCount last, sampleCount total, float amplitude)
static constexpr EffectParameter Sequence
std::unique_ptr< EffectUIValidator > PopulateOrExchange(ShuttleGui &S, EffectInstance &instance, EffectSettingsAccess &access, const EffectOutputs *pOutputs) override
Add controls to effect panel; always succeeds.
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.
Hold values to send to effect output meters.
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
bool ProcessInitialize(EffectSettings &settings, double sampleRate, ChannelNames chanMap) override
unsigned GetAudioInCount() const override
How many input buffers to allocate at once.
unsigned GetAudioOutCount() const override
How many output buffers to allocate at once.
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.
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)