我如何确定WAV文件的持续时间

时间:2019-07-08 13:35:31

标签: wav

我正在使用 .wav 文件,我需要获取它们的持续时间(以秒为单位)。 到目前为止,我一直在用以下方法来确定它:

文件大小/字节速率

Byte_rate为(采样率* BitsPerSample *通道)/ 8。 对于较小的文件,它可以工作,当我尝试解析较大的文件时,我得到的秒数比实际持续时间更长。

  

示例:

     

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

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

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

2 个答案:

答案 0 :(得分:0)

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

但是,由于您已在注释中指定使用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命令行工具的源代码中得出的。

答案 1 :(得分:0)

感谢EPR,我为我的程序中的计时问题提供了解决方案。我没有使用libsox,而是建立了一个试图与http://www.lightlink.com/tjweber/StripWav/Canon.html上的原始文件相匹配的结构。这不是正确的方法,但它适用于简单文件。另一个有用的参考网址是http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html

无论如何,我假设标头是44个字节,并将它read()读入结构位置的内存中。然后,我可以访问struct的字段,用于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倍。