问题
I now currently try to read .wav file using delphi here is my code :
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;
BytesPerSecond: longint;
BytesPerSample: word;
BitsPerSample: word;
Marker_data: array [0..3] of char;
DataBytes: longint;
end;
TChannel = record
Data : array of double;
end;
some private delcaration
private
wavehdr:TWaveHeader;
wavedata:array[0..3]of TChannel;
numsamples:integer;
the function
FillChar(wavehdr, sizeof(wavehdr), 0);
Stream.Read(wavehdr, sizeof(wavehdr));
{ Log Header data }
with memo1.Lines do begin
Add('Filename : '+od.FileName);
Add('Header size : '+inttostr(sizeof(wavehdr)));
tmpstr := wavehdr.Marker_RIFF;
Add('RIFF ID : '+tmpstr+'');
Add('Chunk size : '+inttostr(wavehdr.ChunkSize));
tmpstr := wavehdr.Marker_WAVE;
Add('WAVE ID : '+tmpstr+'');
tmpstr := wavehdr.Marker_fmt;
Add('''fmt '' ID : '+tmpstr+''' ');
Add('SubChunk size : '+inttostr(wavehdr.SubChunkSize));
Add('Format : '+inttostr(wavehdr.FormatTag));
Add('Num Channels : '+inttostr(wavehdr.NumChannels));
Add('Sample rate : '+inttostr(wavehdr.SampleRate));
Add('Bytes per second : '+inttostr(wavehdr.BytesPerSecond));
Add('Bits per sample : '+inttostr(wavehdr.BitsPerSample));
Add('Block Align : '+inttostr((wavehdr.NumChannels*wavehdr.BitsPerSample)div 8));
end;
numsamples := (file.size div (wavehdr.NumChannels*wavehdr.BitsPerSample)div 8) div wavehdr.BytesPerSample;
case wavehdr.NumChannels of
1:begin
SetLength(wavedata[0].Data, numsamples);
Stream.Read(wavedata[0].Data[0], numsamples);
end;
2:begin
SetLength(wavedata[0].Data, numsamples);
SetLength(wavedata[1].Data, numsamples);
for i := 0 to high(wavedata[0].Data) do begin
Stream.Read(wavedata[0].Data[i], 2);
Stream.Read(wavedata[1].Data[i], 2);
end;
end;
end;
Above code give me the exact same information and detail about the .wav header (same as MATLAB DOES) which is :
- Filename : E:\dephi\classic3.wav
- RIFF ID : RIFF
- Chunk size : 18312354
- WAVE ID : WAVE
- 'fmt ' ID : fmt '
- SubChunk size : 16
- Format : 1 (PCM)
- Num Channels : 2 (Stereo)
- Sample rate : 44100
- Bytes per second : 176400
- Bits per sample : 16
- Block Align : 4
Except the Total Sample Data Which i calculated by (size of wavedata/ blockalign of wavedata)-44, 44 is header of wav. It's not accurate, sometimes is miss by 5,1,10 . I have only tested using 5 sample.And here an example :
- classic1.wav matlab:3420288, delphi(my calculation):(13681352/4)-44= 3420294
- classic2.wav matlab:2912256, delphi(my calculation):(11649204/4)-44= 2912257
And also the sample data value from matlab and delphi is different like
classic1.wav MATLAB:(first 10 value leftchannel and rightchannel)
- -3.05175781250000e-05 [] 6.10351562500000e-05
- -6.10351562500000e-05 [] 6.10351562500000e-05
- -6.10351562500000e-05 [] 3.05175781250000e-05
- 0 [] -3.05175781250000e-05
- 6.10351562500000e-05 [] -6.10351562500000e-05
- 6.10351562500000e-05 [] -6.10351562500000e-05
- 3.05175781250000e-05 [] -3.05175781250000e-05
- 6.10351562500000e-05 [] -6.10351562500000e-05
- 3.05175781250000e-05 [] 0
- -3.05175781250000e-05 [] 6.10351562500000e-05
DELPHI:(first 10 value leftchannel and rightchannel)
- 9.90156960830442E-320 [] 1.00265682167023E-319
- 9.90156960830442E-320 [] 9.77113627780233E-320
- 3.26083326255223E-322 [] 0
- 1.39677298735779E-319 [] 1.37088394751571E-319
- 1.45932169812129E-319 [] 1.33373021094845E-319
- 1.23175506164681E-319 [] 1.206903559661E-319
- 1.28239679034554E-319 [] 1.40932225476216E-319
- 1.37068632125737E-319 [] 1.33382902407761E-319
- 1.33373021094845E-319 [] 1.25685359645555E-319
- 1.40907522193924E-319 [] 1.33358199125469E-319
My question are :
- When Finding the total sample of the wav file, how to do it correctly?
- Are the way matlab and delphi reading wav file (data chunk) in a different way? or maybe my code was the one here is wrong?
- Is there a way to get the same value like MATLAB does?
EDIT : i followed mBo advise and changed it into mbo advise
Data : array of SmallInt;
numsamples := wavehdr.DataBytes div (wavehdr.NumChannels * wavehdr.BitsPerSample div 8);
Stream.Read(wavedata[0].Data[i], SizeOf(SmallInt));
the interpreting part i'm not sure but i changed it into
floattostr(wavedata[0].Data[i]/32768.0)
floattostr(wavedata[1].Data[i]/32768.0)
the result i get :
- 0.611602783203125 [] 0.61932373046875
- 0.611602783203125 [] 0.603546142578125
- 0.0023193359375 [] 0
- 0.862762451171875 [] 0.846771240234375
- 0.901397705078125 [] 0.823822021484375
- 0.760833740234375 [] 0.7454833984375
- 0.7921142578125 [] 0.870513916015625
- 0.799774169921875 [] 0.761016845703125
- 0.8238525390625 [] 0.782623291015625
- 0.354766845703125 [] 0.76123046875
回答1:
Wav-file (Bits per sample : 16) contains signed 16 bit integer data (SmallInt type), but you read data in float 8-byte type Double array.
You can declare
Data : array of SmallInt;
calculate
numsamples := wavehdr.DataBytes div (wavehdr.NumChannels * wavehdr.BitsPerSample div 8);
read them as
Stream.Read(wavedata[0].Data[0], numsamples * SizeOf(SmallInt))
or multichannel case:
Stream.Read(wavedata[0].Data[i], SizeOf(SmallInt));
and then interpret data values as floats Data[i] / 32768.0
note that matlab value 3.05175781250000e-05 = 1/32768.0 is minimal quantum of 16-bit signal
来源:https://stackoverflow.com/questions/16227719/read-wav-file-using-delphi