简单程序将 int16_t 数组转换为 uint16_t
Simple program convert int16_t array to uint16_t
我已经使用 WinFilter 程序在 C 代码上计算 FIR 滤波器,但我遇到了一个问题:
该程序仅提供 16 位有符号数组,我需要该向量为无符号整数。所以我正在寻找一个简单的解决方案来将数组值重新定位到下一个 "values".
int16_t FIRCoef[Ntap] = {
-1029,
-1560,
-1188,
0,
1405,
2186,
1718,
0,
-2210,
-3647,
-3095,
0,
5160,
10947,
15482,
17197,
15482,
10947,
5160,
0,
-3095,
-3647,
-2210,
0,
1718,
2186,
1405,
0,
-1188,
-1560,
-1029,
0
};
uint16_t fir(uint16_t NewSample) {
static uint16_t x[Ntap]; //input samples
uint32_t y=0; //output sample
int n;
//shift the old samples
for(n=Ntap-1; n>0; n--)
x[n] = x[n-1];
//Calculate the new output
x[0] = NewSample;
for(n=0; n<Ntap; n++)
y += FIRCoef[n] * x[n]; // calculo da convolucao na amostra
// Calculation of the convolution in the sample
return y / DCgain;
}
我认为一种解决方案应该是这样的:
uint16_t--------int16_t---------index
0 -32767 1
1 -32766 2
2 -32765 3
... ... ...
65535 32767 65535
有什么提示吗?
int16_t
的值范围是 -32768 到 32767。您的问题在这一点上不清楚,但您似乎只想将这些值转移到 uint16_t
的范围内, 0 到 65535。这是合理的,因为两种类型的可表示值的数量是相同的;它可以通过将 int16_t
的最小可能值的倒数添加到输入中来实现。
当然,细节决定成败。当有符号加法溢出时,会产生未定义的行为。当超出范围的值转换为有符号整数类型时,结果是实现定义的,并且可以是(实现定义的)异常。避免实现定义的行为是可取的,避免未定义的行为是必不可少的;在这种情况下,只要稍微小心一点就可以做到:
uint16_t convert(int16_t in) {
return (uint16_t) 32768 + (uint16_t) in;
}
在任何首先提供 uint16_t
和 int16_t
类型的符合系统上可靠地做正确的事情,因为转换和加法以模一加上 a 的最大值进行操作uint16_t
。负输入值被转换为uint16_t
范围上半部分的无符号值,然后加法旋转所有值,将范围上半部分的值带到下半部分。
至于对整个数组执行此操作,如果您只想依赖定义明确的 C 行为(即,如果您想要一个严格符合标准的解决方案),那么您需要复制数据。您可以使用上述函数来填充副本。
我已经使用 WinFilter 程序在 C 代码上计算 FIR 滤波器,但我遇到了一个问题:
该程序仅提供 16 位有符号数组,我需要该向量为无符号整数。所以我正在寻找一个简单的解决方案来将数组值重新定位到下一个 "values".
int16_t FIRCoef[Ntap] = {
-1029,
-1560,
-1188,
0,
1405,
2186,
1718,
0,
-2210,
-3647,
-3095,
0,
5160,
10947,
15482,
17197,
15482,
10947,
5160,
0,
-3095,
-3647,
-2210,
0,
1718,
2186,
1405,
0,
-1188,
-1560,
-1029,
0
};
uint16_t fir(uint16_t NewSample) {
static uint16_t x[Ntap]; //input samples
uint32_t y=0; //output sample
int n;
//shift the old samples
for(n=Ntap-1; n>0; n--)
x[n] = x[n-1];
//Calculate the new output
x[0] = NewSample;
for(n=0; n<Ntap; n++)
y += FIRCoef[n] * x[n]; // calculo da convolucao na amostra
// Calculation of the convolution in the sample
return y / DCgain;
}
我认为一种解决方案应该是这样的:
uint16_t--------int16_t---------index
0 -32767 1
1 -32766 2
2 -32765 3
... ... ...
65535 32767 65535
有什么提示吗?
int16_t
的值范围是 -32768 到 32767。您的问题在这一点上不清楚,但您似乎只想将这些值转移到 uint16_t
的范围内, 0 到 65535。这是合理的,因为两种类型的可表示值的数量是相同的;它可以通过将 int16_t
的最小可能值的倒数添加到输入中来实现。
当然,细节决定成败。当有符号加法溢出时,会产生未定义的行为。当超出范围的值转换为有符号整数类型时,结果是实现定义的,并且可以是(实现定义的)异常。避免实现定义的行为是可取的,避免未定义的行为是必不可少的;在这种情况下,只要稍微小心一点就可以做到:
uint16_t convert(int16_t in) {
return (uint16_t) 32768 + (uint16_t) in;
}
在任何首先提供 uint16_t
和 int16_t
类型的符合系统上可靠地做正确的事情,因为转换和加法以模一加上 a 的最大值进行操作uint16_t
。负输入值被转换为uint16_t
范围上半部分的无符号值,然后加法旋转所有值,将范围上半部分的值带到下半部分。
至于对整个数组执行此操作,如果您只想依赖定义明确的 C 行为(即,如果您想要一个严格符合标准的解决方案),那么您需要复制数据。您可以使用上述函数来填充副本。