【问题标题】:How can i determine duration of wav file我如何确定 wav 文件的持续时间
【发布时间】:2019-07-08 13:35:31
【问题描述】:

我正在处理 .wav 文件,我需要以秒为单位获取它们的持续时间。 到目前为止,我一直在确定它:

文件大小/字节速率

Byte_rate 为 (Sample Rate * BitsPerSample * Channels) / 8。 它适用于较小的文件,当我尝试解析较大的文件时,我得到的秒数比实际持续时间长。

例子:

大小(字节):45207622 Byte_rate:176400 持续时间:256 (45207622 / 176400)

但实际持续时间是 250...

仅供参考:我已经仔细检查了大小和字节速率,它们是正确的。

【问题讨论】:

  • 你需要什么编程语言:here是一个python解决方案。
  • 感谢您的回答,我使用 C。在您的链接中它说 frames/frame_rate 但是我不清楚什么是 frame 和 frame_rate,或者我应该如何获得它们。

标签: wav


【解决方案1】:

如果没有示例 RIFF 标头或您的代码,就很难回答您问题中的细节。 (即为什么你的数学没有达到你的预期结果。)

但是,既然您已指定您在 cmets 中使用 C 语言工作,我是否建议您使用 sox 库而不是使用新编写的代码解析标头?除了捕获相当多的边缘情况之外,这还允许您支持任何格式sox 支持读取,而无需自己编写任何读取代码。 (虽然任何倾向于这样做的人可能应该看看Can someone explain .wav(WAVE) file headers?RIFF WAVE format specifications。该过程应该大致是问题中描述的方法,至少在大多数情况下。[编辑:这是块数据长度除以标头的字节率。])

示例代码:

#include <sox.h>
#include <stdio.h>

int main(int argc, char **argv) {
  sox_format_t *fmt;
  if(argc < 2) {
    printf("Please provide audio file.\n");
    return 1;
  }
  fmt = sox_open_read(argv[1], NULL, NULL, NULL);
  __uint64_t ws = fmt->signal.length / fmt->signal.channels;
  if(fmt->signal.length) {
    printf("%0.2f seconds long\n", (double)ws / fmt->signal.rate);
  } else {
    printf("Cannot determine duration from header.\n");
  }
}

对于任何好奇的人,我主要是从sox 命令行工具的源代码中派生出来的。

【讨论】:

    【解决方案2】:

    感谢 EPR 为我修复程序中的时间问题。我没有使用 libsox,我设置了一个结构,试图匹配 http://www.lightlink.com/tjweber/StripWav/Canon.html 的原始结构。这不是正确的方法,但它适用于简单文件。另一个有用的参考是http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html

    无论如何,我假设标头是 44 字节,并将其 read() 到结构所在位置的内存中。然后我可以访问结构的字段,用于 pcm 数据的 malloc 空间,并将其 read() 到文件指针所在的 pcm 空间中。我只是在写一个听力图程序,所以它需要接近正确的我用 arecord、sox、Audacity 生成的 WAV 文件。始终 2 通道,44100 采样率。我的结构:

    struct wavhdr { // defined by Microsoft, needs to match
      char riff[4];  // should be "RIFF"
      uint32_t len8; // file length - 8
      char wave[4];  // should be "WAVE"
      char fmt[4];   // should be "fmt "
      uint32_t fdatalen; // should be 16 (0x10)
      uint16_t ftag;     // format tag, 1 = pcm
      uint16_t channels; // 2 for stereo
      uint32_t sps;      // samples/sec
      uint32_t srate;    // sample rate in bytes/sec (block align)
      uint16_t chan8;    // channels * bits/sample / 8 
      uint16_t bps;      // bits/sample
      char data[4];      // should be "data"
      uint32_t datlen;   // length of data block
      // pcm data follows this  
    } hdr;
    

    我试图使用测量的文件大小 - 标题长度/样本/秒,但没有用,我偏离了 6 倍。

    【讨论】:

      猜你喜欢
      • 2010-09-10
      • 1970-01-01
      • 2011-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-11
      • 1970-01-01
      相关资源
      最近更新 更多