!******************************************************************************!
! Tests the FILTER macro. Prior to NeXtMidas 3.3.1 the FILTER macro was tested
! via the 'test_filter_macro' procedure in %test_tuner.
!
! @author  Jason Broussard / J. Czechowski IV
! @version $Id: test_filter.mm,v 1.2 2013/01/10 01:45:46 jxc Exp $
! @since   NeXtMidas 3.3.1
!******************************************************************************
startmacro
  switch INTERACTIVE interAct GET DEF=TRUE  SDEF=TRUE  ! for normal interactive test(s)
  switch BASELINE    baseline GET DEF=FALSE SDEF=TRUE  ! for defects or more obscure test case(s)

  waveform ram:sfnoise sf 100k white 1 0 0 0 1
  waveform ram:cfnoise cf 100k white 1 0 0 0 1

  ! ==== FILTER GENERATION =====================================================
  tuner input=ram:sfnoise inputif=0.1 bandwidth=0.1 filtout=ram:imp_resp_sf_time
  fft/psd ram:imp_resp_sf_time ram:imp_resp_sf_freq
  headermod ram:imp_resp_sf_freq type=1000
  call band_atten ram:imp_resp_sf_freq .055 .145 -.4 0 dbout
  if /plot gt 0 plot ram:imp_resp_sf_freq cm=10log
  assert/text="FILTER creation SF" dbout nlt 100

  tuner input=ram:cfnoise inputif=0.1 bandwidth=0.1 filtout=ram:imp_resp_cf_time
  fft/psd ram:imp_resp_cf_time ram:imp_resp_cf_freq
  headermod ram:imp_resp_cf_freq type=1000
  call band_atten ram:imp_resp_cf_freq .055 .145 -.4 0 dbout
  if /plot gt 0 plot ram:imp_resp_cf_freq cm=10log
  assert/text="FILTER creation CF" dbout nlt 100

  ! ==== USER-DEFINED FILTER ===================================================
  filter ram:sfnoise ram:nmsfsfnoiseout,,,ram:imp_resp_sf_time
  fft/psd ram:nmsfsfnoiseout ram:nmsfsffiltspec 2k hanni 0 -1
  headermod ram:nmsfsffiltspec type=1000
  call band_atten ram:nmsfsffiltspec .05 .15 .2 .4  dbout
  if /plot gt 0 plot ram:nmsfsffiltspec cm=10log
  assert/text="FILTER user-defined filter (SF->SF)" dbout nlt 100

  filter ram:cfnoise ram:nmcfcfnoiseout,,,ram:imp_resp_cf_time
  fft/psd ram:nmcfcfnoiseout ram:nmcfcffiltspec 2k hanni 0 -1
  headermod ram:nmcfcffiltspec type=1000
  call band_atten ram:nmcfcffiltspec .05 .15 .2 .4  dbout
  if /plot gt 0 plot ram:nmcfcffiltspec cm=10log
  assert/text="FILTER user-defined filter (CF->CF)" dbout nlt 100

  ! ==== INTERNAL FILTER =======================================================
  filter input=ram:sfnoise output=ram:nmsfsfnoiseout cfreq=.1 bw=.1
  fft/psd ram:nmsfsfnoiseout ram:nmsfsffiltspec 2k hanni 0 -1
  headermod ram:nmsfsffiltspec type=1000
  call band_atten ram:nmsfsffiltspec .05 .15 .2 .4  dbout
  if /plot gt 0 plot ram:nmsfsffiltspec cm=10log
  assert/text="FILTER internal filter test (SF->SF)" dbout nlt 100

  filter ram:cfnoise ram:nmcfcfnoiseout .1 .1
  fft/psd ram:nmcfcfnoiseout ram:nmcfcffiltspec 2k hanni 0 -1
  headermod ram:nmcfcffiltspec type=1000
  call band_atten ram:nmcfcffiltspec .05 .15 -.45 0  dbout
  if /plot gt 0 plot ram:nmcfcffiltspec cm=10log
  assert/text="FILTER internal filter test (CF->CF)" dbout nlt 100

  if interAct then
    set instructions "You may see two deprecation warnings regarding the use &
                      of INFILE= and OUTFILE="

    pipe on
      panel/msgid=MAIN/setup/controls=gc
      shellgui/id=idshellgui/attach

      gcontrol label macro "Test MACRO"
      gcontrol menu  main "Exit with Status =" "PASS,FAIL" TABLE={ItemColors={PASS="GREEN",FAIL="RED"}} /tleft

      gcontrol text  idtext "Instructions" instructions 24 8 /title

      ! ==== Tests for deprecated code =========================================
      waveform _sfnoise sf 100k white 1 0 0 0 1
      filter  input=_sfnoise  output=_output  cfreq=.1 bw=.1
      filter infile=_sfnoise outfile=_outfile cfreq=.1 bw=.1
    pipe run
      assert/TEXT="Deprecated INFILE= and OUTFILE= still work" _output FEQ/B _outfile
    pipe off
  endif
