/***************************************************************************
                          Melody.cpp  -  description
                             -------------------
    begin                : Die Nov 25 2003
    copyright            : (C) 2003 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.                                   *
 *                                                                         *
 ***************************************************************************/
#include "Melody.h"
#include "MIDITime.h"
#include "ZN.h"

double Melody::major[12] = {6.33, 2.23, 3.48, 2.33, 4.38, 4.09, 2.52, 5.19, 2.39, 3.66, 2.29, 2.88 };
double Melody::minor[12] = {6.33, 2.68, 3.52, 5.38, 2.60, 3.53, 2.54, 4.75, 3.98, 2.69, 3.34, 3.17 };

double Melody::tonics[12] = { 
   0.208142456, 0,  0.175188414, 
   0, 0, 0.059775381, 
   0.016920349, 0.143416580, 0.0, 
   0.0, 0.0, 0.056524309
};
Melody  Melody::subMelody(const uint start, const uint end)
{
   Melody ret(*this);
   ret.clear();
   for(uint i = start; i<size()&&i<end ; ++i){
      ret.push_back(at(i));
   } 
   ret.check();
   
   return ret;
}

void  Melody::createOnsets(double start)
{
   double t = start;
   uint totTicks = (uint)floor(getTicksPerMs()*start);
   for(uint i = 0; i<size(); ++i){
      double tmp = at(i).getTime();
      uint  ticks = at(i).getTicks();
      at(i).setTime(t);
      at(i).setTicks(totTicks);
      t += tmp;
      totTicks += ticks;
   }
   Tone  dummy(totTicks, t, DUMMY_PITCH, 0.0, invalidBarPosition);
   push_back(dummy);
}

void Melody::createIOIs()
{
   bool     hasDummy = at(size()-1).getPitch() == DUMMY_PITCH;
   
   for(uint i = 0; i<size()-1; ++i){
      double t1 = at(i).getTime();
      double t2 = at(i+1).getTime();
      Tone tone = at(i);
      at(i).setDuration(t2-t1);
   }
   if(hasDummy){
      ToneList::pop_back();
   }
   else{
      at(size()-1).setDuration(0);
   }
}


bool  Melody::hasMeterInformation() const
{
   BarTimeline timeLine  = getBarPositions();
   for(uint i = 0; i<timeLine.size(); ++i){
      if(timeLine[i] == invalidBarPosition) return false;
   }
   return true;
}

uint  Melody::calculateKey(const uint mode)const
{
   if(mode == 1) return calculateKeyKS();
   return calculateKeyMarkov();
}
uint  Melody::calculateKeyKS()const
{
   uint key = 0;//C-Major
   double maxVal = 0;
   for(uint i = 0; i<12; ++i){
      double sumMinor = 0;
      double sumMajor = 0;
            
      for(uint j = 0; j<size();++j){
         Chroma pc(at(j).getPitch()-C0);
         Chroma k(pc.get() - i);
         sumMinor +=Melody::minor[k.get()];
         sumMajor +=Melody::major[k.get()];
         //cout<<"Pitch: "<<at(j).getPitch()<<" pc = "<<pc.get()<<" Key = "<<i<<" pc = "<<k.get()<<endl;
      }
      //cout<<"Key: "<<i<<" Major: "<<sumMajor<<" Minor: "<<sumMinor<<endl;
      if(sumMinor>maxVal){
         key = i + 12;
         maxVal = sumMinor;
      }
      if(sumMajor>maxVal){
         key = i;
         maxVal = sumMajor;
      }
   }
   return key;
}

uint  Melody::calculateKeyMarkov()const
{
   uint key = 0;//C-Major
   double maxVal = 0;
   for(uint i = 0; i<12; ++i){
      double sum = 0;
            
      for(uint j = 0; j<size();++j){
         Chroma pc(at(j).getPitch()-C0);
         Chroma k(pc.get() - i);
         sum +=Melody::tonics[k.get()];
         //cout<<"Pitch: "<<at(j).getPitch()<<" pc = "<<pc.get()<<" Key = "<<i<<" pc = "<<k.get()<<endl;
      }
      //cout<<"Key: "<<i<<" Tonic: "<<sum<<endl;
      if(sum>maxVal){
         key = i;
         maxVal = sum;
      }
   }
   //cout<<"Key: "<<key<<" Tonic: "<<maxVal<<endl;
   return key;
}


