/***************************************************************************
 *   Copyright (C) 2004 by Predrag Viceic                                  *
 *   viceic@net2000.ch                                            *
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "envelopedata.h"

EnvelopeData::EnvelopeData( const QString & text,QWidget * dragSource, const char * name)
    : QTextDrag(text,dragSource, name)
{
    setData(text);
}

EnvelopeData::EnvelopeData(QWidget * dragSource , const char * name)
    : QTextDrag(dragSource,name)
{
    attack=0.1;
    attackC.rx=attack/2.0;
    attackC.ry=0.5;
    hold=0.1;
    decay=0.1;
    decayC.rx=attack+hold+decay/2.0;
    decayC.ry=1;
    release=0.1;
    releaseC.rx=1-release/2.0;
    releaseC.ry=0.5;
    sustain=1.0;
    env_duration=1000.0;
    env_resolution=100.0;
    env_mode=FIT_TO_DURATION_CONTINUE;
    enabled=0;
    cout<<toString()<<"\n";
}


EnvelopeData::~EnvelopeData()
{
}




/*!
    \fn EnvelopeData::toString()
 */
QString EnvelopeData::toString()
{
    return
            "A:"+QString::number(attack)+","+
            QString::number(attackC.x())+","+
            QString::number(attackC.y())+","+
            "H:"+QString::number(hold)+","+
            "D:"+QString::number(decay)+","+
            QString::number(decayC.x())+","+
            QString::number(decayC.y())+","+
            "S:"+QString::number(sustain)+","+
            "R:"+QString::number(release)+","+
            QString::number(releaseC.x())+","+
            QString::number(releaseC.y())+","+
            "Dur:"+QString::number(env_duration)+","+
            "Res:"+QString::number(env_resolution)+","+
            "M:"+QString::number(env_mode);
}

/*!
    \fn EnvelopeData::setData(QString envData)
 */
void EnvelopeData::setData(QString envDataS)
{
        QStringList list=QStringList::split(",",envDataS);
        attack=list[1].toFloat();
        attackC.rx==list[2].toFloat();
        attackC.ry==list[3].toFloat();
        hold=list[4].toFloat();
        decay=list[5].toFloat();
        decayC.rx=list[6].toFloat();
        decayC.ry=list[7].toFloat();
        sustain=list[8].toFloat();
        release=list[9].toFloat();
        releaseC.rx=list[9].toFloat();
        releaseC.ry=list[10].toFloat();
        env_duration=list[11].toFloat();
        env_resolution=list[12].toFloat();
        env_mode=(mode)(list[13].toInt());
}


/*!
    \fn EnvelopeData::getEnvAt(float x,float dt)
 */
float EnvelopeData::getEnvAt(float x,float dt)
{
    MyMath::FPoint2D a,d,returnP;
    returnP.rx=1;
    float returnVal=1;
    if(x<attack){
        a.rx=0;a.ry=0;d.rx=attack;d.ry=1;
        returnVal=MyMath::PointOnCubicBezierAt(a,attackC,attackC,d,dt,x);
    }
    else if (x>attack && x<attack+hold) returnVal=1.0;
    else if (x>attack+hold && x<attack+hold+decay){
        a.rx=attack+hold;a.ry=1;d.rx=attack+hold+decay;d.ry=sustain;
        returnVal=MyMath::PointOnCubicBezierAt(a,decayC,decayC,d,dt,x);
    }
    else if(x>attack+hold+decay && x<1-release) returnVal=sustain;
    else{
        a.rx=1-release;a.ry=sustain;d.rx=1;d.ry=0;
        returnVal=MyMath::PointOnCubicBezierAt(a,releaseC,releaseC,d,dt,x);
    }
    return returnVal>1?1:returnVal<0?0:returnVal;
}


/*!
    \fn EnvelopeData::getMode()
 */
EnvelopeData::mode EnvelopeData::getMode()
{
    return env_mode;
}



/*!
    \fn EnvelopeData::getDuration()
 */
float EnvelopeData::getDuration()
{
    return env_duration;
}


/*!
    \fn EnvelopeData::setAttack(float a)
 */
void EnvelopeData::setAttack(float a)
{
    if(a+hold+decay+release>1) a=1-hold-decay-release;
        float diffxratio=attackC.x()/attack;
        attack=a;
        attackC.setX(diffxratio>0?attack*diffxratio:attack/2);
        decayC.setX(diffxratio>0?attack+hold+decay*diffxratio:
                attack+hold+decay/2);
}


/*!
    \fn EnvelopeData::setAttackCx(float ax)
 */
void EnvelopeData::setAttackCx(float ax)
{
    attackC.setX(ax<=attack?ax:attack);
}


/*!
    \fn EnvelopeData::setAttackCy(float ay)
 */
void EnvelopeData::setAttackCy(float ay)
{
    attackC.setY(ay);
}

/*!
    \fn EnvelopeData::setHold(float a)
 */
void EnvelopeData::setHold(float h)
{
    if (h<attack) h=attack;
    if (h+decay+release>1) h=1-decay-release;
    float diffxratio=(decayC.x()-(attack+hold))/decay;
    hold=h-attack;
    decayC.setX(diffxratio>0?attack+hold+decay*diffxratio:
            attack+hold+decay/2);
}


/*!
    \fn EnvelopeData::setDecay(float d)
 */
void EnvelopeData::setDecay(float d)
{
    if(d<attack+hold) d=attack+hold;
    if(d+release>1) d=1-release;
        float diffxratio=(decayC.x()-(attack+hold))/decay;
        decay=d-attack-hold;
        decayC.setX(diffxratio>0?attack+hold+decay*diffxratio:
                attack+hold+decay/2);
}


/*!
    \fn EnvelopeData::setDecayCx(float dx)
 */
void EnvelopeData::setDecayCx(float dx)
{
    float x=dx>attack+hold+decay?
                        attack+hold+decay:
                        dx<attack+hold?
            attack+hold:dx;
    decayC.setX(x);
}


/*!
    \fn EnvelopeData::setDecayCy(float dy)
 */
void EnvelopeData::setDecayCy(float dy)
{
    decayC.setY(dy);
}


/*!
    \fn EnvelopeData::setSustain(float a)
 */
void EnvelopeData::setSustain(float s)
{
    sustain=s;
}


/*!
    \fn EnvelopeData::setRelease(float a)
 */
void EnvelopeData::setRelease(float r)
{
    if(r<attack+hold+decay) r=attack+hold+decay;
    float diffxratio=(1-releaseC.x())/release;
    release=(1-r)<0?0:(1-r)>1?1:1-r;
    setReleaseCx(diffxratio>0?1-release*diffxratio:1-release/2);
}


/*!
    \fn EnvelopeData::setReleaseCx(float rx)
 */
void EnvelopeData::setReleaseCx(float rx)
{
    releaseC.setX(rx<1-release?1-release:rx);
}

/*!
    \fn EnvelopeData::setReleaseCy(float ry)
 */
void EnvelopeData::setReleaseCy(float ry)
{
    releaseC.setY(ry);
}








/*!
    \fn EnvelopeData::isEnabled()
 */
int EnvelopeData::isEnabled()
{
  return enabled;
}


/*!
    \fn EnvelopeData::setEnabled(int e)
 */
void EnvelopeData::setEnabled(int e)
{
    enabled=e;
}


/*!
    \fn EnvelopeData::getData()
 */
QString EnvelopeData::getData()
{
    return
            QString::number(attack)+","+
            QString::number(attackC.x())+","+
            QString::number(attackC.y())+","+
            QString::number(hold)+","+
            QString::number(decay)+","+
            QString::number(decayC.x())+","+
            QString::number(decayC.y())+","+
            QString::number(sustain)+","+
            QString::number(release)+","+
            QString::number(releaseC.x())+","+
            QString::number(releaseC.y())+","+
            QString::number(env_duration)+","+
            QString::number(env_resolution)+","+
            QString::number(env_mode);
}


/*!
    \fn EnvelopeData::getResolution()
 */
int EnvelopeData::getResolution()
{
    return int(env_resolution);
}

