如何从以毫秒为单位的长度中找到以帧、字节和整数为单位的音符长度
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 中有一些部分涵盖了播放、保存文件,以及关于文件格式和格式转换的好部分(强烈建议您阅读此内容)。
【讨论】:
以上是关于如何从以毫秒为单位的长度中找到以帧、字节和整数为单位的音符长度的主要内容,如果未能解决你的问题,请参考以下文章
如何发现 std::vector 的大小/长度(以字节为单位)?