| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  | /*  speak.cpp
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This file is part of a program that implements a Software-Defined Radio. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Copyright (C) 2014, 2022, 2023 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 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "comm.hpp"
 | 
					
						
							|  |  |  | #include "speak.hpp"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace WDSP { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /********************************************************************************************************
 | 
					
						
							|  |  |  | *                                                                                                       * | 
					
						
							|  |  |  | *                                           Complex Bi-Quad Peaking                                     * | 
					
						
							|  |  |  | *                                                                                                       * | 
					
						
							|  |  |  | ********************************************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  | void SPEAK::calc() | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     double ratio; | 
					
						
							| 
									
										
										
										
											2024-08-03 11:05:12 +02:00
										 |  |  |     double f_corr; | 
					
						
							|  |  |  |     double g_corr; | 
					
						
							|  |  |  |     double bw_corr; | 
					
						
							|  |  |  |     double bw_parm; | 
					
						
							|  |  |  |     double A; | 
					
						
							|  |  |  |     double f_min; | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  |     switch (design) | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |     case 0: | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  |         ratio = bw / f; | 
					
						
							| 
									
										
										
										
											2024-08-03 11:05:12 +02:00
										 |  |  |         if (nstages == 4) | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  |         { | 
					
						
							|  |  |  |             bw_parm = 2.4; | 
					
						
							|  |  |  |             f_corr  = 1.0 - 0.160 * ratio + 1.440 * ratio * ratio; | 
					
						
							|  |  |  |             g_corr = 1.0 - 1.003 * ratio + 3.990 * ratio * ratio; | 
					
						
							| 
									
										
										
										
											2024-08-03 11:05:12 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  |             bw_parm = 1.0; | 
					
						
							|  |  |  |             f_corr  = 1.0; | 
					
						
							|  |  |  |             g_corr = 1.0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2024-08-03 11:05:12 +02:00
										 |  |  |             double fn; | 
					
						
							|  |  |  |             double qk; | 
					
						
							|  |  |  |             double qr; | 
					
						
							|  |  |  |             double csn; | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  |             fgain = gain / g_corr; | 
					
						
							| 
									
										
										
										
											2024-08-03 11:05:12 +02:00
										 |  |  |             fn = f / rate / f_corr; | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  |             csn = cos (TWOPI * fn); | 
					
						
							| 
									
										
										
										
											2024-08-03 11:05:12 +02:00
										 |  |  |             qr = 1.0 - 3.0 * bw / rate * bw_parm; | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  |             qk = (1.0 - 2.0 * qr * csn + qr * qr) / (2.0 * (1.0 - csn)); | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  |             a0 = 1.0 - qk; | 
					
						
							|  |  |  |             a1 = 2.0 * (qk - qr) * csn; | 
					
						
							|  |  |  |             a2 = qr * qr - qk; | 
					
						
							|  |  |  |             b1 = 2.0 * qr * csn; | 
					
						
							|  |  |  |             b2 = - qr * qr; | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case 1: | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  |         if (f < 200.0) f = 200.0; | 
					
						
							|  |  |  |         ratio = bw / f; | 
					
						
							| 
									
										
										
										
											2024-08-03 11:05:12 +02:00
										 |  |  |         if (nstages == 4) | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  |         { | 
					
						
							|  |  |  |             bw_parm = 5.0; | 
					
						
							|  |  |  |             bw_corr = 1.13 * ratio - 0.956 * ratio * ratio; | 
					
						
							|  |  |  |             A = 2.5; | 
					
						
							|  |  |  |             f_min = 50.0; | 
					
						
							| 
									
										
										
										
											2024-08-03 11:05:12 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  |             bw_parm = 1.0; | 
					
						
							|  |  |  |             bw_corr  = 1.0; | 
					
						
							|  |  |  |             A = 2.5; | 
					
						
							|  |  |  |             f_min = 50.0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2024-08-03 11:05:12 +02:00
										 |  |  |             double w0; | 
					
						
							|  |  |  |             double sn; | 
					
						
							|  |  |  |             double c; | 
					
						
							|  |  |  |             double den; | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  |             if (f < f_min) f = f_min; | 
					
						
							| 
									
										
										
										
											2024-08-03 11:05:12 +02:00
										 |  |  |             w0 = TWOPI * f / rate; | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  |             sn = sin (w0); | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  |             cbw = bw_corr * f; | 
					
						
							|  |  |  |             c = sn * sinh(0.5 * log((f + 0.5 * cbw * bw_parm) / (f - 0.5 * cbw * bw_parm)) * w0 / sn); | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  |             den = 1.0 + c / A; | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  |             a0 = (1.0 + c * A) / den; | 
					
						
							|  |  |  |             a1 = - 2.0 * cos (w0) / den; | 
					
						
							|  |  |  |             a2 = (1 - c * A) / den; | 
					
						
							|  |  |  |             b1 = - a1; | 
					
						
							|  |  |  |             b2 = - (1 - c / A ) / den; | 
					
						
							|  |  |  |             fgain = gain / pow (A * A, (double)nstages); | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2024-08-03 11:05:12 +02:00
										 |  |  |     default: | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  |     flush(); | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  | SPEAK::SPEAK( | 
					
						
							|  |  |  |     int _run, | 
					
						
							|  |  |  |     int _size, | 
					
						
							|  |  |  |     float* _in, | 
					
						
							|  |  |  |     float* _out, | 
					
						
							|  |  |  |     int _rate, | 
					
						
							|  |  |  |     double _f, | 
					
						
							|  |  |  |     double _bw, | 
					
						
							|  |  |  |     double _gain, | 
					
						
							|  |  |  |     int _nstages, | 
					
						
							|  |  |  |     int _design | 
					
						
							|  |  |  | ) : | 
					
						
							|  |  |  |     run(_run), | 
					
						
							|  |  |  |     size(_size), | 
					
						
							|  |  |  |     in(_in), | 
					
						
							|  |  |  |     out(_out), | 
					
						
							|  |  |  |     rate(_rate), | 
					
						
							|  |  |  |     f(_f), | 
					
						
							|  |  |  |     bw(_bw), | 
					
						
							|  |  |  |     gain(_gain), | 
					
						
							|  |  |  |     nstages(_nstages), | 
					
						
							|  |  |  |     design(_design) | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-08-03 11:05:12 +02:00
										 |  |  |     x0.resize(nstages * 2); | 
					
						
							|  |  |  |     x1.resize(nstages * 2); | 
					
						
							|  |  |  |     x2.resize(nstages * 2); | 
					
						
							|  |  |  |     y0.resize(nstages * 2); | 
					
						
							|  |  |  |     y1.resize(nstages * 2); | 
					
						
							|  |  |  |     y2.resize(nstages * 2); | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  |     calc(); | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  | void SPEAK::flush() | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  |     for (int i = 0; i < nstages; i++) | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  |         x1[2 * i + 0] = x2[2 * i + 0] = y1[2 * i + 0] = y2[2 * i + 0] = 0.0; | 
					
						
							|  |  |  |         x1[2 * i + 1] = x2[2 * i + 1] = y1[2 * i + 1] = y2[2 * i + 1] = 0.0; | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  | void SPEAK::execute() | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  |     if (run) | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  |         for (int i = 0; i < size; i++) | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  |             for (int j = 0; j < 2; j++) | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  |             { | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  |                 x0[j] = fgain * in[2 * i + j]; | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  |                 for (int n = 0; n < nstages; n++) | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  |                 { | 
					
						
							|  |  |  |                     if (n > 0) | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  |                         x0[2 * n + j] = y0[2 * (n - 1) + j]; | 
					
						
							|  |  |  |                     y0[2 * n + j] = a0 * x0[2 * n + j] | 
					
						
							|  |  |  |                         + a1 * x1[2 * n + j] | 
					
						
							|  |  |  |                         + a2 * x2[2 * n + j] | 
					
						
							|  |  |  |                         + b1 * y1[2 * n + j] | 
					
						
							|  |  |  |                         + b2 * y2[2 * n + j]; | 
					
						
							|  |  |  |                     y2[2 * n + j] = y1[2 * n + j]; | 
					
						
							|  |  |  |                     y1[2 * n + j] = y0[2 * n + j]; | 
					
						
							|  |  |  |                     x2[2 * n + j] = x1[2 * n + j]; | 
					
						
							|  |  |  |                     x1[2 * n + j] = x0[2 * n + j]; | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-03 11:05:12 +02:00
										 |  |  |                 out[2 * i + j] = (float) y0[2 * (nstages - 1) + j]; | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  |     else if (out != in) | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  |         std::copy( in,  in + size * 2, out); | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  | void SPEAK::setBuffers(float* _in, float* _out) | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  |     in = _in; | 
					
						
							|  |  |  |     out = _out; | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  | void SPEAK::setSamplerate(int _rate) | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  |     rate = _rate; | 
					
						
							|  |  |  |     calc(); | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  | void SPEAK::setSize(int _size) | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  |     size = _size; | 
					
						
							|  |  |  |     flush(); | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /********************************************************************************************************
 | 
					
						
							|  |  |  | *                                                                                                       * | 
					
						
							|  |  |  | *                                           RXA Properties                                              * | 
					
						
							|  |  |  | *                                                                                                       * | 
					
						
							|  |  |  | ********************************************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  | void SPEAK::setRun(int _run) | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  |     run = _run; | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  | void SPEAK::setFreq(double _freq) | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  |     f = _freq; | 
					
						
							|  |  |  |     calc(); | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  | void SPEAK::setBandwidth(double _bw) | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  |     bw = _bw; | 
					
						
							|  |  |  |     calc(); | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  | void SPEAK::setGain(double _gain) | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-08-01 00:31:28 +02:00
										 |  |  |     gain = _gain; | 
					
						
							|  |  |  |     calc(); | 
					
						
							| 
									
										
										
										
											2024-07-31 01:37:17 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } // namespace WDSP
 |