2024-06-16 05:31:13 -04:00
|
|
|
/* osctrl.c
|
|
|
|
|
|
|
|
This file is part of a program that implements a Software-Defined Radio.
|
|
|
|
|
|
|
|
Copyright (C) 2014, 2017 Warren Pratt, NR0V
|
|
|
|
Copyright (C) 2024 Edouard Griffiths, F4EXB Adapted to SDRangel
|
|
|
|
|
|
|
|
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
|
|
|
The author can be reached by email at
|
|
|
|
|
|
|
|
warren@wpratt.com
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
// This file is part of the implementation of the Overshoot Controller from
|
|
|
|
// "Controlled Envelope Single Sideband" by David L. Hershberger, W9GR, in
|
|
|
|
// the November/December 2014 issue of QEX.
|
|
|
|
|
|
|
|
#include "comm.hpp"
|
|
|
|
#include "osctrl.hpp"
|
|
|
|
#include "TXA.hpp"
|
|
|
|
|
|
|
|
namespace WDSP {
|
|
|
|
|
2024-08-07 15:14:09 -04:00
|
|
|
void OSCTRL::calc()
|
2024-06-16 05:31:13 -04:00
|
|
|
{
|
2024-08-07 15:14:09 -04:00
|
|
|
pn = (int)((0.3 / bw) * rate + 0.5);
|
|
|
|
if ((pn & 1) == 0) pn += 1;
|
|
|
|
if (pn < 3) pn = 3;
|
|
|
|
dl_len = pn >> 1;
|
|
|
|
dl.resize(pn * 2);
|
|
|
|
dlenv.resize(pn);
|
|
|
|
in_idx = 0;
|
|
|
|
out_idx = in_idx + dl_len;
|
|
|
|
max_env = 0.0;
|
2024-06-16 05:31:13 -04:00
|
|
|
}
|
|
|
|
|
2024-08-07 15:14:09 -04:00
|
|
|
OSCTRL::OSCTRL(
|
|
|
|
int _run,
|
|
|
|
int _size,
|
|
|
|
float* _inbuff,
|
|
|
|
float* _outbuff,
|
|
|
|
int _rate,
|
|
|
|
double _osgain
|
|
|
|
) :
|
|
|
|
run(_run),
|
|
|
|
size(_size),
|
|
|
|
inbuff(_inbuff),
|
|
|
|
outbuff(_outbuff),
|
|
|
|
rate(_rate),
|
|
|
|
osgain(_osgain)
|
2024-06-16 05:31:13 -04:00
|
|
|
{
|
2024-08-07 15:14:09 -04:00
|
|
|
bw = 3000.0;
|
|
|
|
calc();
|
2024-06-16 05:31:13 -04:00
|
|
|
}
|
|
|
|
|
2024-08-07 15:14:09 -04:00
|
|
|
void OSCTRL::flush()
|
2024-06-16 05:31:13 -04:00
|
|
|
{
|
2024-08-07 15:14:09 -04:00
|
|
|
std::fill(dl.begin(), dl.end(), 0);
|
|
|
|
std::fill(dlenv.begin(), dlenv.end(), 0);
|
2024-06-16 05:31:13 -04:00
|
|
|
}
|
|
|
|
|
2024-08-07 15:14:09 -04:00
|
|
|
void OSCTRL::execute()
|
2024-06-16 05:31:13 -04:00
|
|
|
{
|
2024-08-07 15:14:09 -04:00
|
|
|
if (run)
|
2024-06-16 05:31:13 -04:00
|
|
|
{
|
2024-08-07 15:14:09 -04:00
|
|
|
double divisor;
|
|
|
|
for (int i = 0; i < size; i++)
|
2024-06-16 05:31:13 -04:00
|
|
|
{
|
2024-08-07 15:14:09 -04:00
|
|
|
dl[2 * in_idx + 0] = inbuff[2 * i + 0]; // put sample in delay line
|
|
|
|
dl[2 * in_idx + 1] = inbuff[2 * i + 1];
|
|
|
|
env_out = dlenv[in_idx]; // take env out of delay line
|
|
|
|
dlenv[in_idx] = sqrt (inbuff[2 * i + 0] * inbuff[2 * i + 0] // put env in delay line
|
|
|
|
+ inbuff[2 * i + 1] * inbuff[2 * i + 1]);
|
|
|
|
if (dlenv[in_idx] > max_env) max_env = dlenv[in_idx];
|
|
|
|
if (env_out >= max_env && env_out > 0.0) // run the buffer
|
2024-06-16 05:31:13 -04:00
|
|
|
{
|
2024-08-07 15:14:09 -04:00
|
|
|
max_env = 0.0;
|
|
|
|
for (int j = 0; j < pn; j++)
|
|
|
|
if (dlenv[j] > max_env) max_env = dlenv[j];
|
2024-06-16 05:31:13 -04:00
|
|
|
}
|
2024-08-07 15:14:09 -04:00
|
|
|
if (max_env > 1.0) divisor = 1.0 + osgain * (max_env - 1.0);
|
2024-06-16 05:31:13 -04:00
|
|
|
else divisor = 1.0;
|
2024-08-07 15:14:09 -04:00
|
|
|
outbuff[2 * i + 0] = (float) (dl[2 * out_idx + 0] / divisor); // output sample
|
|
|
|
outbuff[2 * i + 1] = (float) (dl[2 * out_idx + 1] / divisor);
|
|
|
|
if (--in_idx < 0) in_idx += pn;
|
|
|
|
if (--out_idx < 0) out_idx += pn;
|
2024-06-16 05:31:13 -04:00
|
|
|
}
|
|
|
|
}
|
2024-08-07 15:14:09 -04:00
|
|
|
else if (inbuff != outbuff)
|
|
|
|
std::copy(inbuff, inbuff + size * 2, outbuff);
|
2024-06-16 05:31:13 -04:00
|
|
|
}
|
|
|
|
|
2024-08-07 15:14:09 -04:00
|
|
|
void OSCTRL::setBuffers(float* _in, float* _out)
|
2024-06-16 05:31:13 -04:00
|
|
|
{
|
2024-08-07 15:14:09 -04:00
|
|
|
inbuff = _in;
|
|
|
|
outbuff = _out;
|
2024-06-16 05:31:13 -04:00
|
|
|
}
|
|
|
|
|
2024-08-07 15:14:09 -04:00
|
|
|
void OSCTRL::setSamplerate(int _rate)
|
2024-06-16 05:31:13 -04:00
|
|
|
{
|
2024-08-07 15:14:09 -04:00
|
|
|
rate = _rate;
|
|
|
|
calc();
|
2024-06-16 05:31:13 -04:00
|
|
|
}
|
|
|
|
|
2024-08-07 15:14:09 -04:00
|
|
|
void OSCTRL::setSize(int _size)
|
2024-06-16 05:31:13 -04:00
|
|
|
{
|
2024-08-07 15:14:09 -04:00
|
|
|
size = _size;
|
|
|
|
flush();
|
2024-06-16 05:31:13 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace WDSP
|