📄 mmfftflt.pas
字号:
with pflt^,pflt^.Params[channel] do
begin
EnterCriticalSection(DataSection);
try
{-- ZApolnenie dlya fft --}
for i := 0 to FFTLen_2-1 do
begin
fx[i].re := pIn[i];
fx[i].im := pIn[FFTLen_2+i];
fx[FFTLen_2+i].re :=0;
fx[FFTLen_2+i].im :=0;
end;
{-- DIRECT FFT SIGNAL --}
DoCplxFFTb(pfft,@fx,1);
{-- PEREMNOSENIE Na Impl. Reaction --}
fvecMul2(@fh, @fx, FFTLen);
{-- IFFT ---------------}
DoCplxFFTb(pfft,@fx,-1);
{-- SUMMIR s Hvostom IMPuls reactsi --}
for i := 0 to FFTLen_2-1 do
begin
pOut[i] := Trunc(fx[i].re+old_r[i]);
pOut[FFTLen_2+i] := Trunc(fx[FFTLen_2+i].re+fx[i].im);
old_r[i] := fx[FFTLen_2+i].im;
end;
finally
LeaveCriticalSection(DataSection);
end;
end;
end;
{== GetSignal =================================================================}
procedure GetSignal(pflt: PFFTFilter; pIn: PSmallint; pOut: PIntArray);
{$IFNDEF USEASM}
var
i: integer;
begin
with pflt^ do
for i := 0 to FFTlen-1 do
begin
pOut[i] := pIn^;
inc(pIn,Channels);
end;
{$ELSE}
const
ParmSize = sizeOf(TFilterParams);
asm
// EAX = pflt
// EDX = pIn
// ECX = pOut
push ebx
push esi
push edi
mov esi, TFFTFilter(eax).Channels
mov edi, TFFTFilter(eax).FFTLen
shl esi, 1
xor ebx, ebx
@@loop:
movsx eax, word ptr [edx]
add edx, esi
mov [ecx+4*ebx], eax
movsx eax, word ptr [edx]
add edx, esi
mov [ecx+4*ebx+4], eax
movsx eax, word ptr [edx]
add edx, esi
mov [ecx+4*ebx+8], eax
movsx eax, word ptr [edx]
add edx, esi
mov [ecx+4*ebx+12], eax
add ebx, 4
cmp ebx, edi
jl @@loop
@@exit:
pop edi
pop esi
pop ebx
{$ENDIF}
end;
{== Clip Output ===============================================================}
function ClipOutput(pflt: PFFTFilter; pOut: PSmallArray; channel: integer): Boolean;
{$IFNDEF USEASM}
var
i: integer;
outval: Longint;
pS: PSmallint;
begin
Result := False;
with pflt^,pflt^.Params[channel] do
begin
pS := Pointer(pOut);
for i := 0 to FFTLen-1 do
begin
outval := Out_Buf[i];
if outval > 32767 then
begin
Result := True;
pS^ := 32767;
end
else if outval < -32767 then
begin
Result := True;
pS^ := -32767;
end
else
pS^ := outval;
inc(pS,Channels);
end;
end;
{$ELSE}
const
ParmSize = sizeOf(TFilterParams);
asm
// EAX = pflt
// EDX = pOut
// ECX = channel
push ebx
push edi
push esi
push ebp
imul ecx, ParmSize/8
lea esi, TFFTFilter(eax).Params+8*ecx
mov ebx, TFFTFilter(eax).Channels
shl ebx, 1
mov ebp, TFFTFilter(eax).FFTLen
xor eax, eax
xor ecx, ecx
@@loop:
{--- 1. sample ---}
mov edi, dword ptr TFilterParams(esi).Out_Buf[4*ecx]
cmp edi, 32767
jle @@skip1
mov di, 32767
mov eax, True
jmp @@set1
@@skip1:
cmp edi, -32768
jge @@set1
mov di, -32768
mov eax, True
@@set1:
mov word ptr [edx], di
add edx, ebx
{--- 2. sample ---}
mov edi, dword ptr TFilterParams(esi).Out_Buf[4*ecx+4]
cmp edi, 32767
jle @@skip2
mov di, 32767
mov eax, True
jmp @@set2
@@skip2:
cmp edi, -32768
jge @@set2
mov di, -32768
mov eax, True
@@set2:
mov word ptr [edx], di
add edx, ebx
{--- 3. sample ---}
mov edi, dword ptr TFilterParams(esi).Out_Buf[4*ecx+8]
cmp edi, 32767
jle @@skip3
mov di, 32767
mov eax, True
jmp @@set3
@@skip3:
cmp edi, -32768
jge @@set3
mov di, -32768
mov eax, True
@@set3:
mov word ptr [edx], di
add edx, ebx
{--- 4. sample ---}
mov edi, dword ptr TFilterParams(esi).Out_Buf[4*ecx+12]
cmp edi, 32767
jle @@skip4
mov di, 32767
mov eax, True
jmp @@set4
@@skip4:
cmp edi, -32768
jge @@set4
mov di, -32768
mov eax, True
@@set4:
mov word ptr [edx], di
add edx, ebx
add ecx, 4
cmp ecx, ebp
jl @@loop
pop ebp
pop esi
pop edi
pop ebx
{$ENDIF}
end;
var
p: PFFTFilter;
{== FFT Filter ================================================================}
function DoFFTFilter(pflt: PFFTFilter; Channel: TMMChannel; pIn: PChar; Len: Cardinal): Boolean;
var
i,ch,KOL,Count,chMin,chMax,BytesDone,nBytes: integer;
pW,pS: PSmallArray;
begin
Result := False;
if (pflt <> nil) then
with pflt^ do
begin
p := pflt;
GlobalMoveMem(pIn^,(BufIn+BufIn_Bytes)^,Len);
inc(BufIn_Bytes,Len);
KOL := BufIn_Bytes div (Channels*sizeOf(Smallint)) div FFTlen;
chMax := Channels;
if (Channel = chLeft) then chMax := 1;
chMin := 0;
if (Channels = 2) and (Channel = chRight) then chMin := 1;
for ch := chMin to chMax-1 do
with Params[ch] do
begin
Count := 0;
while (Count < KOL) do
begin
pW := @PSmallArray(BufIn)^[FFTLen*Count*Channels+ch];
{-- get signal -------------------------------------------------}
GetSignal(pflt,PSmallint(pW),@Out_Buf);
{-- filter ---}
FFT_Filter(pflt,@Out_Buf,@Out_Buf,ch);
pW := @PSmallArray(PChar(BufOut+BufOut_Bytes))^[FFTLen*Count*Channels+ch];
{-- formirov vixod signala -------------------------------------}
if ClipOutput(pflt,pW,ch) then Result := True;
inc(count);
end;
end;
// TODO: Alles nochmal pr黤en
BytesDone := KOL * (Channels*sizeOf(Smallint)) * FFTlen;
if (BytesDone > 0) then
begin
inc(BufOut_Bytes,BytesDone);
dec(BufIn_Bytes,BytesDone);
GlobalMoveMem((BufIn+BytesDone)^,BufIn^,BufIn_Bytes);
end;
nBytes := Min(Len,BufOut_Bytes);
GlobalFillMem(pIn^,Len-nBytes,0);
if (Channels = 2) and (Channel <> chBoth) then
begin
pS := Pointer(BufOut+(Len-nBytes)+2*chMin);
pW := Pointer(pIn+(Len-nBytes)+2*chMin);
i := 0;
while i < nBytes div 2 do
begin
pW^[i] := pS^[i];
inc(i,2);
end;
end
else GlobalMoveMem((BufOut+(Len-nBytes))^,(pIn+(Len-nBytes))^,nBytes);
dec(BufOut_Bytes,nBytes);
GlobalMoveMem((BufOut+nBytes)^,BufOut^,BufOut_Bytes);
end;
end;
initialization
Allocator := TMMAllocator.Create;
finalization
Allocator.Free;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -