【问题标题】:How is audio data stored in raw pcm format?原始 pcm 格式的音频数据如何存储?
【发布时间】:2018-04-11 00:44:21
【问题描述】:

我正在编写一个应用程序来处理音频,我首先需要将文件(wav、MP3 等)转换为原始数据(样本显示为浮点数)。

我在cmd中使用ffmpeg:

ffmpeg -i test.wav -f s16le -acodec pcm_s16le output.dat

output.dat 文件中的样本如何表示?我知道一个样本在 S16 下需要两个字节,双通道意味着它存储为 L1 R1 L2 R2 ......但是这个文件是否带有帧表示或 dat 文件中的所有字节都是样本值?两种方法转换后的 test.wav 文件大小不相同。一种是通过libav使用ffmpeg网站上的示例代码,另一种是上面提到的,直接在cmd中使用ffmpeg.exe,前一种方法给我的文件大小略小。当我发现有人说pcm使用框架演示时我很困惑(2048 个样本一帧)。

我实际上不需要任何代码,但希望有人能详细解释原始 pcm 格式。

非常感谢

【问题讨论】:

    标签: ffmpeg pcm audioformat


    【解决方案1】:

    从一个位深度为 16 位、采样率为 44,100 kHz 的立体声 wav 文件开始,您将拥有一个标准 CD 质量的音频文件...在命令行上发出此命令以在文件上显示此类统计信息

    ffprobe Cesária_Évora.wav
    

    典型输出

      Duration: 00:00:21.51, bitrate: 1411 kb/s
        Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 44100 Hz, 2 channels, s16, 1411 kb/s
    

    从 wav 问题创建 PCM 文件

    ffmpeg -i Cesária_Évora.wav -f s16le -acodec pcm_s16le cesaria.dat
    

    请注意,wav 文件只是一个 44 字节的标头,后跟有效负载,这是 PCM 格式的原始音频曲线……这个 PCM 文件严格来说是 L1 R1 L2 R2 仅此而已……任何帧的概念都是抽象我们如何解析没有专门用于实现帧的位(如开始/结束标记)的数据......编写代码来操作 PCM 数据请记住您的位深度以及您的文件是小端还是大端字节序字节结构...只要您的文件的位深度为 8 位,那么您可以安全地忽略字节序,因为您永远不需要移动字节,但是由于上述文件的位深度为 16 位,这意味着音频曲线的每个点都被表示每个通道一个 16 位数字(立体声是两个通道,单声道是一个通道)

    当读取这样一个文件时,这个 16 位数字存储在两个字节中......如果您读取字节时的小端序,最左边的字节(在您遍历文件时第一次在循环中遇到)是后面的最小字节由下一个更重要的字节含义

    L1 R1 L2 R2 
    

    下面我们表示音频曲线上两个 16 位点的立体声表示

    Llittle1 Lbig1 Rlittle1 Rbig1 Llittle2 Lbig2 Rlittle2 Rbig2
    

    当我们谈到用于存储这两个点的单个字节时......上面的注释显示了 8 个字节......类似地,如果我们有 24 个字节的位深度,那么对于一个通道上的一个原始音频样本将如下所示

    Llittle1 Lbigger1 Lbiggest1 Rlittle1 Rbigger1 Rbiggest1  
    

    因此,从概念上讲,当读取位深为 16 位的小端文件时,这里是您如何为原始音频曲线上的一个点解析一个通道的 PCM

    Llittle1 Lbig1
    

    现在要生成单个值 L1 你在概念上这样做

    L1 = ( Lbig1 << shift 8 bits to left ) + Llittle1
    

    不确定这是否是您正在寻找的抽象级别,但它是确定数字音频的垫脚石

    超级有用的工具Audacity 允许您导入我们上面生成的 PCM 格式的原始音频文件 cesaria.dat ... Audacity -> 文件 -> 导入 -> 原始数据 -> 选择 cesaria.dat ->

    【讨论】:

    • 这个答案因其清晰而反映了如此多的知识。很少有人能如此理解音频。
    • wave 文件 L1 L2 R1 R2 是否正确?好吧,我看到一些图表似乎表明了这一点
    【解决方案2】:

    -f s16le 生成一个原始样本转储,没有标题/预告片或任何元数据。所以,它就是L1 R1 C1 L2 R2 C2...,其中 L R C 代表 3 个通道。

    当 ffmpeg 读取这样的文件时,它会一次从每个通道读取和帧 1024 个样本,除非sampling rate/25 小于 1024,在这种情况下,它将读取并打包那些许多样本,例如对于 16000 Hz 的流,sampling rate/25 = 640,小于 1024。所以,ffmpeg 会打包640x2 = 1280 这样一个立体声流的样本。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-28
      • 1970-01-01
      • 2011-09-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多