(* 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.