/***************************************************************************
                          tone.h  -  description
                             -------------------
    begin                : Don Feb 10 2005
    copyright            : (C) 2005 by klaus frieler
    email                : kgf@omniversum.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
#ifndef _LIBMELODY_SEGMENTER_H
#define _LIBMELODY_SEGMENTER_H
#include "types.h"
#include "Melody.h"
#include "Vector.h"

class SegmenterBase
{
public:
   SegmenterBase(const Melody *pMel): m_pMel(pMel), m_sErrText(""){};
   virtual ~SegmenterBase(){};

   virtual Vector analyze() = 0;
   string   getErrText(){ return m_sErrText; }

protected:
   const Melody * m_pMel;
   string         m_sErrText;

private:
};

class LBDMBase: public SegmenterBase
{
public:

   typedef enum{ iois = 0, pitches, rests} IntervalType;

public:
   LBDMBase(const Melody* pMel, const IntervalType interval): SegmenterBase(pMel), m_interval(interval)
   {}
   
   virtual Vector analyze(){Vector ret; return ret;} ;
   
   void           setIntervalType(IntervalType interval){ m_interval = interval;}
   Vector         getBoundaries(const Vector& bounds);
   Vector         getSecondBoundaries(const Vector& bounds);

protected:
   IntervalType   m_interval;

   dData          getIOIs();
   dData          getOOIs();
   dData          getPitchIntervals() ;
   virtual Vector assignBoundaryStrengths(const dData& intervals)const {Vector ret; return ret;}

private:

};

class PlainLBDM: public LBDMBase
{
public:
   struct Parameters{
      Parameters(double bon = 0., double d = 1., double big = 1.,bool useBonus = false):bonus(bon), diff(d), bigger(big), bUseBonus(useBonus)
      {}
      double bonus;
      double diff;
      double bigger;
      bool bUseBonus;
   };

public:
   PlainLBDM(const Melody *pMel, const LBDMBase::IntervalType interval, double bonus , double diff, double larger, bool bUseBonus):
      LBDMBase(pMel, interval), m_param(bonus, diff,larger, bUseBonus)
   {}
   PlainLBDM(const Melody *pMel, const LBDMBase::IntervalType interval): LBDMBase(pMel, interval), m_param(2.,1.,1., false)
   {}

   Vector   analyze();
   void     setParameters(PlainLBDM::Parameters param)
   {
      m_param = param; //structure copy!
   }

protected:
   PlainLBDM::Parameters  m_param;

   int      getIntervalRelation(const double d1, const double d2) const;
   Vector   assignBoundaryStrengths(const dData& intervals);

};

class RefinedLBDM: public LBDMBase
{
public:
   RefinedLBDM(const Melody *pMel, LBDMBase::IntervalType interval): LBDMBase(pMel, interval)
   {}
   Vector   analyze();

protected:
   Vector   assignBoundaryStrengths(const dData& intervals);
   double   alpha(double x, double y) const;
};

class TemperleySegmenter: public SegmenterBase
{
public:
   struct Parameters{
      Parameters(uint opt = 10, double gap = 0.5, double lenW = 0.6, double phase4 = 0.15, double phase3 = 0.3, uint testLen = 20)
         :optimalLength(opt), gapWeight(gap), lengthWeight(lenW),
         phase4Penalty(phase4), phase3Penalty(phase3), testLength(testLen)
      {}
      uint     optimalLength;
      double   gapWeight;
      double   lengthWeight;
      double   phase4Penalty;
      double   phase3Penalty;
      uint     testLength;
   };

public:
   TemperleySegmenter(const Melody *pMel): SegmenterBase(pMel){}
   TemperleySegmenter(const Melody *pMel, const Parameters param): SegmenterBase(pMel), m_params(param){}
   virtual ~TemperleySegmenter(){};

   virtual  Vector   analyze();
   string            getErrText(){ return m_sErrText; }

protected:
   Parameters        m_params;
   dData             getIOIs();
   dData             getOOIs();
   dData             getPitchIntervals() ;

   Vector            assignGapScores() ;
   double            getPhasePenalty(const Tone& tone1, const Tone& tone2) const;
   double            getLengthPenalty(const uint len){ 
      return fabs(m_params.lengthWeight*1.4427*log((double)len/m_params.optimalLength));
   }
private:

};

class SimpleSegmenter:public SegmenterBase
{
public:
   struct Parameters{
      Parameters(uint gapTime = 1500, double modusFactor = 3.9, bool runningModus = false)
         :m_gapTime(gapTime), m_modusFactor(modusFactor), m_bRunningModus(runningModus)
      {}
      uint     m_gapTime;
      double   m_modusFactor;
      bool m_bRunningModus;
   };
   SimpleSegmenter(const Melody *pMel): SegmenterBase(pMel){}
   virtual  Vector   analyze();
   string            getErrText(){ return m_sErrText; }
   void              setParameters(const Parameters params){m_params = params;}
protected:
   Parameters        m_params;

private:
};
#endif
