规范化音频,如何将浮点数组转换为字节数组?

2024-01-28

大家好,我正在播放音频文件。我把它读作byte[]然后我需要通过将值放入 [-1,1] 范围内来标准化音频。然后我想将每个浮点值放入byte[i]数组然后把它byte[]返回到正在播放的音频播放器。

我试过这个:

byte[] data = ar.ReadData();
byte[] temp=new byte[data.Length];
float biggest= 0; ;
for (int i = 0; i < data.Length; i++)
{
    if (data[i] > biggest)
    {
        biggest= data[i];
    }
}

这部分代码应该放置例如 0.43 int byte[] 如果可能的话我尝试了这个但它不起作用:

for (int i = 0; i < data.Length; i++)
{
    temp = BitConverter.GetBytes(data[i] * (1 / biggest));
}

您在评论中表示“我正在播放音频文件...我将其读取为 byte[],然后我需要通过将值放入 [-1,1] 范围内来标准化音频,然后我需要将该 byte[] 放回到播放音频播放器中"

我在这里做了一个很大的假设,但我猜测您收到的数据ar.ReadData()是2通道16位/44.1kHz PCM数据的字节数组。 (旁注:您是否使用 Alvas.Audio 库?)如果是这种情况,以下是如何执行您想要的操作。

背景

首先,介绍一下背景。 2 通道、16 位 PCM 数据流如下所示:

   byte | 01 02 | 03 04 | 05 06 | 07 08 | 09 10 | 11 12 | ...
channel |  Left | Right | Left  | Right | Left |  Right | ...
  frame |     First     |    Second     |     Third     | ...
 sample | 1st L | 1st R | 2nd L | 2nd R | 3rd L | 3rd R | ... etc.

这里重要的是要注意以下几点:

  1. 由于音频数据是 16 位,因此来自单个通道的单个样本是short(2 个字节),不是int(4 个字节),值范围为 -32768 到 32767。
  2. 该数据位于小尾数法 http://en.wikipedia.org/wiki/Endianness表示,除非您的架构也是小端,否则您不能使用 .NETBitConverter http://msdn.microsoft.com/en-us/library/system.bitconverter.aspx用于转换的类。
  3. 我们不必将数据拆分为每个通道的流,因为我们根据任一通道的单个最高值对两个通道进行标准化。
  4. 将浮点值转换为整数值将导致量化错误,因此您可能需要使用某种抖动 http://en.wikipedia.org/wiki/Dither(这本身就是一个完整的主题)。

辅助函数

在我们开始实际的标准化之前,让我们通过编写几个辅助函数来使这变得更容易short from a byte[]反之亦然:

short GetShortFromLittleEndianBytes(byte[] data, int startIndex)
{
    return (short)((data[startIndex + 1] << 8)
         | data[startIndex]);
}

byte[] GetLittleEndianBytesFromShort(short data)
{
    byte[] b = new byte[2];
    b[0] = (byte)data;
    b[1] = (byte)(data >> 8 & 0xFF);
    return b;
}

正常化

这里应该做出一个重要的区别:音频标准化 http://en.wikipedia.org/wiki/Audio_normalization is not统计标准化 http://en.wikipedia.org/wiki/Normalization_(statistics)。在这里,我们将对音频数据进行峰值归一化,将信号放大恒定量,使其峰值处于上限。为了对音频数据进行峰值归一化,我们首先找到最大值,从上限中减去它(对于 16 位 PCM 数据,这是 32767)以获得偏移量,然后将每个值增加该偏移量。

因此,为了标准化我们的音频数据,首先扫描它以找到峰值幅度:

byte[] input = ar.ReadData();  // the function you used above
float biggest = -32768F;
float sample;
for (int i = 0; i < input.Length; i += 2)
{
    sample = (float)GetShortFromLittleEndianBytes(input, i);
    if (sample > biggest) biggest = sample;
}

在此刻,biggest包含我们音频数据中的最大值。现在要执行实际的标准化,我们减去biggest从 32767 获取一个与音频数据中最大声样本的峰值偏移相对应的值。接下来,我们将此偏移添加到每个音频样本,有效地增加每个样本的音量,直到我们最大声的样本达到峰值。

float offset = 32767 - biggest;

