📄 mmreverb.pas
字号:
destructor TMMReverb.Destroy;
begin
Close;
FEchos.Free;
inherited Destroy;
end;
{-- TMMReverb -----------------------------------------------------------}
procedure TMMReverb.PcmOverflow;
begin
if assigned(FOnPcmOverflow) then FOnPcmOverflow(Self);
end;
{-- TMMReverb -----------------------------------------------------------}
procedure TMMReverb.Change;
begin
if assigned(FOnChange) then FOnChange(Self);
end;
{-- TMMReverb -----------------------------------------------------------}
procedure TMMReverb.SetEchos(aValue: TMMEchoList);
begin
if (aValue <> FEchos) then FEchos.Assign(aValue);
end;
{-- TMMReverb -----------------------------------------------------------}
procedure TMMReverb.EchosChanged(Sender: TObject);
begin
if not FUpdating then
begin
Update;
Change;
end;
end;
{-- TMMReverb -----------------------------------------------------------}
procedure TMMReverb.SetPWaveFormat(aValue: PWaveFormatEx);
begin
if (aValue <> nil) then
begin
if not (csDesigning in ComponentState) then
if not pcmIsValidFormat(aValue) then
raise EMMReverbError.Create(LoadResStr(IDS_INVALIDFORMAT));
end;
inherited SetPWaveFormat(aValue);
end;
{-- TMMReverb -----------------------------------------------------------}
procedure TMMReverb.SaveToIniFile(IniFile: TFileName; Section: string);
var
i,j: integer;
begin
if (IniFile <> '') then
begin
with TIniFile.Create(IniFile) do
try
if Pos('Reverb.',Section) = 0 then Section := 'Reverb.'+Section;
WriteInteger(Section, 'MaxDelay', MaxDelay);
WriteInteger(Section, 'InputGain', InputGain);
WriteInteger(Section, 'InputPan', InputPan);
WriteInteger(Section, 'OutputGain', OutputGain);
WriteInteger(Section, 'FeedBack', FeedBack);
WriteBool(Section, 'Filter', Filter);
j := 0;
for i := 0 to Echos.Count-1 do
with Echos[i] do
begin
if (Gain <> 0) then
begin
WriteInteger(Section, 'Delay'+IntToStr(j), Delay);
WriteInteger(Section, 'Gain'+IntToStr(j), Gain);
inc(j);
end;
end;
finally
Free;
end;
end;
end;
{-- TMMReverb -----------------------------------------------------------}
procedure TMMReverb.ReadFromIniFile(IniFile: TFileName; Section: string);
var
i,P: integer;
begin
if (IniFile <> '') then
begin
with TIniFile.Create(IniFile) do
try
if Pos('Reverb.',Section) = 0 then Section := 'Reverb.'+Section;
i := ReadInteger(Section, 'MaxDelay', -1);
if (i > 0) then
try
FUpdating := True;
MaxDelay := ReadInteger(Section, 'MaxDelay', 1000);
InputGain := ReadInteger(Section, 'InputGain', 50);
InputPan := ReadInteger(Section, 'InputPan', 50);
OutputGain := ReadInteger(Section, 'OutputGain', 50);
FeedBack := ReadInteger(Section, 'FeedBack', 0);
Filter := ReadBool(Section, 'Filter', True);
for i := 0 to MAXECHOS-1 do
with Echos[i] do
begin
Delay := ReadInteger(Section, 'Delay'+IntToStr(i), 0);
Gain := ReadInteger(Section, 'Gain'+IntToStr(i), 0);
end;
P := Pos('.',Section);
if (P <> 0) then Section := Copy(Section,P+1,MaxInt);
Description := Section;
finally
FUpdating := False;
Update;
Change;
end;
finally
Free;
end;
end;
end;
{-- TMMReverb -----------------------------------------------------------}
procedure TMMReverb.ReadIniSections(IniFile: TFileName; Strings: TStrings);
var
i, P: integer;
Sections: TStringList;
begin
if (IniFile <> '') and (Strings <> nil) then
begin
with TIniFile.Create(IniFile) do
try
Sections := TStringList.Create;
try
ReadSections(Sections);
Strings.BeginUpdate;
try
Strings.Clear;
for i := 0 to Sections.Count-1 do
begin
P := Pos('.',Sections[i]);
if (P <> 0) then Strings.Add(Copy(Sections[i],P+1,MaxInt));
end;
finally
Strings.EndUpdate;
end;
finally
Sections.Free;
end;
finally
Free;
end;
end;
end;
{-- TMMReverb -----------------------------------------------------------}
procedure TMMReverb.DeleteSection(IniFile: TFileName; Section: string);
begin
if (IniFile <> '') then
begin
with TIniFile.Create(IniFile) do
try
if Pos('Reverb.',Section) = 0 then Section := 'Reverb.'+Section;
EraseSection(Section);
finally
Free;
end;
end;
end;
{-- TMMReverb -----------------------------------------------------------}
procedure TMMReverb.Assign(Source: TPersistent);
begin
if (Source is TMMReverb) then
begin
if (Source <> nil) then
begin
Enabled := TMMReverb(Source).Enabled;
Description:= TMMReverb(Source).Description;
MaxDelay := TMMReverb(Source).MaxDelay;
InputGain := TMMReverb(Source).InputGain;
InputPan := TMMReverb(Source).InputPan;
OutputGain := TMMReverb(Source).OutputGain;
FeedBack := TMMReverb(Source).FeedBack;
Filter := TMMReverb(Source).Filter;
Echos := TMMReverb(Source).Echos;
end;
end;
end;
{-- TMMReverb -----------------------------------------------------------}
procedure TMMReverb.SetDescription(aValue: String);
begin
if (aValue <> FDescription) then
begin
FDescription := aValue;
Change;
end;
end;
{-- TMMReverb -----------------------------------------------------------}
procedure TMMReverb.SetMaxDelay(aValue: integer);
begin
if (aValue <> FMaxDelay) then
begin
FMaxDelay := aValue;
end;
end;
{-- TMMReverb -----------------------------------------------------------}
procedure TMMReverb.SetEnabled(aValue: Boolean);
begin
if (aValue <> FEnabled) then
begin
FEnabled := aValue;
if FEnabled then Update;
end;
end;
{-- TMMReverb -----------------------------------------------------------}
procedure TMMReverb.SetGains(index: integer; aValue: TMMEffectVolume);
begin
case index of
0: if (aValue = FInputGain) then exit
else
begin
FInputGain := aValue;
if FOpen then FPReverb^.InputGain := MulDiv(aValue,256,100);
end;
1: if (aValue = FInputPan) then exit
else
begin
FInputPan := aValue;
if FOpen then FPReverb^.InputPan := MulDiv(aValue,256,100);
end;
2: if (aValue = FOutputGain) then exit
else
begin
FOutputGain := aValue;
if FOpen then FPReverb^.OutputGain := MulDiv(aValue,256,100);
end;
end;
Change;
end;
{-- TMMReverb -----------------------------------------------------------}
procedure TMMReverb.SetFeedBack(aValue: TMMFeedBack);
begin
if (aValue <> FFeedBack) then
begin
FFeedBack := aValue;
if FOpen then FPReverb^.FeedBack := MulDiv(aValue,256,100);
Change;
end;
end;
{-- TMMReverb -----------------------------------------------------------}
procedure TMMReverb.SetFilter(aValue: Boolean);
begin
if (aValue <> FFilter) then
begin
FFilter := aValue;
if FOpen then FPReverb^.OutputFilter := FFilter;
Change;
end;
end;
{-- TMMReverb -----------------------------------------------------------}
procedure TMMReverb.Open;
begin
if not FOpen then
begin
if pcmIsValidFormat(PWaveFormat) then
begin
FPReverb := InitReverb(PWaveFormat, FMaxDelay);
if (FPReverb = nil) then OutOfMemoryError
else
begin
FOpen := True;
Update;
end;
end;
end;
end;
{-- TMMReverb -----------------------------------------------------------}
procedure TMMReverb.Close;
begin
if FOpen then
begin
FOpen := False;
DoneReverb(FPReverb);
end;
end;
{-- TMMReverb -----------------------------------------------------------}
procedure TMMReverb.Process(Buffer: PChar; Length: integer);
begin
{ process the buffer trough the reverb engine }
if (FPReverb <> nil) then
if DoReverb(FPReverb, Buffer, Length) then
GlobalSynchronize(PcmOverflow);
end;
{-- TMMReverb -----------------------------------------------------------}
function TMMReverb.CleanUp(Buffer: PChar; Length: integer): Longint;
begin
{ process the remaining delayed bytes in the delay lines }
if (FPReverb <> nil) and (FCleanup > 0) then
begin
FCleanup := Max(FCleanup - Length,0);
FillChar(Buffer^, Length, 0);
if DoReverb(FPReverb, Buffer, Length) then
GlobalSynchronize(PcmOverflow);
end;
{ return the remaining bytes to process }
Result := FCleanup;
end;
{-- TMMReverb -----------------------------------------------------------}
procedure TMMReverb.Update;
var
i: integer;
_Echos: TEchoArray;
NumEchos: integer;
begin
{ setup the reverb engine with the params }
if FOpen then
begin
NumEchos := 0;
FCleanup := 0;
for i := 0 to Echos.Count-1 do
begin
if (Echos[i].Gain <> 0) then
begin
{ copy in temp record }
_Echos[NumEchos].Delay := Echos[i].Delay;
_Echos[NumEchos].Gain := Echos[i].Gain;
inc(NumEchos);
if Echos[i].Delay > FCleanup then FCleanup := Echos[i].Delay;
end;
end;
if (FCleanup > 0) then
begin
{ convert cleanup time to bytes }
FCleanup := wioTimeToSamples(PWaveFormat,FCleanup*abs(FFeedBack));
end;
{ now update the reverb params }
SetReverb(FPReverb, FFilter, FInputGain, FInputPan,
FOutputGain, FFeedBack, NumEchos, @_Echos);
end;
end;
{-- TMMReverb -----------------------------------------------------------}
procedure TMMReverb.Opened;
begin
Open;
inherited Opened;
end;
{-- TMMReverb -----------------------------------------------------------}
procedure TMMReverb.Closed;
begin
Close;
inherited Closed;
end;
{-- TMMReverb -----------------------------------------------------------}
procedure TMMReverb.Started;
begin
Update;
inherited Started;
end;
{-- TMMReverb -----------------------------------------------------------}
procedure TMMReverb.BufferReady(lpwh: PWaveHdr);
begin
if Enabled and FOpen then
begin
Process(lpwh^.lpData, lpwh^.dwBytesRecorded);
end;
inherited BufferReady(lpwh);
end;
{-- TMMReverb -----------------------------------------------------------}
procedure TMMReverb.BufferLoad(lpwh: PWaveHdr; var MoreBuffers: Boolean);
var
aLength: Longint;
begin
inherited BufferLoad(lpwh, MoreBuffers);
if Enabled and FOpen then
begin
if not MoreBuffers then
begin
aLength := lpwh^.dwBufferLength;
if Cleanup(lpwh^.lpData, aLength) > 0 then MoreBuffers := True;
lpwh^.dwBytesRecorded := aLength;
end
else Process(lpwh^.lpData, lpwh^.dwBytesRecorded);
end;
end;
Initialization
{ register echo class for streaming ! }
DoRegisterClass(@TMMEcho.Load,
@TMMEcho.Store,
TMMEcho);
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -