我如何确定 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 文件的持续时间的主要内容,如果未能解决你的问题,请参考以下文章
如何在不实际转换的情况下确定转换后音频文件的理论文件大小(即 mp3 到 wav)