float[] data = new float[input.length / 2];
for (int i = 0; i < input.Length; i += 2)
{
    data[i / 2] = (float)GetShortFromLittleEndianBytes(input, i) + offset;
}

最后一步是将样本从浮点转换为整数值,并将它们存储为小尾数shorts.

byte[] output = new byte[input.Length];
for (int i = 0; i < output.Length; i += 2)
{
    byte[] tmp = GetLittleEndianBytesFromShort(Convert.ToInt16(data[i / 2]));
    output[i] = tmp[0];
    output[i + 1] = tmp[1];
}

我们就完成了!现在您可以发送output字节数组,其中包含规范化的 PCM 数据,发送到音频播放器。

最后一点,请记住,此代码并不是最有效的;它是最有效的。您可以组合其中几个循环,并且您可能可以使用Buffer.BlockCopy()用于数组复制,以及修改您的short to byte[]辅助函数将字节数组作为参数并将值直接复制到数组中。 我没有做任何这些事情,以便更容易地了解发生了什么。

正如我之前提到的,你应该绝对地阅读有关抖动的内容,因为它将极大地提高音频输出的质量。

我自己一直在从事一个音频项目,所以我通过一些尝试和错误弄清楚了这一切;我希望它能帮助某人。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

规范化音频,如何将浮点数组转换为字节数组? 的相关文章

  • Mono 无法保存用户设置

    我在 Mono Ubuntu 上保存用户设置时遇到问题 这是代码示例 private void Form1 Load object sender EventArgs e string savedText Properties Setting
  • 在 OpenCL 中将函数作为参数传递

    是否可以在 OpenCL 1 2 中将函数指针传递给内核 我知道可以用C实现 但不知道如何在OpenCL的C中实现 编辑 我想做这篇文章中描述的同样的事情 在 C 中如何将函数作为参数传递 https stackoverflow com q
  • Chromium 嵌入式框架支持 HTML5 音频吗?

    我一直在玩 CefSharp 但似乎无法播放任何音频 我可以让音频控件出现 但它们保持冻结状态 这些是我使用的版本 Chromium 21 0 1180 0 CEF r728 CefSharp 0 12 4596 50 我先尝试了 mp3
  • 通信对象 System.ServiceModel.Channels.ServiceChannel 不能用于通信

    通信对象System ServiceModel Channels ServiceChannel 无法用于通信 因为它处于故障状态 这个错误到底是什么意思 我该如何解决它 您收到此错误是因为您让服务器端发生 NET 异常 并且您没有捕获并处理
  • 处理 fanart.tv Web 服务响应 JSON 和 C#

    我正在尝试使用 fanart tv Webservice API 但有几个问题 我正在使用 Json Net Newtonsoft Json 并通过其他 Web 服务将 JSON 响应直接反序列化为 C 对象 这里的问题是元素名称正在更改
  • 使用实体框架从集合中删除项目

    我正在使用DDD 我有一个 Product 类 它是一个聚合根 public class Product IAggregateRoot public virtual ICollection
  • Linux TUN/TAP:无法从 TAP 设备读回数据

    问题是关于如何正确配置想要使用 Tun Tap 模块的 Linux 主机 My Goal 利用现有的路由软件 以下为APP1和APP2 但拦截并修改其发送和接收的所有消息 由Mediator完成 我的场景 Ubuntu 10 04 Mach
  • ASP .NET MVC,创建类似路由配置的永久链接

    我需要帮助在 MVC 网站中创建类似 URL 路由的永久链接 Slug 已设置为 www xyz com profile slug 代码为 routes MapRoute name Profile url profile slug defa
  • 将数组拆分为特定数量的块

    我知道array chunk 允许将数组拆分为多个块 但块的数量根据元素的数量而变化 我需要的是始终将数组拆分为特定数量的数组 例如 4 个数组 以下代码将数组分为 3 个块 两个块各有 2 个元素 1 个块有 1 个元素 我想要的是将数组
  • 转到 C# WPF 中的第一页

    我正在 WPF 中使用导航服务 为了导航到页面 我使用 this NavigationService Navigate new MyPage 为了返回我使用 this NavigationService GoBack 但是如何在不使用的情况
  • Xamarin Android:获取内存中的所有进程

    有没有办法读取所有进程 而不仅仅是正在运行的进程 如果我对 Android 的理解正确的话 一次只有一个进程在运行 其他所有进程都被冻结 后台进程被忽略 您可以使用以下代码片段获取当前正在运行的所有 Android 应用程序进程 Activ
  • 用于从字符串安全转换的辅助函数

    回到 VB6 我编写了一些函数 让我在编码时无需关心字符串的 null 和 数字的 null 和 0 等之间的区别 编码时 没有什么比添加特殊情况更能降低我的工作效率了用于处理可能导致一些不相关错误的数据的代码 9999 10000 如果我
  • C# using 语句、SQL 和 SqlConnection

    使用 using 语句 C SQL 可以吗 private static void CreateCommand string queryString string connectionString using SqlConnection c
  • 是否有一个 C++ 库可以从 PDF 文件中提取文本,例如 PDFBox for Java? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 去年 我使用 PDFBox 在 Java 中创建了一个应用程序来获取某些 PDF 文件中的原始文本 现在
  • 如何检测 C# 中该字典键是否存在?

    我正在使用 Exchange Web 服务托管 API 和联系人数据 我有以下代码 即功能性的 但并不理想 foreach Contact c in contactList string openItemUrl https service
  • 无法使用 Ninject 将依赖项注入到从 Angular 服务调用的 ASP.NET Web API 控制器中

    我将 Ninject 与 ASP NET MVC 4 一起使用 我正在使用存储库 并希望进行构造函数注入以将存储库传递给其中一个控制器 这是实现 StatTracker 接口的上下文对象 EntityFramework public cla
  • 同时从多个流中捕获、最佳方法以及如何减少 CPU 使用率

    我目前正在编写一个应用程序 该应用程序将捕获大量 RTSP 流 在我的例子中为 12 个 并将其显示在 QT 小部件上 当我超过大约 6 7 个流时 问题就会出现 CPU 使用率激增并且出现明显的卡顿 我认为它不是 QT 绘制函数的原因是因
  • 为什么 Ajax.BeginForm 在 Chrome 中不起作用?

    我正在使用 c NET MVC2 并尝试创建一个 ajax 表单来调用删除数据库记录 RemoveRelation 的方法 删除记录的过程正在按预期进行 删除记录后 表单应调用一个 JavaScript 函数 从视觉效果中删除该记录 Rem
  • 泛型、数组和 ClassCastException

    我想这里一定发生了一些我不知道的微妙事情 考虑以下 public class Foo
  • boost::program_options:带有固定和可变标记的参数?

    是否可以在 boost program options 中使用此类参数 program p1 123 p2 234 p3 345 p12 678 即 是否可以使用第一个标记指定参数名称 例如 p 后跟一个数字 是动态的吗 我想避免这种情况