uint Melody::getTicksOfFirstBar() const
{
   uint ticks = at(m_firstOne).getTicks();
   if(ticks == invalidTick){
      ticks = (uint) floor(at(m_firstOne).getTime() *getTicksPerMs() + 0.5);
   }
   return ticks;
}

uint Melody::getMinPitch() const
{
   uint minPitch = nopos;
   for(uint i = 0;i<size(); ++i){
      if(at(i).getPitch()<minPitch){
         minPitch = at(i).getPitch();
      }
   }
   return minPitch;
}

uint Melody::getMaxPitch() const
{
   uint maxPitch = 0;
   for(uint i = 0;i<size(); ++i){
      if(at(i).getPitch()>maxPitch){
         maxPitch = at(i).getPitch();
      }
   }
   return maxPitch;
}
uint Melody::getAmbitus() const
{
   return getMaxPitch()-getMinPitch();
}

double Melody::getMeanPitch() const
{
   double sum = 0.0;
   for(uint i = 0;i<size(); ++i){
      sum += at(i).getPitch();
   }
   return sum/size();
}

uint Melody::getModusPitch() const
{
   iData pitches, freqs;
   uint maxF = 0, maxP = 0;
   getPitchHistogram(pitches, freqs);
   for(uint i = 0; i<freqs.size(); ++i){
      if(freqs[i]>maxF){
          maxF = freqs[i];
          maxP = pitches[i];
      }
   }
   return maxP;   
}

uint Melody::getMedianPitch()  const
{
   iData pitches, freqs;
   uint sum    = 0;
   uint half   = (uint)size()/2;

   getPitchHistogram(pitches, freqs);

   for(uint i = 0; i<freqs.size(); ++i){
      sum += freqs[i];
      if(sum>=half){
         return pitches[i];
      }
   }
   
   return 0;   
}

void Melody::getPitchList(iData &pitches) const
{
   pitches.clear();
   iData dummy;
   getPitchHistogram(pitches, dummy);
}

void Melody::getPitchHistogram(iData &pitches, iData &frequencies) const
{
   pitches.clear();
   frequencies.clear();

   uint amb       = getAmbitus();
   uint min       = getMinPitch();

   uint *freqs    = new uint[amb+1];
   if(!freqs) return;

   memset(freqs, 0, (amb+1)*sizeof(uint));

   for(uint i = 0; i<size(); ++i){
      uint pitch = at(i).getPitch()-min;
      freqs[pitch]++;
   }

   for(uint i = 0; i<amb+1; ++i){
      if(freqs[i]>0){
         pitches.push_back(i+min);
         frequencies.push_back(freqs[i]);
      }
   }
   delete []freqs;
   return;
}

iData  Melody::getPitches() const
{
   iData ret;
   for(uint i = 0; i<size(); ++i){
      ret.push_back(at(i).getPitch());
   }
   return ret;
}

uint Melody::getMaxIOITicks() const
{
   iData iois = getIOITicks();
   uint max = 0;
   for(uint i = 0; i<iois.size(); ++i){
      if(iois[i]>max){
         max = iois[i];
      }
   }
   return max;
}

uint Melody::getMaxIOIUnits() const
{
   uint max = getMaxIOITicks()/getIOIUnit();
   return max;
}

uint Melody::getMaxDurationUnits() const
{
   uint max = getMaxDurationTicks()/getDurationUnit();
   return max;
}

uint Melody::getMaxDurationTicks() const
{
   iData duration = getDurationTicks();
   uint max = 0;
   for(uint i = 0; i<duration.size(); ++i){
      if(duration[i]>max){
         max = duration[i];
      }
   }
   return max;
}

uint Melody::getMinIOITicks() const
{
   iData iois = getIOITicks();
   uint min = nopos;
   for(uint i = 0; i<iois.size(); ++i){
      if(iois[i]>0 && iois[i]<min){
         min = iois[i];
      }
   }
   return min;
}

uint Melody::getMinIOIUnits() const
{
   uint min = divRound(getMinIOITicks(),getIOIUnit());
   return min;
}

uint Melody::getMinDurationUnits() const
{
   uint min = divRound(getMinDurationTicks(),getDurationUnit());
   return min;
}

uint Melody::getMinDurationTicks() const
{
   iData duration = getDurationTicks();
   uint min = nopos;
   for(uint i = 0; i<duration.size(); ++i){
      if(duration[i]<min){
         min = duration[i];
      }
   }
   return min;
}
double Melody::getTotalLength() const
{
   double start = at(0).getTime();
   double end = at(size()-1).getTime();
   double dur = at(size()-1).getDuration();
   return end+dur-start;
}

