Audacity 3.2.0
NoiseRemoval.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 NoiseRemoval.cpp
6
7 Dominic Mazzoni
8
9*******************************************************************//****************************************************************//*******************************************************************/
40
41
42#include "NoiseRemoval.h"
43
44#if !defined(EXPERIMENTAL_NOISE_REDUCTION)
45
46#include "LoadEffects.h"
47
48#include "../WaveTrack.h"
49#include "Prefs.h"
50#include "FileNames.h"
51#include "../ShuttleGui.h"
52
53#include <math.h>
54
55#if defined(__WXMSW__) && !defined(__CYGWIN__)
56#include <float.h>
57#define finite(x) _finite(x)
58#endif
59
60#include <wx/file.h>
61#include <wx/ffile.h>
62#include <wx/bitmap.h>
63#include <wx/brush.h>
64#include <wx/button.h>
65#include <wx/choice.h>
66#include <wx/radiobut.h>
67#include <wx/statbox.h>
68#include <wx/stattext.h>
69#include <wx/textctrl.h>
70#include <wx/valtext.h>
71
72
74
76{ XO("Noise Removal") };
77
79
81{
82 mWindowSize = 2048;
83 mSpectrumSize = 1 + mWindowSize / 2;
84
85 gPrefs->Read(wxT("/Effects/NoiseRemoval/NoiseSensitivity"),
86 &mSensitivity, 0.0);
87 gPrefs->Read(wxT("/Effects/NoiseRemoval/NoiseGain"),
88 &mNoiseGain, -24.0);
89 gPrefs->Read(wxT("/Effects/NoiseRemoval/NoiseFreqSmoothing"),
90 &mFreqSmoothingHz, 150.0);
91 gPrefs->Read(wxT("/Effects/NoiseRemoval/NoiseAttackDecayTime"),
92 &mAttackDecayTime, 0.15);
93 gPrefs->Read(wxT("/Effects/NoiseRemoval/NoiseLeaveNoise"),
94 &mbLeaveNoise, false);
95// mbLeaveNoise = false;
96
97
98 mMinSignalTime = 0.05f;
99 mHasProfile = false;
100 mDoProfile = true;
101
103
104 Init();
105}
106
108{
109}
110
111// ComponentInterface implementation
112
114{
115 return Symbol;
116}
117
119{
120 return XO("Removes constant background noise such as fans, tape noise, or hums");
121}
122
123// EffectDefinitionInterface implementation
124
126{
127 return EffectTypeProcess;
128}
129
131{
132 return false;
133}
134
135// Effect implementation
136
137#define MAX_NOISE_LEVEL 30
139{
140 mLevel = gPrefs->Read(wxT("/Effects/NoiseRemoval/Noise_Level"), 3L);
141 if ((mLevel < 0) || (mLevel > MAX_NOISE_LEVEL)) { // corrupted Prefs?
142 mLevel = 0; //Off-skip
143 gPrefs->Write(wxT("/Effects/NoiseRemoval/Noise_Level"), mLevel);
144 }
145 return gPrefs->Flush();
146}
147
149{
150 return (mLevel == 0);
151}
152
155
160 wxWindow &parent, const EffectDialogFactory &,
161 std::shared_ptr<EffectInstance> &pInstance, EffectSettingsAccess &access,
162 bool forceModal )
163{
164 // Assign the out parameter
165 pInstance = MakeInstance();
166 if (pInstance && !pInstance->Init())
167 pInstance.reset();
168
169 // to do: use forceModal correctly
170 NoiseRemovalDialog dlog(this, access, &parent);
172 dlog.mGain = -mNoiseGain;
173 dlog.mFreq = mFreqSmoothingHz;
174 dlog.mTime = mAttackDecayTime;
176 dlog.mKeepSignal->SetValue(!mbLeaveNoise);
177 dlog.mKeepNoise->SetValue(mbLeaveNoise);
178
179 // We may want to twiddle the levels if we are setting
180 // from a macro editing dialog
181 bool bAllowTwiddleSettings = forceModal;
182
183 if (mHasProfile || bAllowTwiddleSettings) {
184 dlog.m_pButton_Preview->Enable(GetNumWaveTracks() != 0);
185 dlog.m_pButton_RemoveNoise->SetDefault();
186 } else {
187 dlog.m_pButton_Preview->Enable(false);
188 dlog.m_pButton_RemoveNoise->Enable(false);
189 }
190
192 dlog.mKeepNoise->SetValue(dlog.mbLeaveNoise);
193 dlog.CentreOnParent();
194 dlog.ShowModal();
195
196 const auto returnCode = dlog.GetReturnCode();
197 if (!returnCode)
198 return 0;
199
201 mNoiseGain = -dlog.mGain;
202 mFreqSmoothingHz = dlog.mFreq;
203 mAttackDecayTime = dlog.mTime;
205
206 gPrefs->Write(wxT("/Effects/NoiseRemoval/NoiseSensitivity"), mSensitivity);
207 gPrefs->Write(wxT("/Effects/NoiseRemoval/NoiseGain"), mNoiseGain);
208 gPrefs->Write(wxT("/Effects/NoiseRemoval/NoiseFreqSmoothing"), mFreqSmoothingHz);
209 gPrefs->Write(wxT("/Effects/NoiseRemoval/NoiseAttackDecayTime"), mAttackDecayTime);
210 gPrefs->Write(wxT("/Effects/NoiseRemoval/NoiseLeaveNoise"), mbLeaveNoise);
211
212 mDoProfile = (dlog.GetReturnCode() == 1);
213 if (!gPrefs->Flush())
214 return 0;
215 return returnCode;
216}
217
219{
220 Initialize();
221
222 // This same code will both remove noise and profile it,
223 // depending on 'mDoProfile'
224 this->CopyInputTracks(); // Set up mOutputTracks.
225 bool bGoodResult = true;
226
227 int count = 0;
228 for( auto track : mOutputTracks->Selected< WaveTrack >() ) {
229 double trackStart = track->GetStartTime();
230 double trackEnd = track->GetEndTime();
231 double t0 = mT0 < trackStart? trackStart: mT0;
232 double t1 = mT1 > trackEnd? trackEnd: mT1;
233
234 if (t1 > t0) {
235 auto start = track->TimeToLongSamples(t0);
236 auto end = track->TimeToLongSamples(t1);
237 auto len = end - start;
238
239 if (!ProcessOne(count, track, start, len)) {
240 bGoodResult = false;
241 break;
242 }
243 }
244 count++;
245 }
246
247 if (bGoodResult && mDoProfile) {
248 mHasProfile = true;
249 mDoProfile = false;
250 }
251
252 this->ReplaceProcessedTracks(bGoodResult);
253 return bGoodResult;
254}
255
257{
258 Floats tmp{ mSpectrumSize };
259 int j, j0, j1;
260
261 for(int i = 0; i < mSpectrumSize; i++) {
262 j0 = wxMax(0, i - mFreqSmoothingBins);
263 j1 = wxMin(mSpectrumSize-1, i + mFreqSmoothingBins);
264 tmp[i] = 0.0;
265 for(j = j0; j <= j1; j++) {
266 tmp[i] += spec[j];
267 }
268 tmp[i] /= (j1 - j0 + 1);
269 }
270
271 for(size_t i = 0; i < mSpectrumSize; i++)
272 spec[i] = tmp[i];
273}
274
276{
283 // Applies to power, divide by 10:
284 mSensitivityFactor = pow(10.0, mSensitivity/10.0);
286 (int)(mMinSignalTime * mSampleRate / (mWindowSize / 2));
287 if( mMinSignalBlocks < 1 )
290
293
298
299 // Initialize the FFT
301
306
307 // Create a Hann window function
308 for(size_t i=0; i<mWindowSize; i++)
309 mWindow[i] = 0.5 - 0.5 * cos((2.0*M_PI*i) / mWindowSize);
310
311 if (mDoProfile) {
312 for (size_t i = 0; i < mSpectrumSize; i++)
313 mNoiseThreshold[i] = float(0);
314 }
315}
316
318{
319 hFFT.reset();
320
321 if (mDoProfile) {
323 }
324
325 mSpectrums.reset();
326 mGains.reset();
327 mRealFFTs.reset();
328 mImagFFTs.reset();
329
330 mFFTBuffer.reset();
331 mInWaveBuffer.reset();
332 mWindow.reset();
333 mOutOverlapBuffer.reset();
334
335 mOutputTrack.reset();
336}
337
339{
340 for(size_t i = 0; i < mHistoryLen; i++) {
341 for(size_t j = 0; j < mSpectrumSize; j++) {
342 mSpectrums[i][j] = 0;
344 mRealFFTs[i][j] = 0.0;
345 mImagFFTs[i][j] = 0.0;
346 }
347 }
348
349 for(size_t j = 0; j < mWindowSize; j++)
350 mOutOverlapBuffer[j] = 0.0;
351
352 mInputPos = 0;
353 mInSampleCount = 0;
354 mOutSampleCount = -(int)((mWindowSize / 2) * (mHistoryLen - 1));
355}
356
357void EffectNoiseRemoval::ProcessSamples(size_t len, float *buffer)
358{
359 while(len && mOutSampleCount < mInSampleCount) {
360 size_t avail = wxMin(len, mWindowSize - mInputPos);
361 for(size_t i = 0; i < avail; i++)
362 mInWaveBuffer[mInputPos + i] = buffer[i];
363 buffer += avail;
364 len -= avail;
365 mInputPos += avail;
366
367 if (mInputPos == int(mWindowSize)) {
369 if (mDoProfile)
370 GetProfile();
371 else
372 RemoveNoise();
374
375 // Rotate halfway for overlap-add
376 for(size_t i = 0; i < mWindowSize / 2; i++) {
378 }
380 }
381 }
382}
383
385{
386 for(size_t i = 0; i < mWindowSize; i++)
388 RealFFTf(mFFTBuffer.get(), hFFT.get());
389 for(size_t i = 1; i + 1 < mSpectrumSize; i++) {
390 mRealFFTs[0][i] = mFFTBuffer[hFFT->BitReversed[i] ];
391 mImagFFTs[0][i] = mFFTBuffer[hFFT->BitReversed[i]+1];
392 mSpectrums[0][i] = mRealFFTs[0][i]*mRealFFTs[0][i] + mImagFFTs[0][i]*mImagFFTs[0][i];
394 }
395 // DC and Fs/2 bins need to be handled specially
396 mSpectrums[0][0] = mFFTBuffer[0]*mFFTBuffer[0];
400}
401
402namespace {
403 inline void Rotate(ArraysOf<float> &arrays, size_t historyLen)
404 {
405 Floats temp = std::move( arrays[ historyLen - 1 ] );
406
407 for ( size_t nn = historyLen - 1; nn--; )
408 arrays[ nn + 1 ] = std::move( arrays[ nn ] );
409 arrays[0] = std::move( temp );
410 }
411}
412
414{
415 // Remember the last window so we can reuse it
420}
421
423{
424 // Keep flushing empty input buffers through the history
425 // windows until we've output exactly as many samples as
426 // were input.
427 // Well, not exactly, but not more than mWindowSize/2 extra samples at the end.
428 // We'll DELETE them later in ProcessOne.
429
430 Floats empty{ mWindowSize / 2 };
431 for(size_t i = 0; i < mWindowSize / 2; i++)
432 empty[i] = 0.0;
433
435 ProcessSamples(mWindowSize / 2, empty.get());
436 }
437}
438
440{
441 // The noise threshold for each frequency is the maximum
442 // level achieved at that frequency for a minimum of
443 // mMinSignalBlocks blocks in a row - the max of a min.
444
445 int start = mHistoryLen - mMinSignalBlocks;
446 int finish = mHistoryLen;
447 int i;
448
449 for (size_t j = 0; j < mSpectrumSize; j++) {
450 float min = mSpectrums[start][j];
451 for (i = start+1; i < finish; i++) {
452 if (mSpectrums[i][j] < min)
453 min = mSpectrums[i][j];
454 }
455 if (min > mNoiseThreshold[j])
456 mNoiseThreshold[j] = min;
457 }
458
459 mOutSampleCount += mWindowSize / 2; // what is this for? Not used when we are getting the profile?
460}
461
463{
464 size_t center = mHistoryLen / 2;
465 size_t start = center - mMinSignalBlocks/2;
466 size_t finish = start + mMinSignalBlocks;
467
468 // Raise the gain for elements in the center of the sliding history
469 for (size_t j = 0; j < mSpectrumSize; j++) {
470 float min = mSpectrums[start][j];
471 for (size_t i = start+1; i < finish; i++) {
472 if (mSpectrums[i][j] < min)
473 min = mSpectrums[i][j];
474 }
475 if (min > mSensitivityFactor * mNoiseThreshold[j] && mGains[center][j] < 1.0) {
476 if (mbLeaveNoise) mGains[center][j] = 0.0;
477 else mGains[center][j] = 1.0;
478 } else {
479 if (mbLeaveNoise) mGains[center][j] = 1.0;
480 }
481 }
482
483 // Decay the gain in both directions;
484 // note that mOneBlockAttackDecay is less than 1.0
485 // of linear attenuation per block
486 for (size_t j = 0; j < mSpectrumSize; j++) {
487 for (size_t i = center + 1; i < mHistoryLen; i++) {
488 if (mGains[i][j] < mGains[i - 1][j] * mOneBlockAttackDecay)
489 mGains[i][j] = mGains[i - 1][j] * mOneBlockAttackDecay;
490 if (mGains[i][j] < mNoiseAttenFactor)
492 }
493 for (size_t i = center; i--;) {
494 if (mGains[i][j] < mGains[i + 1][j] * mOneBlockAttackDecay)
495 mGains[i][j] = mGains[i + 1][j] * mOneBlockAttackDecay;
496 if (mGains[i][j] < mNoiseAttenFactor)
498 }
499 }
500
501
502 // Apply frequency smoothing to output gain
503 int out = mHistoryLen - 1; // end of the queue
504
505 ApplyFreqSmoothing(mGains[out].get());
506
507 // Apply gain to FFT
508 for (size_t j = 0; j < (mSpectrumSize-1); j++) {
509 mFFTBuffer[j*2 ] = mRealFFTs[out][j] * mGains[out][j];
510 mFFTBuffer[j*2+1] = mImagFFTs[out][j] * mGains[out][j];
511 }
512 // The Fs/2 component is stored as the imaginary part of the DC component
514
515 // Invert the FFT into the output buffer
516 InverseRealFFTf(mFFTBuffer.get(), hFFT.get());
517
518 // Overlap-add
519 for(size_t j = 0; j < (mSpectrumSize-1); j++) {
520 mOutOverlapBuffer[j*2 ] += mFFTBuffer[hFFT->BitReversed[j] ] * mWindow[j*2 ];
521 mOutOverlapBuffer[j*2+1] += mFFTBuffer[hFFT->BitReversed[j]+1] * mWindow[j*2+1];
522 }
523
524 // Output the first half of the overlap buffer, they're done -
525 // and then shift the next half over.
526 if (mOutSampleCount >= 0) { // ...but not if it's the first half-window
528 mWindowSize / 2);
529 }
531 for(size_t j = 0; j < mWindowSize / 2; j++) {
533 mOutOverlapBuffer[j + (mWindowSize / 2)] = 0.0;
534 }
535}
536
538 sampleCount start, sampleCount len)
539{
540 if (track == NULL)
541 return false;
542
544
545 if (!mDoProfile)
546 mOutputTrack = track->EmptyCopy();
547
548 auto bufferSize = track->GetMaxBlockSize();
549 Floats buffer{ bufferSize };
550
551 bool bLoopSuccess = true;
552 auto samplePos = start;
553 while (samplePos < start + len) {
554 //Get a blockSize of samples (smaller than the size of the buffer)
555 //Adjust the block size if it is the final block in the track
556 const auto blockSize = limitSampleBufferSize(
557 track->GetBestBlockSize(samplePos),
558 start + len - samplePos
559 );
560
561 //Get the samples from the track and put them in the buffer
562 track->Get((samplePtr)buffer.get(), floatSample, samplePos, blockSize);
563
564 mInSampleCount += blockSize;
565 ProcessSamples(blockSize, buffer.get());
566
567 samplePos += blockSize;
568
569 // Update the Progress meter
570 if (TrackProgress(count, (samplePos - start).as_double() / len.as_double())) {
571 bLoopSuccess = false;
572 break;
573 }
574 }
575
576 FinishTrack();
577
578 if (!mDoProfile) {
579 // Flush the output WaveTrack (since it's buffered)
580 mOutputTrack->Flush();
581
582 // Take the output track and insert it in place of the original
583 // sample data (as operated on -- this may not match mT0/mT1)
584 if (bLoopSuccess) {
585 double t0 = mOutputTrack->LongSamplesToTime(start);
586 double tLen = mOutputTrack->LongSamplesToTime(len);
587 // Filtering effects always end up with more data than they started with. Delete this 'tail'.
588 mOutputTrack->HandleClear(tLen, mOutputTrack->GetEndTime(), false, false);
589 track->ClearAndPaste(t0, t0 + tLen, mOutputTrack.get(), true, false);
590 }
591 }
592
593 return bLoopSuccess;
594}
595
596// WDR: class implementations
597
598//----------------------------------------------------------------------------
599// NoiseRemovalDialog
600//----------------------------------------------------------------------------
601
602// WDR: event table for NoiseRemovalDialog
603
604enum {
617};
618
619#define SENSITIVITY_MIN 0 // Corresponds to -20 dB
620#define SENSITIVITY_MAX 4000 // Corresponds to 20 dB
621
622#define GAIN_MIN 0
623#define GAIN_MAX 48 // Corresponds to -48 dB
624
625#define FREQ_MIN 0
626#define FREQ_MAX 100 // Corresponds to 1000 Hz
627
628#define TIME_MIN 0
629#define TIME_MAX 100 // Corresponds to 1.000 seconds
630
631
632BEGIN_EVENT_TABLE(NoiseRemovalDialog,wxDialogWrapper)
648
650 EffectNoiseRemoval * effect, EffectSettingsAccess &access, wxWindow *parent)
651 : EffectDialog( parent, XO("Noise Removal"), EffectTypeProcess)
652 , mAccess{ access }
653{
654 m_pEffect = effect;
655
656 // NULL out the control members until the controls are created.
657 m_pButton_GetProfile = NULL;
658 m_pButton_Preview = NULL;
659 m_pButton_RemoveNoise = NULL;
660
661 Init();
662
663 m_pButton_Preview =
664 (wxButton *)wxWindow::FindWindowById(ID_EFFECT_PREVIEW, this);
665 m_pButton_RemoveNoise =
666 (wxButton *)wxWindow::FindWindowById(wxID_OK, this);
667}
668
669void NoiseRemovalDialog::OnGetProfile( wxCommandEvent & WXUNUSED(event))
670{
671 EndModal(1);
672}
673
674void NoiseRemovalDialog::OnKeepNoise( wxCommandEvent & WXUNUSED(event))
675{
676 mbLeaveNoise = mKeepNoise->GetValue();
677}
678
679void NoiseRemovalDialog::OnPreview(wxCommandEvent & WXUNUSED(event))
680{
681 // Save & restore parameters around Preview, because we didn't do OK.
682 bool oldDoProfile = m_pEffect->mDoProfile;
683 bool oldLeaveNoise = m_pEffect->mbLeaveNoise;
684 double oldSensitivity = m_pEffect->mSensitivity;
685 double oldGain = m_pEffect->mNoiseGain;
686 double oldFreq = m_pEffect->mFreqSmoothingHz;
687 double oldTime = m_pEffect->mAttackDecayTime;
688
690
691 m_pEffect->mDoProfile = false;
697
698 auto cleanup = finally( [&] {
699 m_pEffect->mSensitivity = oldSensitivity;
700 m_pEffect->mNoiseGain = oldGain;
701 m_pEffect->mFreqSmoothingHz = oldFreq;
702 m_pEffect->mAttackDecayTime = oldTime;
703 m_pEffect->mbLeaveNoise = oldLeaveNoise;
704 m_pEffect->mDoProfile = oldDoProfile;
705 } );
706
707 m_pEffect->Preview(mAccess, false);
708}
709
710void NoiseRemovalDialog::OnRemoveNoise( wxCommandEvent & WXUNUSED(event))
711{
712 mbLeaveNoise = mKeepNoise->GetValue();
713 EndModal(2);
714}
715
716void NoiseRemovalDialog::OnCancel(wxCommandEvent & WXUNUSED(event))
717{
718 EndModal(0);
719}
720
722{
723 S.StartStatic(XO("Step 1"));
724 {
725 S.AddVariableText(XO(
726"Select a few seconds of just noise so Audacity knows what to filter out,\nthen click Get Noise Profile:"));
727 m_pButton_GetProfile = S.Id(ID_BUTTON_GETPROFILE).AddButton(XXO("&Get Noise Profile"));
728 }
729 S.EndStatic();
730
731 S.StartStatic(XO("Step 2"));
732 {
733 S.AddVariableText(XO(
734"Select all of the audio you want filtered, choose how much noise you want\nfiltered out, and then click 'OK' to remove noise.\n"));
735
736 S.StartMultiColumn(3, wxEXPAND);
737 S.SetStretchyCol(2);
738 {
739 mGainT = S.Id(ID_GAIN_TEXT)
740 .Validator<wxTextValidator>(wxFILTER_NUMERIC)
741 .AddTextBox(XXO("Noise re&duction (dB):"), wxT(""), 0);
742
744 .Name(XO("Noise reduction"))
745 .Style(wxSL_HORIZONTAL)
746 .MinSize( { 150, -1 } )
747 .AddSlider( {}, 0, GAIN_MAX, GAIN_MIN);
748
750 .Validator<wxTextValidator>(wxFILTER_NUMERIC)
751 .AddTextBox(XXO("&Sensitivity (dB):"), wxT(""), 0);
753 .Name(XO("Sensitivity"))
754 .Style(wxSL_HORIZONTAL)
755 .MinSize( { 150, -1 } )
756 .AddSlider( {}, 0, SENSITIVITY_MAX, SENSITIVITY_MIN);
757
758 mFreqT = S.Id(ID_FREQ_TEXT)
759 .Validator<wxTextValidator>(wxFILTER_NUMERIC)
760 .AddTextBox(XXO("Fr&equency smoothing (Hz):"), wxT(""), 0);
762 .Name(XO("Frequency smoothing"))
763 .Style(wxSL_HORIZONTAL)
764 .MinSize( { 150, -1 } )
765 .AddSlider( {}, 0, FREQ_MAX, FREQ_MIN);
766
767 mTimeT = S.Id(ID_TIME_TEXT)
768 .Validator<wxTextValidator>(wxFILTER_NUMERIC)
769 .AddTextBox(XXO("Attac&k/decay time (secs):"), wxT(""), 0);
771 .Name(XO("Attack/decay time"))
772 .Style(wxSL_HORIZONTAL)
773 .MinSize( { 150, -1 } )
774 .AddSlider( {}, 0, TIME_MAX, TIME_MIN);
775
776 S.AddPrompt(XXO("Noise:"));
778 .AddRadioButton(XXO("Re&move"));
780 .AddRadioButtonToGroup(XXO("&Isolate"));
781 }
782 S.EndMultiColumn();
783 }
784 S.EndStatic();
785}
786
788{
789 mSensitivityT->SetValue(wxString::Format(wxT("%.2f"), mSensitivity));
790 mGainT->SetValue(wxString::Format(wxT("%d"), (int)mGain));
791 mFreqT->SetValue(wxString::Format(wxT("%d"), (int)mFreq));
792 mTimeT->SetValue(wxString::Format(wxT("%.2f"), mTime));
793 mKeepNoise->SetValue(mbLeaveNoise);
794 mKeepSignal->SetValue(!mbLeaveNoise);
795
796 mSensitivityS->SetValue(std::clamp<long>(mSensitivity*100.0 + (SENSITIVITY_MAX-SENSITIVITY_MIN+1)/2.0, SENSITIVITY_MIN, SENSITIVITY_MAX));
797 mGainS->SetValue(std::clamp<long>(mGain, GAIN_MIN, GAIN_MAX));
798 mFreqS->SetValue(std::clamp<long>(mFreq / 10, FREQ_MIN, FREQ_MAX));
799 mTimeS->SetValue(std::clamp<long>(mTime * TIME_MAX + 0.5, TIME_MIN, TIME_MAX));
800
801 return true;
802}
803
805{
806 // Nothing to do here
807 return true;
808}
809
810void NoiseRemovalDialog::OnSensitivityText(wxCommandEvent & WXUNUSED(event))
811{
812 mSensitivityT->GetValue().ToDouble(&mSensitivity);
813 mSensitivityS->SetValue(std::clamp<long>(mSensitivity*100.0 + (SENSITIVITY_MAX-SENSITIVITY_MIN+1)/2.0, SENSITIVITY_MIN, SENSITIVITY_MAX));
814}
815
816void NoiseRemovalDialog::OnGainText(wxCommandEvent & WXUNUSED(event))
817{
818 mGainT->GetValue().ToDouble(&mGain);
819 mGainS->SetValue(std::clamp<long>(mGain, GAIN_MIN, GAIN_MAX));
820}
821
822void NoiseRemovalDialog::OnFreqText(wxCommandEvent & WXUNUSED(event))
823{
824 mFreqT->GetValue().ToDouble(&mFreq);
825 mFreqS->SetValue(std::clamp<long>(mFreq / 10, FREQ_MIN, FREQ_MAX));
826}
827
828void NoiseRemovalDialog::OnTimeText(wxCommandEvent & WXUNUSED(event))
829{
830 mTimeT->GetValue().ToDouble(&mTime);
831 mTimeS->SetValue(std::clamp<long>(mTime * TIME_MAX + 0.5, TIME_MIN, TIME_MAX));
832}
833
834void NoiseRemovalDialog::OnSensitivitySlider(wxCommandEvent & WXUNUSED(event))
835{
836 mSensitivity = mSensitivityS->GetValue()/100.0 - 20.0;
837 mSensitivityT->SetValue(wxString::Format(wxT("%.2f"), mSensitivity));
838}
839
840void NoiseRemovalDialog::OnGainSlider(wxCommandEvent & WXUNUSED(event))
841{
842 mGain = mGainS->GetValue();
843 mGainT->SetValue(wxString::Format(wxT("%d"), (int)mGain));
844}
845
846void NoiseRemovalDialog::OnFreqSlider(wxCommandEvent & WXUNUSED(event))
847{
848 mFreq = mFreqS->GetValue() * 10;
849 mFreqT->SetValue(wxString::Format(wxT("%d"), (int)mFreq));
850}
851
852void NoiseRemovalDialog::OnTimeSlider(wxCommandEvent & WXUNUSED(event))
853{
854 mTime = mTimeS->GetValue() / (TIME_MAX*1.0);
855 mTimeT->SetValue(wxString::Format(wxT("%.2f"), mTime));
856}
857
858#endif
wxT("CloseDown"))
END_EVENT_TABLE()
int min(int a, int b)
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
#define M_PI
Definition: Distortion.cpp:29
#define ID_EFFECT_PREVIEW
Definition: Effect.h:368
EffectType
@ EffectTypeProcess
std::function< DialogFactoryResults(wxWindow &parent, EffectPlugin &, EffectUIClientInterface &, EffectSettingsAccess &) > EffectDialogFactory
Type of function that creates a dialog for an effect.
Definition: EffectPlugin.h:42
XO("Cut/Copy/Paste")
XXO("&Cut/Copy/Paste Toolbar")
#define DB_TO_LINEAR(x)
Definition: MemoryX.h:543
#define TIME_MAX
@ ID_GAIN_TEXT
@ ID_TIME_SLIDER
@ ID_BUTTON_GETPROFILE
@ ID_GAIN_SLIDER
@ ID_FREQ_SLIDER
@ ID_BUTTON_LEAVENOISE
@ ID_SENSITIVITY_TEXT
@ ID_SENSITIVITY_SLIDER
@ ID_RADIOBUTTON_KEEPSIGNAL
@ ID_TIME_TEXT
@ ID_FREQ_TEXT
@ ID_RADIOBUTTON_KEEPNOISE
#define SENSITIVITY_MIN
#define SENSITIVITY_MAX
#define MAX_NOISE_LEVEL
#define FREQ_MAX
#define TIME_MIN
#define GAIN_MIN
#define GAIN_MAX
#define FREQ_MIN
FileConfig * gPrefs
Definition: Prefs.cpp:70
void RealFFTf(fft_type *buffer, const FFTParam *h)
Definition: RealFFTf.cpp:161
void InverseRealFFTf(fft_type *buffer, const FFTParam *h)
Definition: RealFFTf.cpp:263
HFFT GetFFT(size_t fftlen)
Definition: RealFFTf.cpp:104
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
Definition: SampleCount.cpp:22
char * samplePtr
Definition: SampleFormat.h:55
#define S(N)
Definition: ToChars.cpp:64
void reinit(Integral count, bool initialize=false)
Definition: MemoryX.h:57
void reinit(Integral count)
Definition: MemoryX.h:109
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
double mT1
Definition: EffectBase.h:109
std::shared_ptr< TrackList > mOutputTracks
Definition: EffectBase.h:107
double mProjectRate
Definition: EffectBase.h:101
double mT0
Definition: EffectBase.h:108
void ReplaceProcessedTracks(const bool bGoodResult)
Definition: EffectBase.cpp:241
void Preview(EffectSettingsAccess &access, bool dryOnly) override
Definition: EffectBase.cpp:333
void CopyInputTracks(bool allSyncLockSelected=false)
Definition: Effect.cpp:677
bool TrackProgress(int whichTrack, double frac, const TranslatableString &={}) const
Definition: Effect.cpp:627
int GetNumWaveTracks() const
Definition: Effect.h:220
Performs effect computation.
A two-pass effect to remove background noise.
Definition: NoiseRemoval.h:37
static const ComponentInterfaceSymbol Symbol
Definition: NoiseRemoval.h:39
ComponentInterfaceSymbol GetSymbol() override
bool SupportsAutomation() const override
Whether the effect has any automatable controls.
bool Init() override
ArraysOf< float > mImagFFTs
Definition: NoiseRemoval.h:124
void ProcessSamples(size_t len, float *buffer)
std::shared_ptr< WaveTrack > mOutputTrack
Definition: NoiseRemoval.h:103
int ShowHostInterface(wxWindow &parent, const EffectDialogFactory &factory, std::shared_ptr< EffectInstance > &pInstance, EffectSettingsAccess &access, bool forceModal=false) override
ArraysOf< float > mRealFFTs
Definition: NoiseRemoval.h:123
void ApplyFreqSmoothing(float *spec)
EffectType GetType() const override
Type determines how it behaves.
bool ProcessOne(int count, WaveTrack *track, sampleCount start, sampleCount len)
sampleCount mOutSampleCount
Definition: NoiseRemoval.h:105
TranslatableString GetDescription() override
bool Process(EffectInstance &instance, EffectSettings &settings) override
ArraysOf< float > mSpectrums
Definition: NoiseRemoval.h:121
bool CheckWhetherSkipEffect(const EffectSettings &settings) const override
Default implementation returns false.
virtual ~EffectNoiseRemoval()
ArraysOf< float > mGains
Definition: NoiseRemoval.h:122
void End() override
sampleCount mInSampleCount
Definition: NoiseRemoval.h:104
virtual bool Flush(bool bCurrentOnly=false) wxOVERRIDE
Definition: FileConfig.cpp:143
Dialog used with EffectNoiseRemoval.
Definition: NoiseRemoval.h:138
void OnFreqText(wxCommandEvent &event)
wxButton * m_pButton_RemoveNoise
Definition: NoiseRemoval.h:175
void OnPreview(wxCommandEvent &event) override
void OnFreqSlider(wxCommandEvent &event)
void PopulateOrExchange(ShuttleGui &S) override
wxTextCtrl * mTimeT
Definition: NoiseRemoval.h:188
void OnCancel(wxCommandEvent &event)
EffectSettingsAccess & mAccess
Definition: NoiseRemoval.h:171
void OnRemoveNoise(wxCommandEvent &event)
wxTextCtrl * mSensitivityT
Definition: NoiseRemoval.h:185
wxButton * m_pButton_Preview
Definition: NoiseRemoval.h:174
wxRadioButton * mKeepNoise
Definition: NoiseRemoval.h:178
wxButton * m_pButton_GetProfile
Definition: NoiseRemoval.h:173
void OnGainText(wxCommandEvent &event)
bool TransferDataFromWindow() override
void OnTimeSlider(wxCommandEvent &event)
wxTextCtrl * mFreqT
Definition: NoiseRemoval.h:187
void OnGainSlider(wxCommandEvent &event)
EffectNoiseRemoval * m_pEffect
Definition: NoiseRemoval.h:170
wxSlider * mSensitivityS
Definition: NoiseRemoval.h:180
void OnGetProfile(wxCommandEvent &event)
void OnKeepNoise(wxCommandEvent &event)
void OnSensitivityText(wxCommandEvent &event)
void OnSensitivitySlider(wxCommandEvent &event)
void OnTimeText(wxCommandEvent &event)
wxTextCtrl * mGainT
Definition: NoiseRemoval.h:186
wxRadioButton * mKeepSignal
Definition: NoiseRemoval.h:177
bool TransferDataToWindow() override
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:628
std::shared_ptr< EffectInstance > MakeInstance() const override
Make an object maintaining short-term state of an Effect.
Definition: Effect.cpp:139
Holds a msgid for the translation catalog; may also bind format arguments.
A Track that contains audio waveform data.
Definition: WaveTrack.h:57
bool Get(samplePtr buffer, sampleFormat format, sampleCount start, size_t len, fillFormat fill=fillZero, bool mayThrow=true, sampleCount *pNumWithinClips=nullptr) const override
Definition: WaveTrack.cpp:2108
size_t GetMaxBlockSize() const override
This returns a nonnegative number of samples meant to size a memory buffer.
Definition: WaveTrack.cpp:1800
size_t GetBestBlockSize(sampleCount t) const override
This returns a nonnegative number of samples meant to size a memory buffer.
Definition: WaveTrack.cpp:1782
void ClearAndPaste(double t0, double t1, const Track *src, bool preserve=true, bool merge=true, const TimeWarper *effectWarper=NULL)
Definition: WaveTrack.cpp:899
Holder EmptyCopy(const SampleBlockFactoryPtr &pFactory={}, bool keepLink=true) const
Definition: WaveTrack.cpp:689
Positions or offsets within audio files need a wide type.
Definition: SampleCount.h:19
double as_double() const
Definition: SampleCount.h:46
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:159
void Rotate(ArraysOf< float > &arrays, size_t historyLen)
BuiltinEffectsModule::Registration< EffectNoiseRemoval > reg
Externalized state of a plug-in.