仅使用整数数学修改C中正弦信号的形状

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了仅使用整数数学修改C中正弦信号的形状相关的知识,希望对你有一定的参考价值。

我想在ARM Cortex M0微控制器上生成正弦信号,该微控制器可通过形状参数n自定义其形状。以下面的图表为例。在这里,我用功能模拟了不同的曲线

$y(x) = (1/2*(1 + sin(x)))^n$

enter image description here

对于更高的n,最大值是“更短”,最小值是“wider”。对于较低的n,最大值是“wider”,最小值是“shorter”。

为了减少内存消耗并提高性能,我只使用整数数学来生成正弦信号。

这是正弦计算的代码:

Input range [0R 2πR] mapped to [0 to 1024].

输出范围[-1.0 1.0]映射到[-16,384 16,384]。

int_fast16_t sin_bam(int angle_bam) {
  angle_bam %= 1024;
  if (angle_bam < 0)
    angle_bam += 1024;
  uint_fast16_t sub_angle = angle_bam % (1024u / 2);
  int_fast16_t sn = unsigned_mult16x16_into_32(sub_angle, (1024/2 - sub_angle)) / 4;
  if (angle_bam & 512) {
    sn = -sn;
  }
  return sn;
}

有没有人知道如何只用整数数学来实现这样的形状修改?

答案

有没有人知道如何只用整数数学来实现这样的形状修改? 例如,n的范围也可以是1到10

$ y(x)=(1/2 *(1 + sin(x)))^ n $

OP具有正弦近似函数sin_bam(),然后使用它来形成1/2*(1 + sin(x)),即hacovercosin(θ)。剩下的就是比例功率函数。

#include <inttypes.h>
#define SCALE 16384

int pow_scale(int x, unsigned n) {
  unsigned y = SCALE;
  while (n>0) {
    if (n%2) {
      y = unsigned_mult16x16_into_32(x,y)/SCALE; // 16-bit x 16-bit --> 32-bit product.
    }
    n /= 2;
    x = unsigned_mult16x16_into_32(x,x)/SCALE;
  }
  return x;
}

// x is the angle in 1024 BAM per period
// output is scaled to range [0....SCALE]
int shaped(int x, unsigned n) {
  return pow_scale(SCALE/2 + sin_bam(x)/2), n);
}
另一答案

这个怎么样:

/*
 * Generate integers to drive an n-bit D/A to make a modified sine wave.
 *
 * y = (1/2 * (1 + sin(theta))) ^ q
 *
 * y and q are 16-bit fixed-point numbers:
 *
 * 1000.000000000000 -> -8.000000000000
 *      ...
 * 1111.111111111110 -> -0.000488281250
 * 1111.111111111111 -> -0.000244140625
 * 0000.000000000000 ->  0.000000000000
 * 0000.000000000001 ->  0.000244140625
 * 0000.000000000010 ->  0.000488281250
 *      ...
 * 0111.111111111111 ->  7.999755859375
 *
 * theta is an 8-bit integer where
 *  0x00 -> 0
 *  0xff -> pi
 */
#include <iostream>
#include <string>
using namespace std;
#include <sys/types.h>
#include <stdlib.h>
#include <math.h>

string
fp2str( uint16_t n )
{
    char     buf[64];
    bool     neg = ((n & 0x8000) != 0);

    if (neg) {
        n = ~n + 1;
        buf[0] = '-';
    }

    sprintf( buf + 1, "%14.12f", double(n) / double(0x1000) );

    return neg ? buf : buf + 1;
}