uint Melody::getLengthTicks() const
{
   uint start = at(0).getTicks();
   uint end = at(size()-1).getTicks();
   uint dur = (uint)floor(at(size()-1).getDuration() +getTicksPerMs());
   return end+dur-start;

}

iData Melody::getOnsetTicks() const
{
   iData ret;
   for(uint i = 0; i<size(); ++i){
      uint onsetticks = at(i).getTicks();
      if(onsetticks == invalidTick){
         onsetticks =(uint) floor(at(i).getTime() * getTicksPerMs() + 0.5);
      }
      ret.push_back(onsetticks);
   }
   return ret;
}

dData Melody::getOnsets() const
{
   dData ret;
   if(size()==0) return ret;
   for(uint i = 0; i<size(); ++i){
      double onset =  at(i).getTime();
      ret.push_back(onset);
   }
   return ret;
}

dData Melody::getDurations() const
{
   dData ret;
   if(size()==0) return ret;
   for(uint i = 0; i<size(); ++i){
      double dur =  at(i).getDuration();
      ret.push_back(dur);
   }
   return ret;
}

uint  Melody::getNextValidPitchIdx(const uint start)const
{
   for(uint j = start+1; j<size(); ++j){
      if(validPitch(at(j).getPitch())) return j;
   }
   return nopos;
}

dData Melody::getIOIs() const
{
   dData ret;
   double ioi = 0.0;

   if(size()==0) return ret;

   for(uint i = 0; i<size()-1; ++i){
      uint idx = getNextValidPitchIdx(i);
      if(idx != nopos){
         ioi =  at(idx).getTime()-at(i).getTime();
         ret.push_back(ioi);
      }
   }
   return ret;
}

dData Melody::getOOIs() const
{
   dData ret;
   double ioi = 0.0;
   if(size()==0) return ret;
   
   for(uint i = 0; i<size()-1; ++i){
      uint idx = getNextValidPitchIdx(i);
      if(idx != nopos){
         ioi =  at(idx).getTime()-at(i).getTime();
      }
      else continue;
      double ooi =  ioi - at(i).getDuration();
      if(fabs(ooi)<1) ooi = 0.0;
      ret.push_back(ooi);
   }
   return ret;
}

BarTimeline Melody::getBarPositions() const
{
   BarTimeline ret;
   if(size()==0) return ret;
   for(uint i = 0; i<size(); ++i){
      //BarPosition pos =  at(i).getBarPosition();
      ret.push_back(at(i).getBarPosition());
   }
   return ret;
}

uint Melody::getTicksFiller()const
{
   BarPosition pos1 = at(size()-1).getBarPosition();
   BarPosition pos2 = at(0).getBarPosition();
   Signature sig = pos1.getSignature();

   MIDITime mt1, mt2;
   mt1.set(pos1.getBar(), pos1.getBeat(), pos1.getTicks(), sig.count(), sig.ticks(), (uint)floor(getTempo()*1e3), 0, 0);

   if(pos2.getBeat()-1>=(uint)floor(sig.count()/2.0)){
      mt2.set(pos1.getBar(), pos2.getBeat(), pos2.getTicks(), sig.count(), sig.ticks(), (uint)floor(getTempo()*1e3), 0, 0);
   }
   else{
      mt2.set(pos1.getBar()+1, 1, 0, sig.count(), sig.ticks(), (uint)floor(getTempo()*1e3), 0, 0);
   }
   mt1.calculate();
   mt2.calculate();
   uint durticks = (uint)floor(at(size()-1).getDuration()*getTicksPerMs()+0.5);

   uint diffticks = mt2.getDiffTicks(mt1);
   if(durticks>diffticks){
      diffticks = durticks;
   }
   return diffticks;
}

iData Melody::getIOITicks() const
{
   iData ret;
   double tickperms = getTicksPerMs();
   if(size()==0) return ret;
   for(uint i = 0; i<size()-1; ++i){
      uint IOIticks = at(i+1).getTicks()-at(i).getTicks();
      if(IOIticks == invalidTick){
         IOIticks = (uint)floor((at(i+1).getTime()-at(i).getTime())*tickperms+0.5);
      }
      ret.push_back(IOIticks);
   }
   uint diffticks= getTicksFiller();
   ret.push_back(diffticks);
   return ret;
}

