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

Posted

技术标签:

【中文标题】我如何确定 wav 文件的持续时间【英文标题】:How can i determine duration of wav file 【发布时间】: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,或者我应该如何获得它们。 【参考方案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 倍。

【讨论】:

以上是关于我如何确定 wav 文件的持续时间的主要内容,如果未能解决你的问题,请参考以下文章

使用ffmpeg在特定时间向wav文件添加静音[重复]

如何在不实际转换的情况下确定转换后音频文件的理论文件大小(即 mp3 到 wav)

如何确定媒体文件的持续时间?

确定 wav 文件的位深度

您如何确定 NAudio 1.7 中的 midi 文件持续时间(以条为单位)?

如何确定与 AVAudioPlayer 关联的音频文件的长度