如何从以毫秒为单位的长度中找到以帧、字节和整数为单位的音符长度

Posted

技术标签:

【中文标题】如何从以毫秒为单位的长度中找到以帧、字节和整数为单位的音符长度【英文标题】:How to find a note's length in frames, bytes, and ints from its length in milliseconds 【发布时间】:2017-03-01 00:23:20 【问题描述】:

我需要用 Java 编写一个函数,为音频添加特定频率和长度的音符。我有双倍的频率,以及以毫秒为单位的音符长度。

完整功能说明:

This method takes one AudioInputStream and adds the sound of a certain pure frequency to the FRONT of it, lasting a certain length of time. So the method takes two additional parameters: frequency and noteLengthInMilliseconds. The amplitude of the additional sound should be 64*256.

但是,我需要在 Frames 以及 Bytes 和 Ints 中找到笔记的长度。

此外,关于如何将音符创建为样本数据数组(我使用 java.sound.sampled 包)的任何建议都会有所帮助。

帧和采样率:44100.0hz 编码:PCM_SIGNED

【问题讨论】:

什么样的镜框? PCM 帧?采样率是多少?而且,“以及字节和整数”是什么意思? PCM_SIGNED 编码,44,100.0 Hz 采样率 【参考方案1】:

由于您的帧速率和采样率相同,假设您指的是 PCM 帧。一个 PCM 帧是每个通道一个样本。如果您只有一个音频通道,每个样本 16 位,则每两个字节获得一帧。如果您有每个样本 16 位的立体声音频,则每四个字节获得一帧。

要计算长度,请取采样率并将其除以。如果我的采样率为 44.1 kHz,并且我希望音符持续半秒:

44,100 * 0.5 = 22,050 samples (22,050 frames)

如果你知道音频是 16 位的,并且只有一个通道:

22,050 * 2 (bytes per channel) * 1 (channels) = 44,100 bytes

【讨论】:

因此,如果我的长度以毫秒为单位,采样率为 44.1 kHz,我会简单地使用 2 个通道:(44,100 * noteLengthInSeconds) * 2 (bytes per channel) * 2 (channels)? 是的。不要忘记将毫秒转换为秒。【参考方案2】:

以帧为单位的长度是一个简单的计算,它依赖于AudioFormat 中的信息。具体来说,检查属性“frameRate”。每帧的字节数由 frameSize 属性覆盖。

制作音频数据数组需要几个步骤。纯音的值可以通过运行 Math.sin 函数来创建。 Math.PI * 2 相当于一个完整的周期(我希望你已经知道这一点——这是非常初级的),所以使用除法来计算每一步的增量有多小。

Math.sin 函数的结果是介于 -1 和 1 之间的双精度数。您必须将此数字转换为适合分配的数据范围。这是通过将音频值乘以一个因子来完成的。例如,乘以 32767 会得到一个填充 Short 或 16 位有符号的范围。

从 Short 到字节的转换部分取决于您是 big-endian 还是 little-endian。您还必须管理是否有多个音轨(例如,立体声很常见)。所有这些步骤都已在其他 *** 帖子中介绍过。

拥有数据数组后如何处理它,它如何与现有音频结合,部分取决于您是作为音频输出还是尝试创建新的 wav 文件以导出。 Java 教程的Audio Trail 中有一些部分涵盖了播放、保存文件,以及关于文件格式和格式转换的好部分(强烈建议您阅读此内容)。

【讨论】:

以上是关于如何从以毫秒为单位的长度中找到以帧、字节和整数为单位的音符长度的主要内容,如果未能解决你的问题,请参考以下文章

如何以毫秒为单位获取javaFX音频片段的长度[关闭]

读取一个 k 字节块的时间(以毫秒为单位)

如何发现 std::vector 的大小/长度(以字节为单位)?

GeoTools 从以米为单位的 CRS 转换为以度数为单位的 CRS (WGS84)

两个日期时间之间的差异(以毫秒为单位)(Informix)

如何找到纪元时间戳和 std::chrono::system_clock::now 之间的时间差(以毫秒为单位)