iData Melody::getDurationTicks() const
{
   iData ret;
   double tickperms = getTicksPerMs();
   for(uint i = 0; i<size(); ++i){
      uint durticks = (uint)floor(at(i).getDuration()*tickperms+0.5);
      ret.push_back(durticks);
   }
   return ret;
}

iData Melody::getIOIsInUnits() const
{
   uint dummy;
   return getIOIsInUnits(dummy);
}

iData Melody::getIOIsInUnits(uint &minIOI) const
{
   iData ret;
   if(size()==0) return ret;
   minIOI = nopos;
   for(uint i = 0; i<size()-1; ++i){
      uint IOIticks = at(i+1).getTicks() - at(i).getTicks();
      if(IOIticks== invalidTick){
         IOIticks = (uint)floor((at(i+1).getTime()- at(i).getTime())*getTicksPerMs()+0.5);
      }
      uint IOIUnit  = divRound(IOIticks, m_nUnitIOI);
      ret.push_back(IOIUnit);
      if(IOIUnit<minIOI){
         minIOI = IOIUnit;
      }
   }
   return ret;
}

iData Melody::getDurationsInUnits() const
{
   uint dummy;
   return getDurationsInUnits(dummy);
}

iData Melody::getDurationsInUnits(uint &minDur) const
{
   iData ret;
   if(size()==0) return ret;

   minDur = nopos;
   double tickperms = getTicksPerMs();
   for(uint i = 0; i<size(); ++i){
      uint durTicks = (uint)floor(at(i).getDuration()*tickperms+0.5);
      uint durUnit = divRound(durTicks, m_nDurationUnit);
      if(durUnit<1) durUnit = 1;
      ret.push_back(durUnit);
      if(durUnit<minDur){
         minDur = durUnit ;
      }
   }
   return ret;
}
void  Melody::check(uint quantLevel)
{
   if(quantLevel == 0){
      checkTicks();
      checkDurationUnit();
   }
   calcBarPositions(quantLevel);
}

void  Melody::checkTicks()
{
   bool bNeedTickCalc = false;
   uint lastTick = at(0).getTicks();
   for(uint i = 1; i<size(); ++i){
      if(lastTick >= at(i).getTicks()){
         bNeedTickCalc = true;
         break;
      }
   }
   if(bNeedTickCalc){
      calcTicks();
   }
}
void   Melody::calcTicks()
{
   double ticksperms = getTicksPerMs();
   for(uint i = 0; i<size(); ++i){
      uint ticks = (uint)floor(at(i).getTime() * ticksperms+ 0.5);
      //cout<<"Pre :"<<at(i).getTicks();
      at(i).setTicks(ticks);
      //cout<<" Post: "<<at(i).getTicks()<<endl;
   }
}

void  Melody::checkDurationUnit()
{
   checkIOIUnit();
   m_nDurationUnit = m_nUnitIOI;
   iData durs = getDurationTicks();
   for(uint i = 0; i<durs.size(); ++i){
      uint r = durs[i]%m_nDurationUnit;
      if(r == 0) continue;
      uint factor = getMinDivErrFactor(durs[i], m_nDurationUnit, 8);
      uint unit = m_nDurationUnit/factor;
      if(unit<m_nDurationUnit && getTicks()/unit<=6) m_nDurationUnit = unit;
      //cout<<"dur = "<<durs[i]<<" r = "<<r<<" factor ="<<factor<<" unit = "<<unit<<" m_nUnit32 = "<<m_nDurationUnit<<endl;
   }
   //tmp
   if(m_nDurationUnit<m_nUnitIOI) m_nUnitIOI = m_nDurationUnit;
}


void  Melody::checkIOIUnit()
{
   if(m_bChecked) return;
   if(m_nUnitIOI == 0){
      return;
   }
   iData iois = getIOITicks();
   m_nUnitIOI = getTicks()/2;
   for(uint i = 0; i<iois.size(); ++i){
      uint div = iois[i]%getTicks();
      if(div == 0) continue;
      uint rDur = divRound(getTicks(), div);
      uint unit = getTicks()/m_nUnitIOI;
      uint factor = getMinDivErrFactor(iois[i], m_nUnitIOI, 8);
      //cout<<" m_nUnit = "<<m_nUnitIOI<<endl;
      m_nUnitIOI = m_nUnitIOI/factor;
      //cout<<"factor = "<<factor<<endl;
      //cout<<"iois = "<<iois[i]<<" div = "<<div<<" rdur ="<<rDur<<" unit ="<<unit<<" m_nUnit = "<<m_nUnitIOI<<endl;
      continue;
      if(rDur%unit != 0){
         m_nUnitIOI = ggT(getTicks()/rDur, getTicks()/unit);
      }
   }
   m_bChecked = true;
}

