用两个字节表示音频样本的正确方法是什么?

What is the proper way to represent an audio sample in two bytes?

我正在开发一个应用程序,该应用程序生成代表正弦波的数字序列,并将正弦波保存在 .wav 文件中以作为音频播放。

下面一行代码生成音频波中单个样本的值:

double sample = Math.Sin(2.0 * Math.PI * frequency * i * (1.0 / samplesPerSecond));

生成的 .wav 文件将具有 16 位深度。也就是说,每个样本由 2 个字节 (short) 表示。 double 但是占用 8 个字节。

sample 编码为结果 byte[] 的正确方法是什么?它只能占用 2 个字节?

由于sine的范围有限[-1.0, 1.0],您可以将该范围内的值映射到16位整数的范围[-32768, 32767]

short sample_short = SHORT_MAX * sample;

会有一些舍入误差,但这是将值压缩为不太精确的数据类型所必需的。

公式之所以这么简单,是因为sine的范围是-11。如果您使用的是具有不同范围的其他值,则需要先对其进行归一化:

result = DST_TYPE_MAX * original / ORIGINAL_MAX;

这还假设原始值的范围围绕 0 对称。如果没有,你需要做:

result = DST_TYPE_MAX * (original - ORIGINAL_MIN) / (ORIGINAL_MAX-ORIGINAL_MIN)

这仅适用于范围有限的值。你不能对像 tangent 这样的函数进行这种归一化,因为它的范围是无限的。