23#include <wx/valtext.h>
24#include <wx/stattext.h>
28#include "../widgets/NumericTextCtrl.h"
29#include "../widgets/valnum.h"
43 if (s.dtmfSequence.find_first_not_of(
AllSymbols())
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";
135 const float *
const *inBlock,
float *
const *outBlock,
size_t blockLen)
167 if (dtmfSettings.dtmfNTones == 0) {
170 XO(
"DTMF sequence empty.\nCheck ALL settings for this effect."),
176 double duration =
settings.extra.GetDuration();
198 while (
diff > 2 * dtmfSettings.dtmfNTones - 1) {
204 wxASSERT(dtmfSettings.dtmfNTones > 1);
220 const float *
const *,
float *
const *outbuf,
size_t size)
223 float *buffer = outbuf[0];
224 decltype(
size) processed = 0;
245 if (numRemaining == 0)
252 numRemaining = numSamplesTone;
257 numRemaining = numSamplesSilence;
262 numRemaining += (diff-- > 0 ? 1 : 0);
270 assert(curSeqPos < dtmfSettings.dtmfNTones) ;
272 dtmfSettings.dtmfSequence[curSeqPos], curTonePos, numSamplesTone,
273 dtmfSettings.dtmfAmplitude);
278 memset(buffer, 0,
sizeof(
float) * len);
328 auto &dtmfSettings = mSettings;
342 S.StartMultiColumn(2, wxCENTER);
346 .Validator([&dtmfSettings]{
347 wxTextValidator vldDtmf(
348 wxFILTER_INCLUDE_CHAR_LIST, &dtmfSettings.dtmfSequence);
352 .AddTextBox(
XXO(
"DTMF &sequence:"),
wxT(
""), 10);
358 .Validator<FloatingPointValidator<double>>(
359 3, &dtmfSettings.dtmfAmplitude, NumValidatorStyle::NO_TRAILING_ZEROES,
361 .AddTextBox(
XXO(
"&Amplitude (0-1):"),
wxT(
""), 10);
363 S.AddPrompt(
XXO(
"&Duration:"));
367 S.GetParent(), wxID_ANY,
369 extra.GetDurationFormat(),
373 S.Name(
XO(
"Duration"))
374 .AddWindow(mDtmfDurationT);
377 S.AddFixedText(
XO(
"&Tone/silence ratio:"),
false);
380 .Style(wxSL_HORIZONTAL | wxEXPAND)
381 .MinSize( { -1, -1 } )
390 S.StartMultiColumn(2, wxCENTER);
392 S.AddFixedText(
XO(
"Duty cycle:"),
false);
394 S.AddVariableText(
XO(
"%.1f %%")
395 .
Format( dtmfSettings.dtmfDutyCycle ),
false);
397 S.AddFixedText(
XO(
"Tone duration:"),
false);
400 S.AddVariableText(
XO(
"%.0f ms")
401 .
Format( dtmfSettings.dtmfTone * 1000.0 ),
false);
403 S.AddFixedText(
XO(
"Silence duration:"),
false);
406 S.AddVariableText(
XO(
"%0.f ms")
407 .
Format( dtmfSettings.dtmfSilence * 1000.0 ),
false);
420 auto result = std::make_unique<Editor>(*
this, access, dtmfSettings);
429 return std::make_shared<Instance>(*
this,
mT0);
434 const auto &
settings = mAccess.Get();
435 auto &dtmfSettings = mSettings;
440 mDtmfDutyCycleS->SetValue(dtmfSettings.dtmfDutyCycle *
DutyCycle.
scale);
442 mDtmfDurationT->SetValue(
settings.extra.GetDuration());
452 auto &dtmfSettings = mSettings;
453 dtmfSettings.dtmfDutyCycle =
455 settings.extra.SetDuration(mDtmfDurationT->GetValue());
475 dtmfNTones = dtmfSequence.length();
481 extra.SetDuration(0.0);
487 dtmfTone = extra.GetDuration();
499 double slot = extra.GetDuration()
500 / ((double)dtmfNTones + (dtmfDutyCycle / 100.0) - 1);
501 dtmfTone = slot * (dtmfDutyCycle / 100.0);
502 dtmfSilence = slot * (1.0 - (dtmfDutyCycle / 100.0));
559 case '1':
case '2':
case '3':
case 'A':
560 case 'a':
case 'b':
case 'c':
561 case 'd':
case 'e':
case 'f':
564 case '4':
case '5':
case '6':
case 'B':
565 case 'g':
case 'h':
case 'i':
566 case 'j':
case 'k':
case 'l':
567 case 'm':
case 'n':
case 'o':
570 case '7':
case '8':
case '9':
case 'C':
571 case 'p':
case 'q':
case 'r':
case 's':
572 case 't':
case 'u':
case 'v':
573 case 'w':
case 'x':
case 'y':
case 'z':
576 case '*':
case '0':
case '#':
case 'D':
585 case '1':
case '4':
case '7':
case '*':
586 case 'g':
case 'h':
case 'i':
587 case 'p':
case 'q':
case 'r':
case 's':
590 case '2':
case '5':
case '8':
case '0':
591 case 'a':
case 'b':
case 'c':
592 case 'j':
case 'k':
case 'l':
593 case 't':
case 'u':
case 'v':
596 case '3':
case '6':
case '9':
case '#':
597 case 'd':
case 'e':
case 'f':
598 case 'm':
case 'n':
case 'o':
599 case 'w':
case 'x':
case 'y':
case 'z':
602 case 'A':
case 'B':
case 'C':
case 'D':
616 for(
decltype(len) i = 0; i < len; i++) {
617 buffer[i] = amplitude * 0.5 *
618 (sin(
A * (i + last).as_double() ) +
619 sin( B * (i + last).as_double() ));
625 for(
size_t i = 0; i <
A; i++) {
631 if (last >= total - len) {
635 size_t offset = len -
A;
636 wxASSERT(offset >= 0);
637 for(
size_t i = 0; i <
A; i++) {
638 buffer[i + offset] *= (1 - (i /
A));
647 auto &dtmfSettings = mSettings;
650 ->SetLabel(wxString::Format(
wxT(
"%.1f %%"), dtmfSettings.dtmfDutyCycle));
651 mDtmfDutyT->SetName(mDtmfDutyT->GetLabel());
654 ->SetLabel(wxString::Format(
_(
"%.0f ms"), dtmfSettings.dtmfTone * 1000.0));
655 mDtmfSilenceT->SetName(mDtmfSilenceT->GetLabel());
658 ->SetLabel(wxString::Format(
_(
"%.0f ms"), dtmfSettings.dtmfSilence * 1000.0));
659 mDtmfToneT->SetName(mDtmfToneT->GetLabel());
665 auto &dtmfSettings = mSettings;
666 dtmfSettings.dtmfSequence = mDtmfSequenceT->GetValue();
676 auto &dtmfSettings = mSettings;
677 settings.extra.SetDuration(mDtmfDurationT->GetValue());
687 auto &dtmfSettings = mSettings;
688 dtmfSettings.dtmfDutyCycle = (double) evt.GetInt() /
DutyCycle.
scale;
static const wxChar * kSymbols[]
static const double kFadeInOut
XXO("&Cut/Copy/Paste Toolbar")
const NumericConverterType & NumericConverterType_TIME()
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
std::unique_ptr< EffectEditor > MakeEditor(ShuttleGui &S, EffectInstance &instance, EffectSettingsAccess &access, const EffectOutputs *pOutputs) const override
Called only from PopulateUI, to add controls to effect panel.
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
ComponentInterfaceSymbol GetSymbol() const override
static constexpr EffectParameter DutyCycle
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
static int DoMessageBox(const EffectPlugin &plugin, const TranslatableString &message, long style=DefaultMessageBoxStyle, const TranslatableString &titleStr={})
static DtmfSettings & GetSettings(EffectSettings &settings)
Assume settings originated from MakeSettings() and copies thereof.
static FormatterContext SampleRateContext(double sampleRate)
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.
constexpr size_t npos(-1)
constexpr auto sampleRate
BuiltinEffectsModule::Registration< EffectDtmf > reg
void Recalculate(EffectSettings &settings)
wxSlider * mDtmfDutyCycleS
void OnDuration(wxCommandEvent &evt)
wxStaticText * mDtmfDutyT
void OnDutyCycle(wxCommandEvent &evt)
Editor(const EffectUIServices &effect, EffectSettingsAccess &access, const DtmfSettings &settings)
wxTextCtrl * mDtmfSequenceT
void PopulateOrExchange(ShuttleGui &S, const EffectSettings &settings, double projectRate)
bool ValidateUI() override
Get settings data from the panel; may make error dialogs and return false.
NumericTextCtrl * mDtmfDurationT
wxStaticText * mDtmfSilenceT
wxStaticText * mDtmfToneT
virtual ~Editor()=default
bool UpdateUI() override
Update appearance of the panel for changes in settings.
void OnSequence(wxCommandEvent &evt)
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.
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)