void Melody::calcBarPositions(uint quantLevel)
{
   if(empty()) return;
   
   iData iois     = getIOITicks();
   uint barTicks  = getTicksPerBar();
   
   uint firstOnset = at(0).getTicks();
   if(firstOnset == nopos){
      firstOnset = (uint)floor(at(0).getTime()*getTicksPerMs()+0.5);
   }
   uint firstBar     = firstOnset/ barTicks + 1;
   uint firstTicks   = firstOnset % barTicks;
   bool bFirstOnIdxSet = false;
   BarPosition pos;
   pos.setSignature(getSignature());

   if(firstTicks == 0){
      pos.set(firstBar,1,0);
      setFirstOneIdx(0);
      bFirstOnIdxSet = true;
   }
   else{
      if(firstTicks<barTicks/2){
         pos.set(firstBar,1,0);
         pos.addTicks(firstTicks);
      }
      else{
         pos.set(firstBar-1,1,0);
         pos.addTicks(firstTicks);
      }
   }
   uint startBar = pos.getBar();
   for(uint i = 0; i<iois.size()-1; ++i){
      //pos.dump();
      if(!bFirstOnIdxSet && pos.getBar() != startBar){
         setFirstOneIdx(i-1);
         bFirstOnIdxSet = true;
      }
      if(quantLevel) 
         pos.quantize(quantLevel);
      at(i).setBarPosition(pos);
      pos.addTicks(iois[i]);
   }
   at(size()-1).setBarPosition(pos);
   return;
}
void   Melody::removeNoteOverlaps()
{
   for(uint i = 0;i<size()-1; ++i){
      double ioi        = at(i+1).getTime()-at(i).getTime();
      double duration   = at(i).getDuration();
      if(duration>ioi){
         at(i).setDuration(ioi);
      }
   }
   return;
}

uint Melody::getStartUnits() const
{
   return getStartTicks()/m_nUnitIOI;
}

uint Melody::getStartTicks() const
{
   if(empty()|| m_nUnitIOI == 0) return 0;

   BarPosition pos   = at(0).getBarPosition();
   Signature sig     = pos.getSignature();
   uint ticks = (pos.getBeat()-1)*sig.ticks()+ pos.getTicks();
   return ticks;
}

uint Melody::getFirstOneUnits() const
{
   iData iois = getIOITicks();
   uint units = 0;
   if(size()<=m_firstOne) return 0;

   for(uint i = 0; i<m_firstOne; ++i){
      units += iois[i]/m_nUnitIOI;
   }
   return units;
}

uint Melody::ggT(uint t1, uint t2) const
{
   uint r = t1 % t2;
   while (r !=0){
      t1 = t2; t2 = r;
      r = t1 % t2;
   };
   return t2;
}

uint Melody::divRound(const uint x, const uint y) const
{
   return (uint)floor((0.0+x)/y +0.5);
}

uint Melody::divRoundError(const uint x, const uint y, double& err) const
{
   double div = (0.0+x)/y;
   double div2 =floor((0.0+x)/y +0.5);
   err = fabs(div -div2);
   return (uint)div2;
}

