.wav样本数据值起始索引?

时间:2013-04-26 16:52:53

标签: delphi matlab delphi-7 wav

我一直用this代码来读取delphi中的.wav数据,我一直在比较结果和matlab函数wavread得到的值。从中我可以说matlab函数可以自动识别哪一个是样本数据值,但不能用delphi(但matlab和delphi代码的结果都是一样的)。由于我的delphi代码无法识别样本数据值,我通过数组查看并发现样本数据值起始的索引每个.wav文件都不同。举个例子,我测试了一些.wav文件并得到了这个:

  1. classic1.wav从wavedata []开始的样本数据值.Data [] index number 40
  2. classic2.wav从wavedata []开始的样本数据值.Data [] index number 35
  3. 我通过查看结果y获得了上述结论,[y,Fs,nbits,opts] = wavread('classic1.wav','double');然后我转到结果delphi返回一个数组检查它的值,并从classic1.wav的索引40和classic2.wav的索引40中找到完全相同的值。我想知道是否有一种方法可以知道每个.wav文件的样本数据值的起始索引?

    编辑:我已经更正了类似于给定的reference的记录,它与标题完全正确(从ChunkID到Subchunk2size)但我仍然对它后面的示例数据感到困惑,因为之前的结果没有变化。

    type
    TWaveHeader = packed record
    
        Marker_RIFF: array [0..3] of char;
        ChunkSize: cardinal;
        Marker_WAVE: array [0..3] of char;
    
    
        Marker_fmt: array [0..3] of char;
        SubChunkSize: cardinal;
        FormatTag: word;
        NumChannels: word;
        SampleRate: longint;
        ByteRate: longint;
        BlockAlign:word; 
        BitsPerSample: word;
    
    
        Marker_data: array [0..3] of char;
        DataBytes: longint;
      end;
    
      TChannel = record
      Data : array of smallint;
    
    
    end;
    

2 个答案:

答案 0 :(得分:4)

您显然没有正确地跳过所有标头字段。 Wav文件可以有一些可选的头信息,所以虽然实际的样本值通常从字节44开始,但总是的情况。

请参见此处:https://ccrma.stanford.edu/courses/422/projects/WaveFormat/

直接跳到示例数据的一种方法(在读取所需的标题的任何部分之后)是扫描文件(一次四个字节),用于ascii字符串“data”(64 61 74 61 hex)然后读取紧随其后的4个字节,其中(作为基数或长字)表示要读取的字节的总数。实际样本紧跟在该红衣主教之后。

编辑:

正如预期的那样,在十六进制编辑器中查看文件Classic1.wav和Classic2.wav,很明显它们都有一些元数据。在每个文件中的位置36,而不是找到“数据”的SubchunkID,而是找到“LIST”。此后的四个字节给出了这些附加数据的大小。这是您必须跳过才能获取音乐样本数据。

例如,Classic1.wav从偏移44开始有148个字节的额外数据。这将Subchunk2ID置于偏移192处,Subchunk2Size置于偏移量196处,这意味着第一个样本从文件中的偏移量200开始。

Classic2.wav从偏移44开始有128字节的额外数据。这将Subchunk2ID置于偏移172处,Subchunk2Size置于偏移量176处,这意味着第一个样本从文件中的偏移180开始。

这是一个非常基本的十六进制编辑器中的Classic2.wav: enter image description here

答案 1 :(得分:3)

不是手动执行所有文件I / O,而应使用Win32多媒体API函数 - mmioOpen()mmioDescend()mmioAscend()mmioRead()等让他们为你做所有艰苦的工作。您的代码将更易于管理和阅读,因为您可以更专注于各个块的内容,同时让API处理为您查找每个块的低级细节。