我正在使用 .wav 文件,我需要获取它们的持续时间(以秒为单位)。 到目前为止,我一直在用以下方法来确定它:
文件大小/字节速率
Byte_rate为(采样率* BitsPerSample *通道)/ 8。 对于较小的文件,它可以工作,当我尝试解析较大的文件时,我得到的秒数比实际持续时间更长。
示例:
大小(字节):45207622字节率:176400持续时间:256 (45207622/176400)
但是实际持续时间是250 ...
仅供参考:我已经仔细检查了大小和字节率,它们是正确的。
答案 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倍。