首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何从wav文件中提取声音数据?

如何从wav文件中提取声音数据?
EN

Stack Overflow用户
提问于 2012-10-14 04:05:42
回答 3查看 23K关注 0票数 9

首先这是为了家庭作业或者..。项目。

我很难理解如何在Java中为项目绘制声音数据波的想法。我必须完全从零开始使用UI和任何东西来完成这个任务,所以基本上是制作了一个.wav文件编辑器。我的主要问题是将声音数据输入要绘制的图形中。目前,我正在绘制一个随机生成的值数组.

到目前为止,我有一个微型程序运行和验证的wav文件,它实际上是一个wav文件。

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

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

任何帮助都是非常感谢的。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-10-14 05:19:04

我不是一个Java程序员,但我知道一些关于音频渲染的知识,所以希望下面的内容能有所帮助.

考虑到您几乎总是拥有比可用像素更多的样本,那么明智的做法是从示例数据的缓存缩减或“摘要”中提取。这通常是音频编辑器(如Audacity)呈现音频数据的方式。实际上,最常见的策略是计算每个像素的样本数,然后为每个大小SamplesPerPixel块找到最大和最小样本,然后在每个最大-min对之间画一条垂直线。您可能希望缓存这种缩减,或者针对不同的缩放级别进行一系列这样的缩减。Audacity将缓存到磁盘上的临时文件(“块文件”)。

然而,上述可能有点过于简化,因为在现实中,您将希望从固定大小的块(例如256个样本)中计算初始的max-min对,而不是从一个大小SamplesPerPixel中计算。然后,您可以从缓存的缩减中进一步计算“动态”的缩减。要点是,SamplesPerPixel通常是一个动态的数量--因为用户可能随时调整画布的大小(希望这是合理的.)。

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

This页面展示了如何使用Java构建基本的波形显示。我没有详细地看过它,但我认为它只是降低了数据样本,而不是计算max-min对。当然,这不会像max-min方法那样提供精确的简化,但是计算起来更容易。

如果您想知道如何正确地处理事情,您应该深入了解Audacity源代码(不过,请注意--这是相当粗糙的C++)。要获得一个总体的概述,您可以看看'A Fast Data Structure for Disk-Based Audio Editing',由奥迪的原始作者,多米尼克马佐尼。不过,你需要从CMJ那里购买。

票数 18
EN

Stack Overflow用户

发布于 2012-10-14 04:51:59

对于标准的WAV文件,这实际上是相当容易的。一旦您通过标题,您只需将每16位解释为一个2的补整数。我建议使用DataInputStream,因为它就像调用readShort()一样容易。

这是每个样本点的振幅值。您可能想做一些平均值或其他什么,因为大多数情况下,会有更多的样本比水平像素。尝试在某种线条图上绘制所有的样本可能不是最好的方法。

票数 3
EN

Stack Overflow用户

发布于 2012-10-15 15:18:36

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

http://www.jsresources.org/

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

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

一旦有了原始数据,就可以将其显示为时间的函数。这叫做波形。

但是,当用户对大量数据“放大”时,显示波形是很费时的:一个小时的数据需要很长时间才能以这种方式呈现。因此,大多数应用程序都预先计算了一些数据,以便更快地绘制放大后的数据。这样做的“正确”方式如下:

  • 在文件中的示例块上循环(大约从50到500之间)
    • 读取样本块
    • 取所有这些样品的绝对值
    • 取绝对值的最大值
    • 将最大值存储为该块的“缩放”值。

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

drawing waveform - converting to DB squashes it

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12879210

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档