这个组件源码。
//waveComp.pas
unit WaveComp;interfaceuses Windows, Messages, Classes, SysUtils, Controls, MMSystem, WaveConsts;type
TWave = class;
TWaveFileStream = class(TObject)
private
FReadEof: Boolean;
FFormat: TWaveFormatEx;
FStream: TFileStream;
FDataPosition: Integer;
FReadPos: Integer;
FWritePos: Integer;
FFileName: string;
FOwner: TWave;
procedure ReadFormat;
function GetSize: Integer;
procedure InternatSaveFile;
procedure SetFileName(const Value: string);
public
constructor Create(FileName: string; AOwner: TWave);
destructor Destroy; override;
procedure ClearWave;
function ReadWave(var Buffer; Count: Integer): Integer;
function WriteWave(const Buffer; Count: Integer): Integer;
procedure SaveToFile(const FileName: string);
property Size: Integer read GetSize;
property Format: TWaveFormatEx read FFormat write FFormat;
property FileName: string read FFileName write SetFileName;
property ReadPos: Integer read FReadPos;
property WritePos: Integer read FWritePos;
end; EWaveFileException = class(Exception); TWave = class(TWinControl)
private
FActive: Boolean;
FFormat: TWaveFormatEx;
FHeaderList: TList;
FWaveStream: TWaveFileStream;
procedure AddBuffer(Header: PWaveHdr);
procedure DeleteBuffer(var Header: PWaveHdr);
procedure CheckActive;
procedure SetFileName(const Value: string);
function GetBitsperSample: TBitsperSample;
function GetChannels: TChannels;
function GetSamplesPerSec: TSamplesPerSec;
procedure SetBitsperSample(const Value: TBitsperSample);
procedure SetChannels(const Value: TChannels);
procedure SetSamplesPerSec(const Value: TSamplesPerSec);
function GetActive: Boolean;
procedure SetFormat(const Value: TWaveFormatEx);
procedure FreeHeaderBuffer;
protected
function GetFileName: string; virtual;
procedure CheckError(msg: string);
procedure SetActive(Value: Boolean); virtual;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Close;
procedure Open;
property Format: TWaveFormatEx read FFormat write SetFormat;
property WaveStream: TWaveFileStream read FWaveStream write FWaveStream;
published
property Active: Boolean read GetActive write SetActive;
{ Channels: 单声/立体声}
property Channels: TChannels read GetChannels write SetChannels;
{ SamplesPerSec: 声音频率 }
property SamplesPerSec: TSamplesPerSec read GetSamplesPerSec write SetSamplesPerSec;
{ SamplesPerSec: 声音位:8位/16位}
property BitsperSample: TBitsperSample read GetBitsperSample write SetBitsperSample;
property FileName: string read GetFileName write SetFileName;
end; EWaveException = class(Exception); TWaveIn = class(TWave)
private
FWaveID: PHWaveIn;
FDataSize: Integer;
FBufferSize: Integer;
FAutoSaveFile: Boolean;
FOnData: TWaveInEvent;
procedure AddPrepareBuffer;
procedure DoDataEvent(Data: Pointer; Count: Integer);
procedure DoAutoSaveFile(Data: Pointer; Count: Integer);
procedure WaveInCallback (var msg:TMessage); message MM_WIM_DATA;
procedure SetAutoSaveFile(const Value: Boolean);
procedure DoCheckWaveFormat;
protected
procedure CheckError(Res: Integer);
procedure SetActive(Value: Boolean); override;
public
constructor Create(AOwner: TComponent); override;
procedure Start;
procedure Stop;
published
property OnData: TWaveInEvent read FOnData write FOnData;
property BufferSize: Integer read FBufferSize write FBufferSize default 3;
property AutoSaveFile: Boolean read FAutoSaveFile write SetAutoSaveFile;
end; TWaveOut = class(TWave)
private
FWaveID: PHWaveOut;
FAutoPlayFile: Boolean;
procedure WaveOutCallback(var msg: TMessage); message MM_WOM_DONE;
procedure VolumeProc(Add: Boolean);
procedure SetAutoPlayFile(const Value: Boolean);
procedure DoCheckWaveFormat;
procedure DoAutoPlayFile;
procedure AutoPlayBuffer;
protected
procedure CheckError(Res: Integer);
procedure SetActive(Value: Boolean); override;
procedure IncVolume;
procedure DecVolume;
public
constructor Create(AOwner: TComponent); override;
procedure PlayBack(Data: Pointer; Count: Integer);
procedure Pause;
procedure ReStart;
published
property AutoPlayFile: Boolean read FAutoPlayFile write SetAutoPlayFile;
end;implementationconst
OpenType: array [Boolean] of Integer = (fmCreate, fmOpenReadWrite or fmShareDenyNone);procedure MakeWaveFormat(var Format: TWaveFormatEx;
Channels, SamplesPerSec, BitsperSample: DWORD);
begin
with Format do
begin
wFormatTag := WAVE_FORMAT_PCM;
nChannels := Channels;
nSamplesPerSec := SamplesPerSec;
wBitsperSample := BitsperSample;
nBlockAlign := nChannels * (wBitsperSample div 8);
nAvgBytesPerSec := nBlockAlign * nSamplesPerSec;
cbSize := 0;
end;
end;function GetLen(S: string): Integer;
var
Len: Integer;
begin
Result := 1;
Len := Length(S);
while not (S[Result] = #0) and (Result < Len) do Inc(Result);
end;procedure FreePointer(var P: Pointer);
begin
FreeMem(P);
P := nil;
end;function IsDesign(Control: TComponent): Boolean;
begin
Result := csDesigning in Control.ComponentState;
end;procedure TWaveFileStream.ClearWave;
begin
FReadPos := FDataPosition;
FWritePos := FDataPosition;
FStream.Size := FDataPosition;
end;procedure TWaveFileStream.SetFileName(const Value: string);
begin
FFileName := Value;
if Assigned(FStream) then
FreeAndNil(FStream);
FStream := TFileStream.Create(FFileName, OpenType[FileExists(FFileName)]);
ReadFormat;
end;constructor TWaveFileStream.Create(FileName: string; AOwner: TWave);
begin
inherited Create;
FOwner := AOwner;
FFileName := FileName;
FStream := TFileStream.Create(FileName, OpenType[FileExists(FFileName)]);
ReadFormat;
end;destructor TWaveFileStream.Destroy;
begin
InternatSaveFile;
FStream.Free;
inherited Destroy;
end;function TWaveFileStream.GetSize: Integer;
begin
Result := FStream.Size - FDataPosition;
end;procedure TWaveFileStream.ReadFormat;
var
I: Integer;
Chunk: TWaveChunkHeader;
Header: TWaveFileHeader;
begin
I := 0;
FillChar(Header, SizeOf(Header), 0);
FillChar(Chunk, SizeOf(Chunk), 0);
if FStream.Size = 0 then
begin
FFormat := PCMFormat;
{ Header, ID_FMT(contain Format), ID_FACT, ID_DATA }
FStream.WriteBuffer(Header, SizeOf(Header));
FStream.WriteBuffer(Chunk, SizeOf(Chunk));
FStream.WriteBuffer(FFormat, SizeOf(FFormat));
FStream.WriteBuffer(Chunk, SizeOf(Chunk));
FStream.WriteBuffer(I, SizeOf(I));
FStream.WriteBuffer(Chunk, SizeOf(Chunk));
FDataPosition := FStream.Position;
FReadPos := FDataPosition;
FWritePos := FDataPosition;
Exit;
end; FStream.ReadBuffer(Header, SizeOf(Header));
if (Header.FType <> ID_RIFF) and (Header.RType <> ID_WAVE) then
raise EWaveFileException.Create(SInvalidWaveFile);
FStream.ReadBuffer(Chunk, SizeOf(Chunk));
while Chunk.CType <> 0 do
begin
case Chunk.CType of
ID_FMT:
FStream.ReadBuffer(FFormat, Chunk.Size);
ID_DATA:
begin
FDataPosition := FStream.Position;
break;
end;
ID_FACT: { save data size }
FStream.Seek(Chunk.Size, soFromCurrent);
else
FStream.Seek(Chunk.Size, soFromCurrent);
end;
FillChar(Chunk, SizeOf(Chunk), 0);
FStream.ReadBuffer(Chunk, SizeOf(Chunk));
end;
FReadPos := FDataPosition;
FWritePos := FDataPosition;
end;procedure TWaveFileStream.InternatSaveFile;
var
Header: TWaveFileHeader;
Chunk: TWaveChunkHeader;
Count: Integer;
begin
{ Header => Chunk(FMT(Format)->FACT->DATA) }
FStream.Position := 0;
Count := Self.Size;
with Header do
begin
FType := ID_RIFF;
Size := Count;
RType := ID_WAVE;
end;
FStream.WriteBuffer(Header, SizeOf(Header));
with Chunk do
begin
{ ID_FMT and Format }
CType := ID_FMT;
Size := SizeOf(FFormat);
FStream.WriteBuffer(Chunk, SizeOf(Chunk));
FStream.WriteBuffer(FFormat, SizeOf(FFormat));
{ ID_FACT and wave data size }
CType := ID_FACT;
Size := SizeOf(Integer);
FStream.WriteBuffer(Chunk, SizeOf(Chunk));
FStream.WriteBuffer(Count, SizeOf(Count));
{ ID_DATA }
CType := ID_DATA;
Size := Count;
FStream.WriteBuffer(Chunk, SizeOf(Chunk));
end;
end;function TWaveFileStream.ReadWave(var Buffer; Count: Integer): Integer;
begin
Result := -1;
if Count <= 0 then Exit;
FStream.Position := FReadPos;
Result := FStream.Read(Buffer, Count);
Inc(FReadPos, Result);
FReadEof := FStream.Size = FReadPos;
end;function TWaveFileStream.WriteWave(const Buffer; Count: Integer): Integer;
begin
Result := -1;
if Count <= 0 then Exit;
FStream.Position := FWritePos;
Result := FStream.Write(Buffer, Count);
Inc(FWritePos, Result);
end;procedure TWaveFileStream.SaveToFile(const FileName: string); function Confirm(S: string): Boolean;
begin
Result := MessageBox(0, PChar(S), PChar(SConfirm), MB_YESNO + MB_ICONWARNING) = IDYES;
end;var
RetVal, Count: Integer;
Buffer: Pointer;
begin
if FileExists(FileName) and not Confirm(SOverlay) then Exit;
InternatSaveFile;
with TFileStream.Create(FileName, fmCreate) do
try
FStream.Position := 0;
Count := 1024000; { 1M }
GetMem(Buffer, Count); { FStream may be huge }
try
RetVal := FStream.Read(Buffer^, Count);
while RetVal > 0 do
begin
WriteBuffer(Buffer^, RetVal);
RetVal := FStream.Read(Buffer^, Count);
end;
finally
FreeMem(Buffer, 0);
end;
finally
Free;
end;
end;{ TWave }procedure TWave.Close;
begin
SetActive(False);
end;constructor TWave.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
Parent := TWinControl(AOwner);
FFormat := PCMFormat;
FActive := False;
FHeaderList := TList.Create;
FWaveStream := nil;
end;destructor TWave.Destroy;
begin
Close;
FreeHeaderBuffer;
FHeaderList.Free;
if Assigned(FWaveStream) then
FreeAndNil(FWaveStream);
inherited Destroy;
end;procedure TWave.Open;
begin
SetActive(True);
end;procedure TWave.SetActive(Value: Boolean);
begin
FActive := Value;
end;function TWave.GetBitsperSample: TBitsperSample;
begin
Result := bs8Bit;
if FFormat.wBitsPerSample = BitsPerSampleValue[bs16Bit] then
Result := bs16Bit;
end;function TWave.GetChannels: TChannels;
begin
Result := ctMono;
if FFormat.nChannels = ChannelValue[ctStereo] then
Result := ctStereo;
end;function TWave.GetSamplesPerSec: TSamplesPerSec;
begin
Result := sp11k;
while FFormat.nSamplesPerSec <> SamplesPerSecValue[Result] do
Inc(Result);
end;procedure TWave.SetBitsperSample(const Value: TBitsperSample);
begin
if BitsPerSample = Value then Exit;
MakeWaveFormat(FFormat, ChannelValue[Channels],
SamplesPerSecValue[SamplesPerSec], BitsPerSampleValue[Value]);
SetFormat(FFormat);
end;procedure TWave.SetChannels(const Value: TChannels);
begin
if Channels = Value then Exit;
MakeWaveFormat(FFormat, ChannelValue[Value], SamplesPerSecValue[SamplesPerSec],
BitsPerSampleValue[BitsPerSample]);
SetFormat(FFormat);
end;procedure TWave.SetSamplesPerSec(const Value: TSamplesPerSec);
begin
if SamplesPerSec = Value then Exit;
MakeWaveFormat(FFormat, ChannelValue[Channels],
SamplesPerSecValue[Value], BitsPerSampleValue[BitsPerSample]);
SetFormat(FFormat);
end;function TWave.GetActive: Boolean;
begin
Result := FActive;
end;procedure TWave.SetFormat(const Value: TWaveFormatEx);
var
Connected: Boolean;
begin
Connected := FActive;
SetActive(False);
FFormat := Value;
SetActive(Connected);
end;procedure TWave.FreeHeaderBuffer;
var
I: Integer;
begin
for I := 0 to FHeaderList.Count - 1 do
begin
FreeMem(PWaveHdr(FHeaderList[I])^.lpData);
FreeMem(FHeaderList[I]);
end;
end;procedure TWave.AddBuffer(Header: PWaveHdr);
begin
if FHeaderList.IndexOf(Header) <> -1 then
FHeaderList.Add(Header);
end;procedure TWave.DeleteBuffer(var Header: PWaveHdr);
begin
if FHeaderList.IndexOf(Header) <> -1 then
begin
FHeaderList.Delete(FHeaderList.IndexOf(Header));
FreePointer(Pointer(Header^.lpData));
FreePointer(Pointer(Header));
end;
end;function TWave.GetFileName: string;
begin
Result := ExtractFilePath(ParamStr(0)) + 'Temp.wav';
if Assigned(FWaveStream) and (FWaveStream.FileName <> '') then
Result := FWaveStream.FileName;
end;procedure TWave.SetFileName(const Value: string);
begin
if Assigned(FWaveStream) then FWaveStream.FileName := Value;
end;procedure TWave.CheckError(msg: string);
begin
SetLength(msg, GetLen(msg));
raise EWaveException.Create(msg);
end;{ TWaveIn }procedure TWaveIn.AddPrepareBuffer;
var
Data: Pointer;
Header: PWaveHdr;
begin
GetMem(Data, FDataSize);
New(Header);
FillChar(Header^, SizeOf(Header), 0);
with Header^ do
begin
lpData := Data;
dwBufferLength := FDataSize;
end;
AddBuffer(Header);
CheckError(waveInPrepareHeader(FWaveID^, Header, SizeOf(TWaveHdr)));
CheckError(waveInAddBuffer(FWaveID^, Header, SizeOf(TWaveHdr)));
end;procedure TWaveIn.DoCheckWaveFormat;
begin
if FAutoSaveFile then
FFormat := FWaveStream.Format;
end;constructor TWaveIn.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FWaveID := nil;
FDataSize := 0;
FBufferSize := 3;
end;procedure TWaveIn.DoDataEvent(Data: Pointer; Count: Integer);
begin
if Assigned(FOnData) then FOnData(Data, Count);
end;procedure TWaveIn.DoAutoSaveFile(Data: Pointer; Count: Integer);
begin
if FAutoSaveFile and Assigned(FWaveStream) then
FWaveStream.WriteWave(Data^, Count);
end;procedure TWaveIn.SetActive(Value: Boolean);
var
I: Integer;
begin
if FActive = Value then Exit;
FActive := Value;
if FActive then
begin
if not Assigned(FWaveID) and not IsDesign(Self) then
try
New(FWaveID);
DoCheckWaveFormat;
CheckError(WaveInOpen(FWaveID, 0, @FFormat, Handle, 0, CALLBACK_WINDOW or WAVE_MAPPED));
FDataSize := FFormat.nAvgBytesPerSec;
for I := 0 to FBufferSize - 1 do AddPrepareBuffer;
CheckError(waveInStart(FWaveID^));
except
FActive := False;
if Assigned(FWaveID) then
try
waveInReset(FWaveID^);
finally
FreeHeaderBuffer;
waveInClose(FWaveID^);
FreePointer(Pointer(FWaveID));
end;
raise;
end;
end else
begin
if Assigned(FWaveID) then
try
WaveInReset(FWaveID^);
finally
FreeHeaderBuffer;
WaveInClose(FWaveID^);
FreePointer(Pointer(FWaveID));
end;
end;
end;procedure TWaveIn.SetAutoSaveFile(const Value: Boolean);
begin
if FAutoSaveFile = Value then Exit;
FAutoSaveFile := Value;
if FAutoSaveFile then
FWaveStream := TWaveFileStream.Create(FileName, Self)
else if Assigned(FWaveStream) then
FreeAndNil(FWaveStream);
end;procedure TWaveIn.Start;
begin
CheckActive;
waveInStart(FWaveID^);
end;procedure TWaveIn.Stop;
begin
CheckActive;
waveInStop(FWaveID^);
end;procedure TWaveIn.WaveInCallback(var msg: TMessage);
var
Header: PWaveHdr;
begin
Header := PWaveHdr(msg.lparam);
if FActive then
begin
CheckError(WaveInUnPrepareHeader(FWaveID^, Header, SizeOf(TWavehdr)));
with Header^ do
begin
DoDataEvent(lpData, dwBytesRecorded);
DoAutoSaveFile(lpData, dwBytesRecorded);
end;
with Header^ do
begin
FillMemory(lpData, FDataSize, 0);
dwBufferLength := FDataSize;
dwBytesRecorded := 0;
dwUser := 0;
dwFlags := 0;
dwLoops := 0;
end;
CheckError(WaveInPrepareHeader(FWaveID^, Header, SizeOf(TWavehdr)));
CheckError(WaveInAddBuffer(FWaveID^, Header, SizeOf(TWaveHdr)));
end else
DeleteBuffer(Header);
end;procedure TWaveIn.CheckError(Res: Integer);
var
S: string;
begin
if Res <> 0 then
begin
SetLength(S, MAXERRORLENGTH);
waveInGetErrorText(Res, PChar(S), MAXERRORLENGTH);
inherited CheckError(S);
end;
end;{ TWaveOut }constructor TWaveOut.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FWaveID := nil;
FAutoPlayFile := False;
end;procedure TWaveOut.WaveOutCallback(var msg: TMessage);
var
Header: PWaveHdr;
begin
Header := PWaveHdr(msg.LParam);
try
if FActive then
begin
CheckError(WaveOutUnPrepareHeader(FWaveID^, Header, SizeOf(TWaveHdr)));
AutoPlayBuffer;
end;
finally
DeleteBuffer(Header);
end;
end;procedure TWaveOut.PlayBack(Data: Pointer; Count: Integer);
var
Buffer: Pointer;
Header: PWaveHdr;
begin
if Count = 0 then Exit;
CheckActive;
if Assigned(FWaveID) then
begin
GetMem(Buffer, Count);
Move(Data^, Buffer^, Count);
New(Header);
FillChar(Header^, SizeOf(TWaveHdr), 0);
with Header^ do
begin
lpData:= Buffer;
dwBufferLength := Count;
dwBytesRecorded := Count;
end;
AddBuffer(Header);
CheckError(WaveOutPrepareHeader(FWaveID^, Header, SizeOf(TWaveHdr)));
CheckError(WaveOutWrite(FWaveID^, Header, SizeOf(TWaveHdr)));
end;
end;procedure TWaveOut.SetAutoPlayFile(const Value: Boolean);
begin
if FAutoPlayFile = Value then Exit;
FAutoPlayFile := Value;
if FAutoPlayFile then
FWaveStream := TWaveFileStream.Create(FileName, Self)
else if Assigned(FWaveStream) then
FreeAndNil(FWaveStream);
end;procedure TWaveOut.AutoPlayBuffer;
var
Buffer: Pointer;
RetVal, Count: Integer;
begin
if FWaveStream.FReadEof then Exit;
Count := C_PlayBufferSize;
if FWaveStream.Size - FWaveStream.ReadPos <= C_PlayBufferSize then
Count := FWaveStream.Size - FWaveStream.ReadPos;
GetMem(Buffer, Count);
try
RetVal := FWaveStream.ReadWave(Buffer^, Count);
if RetVal > 0 then
PlayBack(Buffer, RetVal);
finally
FreeMem(Buffer);
end;
end;procedure TWaveOut.DoAutoPlayFile;
begin
if FAutoPlayFile then
begin
AutoPlayBuffer;
AutoPlayBuffer;
end;
end;procedure TWaveOut.DoCheckWaveFormat;
begin
if FAutoPlayFile then
FFormat := FWaveStream.Format;
end;procedure TWaveOut.SetActive(Value: Boolean);
begin
if FActive = Value then Exit;
FActive := Value;
if FActive then
begin
if not Assigned(FWaveID) and not IsDesign(Self) then
try
New(FWaveID);
DoCheckWaveFormat;
CheckError(WaveOutOpen(FWaveID, 0, @FFormat, Handle, 0, CALLBACK_WINDOW or WAVE_MAPPED));
DoAutoPlayFile;
except
FActive := False;
if Assigned(FWaveID) then
FreePointer(Pointer(FWaveID));
raise;
end;
end else
begin
if Assigned(FWaveID) then
try
WaveOutReset(FWaveID^);
finally
FreeHeaderBuffer;
WaveOutClose(FWaveID^);
FreePointer(Pointer(FWaveID));
end;
end;
end;procedure TWaveOut.Pause;
begin
CheckActive;
waveOutPause(FWaveID^);
end;procedure TWaveOut.ReStart;
begin
CheckActive;
waveOutRestart(FWaveID^);
end;procedure TWave.CheckActive;
begin
if not Active then
CheckError(SNotActive);
end;procedure TWaveOut.DecVolume;
begin
VolumeProc(False);
end;procedure TWaveOut.IncVolume;
begin
VolumeProc(True);
end;procedure TWaveOut.VolumeProc(Add: Boolean);
const
StepValue: array [Boolean] of Integer = (100, -100);
var
Value, CurrVolume: Integer;
begin
CheckActive;
waveOutGetVolume(FWaveID^, @CurrVolume);
Value := CurrVolume div $FFFF;
CurrVolume := Value + StepValue[Add] + Value * Value;
waveOutSetVolume(FWaveID^, CurrVolume);
end;procedure TWaveOut.CheckError(Res: Integer);
var
S: string;
begin
if Res <> 0 then
begin
SetLength(S, MAXERRORLENGTH);
waveOutGetErrorText(Res, PChar(S), MAXERRORLENGTH);
inherited CheckError(S);
end;
end;end.
//waveComp.pas
unit WaveComp;interfaceuses Windows, Messages, Classes, SysUtils, Controls, MMSystem, WaveConsts;type
TWave = class;
TWaveFileStream = class(TObject)
private
FReadEof: Boolean;
FFormat: TWaveFormatEx;
FStream: TFileStream;
FDataPosition: Integer;
FReadPos: Integer;
FWritePos: Integer;
FFileName: string;
FOwner: TWave;
procedure ReadFormat;
function GetSize: Integer;
procedure InternatSaveFile;
procedure SetFileName(const Value: string);
public
constructor Create(FileName: string; AOwner: TWave);
destructor Destroy; override;
procedure ClearWave;
function ReadWave(var Buffer; Count: Integer): Integer;
function WriteWave(const Buffer; Count: Integer): Integer;
procedure SaveToFile(const FileName: string);
property Size: Integer read GetSize;
property Format: TWaveFormatEx read FFormat write FFormat;
property FileName: string read FFileName write SetFileName;
property ReadPos: Integer read FReadPos;
property WritePos: Integer read FWritePos;
end; EWaveFileException = class(Exception); TWave = class(TWinControl)
private
FActive: Boolean;
FFormat: TWaveFormatEx;
FHeaderList: TList;
FWaveStream: TWaveFileStream;
procedure AddBuffer(Header: PWaveHdr);
procedure DeleteBuffer(var Header: PWaveHdr);
procedure CheckActive;
procedure SetFileName(const Value: string);
function GetBitsperSample: TBitsperSample;
function GetChannels: TChannels;
function GetSamplesPerSec: TSamplesPerSec;
procedure SetBitsperSample(const Value: TBitsperSample);
procedure SetChannels(const Value: TChannels);
procedure SetSamplesPerSec(const Value: TSamplesPerSec);
function GetActive: Boolean;
procedure SetFormat(const Value: TWaveFormatEx);
procedure FreeHeaderBuffer;
protected
function GetFileName: string; virtual;
procedure CheckError(msg: string);
procedure SetActive(Value: Boolean); virtual;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Close;
procedure Open;
property Format: TWaveFormatEx read FFormat write SetFormat;
property WaveStream: TWaveFileStream read FWaveStream write FWaveStream;
published
property Active: Boolean read GetActive write SetActive;
{ Channels: 单声/立体声}
property Channels: TChannels read GetChannels write SetChannels;
{ SamplesPerSec: 声音频率 }
property SamplesPerSec: TSamplesPerSec read GetSamplesPerSec write SetSamplesPerSec;
{ SamplesPerSec: 声音位:8位/16位}
property BitsperSample: TBitsperSample read GetBitsperSample write SetBitsperSample;
property FileName: string read GetFileName write SetFileName;
end; EWaveException = class(Exception); TWaveIn = class(TWave)
private
FWaveID: PHWaveIn;
FDataSize: Integer;
FBufferSize: Integer;
FAutoSaveFile: Boolean;
FOnData: TWaveInEvent;
procedure AddPrepareBuffer;
procedure DoDataEvent(Data: Pointer; Count: Integer);
procedure DoAutoSaveFile(Data: Pointer; Count: Integer);
procedure WaveInCallback (var msg:TMessage); message MM_WIM_DATA;
procedure SetAutoSaveFile(const Value: Boolean);
procedure DoCheckWaveFormat;
protected
procedure CheckError(Res: Integer);
procedure SetActive(Value: Boolean); override;
public
constructor Create(AOwner: TComponent); override;
procedure Start;
procedure Stop;
published
property OnData: TWaveInEvent read FOnData write FOnData;
property BufferSize: Integer read FBufferSize write FBufferSize default 3;
property AutoSaveFile: Boolean read FAutoSaveFile write SetAutoSaveFile;
end; TWaveOut = class(TWave)
private
FWaveID: PHWaveOut;
FAutoPlayFile: Boolean;
procedure WaveOutCallback(var msg: TMessage); message MM_WOM_DONE;
procedure VolumeProc(Add: Boolean);
procedure SetAutoPlayFile(const Value: Boolean);
procedure DoCheckWaveFormat;
procedure DoAutoPlayFile;
procedure AutoPlayBuffer;
protected
procedure CheckError(Res: Integer);
procedure SetActive(Value: Boolean); override;
procedure IncVolume;
procedure DecVolume;
public
constructor Create(AOwner: TComponent); override;
procedure PlayBack(Data: Pointer; Count: Integer);
procedure Pause;
procedure ReStart;
published
property AutoPlayFile: Boolean read FAutoPlayFile write SetAutoPlayFile;
end;implementationconst
OpenType: array [Boolean] of Integer = (fmCreate, fmOpenReadWrite or fmShareDenyNone);procedure MakeWaveFormat(var Format: TWaveFormatEx;
Channels, SamplesPerSec, BitsperSample: DWORD);
begin
with Format do
begin
wFormatTag := WAVE_FORMAT_PCM;
nChannels := Channels;
nSamplesPerSec := SamplesPerSec;
wBitsperSample := BitsperSample;
nBlockAlign := nChannels * (wBitsperSample div 8);
nAvgBytesPerSec := nBlockAlign * nSamplesPerSec;
cbSize := 0;
end;
end;function GetLen(S: string): Integer;
var
Len: Integer;
begin
Result := 1;
Len := Length(S);
while not (S[Result] = #0) and (Result < Len) do Inc(Result);
end;procedure FreePointer(var P: Pointer);
begin
FreeMem(P);
P := nil;
end;function IsDesign(Control: TComponent): Boolean;
begin
Result := csDesigning in Control.ComponentState;
end;procedure TWaveFileStream.ClearWave;
begin
FReadPos := FDataPosition;
FWritePos := FDataPosition;
FStream.Size := FDataPosition;
end;procedure TWaveFileStream.SetFileName(const Value: string);
begin
FFileName := Value;
if Assigned(FStream) then
FreeAndNil(FStream);
FStream := TFileStream.Create(FFileName, OpenType[FileExists(FFileName)]);
ReadFormat;
end;constructor TWaveFileStream.Create(FileName: string; AOwner: TWave);
begin
inherited Create;
FOwner := AOwner;
FFileName := FileName;
FStream := TFileStream.Create(FileName, OpenType[FileExists(FFileName)]);
ReadFormat;
end;destructor TWaveFileStream.Destroy;
begin
InternatSaveFile;
FStream.Free;
inherited Destroy;
end;function TWaveFileStream.GetSize: Integer;
begin
Result := FStream.Size - FDataPosition;
end;procedure TWaveFileStream.ReadFormat;
var
I: Integer;
Chunk: TWaveChunkHeader;
Header: TWaveFileHeader;
begin
I := 0;
FillChar(Header, SizeOf(Header), 0);
FillChar(Chunk, SizeOf(Chunk), 0);
if FStream.Size = 0 then
begin
FFormat := PCMFormat;
{ Header, ID_FMT(contain Format), ID_FACT, ID_DATA }
FStream.WriteBuffer(Header, SizeOf(Header));
FStream.WriteBuffer(Chunk, SizeOf(Chunk));
FStream.WriteBuffer(FFormat, SizeOf(FFormat));
FStream.WriteBuffer(Chunk, SizeOf(Chunk));
FStream.WriteBuffer(I, SizeOf(I));
FStream.WriteBuffer(Chunk, SizeOf(Chunk));
FDataPosition := FStream.Position;
FReadPos := FDataPosition;
FWritePos := FDataPosition;
Exit;
end; FStream.ReadBuffer(Header, SizeOf(Header));
if (Header.FType <> ID_RIFF) and (Header.RType <> ID_WAVE) then
raise EWaveFileException.Create(SInvalidWaveFile);
FStream.ReadBuffer(Chunk, SizeOf(Chunk));
while Chunk.CType <> 0 do
begin
case Chunk.CType of
ID_FMT:
FStream.ReadBuffer(FFormat, Chunk.Size);
ID_DATA:
begin
FDataPosition := FStream.Position;
break;
end;
ID_FACT: { save data size }
FStream.Seek(Chunk.Size, soFromCurrent);
else
FStream.Seek(Chunk.Size, soFromCurrent);
end;
FillChar(Chunk, SizeOf(Chunk), 0);
FStream.ReadBuffer(Chunk, SizeOf(Chunk));
end;
FReadPos := FDataPosition;
FWritePos := FDataPosition;
end;procedure TWaveFileStream.InternatSaveFile;
var
Header: TWaveFileHeader;
Chunk: TWaveChunkHeader;
Count: Integer;
begin
{ Header => Chunk(FMT(Format)->FACT->DATA) }
FStream.Position := 0;
Count := Self.Size;
with Header do
begin
FType := ID_RIFF;
Size := Count;
RType := ID_WAVE;
end;
FStream.WriteBuffer(Header, SizeOf(Header));
with Chunk do
begin
{ ID_FMT and Format }
CType := ID_FMT;
Size := SizeOf(FFormat);
FStream.WriteBuffer(Chunk, SizeOf(Chunk));
FStream.WriteBuffer(FFormat, SizeOf(FFormat));
{ ID_FACT and wave data size }
CType := ID_FACT;
Size := SizeOf(Integer);
FStream.WriteBuffer(Chunk, SizeOf(Chunk));
FStream.WriteBuffer(Count, SizeOf(Count));
{ ID_DATA }
CType := ID_DATA;
Size := Count;
FStream.WriteBuffer(Chunk, SizeOf(Chunk));
end;
end;function TWaveFileStream.ReadWave(var Buffer; Count: Integer): Integer;
begin
Result := -1;
if Count <= 0 then Exit;
FStream.Position := FReadPos;
Result := FStream.Read(Buffer, Count);
Inc(FReadPos, Result);
FReadEof := FStream.Size = FReadPos;
end;function TWaveFileStream.WriteWave(const Buffer; Count: Integer): Integer;
begin
Result := -1;
if Count <= 0 then Exit;
FStream.Position := FWritePos;
Result := FStream.Write(Buffer, Count);
Inc(FWritePos, Result);
end;procedure TWaveFileStream.SaveToFile(const FileName: string); function Confirm(S: string): Boolean;
begin
Result := MessageBox(0, PChar(S), PChar(SConfirm), MB_YESNO + MB_ICONWARNING) = IDYES;
end;var
RetVal, Count: Integer;
Buffer: Pointer;
begin
if FileExists(FileName) and not Confirm(SOverlay) then Exit;
InternatSaveFile;
with TFileStream.Create(FileName, fmCreate) do
try
FStream.Position := 0;
Count := 1024000; { 1M }
GetMem(Buffer, Count); { FStream may be huge }
try
RetVal := FStream.Read(Buffer^, Count);
while RetVal > 0 do
begin
WriteBuffer(Buffer^, RetVal);
RetVal := FStream.Read(Buffer^, Count);
end;
finally
FreeMem(Buffer, 0);
end;
finally
Free;
end;
end;{ TWave }procedure TWave.Close;
begin
SetActive(False);
end;constructor TWave.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
Parent := TWinControl(AOwner);
FFormat := PCMFormat;
FActive := False;
FHeaderList := TList.Create;
FWaveStream := nil;
end;destructor TWave.Destroy;
begin
Close;
FreeHeaderBuffer;
FHeaderList.Free;
if Assigned(FWaveStream) then
FreeAndNil(FWaveStream);
inherited Destroy;
end;procedure TWave.Open;
begin
SetActive(True);
end;procedure TWave.SetActive(Value: Boolean);
begin
FActive := Value;
end;function TWave.GetBitsperSample: TBitsperSample;
begin
Result := bs8Bit;
if FFormat.wBitsPerSample = BitsPerSampleValue[bs16Bit] then
Result := bs16Bit;
end;function TWave.GetChannels: TChannels;
begin
Result := ctMono;
if FFormat.nChannels = ChannelValue[ctStereo] then
Result := ctStereo;
end;function TWave.GetSamplesPerSec: TSamplesPerSec;
begin
Result := sp11k;
while FFormat.nSamplesPerSec <> SamplesPerSecValue[Result] do
Inc(Result);
end;procedure TWave.SetBitsperSample(const Value: TBitsperSample);
begin
if BitsPerSample = Value then Exit;
MakeWaveFormat(FFormat, ChannelValue[Channels],
SamplesPerSecValue[SamplesPerSec], BitsPerSampleValue[Value]);
SetFormat(FFormat);
end;procedure TWave.SetChannels(const Value: TChannels);
begin
if Channels = Value then Exit;
MakeWaveFormat(FFormat, ChannelValue[Value], SamplesPerSecValue[SamplesPerSec],
BitsPerSampleValue[BitsPerSample]);
SetFormat(FFormat);
end;procedure TWave.SetSamplesPerSec(const Value: TSamplesPerSec);
begin
if SamplesPerSec = Value then Exit;
MakeWaveFormat(FFormat, ChannelValue[Channels],
SamplesPerSecValue[Value], BitsPerSampleValue[BitsPerSample]);
SetFormat(FFormat);
end;function TWave.GetActive: Boolean;
begin
Result := FActive;
end;procedure TWave.SetFormat(const Value: TWaveFormatEx);
var
Connected: Boolean;
begin
Connected := FActive;
SetActive(False);
FFormat := Value;
SetActive(Connected);
end;procedure TWave.FreeHeaderBuffer;
var
I: Integer;
begin
for I := 0 to FHeaderList.Count - 1 do
begin
FreeMem(PWaveHdr(FHeaderList[I])^.lpData);
FreeMem(FHeaderList[I]);
end;
end;procedure TWave.AddBuffer(Header: PWaveHdr);
begin
if FHeaderList.IndexOf(Header) <> -1 then
FHeaderList.Add(Header);
end;procedure TWave.DeleteBuffer(var Header: PWaveHdr);
begin
if FHeaderList.IndexOf(Header) <> -1 then
begin
FHeaderList.Delete(FHeaderList.IndexOf(Header));
FreePointer(Pointer(Header^.lpData));
FreePointer(Pointer(Header));
end;
end;function TWave.GetFileName: string;
begin
Result := ExtractFilePath(ParamStr(0)) + 'Temp.wav';
if Assigned(FWaveStream) and (FWaveStream.FileName <> '') then
Result := FWaveStream.FileName;
end;procedure TWave.SetFileName(const Value: string);
begin
if Assigned(FWaveStream) then FWaveStream.FileName := Value;
end;procedure TWave.CheckError(msg: string);
begin
SetLength(msg, GetLen(msg));
raise EWaveException.Create(msg);
end;{ TWaveIn }procedure TWaveIn.AddPrepareBuffer;
var
Data: Pointer;
Header: PWaveHdr;
begin
GetMem(Data, FDataSize);
New(Header);
FillChar(Header^, SizeOf(Header), 0);
with Header^ do
begin
lpData := Data;
dwBufferLength := FDataSize;
end;
AddBuffer(Header);
CheckError(waveInPrepareHeader(FWaveID^, Header, SizeOf(TWaveHdr)));
CheckError(waveInAddBuffer(FWaveID^, Header, SizeOf(TWaveHdr)));
end;procedure TWaveIn.DoCheckWaveFormat;
begin
if FAutoSaveFile then
FFormat := FWaveStream.Format;
end;constructor TWaveIn.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FWaveID := nil;
FDataSize := 0;
FBufferSize := 3;
end;procedure TWaveIn.DoDataEvent(Data: Pointer; Count: Integer);
begin
if Assigned(FOnData) then FOnData(Data, Count);
end;procedure TWaveIn.DoAutoSaveFile(Data: Pointer; Count: Integer);
begin
if FAutoSaveFile and Assigned(FWaveStream) then
FWaveStream.WriteWave(Data^, Count);
end;procedure TWaveIn.SetActive(Value: Boolean);
var
I: Integer;
begin
if FActive = Value then Exit;
FActive := Value;
if FActive then
begin
if not Assigned(FWaveID) and not IsDesign(Self) then
try
New(FWaveID);
DoCheckWaveFormat;
CheckError(WaveInOpen(FWaveID, 0, @FFormat, Handle, 0, CALLBACK_WINDOW or WAVE_MAPPED));
FDataSize := FFormat.nAvgBytesPerSec;
for I := 0 to FBufferSize - 1 do AddPrepareBuffer;
CheckError(waveInStart(FWaveID^));
except
FActive := False;
if Assigned(FWaveID) then
try
waveInReset(FWaveID^);
finally
FreeHeaderBuffer;
waveInClose(FWaveID^);
FreePointer(Pointer(FWaveID));
end;
raise;
end;
end else
begin
if Assigned(FWaveID) then
try
WaveInReset(FWaveID^);
finally
FreeHeaderBuffer;
WaveInClose(FWaveID^);
FreePointer(Pointer(FWaveID));
end;
end;
end;procedure TWaveIn.SetAutoSaveFile(const Value: Boolean);
begin
if FAutoSaveFile = Value then Exit;
FAutoSaveFile := Value;
if FAutoSaveFile then
FWaveStream := TWaveFileStream.Create(FileName, Self)
else if Assigned(FWaveStream) then
FreeAndNil(FWaveStream);
end;procedure TWaveIn.Start;
begin
CheckActive;
waveInStart(FWaveID^);
end;procedure TWaveIn.Stop;
begin
CheckActive;
waveInStop(FWaveID^);
end;procedure TWaveIn.WaveInCallback(var msg: TMessage);
var
Header: PWaveHdr;
begin
Header := PWaveHdr(msg.lparam);
if FActive then
begin
CheckError(WaveInUnPrepareHeader(FWaveID^, Header, SizeOf(TWavehdr)));
with Header^ do
begin
DoDataEvent(lpData, dwBytesRecorded);
DoAutoSaveFile(lpData, dwBytesRecorded);
end;
with Header^ do
begin
FillMemory(lpData, FDataSize, 0);
dwBufferLength := FDataSize;
dwBytesRecorded := 0;
dwUser := 0;
dwFlags := 0;
dwLoops := 0;
end;
CheckError(WaveInPrepareHeader(FWaveID^, Header, SizeOf(TWavehdr)));
CheckError(WaveInAddBuffer(FWaveID^, Header, SizeOf(TWaveHdr)));
end else
DeleteBuffer(Header);
end;procedure TWaveIn.CheckError(Res: Integer);
var
S: string;
begin
if Res <> 0 then
begin
SetLength(S, MAXERRORLENGTH);
waveInGetErrorText(Res, PChar(S), MAXERRORLENGTH);
inherited CheckError(S);
end;
end;{ TWaveOut }constructor TWaveOut.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FWaveID := nil;
FAutoPlayFile := False;
end;procedure TWaveOut.WaveOutCallback(var msg: TMessage);
var
Header: PWaveHdr;
begin
Header := PWaveHdr(msg.LParam);
try
if FActive then
begin
CheckError(WaveOutUnPrepareHeader(FWaveID^, Header, SizeOf(TWaveHdr)));
AutoPlayBuffer;
end;
finally
DeleteBuffer(Header);
end;
end;procedure TWaveOut.PlayBack(Data: Pointer; Count: Integer);
var
Buffer: Pointer;
Header: PWaveHdr;
begin
if Count = 0 then Exit;
CheckActive;
if Assigned(FWaveID) then
begin
GetMem(Buffer, Count);
Move(Data^, Buffer^, Count);
New(Header);
FillChar(Header^, SizeOf(TWaveHdr), 0);
with Header^ do
begin
lpData:= Buffer;
dwBufferLength := Count;
dwBytesRecorded := Count;
end;
AddBuffer(Header);
CheckError(WaveOutPrepareHeader(FWaveID^, Header, SizeOf(TWaveHdr)));
CheckError(WaveOutWrite(FWaveID^, Header, SizeOf(TWaveHdr)));
end;
end;procedure TWaveOut.SetAutoPlayFile(const Value: Boolean);
begin
if FAutoPlayFile = Value then Exit;
FAutoPlayFile := Value;
if FAutoPlayFile then
FWaveStream := TWaveFileStream.Create(FileName, Self)
else if Assigned(FWaveStream) then
FreeAndNil(FWaveStream);
end;procedure TWaveOut.AutoPlayBuffer;
var
Buffer: Pointer;
RetVal, Count: Integer;
begin
if FWaveStream.FReadEof then Exit;
Count := C_PlayBufferSize;
if FWaveStream.Size - FWaveStream.ReadPos <= C_PlayBufferSize then
Count := FWaveStream.Size - FWaveStream.ReadPos;
GetMem(Buffer, Count);
try
RetVal := FWaveStream.ReadWave(Buffer^, Count);
if RetVal > 0 then
PlayBack(Buffer, RetVal);
finally
FreeMem(Buffer);
end;
end;procedure TWaveOut.DoAutoPlayFile;
begin
if FAutoPlayFile then
begin
AutoPlayBuffer;
AutoPlayBuffer;
end;
end;procedure TWaveOut.DoCheckWaveFormat;
begin
if FAutoPlayFile then
FFormat := FWaveStream.Format;
end;procedure TWaveOut.SetActive(Value: Boolean);
begin
if FActive = Value then Exit;
FActive := Value;
if FActive then
begin
if not Assigned(FWaveID) and not IsDesign(Self) then
try
New(FWaveID);
DoCheckWaveFormat;
CheckError(WaveOutOpen(FWaveID, 0, @FFormat, Handle, 0, CALLBACK_WINDOW or WAVE_MAPPED));
DoAutoPlayFile;
except
FActive := False;
if Assigned(FWaveID) then
FreePointer(Pointer(FWaveID));
raise;
end;
end else
begin
if Assigned(FWaveID) then
try
WaveOutReset(FWaveID^);
finally
FreeHeaderBuffer;
WaveOutClose(FWaveID^);
FreePointer(Pointer(FWaveID));
end;
end;
end;procedure TWaveOut.Pause;
begin
CheckActive;
waveOutPause(FWaveID^);
end;procedure TWaveOut.ReStart;
begin
CheckActive;
waveOutRestart(FWaveID^);
end;procedure TWave.CheckActive;
begin
if not Active then
CheckError(SNotActive);
end;procedure TWaveOut.DecVolume;
begin
VolumeProc(False);
end;procedure TWaveOut.IncVolume;
begin
VolumeProc(True);
end;procedure TWaveOut.VolumeProc(Add: Boolean);
const
StepValue: array [Boolean] of Integer = (100, -100);
var
Value, CurrVolume: Integer;
begin
CheckActive;
waveOutGetVolume(FWaveID^, @CurrVolume);
Value := CurrVolume div $FFFF;
CurrVolume := Value + StepValue[Add] + Value * Value;
waveOutSetVolume(FWaveID^, CurrVolume);
end;procedure TWaveOut.CheckError(Res: Integer);
var
S: string;
begin
if Res <> 0 then
begin
SetLength(S, MAXERRORLENGTH);
waveOutGetErrorText(Res, PChar(S), MAXERRORLENGTH);
inherited CheckError(S);
end;
end;end.
Button1: TButton;//录音开始
BUtton2: TButton;//录音结束//选择新的wave文件,加入到ListBox中,可以找几个wave文件来试试
procedure TForm1.miSelectClick(Sender: TObject);
var
I: Integer;
begin
with OpenDialog1 do
if Execute then
for I := 0 to Files.Count - 1 do
if ListBox1.Items.IndexOf(Files[I])= -1 then
ListBox1.Items.Add(Files[I]);
end;procedure TForm1.FormCreate(Sender: TObject);
begin
FWaveOut := TWaveOut.Create(Self);
FWaveOut.AutoPlayFile := True; //AutoPlayFile是TWaveOut组件自己控制播放的一个属性,如果你在自己PlayBlack,那就看我原来的例子。
FWaveIn := TWaveIn.Create(Self);
FWaveIn.AutoSaveFile := True; //自己保存到一个文件中:default:当前exe目录的temp.wav
end;//双击ListBox1事件,进行播放指定的wave文件。
procedure TForm1.miPlayClick(Sender: TObject);
var
Index: Integer;
begin
Index := ListBox1.ItemIndex;
if Index = -1 then Exit;
if FWaveOut.Active then FWaveOut.Close;
FWaveOut.FileName := ListBox1.Items[Index];
FWaveOut.Open
end;//用winamp播放一首mp3,然后开始录音,结束后,用FWaveOut来放,试试效果。
procedure TForm1.Button1Click(Sender: TObject);
begin
FWaveIn.Open; //录音开始
end;procedure TForm1.Button2Click(Sender: TObject);
begin
FWaveIn.Close; //录音结束
end;
是不是比原来的好多了。:)原来的在:
http://www.csdn.net/expert/topic/490/490089.shtm
新建的文件是58个字节。它的内容是:Header:
TWaveFileHeader = packed record
FType: Integer; //固定:ID_RIFF
Size: Longint; // 当前wave文件的size(可选)
RType: Integer; //固定:ID_WAVE
end; //wave文件Chunk头格式(CType= ID_FMT/ID_FACT/ID_DATA)
TWaveChunkHeader = packed record
CType: Longint;
Size: Longint;
end;
FileHeader读完后就是ChunkHeader,分三种,如上ID_FMT,ID_FACT(可选),ID_DATA
用Stream的read方法可以读出它的格式。
ID_FMT说明wave文件的中声音的格式,占用字节为: ChunkHeader.Size
然后读出它的Format: TWaveFormatEx,字节数为:ChunkHeader.Size
ID_FACT可以忽略,它是记录当前wave文件中声音的数据流的字节。
ID_DATA,数据流,可以将它用maveOutWrite播放的wave数据流。写一个wave文件正好是反操作,不过要注意写入ID_FMT/ID_DATA的数据流的Size,最好你先不要对ID_FACT的操作,熟悉后再对它操作。:)各位明白了吧。
property Channels: TChannels read GetChannels write SetChannels;
{ SamplesPerSec: 声音频率 }
property SamplesPerSec: TSamplesPerSec read GetSamplesPerSec write SetSamplesPerSec;
{ SamplesPerSec: 声音位:8位/16位}
property BitsperSample: TBitsperSample read GetBitsperSample write SetBitsperSample; 记住这些值越高,录出来的声音越好,不过产生出来的文件也越大。 TACMWaveIn是进行录音功能的,当你Open时,就开始录音了,请配置好它的Format: TWaveFormatEx属性,
如果有录音的流过来,会触发OnData(Data: Pointer; Count: Integer)事件,那么你可以根据需要,是将它存储
到文件流中还是将它发送出去(网络语音,爽),有这个功能,做成网络方面的功能应该很简单了,只要触发这
个事件(OnData),那么用TCP/UDP控件将它发送出去,然后用TACMWaveOut接收播放就完了,这就是什么什么网络语音吧。 TACMWaveOut是将TACMWaveIn录出来的声音进行播放的,它的用法很简单了,像对其它组件用法,Open后再
PlayBack(播放),请将它的Format请和TACMWaveIn的Format请设为一样,这样才不会使声音失帧。函数:
1: procedure SaveStreamToWaveFile(FileName: string; Format: TWaveFormatEx; Stream: TStream);
2: procedure OpenWaveFileToStream(FileName: string; var Format: TWaveFormatEx; Stream: TStream); 第一个函数是将TACMWaveIn的录音后的文件流保存为一个*.wav的文件,它可以为winamp或其它播放器所
认识的格式,在Demo中那个Edit1就是当前的数据流转成edit1.Text所指的wave文件。
第二个是反操作,是将*.wav格式的文件转成TACMWaveOut所认识的文件流(其实就是提取wave文件的数据流),
然后在本程序中播放。在Demo中,就是用它来播放那个Edit1.Text所指的任何wave文件。