java - 交错式立体声 PCM 线性 Int16 大端音频是什么样的?

标签 java audio pcm audioformat interleave

我知道网上有很多资源解释如何去交织 PCM 数据。在我目前的项目过程中,我已经看过其中的大部分...但我没有音频处理方面的背景,而且我很难找到关于如何确切这种常见形式的详细解释存储音频。

我知道我的音频将有两个 channel ,因此样本将以 [左][右][左][右] 格式存储... 我不明白的是这到底是什么意思。我还读到每个样本都以 [left MSB][left LSB][right MSB][right LSB] 的格式存储。这是否意味着每个 16 位整数实际上编码两个 8 位帧,或者每个 16 位整数是它自己的帧,用于左声道或右声道?

谢谢大家。感谢任何帮助。

编辑:如果您选择举例,请引用以下内容。

方法上下文

具体来说,我要做的是将一个交错的 short[] 转换为两个分别代表左声道或右声道的 float[]。我将用 Java 实现它。

public static float[][] deinterleaveAudioData(short[] interleavedData) {
    //initialize the channel arrays
    float[] left = new float[interleavedData.length / 2];
    float[] right = new float[interleavedData.length / 2];
    //iterate through the buffer
    for (int i = 0; i < interleavedData.length; i++) {
        //THIS IS WHERE I DON'T KNOW WHAT TO DO
    }
    //return the separated left and right channels
    return new float[][]{left, right};
}

我目前的实现

我试过播放由此产生的音频。它非常接近,接近到你可以理解一首歌的歌词,但显然仍然不是正确的方法。

public static float[][] deinterleaveAudioData(short[] interleavedData) {
    //initialize the channel arrays
    float[] left = new float[interleavedData.length / 2];
    float[] right = new float[interleavedData.length / 2];
    //iterate through the buffer
    for (int i = 0; i < left.length; i++) {
        left[i] = (float) interleavedData[2 * i];
        right[i] = (float) interleavedData[2 * i + 1];
    }
    //return the separated left and right channels
    return new float[][]{left, right};
}

格式

如果有人想了解有关音频格式的更多信息,以下是我所有的信息。

  • 格式为 PCM 2 channel 交错大端线性 int16
  • 采样率为 44100
  • 每个 short[] 缓冲区的短裤数量为 2048
  • 每个 short[] 缓冲区的帧数为 1024
  • 每个数据包的帧数为 1

最佳答案

I do understand that my audio will have two channels and thus the samples will be stored in the format [left][right][left][right]... What I don't understand is what exactly this means.

交错 PCM 数据在每个 channel 存储一个样本,在继续下一个样本之前按 channel 顺序存储。 PCM 由每个 channel 的一组样本组成。如果您有左右声道的立体声音频,则每个声道的一个样本一起构成一帧。

  • 第 0 帧:[左样本][右样本]
  • 第 1 帧:[左样本][右样本]
  • 第 2 帧:[左样本][右样本]
  • 第 3 帧:[左样本][右样本]
  • 等...

每个样本都是瞬时压力的测量和数字量化。也就是说,如果每个样本有 8 位,则可以在 256 种可能的精度水平上对压力进行采样。知道声波是……波……有波峰和波谷,我们将希望能够测量到中心的距离。因此,我们可以将中心定义为 127 左右,然后从那里减去和添加(0 到 255,无符号),或者我们可以将这 8 位视为有符号(相同的值,只是对它们的不同解释)并从 -128 到 127。

对于单 channel (单声道)音频,每个样本使用 8 位,我们每个样本使用一个字节,这意味着以 44.1kHz 采样的一秒音频正好使用 44,100 字节的存储空间。

现在,我们假设每个样本 8 位,但在 44.1.kHz 的立体声中。每隔一个字节都将用于左侧,每个其他字节将用于 R。

LRLRLRLRLRLRLRLRLRLRLR...

将它扩展到 16 位,每个样本有两个字节(样本用方括号 [] 设置,空格表示帧边界)

[LL][RR] [LL][RR] [LL][RR] [LL][RR] [LL][RR] [LL][RR]...

I have also read that each sample is stored in the format [left MSB][left LSB][right MSB][right LSB].

不一定。音频可以以任何字节顺序存储。 Little endian 是最常见的,但这不是一个神奇的规则。我确实认为所有 channel 总是按顺序进行,在大多数情况下,左前方是 channel 0。

Does this mean the each 16 bit integer actually encodes two 8 bit frames, or is each 16 bit integer its own frame destined for either the left or right channel?

每个值(在本例中为 16 位整数)都用于单个 channel 。永远不会有两个多字节值相互碰撞。

希望对您有所帮助。我无法运行您的代码,但根据您的描述,我怀疑您遇到了端序问题,并且您的样本不是真正的大端序。

关于java - 交错式立体声 PCM 线性 Int16 大端音频是什么样的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32128206/

相关文章:

java - 如何测试字符串中仅包含字母或撇号?

java - ElasticSearch 中 BoolQuery 的 "filter"的用途是什么?

c++ - 输出音频 (Windows Audio API) - 低频静音

c - Wav 文件多次写入和播放

android - 使用 AmrInputStream 将 PCM-16 转换为 AMR

java - 有没有办法验证数据在发送到网络服务(使用 HTTP 连接)期间是否未更改?

java - 推送通知在 Android 中不起作用,代号一

iphone - 声音引擎泄漏……预加载是一种不好的做法吗?

iphone - 将声音文件上传到服务器

audio - ffmpeg 音频转换 : encoder pcm_u8 working pcm_s8 not