Audacity  2.2.2
Normalize.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  Normalize.cpp
6 
7  Dominic Mazzoni
8  Vaughan Johnson (Preview)
9 
10 *******************************************************************//*******************************************************************/
16 
17 
18 #include "../Audacity.h" // for rint from configwin.h
19 #include "Normalize.h"
20 
21 #include <math.h>
22 
23 #include <wx/intl.h>
24 #include <wx/valgen.h>
25 
26 #include "../Internat.h"
27 #include "../Prefs.h"
28 #include "../ShuttleGui.h"
29 #include "../WaveTrack.h"
30 #include "../widgets/valnum.h"
31 
32 // Define keys, defaults, minimums, and maximums for the effect parameters
33 //
34 // Name Type Key Def Min Max Scale
35 Param( Level, double, wxT("Level"), -1.0, -145.0, 0.0, 1 );
36 Param( RemoveDC, bool, wxT("RemoveDcOffset"), true, false, true, 1 );
37 Param( ApplyGain, bool, wxT("ApplyGain"), true, false, true, 1 );
38 Param( StereoInd, bool, wxT("StereoIndependent"), false, false, true, 1 );
39 
40 BEGIN_EVENT_TABLE(EffectNormalize, wxEvtHandler)
41  EVT_CHECKBOX(wxID_ANY, EffectNormalize::OnUpdateUI)
42  EVT_TEXT(wxID_ANY, EffectNormalize::OnUpdateUI)
44 
46 {
47  mLevel = DEF_Level;
48  mDC = DEF_RemoveDC;
49  mGain = DEF_ApplyGain;
50  mStereoInd = DEF_StereoInd;
51 
52  SetLinearEffectFlag(false);
53 }
54 
56 {
57 }
58 
59 // IdentInterface implementation
60 
62 {
64 }
65 
67 {
68  return _("Sets the peak amplitude of one or more tracks");
69 }
70 
72 {
73  return wxT("Normalize");
74 }
75 
76 // EffectDefinitionInterface implementation
77 
79 {
80  return EffectTypeProcess;
81 }
82 
83 // EffectClientInterface implementation
85  S.SHUTTLE_PARAM( mLevel, Level );
86  S.SHUTTLE_PARAM( mGain, ApplyGain );
87  S.SHUTTLE_PARAM( mDC, RemoveDC );
88  S.SHUTTLE_PARAM( mStereoInd, StereoInd );
89  return true;
90 }
91 
93 {
94  parms.Write(KEY_Level, mLevel);
95  parms.Write(KEY_ApplyGain, mGain);
96  parms.Write(KEY_RemoveDC, mDC);
97  parms.Write(KEY_StereoInd, mStereoInd);
98 
99  return true;
100 }
101 
103 {
104  ReadAndVerifyDouble(Level);
105  ReadAndVerifyBool(ApplyGain);
106  ReadAndVerifyBool(RemoveDC);
107  ReadAndVerifyBool(StereoInd);
108 
109  mLevel = Level;
110  mGain = ApplyGain;
111  mDC = RemoveDC;
112  mStereoInd = StereoInd;
113 
114  return true;
115 }
116 
117 // Effect implementation
118 
120 {
121  return ((mGain == false) && (mDC == false));
122 }
123 
125 {
126  wxString base = wxT("/Effects/Normalize/");
127 
128  // Migrate settings from 2.1.0 or before
129 
130  // Already migrated, so bail
131  if (gPrefs->Exists(base + wxT("Migrated")))
132  {
133  return true;
134  }
135 
136  // Load the old "current" settings
137  if (gPrefs->Exists(base))
138  {
139  int boolProxy = gPrefs->Read(base + wxT("RemoveDcOffset"), 1);
140  mDC = (boolProxy == 1);
141  boolProxy = gPrefs->Read(base + wxT("Normalize"), 1);
142  mGain = (boolProxy == 1);
143  gPrefs->Read(base + wxT("Level"), &mLevel, -1.0);
144  if(mLevel > 0.0) // this should never happen
145  mLevel = -mLevel;
146  boolProxy = gPrefs->Read(base + wxT("StereoIndependent"), 0L);
147  mStereoInd = (boolProxy == 1);
148 
150 
151  // Do not migrate again
152  gPrefs->Write(base + wxT("Migrated"), true);
153  gPrefs->Flush();
154  }
155 
156  return true;
157 }
158 
160 {
161  if (mGain == false && mDC == false)
162  return true;
163 
164  float ratio;
165  if( mGain )
166  // same value used for all tracks
167  ratio = DB_TO_LINEAR(TrapDouble(mLevel, MIN_Level, MAX_Level));
168  else
169  ratio = 1.0;
170 
171  //Iterate over each track
172  this->CopyInputTracks(); // Set up mOutputTracks.
173  bool bGoodResult = true;
175  WaveTrack *track = (WaveTrack *) iter.First();
176  WaveTrack *prevTrack;
177  prevTrack = track;
178  int curTrackNum = 0;
179  wxString topMsg;
180  if(mDC && mGain)
181  topMsg = _("Removing DC offset and Normalizing...\n");
182  else if(mDC && !mGain)
183  topMsg = _("Removing DC offset...\n");
184  else if(!mDC && mGain)
185  topMsg = _("Normalizing without removing DC offset...\n");
186  else if(!mDC && !mGain)
187  topMsg = _("Not doing anything...\n"); // shouldn't get here
188 
189  while (track) {
190  //Get start and end times from track
191  double trackStart = track->GetStartTime();
192  double trackEnd = track->GetEndTime();
193 
194  //Set the current bounds to whichever left marker is
195  //greater and whichever right marker is less:
196  mCurT0 = mT0 < trackStart? trackStart: mT0;
197  mCurT1 = mT1 > trackEnd? trackEnd: mT1;
198 
199  // Process only if the right marker is to the right of the left marker
200  if (mCurT1 > mCurT0) {
201  wxString msg;
202  auto trackName = track->GetName();
203 
204  if(!track->GetLinked() || mStereoInd)
205  msg =
206  topMsg + wxString::Format( _("Analyzing: %s"), trackName );
207  else
208  msg =
209  topMsg + wxString::Format( _("Analyzing first track of stereo pair: %s"), trackName );
210  float offset, min, max;
211  bGoodResult = AnalyseTrack(track, msg, curTrackNum, offset, min, max);
212  if (!bGoodResult )
213  break;
214  if(!track->GetLinked() || mStereoInd) {
215  // mono or 'stereo tracks independently'
216  float extent = wxMax(fabs(max), fabs(min));
217  if( (extent > 0) && mGain )
218  mMult = ratio / extent;
219  else
220  mMult = 1.0;
221  msg =
222  topMsg + wxString::Format( _("Processing: %s"), trackName );
223  if(track->GetLinked() || prevTrack->GetLinked()) // only get here if there is a linked track but we are processing independently
224  msg =
225  topMsg + wxString::Format( _("Processing stereo channels independently: %s"), trackName );
226 
227  if (!ProcessOne(track, msg, curTrackNum, offset))
228  {
229  bGoodResult = false;
230  break;
231  }
232  }
233  else
234  {
235  // we have a linked stereo track
236  // so we need to find it's min, max and offset
237  // as they are needed to calc the multiplier for both tracks
238  track = (WaveTrack *) iter.Next(); // get the next one
239  msg =
240  topMsg + wxString::Format( _("Analyzing second track of stereo pair: %s"), trackName );
241  float offset2, min2, max2;
242  bGoodResult = AnalyseTrack(track, msg, curTrackNum + 1, offset2, min2, max2);
243  if ( !bGoodResult )
244  break;
245  float extent = wxMax(fabs(min), fabs(max));
246  extent = wxMax(extent, fabs(min2));
247  extent = wxMax(extent, fabs(max2));
248  if( (extent > 0) && mGain )
249  mMult = ratio / extent; // we need to use this for both linked tracks
250  else
251  mMult = 1.0;
252  track = (WaveTrack *) iter.Prev(); // go back to the first linked one
253  msg =
254  topMsg + wxString::Format( _("Processing first track of stereo pair: %s"), trackName );
255  if (!ProcessOne(track, msg, curTrackNum, offset))
256  {
257  bGoodResult = false;
258  break;
259  }
260  track = (WaveTrack *) iter.Next(); // go to the second linked one
261  curTrackNum++; // keeps progress bar correct
262  msg =
263  topMsg + wxString::Format( _("Processing second track of stereo pair: %s"), trackName );
264  if (!ProcessOne(track, msg, curTrackNum, offset2))
265  {
266  bGoodResult = false;
267  break;
268  }
269  }
270  }
271 
272  //Iterate to the next track
273  prevTrack = track;
274  track = (WaveTrack *) iter.Next();
275  curTrackNum++;
276  }
277 
278  this->ReplaceProcessedTracks(bGoodResult);
279  return bGoodResult;
280 }
281 
283 {
284  mCreating = true;
285 
286  S.StartVerticalLay(0);
287  {
288  S.StartMultiColumn(2, wxALIGN_CENTER);
289  {
290  S.StartVerticalLay(false);
291  {
292  mDCCheckBox = S.AddCheckBox(_("Remove DC offset (center on 0.0 vertically)"),
293  mDC ? wxT("true") : wxT("false"));
294  mDCCheckBox->SetValidator(wxGenericValidator(&mDC));
295 
296  S.StartHorizontalLay(wxALIGN_CENTER, false);
297  {
298  mGainCheckBox = S.AddCheckBox(_("Normalize maximum amplitude to"),
299  mGain ? wxT("true") : wxT("false"));
300  mGainCheckBox->SetValidator(wxGenericValidator(&mGain));
301 
302  FloatingPointValidator<double> vldLevel(2, &mLevel, NumValidatorStyle::ONE_TRAILING_ZERO);
303  vldLevel.SetRange(MIN_Level, MAX_Level);
304  mLevelTextCtrl = S.AddTextBox( {}, wxT(""), 10);
305  mLevelTextCtrl->SetName(_("Maximum amplitude dB"));
306  mLevelTextCtrl->SetValidator(vldLevel);
307  mLeveldB = S.AddVariableText(_("dB"), false,
308  wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT);
309  mWarning = S.AddVariableText( {}, false,
310  wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT);
311  }
312  S.EndHorizontalLay();
313 
314 
315  mStereoIndCheckBox = S.AddCheckBox(_("Normalize stereo channels independently"),
316  mStereoInd ? wxT("true") : wxT("false"));
317  mStereoIndCheckBox->SetValidator(wxGenericValidator(&mStereoInd));
318  }
319  S.EndVerticalLay();
320  }
321  S.EndMultiColumn();
322  }
323  S.EndVerticalLay();
324 
325  mCreating = false;
326 }
327 
329 {
330  if (!mUIParent->TransferDataToWindow())
331  {
332  return false;
333  }
334 
335  UpdateUI();
336 
337  return true;
338 }
339 
341 {
342  if (!mUIParent->Validate() || !mUIParent->TransferDataFromWindow())
343  {
344  return false;
345  }
346 
347  return true;
348 }
349 
350 // EffectNormalize implementation
351 
352 bool EffectNormalize::AnalyseTrack(const WaveTrack * track, const wxString &msg,
353  int curTrackNum,
354  float &offset, float &min, float &max)
355 {
356  if(mGain) {
357  // Since we need complete summary data, we need to block until the OD tasks are done for this track
358  // TODO: should we restrict the flags to just the relevant block files (for selections)
359  while (track->GetODFlags()) {
360  // update the gui
362  0, _("Waiting for waveform to finish computing...")) )
363  return false;
364  wxMilliSleep(100);
365  }
366 
367  // set mMin, mMax. No progress bar here as it's fast.
368  auto pair = track->GetMinMax(mCurT0, mCurT1); // may throw
369  min = pair.first, max = pair.second;
370 
371  } else {
372  min = -1.0, max = 1.0; // sensible defaults?
373  }
374 
375  if(mDC) {
376  auto rc = AnalyseDC(track, msg, curTrackNum, offset);
377  min += offset;
378  max += offset;
379  return rc;
380  } else {
381  offset = 0.0;
382  return true;
383  }
384 }
385 
386 //AnalyseDC() takes a track, transforms it to bunch of buffer-blocks,
387 //and executes AnalyzeData on it...
388 bool EffectNormalize::AnalyseDC(const WaveTrack * track, const wxString &msg,
389  int curTrackNum,
390  float &offset)
391 {
392  bool rc = true;
393 
394  offset = 0.0; // we might just return
395 
396  if(!mDC) // don't do analysis if not doing dc removal
397  return(rc);
398 
399  //Transform the marker timepoints to samples
400  auto start = track->TimeToLongSamples(mCurT0);
401  auto end = track->TimeToLongSamples(mCurT1);
402 
403  //Get the length of the buffer (as double). len is
404  //used simply to calculate a progress meter, so it is easier
405  //to make it a double now than it is to do it later
406  auto len = (end - start).as_double();
407 
408  //Initiate a processing buffer. This buffer will (most likely)
409  //be shorter than the length of the track being processed.
410  Floats buffer{ track->GetMaxBlockSize() };
411 
412  mSum = 0.0; // dc offset inits
413  mCount = 0;
414 
415  sampleCount blockSamples;
416  sampleCount totalSamples = 0;
417 
418  //Go through the track one buffer at a time. s counts which
419  //sample the current buffer starts at.
420  auto s = start;
421  while (s < end) {
422  //Get a block of samples (smaller than the size of the buffer)
423  //Adjust the block size if it is the final block in the track
424  const auto block = limitSampleBufferSize(
425  track->GetBestBlockSize(s),
426  end - s
427  );
428 
429  //Get the samples from the track and put them in the buffer
430  track->Get((samplePtr) buffer.get(), floatSample, s, block, fillZero, true, &blockSamples);
431  totalSamples += blockSamples;
432 
433  //Process the buffer.
434  AnalyzeData(buffer.get(), block);
435 
436  //Increment s one blockfull of samples
437  s += block;
438 
439  //Update the Progress meter
440  if (TrackProgress(curTrackNum,
441  ((s - start).as_double() / len)/2.0, msg)) {
442  rc = false; //lda .. break, not return, so that buffer is deleted
443  break;
444  }
445  }
446  if( totalSamples > 0 )
447  offset = -mSum / totalSamples.as_double(); // calculate actual offset (amount that needs to be added on)
448  else
449  offset = 0.0;
450 
451  //Return true because the effect processing succeeded ... unless cancelled
452  return rc;
453 }
454 
455 //ProcessOne() takes a track, transforms it to bunch of buffer-blocks,
456 //and executes ProcessData, on it...
457 // uses mMult and offset to normalize a track.
458 // mMult must be set before this is called
460  WaveTrack * track, const wxString &msg, int curTrackNum, float offset)
461 {
462  bool rc = true;
463 
464  //Transform the marker timepoints to samples
465  auto start = track->TimeToLongSamples(mCurT0);
466  auto end = track->TimeToLongSamples(mCurT1);
467 
468  //Get the length of the buffer (as double). len is
469  //used simply to calculate a progress meter, so it is easier
470  //to make it a double now than it is to do it later
471  auto len = (end - start).as_double();
472 
473  //Initiate a processing buffer. This buffer will (most likely)
474  //be shorter than the length of the track being processed.
475  Floats buffer{ track->GetMaxBlockSize() };
476 
477  //Go through the track one buffer at a time. s counts which
478  //sample the current buffer starts at.
479  auto s = start;
480  while (s < end) {
481  //Get a block of samples (smaller than the size of the buffer)
482  //Adjust the block size if it is the final block in the track
483  const auto block = limitSampleBufferSize(
484  track->GetBestBlockSize(s),
485  end - s
486  );
487 
488  //Get the samples from the track and put them in the buffer
489  track->Get((samplePtr) buffer.get(), floatSample, s, block);
490 
491  //Process the buffer.
492  ProcessData(buffer.get(), block, offset);
493 
494  //Copy the newly-changed samples back onto the track.
495  track->Set((samplePtr) buffer.get(), floatSample, s, block);
496 
497  //Increment s one blockfull of samples
498  s += block;
499 
500  //Update the Progress meter
501  if (TrackProgress(curTrackNum,
502  0.5+((s - start).as_double() / len)/2.0, msg)) {
503  rc = false; //lda .. break, not return, so that buffer is deleted
504  break;
505  }
506  }
507 
508  //Return true because the effect processing succeeded ... unless cancelled
509  return rc;
510 }
511 
512 void EffectNormalize::AnalyzeData(float *buffer, size_t len)
513 {
514  for(decltype(len) i = 0; i < len; i++)
515  mSum += (double)buffer[i];
516  mCount += len;
517 }
518 
519 void EffectNormalize::ProcessData(float *buffer, size_t len, float offset)
520 {
521  for(decltype(len) i = 0; i < len; i++) {
522  float adjFrame = (buffer[i] + offset) * mMult;
523  buffer[i] = adjFrame;
524  }
525 }
526 
527 void EffectNormalize::OnUpdateUI(wxCommandEvent & WXUNUSED(evt))
528 {
529  UpdateUI();
530 }
531 
533 {
534  if (!mUIParent->TransferDataFromWindow())
535  {
536  mWarning->SetLabel(_(". Maximum 0dB."));
537  EnableApply(false);
538  return;
539  }
540  mWarning->SetLabel(wxT(""));
541 
542  // Disallow level stuff if not normalizing
543  mLevelTextCtrl->Enable(mGain);
544  mLeveldB->Enable(mGain);
545  mStereoIndCheckBox->Enable(mGain);
546 
547  // Disallow OK/Preview if doing nothing
548  EnableApply(mGain || mDC);
549 }
double mT1
Definition: Effect.h:461
AudacityPrefs * gPrefs
Definition: Prefs.cpp:73
bool SaveUserPreset(const wxString &name) override
Definition: Effect.cpp:600
bool SetAutomationParameters(CommandParameters &parms) override
Definition: Normalize.cpp:102
bool TrackProgress(int whichTrack, double frac, const wxString &=wxEmptyString)
Definition: Effect.cpp:1985
bool ProcessOne(WaveTrack *t, const wxString &msg, int curTrackNum, float offset)
Definition: Normalize.cpp:459
void AnalyzeData(float *buffer, size_t len)
Definition: Normalize.cpp:512
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI...
Definition: ShuttleGui.h:409
wxCheckBox * mDCCheckBox
Definition: Normalize.h:87
ProgressDialog * mProgress
Definition: Effect.h:452
wxString GetCurrentSettingsGroup() override
Definition: Effect.cpp:801
void CopyInputTracks()
Definition: Effect.cpp:2036
void OnUpdateUI(wxCommandEvent &evt)
Definition: Normalize.cpp:527
void ReplaceProcessedTracks(const bool bGoodResult)
Definition: Effect.cpp:2162
void EndMultiColumn()
unsigned int GetODFlags() const
gets an int with OD flags so that we can determine which ODTasks should be run on this track after sa...
Definition: WaveTrack.cpp:1583
void ProcessData(float *buffer, size_t len, float offset)
Definition: Normalize.cpp:519
bool GetLinked() const
Definition: Track.h:278
bool Startup() override
Definition: Normalize.cpp:124
wxCheckBox * mGainCheckBox
Definition: Normalize.h:86
double as_double() const
Definition: Types.h:88
bool TransferDataFromWindow() override
Definition: Normalize.cpp:340
bool GetAutomationParameters(CommandParameters &parms) override
Definition: Normalize.cpp:92
#define NORMALIZE_PLUGIN_SYMBOL
Definition: Normalize.h:25
Param(Level, double, wxT("Level"),-1.0,-145.0, 0.0, 1)
Shuttle that deals with parameters. This is a base class with lots of virtual functions that do nothi...
Definition: Shuttle.h:60
EffectType GetType() override
Definition: Normalize.cpp:78
double mCurT0
Definition: Normalize.h:80
wxTextCtrl * mLevelTextCtrl
Definition: Normalize.h:88
size_t GetBestBlockSize(sampleCount t) const
Definition: WaveTrack.cpp:1607
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
Definition: Types.h:178
void EndHorizontalLay()
void EndVerticalLay()
wxTextCtrl * AddTextBox(const wxString &Caption, const wxString &Value, const int nChars)
Definition: ShuttleGui.cpp:540
wxStaticText * mWarning
Definition: Normalize.h:90
wxCheckBox * AddCheckBox(const wxString &Prompt, const wxString &Selected)
Definition: ShuttleGui.cpp:298
void Set(samplePtr buffer, sampleFormat format, sampleCount start, size_t len)
Definition: WaveTrack.cpp:2052
void StartHorizontalLay(int PositionFlags=wxALIGN_CENTRE, int iProp=1)
bool Process() override
Definition: Normalize.cpp:159
void StartMultiColumn(int nCols, int PositionFlags=wxALIGN_LEFT)
CommandParameters, derived from wxFileConfig, is essentially doing the same things as the Shuttle cla...
char * samplePtr
Definition: Types.h:203
A Track that contains audio waveform data.
Definition: WaveTrack.h:60
An Effect to bring the peak level up to a chosen level.
Definition: Normalize.h:27
ProgressResult Update(int value, const wxString &message=wxEmptyString)
#define ReadAndVerifyDouble(name)
Definition: Effect.h:798
double mLevel
Definition: Normalize.h:75
int min(int a, int b)
IdentInterfaceSymbol pairs a persistent string identifier used internally with an optional...
size_t GetMaxBlockSize() const
Definition: WaveTrack.cpp:1625
bool AnalyseTrack(const WaveTrack *track, const wxString &msg, int curTrackNum, float &offset, float &min, float &max)
Definition: Normalize.cpp:352
IdentInterfaceSymbol GetSymbol() override
Definition: Normalize.cpp:61
sampleCount mCount
Definition: Normalize.h:84
wxWindow * mUIParent
Definition: Effect.h:472
void PopulateOrExchange(ShuttleGui &S) override
Definition: Normalize.cpp:282
double TrapDouble(double x, double min, double max)
Definition: Effect.h:729
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom")).Raw()), OnMoveTrack)#define SET_TRACK_NAME_PLUGIN_SYMBOLclass SetTrackNameCommand:public AudacityCommand
EffectType
sampleCount TimeToLongSamples(double t0) const
Convert correctly between an (absolute) time in seconds and a number of samples.
Definition: WaveTrack.cpp:1843
wxStaticText * mLeveldB
Definition: Normalize.h:89
wxString GetDescription() override
Definition: Normalize.cpp:66
wxStaticText * AddVariableText(const wxString &Str, bool bCenter=false, int PositionFlags=0)
Definition: ShuttleGui.cpp:414
#define ReadAndVerifyBool(name)
Definition: Effect.h:800
double mCurT1
Definition: Normalize.h:81
std::pair< float, float > GetMinMax(double t0, double t1, bool mayThrow=true) const
Definition: WaveTrack.cpp:1898
bool TransferDataToWindow() override
Definition: Normalize.cpp:328
bool CheckWhetherSkipEffect() override
Definition: Normalize.cpp:119
virtual ~EffectNormalize()
Definition: Normalize.cpp:55
END_EVENT_TABLE()
bool Get(samplePtr buffer, sampleFormat format, sampleCount start, size_t len, fillFormat fill=fillZero, bool mayThrow=true, sampleCount *pNumCopied=nullptr) const
Definition: WaveTrack.cpp:1971
bool DefineParams(ShuttleParams &S) override
Definition: Normalize.cpp:84
wxCheckBox * mStereoIndCheckBox
Definition: Normalize.h:91
const double MIN_Threshold_Linear DB_TO_LINEAR(MIN_Threshold_dB)
std::shared_ptr< TrackList > mOutputTracks
Definition: Effect.h:459
bool AnalyseDC(const WaveTrack *track, const wxString &msg, int curTrackNum, float &offset)
Definition: Normalize.cpp:388
virtual bool EnableApply(bool enable=true)
Definition: Effect.cpp:1886
double mT0
Definition: Effect.h:460
wxString ManualPage() override
Definition: Normalize.cpp:71
void StartVerticalLay(int iProp=1)