endmacro

!******************************************************************************!
! Main process message for this macro. Should be right after the ENDMACRO.
!******************************************************************************!
procedure processMessage m:msg
  if msg.name eqs "MAIN" then
    assert/text="^reg.main.name: User indicated tests" msg.data eqss "PASS"
    pipe stop
  else
    say "Unhandled message name: ^msg.name from fid: ^msg.fid data: ^msg.data"
  endif
return

!******************************************************************************!
! If an unexpected exception is caught, mark test as failed, unless it is expected
!******************************************************************************!
procedure processException m:emsg
  if expectedException REXISTS then
    assert/text="^reg.main.name: Expected ERROR starts with: ^{expectedException}" expectedException EQSS emsg.data.message
    remove expectedException
  else
    assert/text="^reg.main.name: Caught unexpected exception ^{emsg.data}" "FALSE" isTrue
    if "Trace" SUBS ENV.DEBUG then invoke ,, emsg.data.printStackTrace()
  endif
return

!----------------------------------------------------------------------------
! Checks band attenuation -- NOTE THAT THIS PROCEDURE IS IDENTICAL IN BOTH
!                            %TEST_TUNER and %TEST_FILTER
procedure band_atten s:file d:pass_st d:pass_en d:stop_st d:stop_en u:ratio_db
  ! Calculate bandpass/bandstop ratios for input PSD
  call absc_to_index file pass_st pass_st_ind
  call absc_to_index file pass_en pass_en_ind
  call absc_to_index file stop_st stop_st_ind
  call absc_to_index file stop_en stop_en_ind

  noop ^{file}(^{pass_st_ind}:^{pass_en_ind}) ram:passband
  noop ^{file}(^{stop_st_ind}:^{stop_en_ind}) ram:stopband

  result D:pass_mx 0
  result D:pass_mn 0
  result D:stop_mx 0
  result D:stop_mn 0
  compare ram:passband max_out=pass_mx min_out=pass_mn
  compare ram:stopband max_out=stop_mx min_out=stop_mn
  ! maxmin/quiet ram:passband pass_mx pass_mn
  ! maxmin/quiet ram:stopband stop_mx stop_mn
  !!!say "After maxmin pass_mx=^PASS_MX, pass_mn=^PASS_MN"
  !!!say "After maxmin stop_mx=^STOP_MX, stop_mn=^STOP_MN"

  calc/quiet d:^ratio_db pass_mn stop_mx / log 10 *
  !!!say "ratio_db ^{^RATIO_DB}"
return

!-----------------------------------------------------------------------------
! Converts ABSC to INDEX values -- NOTE THAT THIS PROCEDURE IS IDENTICAL IN BOTH
!                                  %TEST_TUNER and %TEST_FILTER
procedure absc_to_index s:file d:absc_in u:ind_out
  ! Make sure to truncate, NOOP goes south with floating point indices
  status/quiet file xs=file_st xd=file_delt
  calc/quiet l:^ind_out absc_in file_st - file_delt / 1 + round 1 -
return
