Files
lazarus-ccr/components/acs/Src/fileformats/windows/waveconverter.pas

335 lines
7.1 KiB
ObjectPascal
Raw Normal View History

(*
this file is a part of audio components suite v 2.3 (delphi version).
copyright (c) 2002-2005 andrei borovsky. all rights reserved.
see the license file for more details.
you can contact me at acs@compiler4.net
this is the acs for delphi (windows) version of the unit.
*)
{
$Log: waveconverter.pas,v $
Revision 1.1 2005/12/19 18:36:49 z0m3ie
*** empty log message ***
Revision 1.1 2005/09/12 22:04:53 z0m3ie
modified structure again, fileformats are now in an sperat folder.
all File In/Out classes are capsulated from TFileIn and TFileOut
Revision 1.1 2005/08/25 20:18:00 z0m3ie
Version 2.4 restructure
TCDPlayer removed (fits not in component structure)
TMP3ToWavConverter removed (fits not in component structure)
Revision 1.2 2005/08/22 20:17:02 z0m3ie
changed Headers to log
changed mail adress
}
unit waveconverter;
interface
uses
SysUtils,
Windows, Classes, MMSystem, MSAcm;
type
{$IFDEF FPC}
TWaveFormat = WAVEFORMAT;
{$ENDIF}
TRiffID = array[0..3] of char;
TRiffHeader = packed record
ID: TRiffID;
BytesFollowing: DWord;
end;
TACMWaveFormat = packed record
case integer of
0 : (Format : TWaveFormatEx);
1 : (RawData : Array[0..128] of byte);
end;
TWaveConverter = class(TMemoryStream)
private
FMaxFmtSize: DWord;
public
CurrentFormat: TACMWaveFormat;
NewFormat: TACMWaveFormat;
function LoadStream(Stream : TStream): integer;
function Convert: integer;
function SaveWavToStream(MS: TStream): Integer;
constructor Create;
destructor Destroy; override;
end;
implementation
{ TWaveConverter }
function TWaveConverter.Convert: integer;
var
FStreamHandle: HACMStream;
OutputBufferSize: DWord;
FStreamHeader: TACMStreamHeader;
OutPut: Pointer;
begin
FStreamHandle := nil;
//
// Open the stream we're going to use to convert from the current to the
// new format
//
Result := acmStreamOpen(FStreamhandle, nil, CurrentFormat.Format,
NewFormat.Format, nil, 0, 0, ACM_STREAMOPENF_NONREALTIME);
if Result <> 0 then
begin
//SetError('acmStreamOpen', Result);
Exit;
end;
//
// Calculate the size of the converted data
//
Result := acmStreamSize(FStreamHandle, self. Size, OutputBufferSize,
ACM_STREAMSIZEF_SOURCE);
if Result <> 0 then
begin
// SetError('acmStreamSize', Result);
Exit;
end;
//
// Allocate memory for the converted data
//
GetMem(OutPut, OutputBufferSize);
FillChar(OutPut^,OutputBufferSize,#0);
Self.Seek(0,0);
//
// Initialize and prepare a header
//
with FStreamHeader do
begin
cbStruct := SizeOf(TACMStreamHeader);
fdwStatus := 0;
dwUser := 0;
pbSrc := self.Memory;
cbSrcLength := self.Size;
cbSrcLengthUsed := 0;
dwSrcUser := 0;
pbDst := OutPut;
cbDstLength := OutputBufferSize;
cbDstLengthUsed := 0;
dwDstUser := 0;
end;
Result := acmStreamPrepareHeader(FStreamHandle,FStreamHeader, 0);
if Result <> 0 then
begin
// SetError('acmStreamPrepareHeader', Result);
Exit;
end;
//
// Tell acm to convert the stream
//
Result := acmStreamConvert(FStreamHandle,FStreamHeader,
ACM_STREAMCONVERTF_BLOCKALIGN);
if Result <> 0 then
begin
// SetError('acmStreamConvert', Result);
Exit;
end;
//
// Set the format eqaul to the newformat and copy the
// data over to the streams memory
//
Move(NewFormat.RawData, CurrentFormat.RawData, FMaxFmtSize);
Self.SetSize(OutputBufferSize);
Self.Seek(0,0);
Self.Write(Output^, OutputBufferSize);
//
// Unprepeare the header
//
Result := acmStreamUnprepareHeader(FStreamHandle,FStreamHeader, 0);
if Result <> 0 then
begin
// SetError('acmStreamUnprepareHeader', Result);
Exit;
end;
//
// Close the stream
//
Result := acmStreamClose(FStreamHandle, 0);
if Result <> 0 then
begin
// SetError('acmStreamClose', Result);
Exit;
end;
FreeMem(OutPut);
end;
constructor TWaveConverter.Create;
begin
inherited;
acmMetrics(nil, ACM_METRIC_MAX_SIZE_FORMAT, FMaxFmtSize);
FillChar(CurrentFormat.Format, FMaxFmtSize, 0);
FillChar(NewFormat.Format, FMaxFmtSize, 0);
end;
destructor TWaveConverter.Destroy;
begin
inherited;
end;
function TWaveConverter.LoadStream(Stream : TStream): integer;
var
Header: TRiffHeader;
ID: TRiffID;
Mem: Pointer;
Data: PByteArray;
NumRead: Integer;
Pos: Integer;
begin
Result := 0;
try
//read the header
NumRead := Stream.Read(Header, SizeOf(Header));
Pos := NumRead;
NumRead := Stream.Read(ID, SizeOf(ID));
Pos := Pos + NumRead;
if (Header.ID <> 'RIFF') or (ID <> 'WAVE') then
begin
Exit;
end;
while Pos < Stream.Size -1 do
begin
Dec(Pos,7);
Stream.Seek(Pos, soFromBeginning);
NumRead := Stream.Read(Header, SizeOf(Header));
Pos := Pos + NumRead;
if Header.ID = 'fmt ' then
begin
GetMem(Mem, Header.BytesFollowing);
try
NumRead := Stream.Read(Mem^, Header.BytesFollowing);
Pos := Pos + NumRead;
if Header.BytesFollowing < SizeOf(TWaveFormatEx) then
Move(Mem^, CurrentFormat.Format , SizeOf(TWaveFormatEx))
else
Move(Mem^, CurrentFormat.Format, Header.BytesFollowing);
finally
FreeMem(Mem);
end;
end
else
if Header.ID = 'fact' then
begin
GetMem(Data, Header.BytesFollowing);
try
NumRead := Stream.Read(Data^, Header.BytesFollowing);
Pos := Pos + NumRead;
finally
FreeMem(Data);
end;
end
else
if Header.ID = 'data' then
begin
if Header.BytesFollowing > 0 then
begin
GetMem(Data, Header.BytesFollowing);
try
NumRead := Stream.Read(Data^, Header.BytesFollowing);
Pos := Pos + NumRead;
Self.SetSize(Header.BytesFollowing);
Self.Seek(0,0);
Self.Write(Data^, (*Header.BytesFollowing*)self.Size);
finally
FreeMem(Data);
end;
end;
end;
end;
Seek(0,0);
finally
// FileStream.Free;
end;
end;
function TWaveConverter.SaveWavToStream(MS: TStream): Integer;
var
CurrentPos : Integer;
H : TRiffHeader;
ID : TRiffID;
begin
Result := 0;
try
CurrentPos := Position;
H.ID := 'RIFF';
H.BytesFollowing := 0;
MS.Write(H, SizeOf(H));
ID := 'WAVE';
MS.Write(ID, SizeOf(ID));
H.ID := 'fmt ';
H.BytesFollowing := SizeOf(TWaveFormat) + 2;
MS.Write(H, SizeOf(H));
MS.Write(CurrentFormat.Format, SizeOf(TWaveFormat) + 2);
H.ID := 'data';
H.BytesFollowing := Size;
MS.Write(H, SizeOf(H));
Seek(0,0);
// MS.CopyFrom(Self, Size);
// ms.Write( Self, Size);
self.SaveToStream(MS);
MS.Seek(0,0);
H.ID := 'RIFF';
H.BytesFollowing := MS.Size - SizeOf(H) +1;
MS.Write(H,SizeOf(H));
Position := CurrentPos;
// MS.Free;
except
on E: Exception do
begin
Result := MCIERR_FILE_NOT_SAVED;
// SetError('SaveFile', MCIERR_FILE_NOT_SAVED);
end;
end;
end;
end.