9

首先,这是为了家庭作业或……项目。

我无法理解如何将声音数据波绘制到项目的 Java 图形上的想法。我必须使用 UI 和一切从头开始完成这项任务,所以基本上是制作一个 .wav 文件编辑器。 我遇到的主要问题是将声音数据放入要绘制的图表中。目前,我现在正在绘制一个随机生成的值数组。

到目前为止,我有一个小程序正在运行并验证 wav 文件,以便它实际上是一个 wav 文件。

我正在使用 FileInputStream 读取它并验证:RIFF 字节(0-3)、FileLength(4-7)、WAVE 字节(8-11),然后是格式块格式(从 RIFF 块的末尾开始; 并将索引定位到它的末尾并给出格式 0-3,格式块的长度 4-7,然后是波形文件的所有规范的接下来的 16 个字节,并将它们存储在适当的命名变量中。

一旦我到达 DATA 块及其长度,这就是我所有的声音数据,这就是我不确定如何为声音数据字节存储每个字节,甚至将其转换为与振幅相关的值声音。我认为验证是相似的,所以它会是一样的,但它似乎不是那样的......要么就是这样,要么我一直在把一些超级简单的事情复杂化,因为我已经盯着这几天了。

感谢任何帮助。

4

3 回答 3

18

我不是Java程序员,但我对渲染音频有一定的了解,因此希望以下内容可能对您有所帮助...

鉴于您几乎总是拥有比可用像素多得多的样本,明智的做法是从缓存的减少或样本数据的“摘要”中提取。这通常是音频编辑器(例如Audacity)渲染音频数据的方式。事实上,最常见的策略是计算每个像素的样本数,然后找到每个大小为 的块的最大和最小样本SamplesPerPixel,然后在每个最大最小对之间画一条垂直线。您可能希望缓存此缩减,或者可能为不同缩放级别缓存一系列此类缩减。Audacity 缓存到磁盘上的临时文件(“块文件”)。

然而,上面的内容可能过于简单化了,因为实际上您将希望从一块固定大小的样本中计算初始的最大最小对 - 比如 256 个样本 - 而不是从一个 size SamplesPerPixel。然后,您可以从缓存的减少中计算进一步的“动态”减少。关键是这SamplesPerPixel通常是一个动态数量 - 因为用户可能随时调整画布的大小(希望这是有道理的......)。

还要记住,当您在画布上绘图时,您需要按画布的宽度和高度来缩放样本值。最好的方法(至少在垂直方向上)是标准化样本,然后乘以画布高度。16 位音频由 [-32768, 32767] 范围内的样本组成,因此要标准化只需将浮点除以 32768。然后反转符号(将波形翻转到画布坐标),加 1(补偿对于负值)并乘以画布高度的一半。反正我就是这样做的。

本页展示了如何使用 Java Swing 构建基本的波形显示。我没有详细研究它,但我认为它只是对数据进行下采样,而不是计算最大-最小对。当然,这不会提供像 max-min 方法那样精确的减少,但它更容易计算。

如果您想知道如何正确地做事,您应该深入研究 Audacity 源代码(但是请注意 - 它是相当粗糙的 C++)。要获得总体概述,您可以查看Audacity 的原作者 Dominic Mazzoni 的“基于磁盘的音频编辑的快速数据结构” 。但是,您需要从CMJ购买。

于 2012-10-14T05:19:04.830 回答
3

对于标准 WAV 文件,它实际上非常简单。一旦通过标题,您只需将每 16 位解释为二进制补码整数。我建议使用 DataInputStream,因为它就像调用 readShort() 一样简单。

这些是每个采样点的幅度值。您可能想要做一些平均值或其他事情,因为大多数时候样本会比水平像素多得多。尝试在某种折线图上绘制所有样本可能不是最好的方法。

于 2012-10-14T04:51:59.847 回答
1

您需要做的第一件事是读取原始数据。编写 Wav 文件解析器并不太难,但您也可以使用 javasound API。这里有一些关于使用这个 api 的很好的提示和示例代码:

http://www.jsresources.org/

如果你想编写自己的解析器,你可以从这里开始:

https://ccrma.stanford.edu/courses/422/projects/WaveFormat/

获得原始数据后,您可以将其显示为时间函数。这称为波形。

但是,当用户“缩小”大量数据时,显示波形会很耗时:以这种方式呈现一个小时的数据需要很长时间。因此,大多数应用程序会预先计算一些数据,以便更快地绘制缩小的数据。执行此操作的“正确”方法如下:

  • 在文件中的样本块上循环(从 50 到 500 左右)
    • 读取样本块
    • 取所有这些样本的绝对值
    • 取绝对值的最大值
    • 将最大值存储为该块的“缩小”值

当我说“正确”时,我的意思是每个人都这样做,所以它会产生一个看起来像人们期望的视图。如果你做一些不同的事情(例如计算日志或平均而不是寻找峰值)你会得到一些看起来不正确的东西,正如这个家伙发现的那样:

绘制波形 - 转换为 DB 压缩它

于 2012-10-15T15:18:36.607 回答