Mercurial > hg > audiostuff
diff spandsp-0.0.3/spandsp-0.0.3/src/v29rx.c @ 5:f762bf195c4b
import spandsp-0.0.3
author | Peter Meerwald <pmeerw@cosy.sbg.ac.at> |
---|---|
date | Fri, 25 Jun 2010 16:00:21 +0200 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spandsp-0.0.3/spandsp-0.0.3/src/v29rx.c Fri Jun 25 16:00:21 2010 +0200 @@ -0,0 +1,2265 @@ +/* + * SpanDSP - a series of DSP components for telephony + * + * v29rx.c - ITU V.29 modem receive part + * + * Written by Steve Underwood <steveu@coppice.org> + * + * Copyright (C) 2003 Steve Underwood + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id: v29rx.c,v 1.100 2006/11/28 16:59:57 steveu Exp $ + */ + +/*! \file */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <inttypes.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#if defined(HAVE_TGMATH_H) +#include <tgmath.h> +#endif +#if defined(HAVE_MATH_H) +#include <math.h> +#endif + +#include "spandsp/telephony.h" +#include "spandsp/logging.h" +#include "spandsp/complex.h" +#include "spandsp/vector_float.h" +#include "spandsp/complex_vector_float.h" +#include "spandsp/async.h" +#include "spandsp/power_meter.h" +#include "spandsp/arctan2.h" +#include "spandsp/dds.h" +#include "spandsp/complex_filters.h" + +#include "spandsp/v29rx.h" + +#define CARRIER_NOMINAL_FREQ 1700.0f +#define BAUD_RATE 2400 +#define EQUALIZER_DELTA 0.21f + +/* Segments of the training sequence */ +#define V29_TRAINING_SEG_2_LEN 128 +#define V29_TRAINING_SEG_3_LEN 384 +#define V29_TRAINING_SEG_4_LEN 48 + +enum +{ + TRAINING_STAGE_NORMAL_OPERATION = 0, + TRAINING_STAGE_SYMBOL_ACQUISITION, + TRAINING_STAGE_LOG_PHASE, + TRAINING_STAGE_WAIT_FOR_CDCD, + TRAINING_STAGE_TRAIN_ON_CDCD, + TRAINING_STAGE_TRAIN_ON_CDCD_AND_TEST, + TRAINING_STAGE_TEST_ONES, + TRAINING_STAGE_PARKED +}; + +static const complexf_t v29_constellation[16] = +{ + { 3.0f, 0.0f}, /* 0deg low */ + { 1.0f, 1.0f}, /* 45deg low */ + { 0.0f, 3.0f}, /* 90deg low */ + {-1.0f, 1.0f}, /* 135deg low */ + {-3.0f, 0.0f}, /* 180deg low */ + {-1.0f, -1.0f}, /* 225deg low */ + { 0.0f, -3.0f}, /* 270deg low */ + { 1.0f, -1.0f}, /* 315deg low */ + { 5.0f, 0.0f}, /* 0deg high */ + { 3.0f, 3.0f}, /* 45deg high */ + { 0.0f, 5.0f}, /* 90deg high */ + {-3.0f, 3.0f}, /* 135deg high */ + {-5.0f, 0.0f}, /* 180deg high */ + {-3.0f, -3.0f}, /* 225deg high */ + { 0.0f, -5.0f}, /* 270deg high */ + { 3.0f, -3.0f} /* 315deg high */ +}; + +static const uint8_t space_map_9600[20][20] = +{ + {13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11}, + {13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11}, + {13, 13, 13, 13, 13, 13, 13, 4, 4, 4, 4, 4, 4, 11, 11, 11, 11, 11, 11, 11}, + {13, 13, 13, 13, 13, 13, 13, 4, 4, 4, 4, 4, 4, 11, 11, 11, 11, 11, 11, 11}, + {13, 13, 13, 13, 13, 13, 13, 4, 4, 4, 4, 4, 4, 11, 11, 11, 11, 11, 11, 11}, + {13, 13, 13, 13, 13, 13, 13, 5, 4, 4, 4, 4, 3, 11, 11, 11, 11, 11, 11, 11}, + {14, 13, 13, 13, 13, 13, 5, 5, 5, 5, 3, 3, 3, 3, 11, 11, 11, 11, 11, 10}, + {14, 14, 6, 6, 6, 5, 5, 5, 5, 5, 3, 3, 3, 3, 3, 2, 2, 2, 10, 10}, + {14, 14, 6, 6, 6, 6, 5, 5, 5, 5, 3, 3, 3, 3, 2, 2, 2, 2, 10, 10}, + {14, 14, 6, 6, 6, 6, 5, 5, 5, 5, 3, 3, 3, 3, 2, 2, 2, 2, 10, 10}, + {14, 14, 6, 6, 6, 6, 7, 7, 7, 7, 1, 1, 1, 1, 2, 2, 2, 2, 10, 10}, + {14, 14, 6, 6, 6, 6, 7, 7, 7, 7, 1, 1, 1, 1, 2, 2, 2, 2, 10, 10}, + {14, 14, 6, 6, 6, 7, 7, 7, 7, 7, 1, 1, 1, 1, 1, 2, 2, 2, 10, 10}, + {14, 15, 15, 15, 15, 15, 7, 7, 7, 7, 1, 1, 1, 1, 9, 9, 9, 9, 9, 10}, + {15, 15, 15, 15, 15, 15, 15, 7, 0, 0, 0, 0, 1, 9, 9, 9, 9, 9, 9, 9}, + {15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9}, + {15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9}, + {15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9}, + {15, 15, 15, 15, 15, 15, 15, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9}, + {15, 15, 15, 15, 15, 15, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9} +}; + +/* Raised root cosine pulse shaping; Beta = 0.5; 4 symbols either + side of the centre. We cannot simplify this by using only half + the filter, as each variant are each skewed by n/PULSESHAPER_COEFF_SETS of a + sample. Only one is symmetric. */ +#define PULSESHAPER_GAIN 10.00736638f +#define PULSESHAPER_COEFF_SETS 48 +static const complexf_t pulseshaper[PULSESHAPER_COEFF_SETS][V29_RX_FILTER_STEPS] = +{ + { + {-0.0006054906f, -0.0076934875f}, /* Filter 0 */ + { 0.0036800486f, -0.0011957203f}, + {-0.0058580399f, -0.0095594523f}, + { 0.0088272477f, -0.0088272477f}, + {-0.0070156625f, -0.0042992035f}, + { 0.0051634535f, -0.0158914757f}, + {-0.0145681539f, -0.0011465386f}, + {-0.0064674675f, -0.0408339830f}, + {-0.0136664375f, 0.0056608238f}, + {-0.0772003348f, -0.1062571451f}, + { 0.0857393910f, -0.1003879288f}, + {-0.1385128868f, -0.0705758409f}, + { 0.1555698727f, -0.6479951549f}, + { 1.0773601675f, 0.0000000000f}, + { 0.2515047363f, 1.0475926203f}, + {-0.5937739316f, 0.3025429295f}, + {-0.1009610161f, -0.1182101618f}, + {-0.0775987390f, 0.1068055014f}, + {-0.1213433119f, -0.0502620455f}, + { 0.0023140483f, -0.0146103259f}, + {-0.0412155371f, 0.0032437331f}, + {-0.0045157276f, -0.0138979805f}, + {-0.0142470087f, 0.0087305782f}, + {-0.0058181901f, -0.0058181901f}, + {-0.0065226701f, 0.0106440302f}, + {-0.0106628561f, -0.0034645720f}, + {-0.0003035921f, 0.0038575039f}, + }, + { + {-0.0003235976f, -0.0041116977f}, /* Filter 1 */ + { 0.0034317849f, -0.0011150545f}, + {-0.0059948336f, -0.0097826794f}, + { 0.0086437458f, -0.0086437458f}, + {-0.0074140419f, -0.0045433307f}, + { 0.0050851588f, -0.0156505094f}, + {-0.0154601145f, -0.0012167374f}, + {-0.0064469783f, -0.0407046190f}, + {-0.0156933045f, 0.0065003796f}, + {-0.0783633460f, -0.1078578927f}, + { 0.0839596331f, -0.0983041000f}, + {-0.1466635902f, -0.0747288317f}, + { 0.1581236518f, -0.6586324102f}, + { 1.0822215889f, 0.0000000000f}, + { 0.2503251863f, 1.0426794408f}, + {-0.5839878512f, 0.2975566724f}, + {-0.0950902426f, -0.1113363693f}, + {-0.0791302548f, 0.1089134521f}, + {-0.1194691818f, -0.0494857553f}, + { 0.0019760247f, -0.0124761291f}, + {-0.0413061980f, 0.0032508683f}, + {-0.0042392071f, -0.0130469379f}, + {-0.0144455612f, 0.0088522513f}, + {-0.0054839934f, -0.0054839934f}, + {-0.0066522258f, 0.0108554460f}, + {-0.0104075179f, -0.0033816075f}, + {-0.0003235976f, 0.0041116977f}, + }, + { + {-0.0003431146f, -0.0043596842f}, /* Filter 2 */ + { 0.0031779221f, -0.0010325695f}, + {-0.0061279979f, -0.0099999837f}, + { 0.0084521727f, -0.0084521727f}, + {-0.0078074148f, -0.0047843899f}, + { 0.0050005298f, -0.0153900482f}, + {-0.0163511406f, -0.0012868627f}, + {-0.0064201364f, -0.0405351459f}, + {-0.0177497724f, 0.0073521965f}, + {-0.0794957450f, -0.1094165063f}, + { 0.0820917217f, -0.0961170567f}, + {-0.1549087286f, -0.0789299396f}, + { 0.1606663689f, -0.6692235895f}, + { 1.0868898157f, 0.0000000000f}, + { 0.2491014054f, 1.0375820265f}, + {-0.5741661901f, 0.2925522861f}, + {-0.0892910248f, -0.1045463576f}, + {-0.0805830641f, 0.1109130726f}, + {-0.1175509420f, -0.0486911944f}, + { 0.0016433282f, -0.0103755662f}, + {-0.0413575411f, 0.0032549091f}, + {-0.0039628985f, -0.0121965475f}, + {-0.0146266493f, 0.0089632222f}, + {-0.0051463192f, -0.0051463192f}, + {-0.0067756751f, 0.0110568969f}, + {-0.0101460989f, -0.0032966674f}, + {-0.0003431146f, 0.0043596842f}, + }, + { + {-0.0003621305f, -0.0046013044f}, /* Filter 3 */ + { 0.0029186307f, -0.0009483206f}, + {-0.0062573914f, -0.0102111348f}, + { 0.0082526365f, -0.0082526365f}, + {-0.0081953754f, -0.0050221325f}, + { 0.0049095725f, -0.0151101104f}, + {-0.0172404079f, -0.0013568495f}, + {-0.0063868556f, -0.0403250190f}, + {-0.0198348595f, 0.0082158678f}, + {-0.0805962556f, -0.1109312291f}, + { 0.0801351139f, -0.0938261634f}, + {-0.1632463544f, -0.0831781721f}, + { 0.1631971552f, -0.6797650728f}, + { 1.0913630919f, 0.0000000000f}, + { 0.2478338529f, 1.0323022902f}, + {-0.5643122679f, 0.2875314620f}, + {-0.0835646644f, -0.0978416511f}, + {-0.0819577515f, 0.1128051674f}, + {-0.1155905906f, -0.0478791903f}, + { 0.0013161074f, -0.0083095754f}, + {-0.0413701808f, 0.0032559039f}, + {-0.0036870475f, -0.0113475654f}, + {-0.0147903020f, 0.0090635087f}, + {-0.0048055043f, -0.0048055043f}, + {-0.0068929555f, 0.0112482810f}, + {-0.0098788669f, -0.0032098384f}, + {-0.0003621305f, 0.0046013044f}, + }, + { + {-0.0003806334f, -0.0048364061f}, /* Filter 4 */ + { 0.0026540877f, -0.0008623654f}, + {-0.0063828750f, -0.0104159053f}, + { 0.0080452535f, -0.0080452535f}, + {-0.0085775184f, -0.0052563101f}, + { 0.0048122983f, -0.0148107313f}, + {-0.0181270820f, -0.0014266323f}, + {-0.0063470532f, -0.0400737166f}, + {-0.0219475497f, 0.0090909727f}, + {-0.0816636012f, -0.1124003042f}, + { 0.0780893017f, -0.0914308250f}, + {-0.1716744668f, -0.0874725099f}, + { 0.1657151424f, -0.6902532446f}, + { 1.0956397332f, 0.0000000000f}, + { 0.2465230038f, 1.0268422107f}, + {-0.5544294025f, 0.2824958906f}, + {-0.0779124236f, -0.0912237273f}, + {-0.0832549311f, 0.1145905820f}, + {-0.1135901216f, -0.0470505689f}, + { 0.0009945051f, -0.0062790582f}, + {-0.0413447525f, 0.0032539026f}, + {-0.0034118961f, -0.0105007365f}, + {-0.0149365628f, 0.0091531374f}, + {-0.0044618854f, -0.0044618854f}, + {-0.0070040103f, 0.0114295060f}, + {-0.0096060925f, -0.0031212087f}, + {-0.0003806334f, 0.0048364061f}, + }, + { + {-0.0003986119f, -0.0050648440f}, /* Filter 5 */ + { 0.0023844759f, -0.0007747632f}, + {-0.0065043116f, -0.0106140718f}, + { 0.0078301476f, -0.0078301476f}, + {-0.0089534403f, -0.0054866753f}, + { 0.0047087245f, -0.0144919637f}, + {-0.0190103194f, -0.0014961446f}, + {-0.0063006503f, -0.0397807405f}, + {-0.0240867927f, 0.0099770762f}, + {-0.0826965057f, -0.1138219754f}, + { 0.0759538132f, -0.0889304892f}, + {-0.1801910135f, -0.0918119071f}, + { 0.1682194641f, -0.7006844950f}, + { 1.0997181284f, 0.0000000000f}, + { 0.2451693490f, 1.0212038328f}, + {-0.5445209082f, 0.2774472605f}, + {-0.0723355236f, -0.0846940164f}, + {-0.0844752467f, 0.1162702023f}, + {-0.1115515226f, -0.0462061535f}, + { 0.0006786580f, -0.0042848780f}, + {-0.0412819110f, 0.0032489569f}, + {-0.0031376826f, -0.0096567942f}, + {-0.0150654901f, 0.0092321442f}, + {-0.0041157984f, -0.0041157984f}, + {-0.0071087889f, 0.0116004892f}, + {-0.0093280490f, -0.0030308668f}, + {-0.0003986119f, 0.0050648440f}, + }, + { + {-0.0004160550f, -0.0052864799f}, /* Filter 6 */ + { 0.0021099840f, -0.0006855754f}, + {-0.0066215668f, -0.0108054149f}, + { 0.0076074506f, -0.0076074506f}, + {-0.0093227386f, -0.0057129815f}, + { 0.0045988736f, -0.0141538775f}, + {-0.0198892682f, -0.0015653194f}, + {-0.0062475719f, -0.0394456164f}, + {-0.0262515049f, 0.0108737293f}, + {-0.0836936943f, -0.1151944878f}, + { 0.0737282126f, -0.0863246457f}, + {-0.1887938905f, -0.0961952919f}, + { 0.1707092554f, -0.7110552220f}, + { 1.1035967397f, 0.0000000000f}, + { 0.2437733949f, 1.0153892656f}, + {-0.5345900940f, 0.2723872580f}, + {-0.0668351454f, -0.0782539010f}, + {-0.0856193708f, 0.1178449541f}, + {-0.1094767749f, -0.0453467649f}, + { 0.0003686970f, -0.0023278610f}, + {-0.0411823301f, 0.0032411197f}, + {-0.0028646414f, -0.0088164597f}, + {-0.0151771562f, 0.0093005733f}, + {-0.0037675783f, -0.0037675783f}, + {-0.0072072465f, 0.0117611574f}, + {-0.0090450120f, -0.0029389025f}, + {-0.0004160550f, 0.0052864799f}, + }, + { + {-0.0004329524f, -0.0055011823f}, /* Filter 7 */ + { 0.0018308065f, -0.0005948651f}, + {-0.0067345088f, -0.0109897195f}, + { 0.0073773020f, -0.0073773020f}, + {-0.0096850130f, -0.0059349836f}, + { 0.0044827743f, -0.0137965606f}, + {-0.0207630684f, -0.0016340889f}, + {-0.0061877467f, -0.0390678953f}, + {-0.0284405684f, 0.0117804691f}, + {-0.0846538939f, -0.1165160891f}, + { 0.0714121011f, -0.0836128276f}, + {-0.1974809435f, -0.1006215665f}, + { 0.1731836536f, -0.7213618325f}, + { 1.1072741035f, 0.0000000000f}, + { 0.2423356631f, 1.0094006816f}, + {-0.5246402627f, 0.2673175657f}, + {-0.0614124285f, -0.0719047153f}, + {-0.0866880040f, 0.1193158015f}, + {-0.1073678519f, -0.0444732204f}, + { 0.0000647469f, -0.0004087959f}, + {-0.0410467015f, 0.0032304455f}, + {-0.0025930028f, -0.0079804420f}, + {-0.0152716480f, 0.0093584780f}, + {-0.0034175587f, -0.0034175587f}, + {-0.0072993441f, 0.0119114470f}, + {-0.0087572594f, -0.0028454060f}, + {-0.0004329524f, 0.0055011823f}, + }, + { + {-0.0004492944f, -0.0057088271f}, /* Filter 8 */ + { 0.0015471436f, -0.0005026974f}, + {-0.0068430082f, -0.0111667745f}, + { 0.0071398493f, -0.0071398493f}, + {-0.0100398656f, -0.0061524375f}, + { 0.0043604608f, -0.0134201184f}, + {-0.0216308523f, -0.0017023850f}, + {-0.0061211077f, -0.0386471532f}, + {-0.0306528326f, 0.0126968190f}, + {-0.0855758340f, -0.1177850307f}, + { 0.0690051173f, -0.0807946117f}, + {-0.2062499680f, -0.1050896077f}, + { 0.1756417989f, -0.7316007446f}, + { 1.1107488316f, 0.0000000000f}, + { 0.2408566902f, 1.0032403162f}, + {-0.5146747091f, 0.2622398626f}, + {-0.0560684714f, -0.0656477454f}, + {-0.0876818748f, 0.1206837473f}, + {-0.1052267179f, -0.0435863337f}, + {-0.0002330732f, 0.0014715664f}, + {-0.0408757346f, 0.0032169901f}, + {-0.0023229930f, -0.0071494373f}, + {-0.0153490660f, 0.0094059197f}, + {-0.0030660718f, -0.0030660718f}, + {-0.0073850485f, 0.0120513039f}, + {-0.0084650709f, -0.0027504683f}, + {-0.0004492944f, 0.0057088271f}, + }, + { + {-0.0004650718f, -0.0059092972f}, /* Filter 9 */ + { 0.0012592008f, -0.0004091391f}, + {-0.0069469389f, -0.0113363740f}, + { 0.0068952472f, -0.0068952472f}, + {-0.0103869007f, -0.0063651009f}, + { 0.0042319732f, -0.0130246742f}, + {-0.0224917457f, -0.0017701388f}, + {-0.0060475918f, -0.0381829922f}, + {-0.0328871136f, 0.0136222885f}, + {-0.0864582472f, -0.1189995684f}, + { 0.0665069376f, -0.0778696190f}, + {-0.2150987105f, -0.1095982672f}, + { 0.1780828343f, -0.7417683886f}, + { 1.1140196110f, 0.0000000000f}, + { 0.2393370276f, 0.9969104659f}, + {-0.5046967186f, 0.2571558224f}, + {-0.0508043306f, -0.0594842284f}, + {-0.0886017384f, 0.1219498309f}, + {-0.1030553278f, -0.0426869144f}, + {-0.0005246505f, 0.0033125128f}, + {-0.0406701557f, 0.0032008107f}, + {-0.0020548339f, -0.0063241284f}, + {-0.0154095242f, 0.0094429686f}, + {-0.0027134480f, -0.0027134480f}, + {-0.0074643325f, 0.0121806836f}, + {-0.0081687281f, -0.0026541806f}, + {-0.0004650718f, 0.0059092972f}, + }, + { + {-0.0004802758f, -0.0061024829f}, /* Filter 10 */ + { 0.0009671895f, -0.0003142589f}, + {-0.0070461774f, -0.0114983165f}, + { 0.0066436583f, -0.0066436583f}, + {-0.0107257260f, -0.0065727333f}, + { 0.0040973574f, -0.0126103693f}, + {-0.0233448674f, -0.0018372809f}, + {-0.0059671403f, -0.0376750413f}, + {-0.0351421949f, 0.0145563737f}, + {-0.0872998705f, -0.1201579635f}, + { 0.0639172763f, -0.0748375152f}, + {-0.2240248692f, -0.1141463722f}, + { 0.1805059061f, -0.7518612089f}, + { 1.1170852055f, 0.0000000000f}, + { 0.2377772412f, 0.9904134878f}, + {-0.4947095655f, 0.2520671138f}, + {-0.0456210210f, -0.0534153526f}, + {-0.0894483767f, 0.1231151286f}, + {-0.1008556255f, -0.0417757679f}, + {-0.0008098779f, 0.0051133675f}, + {-0.0404307068f, 0.0031819656f}, + {-0.0017887430f, -0.0055051847f}, + {-0.0154531504f, 0.0094697028f}, + {-0.0023600156f, -0.0023600156f}, + {-0.0075371745f, 0.0122995509f}, + {-0.0078685137f, -0.0025566351f}, + {-0.0004802758f, 0.0061024829f}, + }, + { + {-0.0004948985f, -0.0062882817f}, /* Filter 11 */ + { 0.0006713257f, -0.0002181269f}, + {-0.0071406035f, -0.0116524059f}, + { 0.0063852527f, -0.0063852526f}, + {-0.0110559525f, -0.0067750964f}, + { 0.0039566651f, -0.0121773631f}, + {-0.0241893313f, -0.0019037417f}, + {-0.0058796987f, -0.0371229566f}, + {-0.0374168281f, 0.0154985577f}, + {-0.0880994453f, -0.1212584838f}, + { 0.0612358868f, -0.0716980115f}, + {-0.2330260947f, -0.1187327256f}, + { 0.1829101645f, -0.7618756659f}, + { 1.1199444556f, 0.0000000000f}, + { 0.2361779109f, 0.9837517978f}, + {-0.4847165122f, 0.2469753988f}, + {-0.0405195152f, -0.0474422567f}, + {-0.0902225974f, 0.1241807520f}, + {-0.0986295432f, -0.0408536944f}, + {-0.0010886543f, 0.0068734926f}, + {-0.0401581456f, 0.0031605146f}, + {-0.0015249332f, -0.0046932617f}, + {-0.0154800853f, 0.0094862085f}, + {-0.0020061005f, -0.0020061005f}, + {-0.0076035587f, 0.0124078801f}, + {-0.0075647115f, -0.0024579238f}, + {-0.0004948985f, 0.0062882817f}, + }, + { + {-0.0005089323f, -0.0064665981f}, /* Filter 12 */ + { 0.0003718310f, -0.0001208152f}, + {-0.0072301003f, -0.0117984513f}, + { 0.0061202077f, -0.0061202077f}, + {-0.0113771948f, -0.0069719540f}, + { 0.0038099540f, -0.0117258328f}, + {-0.0250242456f, -0.0019694508f}, + {-0.0057852169f, -0.0365264219f}, + {-0.0397097323f, 0.0164483097f}, + {-0.0888557186f, -0.1222994047f}, + { 0.0584625613f, -0.0684508645f}, + {-0.2420999907f, -0.1233561066f}, + { 0.1852947639f, -0.7718082372f}, + { 1.1225962793f, 0.0000000000f}, + { 0.2345396308f, 0.9769278702f}, + {-0.4747208072f, 0.2418823327f}, + {-0.0355007435f, -0.0415660302f}, + {-0.0909252334f, 0.1251478474f}, + {-0.0963790005f, -0.0399214891f}, + {-0.0013608847f, 0.0085922877f}, + {-0.0398532442f, 0.0031365183f}, + {-0.0012636128f, -0.0038890004f}, + {-0.0154904827f, 0.0094925800f}, + {-0.0016520262f, -0.0016520262f}, + {-0.0076634750f, 0.0125056546f}, + {-0.0072576065f, -0.0023581393f}, + {-0.0005089323f, 0.0064665981f}, + }, + { + {-0.0005223703f, -0.0066373443f}, /* Filter 13 */ + { 0.0000689315f, -0.0000223972f}, + {-0.0073145539f, -0.0119362671f}, + { 0.0058487082f, -0.0058487082f}, + {-0.0116890717f, -0.0071630723f}, + { 0.0036572876f, -0.0112559738f}, + {-0.0258487141f, -0.0020343379f}, + {-0.0056836493f, -0.0358851497f}, + {-0.0420195954f, 0.0174050863f}, + {-0.0895674434f, -0.1232790098f}, + { 0.0555971318f, -0.0650958776f}, + {-0.2512441154f, -0.1280152709f}, + { 0.1876588631f, -0.7816554194f}, + { 1.1250396727f, 0.0000000000f}, + { 0.2328630086f, 0.9699442360f}, + {-0.4647256838f, 0.2367895630f}, + {-0.0305655940f, -0.0357877124f}, + {-0.0915571420f, 0.1260175949f}, + {-0.0941059032f, -0.0389799414f}, + {-0.0016264798f, 0.0102691896f}, + {-0.0395167881f, 0.0031100387f}, + {-0.0010049855f, -0.0030930272f}, + {-0.0154845091f, 0.0094889194f}, + {-0.0012981133f, -0.0012981133f}, + {-0.0077169192f, 0.0125928676f}, + {-0.0069474841f, -0.0022573744f}, + {-0.0005223703f, 0.0066373443f}, + }, + { + {-0.0005352062f, -0.0068004397f}, /* Filter 14 */ + {-0.0002371416f, 0.0000770520f}, + {-0.0073938544f, -0.0120656738f}, + { 0.0055709463f, -0.0055709463f}, + {-0.0119912063f, -0.0073482207f}, + { 0.0034987353f, -0.0107680002f}, + {-0.0266618369f, -0.0020983321f}, + {-0.0055749551f, -0.0351988812f}, + {-0.0443450744f, 0.0183683312f}, + {-0.0902333798f, -0.1241955926f}, + { 0.0526394697f, -0.0616329003f}, + {-0.2604559819f, -0.1327089513f}, + { 0.1900016262f, -0.7914137299f}, + { 1.1272737104f, 0.0000000000f}, + { 0.2311486652f, 0.9628034819f}, + {-0.4547343588f, 0.2316987286f}, + {-0.0257149117f, -0.0301082932f}, + {-0.0921192046f, 0.1267912077f}, + {-0.0918121426f, -0.0380298346f}, + {-0.0018853566f, 0.0119036728f}, + {-0.0391495767f, 0.0030811385f}, + {-0.0007492498f, -0.0023059539f}, + {-0.0154623431f, 0.0094753361f}, + {-0.0009446795f, -0.0009446795f}, + {-0.0077638924f, 0.0126695210f}, + {-0.0066346301f, -0.0021557220f}, + {-0.0005352062f, 0.0068004397f}, + }, + { + {-0.0005474342f, -0.0069558110f}, /* Filter 15 */ + {-0.0005461525f, 0.0001774557f}, + {-0.0074678951f, -0.0121864973f}, + { 0.0052871211f, -0.0052871211f}, + {-0.0122832268f, -0.0075271711f}, + { 0.0033343726f, -0.0102621437f}, + {-0.0274627107f, -0.0021613622f}, + {-0.0054590979f, -0.0344673874f}, + {-0.0466847952f, 0.0193374753f}, + {-0.0908522954f, -0.1250474569f}, + { 0.0495894870f, -0.0580618293f}, + {-0.2697330596f, -0.1374358585f}, + { 0.1923222223f, -0.8010797080f}, + { 1.1292975460f, 0.0000000000f}, + { 0.2293972347f, 0.9555082489f}, + {-0.4447500311f, 0.2266114595f}, + {-0.0209494991f, -0.0245287119f}, + {-0.0926123259f, 0.1274699310f}, + {-0.0894995944f, -0.0370719458f}, + {-0.0021374375f, 0.0134952491f}, + {-0.0387524213f, 0.0030498817f}, + {-0.0004965997f, -0.0015283766f}, + {-0.0154241758f, 0.0094519471f}, + {-0.0005920390f, -0.0005920390f}, + {-0.0078044017f, 0.0127356261f}, + {-0.0063193305f, -0.0020532749f}, + {-0.0005474342f, 0.0069558110f}, + }, + { + {-0.0005590491f, -0.0071033921f}, /* Filter 16 */ + {-0.0008578611f, 0.0002787360f}, + {-0.0075365733f, -0.0122985698f}, + { 0.0049974389f, -0.0049974388f}, + {-0.0125647661f, -0.0076996986f}, + { 0.0031642806f, -0.0097386544f}, + {-0.0282504297f, -0.0022233570f}, + {-0.0053360461f, -0.0336904691f}, + {-0.0490373539f, 0.0203119370f}, + {-0.0914229663f, -0.1258329180f}, + { 0.0464471360f, -0.0543826090f}, + {-0.2790727745f, -0.1421946809f}, + { 0.1946198263f, -0.8106499175f}, + { 1.1311104123f, 0.0000000000f}, + { 0.2276093640f, 0.9480612314f}, + {-0.4347758804f, 0.2215293759f}, + {-0.0162701156f, -0.0190498578f}, + {-0.0930374331f, 0.1280550409f}, + {-0.0871701184f, -0.0361070452f}, + {-0.0023826511f, 0.0150434671f}, + {-0.0383261449f, 0.0030163330f}, + {-0.0002472237f, -0.0007608763f}, + {-0.0153702098f, 0.0094188767f}, + {-0.0002405024f, -0.0002405024f}, + {-0.0078384594f, 0.0127912031f}, + {-0.0060018711f, -0.0019501261f}, + {-0.0005590491f, 0.0071033921f}, + }, + { + {-0.0005700463f, -0.0072431248f}, /* Filter 17 */ + {-0.0011720231f, 0.0003808134f}, + {-0.0075997900f, -0.0124017301f}, + { 0.0047021127f, -0.0047021127f}, + {-0.0128354632f, -0.0078655819f}, + { 0.0029885467f, -0.0091978010f}, + {-0.0290240862f, -0.0022842451f}, + {-0.0052057731f, -0.0328679578f}, + {-0.0514013169f, 0.0212911226f}, + {-0.0919441775f, -0.1265503037f}, + { 0.0432124100f, -0.0505952315f}, + {-0.2884725105f, -0.1469840856f}, + { 0.1968936193f, -0.8201209469f}, + { 1.1327116219f, 0.0000000000f}, + { 0.2257857123f, 0.9404651753f}, + {-0.4248150656f, 0.2164540873f}, + {-0.0116774779f, -0.0136725700f}, + {-0.0933954755f, 0.1285478440f}, + {-0.0848255565f, -0.0351358959f}, + {-0.0026209319f, 0.0165479125f}, + {-0.0378715811f, 0.0029805581f}, + {-0.0000013054f, -0.0000040177f}, + {-0.0153006596f, 0.0093762563f}, + { 0.0001096232f, 0.0001096232f}, + {-0.0078660833f, 0.0128362814f}, + {-0.0056825374f, -0.0018463683f}, + {-0.0005700463f, 0.0072431248f}, + }, + { + {-0.0005804218f, -0.0073749578f}, /* Filter 18 */ + {-0.0014883899f, 0.0004836072f}, + {-0.0076574502f, -0.0124958231f}, + { 0.0044013628f, -0.0044013628f}, + {-0.0130949624f, -0.0080246033f}, + { 0.0028072639f, -0.0086398699f}, + {-0.0297827710f, -0.0023439549f}, + {-0.0050682571f, -0.0319997159f}, + {-0.0537752213f, 0.0222744260f}, + {-0.0924147241f, -0.1271979554f}, + { 0.0398853435f, -0.0466997371f}, + {-0.2979296109f, -0.1518027189f}, + { 0.1991427888f, -0.8294894121f}, + { 1.1341005677f, 0.0000000000f}, + { 0.2239269510f, 0.9327228772f}, + {-0.4148707237f, 0.2113871920f}, + {-0.0071722592f, -0.0083976366f}, + {-0.0936874236f, 0.1289496760f}, + {-0.0824677330f, -0.0341592535f}, + {-0.0028522199f, 0.0180082079f}, + {-0.0373895741f, 0.0029426233f}, + { 0.0002409767f, 0.0007416500f}, + {-0.0152157506f, 0.0093242240f}, + { 0.0004580348f, 0.0004580348f}, + {-0.0078872970f, 0.0128708989f}, + {-0.0053616143f, -0.0017420941f}, + {-0.0005804218f, 0.0073749578f}, + }, + { + {-0.0005901721f, -0.0074988473f}, /* Filter 19 */ + {-0.0018067093f, 0.0005870354f}, + {-0.0077094631f, -0.0125807004f}, + { 0.0040954155f, -0.0040954155f}, + {-0.0133429149f, -0.0081765487f}, + { 0.0026205314f, -0.0080651662f}, + {-0.0305255746f, -0.0024024148f}, + {-0.0049234813f, -0.0310856377f}, + {-0.0561575756f, 0.0232612294f}, + {-0.0928334114f, -0.1277742292f}, + { 0.0364660122f, -0.0426962145f}, + {-0.3074413786f, -0.1566492066f}, + { 0.2013665292f, -0.8387519577f}, + { 1.1352767227f, 0.0000000000f}, + { 0.2220337633f, 0.9248371830f}, + {-0.4049459681f, 0.2063302764f}, + {-0.0027550900f, -0.0032257959f}, + {-0.0939142683f, 0.1292619011f}, + {-0.0800984531f, -0.0331778656f}, + {-0.0030764613f, 0.0194240122f}, + {-0.0368809773f, 0.0029025959f}, + { 0.0004794497f, 0.0014755944f}, + {-0.0151157193f, 0.0092629247f}, + { 0.0008044337f, 0.0008044337f}, + {-0.0079021290f, 0.0128951026f}, + {-0.0050393858f, -0.0016373957f}, + {-0.0005901721f, 0.0074988473f}, + }, + { + {-0.0005992944f, -0.0076147568f}, /* Filter 20 */ + {-0.0021267251f, 0.0006910149f}, + {-0.0077557420f, -0.0126562207f}, + { 0.0037845040f, -0.0037845040f}, + {-0.0135789777f, -0.0083212083f}, + { 0.0024284540f, -0.0074740128f}, + {-0.0312515874f, -0.0024595533f}, + {-0.0047714341f, -0.0301256492f}, + {-0.0585468603f, 0.0242509035f}, + {-0.0931990565f, -0.1282774964f}, + { 0.0329545338f, -0.0385848015f}, + {-0.3170050775f, -0.1615221547f}, + { 0.2035640423f, -0.8479052583f}, + { 1.1362396407f, 0.0000000000f}, + { 0.2201068440f, 0.9168109865f}, + {-0.3950438879f, 0.2012849146f}, + { 0.0015734425f, 0.0018422645f}, + {-0.0940770209f, 0.1294859108f}, + {-0.0777195022f, -0.0321924719f}, + {-0.0032936077f, 0.0207950209f}, + {-0.0363466528f, 0.0028605436f}, + { 0.0007139459f, 0.0021972995f}, + {-0.0150008130f, 0.0091925101f}, + { 0.0011485255f, 0.0011485255f}, + {-0.0079106134f, 0.0129089479f}, + {-0.0047161348f, -0.0015323651f}, + {-0.0005992944f, 0.0076147568f}, + }, + { + {-0.0006077863f, -0.0077226571f}, /* Filter 21 */ + {-0.0024481778f, 0.0007954612f}, + {-0.0077962045f, -0.0127222494f}, + { 0.0034688681f, -0.0034688681f}, + {-0.0138028157f, -0.0084583763f}, + { 0.0022311426f, -0.0068667508f}, + {-0.0319599006f, -0.0025152987f}, + {-0.0046121088f, -0.0291197091f}, + {-0.0609415283f, 0.0252428075f}, + {-0.0935104881f, -0.1287061452f}, + { 0.0293510677f, -0.0343656849f}, + {-0.3266179339f, -0.1664201496f}, + { 0.2057345372f, -0.8569460203f}, + { 1.1369889562f, 0.0000000000f}, + { 0.2181468989f, 0.9086472276f}, + {-0.3851675459f, 0.1962526670f}, + { 0.0058127944f, 0.0068059078f}, + {-0.0941767115f, 0.1296231230f}, + {-0.0753326453f, -0.0312038034f}, + {-0.0035036167f, 0.0221209652f}, + {-0.0357874706f, 0.0028165350f}, + { 0.0009443030f, 0.0029062658f}, + {-0.0148712891f, 0.0091131377f}, + { 0.0014900206f, 0.0014900206f}, + {-0.0079127895f, 0.0129124989f}, + {-0.0043921429f, -0.0014270937f}, + {-0.0006077863f, 0.0077226571f}, + }, + { + {-0.0006156462f, -0.0078225266f}, /* Filter 22 */ + {-0.0027708045f, 0.0009002890f}, + {-0.0078307725f, -0.0127786593f}, + { 0.0031487534f, -0.0031487534f}, + {-0.0140141002f, -0.0085878517f}, + { 0.0020287139f, -0.0062437395f}, + {-0.0326496069f, -0.0025695798f}, + {-0.0044455042f, -0.0280678087f}, + {-0.0633400059f, 0.0262362895f}, + {-0.0937665479f, -0.1290585813f}, + { 0.0256558155f, -0.0300391005f}, + {-0.3362771370f, -0.1713417594f}, + { 0.2078772313f, -0.8658709834f}, + { 1.1375243848f, 0.0000000000f}, + { 0.2161546447f, 0.9003488919f}, + {-0.3753199780f, 0.1912350805f}, + { 0.0099624646f, 0.0116645474f}, + {-0.0942143887f, 0.1296749813f}, + {-0.0729396259f, -0.0302125823f}, + {-0.0037064513f, 0.0234016123f}, + {-0.0352043080f, 0.0027706391f}, + { 0.0011703644f, 0.0036020111f}, + {-0.0147274152f, 0.0090249716f}, + { 0.0018286340f, 0.0018286340f}, + {-0.0079087015f, 0.0129058279f}, + {-0.0040676902f, -0.0013216727f}, + {-0.0006156462f, 0.0078225266f}, + }, + { + {-0.0006228729f, -0.0079143505f}, /* Filter 23 */ + {-0.0030943393f, 0.0010054118f}, + {-0.0078593727f, -0.0128253306f}, + { 0.0028244120f, -0.0028244120f}, + {-0.0142125109f, -0.0087094379f}, + { 0.0018212906f, -0.0056053560f}, + {-0.0333198014f, -0.0026223252f}, + {-0.0042716241f, -0.0269699732f}, + {-0.0657406925f, 0.0272306864f}, + {-0.0939660909f, -0.1293332287f}, + { 0.0218690212f, -0.0256053340f}, + {-0.3459798404f, -0.1762855337f}, + { 0.2099913501f, -0.8746769223f}, + { 1.1378457233f, 0.0000000000f}, + { 0.2141308087f, 0.8919190081f}, + {-0.3655041913f, 0.1862336874f}, + { 0.0140219952f, 0.0164176470f}, + {-0.0941911192f, 0.1296429536f}, + {-0.0705421655f, -0.0292195216f}, + {-0.0039020802f, 0.0246367649f}, + {-0.0345980484f, 0.0027229255f}, + { 0.0013919788f, 0.0042840703f}, + {-0.0145694683f, 0.0089281816f}, + { 0.0021640858f, 0.0021640858f}, + {-0.0078983989f, 0.0128890156f}, + {-0.0037430549f, -0.0012161922f}, + {-0.0006228729f, 0.0079143505f}, + }, + { + {-0.0006294658f, -0.0079981214f}, /* Filter 24 */ + {-0.0034185133f, 0.0011107423f}, + {-0.0078819362f, -0.0128621510f}, + { 0.0024961016f, -0.0024961016f}, + {-0.0143977349f, -0.0088229433f}, + { 0.0016090008f, -0.0049519954f}, + {-0.0339695814f, -0.0026734640f}, + {-0.0040904779f, -0.0258262610f}, + {-0.0681419627f, 0.0282253251f}, + {-0.0941079866f, -0.1295285313f}, + { 0.0179909715f, -0.0210647211f}, + {-0.3557231633f, -0.1812500047f}, + { 0.2120761281f, -0.8833606476f}, + { 1.1379528497f, 0.0000000000f}, + { 0.2120761281f, 0.8833606476f}, + {-0.3557231633f, 0.1812500047f}, + { 0.0179909715f, 0.0210647211f}, + {-0.0941079866f, 0.1295285313f}, + {-0.0681419627f, -0.0282253251f}, + {-0.0040904779f, 0.0258262610f}, + {-0.0339695814f, 0.0026734640f}, + { 0.0016090008f, 0.0049519954f}, + {-0.0143977349f, 0.0088229433f}, + { 0.0024961016f, 0.0024961016f}, + {-0.0078819362f, 0.0128621510f}, + {-0.0034185133f, -0.0011107423f}, + {-0.0006294658f, 0.0079981214f}, + }, + { + {-0.0006354249f, -0.0080738393f}, /* Filter 25 */ + {-0.0037430549f, 0.0012161922f}, + {-0.0078983989f, -0.0128890156f}, + { 0.0021640858f, -0.0021640858f}, + {-0.0145694683f, -0.0089281816f}, + { 0.0013919788f, -0.0042840703f}, + {-0.0345980484f, -0.0027229255f}, + {-0.0039020802f, -0.0246367649f}, + {-0.0705421655f, 0.0292195216f}, + {-0.0941911192f, -0.1296429536f}, + { 0.0140219952f, -0.0164176470f}, + {-0.3655041913f, -0.1862336874f}, + { 0.2141308087f, -0.8919190081f}, + { 1.1378457233f, 0.0000000000f}, + { 0.2099913501f, 0.8746769223f}, + {-0.3459798404f, 0.1762855337f}, + { 0.0218690212f, 0.0256053340f}, + {-0.0939660909f, 0.1293332287f}, + {-0.0657406925f, -0.0272306864f}, + {-0.0042716241f, 0.0269699732f}, + {-0.0333198014f, 0.0026223252f}, + { 0.0018212906f, 0.0056053560f}, + {-0.0142125109f, 0.0087094379f}, + { 0.0028244120f, 0.0028244120f}, + {-0.0078593727f, 0.0128253306f}, + {-0.0030943393f, -0.0010054118f}, + {-0.0006354249f, 0.0080738393f}, + }, + { + {-0.0006407508f, -0.0081415109f}, /* Filter 26 */ + {-0.0040676902f, 0.0013216727f}, + {-0.0079087015f, -0.0129058279f}, + { 0.0018286340f, -0.0018286340f}, + {-0.0147274152f, -0.0090249716f}, + { 0.0011703644f, -0.0036020111f}, + {-0.0352043080f, -0.0027706391f}, + {-0.0037064513f, -0.0234016123f}, + {-0.0729396259f, 0.0302125823f}, + {-0.0942143887f, -0.1296749813f}, + { 0.0099624646f, -0.0116645474f}, + {-0.3753199780f, -0.1912350805f}, + { 0.2161546447f, -0.9003488919f}, + { 1.1375243848f, 0.0000000000f}, + { 0.2078772313f, 0.8658709834f}, + {-0.3362771370f, 0.1713417594f}, + { 0.0256558155f, 0.0300391005f}, + {-0.0937665479f, 0.1290585813f}, + {-0.0633400059f, -0.0262362895f}, + {-0.0044455042f, 0.0280678087f}, + {-0.0326496069f, 0.0025695798f}, + { 0.0020287139f, 0.0062437395f}, + {-0.0140141002f, 0.0085878517f}, + { 0.0031487534f, 0.0031487534f}, + {-0.0078307725f, 0.0127786593f}, + {-0.0027708045f, -0.0009002890f}, + {-0.0006407508f, 0.0081415109f}, + }, + { + {-0.0006454445f, -0.0082011502f}, /* Filter 27 */ + {-0.0043921429f, 0.0014270937f}, + {-0.0079127895f, -0.0129124989f}, + { 0.0014900206f, -0.0014900206f}, + {-0.0148712891f, -0.0091131377f}, + { 0.0009443030f, -0.0029062658f}, + {-0.0357874706f, -0.0028165350f}, + {-0.0035036167f, -0.0221209652f}, + {-0.0753326453f, 0.0312038034f}, + {-0.0941767115f, -0.1296231230f}, + { 0.0058127944f, -0.0068059078f}, + {-0.3851675459f, -0.1962526670f}, + { 0.2181468989f, -0.9086472276f}, + { 1.1369889562f, 0.0000000000f}, + { 0.2057345372f, 0.8569460203f}, + {-0.3266179339f, 0.1664201496f}, + { 0.0293510677f, 0.0343656849f}, + {-0.0935104881f, 0.1287061452f}, + {-0.0609415283f, -0.0252428075f}, + {-0.0046121088f, 0.0291197091f}, + {-0.0319599006f, 0.0025152987f}, + { 0.0022311426f, 0.0068667508f}, + {-0.0138028157f, 0.0084583763f}, + { 0.0034688681f, 0.0034688681f}, + {-0.0077962045f, 0.0127222494f}, + {-0.0024481778f, -0.0007954612f}, + {-0.0006454445f, 0.0082011502f}, + }, + { + {-0.0006495077f, -0.0082527783f}, /* Filter 28 */ + {-0.0047161348f, 0.0015323651f}, + {-0.0079106134f, -0.0129089479f}, + { 0.0011485255f, -0.0011485255f}, + {-0.0150008130f, -0.0091925101f}, + { 0.0007139459f, -0.0021972995f}, + {-0.0363466528f, -0.0028605436f}, + {-0.0032936077f, -0.0207950209f}, + {-0.0777195022f, 0.0321924719f}, + {-0.0940770209f, -0.1294859108f}, + { 0.0015734425f, -0.0018422645f}, + {-0.3950438879f, -0.2012849146f}, + { 0.2201068440f, -0.9168109865f}, + { 1.1362396407f, 0.0000000000f}, + { 0.2035640423f, 0.8479052583f}, + {-0.3170050775f, 0.1615221547f}, + { 0.0329545338f, 0.0385848015f}, + {-0.0931990565f, 0.1282774964f}, + {-0.0585468603f, -0.0242509035f}, + {-0.0047714341f, 0.0301256492f}, + {-0.0312515874f, 0.0024595533f}, + { 0.0024284540f, 0.0074740128f}, + {-0.0135789777f, 0.0083212083f}, + { 0.0037845040f, 0.0037845040f}, + {-0.0077557420f, 0.0126562207f}, + {-0.0021267251f, -0.0006910149f}, + {-0.0006495077f, 0.0082527783f}, + }, + { + {-0.0006529426f, -0.0082964229f}, /* Filter 29 */ + {-0.0050393858f, 0.0016373957f}, + {-0.0079021290f, -0.0128951026f}, + { 0.0008044337f, -0.0008044337f}, + {-0.0151157193f, -0.0092629247f}, + { 0.0004794497f, -0.0014755944f}, + {-0.0368809773f, -0.0029025959f}, + {-0.0030764613f, -0.0194240122f}, + {-0.0800984531f, 0.0331778656f}, + {-0.0939142683f, -0.1292619011f}, + {-0.0027550900f, 0.0032257959f}, + {-0.4049459681f, -0.2063302764f}, + { 0.2220337633f, -0.9248371830f}, + { 1.1352767227f, 0.0000000000f}, + { 0.2013665292f, 0.8387519577f}, + {-0.3074413786f, 0.1566492066f}, + { 0.0364660122f, 0.0426962145f}, + {-0.0928334114f, 0.1277742292f}, + {-0.0561575756f, -0.0232612294f}, + {-0.0049234813f, 0.0310856377f}, + {-0.0305255746f, 0.0024024148f}, + { 0.0026205314f, 0.0080651662f}, + {-0.0133429149f, 0.0081765487f}, + { 0.0040954155f, 0.0040954155f}, + {-0.0077094631f, 0.0125807004f}, + {-0.0018067093f, -0.0005870354f}, + {-0.0006529426f, 0.0082964229f}, + }, + { + {-0.0006557520f, -0.0083321188f}, /* Filter 30 */ + {-0.0053616143f, 0.0017420941f}, + {-0.0078872970f, -0.0128708989f}, + { 0.0004580348f, -0.0004580348f}, + {-0.0152157506f, -0.0093242240f}, + { 0.0002409767f, -0.0007416500f}, + {-0.0373895741f, -0.0029426233f}, + {-0.0028522199f, -0.0180082079f}, + {-0.0824677330f, 0.0341592535f}, + {-0.0936874236f, -0.1289496760f}, + {-0.0071722592f, 0.0083976366f}, + {-0.4148707237f, -0.2113871920f}, + { 0.2239269510f, -0.9327228772f}, + { 1.1341005677f, 0.0000000000f}, + { 0.1991427888f, 0.8294894121f}, + {-0.2979296109f, 0.1518027189f}, + { 0.0398853435f, 0.0466997371f}, + {-0.0924147241f, 0.1271979554f}, + {-0.0537752213f, -0.0222744260f}, + {-0.0050682571f, 0.0319997159f}, + {-0.0297827710f, 0.0023439549f}, + { 0.0028072639f, 0.0086398699f}, + {-0.0130949624f, 0.0080246033f}, + { 0.0044013628f, 0.0044013628f}, + {-0.0076574502f, 0.0124958231f}, + {-0.0014883899f, -0.0004836072f}, + {-0.0006557520f, 0.0083321188f}, + }, + { + {-0.0006579390f, -0.0083599075f}, /* Filter 31 */ + {-0.0056825374f, 0.0018463683f}, + {-0.0078660833f, -0.0128362814f}, + { 0.0001096232f, -0.0001096232f}, + {-0.0153006596f, -0.0093762563f}, + {-0.0000013054f, 0.0000040177f}, + {-0.0378715811f, -0.0029805581f}, + {-0.0026209319f, -0.0165479125f}, + {-0.0848255565f, 0.0351358959f}, + {-0.0933954755f, -0.1285478440f}, + {-0.0116774779f, 0.0136725700f}, + {-0.4248150656f, -0.2164540873f}, + { 0.2257857123f, -0.9404651753f}, + { 1.1327116219f, 0.0000000000f}, + { 0.1968936193f, 0.8201209469f}, + {-0.2884725105f, 0.1469840856f}, + { 0.0432124100f, 0.0505952315f}, + {-0.0919441775f, 0.1265503037f}, + {-0.0514013169f, -0.0212911226f}, + {-0.0052057731f, 0.0328679578f}, + {-0.0290240862f, 0.0022842451f}, + { 0.0029885467f, 0.0091978010f}, + {-0.0128354632f, 0.0078655819f}, + { 0.0047021127f, 0.0047021127f}, + {-0.0075997900f, 0.0124017301f}, + {-0.0011720231f, -0.0003808134f}, + {-0.0006579390f, 0.0083599075f}, + }, + { + {-0.0006595075f, -0.0083798372f}, /* Filter 32 */ + {-0.0060018711f, 0.0019501261f}, + {-0.0078384594f, -0.0127912031f}, + {-0.0002405024f, 0.0002405024f}, + {-0.0153702098f, -0.0094188767f}, + {-0.0002472237f, 0.0007608763f}, + {-0.0383261449f, -0.0030163330f}, + {-0.0023826511f, -0.0150434671f}, + {-0.0871701184f, 0.0361070452f}, + {-0.0930374331f, -0.1280550409f}, + {-0.0162701156f, 0.0190498578f}, + {-0.4347758804f, -0.2215293759f}, + { 0.2276093640f, -0.9480612314f}, + { 1.1311104123f, 0.0000000000f}, + { 0.1946198263f, 0.8106499175f}, + {-0.2790727745f, 0.1421946809f}, + { 0.0464471360f, 0.0543826090f}, + {-0.0914229663f, 0.1258329180f}, + {-0.0490373539f, -0.0203119370f}, + {-0.0053360461f, 0.0336904691f}, + {-0.0282504297f, 0.0022233570f}, + { 0.0031642806f, 0.0097386544f}, + {-0.0125647661f, 0.0076996986f}, + { 0.0049974389f, 0.0049974388f}, + {-0.0075365733f, 0.0122985698f}, + {-0.0008578611f, -0.0002787360f}, + {-0.0006595075f, 0.0083798372f}, + }, + { + {-0.0006604618f, -0.0083919627f}, /* Filter 33 */ + {-0.0063193305f, 0.0020532749f}, + {-0.0078044017f, -0.0127356261f}, + {-0.0005920390f, 0.0005920390f}, + {-0.0154241758f, -0.0094519471f}, + {-0.0004965997f, 0.0015283766f}, + {-0.0387524213f, -0.0030498817f}, + {-0.0021374375f, -0.0134952491f}, + {-0.0894995944f, 0.0370719458f}, + {-0.0926123259f, -0.1274699310f}, + {-0.0209494991f, 0.0245287119f}, + {-0.4447500311f, -0.2266114595f}, + { 0.2293972347f, -0.9555082489f}, + { 1.1292975460f, 0.0000000000f}, + { 0.1923222223f, 0.8010797080f}, + {-0.2697330596f, 0.1374358585f}, + { 0.0495894870f, 0.0580618293f}, + {-0.0908522954f, 0.1250474569f}, + {-0.0466847952f, -0.0193374753f}, + {-0.0054590979f, 0.0344673874f}, + {-0.0274627107f, 0.0021613622f}, + { 0.0033343726f, 0.0102621437f}, + {-0.0122832268f, 0.0075271711f}, + { 0.0052871211f, 0.0052871211f}, + {-0.0074678951f, 0.0121864973f}, + {-0.0005461525f, -0.0001774557f}, + {-0.0006604618f, 0.0083919627f}, + }, + { + {-0.0006608067f, -0.0083963451f}, /* Filter 34 */ + {-0.0066346301f, 0.0021557220f}, + {-0.0077638924f, -0.0126695210f}, + {-0.0009446795f, 0.0009446795f}, + {-0.0154623431f, -0.0094753361f}, + {-0.0007492498f, 0.0023059539f}, + {-0.0391495767f, -0.0030811385f}, + {-0.0018853566f, -0.0119036728f}, + {-0.0918121426f, 0.0380298346f}, + {-0.0921192046f, -0.1267912077f}, + {-0.0257149117f, 0.0301082932f}, + {-0.4547343588f, -0.2316987286f}, + { 0.2311486652f, -0.9628034819f}, + { 1.1272737104f, 0.0000000000f}, + { 0.1900016262f, 0.7914137299f}, + {-0.2604559819f, 0.1327089513f}, + { 0.0526394697f, 0.0616329003f}, + {-0.0902333798f, 0.1241955926f}, + {-0.0443450744f, -0.0183683312f}, + {-0.0055749551f, 0.0351988812f}, + {-0.0266618369f, 0.0020983321f}, + { 0.0034987353f, 0.0107680002f}, + {-0.0119912063f, 0.0073482207f}, + { 0.0055709463f, 0.0055709463f}, + {-0.0073938544f, 0.0120656738f}, + {-0.0002371416f, -0.0000770520f}, + {-0.0006608067f, 0.0083963451f}, + }, + { + {-0.0006605475f, -0.0083930522f}, /* Filter 35 */ + {-0.0069474841f, 0.0022573744f}, + {-0.0077169192f, -0.0125928676f}, + {-0.0012981133f, 0.0012981133f}, + {-0.0154845091f, -0.0094889194f}, + {-0.0010049855f, 0.0030930272f}, + {-0.0395167881f, -0.0031100387f}, + {-0.0016264798f, -0.0102691896f}, + {-0.0941059032f, 0.0389799414f}, + {-0.0915571420f, -0.1260175949f}, + {-0.0305655940f, 0.0357877124f}, + {-0.4647256838f, -0.2367895630f}, + { 0.2328630086f, -0.9699442360f}, + { 1.1250396727f, 0.0000000000f}, + { 0.1876588631f, 0.7816554194f}, + {-0.2512441154f, 0.1280152709f}, + { 0.0555971318f, 0.0650958776f}, + {-0.0895674434f, 0.1232790098f}, + {-0.0420195954f, -0.0174050863f}, + {-0.0056836493f, 0.0358851497f}, + {-0.0258487141f, 0.0020343379f}, + { 0.0036572876f, 0.0112559738f}, + {-0.0116890717f, 0.0071630723f}, + { 0.0058487082f, 0.0058487082f}, + {-0.0073145539f, 0.0119362671f}, + { 0.0000689315f, 0.0000223972f}, + {-0.0006605475f, 0.0083930522f}, + }, + { + {-0.0006596901f, -0.0083821579f}, /* Filter 36 */ + {-0.0072576065f, 0.0023581393f}, + {-0.0076634750f, -0.0125056546f}, + {-0.0016520262f, 0.0016520262f}, + {-0.0154904827f, -0.0094925800f}, + {-0.0012636128f, 0.0038890004f}, + {-0.0398532442f, -0.0031365183f}, + {-0.0013608847f, -0.0085922877f}, + {-0.0963790005f, 0.0399214891f}, + {-0.0909252334f, -0.1251478474f}, + {-0.0355007435f, 0.0415660302f}, + {-0.4747208072f, -0.2418823327f}, + { 0.2345396308f, -0.9769278702f}, + { 1.1225962793f, 0.0000000000f}, + { 0.1852947639f, 0.7718082372f}, + {-0.2420999907f, 0.1233561066f}, + { 0.0584625613f, 0.0684508645f}, + {-0.0888557186f, 0.1222994047f}, + {-0.0397097323f, -0.0164483097f}, + {-0.0057852169f, 0.0365264219f}, + {-0.0250242456f, 0.0019694508f}, + { 0.0038099540f, 0.0117258328f}, + {-0.0113771948f, 0.0069719540f}, + { 0.0061202077f, 0.0061202077f}, + {-0.0072301003f, 0.0117984513f}, + { 0.0003718310f, 0.0001208152f}, + {-0.0006596901f, 0.0083821579f}, + }, + { + {-0.0006582408f, -0.0083637423f}, /* Filter 37 */ + {-0.0075647115f, 0.0024579238f}, + {-0.0076035587f, -0.0124078801f}, + {-0.0020061005f, 0.0020061005f}, + {-0.0154800853f, -0.0094862085f}, + {-0.0015249332f, 0.0046932617f}, + {-0.0401581456f, -0.0031605146f}, + {-0.0010886543f, -0.0068734926f}, + {-0.0986295432f, 0.0408536944f}, + {-0.0902225974f, -0.1241807520f}, + {-0.0405195152f, 0.0474422567f}, + {-0.4847165122f, -0.2469753988f}, + { 0.2361779109f, -0.9837517978f}, + { 1.1199444556f, 0.0000000000f}, + { 0.1829101645f, 0.7618756659f}, + {-0.2330260947f, 0.1187327256f}, + { 0.0612358868f, 0.0716980115f}, + {-0.0880994453f, 0.1212584838f}, + {-0.0374168281f, -0.0154985577f}, + {-0.0058796987f, 0.0371229566f}, + {-0.0241893313f, 0.0019037417f}, + { 0.0039566651f, 0.0121773631f}, + {-0.0110559525f, 0.0067750964f}, + { 0.0063852527f, 0.0063852526f}, + {-0.0071406035f, 0.0116524059f}, + { 0.0006713257f, 0.0002181269f}, + {-0.0006582408f, 0.0083637423f}, + }, + { + {-0.0006562063f, -0.0083378917f}, /* Filter 38 */ + {-0.0078685137f, 0.0025566351f}, + {-0.0075371745f, -0.0122995509f}, + {-0.0023600156f, 0.0023600156f}, + {-0.0154531504f, -0.0094697028f}, + {-0.0017887430f, 0.0055051847f}, + {-0.0404307068f, -0.0031819656f}, + {-0.0008098779f, -0.0051133675f}, + {-0.1008556255f, 0.0417757679f}, + {-0.0894483767f, -0.1231151286f}, + {-0.0456210210f, 0.0534153526f}, + {-0.4947095655f, -0.2520671138f}, + { 0.2377772412f, -0.9904134878f}, + { 1.1170852055f, 0.0000000000f}, + { 0.1805059061f, 0.7518612089f}, + {-0.2240248692f, 0.1141463722f}, + { 0.0639172763f, 0.0748375152f}, + {-0.0872998705f, 0.1201579635f}, + {-0.0351421949f, -0.0145563737f}, + {-0.0059671403f, 0.0376750413f}, + {-0.0233448674f, 0.0018372809f}, + { 0.0040973574f, 0.0126103693f}, + {-0.0107257260f, 0.0065727333f}, + { 0.0066436583f, 0.0066436583f}, + {-0.0070461774f, 0.0114983165f}, + { 0.0009671895f, 0.0003142589f}, + {-0.0006562063f, 0.0083378917f}, + }, + { + {-0.0006535939f, -0.0083046980f}, /* Filter 39 */ + {-0.0081687281f, 0.0026541806f}, + {-0.0074643325f, -0.0121806836f}, + {-0.0027134480f, 0.0027134480f}, + {-0.0154095242f, -0.0094429686f}, + {-0.0020548339f, 0.0063241284f}, + {-0.0406701557f, -0.0032008107f}, + {-0.0005246505f, -0.0033125128f}, + {-0.1030553278f, 0.0426869144f}, + {-0.0886017384f, -0.1219498309f}, + {-0.0508043306f, 0.0594842284f}, + {-0.5046967186f, -0.2571558224f}, + { 0.2393370276f, -0.9969104659f}, + { 1.1140196110f, 0.0000000000f}, + { 0.1780828343f, 0.7417683886f}, + {-0.2150987105f, 0.1095982672f}, + { 0.0665069376f, 0.0778696190f}, + {-0.0864582472f, 0.1189995684f}, + {-0.0328871136f, -0.0136222885f}, + {-0.0060475918f, 0.0381829922f}, + {-0.0224917457f, 0.0017701388f}, + { 0.0042319732f, 0.0130246742f}, + {-0.0103869007f, 0.0063651009f}, + { 0.0068952472f, 0.0068952472f}, + {-0.0069469389f, 0.0113363740f}, + { 0.0012592008f, 0.0004091391f}, + {-0.0006535939f, 0.0083046980f}, + }, + { + {-0.0006504113f, -0.0082642593f}, /* Filter 40 */ + {-0.0084650709f, 0.0027504683f}, + {-0.0073850485f, -0.0120513039f}, + {-0.0030660718f, 0.0030660718f}, + {-0.0153490660f, -0.0094059197f}, + {-0.0023229930f, 0.0071494373f}, + {-0.0408757346f, -0.0032169901f}, + {-0.0002330732f, -0.0014715664f}, + {-0.1052267179f, 0.0435863337f}, + {-0.0876818748f, -0.1206837473f}, + {-0.0560684714f, 0.0656477454f}, + {-0.5146747091f, -0.2622398626f}, + { 0.2408566902f, -1.0032403162f}, + { 1.1107488316f, 0.0000000000f}, + { 0.1756417989f, 0.7316007446f}, + {-0.2062499680f, 0.1050896077f}, + { 0.0690051173f, 0.0807946117f}, + {-0.0855758340f, 0.1177850307f}, + {-0.0306528326f, -0.0126968190f}, + {-0.0061211077f, 0.0386471532f}, + {-0.0216308523f, 0.0017023850f}, + { 0.0043604608f, 0.0134201184f}, + {-0.0100398656f, 0.0061524375f}, + { 0.0071398493f, 0.0071398493f}, + {-0.0068430082f, 0.0111667745f}, + { 0.0015471436f, 0.0005026974f}, + {-0.0006504113f, 0.0082642593f}, + }, + { + {-0.0006466667f, -0.0082166790f}, /* Filter 41 */ + {-0.0087572594f, 0.0028454060f}, + {-0.0072993441f, -0.0119114470f}, + {-0.0034175587f, 0.0034175587f}, + {-0.0152716480f, -0.0093584780f}, + {-0.0025930028f, 0.0079804420f}, + {-0.0410467015f, -0.0032304455f}, + { 0.0000647469f, 0.0004087959f}, + {-0.1073678519f, 0.0444732204f}, + {-0.0866880040f, -0.1193158015f}, + {-0.0614124285f, 0.0719047153f}, + {-0.5246402627f, -0.2673175657f}, + { 0.2423356631f, -1.0094006816f}, + { 1.1072741035f, 0.0000000000f}, + { 0.1731836536f, 0.7213618325f}, + {-0.1974809435f, 0.1006215665f}, + { 0.0714121011f, 0.0836128276f}, + {-0.0846538939f, 0.1165160891f}, + {-0.0284405684f, -0.0117804691f}, + {-0.0061877467f, 0.0390678953f}, + {-0.0207630684f, 0.0016340889f}, + { 0.0044827743f, 0.0137965606f}, + {-0.0096850130f, 0.0059349836f}, + { 0.0073773020f, 0.0073773020f}, + {-0.0067345088f, 0.0109897195f}, + { 0.0018308065f, 0.0005948651f}, + {-0.0006466667f, 0.0082166790f}, + }, + { + {-0.0006423686f, -0.0081620664f}, /* Filter 42 */ + {-0.0090450120f, 0.0029389025f}, + {-0.0072072465f, -0.0117611574f}, + {-0.0037675783f, 0.0037675783f}, + {-0.0151771562f, -0.0093005733f}, + {-0.0028646414f, 0.0088164597f}, + {-0.0411823301f, -0.0032411197f}, + { 0.0003686970f, 0.0023278610f}, + {-0.1094767749f, 0.0453467649f}, + {-0.0856193708f, -0.1178449541f}, + {-0.0668351454f, 0.0782539010f}, + {-0.5345900940f, -0.2723872580f}, + { 0.2437733949f, -1.0153892656f}, + { 1.1035967397f, 0.0000000000f}, + { 0.1707092554f, 0.7110552220f}, + {-0.1887938905f, 0.0961952919f}, + { 0.0737282126f, 0.0863246457f}, + {-0.0836936943f, 0.1151944878f}, + {-0.0262515049f, -0.0108737293f}, + {-0.0062475719f, 0.0394456164f}, + {-0.0198892682f, 0.0015653194f}, + { 0.0045988736f, 0.0141538775f}, + {-0.0093227386f, 0.0057129815f}, + { 0.0076074506f, 0.0076074506f}, + {-0.0066215668f, 0.0108054149f}, + { 0.0021099840f, 0.0006855754f}, + {-0.0006423686f, 0.0081620664f}, + }, + { + {-0.0006375260f, -0.0081005359f}, /* Filter 43 */ + {-0.0093280490f, 0.0030308668f}, + {-0.0071087889f, -0.0116004892f}, + {-0.0041157984f, 0.0041157984f}, + {-0.0150654901f, -0.0092321442f}, + {-0.0031376826f, 0.0096567942f}, + {-0.0412819110f, -0.0032489569f}, + { 0.0006786580f, 0.0042848780f}, + {-0.1115515226f, 0.0462061535f}, + {-0.0844752467f, -0.1162702023f}, + {-0.0723355236f, 0.0846940164f}, + {-0.5445209082f, -0.2774472605f}, + { 0.2451693490f, -1.0212038328f}, + { 1.0997181284f, 0.0000000000f}, + { 0.1682194641f, 0.7006844950f}, + {-0.1801910135f, 0.0918119071f}, + { 0.0759538132f, 0.0889304892f}, + {-0.0826965057f, 0.1138219754f}, + {-0.0240867927f, -0.0099770762f}, + {-0.0063006503f, 0.0397807405f}, + {-0.0190103194f, 0.0014961446f}, + { 0.0047087245f, 0.0144919637f}, + {-0.0089534403f, 0.0054866753f}, + { 0.0078301476f, 0.0078301476f}, + {-0.0065043116f, 0.0106140718f}, + { 0.0023844759f, 0.0007747632f}, + {-0.0006375260f, 0.0081005359f}, + }, + { + {-0.0006321484f, -0.0080322075f}, /* Filter 44 */ + {-0.0096060925f, 0.0031212087f}, + {-0.0070040103f, -0.0114295060f}, + {-0.0044618854f, 0.0044618854f}, + {-0.0149365628f, -0.0091531374f}, + {-0.0034118961f, 0.0105007365f}, + {-0.0413447525f, -0.0032539026f}, + { 0.0009945051f, 0.0062790582f}, + {-0.1135901216f, 0.0470505689f}, + {-0.0832549311f, -0.1145905820f}, + {-0.0779124236f, 0.0912237273f}, + {-0.5544294025f, -0.2824958906f}, + { 0.2465230038f, -1.0268422107f}, + { 1.0956397332f, 0.0000000000f}, + { 0.1657151424f, 0.6902532446f}, + {-0.1716744668f, 0.0874725099f}, + { 0.0780893017f, 0.0914308250f}, + {-0.0816636012f, 0.1124003042f}, + {-0.0219475497f, -0.0090909727f}, + {-0.0063470532f, 0.0400737166f}, + {-0.0181270820f, 0.0014266323f}, + { 0.0048122983f, 0.0148107313f}, + {-0.0085775184f, 0.0052563101f}, + { 0.0080452535f, 0.0080452535f}, + {-0.0063828750f, 0.0104159053f}, + { 0.0026540877f, 0.0008623654f}, + {-0.0006321484f, 0.0080322075f}, + }, + { + {-0.0006262457f, -0.0079572062f}, /* Filter 45 */ + {-0.0098788669f, 0.0032098384f}, + {-0.0068929555f, -0.0112482810f}, + {-0.0048055043f, 0.0048055043f}, + {-0.0147903020f, -0.0090635087f}, + {-0.0036870475f, 0.0113475654f}, + {-0.0413701808f, -0.0032559039f}, + { 0.0013161074f, 0.0083095754f}, + {-0.1155905906f, 0.0478791903f}, + {-0.0819577515f, -0.1128051674f}, + {-0.0835646644f, 0.0978416511f}, + {-0.5643122679f, -0.2875314620f}, + { 0.2478338529f, -1.0323022902f}, + { 1.0913630919f, 0.0000000000f}, + { 0.1631971552f, 0.6797650728f}, + {-0.1632463544f, 0.0831781721f}, + { 0.0801351139f, 0.0938261634f}, + {-0.0805962556f, 0.1109312291f}, + {-0.0198348595f, -0.0082158678f}, + {-0.0063868556f, 0.0403250190f}, + {-0.0172404079f, 0.0013568495f}, + { 0.0049095725f, 0.0151101104f}, + {-0.0081953754f, 0.0050221325f}, + { 0.0082526365f, 0.0082526365f}, + {-0.0062573914f, 0.0102111348f}, + { 0.0029186307f, 0.0009483206f}, + {-0.0006262457f, 0.0079572062f}, + }, + { + {-0.0006198280f, -0.0078756618f}, /* Filter 46 */ + {-0.0101460989f, 0.0032966674f}, + {-0.0067756751f, -0.0110568969f}, + {-0.0051463192f, 0.0051463192f}, + {-0.0146266493f, -0.0089632222f}, + {-0.0039628985f, 0.0121965475f}, + {-0.0413575411f, -0.0032549091f}, + { 0.0016433282f, 0.0103755662f}, + {-0.1175509420f, 0.0486911944f}, + {-0.0805830641f, -0.1109130726f}, + {-0.0892910248f, 0.1045463576f}, + {-0.5741661901f, -0.2925522861f}, + { 0.2491014054f, -1.0375820265f}, + { 1.0868898157f, 0.0000000000f}, + { 0.1606663689f, 0.6692235895f}, + {-0.1549087286f, 0.0789299396f}, + { 0.0820917217f, 0.0961170567f}, + {-0.0794957450f, 0.1094165063f}, + {-0.0177497724f, -0.0073521965f}, + {-0.0064201364f, 0.0405351459f}, + {-0.0163511406f, 0.0012868627f}, + { 0.0050005298f, 0.0153900482f}, + {-0.0078074148f, 0.0047843899f}, + { 0.0084521727f, 0.0084521727f}, + {-0.0061279979f, 0.0099999837f}, + { 0.0031779221f, 0.0010325695f}, + {-0.0006198280f, 0.0078756618f}, + }, + { + {-0.0006129060f, -0.0077877091f}, /* Filter 47 */ + {-0.0104075179f, 0.0033816075f}, + {-0.0066522258f, -0.0108554460f}, + {-0.0054839934f, 0.0054839934f}, + {-0.0144455612f, -0.0088522513f}, + {-0.0042392071f, 0.0130469379f}, + {-0.0413061980f, -0.0032508683f}, + { 0.0019760247f, 0.0124761291f}, + {-0.1194691818f, 0.0494857553f}, + {-0.0791302548f, -0.1089134521f}, + {-0.0950902426f, 0.1113363693f}, + {-0.5839878512f, -0.2975566724f}, + { 0.2503251863f, -1.0426794408f}, + { 1.0822215889f, 0.0000000000f}, + { 0.1581236518f, 0.6586324102f}, + {-0.1466635902f, 0.0747288317f}, + { 0.0839596331f, 0.0983041000f}, + {-0.0783633460f, 0.1078578927f}, + {-0.0156933045f, -0.0065003796f}, + {-0.0064469783f, 0.0407046190f}, + {-0.0154601145f, 0.0012167374f}, + { 0.0050851588f, 0.0156505094f}, + {-0.0074140419f, 0.0045433307f}, + { 0.0086437458f, 0.0086437458f}, + {-0.0059948336f, 0.0097826794f}, + { 0.0034317849f, 0.0011150545f}, + {-0.0006129060f, 0.0077877091f}, + }, +}; + +/* Coefficients for the band edge symbol timing synchroniser */ +#define SYNC_LOW_BAND_EDGE_COEFF_0 1.829281f /* 2*alpha*cos(low_edge) */ +#define SYNC_LOW_BAND_EDGE_COEFF_1 -0.980100f /* -alpha^2 */ +#define SYNC_HIGH_BAND_EDGE_COEFF_0 -1.285907f /* 2*alpha*cos(high_edge) */ +#define SYNC_HIGH_BAND_EDGE_COEFF_1 -0.980100f /* -alpha^2 */ +#define SYNC_CROSS_CORR_COEFF_A -0.932131f /* -alpha^2*sin(freq_diff) */ +#define SYNC_CROSS_CORR_COEFF_B 0.752802f /* alpha*sin(high_edge) */ +#define SYNC_CROSS_CORR_COEFF_C -0.378857f /* -alpha*sin(low_edge) */ + +float v29_rx_carrier_frequency(v29_rx_state_t *s) +{ + return dds_frequencyf(s->carrier_phase_rate); +} +/*- End of function --------------------------------------------------------*/ + +float v29_rx_symbol_timing_correction(v29_rx_state_t *s) +{ + return (float) s->total_baud_timing_correction/((float) PULSESHAPER_COEFF_SETS*10.0f/3.0f); +} +/*- End of function --------------------------------------------------------*/ + +void v29_rx_signal_cutoff(v29_rx_state_t *s, float cutoff) +{ + /* The 0.4 factor allows for the gain of the DC blocker */ + s->carrier_on_power = (int32_t) (power_meter_level_dbm0(cutoff + 2.5f)*0.4f); + s->carrier_off_power = (int32_t) (power_meter_level_dbm0(cutoff - 2.5f)*0.4f); +} +/*- End of function --------------------------------------------------------*/ + +float v29_rx_signal_power(v29_rx_state_t *s) +{ + return power_meter_dbm0(&s->power); +} +/*- End of function --------------------------------------------------------*/ + +int v29_rx_equalizer_state(v29_rx_state_t *s, complexf_t **coeffs) +{ + *coeffs = s->eq_coeff; + return V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN; +} +/*- End of function --------------------------------------------------------*/ + +static void equalizer_save(v29_rx_state_t *s) +{ + cvec_copyf(s->eq_coeff_save, s->eq_coeff, V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN); +} +/*- End of function --------------------------------------------------------*/ + +static void equalizer_restore(v29_rx_state_t *s) +{ + cvec_copyf(s->eq_coeff, s->eq_coeff_save, V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN); + cvec_zerof(s->eq_buf, V29_EQUALIZER_MASK); + + s->eq_put_step = PULSESHAPER_COEFF_SETS*10/(3*2) - 1; + s->eq_step = 0; + s->eq_delta = EQUALIZER_DELTA/(V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN); +} +/*- End of function --------------------------------------------------------*/ + +static void equalizer_reset(v29_rx_state_t *s) +{ + /* Start with an equalizer based on everything being perfect */ + cvec_zerof(s->eq_coeff, V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN); + s->eq_coeff[V29_EQUALIZER_PRE_LEN] = complex_setf(3.0f, 0.0f); + cvec_zerof(s->eq_buf, V29_EQUALIZER_MASK); + + s->eq_put_step = PULSESHAPER_COEFF_SETS*10/(3*2) - 1; + s->eq_step = 0; + s->eq_delta = EQUALIZER_DELTA/(V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN); +} +/*- End of function --------------------------------------------------------*/ + +static __inline__ complexf_t equalizer_get(v29_rx_state_t *s) +{ + int i; + int p; + complexf_t z; + complexf_t z1; + + /* Get the next equalized value. */ + z = complex_setf(0.0f, 0.0f); + p = s->eq_step - 1; + for (i = 0; i < V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN; i++) + { + p = (p - 1) & V29_EQUALIZER_MASK; + z1 = complex_mulf(&s->eq_coeff[i], &s->eq_buf[p]); + z = complex_addf(&z, &z1); + } + return z; +} +/*- End of function --------------------------------------------------------*/ + +static void tune_equalizer(v29_rx_state_t *s, const complexf_t *z, const complexf_t *target) +{ + int i; + int p; + complexf_t ez; + complexf_t z1; + + /* Find the x and y mismatch from the exact constellation position. */ + ez = complex_subf(target, z); + ez.re *= s->eq_delta; + ez.im *= s->eq_delta; + + p = s->eq_step - 1; + for (i = 0; i < V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN; i++) + { + p = (p - 1) & V29_EQUALIZER_MASK; + z1 = complex_conjf(&s->eq_buf[p]); + z1 = complex_mulf(&ez, &z1); + s->eq_coeff[i] = complex_addf(&s->eq_coeff[i], &z1); + /* Leak a little to tame uncontrolled wandering */ + s->eq_coeff[i].re *= 0.9999f; + s->eq_coeff[i].im *= 0.9999f; + } +} +/*- End of function --------------------------------------------------------*/ + +static int scrambled_training_bit(v29_rx_state_t *s) +{ + int bit; + + /* Segment 3 of the training sequence - the scrambled CDCD part. */ + /* Apply the 1 + x^-6 + x^-7 scrambler */ + bit = s->training_scramble_reg & 1; + s->training_scramble_reg >>= 1; + if (bit ^ (s->training_scramble_reg & 1)) + s->training_scramble_reg |= 0x40; + return bit; +} +/*- End of function --------------------------------------------------------*/ + +static __inline__ int find_quadrant(const complexf_t *z) +{ + int b1; + int b2; + + /* Split the space along the two diagonals. */ + b1 = (z->im > z->re); + b2 = (z->im < -z->re); + return (b2 << 1) | (b1 ^ b2); +} +/*- End of function --------------------------------------------------------*/ + +static __inline__ void track_carrier(v29_rx_state_t *s, const complexf_t *z, const complexf_t *target) +{ + float error; + + /* The initial coarse carrier frequency and phase estimation should have + got us in the right ballpark. Now we need to fine tune fairly quickly, + to get the receovered carrier more precisely on target. Then we need to + fine tune in a more damped way to keep us on target. The goal is to have + things running really well by the time the training is complete. + We assume the frequency of the oscillators at the two ends drift only + very slowly. The PSTN has rather limited doppler problems. :-) Any + remaining FDM in the network should also drift slowly. */ + /* For small errors the imaginary part of the difference between the actual and the target + positions is proportional to the phase error, for any particular target. However, the + different amplitudes of the various target positions scale things. This isn't all bad, + as the angular error for the larger amplitude constellation points is probably + a more reliable indicator, and we are weighting it as such. */ + error = z->im*target->re - z->re*target->im; + + /* Use a proportional-integral approach to tracking the carrier. The PI + parameters are coarser at first, until we get precisely on target. Then, + the filter will be damped more to keep us on target. */ + s->carrier_phase_rate += (int32_t) (s->carrier_track_i*error); + s->carrier_phase += (int32_t) (s->carrier_track_p*error); + //span_log(&s->logging, SPAN_LOG_FLOW, "Im = %15.5f f = %15.5f\n", error, dds_frequencyf(s->carrier_phase_rate)); +} +/*- End of function --------------------------------------------------------*/ + +static __inline__ void put_bit(v29_rx_state_t *s, int bit) +{ + int out_bit; + + bit &= 1; + + /* Descramble the bit */ + out_bit = (bit ^ (s->scramble_reg >> 17) ^ (s->scramble_reg >> 22)) & 1; + s->scramble_reg = (s->scramble_reg << 1) | bit; + + /* We need to strip the last part of the training - the test period of all 1s - + before we let data go to the application. */ + if (s->in_training == TRAINING_STAGE_NORMAL_OPERATION) + { + s->put_bit(s->user_data, out_bit); + } + else + { + //span_log(&s->logging, SPAN_LOG_FLOW, "bit %5d %d\n", s->training_cd, out_bit); + /* The bits during the final stage of training should be all ones. However, + buggy modems mean you cannot rely on this. Therefore we don't bother + testing for ones, but just rely on a constellation mismatch measurement. */ + } +} +/*- End of function --------------------------------------------------------*/ + +static void decode_baud(v29_rx_state_t *s, complexf_t *z) +{ + static const uint8_t phase_steps_9600[8] = + { + 4, 0, 2, 6, 7, 3, 1, 5 + }; + static const uint8_t phase_steps_4800[4] = + { + 0, 2, 3, 1 + }; + int nearest; + int raw_bits; + int i; + int re; + int im; + + switch (s->bit_rate) + { + case 9600: + default: + re = (int) ((z->re + 5.0f)*2.0f); + if (re > 19) + re = 19; + else if (re < 0) + re = 0; + im = (int) ((z->im + 5.0f)*2.0f); + if (im > 19) + im = 19; + else if (im < 0) + im = 0; + nearest = space_map_9600[re][im]; + /* Deal with the amplitude bit */ + put_bit(s, nearest >> 3); + raw_bits = phase_steps_9600[(nearest - s->constellation_state) & 7]; + for (i = 0; i < 3; i++) + { + put_bit(s, raw_bits); + raw_bits >>= 1; + } + break; + case 7200: + /* We can reuse the space map for 9600, but drop the top bit */ + re = (int) ((z->re + 5.0f)*2.0f); + if (re > 19) + re = 19; + else if (re < 0) + re = 0; + im = (int) ((z->im + 5.0f)*2.0f); + if (im > 19) + im = 19; + else if (im < 0) + im = 0; + nearest = space_map_9600[re][im] & 7; + raw_bits = phase_steps_9600[(nearest - s->constellation_state) & 7]; + for (i = 0; i < 3; i++) + { + put_bit(s, raw_bits); + raw_bits >>= 1; + } + break; + case 4800: + nearest = find_quadrant(z) << 1; + raw_bits = phase_steps_4800[((nearest - s->constellation_state) >> 1) & 3]; + put_bit(s, raw_bits); + put_bit(s, raw_bits >> 1); + break; + } + track_carrier(s, z, &v29_constellation[nearest]); + if (--s->eq_skip <= 0) + { + /* Once we are in the data the equalization should not need updating. + However, the line characteristics may slowly drift. We, therefore, + tune up on the occassional sample, keeping the compute down. */ + s->eq_skip = 10; + tune_equalizer(s, z, &v29_constellation[nearest]); + } + s->constellation_state = nearest; +} +/*- End of function --------------------------------------------------------*/ + +static void process_half_baud(v29_rx_state_t *s, complexf_t *sample) +{ + static const int cdcd_pos[6] = + { + 0, 11, + 0, 3, + 0, 2 + }; + complexf_t z; + complexf_t zz; + const complexf_t *target; + float v; + float p; + int bit; + int i; + int j; + int32_t angle; + int32_t ang; + + /* This routine processes every half a baud, as we put things into the equalizer at the T/2 rate. + This routine adapts the position of the half baud samples, which the caller takes. */ + + /* Add a sample to the equalizer's circular buffer, but don't calculate anything + at this time. */ + s->eq_buf[s->eq_step] = *sample; + s->eq_step = (s->eq_step + 1) & V29_EQUALIZER_MASK; + + /* On alternate insertions we have a whole baud, and must process it. */ + if ((s->baud_half ^= 1)) + return; + + /* Symbol timing synchronisation */ + /* Cross correlate */ + v = s->symbol_sync_low[1]*s->symbol_sync_high[1]*SYNC_CROSS_CORR_COEFF_A + + s->symbol_sync_low[0]*s->symbol_sync_high[1]*SYNC_CROSS_CORR_COEFF_B + + s->symbol_sync_low[1]*s->symbol_sync_high[0]*SYNC_CROSS_CORR_COEFF_C; + + /* Filter away any DC component */ + p = v - s->symbol_sync_dc_filter[1]; + s->symbol_sync_dc_filter[1] = s->symbol_sync_dc_filter[0]; + s->symbol_sync_dc_filter[0] = v; + /* A little integration will now filter away much of the noise */ + s->baud_phase -= p; + + i = 0; + if (s->baud_phase > 1000.0f) + i = 5; + else if (s->baud_phase < -1000.0f) + i = -5; + else if (s->baud_phase > 100.0f) + i = 1; + else if (s->baud_phase < -100.0f) + i = -1; + + //printf("v = %10.5f %5d - %f %f %d %d\n", v, i, p, s->baud_phase, s->total_baud_timing_correction); + + if (i) + { + s->eq_put_step += i; + s->total_baud_timing_correction += i; + } + + z = equalizer_get(s); + + switch (s->in_training) + { + case TRAINING_STAGE_NORMAL_OPERATION: + /* Normal operation. */ + decode_baud(s, &z); + target = &v29_constellation[s->constellation_state]; + break; + case TRAINING_STAGE_SYMBOL_ACQUISITION: + /* Allow time for symbol synchronisation to settle the symbol timing. */ + target = &z; + if (++s->training_count >= 60) + { + /* Record the current phase angle */ + s->in_training = TRAINING_STAGE_LOG_PHASE; + s->angles[0] = + s->start_angles[0] = arctan2(z.im, z.re); + } + break; + case TRAINING_STAGE_LOG_PHASE: + /* Record the current alternate phase angle */ + target = &z; + s->angles[1] = + s->start_angles[1] = arctan2(z.im, z.re); + s->training_count = 1; + s->in_training = TRAINING_STAGE_WAIT_FOR_CDCD; + break; + case TRAINING_STAGE_WAIT_FOR_CDCD: + target = &z; + angle = arctan2(z.im, z.re); + /* Look for the initial ABAB sequence to display a phase reversal, which will + signal the start of the scrambled CDCD segment */ + ang = angle - s->angles[(s->training_count - 1) & 0xF]; + s->angles[(s->training_count + 1) & 0xF] = angle; + if ((ang > 0x20000000 || ang < -0x20000000) && s->training_count >= 13) + { + /* We seem to have a phase reversal */ + /* Slam the carrier frequency into line, based on the total phase drift over the last + section. Use the shift from the odd bits and the shift from the even bits to get + better jitter suppression. We need to scale here, or at the maximum specified + frequency deviation we could overflow, and get a silly answer. */ + /* Step back a few symbols so we don't get ISI distorting things. */ + i = (s->training_count - 8) & ~1; + /* Avoid the possibility of a divide by zero */ + if (i) + { + j = i & 0xF; + ang = (s->angles[j] - s->start_angles[0])/i + + (s->angles[j | 0x1] - s->start_angles[1])/i; + s->carrier_phase_rate += 3*(ang/20); + } + span_log(&s->logging, SPAN_LOG_FLOW, "Coarse carrier frequency %7.2f\n", dds_frequencyf(s->carrier_phase_rate)); + /* Check if the carrier frequency is plausible */ + if (s->carrier_phase_rate < dds_phase_ratef(CARRIER_NOMINAL_FREQ - 20.0f) + || + s->carrier_phase_rate > dds_phase_ratef(CARRIER_NOMINAL_FREQ + 20.0f)) + { + span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (sequence failed)\n"); + /* Park this modem */ + s->in_training = TRAINING_STAGE_PARKED; + s->put_bit(s->user_data, PUTBIT_TRAINING_FAILED); + break; + } + /* Make a step shift in the phase, to pull it into line. We need to rotate the equalizer + buffer, as well as the carrier phase, for this to play out nicely. */ + p = angle*2.0f*3.14159f/(65536.0f*65536.0f); + zz = complex_setf(cosf(p), -sinf(p)); + for (i = 0; i <= V29_EQUALIZER_MASK; i++) + s->eq_buf[i] = complex_mulf(&s->eq_buf[i], &zz); + s->carrier_phase += angle; + /* We have just seen the first bit of the scrambled sequence, so skip it. */ + bit = scrambled_training_bit(s); + s->training_count = 1; + s->in_training = TRAINING_STAGE_TRAIN_ON_CDCD; + break; + } + if (++s->training_count > V29_TRAINING_SEG_2_LEN) + { + /* This is bogus. There are not this many bauds in this section + of a real training sequence. */ + span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (sequence failed)\n"); + /* Park this modem */ + s->in_training = TRAINING_STAGE_PARKED; + s->put_bit(s->user_data, PUTBIT_TRAINING_FAILED); + } + break; + case TRAINING_STAGE_TRAIN_ON_CDCD: + /* Train on the scrambled CDCD section. */ + bit = scrambled_training_bit(s); + //span_log(&s->logging, SPAN_LOG_FLOW, "%5d %15.5f, %15.5f %15.5f, %15.5f\n", s->training_count, z.re, z.im, v29_constellation[cdcd_pos[s->training_cd + bit]].re, v29_constellation[cdcd_pos[s->training_cd + bit]].im); + s->constellation_state = cdcd_pos[s->training_cd + bit]; + target = &v29_constellation[s->constellation_state]; + track_carrier(s, &z, target); + tune_equalizer(s, &z, target); + if (++s->training_count >= V29_TRAINING_SEG_3_LEN - 48) + { + s->in_training = TRAINING_STAGE_TRAIN_ON_CDCD_AND_TEST; + s->training_error = 0.0f; + s->carrier_track_i = 200.0f; + s->carrier_track_p = 1000000.0f; + } + break; + case TRAINING_STAGE_TRAIN_ON_CDCD_AND_TEST: + /* Continue training on the scrambled CDCD section, but measure the quality of training too. */ + bit = scrambled_training_bit(s); + //span_log(&s->logging, SPAN_LOG_FLOW, "%5d %15.5f, %15.5f %15.5f, %15.5f\n", s->training_count, z.re, z.im, v29_constellation[cdcd_pos[s->training_cd + bit]].re, v29_constellation[cdcd_pos[s->training_cd + bit]].im); + s->constellation_state = cdcd_pos[s->training_cd + bit]; + target = &v29_constellation[s->constellation_state]; + track_carrier(s, &z, target); + tune_equalizer(s, &z, target); + /* Measure the training error */ + zz = complex_subf(&z, target); + s->training_error += powerf(&zz); + if (++s->training_count >= V29_TRAINING_SEG_3_LEN) + { + span_log(&s->logging, SPAN_LOG_FLOW, "Constellation mismatch %f\n", s->training_error); + if (s->training_error < 100.0f) + { + s->training_count = 0; + s->training_cd = 0; + s->training_error = 0.0f; + s->constellation_state = 0; + s->in_training = TRAINING_STAGE_TEST_ONES; + } + else + { + span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (convergence failed)\n"); + /* Park this modem */ + s->in_training = TRAINING_STAGE_PARKED; + s->put_bit(s->user_data, PUTBIT_TRAINING_FAILED); + } + } + break; + case TRAINING_STAGE_TEST_ONES: + /* We are in the test phase, where we check that we can receive reliably. + We should get a run of 1's, 48 symbols (192 bits at 9600bps) long. */ + //span_log(&s->logging, SPAN_LOG_FLOW, "%5d %15.5f, %15.5f\n", s->training_count, z.re, z.im); + decode_baud(s, &z); + target = &v29_constellation[s->constellation_state]; + /* Measure the training error */ + zz = complex_subf(&z, target); + s->training_error += powerf(&zz); + if (++s->training_count >= V29_TRAINING_SEG_4_LEN) + { + if (s->training_error < 50.0f) + { + /* We are up and running */ + span_log(&s->logging, SPAN_LOG_FLOW, "Training succeeded (constellation mismatch %f)\n", s->training_error); + s->put_bit(s->user_data, PUTBIT_TRAINING_SUCCEEDED); + /* Apply some lag to the carrier off condition, to ensure the last few bits get pushed through + the processing. */ + s->carrier_present = 60; + s->in_training = TRAINING_STAGE_NORMAL_OPERATION; + equalizer_save(s); + s->carrier_phase_rate_save = s->carrier_phase_rate; + s->agc_scaling_save = s->agc_scaling; + } + else + { + /* Training has failed */ + span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (constellation mismatch %f)\n", s->training_error); + /* Park this modem */ + s->put_bit(s->user_data, PUTBIT_TRAINING_FAILED); + s->in_training = TRAINING_STAGE_PARKED; + } + } + break; + case TRAINING_STAGE_PARKED: + default: + /* We failed to train! */ + /* Park here until the carrier drops. */ + target = &z; + break; + } + if (s->qam_report) + s->qam_report(s->qam_user_data, &z, target, s->constellation_state); +} +/*- End of function --------------------------------------------------------*/ + +int v29_rx(v29_rx_state_t *s, const int16_t amp[], int len) +{ + int i; + int j; + int step; + complexf_t z; + complexf_t zz; + complexf_t sample; + int32_t power; + float v; + + for (i = 0; i < len; i++) + { + s->rrc_filter[s->rrc_filter_step] = + s->rrc_filter[s->rrc_filter_step + V29_RX_FILTER_STEPS] = amp[i]; + if (++s->rrc_filter_step >= V29_RX_FILTER_STEPS) + s->rrc_filter_step = 0; + + /* There should be no DC in the signal, but sometimes there is. + We need to measure the power with the DC blocked, but not using + a slow to respond DC blocker. Use the most elementary HPF. */ + power = power_meter_update(&(s->power), (amp[i] - s->last_sample) >> 1); + s->last_sample = amp[i]; + if (s->carrier_present) + { + /* Look for power below turn-off threshold to turn the carrier off */ + if (power < s->carrier_off_power) + { + if (--s->carrier_present <= 0) + { + /* Count down a short delay, to ensure we push the last + few bits through the filters before stopping. */ + v29_rx_restart(s, s->bit_rate, FALSE); + s->put_bit(s->user_data, PUTBIT_CARRIER_DOWN); + continue; + } + } + } + else + { + /* Look for power exceeding turn-on threshold to turn the carrier on */ + if (power < s->carrier_on_power) + continue; + s->carrier_present = 1; + s->put_bit(s->user_data, PUTBIT_CARRIER_UP); + } + if (s->in_training != TRAINING_STAGE_PARKED) + { + /* Only spend effort processing this data if the modem is not + parked, after training failure. */ + s->eq_put_step -= PULSESHAPER_COEFF_SETS; + step = -s->eq_put_step; + if (step > PULSESHAPER_COEFF_SETS - 1) + step = PULSESHAPER_COEFF_SETS - 1; + if (step < 0) + step += PULSESHAPER_COEFF_SETS; + zz.re = pulseshaper[step][0].re*s->rrc_filter[s->rrc_filter_step]; + for (j = 1; j < V29_RX_FILTER_STEPS; j++) + zz.re += pulseshaper[step][j].re*s->rrc_filter[j + s->rrc_filter_step]; + sample.re = zz.re*s->agc_scaling; + + /* Symbol timing synchronisation band edge filters */ + /* Low Nyquist band edge filter */ + v = s->symbol_sync_low[0]*SYNC_LOW_BAND_EDGE_COEFF_0 + s->symbol_sync_low[1]*SYNC_LOW_BAND_EDGE_COEFF_1 + sample.re; + s->symbol_sync_low[1] = s->symbol_sync_low[0]; + s->symbol_sync_low[0] = v; + /* High Nyquist band edge filter */ + v = s->symbol_sync_high[0]*SYNC_HIGH_BAND_EDGE_COEFF_0 + s->symbol_sync_high[1]*SYNC_HIGH_BAND_EDGE_COEFF_1 + sample.re; + s->symbol_sync_high[1] = s->symbol_sync_high[0]; + s->symbol_sync_high[0] = v; + + z = dds_complexf(&(s->carrier_phase), s->carrier_phase_rate); + + /* Put things into the equalization buffer at T/2 rate. The symbol synchronisation + will fiddle the step to align this with the symbols. */ + if (s->eq_put_step <= 0) + { + if (s->in_training == TRAINING_STAGE_SYMBOL_ACQUISITION) + { + /* Only AGC during the initial training */ + s->agc_scaling = (1.0f/PULSESHAPER_GAIN)*5.0f*0.72f/sqrtf(power); + } + /* Pulse shape while still at the carrier frequency, using a quadrature + pair of filters. This results in a properly bandpass filtered complex + signal, which can be brought directly to bandband by complex mixing. + No further filtering, to remove mixer harmonics, is needed. */ + step = -s->eq_put_step; + if (step > PULSESHAPER_COEFF_SETS - 1) + step = PULSESHAPER_COEFF_SETS - 1; + zz.im = pulseshaper[step][0].im*s->rrc_filter[s->rrc_filter_step]; + for (j = 1; j < V29_RX_FILTER_STEPS; j++) + zz.im += pulseshaper[step][j].im*s->rrc_filter[j + s->rrc_filter_step]; + sample.re = zz.re*s->agc_scaling; + sample.im = zz.im*s->agc_scaling; + s->eq_put_step += PULSESHAPER_COEFF_SETS*10/(3*2); + /* Shift to baseband - since this is done in a full complex form, the + result is clean, and requires no further filtering, apart from the + equalizer. */ + zz.re = sample.re*z.re - sample.im*z.im; + zz.im = -sample.re*z.im - sample.im*z.re; + process_half_baud(s, &zz); + } + } + } + return 0; +} +/*- End of function --------------------------------------------------------*/ + +void v29_rx_set_put_bit(v29_rx_state_t *s, put_bit_func_t put_bit, void *user_data) +{ + s->put_bit = put_bit; + s->user_data = user_data; +} +/*- End of function --------------------------------------------------------*/ + +int v29_rx_restart(v29_rx_state_t *s, int rate, int old_train) +{ + switch (rate) + { + case 9600: + s->training_cd = 0; + break; + case 7200: + s->training_cd = 2; + break; + case 4800: + s->training_cd = 4; + break; + default: + return -1; + } + s->bit_rate = rate; + + vec_zerof(s->rrc_filter, sizeof(s->rrc_filter)/sizeof(s->rrc_filter[0])); + s->rrc_filter_step = 0; + + s->scramble_reg = 0; + s->training_scramble_reg = 0x2A; + s->in_training = TRAINING_STAGE_SYMBOL_ACQUISITION; + s->training_count = 0; + s->carrier_present = 0; + s->old_train = old_train; + + s->carrier_phase = 0; + s->carrier_track_i = 8000.0f; + s->carrier_track_p = 8000000.0f; + + power_meter_init(&(s->power), 4); + + s->constellation_state = 0; + + if (s->old_train) + { + s->carrier_phase_rate = s->carrier_phase_rate_save; + s->agc_scaling = s->agc_scaling_save; + equalizer_restore(s); + } + else + { + s->carrier_phase_rate = dds_phase_ratef(CARRIER_NOMINAL_FREQ); + s->agc_scaling = 0.0005f; + equalizer_reset(s); + } + s->eq_skip = 0; + s->last_sample = 0; + + /* Initialise the working data for symbol timing synchronisation */ + s->symbol_sync_low[0] = 0.0f; + s->symbol_sync_low[1] = 0.0f; + s->symbol_sync_high[0] = 0.0f; + s->symbol_sync_high[1] = 0.0f; + s->symbol_sync_dc_filter[0] = 0.0f; + s->symbol_sync_dc_filter[1] = 0.0f; + s->baud_phase = 0.0f; + s->baud_half = 0; + + s->total_baud_timing_correction = 0; + + return 0; +} +/*- End of function --------------------------------------------------------*/ + +v29_rx_state_t *v29_rx_init(v29_rx_state_t *s, int rate, put_bit_func_t put_bit, void *user_data) +{ + if (s == NULL) + { + if ((s = (v29_rx_state_t *) malloc(sizeof(*s))) == NULL) + return NULL; + } + + memset(s, 0, sizeof(*s)); + s->put_bit = put_bit; + s->user_data = user_data; + /* The V.29 spec says the thresholds should be -31dBm and -26dBm, but that makes little + sense. V.17 uses -48dBm and -43dBm, and there seems no good reason to cut off at a + higher level (though at 9600bps and 7200bps, TCM should put V.17 sensitivity several + dB ahead of V.29). */ + /* The thresholds should be on at -26dBm0 and off at -31dBm0 */ + v29_rx_signal_cutoff(s, -28.5f); + span_log_init(&s->logging, SPAN_LOG_NONE, NULL); + span_log_set_protocol(&s->logging, "V.29"); + + v29_rx_restart(s, rate, FALSE); + return s; +} +/*- End of function --------------------------------------------------------*/ + +int v29_rx_release(v29_rx_state_t *s) +{ + free(s); + return 0; +} +/*- End of function --------------------------------------------------------*/ + +void v29_rx_set_qam_report_handler(v29_rx_state_t *s, qam_report_handler_t *handler, void *user_data) +{ + s->qam_report = handler; + s->qam_user_data = user_data; +} +/*- End of function --------------------------------------------------------*/ +/*- End of file ------------------------------------------------------------*/