Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 直接数字合成中的线性插值_C_Avr_Linear Interpolation - Fatal编程技术网

C 直接数字合成中的线性插值

C 直接数字合成中的线性插值,c,avr,linear-interpolation,C,Avr,Linear Interpolation,我正在从事一个用C语言编写的微控制器DDS项目,在弄清楚如何计算线性插值来平滑输出值时遇到了一些困难。目前的计划 使用24位累加器的前8位作为8位输出值数组的索引。我需要想出一个函数,它将获取累加器的中间和较低字节,并在数组中的“上一个”和“下一个”值之间生成一个值。这在快速硬件上足够简单,但因为我使用的是微控制器,所以我真的需要避免做任何浮点运算或除法 有了这些限制,我不确定如何从我的两个8位输入数字和累加器的较低2个字节中获得8位插值,这表示两个输入值之间的“距离”。提前感谢您的建议 澄清

我正在从事一个用C语言编写的微控制器DDS项目,在弄清楚如何计算线性插值来平滑输出值时遇到了一些困难。目前的计划
使用24位累加器的前8位作为8位输出值数组的索引。我需要想出一个函数,它将获取累加器的中间和较低字节,并在数组中的“上一个”和“下一个”值之间生成一个值。这在快速硬件上足够简单,但因为我使用的是微控制器,所以我真的需要避免做任何浮点运算或除法

有了这些限制,我不确定如何从我的两个8位输入数字和累加器的较低2个字节中获得8位插值,这表示两个输入值之间的“距离”。提前感谢您的建议

澄清


直接数字合成


在DDS中,使用相位累加器从查找表生成波形。相位累加器通常包含整数分量和小数分量。整数组件用作查找表的索引。在简单的DDS实现中,分数部分被忽略,但对于更高质量的输出,分数部分用于相邻查找表值之间的插值(通常仅为线性插值)。对于上述问题,我们正在研究如何有效地执行给定分数f的两个查找表值之间的线性插值,其中
0两个值之间的线性插值,a和b是(a+b)/2

这在简单的硬件中很容易实现,并且不涉及除法或浮点运算


除以2==右移一位。

如果您确实需要速度,请检查。

如果您想要更高的精度,我建议先检查累加器的低位。 例如,如果我们想要4个输出值而不是1:

Acc += 0x2000;
uint lower_bits = Acc & 0xffff;
int rl = LUT[ Acc >> 16];
int rh = LUT[(Acc >> 16) + 1];
if (lower_bits < 0x4000)
    return rl;
if (lower_bits < 0x8000)
    return (rl * 3 + rh) >> 2;
if (lower_bits < 0xC000)
    return (rl + rh) >> 1;
return (rl + rh * 3) >> 2;
Acc+=0x2000;
uint低位=Acc&0xffff;
int rl=LUT[Acc>>16];
int-rh=LUT[(Acc>>16)+1];
if(较低的_位<0x4000)
返回rl;
if(较低的_位<0x8000)
返回(rl*3+rh)>>2;
if(低位<0xC000)
返回(rl+rh)>>1;
返回(rl+rh*3)>>2;

假设您有一个波形值表(一个象限或四个象限,都无所谓),那么一种可能的优化方法是将增量值存储在连续的表格值之间。也就是说,如果您有例如
N=256
和波形表
LUT[N]
,那么您也有一个增量值表,
LUT\u delta[N]
。两个预计算表之间的关系是
LUT_delta[i]=LUT[i+1]-LUT[i]
。因此,不必查找两个连续的表值,
LUT[i]
LUT[i+1]
,而是减去它们得到增量,然后进行插值,您只需查找第一个表值,
LUT[i]
,以及增量,
LUT\u delta[i]
,然后计算插值。这需要相同数量的表查找,但需要较少的数学操作。如果您使用的是DSP,则应该能够使用单个乘法累加指令进行插值,否则它是通用CPU上的乘法+小数+加法。此外,如果将
LUT
LUT_delta
值交错,则可以通过单个读取来查找
LUT[i]
LUT_delta[i]
,然后解压缩这两个值

伪代码:

extract integer LUT index, i, from accumulator // just need a shift for this
extract fractional part of accumulator, f // mask or subtract to get f
get p = LUT[i] // lookup waveform value
get delta = LUT_delta[i] // lookup delta
calculate p_interp = p + p_delta * f // single multiply-accumulate instruction on most DSPs - need scaling on general purpose CPUs

要在不进行除法的情况下进行线性插值,应确保分母是2的幂

值(x)=上一个,
值(x+1)=下一个 值(x+dx)=上一个+(下一个-上一个)*dx

你的问题是,如何计算dx?诀窍是计算插值索引(累加器的16低位),使最大值(dx=1)为2的幂:

value(x + dx) = previous + ((next - previous) * index) / 1024

这里,您已经计算了步长值,因此最大步长为1024,与dx=1相关。Index=512表示dx=0.5等。

仅插值中点-对于上述问题,您可能需要插值任意点。“任意”?中点似乎和任何其他点一样任意。@S.Lott:如果你读到这个问题,他正在用相位累加器进行DDS-相位累加器的分数部分决定了你需要插值的两个值之间的点。至于“武断”,我的字典上说:2。(常数或其他数量)未指定值的数学。@Paul R:“在数组中的“上一个”和“下一个”值之间生成一个值”不知何故并不意味着“中点”?有趣。你认为这个问题应该更新以补充这个拼图中缺失的部分吗?@S.Lott:我认为OP的假设可能是错误的大多数人对DDS和相位累加器都很熟悉。DDS=直接数字合成-用于音频/无线电/通信/etcI中的波形生成我可能不理解你的意思-但是使用24位累加器,这不意味着我必须在每个点之间存储所有2^16增量的增量值吗桌子如果我有这样的空间,我就可以以更高的分辨率存储表格,而不用担心插值了!:)@Bitrex-否如果您有一个N点表(例如N=256),那么您只需要第二个N点表来表示增量,其中
LUT\u delta[i]=LUT[i+1]-LUT[i]
。啊,我明白了。我想我有足够的空间放这么大的桌子@Bitrex:如果没有第二个表,你可能首先要做一个基准测试,然后如果你真的需要,只考虑这个优化。如另一张海报所说,使用2的幂表示桌子大小等。另外请注意,需要对增量值进行签名(除非您仅使用单象限表)。我明白了,因此在我的例子中,24位累加器使用前8位作为除法的索引(2^16步长值)