我有兴趣在 Windows 和 Linux 上用 C 或 C++ 实现音频编辑器。我不知道如何在完全缩小的视图中足够快地显示波形。我不是在寻找有关快速帧缓冲区技术的信息。这是一个关于有效确定显示内容的算法和数据结构的问题。
假设我希望能够编辑 2 小时长的 5 通道、48 KHz、24 位声音。这是 5 GB 的示例数据。我希望能够从每个样本一个像素一直缩小,直到所有样本数据一次可见。我希望应用程序具有响应能力,即使是在一台速度较慢的机器上,例如 1 GHz Atom。当我说响应式时,我希望 GUI 更新通常在用户输入后的 1/30 秒内发生。
在决定为完全缩小的视图渲染什么时,简单的实现会扫描整个波形中的每个样本 - 它需要找到显示器每个像素宽度“覆盖”的所有样本的最大和最小样本值。我编写了一个简单的应用程序来测试这种方法的速度。我在我的 2015 3.5 GHz Xeon 上使用 1 小时长的单声道 16 位 44.1 KHz 样本进行了测试。需要0.12秒。这太慢了数百倍。
您可以想象维护缩小数据的缓存,但我不知道如何避免在大多数插入或删除后重新计算整个缓存。感觉一定有更好的办法。
这是显示我想要实现的目标的图表:
这就是当前大多数可用音频编辑器中的显示方式。用户可能会预料到这种行为。我用 Audacity 进行了测试,它是这样工作的(尽管它也以较浅的颜色显示了样本的平均值)。它可以处理任意插入大声音,似乎是瞬间的。我不会阅读 75 MB 的源代码来了解它是如何实现的。
EDIT:
许多人提出了在显示缩小视图时仅考虑样本子集的方案。我得出的结论是我不想这样做,因为它丢失了太多有用的信息。例如,如果您正在寻找声音中的故障(例如黑胶唱片转换中的咔嗒声),则包含所有样本非常重要。在最坏的情况下,如果故障只有一个样本长,我仍然希望保证它显示在完全缩小的视图中。
阅读 Peter Stock 的回答后,我提出了以下方案。我认为它的显示计算速度比简单方案快大约 500 倍,并且不会为插入或删除增加任何明显的成本。内存开销小于1%。
声音数据将分配在 131072 个样本的块中,因此插入和删除不需要重新分配和复制整个声音。当声音第一次加载时,每个块都将被完全填充(可能除了最后一个)。插入和删除会导致一种碎片。为简单起见,我将安排每个块的开头始终包含有效的样本数据,并且任何间隙都将位于块的末尾。
每个块都有两个与其关联的查找表,一个用于最大值,一个用于最小值。查找表中的每一项对应1024个样本。
下图显示了如何计算显示器一个像素宽度的最大值。它显示了一些与计算相关的块。它假设不存在“碎片”。
插入后,情况稍微复杂一些。现在,两个块的末端都有无效区域。最大查找表中的条目现在对应于样本的部分空区域。这些条目的值只需取最大样本即可找到are展示。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)