// ----------------------------------------------------------------------------
//
//  Copyright (C) 2023 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 <math.h>
#include <stdio.h>
#include <string.h>
#include "jbw8filt.h"
#include "delay.h"


Jbw8chan::Jbw8chan (void) :
    _nreq (0),
    _nack (0),
    _mode (0),
    _inp (0),
    _hpf (0),
    _lpf (0)
{
}


Jbw8chan::~Jbw8chan (void)
{
}


Jbw8filt::Jbw8filt (const char *client_name, const char *server_name,
                    int ninp, int nout) :
    _chanpar (0)
{
    if (ninp < 1) ninp = 1;
    if (ninp > MAXINP) ninp = MAXINP;
    if (nout < 1) nout = 1;
    if (nout > MAXOUT) nout = MAXOUT;
    if (   open_jack (client_name, server_name, ninp, nout)
        || create_inp_ports ("in_%d")
        || create_out_ports ("out_%d"))
    {
        _state = FAILED;
        return;
    }
    _chanpar = new Jbw8chan [(unsigned int) _nout];
    _state = PROCESS;
}


Jbw8filt::~Jbw8filt (void)
{
    _state = INITIAL;
    close_jack ();
    delete[] _chanpar;
}


void Jbw8filt::set_filter (int inp, int out, float hpfreq, float lpfreq)
{
    Jbw8chan *C;

    if ((inp < 0) || (inp >= _ninp)) return;
    if ((out < 0) || (out >= _nout)) return;
    C = _chanpar + out;
    C->_inp = inp;
    C->_hpf = hpfreq / jack_rate ();
    C->_lpf = lpfreq / jack_rate ();
    C->_nreq++;
}


int Jbw8filt::jack_process (int nframes)
{
    Jbw8chan     *C;
    float        *inp [MAXINP];
    float        *out;
    const float  *p;
    int          i, m;
    
    if (_state < PROCESS) return 0;

    for (i = 0; i < _ninp; i++)
    {
        inp [i] = (float *) jack_port_get_buffer (_inp_ports [i], nframes);
    }

    for (i = 0, C = _chanpar; i < _nout; i++, C++)
    {
        out = (float *) jack_port_get_buffer (_out_ports [i], nframes);
        if (C->_nreq != C->_nack)
        {
            C->_mode = 0;
            if (C->_hpf > 0)
            {
                C->_hpfilt.init (C->_hpf);
                C->_mode |= HPF;
            }
            if (C->_lpf > 0)
            {
                C->_lpfilt.init (C->_lpf);
                C->_mode |= LPF;
            }
            C->_nack++;
        }
        m = C->_mode;
        p = inp [C->_inp];
        if (m)
        {
            if (m & HPF)
            {
                C->_hpfilt.prochighpass (nframes, p, out);
                p = out;
            }
            if (m & LPF)
            {
                C->_lpfilt.proclowpass (nframes, p, out);
            }
        }
        else memcpy (out, p, nframes * sizeof (float));
    }

    return 0;
}

