📄 fft.asm
字号:
;---------------------------------------------------------------------
;Fast Fourier Transform(FFT) source code by Pradeeapn--arulpragasam@yahoo.com
;This code calculates both left & right 16 bit audio samples simultaneously using 3dnow! code.
;This code requires processor with 3dnow! support.
;If you found any bugs please email it to me (arulpragasam@yahoo.com).
;
; Usage-
; First call the InitFFT proc:
; invoke InitFFT,FFTSize,pointer to hold RealArray offset,pointer to hold ImaginaryArray offset
; FFTSize have to be power of 2 (256,512,1024...)
; Also give 2 pointers to hold the offsets.
;
;
; To calculate the FFT Call the FFT proc:
; invoke FFT,sample offset,Real offset,Imaginary offset.
; samples have to be 16 bit Stereo.
;
; To calculate the Inverse FFT Call the IFFT proc:
; invoke IFFT,sample offset,Real offset,Imaginary offset.
;---------------------------------------------------------------------
;---------------------------------------------------------------------
include math.asm
InitFFT Proto :Dword,:Dword,:Dword,:Dword,:Dword
FFT Proto :Dword,:Dword,:Dword
IFFT Proto :Dword,:Dword,:Dword
.DATA
Align 8
log2 DD 1.44269504,1.44269504 ;1/log(2)
Pi DD 3.14159265,3.14159265
e1_20 DD 1.e-20
;---------------------------------------------------------------------
.DATA?
Align 8
tmp1 DD ?
nmFFTspl DD ?
lgFFTm DD ?
.CODE
LdFFT Proc REX:Dword,IMX:Dword ;routine for Inverse FFT
Local SR:Qword
Local SI1:Qword
Local NM1,ND2,M,L,LE1,LE2:Dword
Local ND4,N4s2,LE22,NM11:Dword
mov ecx,nmFFTspl
mov eax,ecx
mov ebx,ecx
sub ebx,2
mov esi,lgFFTm
shl ebx,3
mov N4s2,ebx
dec eax
mov M,esi
shl eax,3
mov NM1,eax
shr ecx,1
mov ND2,ecx
shl ecx,3
mov ND4,ecx
mov esi,ecx
mov edx,8
mov edi,REX
mov ebx,IMX
mov ecx,ND4
@fl1: cmp edx,esi
jb @f
movq MM3,[edi+edx]
movq MM0,[edi+esi]
movq [edi+esi],MM3
movq MM1,[ebx+esi]
movq [edi+edx],MM0
movq MM2,[ebx+edx]
movq [ebx+edx],MM1
movq [ebx+esi],MM2
@@: mov eax,ecx
add edx,8
@@: .If eax<=esi
sub esi,eax
shr eax,1
jmp @b
.EndIf
add esi,eax
cmp edx,N4s2
jbe @fl1
mov L,1
@fl2: mov ecx,L
mov eax,1
shl eax,cl
mov LE1,eax
shr eax,1
movd MM2,eax
shl eax,3
pi2fd MM2,MM2
mov edx,eax
movd MM0,Pi
mov LE2,edx
pfrcp MM7,MM2
sub edx,8
punpckldq MM2,MM2
mov LE22,edx
pfrcpit1 MM2,MM7
add eax,eax
pfrcpit2 MM2,MM7
mov LE1,eax
pfmul MM0,MM2
call cos
movq MM2,MM0
punpckldq MM0,MM0
punpckhdq MM2,MM2
movq SR,MM0
movq MM6,ones
pxor MM2,sh_masks
pxor MM7,MM7
mov ebx,IMX
movq SI1,MM2
Align 4
mov ecx,0
@fl3: mov esi,ecx
@fl4: mov eax,esi
add eax,LE2
movq MM0,[ebx+eax]
movq MM2,MM0
movq MM1,[edi+eax]
pfmul MM0,MM7
movq MM3,MM1
pfmul MM1,MM6
movq MM4,[edi+esi]
pfmul MM2,MM6
pfsub MM1,MM0
movq MM5,[ebx+esi]
pfmul MM3,MM7
pfadd MM3,MM2
movq MM0,MM4
pfsub MM4,MM1
pfadd MM0,MM1
movq [edi+eax],MM4
movq MM4,MM5
movq [edi+esi],MM0
pfsub MM5,MM3
movq [ebx+eax],MM5
pfadd MM4,MM3
movq [ebx+esi],MM4
add esi,LE1
cmp esi,NM1
jbe @fl4
movq MM0,MM6
movq MM4,SR
movq MM2,MM6
pfmul MM0,MM4
movq MM1,MM7
movq MM5,SI1
movq MM3,MM7
pfmul MM1,MM5
pfsub MM0,MM1
pfmul MM2,MM5
movq MM6,MM0
pfmul MM3,MM4
pfadd MM2,MM3
add ecx,8
movq MM7,MM2
cmp ecx,LE22
jbe @fl3
inc L
mov eax,M
cmp L,eax
jbe @fl2
ret
LdFFT EndP
LdFFT2 Proc REX:Dword,IMX:Dword ;routine for forward FFT
Local SR:Qword
Local SI1:Qword
Local NM1,ND2,M,L,LE1,LE2:Dword
Local ND4,N4s2,LE22,NM11:Dword
mov ecx,nmFFTspl
mov eax,ecx
mov ebx,ecx
sub ebx,2
mov esi,lgFFTm
shl ebx,3
mov N4s2,ebx
dec eax
mov M,esi
shl eax,3
mov NM1,eax
shr ecx,1
mov ND2,ecx
shl ecx,3
mov ND4,ecx
mov esi,ecx
mov edx,8
mov edi,REX
mov ebx,IMX
mov ecx,ND4
@fl1: cmp edx,esi
jb @f
movq MM3,[edi+edx]
movq MM0,[edi+esi]
movq [edi+esi],MM3
movq [edi+edx],MM0
@@: mov eax,ecx
add edx,8
@@: .If eax<=esi
sub esi,eax
shr eax,1
jmp @b
.EndIf
add esi,eax
cmp edx,N4s2
jbe @fl1
mov L,1
@fl2: mov ecx,L
mov eax,1
shl eax,cl
mov LE1,eax
shr eax,1
movd MM2,eax
shl eax,3
pi2fd MM2,MM2
mov edx,eax
movd MM0,Pi
mov LE2,edx
pfrcp MM7,MM2
sub edx,8
punpckldq MM2,MM2
mov LE22,edx
pfrcpit1 MM2,MM7
add eax,eax
pfrcpit2 MM2,MM7
mov LE1,eax
pfmul MM0,MM2
call cos
movq MM2,MM0
punpckldq MM0,MM0
punpckhdq MM2,MM2
movq SR,MM0
movq MM6,ones
pxor MM2,sh_masks
pxor MM7,MM7
mov ebx,IMX
movq SI1,MM2
Align 4
mov ecx,0
@fl3: mov esi,ecx
@fl4: mov eax,esi
add eax,LE2
movq MM0,[ebx+eax]
movq MM2,MM0
movq MM1,[edi+eax]
pfmul MM0,MM7
movq MM3,MM1
pfmul MM1,MM6
movq MM4,[edi+esi]
pfmul MM2,MM6
pfsub MM1,MM0
movq MM5,[ebx+esi]
pfmul MM3,MM7
pfadd MM3,MM2
movq MM0,MM4
pfsub MM4,MM1
pfadd MM0,MM1
movq [edi+eax],MM4
movq MM4,MM5
movq [edi+esi],MM0
pfsub MM5,MM3
movq [ebx+eax],MM5
pfadd MM4,MM3
movq [ebx+esi],MM4
add esi,LE1
cmp esi,NM1
jbe @fl4
movq MM0,MM6
movq MM4,SR
movq MM2,MM6
pfmul MM0,MM4
movq MM1,MM7
movq MM5,SI1
movq MM3,MM7
pfmul MM1,MM5
pfsub MM0,MM1
pfmul MM2,MM5
movq MM6,MM0
pfmul MM3,MM4
pfadd MM2,MM3
add ecx,8
movq MM7,MM2
cmp ecx,LE22
jbe @fl3
inc L
mov eax,M
cmp L,eax
jbe @fl2
ret
LdFFT2 EndP
;---------------------------------------------------------------------
ldIFFT Proc REX:Dword,IMX:Dword
Local K,I:Dword
mov edi,REX
mov ebx,IMX
mov ecx,nmFFTspl
@ifl1: movq MM0,[ebx]
pxor MM0,sh_masks
movq [ebx],MM0
add ebx,8
loop @ifl1
Invoke LdFFT,REX,IMX
mov edi,REX
mov ebx,IMX
movd MM2,nmFFTspl
pi2fd MM2,MM2
pfrcp MM1,MM2
punpckldq MM2,MM2
pfrcpit1 MM2,MM1
pfrcpit2 MM2,MM1
mov ecx,nmFFTspl
@ifl2: movq MM0,[edi]
pfmul MM0,MM2
movq MM3,[ebx]
movq [edi],MM0
pfmul MM3,MM2
add edi,8
pxor MM3,sh_masks
movq [ebx],MM3
add ebx,8
loop @ifl2
ret
ldIFFT EndP
;---------------------------------------------------------------------
;Converts Rectangular FFT to Polar FFT
;usage: Invoke pointer to R[X],pointer to I[X]
;----------------------------------------------------------------------
RectToPol Proc REX:Dword,IMX:Dword,Mgmem:Dword,PhMem:Dword
Local K:Dword
mov edi,REX
mov ebx,IMX
mov eax,Mgmem
mov edx,PhMem
mov K,0
@RtP1: mov esi,K
movd MM0,[edi+esi*4]
movq MM3,MM0
pfmul MM0,MM0
movd MM1,[ebx+esi*4]
movq MM4,MM1
pfmul MM1,MM1
pfadd MM0,MM1
pfrsqrt MM1,MM0
movq MM2,MM1
pfmul MM1,MM1
punpckldq MM0,MM0
pfrsqit1 MM1,MM0
pfrcpit2 MM1,MM2
pfmul MM0,MM1
movd [eax+esi*4],MM0
movd ecx,MM0
.If ecx==0
mov ecx,e1_20
mov [eax+esi*4],ecx
.EndIf
pfrcp MM5,MM3
punpckldq MM3,MM3
pfrcpit1 MM3,MM5
pfrcpit2 MM3,MM5
pfmul MM4,MM3
movq MM0,MM4
call atan
movd [edx+esi*4],MM0
movd MM4,[edi+esi*4]
movd MM5,[ebx+esi*4]
pxor MM2,MM2
pxor MM3,MM3
pfcmpgt MM2,MM4
pfcmpgt MM3,MM5
movd ecx,MM2
push eax
movd eax,MM3
.If ecx!=0
.If eax!=0
pfsub MM0,Qword Ptr[Pi]
.Else
pfadd MM0,Qword Ptr[Pi]
.EndIf
movd [edx+esi*4],MM0
.EndIf
pop eax
inc K
mov ecx,nmFFTspl
;shr ecx,1
cmp K,ecx
jbe @RtP1
ret
RectToPol EndP
;-------------------------------------------------------------------------
;-------------------------------------------------------------------------
;Usage: invoke FFT,offset sample data,offset RealArray,offset Imaginary Array
; sample data have to be at least 4 times the FTTsize
; samples have to be 16 bit stereo.
;--------------------------------------------------------------------------
;--------------------------------------------------------------------------
FFT Proc pSamp:Dword,REX:Dword,IMX:Dword
mov eax,IMX
pxor MM7,MM7
mov ecx,nmFFTspl
xor esi,esi
mov ebx,REX
mov edi,pSamp
@@: movq MM0,[edi]
movq [eax],MM7 ;initialize the Immaginary part to 0
punpcklwd MM0,MM0
;mov [edi],esi ;clear the original sample - normaly not nessary
pi2fw MM0,MM0 ;convert 16bit stereo samples into 32bit float
add eax,8
movq [ebx],MM0 ;copy the 32bit packed(Left,Right) float samples to Real part
add edi,4
add ebx,8
dec ecx
jnz @b
Invoke LdFFT2,REX,IMX
ret
FFT EndP
;--------------------------------------------------------------------------
;Usage: invoke IFFT,offset sample data,offset RealArray,offset Imaginary Array
; sample data have to atleast 4 times the FTTsize
; samples have to be 16 bit stereo.
;--------------------------------------------------------------------------
IFFT Proc pSamp:Dword,REX:Dword,IMX:Dword
Invoke ldIFFT,REX,IMX
mov ecx,nmFFTspl
mov ebx,REX
mov edi,pSamp
@@: movq MM0,[ebx]
pf2id MM0,MM0
packssdw MM0,MM0
movd [edi],MM0
add ebx,8
add edi,4
loop @b
ret
IFFT EndP
;---------------------------------------------------------------------------------;
@Mem Macro NoBytes:req
Invoke GetProcessHeap
mov HeapHnd,eax
Invoke HeapAlloc,HeapHnd,HEAP_ZERO_MEMORY,NoBytes
EXITM <eax>
EndM
;--------------------------------------------------------------------------
;Usage: invoke InitFFT,FFTsize,pointer to hold RealArray offset,pointer to hold ImaginaryArray offset
; FFTsize have to be power of 2(128,256,512...)
;--------------------------------------------------------------------------
InitFFT Proc FFTsize:Dword,REX:Dword,IMX:Dword,MAG:Dword,PHS:Dword
pusha
mov esi,FFTsize
mov nmFFTspl,esi
movd MM0,esi
pi2fd MM0,MM0
call log
pfmul MM0,Qword Ptr[log2]
pf2id MM0,MM0
movd lgFFTm,MM0
shl esi,3
mov edi,REX
mov [edi],@Mem(esi)
mov edi,IMX
mov [edi],@Mem(esi)
mov edi,MAG
mov [edi],@Mem(esi)
mov edi,PHS
mov [edi],@Mem(esi)
popa
ret
InitFFT EndP
;--------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -