当前位置: 首页 > 面试题库 >

如何将字节数组中的pcm样本转换为-1.0到1.0范围内的浮点数并返回?

史逸春
2023-03-14
问题内容

我使用的重采样算法期望 float 数组包含 -1.0到1.0 范围内的输入样本。音频数据是 16位 PCM,采样
率为22khz

我想将音频从22khz下采样到8khz,如何将字节数组中的样本表示为浮点数 > = -1和<= 1并返回字节数组?


问题答案:

您问两个问题:

  1. 如何将采样率从22kHz下调至8kHz?

  2. 如何从float [-1,1]转换为16位int并返回?

请注意,该问题已更新,以指示#1已在其他地方处理,但如果有帮助,我将保留我的部分答案。

1.如何将采样频率从22kHz下调至8kHz?

一个评论者暗示这可以通过FFT解决。这是不正确的(重新采样的第一步是过滤。如果您感兴趣,我在这里提到了为什么不使用FFT进行过滤:http : //blog.bjornroche.com/2012/08/when-to-not-use
-fft.html
)。

对信号进行重采样的一种非常好的方法是使用多相滤波器。但是,即使对于有信号处理经验的人来说,这也相当复杂。您还有其他几种选择:

  • 使用实现高质量重采样的库,例如libsamplerate
  • 快速而肮脏地做某事

听起来您已经采用第一种方法,这很棒。

快速而肮脏的解决方案听起来不那么好,但是由于您将频率降至8 kHz,因此我认为音质不是您的首要任务。一种快速而肮脏的选择是:

  • 对信号应用低通滤波器。尝试消除4 kHz以上的音频。您可以使用此处描述的过滤器(尽管理想情况下,您想要比这些过滤器更陡峭的东西,但至少比没有要好)。
  • 从原始信号中选择每个第2.75个采样,以产生新的,重新采样的信号。当您需要非整数样本时,请使用线性插值。如果您需要线性插值方面的帮助,请在此处尝试。

对于语音应用来说,这种技术应该已经足够好了。但是,我还没有尝试过,所以我不确定,因此我强烈建议您使用其他人的库。

如果您真的想实现自己的高质量采样率转换(例如多相滤波器),则应该对其进行研究,然后在https://dsp.stackexchange.com/上提出任何问题,而不是在此处提出。

2.如何从float [-1,1]转换为16位int并返回?

这已经由c.fogelklou开始,但是让我修饰一下。

首先,16位整数的范围是-32768到32767(通常对16位音频进行签名)。要将int转换为float,请执行以下操作:

float f;
int16 i = ...;
f = ((float) i) / (float) 32768
if( f > 1 ) f = 1;
if( f < -1 ) f = -1;

通常,您不需要执行额外的“边界”操作(实际上,如果确实使用的是16位整数,则不需要这样做),但是如果您出于某些原因拥有一些> 16位整数,就可以使用它。

要转换回来,请执行以下操作:

float f = ...;
int16 i;
f = f * 32768 ;
if( f > 32767 ) f = 32767;
if( f < -32768 ) f = -32768;
i = (int16) f;

在这种情况下,通常有必要注意超出范围的值,尤其是大于32767的值。您可能会抱怨说,这会导致f =
1产生一些失真。有关此问题的一些(不完整的)讨论,请参阅此博客文章。

这不仅仅是“足以胜任政府工作”。换句话说,除非您担心最终的声音质量,否则它将正常工作。由于您将达到8kHz,因此我认为事实并非如此,因此此答案很好。

但是,为了完整起见,我必须添加一点:如果您要使事情绝对原始,请记住,这种转换会导致失真。为什么?因为从float转换为int时的误差与信号相关。事实证明,该错误的相关性非常糟糕,即使它很小,您实际上也可以听到。(幸运的是,它很小,以至于对于语音和低动态范围的音乐来说,它并不重要)。要消除此错误,必须在从float到int的转换中使用dither。同样,如果您对此很在意,请进行研究并在https://dsp.stackexchange.com/上提出相关的特定问题,而不是在此处。

您可能也对我在数字音频编程基础上的幻灯片中的幻灯片感兴趣,该幻灯片也有关于此主题的幻灯片,尽管它基本上说的是同一件事(甚至比我刚才说的要少):http://
blog .bjornroche.com / 2011/11 / slides-from-fundamentals-of-
audio.html



 类似资料:
  • 问题内容: 我有一个必须解析的二进制文件,并且正在使用Python。有没有办法占用4个字节并将其转换为单个精度浮点数? 问题答案:

  • 问题内容: 我正在尝试对.3gpp音频文件执行快速傅立叶变换。该文件包含来自电话麦克风的44100kHz的5秒钟小录音。 出于显而易见的原因,我可以找到的每个Java FFT算法都只接受double [],float []或Complex []输入,但是我以字节数组的形式读取音频文件,因此我有点困惑我从这里去哪里。我唯一能找到的是上一个问题的答案: Android音频FFT使用音频记录检索特定频率

  • 问题内容: 我正在尝试将a 转换为原始类型,反之亦然: 奇怪的是,当我尝试将新分配的分配回a时,结果不过是垃圾。 但是,当我使用原始数据类型作为参数时,似乎相同的算法工作得很好。 问题答案: 改用这些。

  • 问题内容: 如何转换 至 在NumPy中? 问题答案: 好吧,如果您以列表的形式读取数据,则可以这样做(或等效地,使用列表理解)。(在Python 3,你需要调用的,如果你使用的返回值,因为现在返回一个迭代器)。 但是,如果已经是一串Numpy的字符串,则有更好的方法。使用。

  • 我目前正在处理音频样本。我从AVAssetReader获得它们,并有一个,其内容如下: 如您所见,我找到的唯一用于转换[Int16]->[Float]的方法是,但这样做会增加我的处理时间。是否存在将Int16指针转换为Float指针的其他方法?

  • 问题内容: 为了将字节数组转换为双精度型,我发现了这一点: 但是我找不到将双精度型转换为字节数组的任何东西。 问题答案: 甚至更简单