0

长话短说,我在 int r 中有一个音频信号输出,即 r 的值介于 32768 和 - 32768 之间。

我试图创建一个规范化例程,但由于某种原因,以下代码产生了一个半波,只有上部是可见的,或者换句话说,高于 0,没有负值。

在这里(dif 也是一个 int,dif_vorher)

if (r * 8 > 32768)
  dif = dif_vorher;
else if (r * 8 < -32768)
  dif = dif_vorher;
else
  dif = r * 8;        
dif_vorher = dif;

然后准备将其写入原始文件:

if (dif != 0)
{
  putc((char) ( (unsigned)dif       & 0xff),ausgabe);
  putc((char) (((unsigned)dif >> 8) & 0xff),ausgabe);
}    

这个原始文件只有上限值。我也试过

if (r * 8 > 32768)
  dif = 32768;
else if (r * 8 < -32768)
  dif = -32768;
else
  dif = r * 8;        

if (r * 8 > 32768 || r * 8 < -32768)
  dif = -32768;
else
  dif = r * 8;  

结果相同,除非我使用

if (r * 8 > 32768)
  dif = 32768;
else if (r * 8 < -32768)
  dif = -32768;
else
  dif = r * 8;   

它的上部也是扭曲的。

为什么负面的部分被遗漏了?

编辑:我发现 r * 8 的最大值为 524272,最小值为 0。所以 r_max = 524272/8 = 65534; 65534/2 = 32767。因此,为了避免负值,该值似乎移动了 32768。

4

1 回答 1

0

我认为关键问题是您试图将大量数字放入一个小空间中。也就是说,如果不首先将原始数字缩小到适合char存储的大小,您将截断 int 数据中的一些信息,导致大的负值被解释为零。顺便说一句,如果您的任何负值 > -128,我认为表达式:
(char) ( (unsigned)dif & 0xff) 会返回负值。

我仍然不确定您首先使用该表达式究竟在做什么,即如果您已经从规范化函数中获得了一个缩放的数据值(假设它有效),那么您是否不只是将它放入您的文件中?

无论如何,据我所知,您正在尝试完成两件事,标准化(在这里,我假设您的意思是规模,如果我错了,请告诉我)
一组正面和负面数据,以便它可以存储在 中char,然后使用将该数据写入 putc()文件。如果我们解决了缩放问题,
那么将正负结果写入文件将毫无问题。

要将输入范围从 +/- 32768 缩小到 char 可以容纳的值,即 127 到 -128,您可以将数据中的每个值乘以这两个值的比率。就像是:

char ScaleToChar(int x); //prototype

char ScaleToChar(int x)
{
    int a = x;
    float ratio;
    //bound a:  -32768 to 32768
    if (abs(x) > 32768)
    {
        a = (x >= 0) ? (32768) : (-32768);
    }
    //scale x: -128 to 127
    ratio = (a <= 0) ? (128.0/32768.0) : (127.0/32768);

    return (char)(a * ratio);
}

使用这个,你的线路:

  putc((char) ( (unsigned)dif       & 0xff),ausgabe);
  putc((char) (((unsigned)dif >> 8) & 0xff),ausgabe);  

会成为

  putc(ScaleToChar(dif),ausgabe);

(我不知道你在用第二个电话做什么,但如果需要,你可以做 shift 和 & op,然后打电话ScaleToChar()

[编辑]

而不是我最初建议的缩放方法,我认为你要做的是过滤波形。也就是说,通过数据数组递增,当波形接近极限(负极限或正极限)时,使用最近 10 到 15 个数组值中的一些历史记录来确定您应该如何趋势潜在错误值这样他们就不会违反限制。这样,您的大部分数据将永远不会被触及。这将允许保持保真度(与缩放方法不同),同时,对任何修改数据的更改将仅限于那些落在某些预定区域内的数据,该区域围绕波形违规部分的中心延伸,

想到了 FIR 滤波器方法,但像运行平均值这样简单的方法也可以。没有违反限制危险的数据值永远不会被过滤器触及。从概念上讲,这种方法听起来并不太复杂。然而,当我开始思考如何解决它时,我意识到你可能会变得非常复杂(例如,应用卡尔曼滤波器进行预测分析)。话虽如此,它也可以保持相当简单,例如简单的运行平均值。

于 2013-10-25T18:37:32.023 回答