从wave文件的读写看程序中struct的设计


在windows中,对于wave音频格式,有如下的一系列结构:
typedef struct waveformat_tag 
{
    WORD    wFormatTag;        
/**//* format type */
    WORD    nChannels;         
/**//* number of channels (i.e. mono, stereo, etc.) */
    DWORD   nSamplesPerSec;    
/**//* sample rate */
    DWORD   nAvgBytesPerSec;   
/**//* for buffer estimation */
    WORD    nBlockAlign;       
/**//* block size of data */
}
 WAVEFORMAT;

typedef 
struct pcmwaveformat_tag 
{
    WAVEFORMAT  wf;
    WORD        wBitsPerSample;
}
 PCMWAVEFORMAT;

struct TWavHeader
{
    
char rId[4];                //标志符(RIFF)
    DWORD rLen;         //数据大小,包括数据头的大小和音频文件的大小
    char wId[4];              //格式类型("WAVE")
    char fId[4];                //"fmt"
    DWORD fLen;         //Sizeof(PCMWAVEFORMAT)
    PCMWAVEFORMAT wavFormat;
    
char dId[4];              //"data"
    DWORD wSampleLength;    //音频数据的大小
}
;

采用这样的结构写的音频文件,文件头会有如下的结果:

不难发现,第0020行明显多出几个字节。这样造成声音文件无法播放出来。

从结构定义角度来看,也不难发现PCMWAVEFORMAT结构中,WAVEFORMAT结构前四个成员已经4字节对齐了,最后一个成员nBlockAlign只占用两字节,按照字节对齐规则,需要在填充两个无效字节,从而保证到4字节对齐;PCMWAVEFORMAT结构还是采用4字节对齐,因此只占用两字节的
最后一个成员wBitsPerSample还需要两字节补齐,因此才有了上图的字节分布。

解决方法就是采用紧缩结构,不允许字节对齐。

从这个亲身经历来看,字节非对齐的结构也是一种潜在的bug,程序中设计的各种结构尽量保持字节对齐是一种好的习惯。

posted on 2008-06-16 11:00 Wealth 阅读(1916) 评论(4)  编辑 收藏 引用 所属分类: C++

评论

# re: 从wave文件的读写看程序中struct的设计 2008-06-16 11:21 Kevin Lynx

有道理,对于用struct写文件这种情况,很容易因为struct的字节对齐问题导致想不到的BUG。尤其是采用直接将struct以二进制方式写入文件的方式写文件。
  回复  更多评论   

# re: 从wave文件的读写看程序中struct的设计 2008-06-17 19:56 Wealth

@Kevin Lynx

对呀,这些bug一般还很难找。  回复  更多评论   

# re: 从wave文件的读写看程序中struct的设计 2008-06-23 01:10 R2仔

用 #pragma pack(2) 来改变字节对齐设置也可以吧  回复  更多评论   

# re: 从wave文件的读写看程序中struct的设计 2008-06-24 14:55 Wealth

@R2仔
在这个应用中是可以的。
但我们在这里讨论的不是几个字节对齐的问题,而是如何避免由于潜在的机制而导致的bug  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2008年6月>
25262728293031
1234567
891011121314
15161718192021
22232425262728
293012345

导航

统计

常用链接

留言簿

随笔分类(8)

随笔档案(8)

文章分类

Around Web

CoBlog

Develop Usage Link

搜索

最新评论

阅读排行榜

评论排行榜