📄 mmreverb.pas
字号:
{========================================================================}
{= (c) 1995-98 SwiftSoft Ronald Dittrich =}
{========================================================================}
{= All Rights Reserved =}
{========================================================================}
{= D 01099 Dresden = Tel.: +0351-8012255 =}
{= Loewenstr.7a = info@swiftsoft.de =}
{========================================================================}
{= Actual versions on http://www.swiftsoft.de/mmtools.html =}
{========================================================================}
{= This code is for reference purposes only and may not be copied or =}
{= distributed in any format electronic or otherwise except one copy =}
{= for backup purposes. =}
{= =}
{= No Delphi Component Kit or Component individually or in a collection=}
{= subclassed or otherwise from the code in this unit, or associated =}
{= .pas, .dfm, .dcu, .asm or .obj files may be sold or distributed =}
{= without express permission from SwiftSoft. =}
{= =}
{= For more licence informations please refer to the associated =}
{= HelpFile. =}
{========================================================================}
{= $Date: 1/29/98 - 5:37:12 PM $ =}
{========================================================================}
unit MMReverb;
{$I COMPILER.INC}
interface
uses
{$IFDEF WIN32}
Windows,
{$ELSE}
WinTypes,
WinProcs,
{$ENDIF}
SysUtils,
Classes,
Controls,
MMSystem,
MMRegs,
MMObj,
MMDSPObj,
MMObjLst,
MMUtils,
MMWaveIO,
MMPCMSup,
MMFX;
type
TMMEchoIndex = 0..MaxEchos-1;
EMMReverbError = class(Exception);
TMMReverb = class;
{-- TMMEcho ----------------------------------------------------------}
TMMEcho = class(TObject)
private
FDelay : Longint; { delay (ms) for this echo line }
FGain : Longint; { mix volume (%) for this echo }
FOnChange: TNotifyEvent;
procedure SetDelay(aValue: Longint);
procedure SetGain(aValue: Longint);
procedure Store(S: TStream); virtual;
procedure Load(S: TStream); virtual;
protected
procedure Changed; virtual;
public
constructor Create;
procedure Assign(Source: TObject);
procedure SetParams(aDelay, aGain: Longint);
property OnChange: TNotifyEvent read FOnChange write FOnChange;
property Delay: Longint read FDelay write SetDelay default 0;
property Gain: Longint read FGain write SetGain default 0;
end;
{-- TMMEchoList ------------------------------------------------------}
TMMEchoList = class(TObjectList)
private
FReverb: TMMReverb;
procedure SetEcho(Index: TMMEchoIndex; Echo: TMMEcho);
function GetEcho(Index: TMMEchoIndex): TMMEcho;
protected
procedure ReadData(S: TStream); override;
procedure WriteData(S: TStream); override;
public
function AddObject(Item: TObject): TOLSize; override;
procedure Assign(Source: TPersistent); override;
property Items[Index: TMMEchoIndex]: TMMEcho read GetEcho write SetEcho; default;
end;
{-- TMMReverb --------------------------------------------------------}
TMMReverb = class(TMMDSPComponent)
private
FEnabled : Boolean;
FOpen : Boolean;
FPReverb : PReverb;
FDescription : String;
FMaxDelay : integer;
FInputGain : TMMEffectVolume;
FInputPan : TMMEffectVolume;
FOutputGain : TMMEffectVolume;
FFeedBack : TMMFeedBack;
FFilter : Boolean;
FEchos : TMMEchoList;
FUpdating : Boolean;
FCleanup : Longint;
FOnChange : TNotifyEvent;
FOnPcmOverflow : TNotifyEvent;
procedure SetEnabled(aValue: Boolean);
procedure SetDescription(aValue: String);
procedure SetMaxDelay(aValue: integer);
procedure SetGains(index: integer; aValue: TMMEffectVolume);
procedure SetFeedBack(aValue: TMMFeedBack);
procedure SetFilter(aValue: Boolean);
procedure SetEchos(aValue: TMMEchoList);
procedure EchosChanged(Sender: TObject);
protected
procedure SetPWaveFormat(aValue: PWaveFormatEx); override;
procedure Assign(Source: TPersistent); override;
procedure Change; dynamic;
procedure Update; virtual;
procedure Opened; override;
procedure Closed; override;
procedure Started; override;
procedure PcmOverflow; dynamic;
procedure BufferReady(lpwh: PWaveHdr); override;
procedure BufferLoad(lpwh: PWaveHdr; var MoreBuffers: Boolean); override;
public
constructor Create(aOwner: TComponent); override;
destructor Destroy; override;
procedure Open;
procedure Close;
procedure Process(Buffer: PChar; Length: integer);
function CleanUp(Buffer: PChar; Length: integer): Longint;
procedure SaveToIniFile(IniFile: TFileName; Section: string);
procedure ReadFromIniFile(IniFile: TFileName; Section: string);
procedure ReadIniSections(IniFile: TFileName; Strings: TStrings);
procedure DeleteSection(IniFile: TFileName; Section: string);
published
property OnChange: TNotifyEvent read FOnChange write FOnChange;
property OnPcmOverflow: TNotifyEvent read FOnPcmOverflow write FOnPcmOverflow;
property Input;
property Output;
property Enabled: Boolean read FEnabled write SetEnabled default True;
property Description: String read FDescription write SetDescription stored False;
property MaxDelay: integer read FMaxDelay write SetMaxDelay stored False;
property InputGain: TMMEffectVolume index 0 read FInputGain write SetGains stored False;
property InputPan: TMMEffectVolume index 1 read FInputPan write SetGains stored False;
property OutputGain: TMMEffectVolume index 2 read FOutputGain write SetGains stored False;
property FeedBack: TMMFeedBack read FFeedback write SetFeedBack stored False;
property Filter: Boolean read FFilter write SetFilter stored False;
property Echos: TMMEchoList read FEchos write SetEchos;
end;
implementation
uses IniFiles;
const
STREAMKENNUNG : Longint = $00425652; { 'RVB ' }
{== TMMEcho =============================================================}
constructor TMMEcho.Create;
begin
inherited Create;
FDelay := 0;
FGain := 0;
FOnChange := nil;
end;
{-- TMMEcho -------------------------------------------------------------}
procedure TMMEcho.Changed;
begin
if assigned(FOnChange) then FOnChange(Self);
end;
{-- TMMEcho -------------------------------------------------------------}
procedure TMMEcho.SetParams(aDelay, aGain: Longint);
begin
if (aDelay <> FDelay) or (aGain <> FGain) then
begin
FDelay := aDelay;
FGain := aGain;
Changed;
end;
end;
{-- TMMEcho -------------------------------------------------------------}
procedure TMMEcho.SetDelay(aValue: Longint);
begin
SetParams(aValue, FGain);
end;
{-- TMMEcho -------------------------------------------------------------}
procedure TMMEcho.SetGain(aValue: Longint);
begin
SetParams(FDelay, aValue);
end;
{-- TMMEcho -------------------------------------------------------------}
procedure TMMEcho.Store(S: TStream);
begin
S.WriteBuffer(FDelay,SizeOf(FDelay));
S.WriteBuffer(FGain,SizeOf(FGain));
end;
{-- TMMEcho -------------------------------------------------------------}
procedure TMMEcho.Load(S: TStream);
var
aDelay,aGain: Longint;
begin
S.ReadBuffer(aDelay,SizeOf(aDelay));
S.ReadBuffer(aGain,SizeOf(aGain));
SetParams(aDelay,aGain);
end;
{-- TMMEcho -------------------------------------------------------------}
procedure TMMEcho.Assign(Source: TObject);
begin
if Source is TMMEcho then
begin
SetParams(TMMEcho(Source).Delay,TMMEcho(Source).Gain);
end;
end;
{== TMMEchoList =========================================================}
procedure TMMEchoList.SetEcho(Index: TMMEchoIndex; Echo: TMMEcho);
begin
Put(Index, Echo);
end;
{-- TMMEchoList ---------------------------------------------------------}
function TMMEchoList.GetEcho(Index: TMMEchoIndex): TMMEcho;
begin
Result := TMMEcho(Get(Index));
end;
{-- TMMEchoList ---------------------------------------------------------}
function TMMEchoList.AddObject(Item: TObject): TOLSize;
begin
Result := inherited AddObject(Item);
(Item as TMMEcho).OnChange := OnChange;
end;
{-- TMMEchoList ---------------------------------------------------------}
procedure TMMEchoList.Assign(Source: TPersistent);
var
i: integer;
Echo: TMMEcho;
begin
if (Source is TMMEchoList) or (Source = nil) then
begin
BeginUpdate;
try
FReverb.FUpdating := True;
FreeAll;
if (Source <> nil) then
for i := 0 to TMMEchoList(Source).Count-1 do
begin
Echo := TMMEcho.Create;
Echo.Assign(TMMEchoList(Source)[i]);
AddObject(Echo);
end;
finally
FReverb.FUpdating := False;
EndUpdate;
end;
exit;
end;
inherited assign(Source);
end;
{-- TMMEchoList ---------------------------------------------------------}
procedure TMMEchoList.ReadData(S: TStream);
Var
pBuf: PChar;
Kennung: Longint;
ObjCount,
Index: TOLSize;
Destroy: Boolean;
Value: Longint;
begin
BeginUpdate;
try
FReverb.FUpdating := True;
S.ReadBuffer(Kennung,sizeOf(STREAMKENNUNG));
if (Kennung <> STREAMKENNUNG) then
raise EStreamError.Create('Invalid Object stream');
FreeAll;
{ load stream items }
S.ReadBuffer(Destroy,SizeOf(Destroy));
DestroyObjects := Destroy;
{ read string length }
S.ReadBuffer(Value,SizeOf(Value));
if Value > 0 then
begin
pBuf := StrAlloc(Value+1);
try
FillChar(pBuf^, Value+1, 0);
S.ReadBuffer(pBuf^, Value);
FReverb.Description := StrPas(pBuf);
finally
StrDispose(pBuf);
end;
end;
S.ReadBuffer(Value,SizeOf(Value));
FReverb.FMaxDelay := Value;
S.ReadBuffer(Value,SizeOf(Value));
FReverb.FInputGain := Value;
S.ReadBuffer(Value,SizeOf(Value));
FReverb.FInputPan := Value;
S.ReadBuffer(Value,SizeOf(Value));
FReverb.FOutputGain := Value;
S.ReadBuffer(Value,SizeOf(Value));
FReverb.FFeedBack := Value;
S.ReadBuffer(ObjCount,SizeOf(Objcount)); { Read in Object count }
ObjCount := Min(ObjCount,MAXECHOS);
if Capacity-Count < ObjCount then Capacity := Count+ObjCount;
{ Read in Object Count }
for Index := 0 to ObjCount-1 do
AddObject(ReadObjectFromStream(S));
finally
FReverb.FUpdating := False;
EndUpdate;
end;
end;
{-- TMMEchoList ---------------------------------------------------------}
procedure TMMEchoList.WriteData(S: TStream);
var
Index,ObjCount: TOlSize;
Destroy: Boolean;
Value: Longint;
begin
{ Write list to Stream }
S.WriteBuffer(STREAMKENNUNG,SizeOf(STREAMKENNUNG));
Destroy := DestroyObjects;
S.WriteBuffer(Destroy,SizeOf(Destroy));
{ write string length }
Value := Length(FReverb.FDescription);
S.WriteBuffer(Value, SizeOf(Value));
{$IFDEF WIN32}
S.WriteBuffer(PChar(FReverb.FDescription)^, Length(FReverb.FDescription));
{$ELSE}
S.WriteBuffer(FReverb.FDescription[1], Length(FReverb.FDescription));
{$ENDIF}
Value := FReverb.FMaxDelay;
S.WriteBuffer(Value, SizeOf(Value));
Value := FReverb.FInputGain;
S.WriteBuffer(Value, SizeOf(Value));
Value := FReverb.FInputPan;
S.WriteBuffer(Value, SizeOf(Value));
Value := FReverb.FOutputGain;
S.WriteBuffer(Value, SizeOf(Value));
Value := FReverb.FFeedBack;
S.WriteBuffer(Value, SizeOf(Value));
ObjCount := Count;
S.WriteBuffer(ObjCount,SizeOf(ObjCount));
for Index := 0 to Count-1 do
WriteObjectToStream(Items[Index],S);
end;
{== TMMReverb ===========================================================}
constructor TMMReverb.Create(aOwner: TComponent);
var
i: integer;
begin
inherited Create(aOwner);
FEchos := TMMEchoList.Create;
FEchos.OnChange := EchosChanged;
FEchos.FReverb := Self;
for i := 0 to MAXECHOS-1 do FEchos.AddObject(TMMEcho.Create);
FPReverb := nil;
FDescription:= 'Untitled';
FEnabled := True;
FOpen := False;
FUpdating := False;
FMaxDelay := 250;
FInputGain := 80;
FInputPan := 0;
FOutputGain := 100;
FFeedBack := 0;
FFilter := False;
end;
{-- TMMReverb -----------------------------------------------------------}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -