2007. november 28., szerda
Getting the length of a Wav file
Problem/Question/Abstract:
How do I get the length of a Wav file without using a TMediaPlayer to open the file?
Answer:
Getting the length is possible using the MCI_SENDSTRING API call, but that does get involved. However, a better method has been suggested that accesses the file directly and interprets its own internal data to obtain the information.
Here is the function:
function GetWaveLength(WaveFile: string): Double;
var
��groupID: array[0..3] of char;
��riffType: array[0..3] of char;
��BytesPerSec: Integer;
��Stream: TFileStream;
��dataSize: Integer;
// chunk seeking function,
// -1 means: chunk not found
function GotoChunk(ID: string): Integer;
var
��chunkID: array[0..3] of char;
��chunkSize: Integer;
begin
��Result := -1;
with Stream do
��begin
���� // index of first chunk
����Position := 12;
����repeat
������ // read next chunk
������Read(chunkID, 4);
������Read(chunkSize, 4);
�������if chunkID <> ID then
������ // skip chunk
�����Position := Position + chunkSize;
������until(chunkID = ID) or (Position >= Size);
������if chunkID = ID then
�������� // chunk found,
�������� // return chunk size
��������Result := chunkSize;
����end;
end;
begin
��Result := -1;
��Stream := TFileStream.Create(WaveFile, fmOpenRead or fmShareDenyNone);
��with Stream do
����try
������Read(groupID, 4);
������Position := Position + 4; // skip four bytes (file size)
������Read(riffType, 4);
������if(groupID = 'RIFF') and (riffType = 'WAVE') then
�������begin
��������� // search for format chunk
���������if GotoChunk('fmt') <> -1 then
����������begin
����������� // found it
������������Position := Position + 8;
������������Read(BytesPerSec, 4);
�������������� //search for data chunk
��������������dataSize := GotoChunk('data');
��������������if dataSize <> -1 then
���������������� // found it
����������������Result := dataSize / BytesPerSec
������������end
��������end
����finally
������Free;
����end;
end;
This returns the number of seconds as a floating point number, which is not necessarily the most helpful format. Far better to return it as a string representing the time in hours, minutes and seconds. The following function achieves this based on the number of seconds as an integer:
function SecondsToTimeStr(RemainingSeconds: Integer): string;
var
��Hours, Minutes, Seconds: Integer;
��HourString, MinuteString, SecondString: string;
begin
�� // Calculate Minutes
��Seconds := RemainingSeconds mod 60;
��Minutes := RemainingSeconds div 60;
��Hours := Minutes div 60;
��Minutes := Minutes - (Hours * 60);
��if Hours < 10 then
���HourString := '0' + IntToStr(Hours) + ':'
�else
���HourString := IntToStr(Hours) + ':';
��if Minutes < 10 then
����MinuteString := '0' + IntToStr(Minutes) + ':'
��else
����MinuteString := IntToStr(Minutes) + ':';
��if Seconds < 10 then
����SecondString := '0' + IntToStr(Seconds)
��else
����SecondString := IntToStr(Seconds);
��Result := HourString + MinuteString + SecondString;
end;
Having created these functions you can call them from any relevant event - for example a button click:
procedure TForm1.Button1Click(Sender: TObject);
var
�Seconds: Integer;
begin
��Seconds := Trunc(GetWaveLength(Edit1.Text));
//gets only the Integer part of the length
��Label1.Caption := SecondsToTimeStr(Seconds);
end;
You can even reduce this to a single line of code if you prefer:
procedure TForm1.Button1Click(Sender: TObject);
begin
��Label1.Caption := SecondsToTimeStr(Trunc(GetWaveLength(Edit1.Text)));
end;
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése