//vocoder.cc
/*
    Vocoder class for the Sound Processing Kit
    Copyright (C) 2002 Jarno Wuolijoki and Pilvari Pirtola

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library 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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/



#include <spkit/spkit.h>
#include "vocoder.h"
#include "ampanlzr.h"
#include "fbank.h"
#include <math.h>



SPKitError SPKitVocoder::setInput(SPKitProcessor *input) {
    SPKitProcessor::setInput(input);
    if (!carfb || !modfb || !modinput || !joiner) fprintf(stderr, "error"), exit(1);
    carfb->setInput(input);
    modfb->setInput(modinput); 
    int a=modfb->getFilterCount(), b=carfb->getFilterCount();
    filterCount=a<b?a:b;

    carout=carfb->getOutputs();
    modout=modfb->getOutputs();

    if (caraz) {
        for (int i=0; i<filterCount; i++) caraz[i]->setInput(carout[i]);
        carout2=caraz;
    } else carout2=carout;

    if (modaz) {
        for (int i=0; i<filterCount; i++) modaz[i]->setInput(modout[i]);
        modout2=modaz;
    } else modout2=modout;
    
    multipliers=new SPKitMult*[filterCount];
    for (int i=0; i<filterCount; i++) {
        multipliers[i]=new SPKitMult();
        multipliers[i]->setInput(carout2[i]);
        multipliers[i]->setMultInput(modout2[i]);
    }
    joiner->setInputs(filterCount, (SPKitProcessor**)multipliers);
    return 0;
}

SPKitError SPKitVocoder::setModulatorInput(SPKitProcessor *modinput) {
    this->modinput=modinput;
    return 0;
}

SPKitError SPKitVocoder::setFilters(SPKitFilterbank *modf, SPKitFilterbank *carf, SPKitJoiner *joinr) {
    modfb=modf; carfb=carf; joiner=joinr;
    return 0;
}

SPKitError SPKitVocoder::setAnalyzers(SPKitProcessor **mod, SPKitProcessor **car) {
    modaz=mod; caraz=car;
    return 0;
}

SPKitError SPKitVocoder::setDefaultFilters(SPKitFloat lowfrq, SPKitFloat highfrq, int cnt) {
    SPKitFloat multiplier=pow(highfrq/lowfrq, 1./(cnt-1.));
    SPKitFloat *frqs=new SPKitFloat[cnt], *bws=new SPKitFloat[cnt];
    for (int i=0; i<cnt; i++) frqs[i]=lowfrq*pow(multiplier, i);
    for (int i=0; i<cnt; i++) bws[i]=frqs[i]*(multiplier-1)*.33;
    SPKitFilterbankBW *fb1=new SPKitFilterbankBW(), *fb2=new SPKitFilterbankBW();
    SPKitJoiner *jnr=new SPKitJoiner();
    SPKitAmplitudeAnalyzer **aa=new SPKitAmplitudeAnalyzer*[cnt];
    for (int i=0; i<cnt; i++) {
        aa[i]=new SPKitAmplitudeAnalyzer();
        SPKitFloat f=frqs[i]*.25;
        aa[i]->setCutOffFreq(f>200?200:f); 
    }
    SPKitAmplitudeNormalizer **an=new SPKitAmplitudeNormalizer*[cnt];
    for (int i=0; i<cnt; i++) {
        an[i]=new SPKitAmplitudeNormalizer();
        SPKitFloat f=frqs[i]*.25;
        an[i]->setCutOffFreq(f>200?200:f); 
    }
    fb1->setFilterCount(cnt);
    fb2->setFilterCount(cnt);
    fb1->setFrqs(frqs, bws);
    fb2->setFrqs(frqs, bws);
    setFilters(fb1, fb2, jnr);
    setAnalyzers((SPKitProcessor**)aa, (SPKitProcessor**)an);
    return 0;
}

SPKitError SPKitVocoder::setMatrix() {
  //undone
  return 0;
}

int SPKitVocoder::getSample(SPKitSample &outputSample, SPKitProcessor *caller) {
    return joiner->getSample(outputSample, this);
}

SPKitVocoder::SPKitVocoder() {
    joiner=0; multipliers=0;
    modfb=carfb=0; modaz=caraz=0;
    modinput=0; modout=carout=modout2=carout2=0;   
}