/*
uint  Melody::getMinDivErrFactor(uint d, uint unit) const
{
   double diff = diffToNearestMultiple(d,unit);
   //cout<<"d = "<<d<<" unit = "<<unit<<" diff = "<<diff<<endl;
   uint fact = 1, fact2 = 1, fact3 = 1;
   uint retFact = 1;
   for(uint i = 1; ;++i){
      fact2 *= 2;
      fact3 = 1;
      fact = fact2 * fact3;
      if(unit % fact != 0 || unit == fact) break;
      double tmp = diffToNearestMultiple(d,unit/fact);
      //cout<<"fact = "<<fact<<" diff = "<<tmp<<endl;
      if(tmp<diff){
         diff = tmp;
         retFact =fact;
      }
      for(uint j = 1; ;++j){
         fact3 *= 3;
         fact = fact2*fact3;
         if(unit%fact != 0 || unit == fact) break;
         double tmp = diffToNearestMultiple(d,unit/fact);
         //cout<<"fact = "<<fact<<" diff = "<<tmp<<endl;
         if(tmp<diff){
            diff = tmp;
            retFact =fact;
         }
      }
   }
   return retFact;
}
uint  Melody::getMinDivErrFactor2or3(const uint d, const uint unit) const
{
   double diff = diffToNearestMultiple(d,unit);
   //cout<<"d = "<<d<<" unit = "<<unit<<" diff = "<<diff<<endl;

   uint retFact = 1;
   if(unit % 2 == 0 && unit != 2){
      double tmp = diffToNearestMultiple(d,unit/2);
      //cout<<"fact = "<<2<<" diff = "<<tmp<<endl;
      if(tmp<=diff){
         diff = tmp;
         retFact =2;
      }
   }
   if(unit % 3 == 0 && unit !=3){
      double tmp = diffToNearestMultiple(d,unit/3);
      //cout<<"fact = "<<3<<" diff = "<<tmp<<endl;
      if(tmp<=diff){
         retFact =3;
      }
   }
   return retFact;
}
*/

uint  Melody::getMinDivErrFactor(const uint d, const uint unit, const uint maxN) const
{
   double diff = diffToNearestMultiple(d,unit);
   //cout<<"d = "<<d<<" unit = "<<unit<<" diff = "<<diff<<endl;

   uint retFact = 1;
   for(uint i = maxN; i>=2;--i){
      if(unit % i == 0 && unit != i){
         double tmp = diffToNearestMultiple(d,unit/i);
         //cout<<"fact = "<<2<<" diff = "<<tmp<<endl;
         if(tmp<=diff){
            diff = tmp;
            retFact =i;
            break;
         }
      }
   }
   return retFact;
}

double Melody::diffToNearestMultiple(const uint v, const uint unit) const
{
   return fabs(0.0+v- divRound(v,unit) * unit)/(unit+.0);
}

bool Melody::validPitch(const uint pitch)const
{
   if(pitch >0 && pitch <128 || pitch == 250) return true;
   return false;
}


void Melody::dump()
{
   uint tmp = 0;
   iData onsetTicks  = getOnsetTicks();
   iData IOITicks    = getIOITicks();
   iData durTicks    = getDurationTicks();
   iData IOIUnit     = getIOIsInUnits(tmp);
   cout<<"Min IOIUnit = "<<tmp<<endl;
   iData durUnit     = getDurationsInUnits(tmp);
   cout<<"Min durUnit = "<<tmp<<endl;
   for(uint i = 0; i<size()-1; ++i){
      cout<<"#"<<i<<" Pitch: "<<at(i).getPitch()<<" Onset:"<<at(i).getTime()<<"("<<onsetTicks[i]<<")"<<endl;
      cout<<"Dur: "<<at(i).getDuration()<<"("<<durTicks[i]<<") durUnit:  "<<durUnit[i]<<endl;
      cout<<"IOITicks: "<<IOITicks[i]<<" IOIUnit: "<<IOIUnit[i]<<endl;
      cout<<"BarPos: ";
      at(i).getBarPosition().dump();
      cout<<"--"<<endl;
   }
   uint sz =size()-1;
   cout<<"#"<<sz<<" Pitch: "<<at(sz).getPitch()<<" Onset:"<<at(sz).getTime()<<" OnsetTicks: "<<onsetTicks[sz]<<endl;
   cout<<"Dur: "<<at(sz).getDuration()<<" durTicks: "<<durTicks[sz]<<" durUnit:  "<<durUnit[sz]<<endl;
   cout<<"IOITicks: "<<IOITicks[sz]<<" IOIUnit: "<<IOIUnit[sz]<<endl;
   cout<<"BarPos: ";
   at(sz).getBarPosition().dump();

}
void  Melody::dumpStatistics()
{
   cout<<"Min Pitch: "<<getMinPitch()<<" Max Pitch: "<<getMaxPitch()<<" Ambitus:" <<getAmbitus()<<endl;
   cout<<"Mean = "<<getMeanPitch()<<" Modus ="<<getModusPitch()<<" Median = "<<getMedianPitch()<<endl;
   cout<<"PitchHistogramm: "<<endl;
   cout<<"================="<<endl;
   iData pitches, freqs;
   getPitchHistogram(pitches, freqs);
   
   for(uint i = 0; i<pitches.size(); ++i){
      cout<<"Pitch: "<<pitches[i]<<" Freq: "<<freqs[i]<<endl;
   }

}

