// ----------------------------------------------------------------------------
//
//  Copyright (C) 2015-2021 Fons Adriaensen <fons@linuxaudio.org>
//    
//  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 3 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, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------


#include <assert.h>
#include <string.h>
#include "ambbin8.h"


Ambbin8::Ambbin8 (int fsamp, int degree, int maxlen, int period) :
    _fsamp (fsamp),
    _degree (degree),
    _period (period),
    _ninput (0),
    _nfcomp (false),
    _ambrot8 (0),
    _binconv (0)
{
    if (_degree < 1) _degree = 1;
    if (_degree > MAXDEGR) _degree = MAXDEGR;
    _ambrot8 = new Ambrot8 (_fsamp, _degree);
    _binconv = new Binconv (_degree, maxlen, _period);
    _ninput = (_degree + 1) * (_degree + 1);
    for (int i = 0; i < _ninput; i++) _buff [i] = new float [period];
    for (int i = 0; i < _degree; i++) _nffilt [i] = 0;
    switch (degree)
    {
        // NOTE: no break !!!
        case 8: _nffilt [7] = new NFfilt8 (17);
        case 7: _nffilt [6] = new NFfilt7 (15);
        case 6: _nffilt [5] = new NFfilt6 (13);
        case 5: _nffilt [4] = new NFfilt5 (11);
        case 4: _nffilt [3] = new NFfilt4 (9);
        case 3: _nffilt [2] = new NFfilt3 (7);
        case 2: _nffilt [1] = new NFfilt2 (5);
        case 1: _nffilt [0] = new NFfilt1 (3);
    }
}


Ambbin8::~Ambbin8 (void)
{
    for (int i = 0; i < _ninput; i++) delete _buff [i];
    for (int i = 0; i < _degree; i++) delete _nffilt [i];
    delete _ambrot8;
    delete _binconv;
}


void Ambbin8::set_nfcomp (float dist)
{
    int   i;
    float w;

    if (dist > 20.0f)
    {
        for (i = 0; i < _degree; i++) _nffilt [i]->reset ();
        _nfcomp = false;
    }
    else
    {
        if (dist < 0.5f) dist = 0.5f;
        w = 343.0f / (dist * _fsamp);
        for (i = 0; i < _degree; i++) _nffilt [i]->init (w);
        _nfcomp = true;
    }
}


void Ambbin8::process (int nframes, float *inp[], float *out[])
{
    int i, k;

    assert (nframes == _period);
    _ambrot8->process (nframes, inp, _buff);
    if (_nfcomp)
    {
        k = 0;
        for (i = 0; i < _degree; i++)
        {
            k += 2 * i + 1;
            _nffilt [i]->process (nframes, _buff + k, _buff + k);
        }        
    }
    _binconv->process (_buff, out);
}

