我正在处理Wave文件。我正在读取所有数据,但在某些文件中,数据大小(要读取的指定字节数)为负,这破坏了读取机制。 Wave文件的字节偏移量是否恒定? x偏移值总是相同吗?
答案 0 :(得分:1)
如果有帮助,这就是我用于wav解码/编码(我几年前编码的):
//---------------------------------------------------------------------------
//--- RIFF WAVE format: 1.01 ------------------------------------------------
//---------------------------------------------------------------------------
#ifndef _RIFF_h
#define _RIFF_h
//---------------------------------------------------------------------------
// 8bit PCM is unsigned
// 16bit PCM is signed 2'os complement little endian (big endian is RIFX)
//---------------------------------------------------------------------------
struct _wave_chunk
{
DWORD ids;
DWORD len;
_wave_chunk(){ ids=' '; len=0; }
_wave_chunk(_wave_chunk& a){ *this=a; }; ~_wave_chunk(){}; _wave_chunk* operator = (const _wave_chunk *a) { *this=*a; return this; }; /*_wave_chunk* operator = (const _wave_chunk &a) { ...copy... return this; };*/
};
struct _wave_hdr
{
DWORD ids; // "RIFF"
DWORD len;
DWORD tps; // "WAVE"
_wave_hdr(){ ids='FFIR'; len=0; tps='EVAW'; }
_wave_hdr(_wave_hdr& a){ *this=a; }; ~_wave_hdr(){}; _wave_hdr* operator = (const _wave_hdr *a) { *this=*a; return this; }; /*_wave_hdr* operator = (const _wave_hdr &a) { ...copy... return this; };*/
};
struct _wave_fmt
{
DWORD ids; // "fmt "
DWORD len; // 16,18,40
WORD format; // 1 = PCM linear quantization
/* 0x0001 WAVE_FORMAT_PCM PCM
0x0003 WAVE_FORMAT_IEEE_FLOAT IEEE float
0x0006 WAVE_FORMAT_ALAW 8-bit ITU-T G.711 A-law
0x0007 WAVE_FORMAT_MULAW 8-bit ITU-T G.711 µ-law
0xFFFE WAVE_FORMAT_EXTENSIBLE Determined by SubFormat */
WORD chanels;
DWORD samplerate;
DWORD byterate;
WORD blockalign;
WORD bits;
WORD ext_len; // extension length 0,22
WORD ext_validbits;
DWORD ext_channelmask;
BYTE ext_subformat[16];
_wave_fmt(){ ids=' tmf'; len=16; format=1; chanels=1; samplerate=44100; bits=8; ext_len=0; ext_validbits=0; ext_channelmask=0; for (int i=0;i<16;i++) ext_subformat[i]=0; compute(); }
_wave_fmt(_wave_fmt& a){ *this=a; }; ~_wave_fmt(){}; _wave_fmt* operator = (const _wave_fmt *a) { *this=*a; return this; }; /*_wave_fmt* operator = (const _wave_fmt &a) { ...copy... return this; };*/
void compute()
{
byterate=(chanels*samplerate*bits)/8;
blockalign=(chanels*bits)/8;
}
};
struct _wave_dat
{
DWORD ids; // "data"
DWORD len;
_wave_dat(){ ids='atad'; len=0; }
_wave_dat(_wave_dat& a){ *this=a; }; ~_wave_dat(){}; _wave_dat* operator = (const _wave_dat *a) { *this=*a; return this; }; /*_wave_dat* operator = (const _wave_dat &a) { ...copy... return this; };*/
};
//---------------------------------------------------------------------------
class wave
{
public:
AnsiString name;
int hnd;
bool readonly;
_wave_hdr hdr;
_wave_fmt fmt;
_wave_dat dat;
wave();
~wave();
void create(AnsiString _name);
void write(BYTE *data,DWORD size);
bool open(AnsiString _name);
DWORD read(BYTE *data,DWORD size);
void close();
};
//---------------------------------------------------------------------------
wave::wave()
{
name=0;
hnd=-1;
readonly=true;
}
//---------------------------------------------------------------------------
wave::~wave()
{
close();
}
//---------------------------------------------------------------------------
void wave::create(AnsiString _name)
{
close();
readonly=true;
// hdr=_wave_hdr();
// fmt=_wave_fmt();
// dat=_wave_dat();
hdr.len=sizeof(hdr)-8;
dat.len=0;
fmt.compute();
name=_name;
hnd=FileCreate(name);
if (hnd<0) return;
FileWrite(hnd,&hdr,sizeof(hdr));
FileWrite(hnd,&fmt,fmt.len+8);
FileWrite(hnd,&dat,sizeof(dat));
readonly=false;
}
//---------------------------------------------------------------------------
bool wave::open(AnsiString _name)
{
close();
readonly=true;
name=_name;
hnd=FileOpen(name,fmOpenRead);
if (hnd<0) return false;
if (FileRead(hnd,&hdr,sizeof(hdr))<sizeof(hdr)){ close(); return false; }
if (hdr.ids!='FFIR') return false;
if (hdr.tps!='EVAW') return false;
_wave_chunk chk;
DWORD sz=sizeof(chk),l;
for(;;)
{
if (FileRead(hnd,&chk,sz)<sz){ close(); return false; }
if (chk.ids==' tmf')
{
fmt.ids=chk.ids;
fmt.len=chk.len;
if (FileRead(hnd,((BYTE*)&fmt)+sz,chk.len)<chk.len){ close(); return false; }
}
else if (chk.ids=='atad')
{
dat.ids=chk.ids;
dat.len=chk.len;
return true;
}
else FileSeek(hnd,int(chk.len),1);
}
}
//---------------------------------------------------------------------------
void wave::write(BYTE *data,DWORD size)
{
if (hnd<0) return;
hdr.len+=size;
dat.len+=size;
if (!readonly) FileWrite(hnd,data,size);
}
//---------------------------------------------------------------------------
DWORD wave::read(BYTE *data,DWORD size)
{
if (hnd<0) return 0;
return FileRead(hnd,data,size);
}
//---------------------------------------------------------------------------
void wave::close()
{
name="";
if (hnd<0) return;
FileSeek(hnd,0,0);
if (!readonly) FileWrite(hnd,&hdr,sizeof(hdr));
FileClose(hnd);
hnd=-1;
}
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
它不支持所有格式,但应该足以比较和修复代码。提取地址...代码基于 C ++ / VCL ,因此您需要将二进制文件访问权限和AnsiString
数据类型移植到您的环境中...
但是负值建议您再次使用带符号的整数(就像在其他question中一样),因此请使用无符号数据类型... RIFF Wave文件绝不会是负面的!
[Edit1]我更新了新格式的代码。
在向Wave格式添加一些扩展名(参见OP下第一个 xbug 的注释中的format info)之后,格式fmt
的块现在可以具有可变大小了。此外,他们还添加了其他几个块(与压缩相关),因此为了可靠地读取数据,您需要根据它们的块大小传递所有 RIFF 块,直到您击中data
块数据样本为止应该跟随...
我的原始代码适用于格式1.0(如前所述,它是几年前编码的),并且没有正确加载较新的wave文件(向 dsp_user 表示感谢)。我用新的格式对其进行了更新,因此可以安全再次使用。
答案 1 :(得分:1)
波形文件的字节偏移量是否恒定?是否总是x偏移 值一样吗?
否,至少不是总是在相同的偏移量找到数据部分。一些简单的程序假定声音采样以固定的偏移量(44)开始,但并非总是如此。 可靠读取wave文件的唯一方法是查找数据部分,一旦找到它,数据大小字段将相对于数据部分偏移+4。
答案 2 :(得分:1)
由于 .wav 标头中的数据大小单位是无符号的,并且由于您获得的是有符号值,这表明您没有正确读取波形标头中的值...