2008-09-03 15:02:00 -04:00
|
|
|
/*
|
|
|
|
* 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)
|
2009-01-27 23:48:03 -05:00
|
|
|
#include "config.h"
|
2008-09-03 15:02:00 -04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <inttypes.h>
|
|
|
|
#if defined(HAVE_TGMATH_H)
|
|
|
|
#include <tgmath.h>
|
|
|
|
#endif
|
|
|
|
#if defined(HAVE_MATH_H)
|
|
|
|
#include <math.h>
|
|
|
|
#endif
|
2009-01-27 23:48:03 -05:00
|
|
|
#include "floating_fudge.h"
|
2008-09-03 15:02:00 -04:00
|
|
|
|
|
|
|
#include "spandsp/telephony.h"
|
|
|
|
#include "spandsp/complex.h"
|
|
|
|
#include "spandsp/dds.h"
|
|
|
|
|
|
|
|
/* In a A-law or u-law channel, a 128 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 7
|
|
|
|
#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 128 entry sin/cos table to cover one quadrant. */
|
|
|
|
|
2011-07-02 02:45:27 -04:00
|
|
|
static const int16_t sine_table[DDS_STEPS + 1] =
|
2008-09-03 15:02:00 -04:00
|
|
|
{
|
|
|
|
201,
|
|
|
|
603,
|
|
|
|
1005,
|
|
|
|
1407,
|
|
|
|
1809,
|
|
|
|
2210,
|
|
|
|
2611,
|
|
|
|
3012,
|
|
|
|
3412,
|
|
|
|
3812,
|
|
|
|
4211,
|
|
|
|
4609,
|
|
|
|
5007,
|
|
|
|
5404,
|
|
|
|
5800,
|
|
|
|
6195,
|
|
|
|
6590,
|
|
|
|
6983,
|
|
|
|
7376,
|
|
|
|
7767,
|
|
|
|
8157,
|
|
|
|
8546,
|
|
|
|
8933,
|
|
|
|
9319,
|
|
|
|
9704,
|
|
|
|
10088,
|
|
|
|
10469,
|
|
|
|
10850,
|
|
|
|
11228,
|
|
|
|
11605,
|
|
|
|
11980,
|
|
|
|
12354,
|
|
|
|
12725,
|
|
|
|
13095,
|
|
|
|
13463,
|
|
|
|
13828,
|
|
|
|
14192,
|
|
|
|
14553,
|
|
|
|
14912,
|
|
|
|
15269,
|
|
|
|
15624,
|
|
|
|
15976,
|
|
|
|
16326,
|
|
|
|
16673,
|
|
|
|
17018,
|
|
|
|
17361,
|
|
|
|
17700,
|
|
|
|
18037,
|
|
|
|
18372,
|
|
|
|
18703,
|
|
|
|
19032,
|
|
|
|
19358,
|
|
|
|
19681,
|
|
|
|
20001,
|
|
|
|
20318,
|
|
|
|
20632,
|
|
|
|
20943,
|
|
|
|
21251,
|
|
|
|
21555,
|
|
|
|
21856,
|
|
|
|
22154,
|
|
|
|
22449,
|
|
|
|
22740,
|
|
|
|
23028,
|
|
|
|
23312,
|
|
|
|
23593,
|
|
|
|
23870,
|
|
|
|
24144,
|
|
|
|
24414,
|
|
|
|
24680,
|
|
|
|
24943,
|
|
|
|
25202,
|
|
|
|
25457,
|
|
|
|
25708,
|
|
|
|
25956,
|
|
|
|
26199,
|
|
|
|
26439,
|
|
|
|
26674,
|
|
|
|
26906,
|
|
|
|
27133,
|
|
|
|
27357,
|
|
|
|
27576,
|
|
|
|
27791,
|
|
|
|
28002,
|
|
|
|
28209,
|
|
|
|
28411,
|
|
|
|
28610,
|
|
|
|
28803,
|
|
|
|
28993,
|
|
|
|
29178,
|
|
|
|
29359,
|
|
|
|
29535,
|
|
|
|
29707,
|
|
|
|
29875,
|
|
|
|
30038,
|
|
|
|
30196,
|
|
|
|
30350,
|
|
|
|
30499,
|
|
|
|
30644,
|
|
|
|
30784,
|
|
|
|
30920,
|
|
|
|
31050,
|
|
|
|
31177,
|
|
|
|
31298,
|
|
|
|
31415,
|
|
|
|
31527,
|
|
|
|
31634,
|
|
|
|
31737,
|
|
|
|
31834,
|
|
|
|
31927,
|
|
|
|
32015,
|
|
|
|
32099,
|
|
|
|
32177,
|
|
|
|
32251,
|
|
|
|
32319,
|
|
|
|
32383,
|
|
|
|
32442,
|
|
|
|
32496,
|
|
|
|
32546,
|
|
|
|
32590,
|
|
|
|
32629,
|
|
|
|
32664,
|
|
|
|
32693,
|
|
|
|
32718,
|
|
|
|
32738,
|
|
|
|
32753,
|
|
|
|
32762,
|
|
|
|
32767,
|
2011-07-02 02:45:27 -04:00
|
|
|
32767
|
2008-09-03 15:02:00 -04:00
|
|
|
};
|
|
|
|
|
2009-02-02 16:36:29 -05:00
|
|
|
SPAN_DECLARE(int32_t) dds_phase_rate(float frequency)
|
2008-09-03 15:02:00 -04:00
|
|
|
{
|
|
|
|
return (int32_t) (frequency*65536.0f*65536.0f/SAMPLE_RATE);
|
|
|
|
}
|
|
|
|
/*- End of function --------------------------------------------------------*/
|
|
|
|
|
2009-02-02 16:36:29 -05:00
|
|
|
SPAN_DECLARE(float) dds_frequency(int32_t phase_rate)
|
2008-09-03 15:02:00 -04:00
|
|
|
{
|
|
|
|
return (float) phase_rate*(float) SAMPLE_RATE/(65536.0f*65536.0f);
|
|
|
|
}
|
|
|
|
/*- End of function --------------------------------------------------------*/
|
|
|
|
|
2009-02-02 16:36:29 -05:00
|
|
|
SPAN_DECLARE(int16_t) dds_scaling_dbm0(float level)
|
2008-09-03 15:02:00 -04:00
|
|
|
{
|
2009-01-28 23:00:33 -05:00
|
|
|
return (int16_t) (powf(10.0f, (level - DBM0_MAX_SINE_POWER)/20.0f)*32767.0f);
|
2008-09-03 15:02:00 -04:00
|
|
|
}
|
|
|
|
/*- End of function --------------------------------------------------------*/
|
|
|
|
|
2009-02-02 16:36:29 -05:00
|
|
|
SPAN_DECLARE(int16_t) dds_scaling_dbov(float level)
|
2008-09-03 15:02:00 -04:00
|
|
|
{
|
2009-01-28 23:00:33 -05:00
|
|
|
return (int16_t) (powf(10.0f, (level - DBOV_MAX_SINE_POWER)/20.0f)*32767.0f);
|
2008-09-03 15:02:00 -04:00
|
|
|
}
|
|
|
|
/*- End of function --------------------------------------------------------*/
|
|
|
|
|
2009-02-02 16:36:29 -05:00
|
|
|
SPAN_DECLARE(int16_t) dds_lookup(uint32_t phase)
|
2008-09-03 15:02:00 -04:00
|
|
|
{
|
|
|
|
uint32_t step;
|
|
|
|
int16_t amp;
|
|
|
|
|
|
|
|
phase >>= DDS_SHIFT;
|
|
|
|
step = phase & (DDS_STEPS - 1);
|
|
|
|
if ((phase & DDS_STEPS))
|
2011-07-02 02:45:27 -04:00
|
|
|
step = DDS_STEPS - step;
|
2008-09-03 15:02:00 -04:00
|
|
|
amp = sine_table[step];
|
|
|
|
if ((phase & (2*DDS_STEPS)))
|
|
|
|
amp = -amp;
|
|
|
|
return amp;
|
|
|
|
}
|
|
|
|
/*- End of function --------------------------------------------------------*/
|
|
|
|
|
2009-02-02 16:36:29 -05:00
|
|
|
SPAN_DECLARE(int16_t) dds_offset(uint32_t phase_acc, int32_t phase_offset)
|
2008-09-03 15:02:00 -04:00
|
|
|
{
|
|
|
|
return dds_lookup(phase_acc + phase_offset);
|
|
|
|
}
|
|
|
|
/*- End of function --------------------------------------------------------*/
|
|
|
|
|
2009-02-02 16:36:29 -05:00
|
|
|
SPAN_DECLARE(void) dds_advance(uint32_t *phase_acc, int32_t phase_rate)
|
2008-09-03 15:02:00 -04:00
|
|
|
{
|
|
|
|
*phase_acc += phase_rate;
|
|
|
|
}
|
|
|
|
/*- End of function --------------------------------------------------------*/
|
|
|
|
|
2009-02-02 16:36:29 -05:00
|
|
|
SPAN_DECLARE(int16_t) dds(uint32_t *phase_acc, int32_t phase_rate)
|
2008-09-03 15:02:00 -04:00
|
|
|
{
|
|
|
|
int16_t amp;
|
|
|
|
|
|
|
|
amp = dds_lookup(*phase_acc);
|
|
|
|
*phase_acc += phase_rate;
|
|
|
|
return amp;
|
|
|
|
}
|
|
|
|
/*- End of function --------------------------------------------------------*/
|
|
|
|
|
2009-02-02 16:36:29 -05:00
|
|
|
SPAN_DECLARE(int16_t) dds_mod(uint32_t *phase_acc, int32_t phase_rate, int16_t scale, int32_t phase)
|
2008-09-03 15:02:00 -04:00
|
|
|
{
|
|
|
|
int16_t amp;
|
|
|
|
|
2011-07-02 02:45:27 -04:00
|
|
|
amp = (int16_t) (((int32_t) dds_lookup(*phase_acc + phase)*scale) >> 15);
|
2008-09-03 15:02:00 -04:00
|
|
|
*phase_acc += phase_rate;
|
|
|
|
return amp;
|
|
|
|
}
|
|
|
|
/*- End of function --------------------------------------------------------*/
|
|
|
|
|
2009-02-02 16:36:29 -05:00
|
|
|
SPAN_DECLARE(complexi_t) dds_lookup_complexi(uint32_t phase)
|
2008-09-03 15:02:00 -04:00
|
|
|
{
|
|
|
|
return complex_seti(dds_lookup(phase + (1 << 30)), dds_lookup(phase));
|
|
|
|
}
|
|
|
|
/*- End of function --------------------------------------------------------*/
|
|
|
|
|
2009-02-02 16:36:29 -05:00
|
|
|
SPAN_DECLARE(complexi_t) dds_complexi(uint32_t *phase_acc, int32_t phase_rate)
|
2008-09-03 15:02:00 -04:00
|
|
|
{
|
|
|
|
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 --------------------------------------------------------*/
|
|
|
|
|
2009-02-02 16:36:29 -05:00
|
|
|
SPAN_DECLARE(complexi_t) dds_complexi_mod(uint32_t *phase_acc, int32_t phase_rate, int16_t scale, int32_t phase)
|
2008-09-03 15:02:00 -04:00
|
|
|
{
|
|
|
|
complexi_t amp;
|
|
|
|
|
2011-07-02 02:45:27 -04:00
|
|
|
amp = complex_seti(((int32_t) dds_lookup(*phase_acc + phase + (1 << 30))*scale) >> 15,
|
|
|
|
((int32_t) dds_lookup(*phase_acc + phase)*scale) >> 15);
|
2008-09-03 15:02:00 -04:00
|
|
|
*phase_acc += phase_rate;
|
|
|
|
return amp;
|
|
|
|
}
|
|
|
|
/*- End of function --------------------------------------------------------*/
|
2008-09-09 13:04:42 -04:00
|
|
|
|
2009-02-02 16:36:29 -05:00
|
|
|
SPAN_DECLARE(complexi16_t) dds_lookup_complexi16(uint32_t phase)
|
2008-09-09 13:04:42 -04:00
|
|
|
{
|
|
|
|
return complex_seti16(dds_lookup(phase + (1 << 30)), dds_lookup(phase));
|
|
|
|
}
|
|
|
|
/*- End of function --------------------------------------------------------*/
|
|
|
|
|
2009-02-02 16:36:29 -05:00
|
|
|
SPAN_DECLARE(complexi16_t) dds_complexi16(uint32_t *phase_acc, int32_t phase_rate)
|
2008-09-09 13:04:42 -04:00
|
|
|
{
|
|
|
|
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 --------------------------------------------------------*/
|
|
|
|
|
2009-02-02 16:36:29 -05:00
|
|
|
SPAN_DECLARE(complexi16_t) dds_complexi16_mod(uint32_t *phase_acc, int32_t phase_rate, int16_t scale, int32_t phase)
|
2008-09-09 13:04:42 -04:00
|
|
|
{
|
|
|
|
complexi16_t amp;
|
|
|
|
|
2011-07-02 02:45:27 -04:00
|
|
|
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));
|
2008-09-09 13:04:42 -04:00
|
|
|
*phase_acc += phase_rate;
|
|
|
|
return amp;
|
|
|
|
}
|
|
|
|
/*- End of function --------------------------------------------------------*/
|
|
|
|
|
2009-02-02 16:36:29 -05:00
|
|
|
SPAN_DECLARE(complexi32_t) dds_lookup_complexi32(uint32_t phase)
|
2008-09-09 13:04:42 -04:00
|
|
|
{
|
|
|
|
return complex_seti32(dds_lookup(phase + (1 << 30)), dds_lookup(phase));
|
|
|
|
}
|
|
|
|
/*- End of function --------------------------------------------------------*/
|
|
|
|
|
2009-02-02 16:36:29 -05:00
|
|
|
SPAN_DECLARE(complexi32_t) dds_complexi32(uint32_t *phase_acc, int32_t phase_rate)
|
2008-09-09 13:04:42 -04:00
|
|
|
{
|
|
|
|
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 --------------------------------------------------------*/
|
|
|
|
|
2009-02-02 16:36:29 -05:00
|
|
|
SPAN_DECLARE(complexi32_t) dds_complexi32_mod(uint32_t *phase_acc, int32_t phase_rate, int16_t scale, int32_t phase)
|
2008-09-09 13:04:42 -04:00
|
|
|
{
|
|
|
|
complexi32_t amp;
|
|
|
|
|
2011-07-02 02:45:27 -04:00
|
|
|
amp = complex_seti32(((int32_t) dds_lookup(*phase_acc + phase + (1 << 30))*scale) >> 15,
|
|
|
|
((int32_t) dds_lookup(*phase_acc + phase)*scale) >> 15);
|
2008-09-09 13:04:42 -04:00
|
|
|
*phase_acc += phase_rate;
|
|
|
|
return amp;
|
|
|
|
}
|
|
|
|
/*- End of function --------------------------------------------------------*/
|
2008-09-03 15:02:00 -04:00
|
|
|
/*- End of file ------------------------------------------------------------*/
|