uint16_t fpsin( uint16_t theta ) {  // 0 < theta < 1024 ==> 0 to 2pi
    static uint16_t sintbl[256] = {
        0x0000,0x0019,0x0032,0x004c,0x0065,0x007e,0x0097,0x00b1,0x00ca,0x00e3,0x00fc,0x0115,0x012e,0x0148,0x0161,0x017a,
        0x0193,0x01ac,0x01c5,0x01de,0x01f7,0x0210,0x0229,0x0242,0x025b,0x0274,0x028d,0x02a6,0x02bf,0x02d8,0x02f1,0x0309,
        0x0322,0x033b,0x0354,0x036c,0x0385,0x039d,0x03b6,0x03cf,0x03e7,0x0400,0x0418,0x0430,0x0449,0x0461,0x0479,0x0491,
        0x04aa,0x04c2,0x04da,0x04f2,0x050a,0x0522,0x053a,0x0551,0x0569,0x0581,0x0598,0x05b0,0x05c8,0x05df,0x05f7,0x060e,
        0x0625,0x063d,0x0654,0x066b,0x0682,0x0699,0x06b0,0x06c7,0x06de,0x06f4,0x070b,0x0722,0x0738,0x074f,0x0765,0x077c,
        0x0792,0x07a8,0x07be,0x07d4,0x07ea,0x0800,0x0816,0x082c,0x0841,0x0857,0x086c,0x0882,0x0897,0x08ac,0x08c1,0x08d6,
        0x08eb,0x0900,0x0915,0x092a,0x093f,0x0953,0x0968,0x097c,0x0990,0x09a4,0x09b8,0x09cc,0x09e0,0x09f4,0x0a08,0x0a1b,
        0x0a2f,0x0a42,0x0a56,0x0a69,0x0a7c,0x0a8f,0x0aa2,0x0ab5,0x0ac7,0x0ada,0x0aed,0x0aff,0x0b11,0x0b23,0x0b35,0x0b47,
        0x0b59,0x0b6b,0x0b7d,0x0b8e,0x0b9f,0x0bb1,0x0bc2,0x0bd3,0x0be4,0x0bf5,0x0c05,0x0c16,0x0c27,0x0c37,0x0c47,0x0c57,
        0x0c67,0x0c77,0x0c87,0x0c97,0x0ca6,0x0cb5,0x0cc5,0x0cd4,0x0ce3,0x0cf2,0x0d01,0x0d0f,0x0d1e,0x0d2c,0x0d3a,0x0d48,
        0x0d56,0x0d64,0x0d72,0x0d80,0x0d8d,0x0d9a,0x0da8,0x0db5,0x0dc2,0x0dcf,0x0ddb,0x0de8,0x0df4,0x0e00,0x0e0d,0x0e19,
        0x0e24,0x0e30,0x0e3c,0x0e47,0x0e53,0x0e5e,0x0e69,0x0e74,0x0e7e,0x0e89,0x0e94,0x0e9e,0x0ea8,0x0eb2,0x0ebc,0x0ec6,
        0x0ecf,0x0ed9,0x0ee2,0x0eeb,0x0ef4,0x0efd,0x0f06,0x0f0f,0x0f17,0x0f1f,0x0f28,0x0f30,0x0f38,0x0f3f,0x0f47,0x0f4e,
        0x0f56,0x0f5d,0x0f64,0x0f6a,0x0f71,0x0f78,0x0f7e,0x0f84,0x0f8a,0x0f90,0x0f96,0x0f9c,0x0fa1,0x0fa6,0x0fac,0x0fb1,
        0x0fb6,0x0fba,0x0fbf,0x0fc3,0x0fc7,0x0fcc,0x0fd0,0x0fd3,0x0fd7,0x0fda,0x0fde,0x0fe1,0x0fe4,0x0fe7,0x0fea,0x0fec,
        0x0fef,0x0ff1,0x0ff3,0x0ff5,0x0ff7,0x0ff8,0x0ffa,0x0ffb,0x0ffc,0x0ffd,0x0ffe,0x0fff,0x0fff,0x1000,0x1000,0x1000
    } ;

    uint16_t val;

    theta &= 0x3ff;

    if (theta < 0x100)
        val = sintbl[theta];
    else
    if (theta < 0x200)
        val = sintbl [0x200 - theta - 1];
    else
    if (theta < 0x300)
        val = (~sintbl[theta - 0x200] + 1); // negate
    else
        val = (~sintbl[0x400 - theta -1] + 1);  // negate

    return val;
}


/*
 * Natural-log table.  Smallest value is ln(2/4096) -> -7.624618986159398403
 * (values smaller than 2/4096 have logs less than -8, which smaller than we
 * can represent in our fixed-point format).  Largest is 2.0776, which is ln(8)
 */
