1 /*
2  * Copyright (C) 2002 - David W. Durham
3  *
4  * This file is part of ReZound, an audio editing application.
5  *
6  * ReZound is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published
8  * by the Free Software Foundation; either version 2 of the License,
9  * or (at your option) any later version.
10  *
11  * ReZound is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
19  */
20 
21 #include "FilterActionDialogs.h"
22 
23 #include "CStatusComm.h"
24 
25 #include "../backend/ActionParamMappers.h"
26 #include "../backend/unit_conv.h"
27 
28 #include <vector>
29 
30 
31 // --- convolution -----------------------
32 
33 
34 static const double froo=log(80.0/(24.0+80.0))/log(0.5); // this is to make the middle come out 0.00dB
35 class CActionParamMapper_dB_gain : public AActionParamMapper
36 {
37 public:
CActionParamMapper_dB_gain(double defaultValue)38 	CActionParamMapper_dB_gain(double defaultValue) :
39 		AActionParamMapper(defaultValue)
40 	{
41 	}
42 
~CActionParamMapper_dB_gain()43 	virtual ~CActionParamMapper_dB_gain() {}
44 
interpretValue(const double x)45 	double interpretValue(const double x)
46 	{
47 		return unitRange_to_otherRange_linear(pow(x,froo),-80,24);
48 	}
49 
uninterpretValue(const double x)50 	double uninterpretValue(const double x)
51 	{
52 		return pow(otherRange_to_unitRange_linear(x,-80,24),1.0/froo);
53 	}
54 };
55 
56 
CConvolutionFilterDialog(FXWindow * mainWindow)57 CConvolutionFilterDialog::CConvolutionFilterDialog(FXWindow *mainWindow) :
58 	CActionParamDialog(mainWindow)
59 {
60 	// ??? still need predelay sliders
61 	void *p0=newVertPanel(NULL,true);
62 			void *p1=newHorzPanel(p0,false);
63 				addSlider(p1,
64 					N_("Wet/Dry Mix"),
65 					"%",
66 					new CActionParamMapper_linear_range(50,-100,100),
67 					NULL,
68 					true
69 				);
70 
71 				addSlider(p1,
72 					N_("Input Lowpass"),
73 					"Hz",
74 					new CActionParamMapper_linear(25000.0,25000,5,100000),
75 					NULL,
76 					false
77 				);
78 
79 				addSlider(p1,
80 					N_("Input Gain"),
81 					"dB",
82 					new CActionParamMapper_dB_gain(0.0),
83 					dB_to_scalar,
84 					false
85 				);
86 
87 				addSlider(p1,
88 					N_("Output Gain"),
89 					"dB",
90 					new CActionParamMapper_dB_gain(0.0),
91 					dB_to_scalar,
92 					false
93 				);
94 
95 				addSlider(p1,
96 					N_("Predelay"),
97 					"ms",
98 					new CActionParamMapper_linear(50.0,100,1,500),
99 					NULL,
100 					false
101 				);
102 
103 
104 				void *p2=newVertPanel(p1,false);
105 					addDiskEntityEntry(p2,N_("Filter Kernel"),"$share/impulse_hall1.wav",FXDiskEntityParamValue::detAudioFilename,_("The Audio File to Use as the Filter Kernel"));
106 
107 					void *p3=newHorzPanel(p2,false);
108 						addSlider(p3,
109 							N_("FK Gain"),
110 							"x",
111 							new CActionParamMapper_recipsym(0.06667,30,1,50),
112 							NULL,
113 							true
114 						);
115 
116 						addSlider(p3,
117 							N_("FK Lowpass"),
118 							"Hz",
119 							new CActionParamMapper_linear(25000.0,25000,5,1000000),
120 							NULL,
121 							false
122 						);
123 
124 						void *p4=newVertPanel(p3,false);
125 							addSlider(p4,
126 								N_("FK Rate"),
127 								"x",
128 								new CActionParamMapper_recipsym(1.0,2,2,10),
129 								NULL,
130 								true
131 							);
132 
133 							addCheckBoxEntry(p4,N_("Reverse"),false);
134 			p1=newHorzPanel(p0,false);
135 				addCheckBoxEntry(p1,N_("Wrap Decay back to Beginning"),false);
136 }
137 
138 
139 
140 
141 
142 // --- arbitrary FIR filter --------------
143 
144 class CActionParamMapper_arbitraryFIRFilter_freq : public AActionParamMapper
145 {
146 public:
147 	// is set dynamically at runtime in by CArbitraryFIRFilterDialog
148 	unsigned baseFrequency;
149 	unsigned numberOfOctaves;
150 
CActionParamMapper_arbitraryFIRFilter_freq()151 	CActionParamMapper_arbitraryFIRFilter_freq() :
152 		AActionParamMapper(),
153 		baseFrequency(20),
154 		numberOfOctaves(11)
155 	{
156 	}
157 
~CActionParamMapper_arbitraryFIRFilter_freq()158 	virtual ~CActionParamMapper_arbitraryFIRFilter_freq() {}
159 
interpretValue(const double x)160 	double interpretValue(const double x)
161 	{
162 		return octave_to_freq(x*numberOfOctaves,baseFrequency);
163 	}
164 
uninterpretValue(const double x)165 	double uninterpretValue(const double x)
166 	{
167 		return freq_to_octave(x,baseFrequency)/numberOfOctaves;
168 	}
169 };
170 
171 class CActionParamMapper_arbitraryFIRFilter_amp : public AActionParamMapper
172 {
173 public:
CActionParamMapper_arbitraryFIRFilter_amp(double defaultValue,int defaultScalar,int minScalar,int maxScalar)174 	CActionParamMapper_arbitraryFIRFilter_amp(double defaultValue,int defaultScalar,int minScalar,int maxScalar) :
175 		AActionParamMapper(defaultValue,defaultScalar,minScalar,maxScalar)
176 	{
177 	}
178 
~CActionParamMapper_arbitraryFIRFilter_amp()179 	virtual ~CActionParamMapper_arbitraryFIRFilter_amp() {}
180 
181 	// intention: 0dB change is always in the middle, and the range above/below the gets wider or narrower depending on s (but that s is really only a tenth of what it would normally be)
interpretValue(const double x)182 	double interpretValue(const double x)
183 	{
184 		return scalar_to_dB(x*2)*(getScalar()/10.0);
185 	}
186 
uninterpretValue(const double x)187 	double uninterpretValue(const double x)
188 	{
189 		return dB_to_scalar(x/(getScalar()/10.0))/2;
190 	}
191 };
192 
193 #include "../backend/DSP/Convolver.h"
194 class CActionParamMapper_arbitraryFIRFilter_kernelLength : public AActionParamMapper
195 {
196 public:
197 	// is set dynamically at runtime in by CArbitraryFIRFilterDialog
198 	unsigned baseFrequency;
199 	unsigned numberOfOctaves;
200 
CActionParamMapper_arbitraryFIRFilter_kernelLength(double defaultValue)201 	CActionParamMapper_arbitraryFIRFilter_kernelLength(double defaultValue) :
202 		AActionParamMapper(defaultValue)
203 	{
204 	}
205 
~CActionParamMapper_arbitraryFIRFilter_kernelLength()206 	virtual ~CActionParamMapper_arbitraryFIRFilter_kernelLength() {}
207 
208 #ifdef HAVE_LIBFFTW
interpretValue(const double x)209 	double interpretValue(const double x)
210 	{
211 		if(goodFilterKernelSizes.size()<=0) // first time
212 			goodFilterKernelSizes=TFFTConvolverTimeDomainKernel<float,float>::getGoodFilterKernelSizes();
213 
214 			// use min and max to place reasonable limits on the kernel size
215 		return min((size_t)(4*1024*1024),max((size_t)8,goodFilterKernelSizes[(size_t)ceil(x*(goodFilterKernelSizes.size()-2))])); // -2 cause I need padding in the actual convolver
216 	}
217 
uninterpretValue(const double x)218 	double uninterpretValue(const double x)
219 	{
220 		if(goodFilterKernelSizes.size()<=0) // first time
221 			goodFilterKernelSizes=TFFTConvolverTimeDomainKernel<float,float>::getGoodFilterKernelSizes();
222 
223 		for(size_t t=0;t<goodFilterKernelSizes.size();t++)
224 		{
225 			if(goodFilterKernelSizes[t]==x)
226 				return ((double)t)/(goodFilterKernelSizes.size()-2); // -2 cause I need padding in the actual convolver
227 		}
228 		return 0;
229 	}
230 #else
231 	// just for show
interpretValue(const double x)232 	double interpretValue(const double x) { return floor(x*1024.0); }
uninterpretValue(const double x)233 	double uninterpretValue(const double x) { return x/1024.0; }
234 #endif
235 
236 private:
237 	vector<size_t> goodFilterKernelSizes;
238 };
239 
240 
241 
242 FXDEFMAP(CArbitraryFIRFilterDialog) CArbitraryFIRFilterDialogMap[]=
243 {
244 	//Message_Type			ID							Message_Handler
245 
246 	FXMAPFUNC(SEL_COMMAND,		CArbitraryFIRFilterDialog::ID_BASE_FREQUENCY,		CArbitraryFIRFilterDialog::onFrequencyRangeChange),
247 	FXMAPFUNC(SEL_COMMAND,		CArbitraryFIRFilterDialog::ID_NUMBER_OF_OCTAVES,	CArbitraryFIRFilterDialog::onFrequencyRangeChange),
248 };
249 
FXIMPLEMENT(CArbitraryFIRFilterDialog,CActionParamDialog,CArbitraryFIRFilterDialogMap,ARRAYNUMBER (CArbitraryFIRFilterDialogMap))250 FXIMPLEMENT(CArbitraryFIRFilterDialog,CActionParamDialog,CArbitraryFIRFilterDialogMap,ARRAYNUMBER(CArbitraryFIRFilterDialogMap))
251 
252 CArbitraryFIRFilterDialog::CArbitraryFIRFilterDialog(FXWindow *mainWindow) :
253 	CActionParamDialog(mainWindow)
254 {
255 	FXPacker *p0=newHorzPanel(NULL);
256 		addSlider(p0,
257 			N_("Wet/Dry Mix"),
258 			"%",
259 			new CActionParamMapper_linear_range(100.0,-100,100),
260 			NULL,
261 			true
262 		);
263 
264 		FXPacker *p1=newVertPanel(p0,false);
265 			addGraph(p1,
266 				N_("Frequency Response"),
267 				N_("Frequency"),
268 				"Hz",
269 				freqMapper=new CActionParamMapper_arbitraryFIRFilter_freq,
270 				N_("Change"),
271 				"dB",
272 				new CActionParamMapper_arbitraryFIRFilter_amp(0.0,20,-100,100),
273 				dB_to_scalar
274 			);
275 
276 			FXPacker *p2=newHorzPanel(p1,false);
277 				FXTextParamValue *baseFreq=addNumericTextEntry(p2,
278 					N_("Base Frequency"),
279 					"Hz",
280 					20,
281 					10,
282 					1000,
283 					_("This Sets the Lowest Frequency Displayed on the Graph.\nThis is the Frequency of the First Octave.")
284 				);
285 				baseFreq->setTarget(this);
286 				baseFreq->setSelector(ID_BASE_FREQUENCY);
287 
288 				FXTextParamValue *numberOfOctaves=addNumericTextEntry(p2,
289 					N_("Number of Octaves"),
290 					"",
291 					11,
292 					1,
293 					15,
294 					_("This Sets the Number of Octaves Displayed on the Graph.\nBut Note that no Frequency Higher than Half of the Sound's Sampling Rate can be Affected Since it Cannot Contain a Frequency Higher than That.")
295 				);
296 				numberOfOctaves->setTarget(this);
297 				numberOfOctaves->setSelector(ID_NUMBER_OF_OCTAVES);
298 
299 		p1=newVertPanel(p0,false);
300 			addSlider(p1,
301 				N_("Kernel Length"),
302 				"",
303 				new CActionParamMapper_arbitraryFIRFilter_kernelLength(1024),
304 				NULL,
305 				false
306 			);
307 			setTipText("Kernel Length",_("This is the Size of the Filter Kernel Computed (in samples) From Your Curve to be Convolved with the Audio"));
308 
309 			addCheckBoxEntry(p1,
310 				N_("Undelay"),
311 				true,
312 				_("This Counteracts the Delay Side-Effect of Custom FIR Filters")
313 			);
314 
315 	onFrequencyRangeChange(NULL,0,NULL);
316 }
317 
onFrequencyRangeChange(FXObject * sender,FXSelector sel,void * ptr)318 long CArbitraryFIRFilterDialog::onFrequencyRangeChange(FXObject *sender,FXSelector sel,void *ptr)
319 {
320 	FXGraphParamValue *g=getGraphParam("Frequency Response");
321 
322 	FXTextParamValue *baseFrequency=getTextParam("Base Frequency");
323 	FXTextParamValue *numberOfOctaves=getTextParam("Number of Octaves");
324 
325 	freqMapper->baseFrequency=(unsigned)baseFrequency->getValue();
326 	freqMapper->numberOfOctaves=(unsigned)numberOfOctaves->getValue();
327 
328 	g->updateNumbers();
329 
330 	return 1;
331 }
332 
333 
334 
335 
336 // --- morphing arbitrary FIR filter --------------
337 
338 FXDEFMAP(CMorphingArbitraryFIRFilterDialog) CMorphingArbitraryFIRFilterDialogMap[]=
339 {
340 	//Message_Type			ID								Message_Handler
341 
342 	FXMAPFUNC(SEL_COMMAND,		CMorphingArbitraryFIRFilterDialog::ID_BASE_FREQUENCY,		CMorphingArbitraryFIRFilterDialog::onFrequencyRangeChange),
343 	FXMAPFUNC(SEL_COMMAND,		CMorphingArbitraryFIRFilterDialog::ID_NUMBER_OF_OCTAVES,	CMorphingArbitraryFIRFilterDialog::onFrequencyRangeChange),
344 	FXMAPFUNC(SEL_COMMAND,		CMorphingArbitraryFIRFilterDialog::ID_USE_LFO_CHECKBOX,		CMorphingArbitraryFIRFilterDialog::onUseLFOCheckBox),
345 	FXMAPFUNC(SEL_COMMAND,		CMorphingArbitraryFIRFilterDialog::ID_COPY_1_TO_2,		CMorphingArbitraryFIRFilterDialog::on1To2Button),
346 	FXMAPFUNC(SEL_COMMAND,		CMorphingArbitraryFIRFilterDialog::ID_COPY_2_TO_1,		CMorphingArbitraryFIRFilterDialog::on1To2Button),
347 	FXMAPFUNC(SEL_COMMAND,		CMorphingArbitraryFIRFilterDialog::ID_SWAP_1_AND_2,		CMorphingArbitraryFIRFilterDialog::on1To2Button),
348 };
349 
FXIMPLEMENT(CMorphingArbitraryFIRFilterDialog,CActionParamDialog,CMorphingArbitraryFIRFilterDialogMap,ARRAYNUMBER (CMorphingArbitraryFIRFilterDialogMap))350 FXIMPLEMENT(CMorphingArbitraryFIRFilterDialog,CActionParamDialog,CMorphingArbitraryFIRFilterDialogMap,ARRAYNUMBER(CMorphingArbitraryFIRFilterDialogMap))
351 
352 CMorphingArbitraryFIRFilterDialog::CMorphingArbitraryFIRFilterDialog(FXWindow *mainWindow) :
353 	CActionParamDialog(mainWindow)
354 {
355 	FXPacker *p0,*p1,*p2,*p3;
356 
357 	p0=newVertPanel(NULL);
358 		p1=newHorzPanel(p0,false);
359 			FXGraphParamValue *g1=addGraph(p1,
360 				N_("Frequency Response 1"),
361 				N_("Frequency"),
362 				"Hz",
363 				freqMapper=new CActionParamMapper_arbitraryFIRFilter_freq,
364 				N_("Change"),
365 				"dB",
366 				new CActionParamMapper_arbitraryFIRFilter_amp(0.0,20,-100,100),
367 				dB_to_scalar
368 			);
369 			g1->setMinSize(450,280);
370 
371 			p2=new FXVerticalFrame(p1,LAYOUT_CENTER_Y, 0,0,0,0, 0,0,0,0, 0,0);
372 				new FXButton(p2,FXString("->\t")+_("Copy Response 1 to Response 2"),NULL,this,ID_COPY_1_TO_2,BUTTON_NORMAL|LAYOUT_FILL_X);
373 				new FXButton(p2,FXString("<>\t")+_("Swap Response 1 and Response 2"),NULL,this,ID_SWAP_1_AND_2,BUTTON_NORMAL|LAYOUT_FILL_X);
374 				new FXButton(p2,FXString("<-\t")+_("Copy Response 2 to Response 1"),NULL,this,ID_COPY_2_TO_1,BUTTON_NORMAL|LAYOUT_FILL_X);
375 
376 			FXGraphParamValue *g2=addGraph(p1,
377 				N_("Frequency Response 2"),
378 				N_("Frequency"),
379 				"Hz",
380 				freqMapper,
381 				N_("Change"),
382 				"dB",
383 				new CActionParamMapper_arbitraryFIRFilter_amp(0.0,20,-100,100),
384 				dB_to_scalar
385 			);
386 			g2->setMinSize(450,280);
387 
388 		p1=newHorzPanel(p0,false);
389 			p2=newHorzPanel(p1,false);
390 			p2->setLayoutHints(p2->getLayoutHints()&(~LAYOUT_FILL_X));
391 
392 				FXConstantParamValue *wetdryMix=addSlider(p2,
393 					N_("Wet/Dry Mix"),
394 					"%",
395 					new CActionParamMapper_linear_range(100.0,-100,100),
396 					NULL,
397 					true
398 				);
399 				wetdryMix->setMinSize(0,150);
400 
401 				p3=newVertPanel(p2,false);
402 					FXCheckBoxParamValue *useLFOCheckBox=addCheckBoxEntry(p3,
403 						N_("Use LFO"),
404 						false
405 					);
406 					useLFOCheckBox->setTarget(this);
407 					useLFOCheckBox->setSelector(ID_USE_LFO_CHECKBOX);
408 
409 					FXLFOParamValue *lfo=addLFO(p3,
410 						N_("Sweep LFO"),
411 						"ms",
412 						"",
413 						0,
414 						"Hz",
415 						20,
416 						true
417 					);
418 					lfo->setMinSize(0,170);
419 
420 				p3=newVertPanel(p2,false);
421 					FXConstantParamValue *kernelLength=addSlider(p3,
422 						N_("Kernel Length"),
423 						"",
424 						new CActionParamMapper_arbitraryFIRFilter_kernelLength(1024),
425 						NULL,
426 						false
427 					);
428 					setTipText("Kernel Length",_("This is the Size of the Filter Kernel Computed (in samples) From Your Curve to be Convolved with the Audio"));
429 					kernelLength->setMinSize(0,150);
430 
431 					addCheckBoxEntry(p3,
432 						N_("Undelay"),
433 						true,
434 						_("This Counteracts the Delay Side-Effect of Custom FIR Filters")
435 					);
436 
437 			p2=newVertPanel(p1,false);
438 			p2->setLayoutHints(p2->getLayoutHints()&(~LAYOUT_FILL_Y));
439 			p2->setLayoutHints(p2->getLayoutHints()&(~LAYOUT_FILL_X));
440 				FXTextParamValue *baseFrequency=addNumericTextEntry(p2,
441 					N_("Base Frequency"),
442 					"Hz",
443 					20,
444 					10,
445 					1000,
446 					_("This Sets the Lowest Frequency Displayed on the Graph.\nThis is the Frequency of the First Octave.")
447 				);
448 					baseFrequency->setTarget(this);
449 					baseFrequency->setSelector(ID_BASE_FREQUENCY);
450 
451 				FXTextParamValue *numberOfOctaves=addNumericTextEntry(p2,
452 					N_("Number of Octaves"),
453 					"",
454 					11,
455 					1,
456 					15,
457 					_("This Sets the Number of Octaves Displayed on the Graph.\nBut Note that no Frequency Higher than Half of the Sound's Sampling Rate can be Affected Since it Cannot Contain a Frequency Higher than That.")
458 				);
459 					numberOfOctaves->setTarget(this);
460 					numberOfOctaves->setSelector(ID_NUMBER_OF_OCTAVES);
461 
462 
463 	onFrequencyRangeChange(NULL,0,NULL);
464 	onUseLFOCheckBox(useLFOCheckBox,0,NULL);
465 }
466 
onFrequencyRangeChange(FXObject * sender,FXSelector sel,void * ptr)467 long CMorphingArbitraryFIRFilterDialog::onFrequencyRangeChange(FXObject *sender,FXSelector sel,void *ptr)
468 {
469 	FXGraphParamValue *g1=getGraphParam("Frequency Response 1");
470 	FXGraphParamValue *g2=getGraphParam("Frequency Response 2");
471 
472 	FXTextParamValue *baseFrequency=getTextParam("Base Frequency");
473 	FXTextParamValue *numberOfOctaves=getTextParam("Number of Octaves");
474 
475 	freqMapper->baseFrequency=(unsigned)baseFrequency->getValue();
476 	freqMapper->numberOfOctaves=(unsigned)numberOfOctaves->getValue();
477 
478 	g1->updateNumbers();
479 	g2->updateNumbers();
480 
481 	return 1;
482 }
483 
onUseLFOCheckBox(FXObject * sender,FXSelector sel,void * ptr)484 long CMorphingArbitraryFIRFilterDialog::onUseLFOCheckBox(FXObject *sender,FXSelector sel,void *ptr)
485 {
486 	if(((FXCheckBoxParamValue *)sender)->getValue())
487 		getLFOParam("Sweep LFO")->enable();
488 	else
489 		getLFOParam("Sweep LFO")->disable();
490 	return 1;
491 }
492 
on1To2Button(FXObject * sender,FXSelector sel,void * ptr)493 long CMorphingArbitraryFIRFilterDialog::on1To2Button(FXObject *sender,FXSelector sel,void *ptr)
494 {
495 	switch(FXSELID(sel))
496 	{
497 	case ID_COPY_1_TO_2:
498 		getGraphParam("Frequency Response 2")->copyFrom(getGraphParam("Frequency Response 1"));
499 		break;
500 	case ID_COPY_2_TO_1:
501 		getGraphParam("Frequency Response 1")->copyFrom(getGraphParam("Frequency Response 2"));
502 		break;
503 	case ID_SWAP_1_AND_2:
504 		getGraphParam("Frequency Response 1")->swapWith(getGraphParam("Frequency Response 2"));
505 		break;
506 	default:
507 		throw runtime_error(string(__func__)+" -- unhandled selector");
508 	}
509 	return 0;
510 }
511 
validateOnOkay()512 bool CMorphingArbitraryFIRFilterDialog::validateOnOkay()
513 {
514 	if(getGraphParam("Frequency Response 1")->getNodes().size()!=getGraphParam("Frequency Response 2")->getNodes().size())
515 	{
516 		Error(_("Frequency Response 1 and Frequency Response 2 must contain the same number of nodes"));
517 		return false;
518 	}
519 	return true;
520 }
521 
522 #include "../backend/Filters/CMorphingArbitraryFIRFilter.h"
getExplanation() const523 const string CMorphingArbitraryFIRFilterDialog::getExplanation() const
524 {
525 	return CMorphingArbitraryFIRFilter::getExplanation();
526 }
527 
528 
529 
530 
531 
532 
533 
534 
535 
536 // --- single pole lowpass ---------------
537 
CSinglePoleLowpassFilterDialog(FXWindow * mainWindow)538 CSinglePoleLowpassFilterDialog::CSinglePoleLowpassFilterDialog(FXWindow *mainWindow) :
539 	CActionParamDialog(mainWindow)
540 {
541 	void *p=newHorzPanel(NULL);
542 		addSlider(p,
543 			N_("Gain"),
544 			"x",
545 			new CActionParamMapper_recipsym(1.0,2,2,50),
546 			NULL,
547 			true
548 		);
549 
550 		addSlider(p,
551 			N_("Cutoff Frequency"),
552 			"Hz",
553 			new CActionParamMapper_linear(500.0,5000,5,100000),
554 			NULL,
555 			false
556 		);
557 }
558 
559 // --- single pole highpass --------------
560 
CSinglePoleHighpassFilterDialog(FXWindow * mainWindow)561 CSinglePoleHighpassFilterDialog::CSinglePoleHighpassFilterDialog(FXWindow *mainWindow) :
562 	CActionParamDialog(mainWindow)
563 {
564 	void *p=newHorzPanel(NULL);
565 		addSlider(p,
566 			N_("Gain"),
567 			"x",
568 			new CActionParamMapper_recipsym(1.0,2,2,50),
569 			NULL,
570 			true
571 		);
572 
573 		addSlider(p,
574 			N_("Cutoff Frequency"),
575 			"Hz",
576 			new CActionParamMapper_linear(1000.0,10000,5,100000),
577 			NULL,
578 			false
579 		);
580 }
581 
582 // --- bandpass --------------------------
583 
CBandpassFilterDialog(FXWindow * mainWindow)584 CBandpassFilterDialog::CBandpassFilterDialog(FXWindow *mainWindow) :
585 	CActionParamDialog(mainWindow)
586 {
587 	void *p=newHorzPanel(NULL);
588 		addSlider(p,
589 			N_("Gain"),
590 			"x",
591 			new CActionParamMapper_recipsym(1.0,2,2,50),
592 			NULL,
593 			true
594 		);
595 
596 		addSlider(p,
597 			N_("Center Frequency"),
598 			"Hz",
599 			new CActionParamMapper_linear(1000.0,10000,5,100000),
600 			NULL,
601 			false
602 		);
603 
604 		addSlider(p,
605 			N_("Band Width"),
606 			"Hz",
607 			new CActionParamMapper_linear(500.0,1000,5,100000),
608 			NULL,
609 			false
610 		);
611 }
612 
613 // --- notch -----------------------------
614 
CNotchFilterDialog(FXWindow * mainWindow)615 CNotchFilterDialog::CNotchFilterDialog(FXWindow *mainWindow) :
616 	CActionParamDialog(mainWindow)
617 {
618 	void *p=newHorzPanel(NULL);
619 		addSlider(p,
620 			N_("Gain"),
621 			"x",
622 			new CActionParamMapper_recipsym(1.0,2,2,50),
623 			NULL,
624 			true
625 		);
626 
627 		addSlider(p,
628 			N_("Center Frequency"),
629 			"Hz",
630 			new CActionParamMapper_linear(1000.0,10000,5,100000),
631 			NULL,
632 			false
633 		);
634 
635 		addSlider(p,
636 			N_("Band Width"),
637 			"Hz",
638 			new CActionParamMapper_linear(500.0,1000,5,100000),
639 			NULL,
640 			false
641 		);
642 }
643 
644 
645 
646 // --- biquad resonant lowpass -----------
647 
CBiquadResLowpassFilterDialog(FXWindow * mainWindow)648 CBiquadResLowpassFilterDialog::CBiquadResLowpassFilterDialog(FXWindow *mainWindow) :
649 	CActionParamDialog(mainWindow)
650 {
651 	void *p=newHorzPanel(NULL);
652 		addSlider(p,
653 			N_("Gain"),
654 			"x",
655 			new CActionParamMapper_recipsym(1.0,2,2,50),
656 			NULL,
657 			true
658 		);
659 
660 		addSlider(p,
661 			N_("Cutoff Frequency"),
662 			"Hz",
663 			new CActionParamMapper_linear(500.0,5000,5,100000),
664 			NULL,
665 			false
666 		);
667 
668 		addSlider(p,
669 			N_("Resonance"),
670 			"x",
671 			new CActionParamMapper_recipsym(2.0,2,1,20),
672 			NULL,
673 			true
674 		);
675 }
676 
677 // --- biquad resonant highpass ----------
678 
CBiquadResHighpassFilterDialog(FXWindow * mainWindow)679 CBiquadResHighpassFilterDialog::CBiquadResHighpassFilterDialog(FXWindow *mainWindow) :
680 	CActionParamDialog(mainWindow)
681 {
682 	void *p=newHorzPanel(NULL);
683 		addSlider(p,
684 			N_("Gain"),
685 			"x",
686 			new CActionParamMapper_recipsym(1.0,2,2,50),
687 			NULL,
688 			true
689 		);
690 
691 		addSlider(p,
692 			N_("Cutoff Frequency"),
693 			"Hz",
694 			new CActionParamMapper_linear(500.0,5000,5,100000),
695 			NULL,
696 			false
697 		);
698 
699 		addSlider(p,
700 			N_("Resonance"),
701 			"x",
702 			new CActionParamMapper_recipsym(2.0,2,1,20),
703 			NULL,
704 			true
705 		);
706 }
707 
708 // --- biquad resonant bandpass ----------
709 
CBiquadResBandpassFilterDialog(FXWindow * mainWindow)710 CBiquadResBandpassFilterDialog::CBiquadResBandpassFilterDialog(FXWindow *mainWindow) :
711 	CActionParamDialog(mainWindow)
712 {
713 	void *p=newHorzPanel(NULL);
714 		addSlider(p,
715 			N_("Gain"),
716 			"x",
717 			new CActionParamMapper_recipsym(1.0,2,2,50),
718 			NULL,
719 			true
720 		);
721 
722 		addSlider(p,
723 			N_("Center Frequency"),
724 			"Hz",
725 			new CActionParamMapper_linear(500.0,5000,5,100000),
726 			NULL,
727 			false
728 		);
729 
730 		addSlider(p,
731 			N_("Resonance"),
732 			"x",
733 			new CActionParamMapper_recipsym(2.0,2,1,20),
734 			NULL,
735 			true
736 		);
737 }
738 
739