| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  | /*  resample.c
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This file is part of a program that implements a Software-Defined Radio. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Copyright (C) 2013 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 "fir.hpp"
 | 
					
						
							|  |  |  | #include "resample.hpp"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace WDSP { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************************************************************************************
 | 
					
						
							|  |  |  | *                                                                                               * | 
					
						
							|  |  |  | *                             VERSION FOR COMPLEX DOUBLE-PRECISION                              * | 
					
						
							|  |  |  | *                                                                                               * | 
					
						
							|  |  |  | ************************************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 04:52:00 +02:00
										 |  |  | void RESAMPLE::calc() | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-08-03 11:05:12 +02:00
										 |  |  |     int x; | 
					
						
							|  |  |  |     int y; | 
					
						
							|  |  |  |     int z; | 
					
						
							|  |  |  |     int i; | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  |     int min_rate; | 
					
						
							| 
									
										
										
										
											2024-07-17 21:50:58 +02:00
										 |  |  |     double full_rate; | 
					
						
							| 
									
										
										
										
											2024-08-03 11:05:12 +02:00
										 |  |  |     double fc_norm_high; | 
					
						
							|  |  |  |     double fc_norm_low; | 
					
						
							| 
									
										
										
										
											2024-08-10 06:40:35 +02:00
										 |  |  |     std::vector<float> impulse; | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  |     fc = fcin; | 
					
						
							|  |  |  |     ncoef = ncoefin; | 
					
						
							|  |  |  |     x = in_rate; | 
					
						
							|  |  |  |     y = out_rate; | 
					
						
							| 
									
										
										
										
											2024-07-17 21:50:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  |     while (y != 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         z = y; | 
					
						
							|  |  |  |         y = x % y; | 
					
						
							|  |  |  |         x = z; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-07-17 21:50:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  |     L = out_rate / x; | 
					
						
							|  |  |  |     M = in_rate / x; | 
					
						
							| 
									
										
										
										
											2024-07-17 21:50:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  |     L = L <= 0 ? 1 : L; | 
					
						
							|  |  |  |     M = M <= 0 ? 1 : M; | 
					
						
							| 
									
										
										
										
											2024-07-19 08:10:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  |     if (in_rate < out_rate) | 
					
						
							|  |  |  |         min_rate = in_rate; | 
					
						
							| 
									
										
										
										
											2024-07-17 21:50:58 +02:00
										 |  |  |     else | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  |         min_rate = out_rate; | 
					
						
							| 
									
										
										
										
											2024-07-17 21:50:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  |     if (fc == 0.0) | 
					
						
							|  |  |  |         fc = 0.45 * (float)min_rate; | 
					
						
							| 
									
										
										
										
											2024-07-17 21:50:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  |     full_rate = (double) (in_rate * L); | 
					
						
							|  |  |  |     fc_norm_high = fc / full_rate; | 
					
						
							| 
									
										
										
										
											2024-07-17 21:50:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  |     if (fc_low < 0.0) | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  |         fc_norm_low = - fc_norm_high; | 
					
						
							|  |  |  |     else | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  |         fc_norm_low = fc_low / full_rate; | 
					
						
							| 
									
										
										
										
											2024-07-17 21:50:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  |     if (ncoef == 0) | 
					
						
							|  |  |  |         ncoef = (int)(140.0 * full_rate / min_rate); | 
					
						
							| 
									
										
										
										
											2024-07-17 21:50:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  |     ncoef = (ncoef / L + 1) * L; | 
					
						
							|  |  |  |     cpp = ncoef / L; | 
					
						
							| 
									
										
										
										
											2024-08-03 11:05:12 +02:00
										 |  |  |     h.resize(ncoef); | 
					
						
							| 
									
										
										
										
											2024-08-10 06:40:35 +02:00
										 |  |  |     FIR::fir_bandpass(impulse, ncoef, fc_norm_low, fc_norm_high, 1.0, 1, 0, gain * (double)L); | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  |     i = 0; | 
					
						
							| 
									
										
										
										
											2024-07-17 21:50:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-03 11:05:12 +02:00
										 |  |  |     for (int j = 0; j < L; j++) | 
					
						
							| 
									
										
										
										
											2024-07-17 21:50:58 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2024-08-03 11:05:12 +02:00
										 |  |  |         for (int k = 0; k < ncoef; k += L) | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  |             h[i++] = impulse[j + k]; | 
					
						
							| 
									
										
										
										
											2024-07-17 21:50:58 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  |     ringsize = cpp; | 
					
						
							| 
									
										
										
										
											2024-08-03 11:05:12 +02:00
										 |  |  |     ring.resize(ringsize); | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  |     idx_in = ringsize - 1; | 
					
						
							|  |  |  |     phnum = 0; | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  | RESAMPLE::RESAMPLE ( | 
					
						
							|  |  |  |     int _run, | 
					
						
							|  |  |  |     int _size, | 
					
						
							|  |  |  |     float* _in, | 
					
						
							|  |  |  |     float* _out, | 
					
						
							|  |  |  |     int _in_rate, | 
					
						
							|  |  |  |     int _out_rate, | 
					
						
							|  |  |  |     double _fc, | 
					
						
							|  |  |  |     int _ncoef, | 
					
						
							|  |  |  |     double _gain | 
					
						
							| 
									
										
										
										
											2024-07-24 04:52:00 +02:00
										 |  |  | ) : | 
					
						
							|  |  |  |     run(_run), | 
					
						
							|  |  |  |     size(_size), | 
					
						
							|  |  |  |     in(_in), | 
					
						
							|  |  |  |     out(_out), | 
					
						
							|  |  |  |     in_rate(_in_rate), | 
					
						
							|  |  |  |     out_rate(_out_rate), | 
					
						
							|  |  |  |     fcin(_fc), | 
					
						
							|  |  |  |     fc_low(-1.0),       // could add to create_resample() parameters
 | 
					
						
							|  |  |  |     ncoefin(_ncoef), | 
					
						
							|  |  |  |     gain(_gain) | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-07-24 04:52:00 +02:00
										 |  |  |     calc(); | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  | void RESAMPLE::flush() | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-07-27 23:29:15 +02:00
										 |  |  |     std::fill(ring.begin(), ring.end(), 0); | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  |     idx_in = ringsize - 1; | 
					
						
							|  |  |  |     phnum = 0; | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  | int RESAMPLE::execute() | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     int outsamps = 0; | 
					
						
							| 
									
										
										
										
											2024-07-17 21:50:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  |     if (run) | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2024-08-03 11:05:12 +02:00
										 |  |  |         int n; | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  |         int idx_out; | 
					
						
							| 
									
										
										
										
											2024-08-03 11:05:12 +02:00
										 |  |  |         double I; | 
					
						
							|  |  |  |         double Q; | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-03 11:05:12 +02:00
										 |  |  |         for (int i = 0; i < size; i++) | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  |             ring[2 * idx_in + 0] = in[2 * i + 0]; | 
					
						
							|  |  |  |             ring[2 * idx_in + 1] = in[2 * i + 1]; | 
					
						
							| 
									
										
										
										
											2024-07-17 21:50:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  |             while (phnum < L) | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  |             { | 
					
						
							|  |  |  |                 I = 0.0; | 
					
						
							|  |  |  |                 Q = 0.0; | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  |                 n = cpp * phnum; | 
					
						
							| 
									
										
										
										
											2024-07-17 21:50:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-03 11:05:12 +02:00
										 |  |  |                 for (int j = 0; j < cpp; j++) | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  |                 { | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  |                     if ((idx_out = idx_in + j) >= ringsize) | 
					
						
							|  |  |  |                         idx_out -= ringsize; | 
					
						
							| 
									
										
										
										
											2024-07-17 21:50:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  |                     I += h[n + j] * ring[2 * idx_out + 0]; | 
					
						
							|  |  |  |                     Q += h[n + j] * ring[2 * idx_out + 1]; | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2024-07-17 21:50:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-03 11:05:12 +02:00
										 |  |  |                 out[2 * outsamps + 0] = (float) I; | 
					
						
							|  |  |  |                 out[2 * outsamps + 1] = (float) Q; | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  |                 outsamps++; | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  |                 phnum += M; | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2024-07-17 21:50:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  |             phnum -= L; | 
					
						
							| 
									
										
										
										
											2024-07-17 21:50:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  |             if (--idx_in < 0) | 
					
						
							|  |  |  |                 idx_in = ringsize - 1; | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  |     else if (in != out) | 
					
						
							| 
									
										
										
										
											2024-07-17 21:50:58 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  |         std::copy( in,  in + size * 2, out); | 
					
						
							| 
									
										
										
										
											2024-07-17 21:50:58 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  |     return outsamps; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  | void RESAMPLE::setBuffers(float* _in, float* _out) | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  |     in = _in; | 
					
						
							|  |  |  |     out = _out; | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  | void RESAMPLE::setSize(int _size) | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  |     size = _size; | 
					
						
							|  |  |  |     flush(); | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  | void RESAMPLE::setInRate(int _rate) | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  |     in_rate = _rate; | 
					
						
							| 
									
										
										
										
											2024-07-24 04:52:00 +02:00
										 |  |  |     calc(); | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  | void RESAMPLE::setOutRate(int _rate) | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  |     out_rate = _rate; | 
					
						
							| 
									
										
										
										
											2024-07-24 04:52:00 +02:00
										 |  |  |     calc(); | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  | void RESAMPLE::setFCLow(double _fc_low) | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  |     if (fc_low != _fc_low) | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  |         fc_low = _fc_low; | 
					
						
							| 
									
										
										
										
											2024-07-24 04:52:00 +02:00
										 |  |  |         calc(); | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  | void RESAMPLE::setBandwidth(double _fc_low, double _fc_high) | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  |     if (fc_low != _fc_low || _fc_high != fcin) | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2024-07-24 04:33:42 +02:00
										 |  |  |         fc_low = _fc_low; | 
					
						
							|  |  |  |         fcin = _fc_high; | 
					
						
							| 
									
										
										
										
											2024-07-24 04:52:00 +02:00
										 |  |  |         calc(); | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // exported calls
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-03 11:05:12 +02:00
										 |  |  | RESAMPLE* RESAMPLE::Create(int in_rate, int out_rate) | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-08-03 11:05:12 +02:00
										 |  |  |     return new RESAMPLE(1, 0, nullptr, nullptr, in_rate, out_rate, 0.0, 0, 1.0); | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-03 11:05:12 +02:00
										 |  |  | void RESAMPLE::Execute(float* input, float* output, int numsamps, int* outsamps, RESAMPLE* ptr) | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-08-03 11:05:12 +02:00
										 |  |  |     ptr->in = input; | 
					
						
							|  |  |  |     ptr->out = output; | 
					
						
							|  |  |  |     ptr->size = numsamps; | 
					
						
							|  |  |  |     *outsamps = ptr->execute(); | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-03 11:05:12 +02:00
										 |  |  | void RESAMPLE::Destroy(RESAMPLE* ptr) | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-08-03 11:05:12 +02:00
										 |  |  |     delete  ptr; | 
					
						
							| 
									
										
										
										
											2024-06-16 11:31:13 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } // namespace WDSP
 |