【问题标题】:Audio wave has no negative values音频波没有负值
【发布时间】:2013-11-01 07:43:33
【问题描述】:

长话短说,我在 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以避免负值。

【问题讨论】:

  • 您能否展示一些实际(典型)输入数据正在被这段代码处理?
  • 乍一看猜你投错了putc((char) ( (unsigned)dif &amp; 0xff),ausgabe);
  • @ryyker 我刚刚在阅读您的回复时这样做了。令人惊讶的是,我没有得到负值,但最多只有 524272。
  • 刚刚删除了我的答案。它没有解决你的问题。我可以看到您正在尝试仅使用最低有效 8 位来准备数据,以便它适合 char,对吗?
  • 为什么要保留从 32768 到 -32768 的数字,然后下面只保留最后 8 位。为什么不首先将其限制在 127 到 -128 之间?

标签: c raspberry-pi


【解决方案1】:

我认为关键问题是你试图把 大数字进入一个小空间。也就是说,没有先 将原始数字缩小到适合的大小 舒适地进入char 存储,你正在截断一些 int 数据中的信息导致大 负值被解释为零。顺便说一句,如果 您的任何负值都 > -128,我认为表达式:
(char) ( (unsigned)dif &amp; 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 滤波器方法,但像运行平均值这样简单的方法也可以使用。没有违反限制危险的数据值永远不会被过滤器触及。从概念上讲,这种方法听起来并不太复杂。然而,当我开始思考如何解决它时,我意识到您可能会变得相当复杂(例如,应用 Kalman filter 进行预测分析)。话虽如此,它也可以保持非常简单,即简单的运行平均值。

【讨论】:

  • 回复:规范化。我的意思是我有一个原始波形文件,其中有时包含噼啪声(它会使振幅尖峰并且对测量没有用)和所需的信号。假设所需信号的最高幅度是最大信号的 20%,即 6554。因此我想将输入信号乘以 5。这反过来又会进一步增加已经削波的噼啪声。所以我需要做点什么。我的想法是限制从计算返回的每个值 (value_source * 5) 并且大于 32768 为 32768(对于负值,vv)。
  • 好的,我明白了。我现在正在工作,但会修改我的代码,使其符合您对规范化的描述。我意识到,一旦我想到它,我缩放输入的方法会降低声音的保真度。我稍后再谈。解决方案将简单地记住二进制数的符号保留在最高有效位中。因此,用 0xff 对值进行 &'ing 将基本上消除该符号位。稍后会修复,如果你还没有。感谢您的投票!
  • 为了避免进一步混淆,这里是我使用的完整代码:pastebin.com/kwrRhbsi Datei 是稍后(第 4 行)连接到整个 RAW 文件名的文件名的一部分。 RAW 文件为 44100 Hz,16 位,立体声。
  • 我将编辑我上面的答案,并评论鉴于我对您的问题的理解(到目前为止),我将如何处理您的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-09
  • 2017-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多