# The main function for onset detection

# INPUT: 	path.wav: path to the wav which has to be analysied
#			path.time: path to the time vector of true onsets
#			ctrl: ctrl object (a list), output of OnsetDetectionControl() function

# OUTPUT:	orig.odf: original odf feature
#			smooth.odf: smoothed odf feature
# 			thresh.odf: threshold values
#			est.onset.times: estimated onste times
#			est.onset.frames: estimated frames numbers where a tone onset occures
#			true.onset.times: true onset times
#			fMeasure: F-value of onset detection
#			c: number of correctly detected onsets
#			f.neg: number of undetected onsets
#			f.pos: numper of false detections
# 			dMeasure: F-value of onset detection


onsetDetection=function(path.wav, path.time, ctrl) {
  wav=readWave(path.wav)
  
  if (ctrl$norm.amplit == TRUE){
   # re-scaling the amplitude
   m = max(abs(wav@left))
   wav@left = wav@left/m
  }

  true.times=read.table(path.time)
  true.times=as.numeric(unlist(true.times))
  true.wind=fromTimeToWindow(true.times,ctrl)
  
  # step 1: windowing + FFT + applying of window.fun
  fa=fftArray(wav, ctrl)
  

  #step 2: pre-proceeding 
  fa = adaptivWhitening(fa, ctrl) # Adaptive Weitening
  fa = specFilter(fa, ctrl)	   # Spectral Filter
  fa = specLog(fa, ctrl)    # Logarithming the spactral amplitude
   
  # step 3: computing odf
  odf=getODF(ctrl)
  orig.odf=odf(fa,ctrl)
  
  # fix some rare cases
  w.nan=which(orig.odf=="NaN")
  if (length(w.nan)!=0) 
    orig.odf[w.nan]=0
  
  # step 4: normalizing the odf. Here just smoothing
  smooth.odf=expSmoothing(orig.odf, ctrl)
  
  # step 5: Thresholding
  thresh.odf=threshold(smooth.odf, ctrl)
  
  # step 6: Localizing the tone onsets
  n = length(orig.odf)
  n.onset.left = timeToNrOfWindows(ctrl$onset.time.left,ctrl)
  n.onset.right = timeToNrOfWindows(ctrl$onset.time.right,ctrl)
  onset.min.dist = timeToNrOfWindows(ctrl$onset.time.min.dist,ctrl)
  
  # help function
  compute.onsets= function(n.onset.left, n.onset.right, smooth.odf, thresh.odf, n, onset.min.dist)
  {  
    onsets = numeric(n)
    l=as.list(1:n)
    
    last.onset = -1000
    I1= smooth.odf > thresh.odf  #condition 1: larger than threshold
    
    I2a = unlist(lapply(l, function(x){ind = max(x-n.onset.left,1):min(x+n.onset.right,n) ; max(smooth.odf[ind])}))
    
    I2b = (smooth.odf == I2a)
    
    I3= I1 & I2b
	
    for (i in 1:n){
      
      if( I3[i]  & ((i-last.onset) >= onset.min.dist))  {
        onsets[i] = 1 
        last.onset = i
      }
      else 
        onsets[i] = 0
    }
    return(onsets)
  }

  onsets = compute.onsets(n.onset.left, n.onset.right, smooth.odf, thresh.odf, n, onset.min.dist)
  frames.nr = which(onsets=="1")
  estim.times = fa$win.start.time[frames.nr]
  
  # shift the estim time
  estim.times = estim.times + ctrl$time.onset.shift
  w.neg=which(estim.times<0)
  if (length(w.neg!=0)) estim.times=estim.times[-w.neg]

  # Computing the goodness measures (F- and D-measures)
  time.end = (length(wav@left))/ctrl$sampling.rate
  fMeas = fMeasure(true.times, estim.times, ctrl)
  dMeas = dMeasure(true.times, estim.times, time.end)

  return(list(orig.odf = orig.odf, 
              smooth.odf = smooth.odf, 
              thresh.odf = thresh.odf, 
              est.onset.times = estim.times, 
              est.onset.frames = frames.nr,
              true.onset.times = true.times,
              fMeasure = fMeas$fMeasure,
              c = fMeas$c,
              f.neg = fMeas$fn,
              f.pos = fMeas$fp,
              dMeasure = dMeas))
}