随机推荐

  • 警告:不鼓励在分离的视图控制器上呈现视图控制器

    我的情况与我在这里找到的所有其他示例都不同 我有一个基于选项卡的应用程序 在其中一个选项卡上 用户可以按下一个按钮 同时从网络服务器下载多个文件 我使用 NSOperation 来执行每个下载 以便我可以利用内置的依赖项 下载全部发生在后台
  • 特殊字符匹配失败之前的字边界

    这是我尝试过的 CSharpClassNameRegex new Regex b x36 class function struct enum interface
  • 是否可以找出某个列表是否是固定大小的?

    是否可以找出某些列表是否是固定大小的 我的意思是 例如这段代码 String arr a b List
  • 如何在 Windows 上查询打印队列

    我们正在开发一个关键应用程序 需要对打印的文档进行最好的控制 为了确定打印了哪些文档 我们要检查打印机队列 我们如何查询 Windows 上的打印队列 状态 队列列表 错误 枚举打印机 http msdn microsoft com en
  • Python - 如何从字符串中删除隐藏的符号?

    有时我的字符串里有奇怪的字符 它们在浏览器中不可见 但属于字符串的一部分 并在 len 中计数 我怎样才能摆脱它 Strip 删除正常空间 但不删除该符号 使用来自的字符类别string模块 如果你想允许所有可打印字符 你可以这样做 fro
  • 如何将图像传递给 Django 模板?

    假设views py中对应的函数如下所示 from PIL import Image def get img request img source base image Image open os getcwd deskprod media
  • 为 pyinstaller 创建的 .exe 生成证书

    我为我的公司编写了一个脚本 随机选择员工进行随机药物测试 它工作得非常好 除非我把它交给了使用该程序的人 她点击了它 然后弹出一条消息 询问她是否信任该程序 无论如何点击 运行 后 AVG 在最终加载之前又标记了两次 我读到别人的评论说要在
  • 为什么空行没有存储在变量中

    我正在使用下面的代码 bin bash for host in cat server txt do echo host done server txt 包含 server1 com server2 com server3 com serve
  • 将冻结模型“.pb”文件转换为“.tflite”文件所需的参数 input_arrays 和 output_arrays 是什么?

    我需要转换我的 pb张量流模型和我的 cpkt文件到一个tflite模型以使其在移动设备中工作 有没有什么直接的方法可以找出如何找到我应该用于 input arrays 和 output arrays 的参数 import tensorfl
  • Mongoose getter / setter 用于标准化数据

    I have User模式有一个username场地 我希望此字段区分大小写 以便用户可以注册诸如BobDylan 但是 我需要我的架构来验证新条目 以检查是否有重复项 区分大小写 例如bobdylan 我的研究告诉我 我应该在模式中创建一
  • Delphi 自定义弹出/下拉菜单,如何实现?

    我想制作一个自定义下拉 弹出菜单 其下方有一个很好的阴影 问题是它不是标准菜单 我需要在弹出菜单 下拉菜单中放置一些组件 所以基本上我想要一个下拉菜单 我可以做任何我想做的事情 而不仅仅是简单的菜单项 我希望它像正常的弹出菜单一样工作 问题
  • 箭头键键入大写字母而不是移动光标

    我已经使用 homebrew 安装了最新的 vim 还从 google code 主页安装了 mac vim 在 mac vim 中一切正常 但是当我在 mac 的terminal app 中运行 vim 并进入插入模式时 我会得到 A B
  • 在文件和文件夹的名称中递归地填充 0

    我有一个文件夹 其中包含有关某个特定主题的视频讲座 它的结构如下 1 fol 1 file mp4 2 file mp4 3 file mp4 2 fol 10 file mp4 4 file mp4 5 file mp4 6 file m
  • 谷歌图表重绘/缩放窗口大小

    如何在窗口调整大小时重绘 调整谷歌折线图的大小 为了仅在窗口调整大小完成时重绘并避免多次触发 我认为最好创建一个事件 create trigger to resizeEnd event window resize function if t
  • Kestrel MaxRequestBodySize 上传文件超出限制

    我确实遇到了红隼的一个奇怪的问题 我无法上传超过 kestrel MaxRequestBodySize 的多个文件 预期的行为是抛出BadHttpRequestException当我尝试阅读时this Request Form Files
  • 使用 bash 脚本比较两个文件并打印详细的差异报告

    我在 Unix 系统上有 2 个大文件 每个文件有数千行和大约 80 列 我已根据一组唯一键对文件进行排序 以便我们始终比较相同的行 为了便于理解 我在这里只给出 3 行和 7 列 File 1 d report ref date 2021
  • Angular-Material 设置了只有月份和年份的日期选择器

    我正在使用角度 1 5 9 和角度材料设计 1 1 1 我想添加一个仅包含月份和年份的日期选择器 没有日期 它用于结帐表单中的信用卡到期字段 您可以设置md mode month 下面的工作演示
  • 在opencv上检测非闭合轮廓

    我正在做自动卡检测的计算机视觉项目 我需要将卡片与背景分开 我已经应用了精明的边缘检测 使用自动参数设置 opencv中Canny操作自动计算低阈值和高阈值 https stackoverflow com questions 4292249
  • 将 EJB 作为实例变量注入 servlet 是否安全?

    我们都知道 在 Web 层中 可能只存在给定 Servlet 的单个实例来服务多个请求 这可能会导致实例变量中的线程问题 我的问题是 使用 EJB 注释将 EJB 作为实例变量注入到 servlet 中是否安全 我最初的直觉是否定的 因为假
  • 规范化音频,如何将浮点数组转换为字节数组?

    大家好 我正在播放音频文件 我把它读作byte 然后我需要通过将值放入 1 1 范围内来标准化音频 然后我想将每个浮点值放入byte i 数组然后把它byte 返回到正在播放的音频播放器 我试过这个 byte data ar ReadDat