forked from Mirrors/freeswitch
469 lines
9.8 KiB
C
469 lines
9.8 KiB
C
/*
|
|
* SpanDSP - a series of DSP components for telephony
|
|
*
|
|
* dds.c
|
|
*
|
|
* 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 Lesser General Public License version 2.1,
|
|
* 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 Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
/*! \file */
|
|
|
|
#if defined(HAVE_CONFIG_H)
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <inttypes.h>
|
|
#if defined(HAVE_TGMATH_H)
|
|
#include <tgmath.h>
|
|
#endif
|
|
#if defined(HAVE_MATH_H)
|
|
#include <math.h>
|
|
#endif
|
|
#include "floating_fudge.h"
|
|
|
|
#include "spandsp/telephony.h"
|
|
#include "spandsp/complex.h"
|
|
#include "spandsp/dds.h"
|
|
|
|
/* In a A-law or u-law channel, a fairly coarse step sine table is adequate to keep the spectral
|
|
mess due to the DDS at a similar level to the spectral mess due to the A-law or u-law
|
|
compression. */
|
|
#define SLENK 8
|
|
#define DDS_STEPS (1 << SLENK)
|
|
#define DDS_SHIFT (32 - 2 - SLENK)
|
|
|
|
/* This is a simple set of direct digital synthesis (DDS) functions to generate sine
|
|
waves. This version uses a 256 entry sin/cos table to cover one quadrant. */
|
|
|
|
static const int16_t sine_table[DDS_STEPS + 1] =
|
|
{
|
|
0,
|
|
201,
|
|
402,
|
|
603,
|
|
804,
|
|
1005,
|
|
1206,
|
|
1407,
|
|
1608,
|
|
1809,
|
|
2009,
|
|
2210,
|
|
2410,
|
|
2611,
|
|
2811,
|
|
3012,
|
|
3212,
|
|
3412,
|
|
3612,
|
|
3811,
|
|
4011,
|
|
4210,
|
|
4410,
|
|
4609,
|
|
4808,
|
|
5007,
|
|
5205,
|
|
5404,
|
|
5602,
|
|
5800,
|
|
5998,
|
|
6195,
|
|
6393,
|
|
6590,
|
|
6786,
|
|
6983,
|
|
7179,
|
|
7375,
|
|
7571,
|
|
7767,
|
|
7962,
|
|
8157,
|
|
8351,
|
|
8545,
|
|
8739,
|
|
8933,
|
|
9126,
|
|
9319,
|
|
9512,
|
|
9704,
|
|
9896,
|
|
10087,
|
|
10278,
|
|
10469,
|
|
10659,
|
|
10849,
|
|
11039,
|
|
11228,
|
|
11417,
|
|
11605,
|
|
11793,
|
|
11980,
|
|
12167,
|
|
12353,
|
|
12539,
|
|
12725,
|
|
12910,
|
|
13094,
|
|
13279,
|
|
13462,
|
|
13645,
|
|
13828,
|
|
14010,
|
|
14191,
|
|
14372,
|
|
14553,
|
|
14732,
|
|
14912,
|
|
15090,
|
|
15269,
|
|
15446,
|
|
15623,
|
|
15800,
|
|
15976,
|
|
16151,
|
|
16325,
|
|
16499,
|
|
16673,
|
|
16846,
|
|
17018,
|
|
17189,
|
|
17360,
|
|
17530,
|
|
17700,
|
|
17869,
|
|
18037,
|
|
18204,
|
|
18371,
|
|
18537,
|
|
18703,
|
|
18868,
|
|
19032,
|
|
19195,
|
|
19357,
|
|
19519,
|
|
19680,
|
|
19841,
|
|
20000,
|
|
20159,
|
|
20317,
|
|
20475,
|
|
20631,
|
|
20787,
|
|
20942,
|
|
21096,
|
|
21250,
|
|
21403,
|
|
21554,
|
|
21705,
|
|
21856,
|
|
22005,
|
|
22154,
|
|
22301,
|
|
22448,
|
|
22594,
|
|
22739,
|
|
22884,
|
|
23027,
|
|
23170,
|
|
23311,
|
|
23452,
|
|
23592,
|
|
23731,
|
|
23870,
|
|
24007,
|
|
24143,
|
|
24279,
|
|
24413,
|
|
24547,
|
|
24680,
|
|
24811,
|
|
24942,
|
|
25072,
|
|
25201,
|
|
25329,
|
|
25456,
|
|
25582,
|
|
25708,
|
|
25832,
|
|
25955,
|
|
26077,
|
|
26198,
|
|
26319,
|
|
26438,
|
|
26556,
|
|
26674,
|
|
26790,
|
|
26905,
|
|
27019,
|
|
27133,
|
|
27245,
|
|
27356,
|
|
27466,
|
|
27575,
|
|
27683,
|
|
27790,
|
|
27896,
|
|
28001,
|
|
28105,
|
|
28208,
|
|
28310,
|
|
28411,
|
|
28510,
|
|
28609,
|
|
28706,
|
|
28803,
|
|
28898,
|
|
28992,
|
|
29085,
|
|
29177,
|
|
29268,
|
|
29358,
|
|
29447,
|
|
29534,
|
|
29621,
|
|
29706,
|
|
29791,
|
|
29874,
|
|
29956,
|
|
30037,
|
|
30117,
|
|
30195,
|
|
30273,
|
|
30349,
|
|
30424,
|
|
30498,
|
|
30571,
|
|
30643,
|
|
30714,
|
|
30783,
|
|
30852,
|
|
30919,
|
|
30985,
|
|
31050,
|
|
31113,
|
|
31176,
|
|
31237,
|
|
31297,
|
|
31356,
|
|
31414,
|
|
31470,
|
|
31526,
|
|
31580,
|
|
31633,
|
|
31685,
|
|
31736,
|
|
31785,
|
|
31833,
|
|
31880,
|
|
31926,
|
|
31971,
|
|
32014,
|
|
32057,
|
|
32098,
|
|
32137,
|
|
32176,
|
|
32213,
|
|
32250,
|
|
32285,
|
|
32318,
|
|
32351,
|
|
32382,
|
|
32412,
|
|
32441,
|
|
32469,
|
|
32495,
|
|
32521,
|
|
32545,
|
|
32567,
|
|
32589,
|
|
32609,
|
|
32628,
|
|
32646,
|
|
32663,
|
|
32678,
|
|
32692,
|
|
32705,
|
|
32717,
|
|
32728,
|
|
32737,
|
|
32745,
|
|
32752,
|
|
32757,
|
|
32761,
|
|
32765,
|
|
32766,
|
|
32767
|
|
};
|
|
|
|
SPAN_DECLARE(int32_t) dds_phase_rate(float frequency)
|
|
{
|
|
return (int32_t) (frequency*65536.0f*65536.0f/SAMPLE_RATE);
|
|
}
|
|
/*- End of function --------------------------------------------------------*/
|
|
|
|
SPAN_DECLARE(float) dds_frequency(int32_t phase_rate)
|
|
{
|
|
return (float) phase_rate*(float) SAMPLE_RATE/(65536.0f*65536.0f);
|
|
}
|
|
/*- End of function --------------------------------------------------------*/
|
|
|
|
SPAN_DECLARE(int16_t) dds_scaling_dbm0(float level)
|
|
{
|
|
return (int16_t) (powf(10.0f, (level - DBM0_MAX_SINE_POWER)/20.0f)*32767.0f);
|
|
}
|
|
/*- End of function --------------------------------------------------------*/
|
|
|
|
SPAN_DECLARE(int16_t) dds_scaling_dbov(float level)
|
|
{
|
|
return (int16_t) (powf(10.0f, (level - DBOV_MAX_SINE_POWER)/20.0f)*32767.0f);
|
|
}
|
|
/*- End of function --------------------------------------------------------*/
|
|
|
|
SPAN_DECLARE(int16_t) dds_lookup(uint32_t phase)
|
|
{
|
|
uint32_t step;
|
|
int16_t amp;
|
|
|
|
phase >>= DDS_SHIFT;
|
|
step = phase & (DDS_STEPS - 1);
|
|
if ((phase & DDS_STEPS))
|
|
step = DDS_STEPS - step;
|
|
amp = sine_table[step];
|
|
if ((phase & (2*DDS_STEPS)))
|
|
amp = -amp;
|
|
return amp;
|
|
}
|
|
/*- End of function --------------------------------------------------------*/
|
|
|
|
SPAN_DECLARE(int16_t) dds_offset(uint32_t phase_acc, int32_t phase_offset)
|
|
{
|
|
return dds_lookup(phase_acc + phase_offset);
|
|
}
|
|
/*- End of function --------------------------------------------------------*/
|
|
|
|
SPAN_DECLARE(void) dds_advance(uint32_t *phase_acc, int32_t phase_rate)
|
|
{
|
|
*phase_acc += phase_rate;
|
|
}
|
|
/*- End of function --------------------------------------------------------*/
|
|
|
|
SPAN_DECLARE(int16_t) dds(uint32_t *phase_acc, int32_t phase_rate)
|
|
{
|
|
int16_t amp;
|
|
|
|
amp = dds_lookup(*phase_acc);
|
|
*phase_acc += phase_rate;
|
|
return amp;
|
|
}
|
|
/*- End of function --------------------------------------------------------*/
|
|
|
|
SPAN_DECLARE(int16_t) dds_mod(uint32_t *phase_acc, int32_t phase_rate, int16_t scale, int32_t phase)
|
|
{
|
|
int16_t amp;
|
|
|
|
amp = (int16_t) (((int32_t) dds_lookup(*phase_acc + phase)*scale) >> 15);
|
|
*phase_acc += phase_rate;
|
|
return amp;
|
|
}
|
|
/*- End of function --------------------------------------------------------*/
|
|
|
|
SPAN_DECLARE(complexi_t) dds_lookup_complexi(uint32_t phase)
|
|
{
|
|
return complex_seti(dds_lookup(phase + (1 << 30)), dds_lookup(phase));
|
|
}
|
|
/*- End of function --------------------------------------------------------*/
|
|
|
|
SPAN_DECLARE(complexi_t) dds_complexi(uint32_t *phase_acc, int32_t phase_rate)
|
|
{
|
|
complexi_t amp;
|
|
|
|
amp = complex_seti(dds_lookup(*phase_acc + (1 << 30)), dds_lookup(*phase_acc));
|
|
*phase_acc += phase_rate;
|
|
return amp;
|
|
}
|
|
/*- End of function --------------------------------------------------------*/
|
|
|
|
SPAN_DECLARE(complexi_t) dds_complexi_mod(uint32_t *phase_acc, int32_t phase_rate, int16_t scale, int32_t phase)
|
|
{
|
|
complexi_t amp;
|
|
|
|
amp = complex_seti(((int32_t) dds_lookup(*phase_acc + phase + (1 << 30))*scale) >> 15,
|
|
((int32_t) dds_lookup(*phase_acc + phase)*scale) >> 15);
|
|
*phase_acc += phase_rate;
|
|
return amp;
|
|
}
|
|
/*- End of function --------------------------------------------------------*/
|
|
|
|
SPAN_DECLARE(complexi16_t) dds_lookup_complexi16(uint32_t phase)
|
|
{
|
|
return complex_seti16(dds_lookup(phase + (1 << 30)), dds_lookup(phase));
|
|
}
|
|
/*- End of function --------------------------------------------------------*/
|
|
|
|
SPAN_DECLARE(complexi16_t) dds_complexi16(uint32_t *phase_acc, int32_t phase_rate)
|
|
{
|
|
complexi16_t amp;
|
|
|
|
amp = complex_seti16(dds_lookup(*phase_acc + (1 << 30)), dds_lookup(*phase_acc));
|
|
*phase_acc += phase_rate;
|
|
return amp;
|
|
}
|
|
/*- End of function --------------------------------------------------------*/
|
|
|
|
SPAN_DECLARE(complexi16_t) dds_complexi16_mod(uint32_t *phase_acc, int32_t phase_rate, int16_t scale, int32_t phase)
|
|
{
|
|
complexi16_t amp;
|
|
|
|
amp = complex_seti16((int16_t) (((int32_t) dds_lookup(*phase_acc + phase + (1 << 30))*scale) >> 15),
|
|
(int16_t) (((int32_t) dds_lookup(*phase_acc + phase)*scale) >> 15));
|
|
*phase_acc += phase_rate;
|
|
return amp;
|
|
}
|
|
/*- End of function --------------------------------------------------------*/
|
|
|
|
SPAN_DECLARE(complexi32_t) dds_lookup_complexi32(uint32_t phase)
|
|
{
|
|
return complex_seti32(dds_lookup(phase + (1 << 30)), dds_lookup(phase));
|
|
}
|
|
/*- End of function --------------------------------------------------------*/
|
|
|
|
SPAN_DECLARE(complexi32_t) dds_complexi32(uint32_t *phase_acc, int32_t phase_rate)
|
|
{
|
|
complexi32_t amp;
|
|
|
|
amp = complex_seti32(dds_lookup(*phase_acc + (1 << 30)), dds_lookup(*phase_acc));
|
|
*phase_acc += phase_rate;
|
|
return amp;
|
|
}
|
|
/*- End of function --------------------------------------------------------*/
|
|
|
|
SPAN_DECLARE(complexi32_t) dds_complexi32_mod(uint32_t *phase_acc, int32_t phase_rate, int16_t scale, int32_t phase)
|
|
{
|
|
complexi32_t amp;
|
|
|
|
amp = complex_seti32(((int32_t) dds_lookup(*phase_acc + phase + (1 << 30))*scale) >> 15,
|
|
((int32_t) dds_lookup(*phase_acc + phase)*scale) >> 15);
|
|
*phase_acc += phase_rate;
|
|
return amp;
|
|
}
|
|
/*- End of function --------------------------------------------------------*/
|
|
/*- End of file ------------------------------------------------------------*/
|