int16_t fplog( int16_t n )
{
    static uint16_t lntbl[512] = {
        /*0.00048828*/ 0x8602,0xbdf3,0xc8cc,0xcf34,0xd3c3,0xd74f,0xda36,0xdcaa,0xdecb,0xe0ab,0xe259,0xe3df,0xe542,0xe689,0xe7b8,0xe8d2,
        /*0.25048828*/ 0xe9da,0xead2,0xebbb,0xec98,0xed6a,0xee32,0xeef0,0xefa6,0xf054,0xf0fb,0xf19b,0xf236,0xf2ca,0xf35a,0xf3e5,0xf46b,
        /*0.50048828*/ 0xf4ed,0xf56b,0xf5e5,0xf65c,0xf6cf,0xf73f,0xf7ac,0xf816,0xf87e,0xf8e3,0xf946,0xf9a6,0xfa04,0xfa60,0xfaba,0xfb12,
        /*0.75048828*/ 0xfb68,0xfbbd,0xfc0f,0xfc60,0xfcb0,0xfcfe,0xfd4a,0xfd96,0xfddf,0xfe28,0xfe6f,0xfeb5,0xfefa,0xff3d,0xff80,0xffc2,
        /*1.00048828*/ 0x0002,0x0041,0x0080,0x00be,0x00fa,0x0136,0x0171,0x01ab,0x01e4,0x021d,0x0254,0x028b,0x02c2,0x02f7,0x032c,0x0360,
        /*1.25048828*/ 0x0394,0x03c6,0x03f9,0x042a,0x045b,0x048c,0x04bc,0x04eb,0x051a,0x0548,0x0576,0x05a3,0x05d0,0x05fc,0x0628,0x0653,
        /*1.50048828*/ 0x067e,0x06a9,0x06d3,0x06fc,0x0725,0x074e,0x0776,0x079e,0x07c6,0x07ed,0x0814,0x083a,0x0860,0x0886,0x08ac,0x08d1,
        /*1.75048828*/ 0x08f5,0x091a,0x093e,0x0962,0x0985,0x09a8,0x09cb,0x09ee,0x0a10,0x0a32,0x0a54,0x0a75,0x0a96,0x0ab7,0x0ad8,0x0af8,
        /*2.00048828*/ 0x0b18,0x0b38,0x0b58,0x0b77,0x0b96,0x0bb5,0x0bd4,0x0bf2,0x0c10,0x0c2e,0x0c4c,0x0c6a,0x0c87,0x0ca4,0x0cc1,0x0cde,
        /*2.25048828*/ 0x0cfa,0x0d17,0x0d33,0x0d4f,0x0d6b,0x0d86,0x0da2,0x0dbd,0x0dd8,0x0df3,0x0e0d,0x0e28,0x0e42,0x0e5c,0x0e76,0x0e90,
        /*2.50048828*/ 0x0eaa,0x0ec3,0x0edd,0x0ef6,0x0f0f,0x0f28,0x0f41,0x0f59,0x0f72,0x0f8a,0x0fa2,0x0fba,0x0fd2,0x0fea,0x1001,0x1019,
        /*2.75048828*/ 0x1030,0x1047,0x105f,0x1075,0x108c,0x10a3,0x10ba,0x10d0,0x10e6,0x10fc,0x1113,0x1129,0x113e,0x1154,0x116a,0x117f,
        /*3.00048828*/ 0x1195,0x11aa,0x11bf,0x11d4,0x11e9,0x11fe,0x1213,0x1227,0x123c,0x1250,0x1265,0x1279,0x128d,0x12a1,0x12b5,0x12c9,
        /*3.25048828*/ 0x12dc,0x12f0,0x1304,0x1317,0x132a,0x133e,0x1351,0x1364,0x1377,0x138a,0x139d,0x13af,0x13c2,0x13d5,0x13e7,0x13fa,
        /*3.50048828*/ 0x140c,0x141e,0x1430,0x1442,0x1454,0x1466,0x1478,0x148a,0x149c,0x14ad,0x14bf,0x14d0,0x14e2,0x14f3,0x1504,0x1515,
        /*3.75048828*/ 0x1526,0x1537,0x1548,0x1559,0x156a,0x157b,0x158c,0x159c,0x15ad,0x15bd,0x15ce,0x15de,0x15ee,0x15fe,0x160f,0x161f,
        /*4.00048828*/ 0x162f,0x163f,0x164f,0x165e,0x166e,0x167e,0x168e,0x169d,0x16ad,0x16bc,0x16cc,0x16db,0x16ea,0x16fa,0x1709,0x1718,
        /*4.25048828*/ 0x1727,0x1736,0x1745,0x1754,0x1763,0x1772,0x1780,0x178f,0x179e,0x17ac,0x17bb,0x17c9,0x17d8,0x17e6,0x17f5,0x1803,
        /*4.50048828*/ 0x1811,0x181f,0x182d,0x183c,0x184a,0x1858,0x1866,0x1873,0x1881,0x188f,0x189d,0x18ab,0x18b8,0x18c6,0x18d4,0x18e1,
        /*4.75048828*/ 0x18ef,0x18fc,0x1909,0x1917,0x1924,0x1931,0x193f,0x194c,0x1959,0x1966,0x1973,0x1980,0x198d,0x199a,0x19a7,0x19b4,
        /*5.00048828*/ 0x19c1,0x19cd,0x19da,0x19e7,0x19f4,0x1a00,0x1a0d,0x1a19,0x1a26,0x1a32,0x1a3f,0x1a4b,0x1a57,0x1a64,0x1a70,0x1a7c,
        /*5.25048828*/ 0x1a88,0x1a95,0x1aa1,0x1aad,0x1ab9,0x1ac5,0x1ad1,0x1add,0x1ae9,0x1af5,0x1b01,0x1b0c,0x1b18,0x1b24,0x1b30,0x1b3b,
        /*5.50048828*/ 0x1b47,0x1b53,0x1b5e,0x1b6a,0x1b75,0x1b81,0x1b8c,0x1b98,0x1ba3,0x1bae,0x1bba,0x1bc5,0x1bd0,0x1bdc,0x1be7,0x1bf2,
        /*5.75048828*/ 0x1bfd,0x1c08,0x1c13,0x1c1e,0x1c29,0x1c34,0x1c3f,0x1c4a,0x1c55,0x1c60,0x1c6b,0x1c76,0x1c80,0x1c8b,0x1c96,0x1ca1,
        /*6.00048828*/ 0x1cab,0x1cb6,0x1cc1,0x1ccb,0x1cd6,0x1ce0,0x1ceb,0x1cf5,0x1d00,0

以上是关于仅使用整数数学修改C中正弦信号的形状的主要内容,如果未能解决你的问题,请参考以下文章

怎么用ADC采样正弦信号来计算峰值

如何讲正弦波转化为方波?频率不变。

8. 正弦和余弦

C系统v信号量不锁定关键区域

matlab 使用定时器画连续正弦波信号

仅使用整数缩放值