⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mmfft.pas

📁 一套及时通讯的原码
💻 PAS
📖 第 1 页 / 共 2 页
字号:
{========================================================================}
{=                (c) 1995-98 SwiftSoft Ronald Dittrich                 =}
{========================================================================}
{=                          All Rights Reserved                         =}
{========================================================================}
{=  D 01099 Dresden             = Fax.: +49 (0)351-8037944              =}
{=  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: 13.04.98 - 20:21:43 $                                        =}
{========================================================================}
unit MMFFT;

{$I COMPILER.INC}

interface

uses
{$IFDEF WIN32}
    Windows,
{$ELSE}
    WinTypes,
    WinProcs,
{$ENDIF}
    SysUtils,
    MMUtils,
    MMMath,
    MMAbout;

{$IFDEF WIN32}
type
   PfCplx = ^TfCplx;
   TfCplx = record
      re: FLoat;
      im: Float;
   end;

   PfCplxArray = ^TfCplxArray;
   TfCplxArray = array[0..0] of TfCplx;

   PFFTCplx    = ^TFFTCplx;
   TFFTCplx    = record
      Order      : integer;
      FFTLen     : integer;
      Scale      : Float;
      BitRevTable: PIntArray;
      SinTable   : PfCplxArray;
   end;

   PFFTReal    = ^TFFTReal;
   TFFTReal    = record
      Order      : integer;
      FFTLen     : integer;
      Scale      : Float;
      BitRevTable: PIntArray;
      SinTable1  : PfCplxArray;
      SinTable2  : PfCplxArray;
   end;

var
   fvecMul1       : procedure(Vec: PFloatArray; val: Float; n: integer); {$IFDEF WIN32}pascal;{$ENDIF}
   fvecMul2       : procedure(SrcVec,DstVec: PfCplxArray; n: integer); {$IFDEF WIN32}pascal;{$ENDIF}
   fvecZero1      : procedure(Vec: PFloatArray; n: integer); {$IFDEF WIN32}pascal;{$ENDIF}
   fvecZero2      : procedure(Vec: PfCplxArray; n: integer); {$IFDEF WIN32}pascal;{$ENDIF}
   fvecBitRev1    : procedure(Vec: PFloatArray; BitRevTable: PIntArray; Order: integer); {$IFDEF WIN32}pascal;{$ENDIF}
   fvecBitRev2    : procedure(Vec: PfCplxArray; BitRevTable: PIntArray; Order: integer); {$IFDEF WIN32}pascal;{$ENDIF}
   GenSinTable1   : procedure(SinTable: PfCplxArray; Order: integer); {$IFDEF WIN32}pascal;{$ENDIF}
   GenSinTable2   : procedure(SinTable: PfCplxArray; Order: integer); {$IFDEF WIN32}pascal;{$ENDIF}
   DoCplxFFT1     : procedure(re, im: PFloatArray; scTable: PfCplxArray; FFTLen, sign: integer); {$IFDEF WIN32}pascal;{$ENDIF}
   DoCplxFFT2     : procedure(samps, scTable: PfCplxArray; FFTLen, sign: integer); {$IFDEF WIN32}pascal;{$ENDIF}
   BuildRealOutput: procedure(samps, SinTable: PfCplxArray; N,Sign: integer); {$IFDEF WIN32}pascal;{$ENDIF}

function  InitCplxFFT(iOrder: integer): PFFTCplx;
procedure DoneCplxFFT(var pfft: PFFTCplx);
procedure DoCplxFFTa(pfft: PFFTCplx; re, im: PFLoatArray; Sign: integer);
procedure DoCplxFFTb(pfft: PFFTCplx; samps: PfCplxArray; Sign: integer);

function  InitRealFFT(iOrder: integer): PFFTReal;
procedure DoneRealFFT(var pfft: PFFTReal);
procedure DoRealFFT(pfft: PFFTReal; Samps: PFloatArray; Sign: integer);
{$ENDIF}

function  CalcWindowFunc(Window, idx, Len: integer): Float;
procedure GenWindowTableInt(pTable: PIntArray; Window, Order: integer);
procedure GenWindowTableFloat(pTable: PFloatArray; Window, Order: integer);
procedure CalcWindowInt(Samps: PIntArray; Window,Order: integer);
procedure CalcWindowFloat(Samps: PFloatArray; Window,Order: integer);
procedure GenBitRevTable(pTable: PIntArray; Order: integer);

{$IFNDEF WIN32}

type
    {-- TMMFFT -----------------------------------------------------------}
    TMMFFT = class(TObject)
    private
      FPoints     : integer;
      FSinTable   : PSmallArray;
      FBitReversed: PIntArray;

      procedure SetFFTLen(FFTLen: integer);
      procedure InitFFT(FFTLen: integer);
      procedure DoneFFT;

    protected
      constructor Create; virtual;
      destructor  Destroy; override;
    public
      procedure CalcFFT(Buffer: PSmallInt);

      property  FFTLength: integer read FPoints write SetFFTLen default 128;
      property  BitReversed: PIntArray read FBitReversed;
      property  SinTable: PSmallArray read FSinTable;
    end;
{$ENDIF}

implementation

{$IFDEF WIN32}

{$IFNDEF USEDLL}
{$L MMFFT32.OBJ}
{$F+}
procedure _fvecMul1(Vec: PFloatArray; val: Float; n: integer); pascal; external;
procedure _fvecMul2(SrcVec,DstVec: PfCplxArray; n: integer); pascal; external;

procedure _fvecZero1(Vec: PFloatArray; n: integer); pascal; external;
procedure _fvecZero2(Vec: PfCplxArray; n: integer); pascal; external;

procedure _fvecBitRev1(Vec: PFloatArray; BitRevTable: PIntArray; Order: integer); pascal; external;
procedure _fvecBitRev2(Vec: PfCplxArray; BitRevTable: PIntArray; Order: integer); pascal; external;

procedure _GenSinTable1(SinTable: PfCplxArray; Order: integer); pascal; external;
procedure _GenSinTable2(SinTable: PfCplxArray; Order: integer); pascal; external;

procedure _DoCplxFFT1(re, im: PFloatArray; scTable: PfCplxArray; FFTLen, sign: integer); pascal; external;
procedure _DoCplxFFT2(samps, scTable: PfCplxArray; FFTLen, sign: integer); pascal; external;

procedure _BuildRealOutput(samps, SinTable: PfCplxArray; N,Sign: integer); pascal; external;
{$F-}
{$ENDIF}
{$ENDIF}

{------------------------------------------------------------------------------}
function CalcWindowFunc(Window, idx, Len: integer): Float;
const
   alpha = 5.0;   { Gaussian window parameter }
begin
   { Calculate Windowing function }
   case Window of
          { Hamming }
       1: Result := 0.54-0.46*cos(2*M_PI*idx/Len);
          { Hanning }
       2: Result := 0.5 - 0.5*cos(2*M_PI*idx/Len);
          { Blackman }
       3: Result := 0.42-0.5*cos(2*M_PI*idx/Len)+0.08*cos(4*M_PI*idx/Len);
	    { Gaussian }
       4: Result := exp(-alpha/(Len*Len)*(2*idx-Len)*(2*idx-Len));
            { Welch }
       5: Result := 1 - ((2*idx-Len)/(Len+1))*((2*idx-Len)/(Len+1));
            { Parzen }
       6: Result := 1 - abs((2*idx-Len)/(Len+1));
            { Rectangular }
     else Result := 1;
   end;
end;

{------------------------------------------------------------------------------}
procedure GenWindowTableInt(pTable: PIntArray; Window, Order: integer);
var
   i: integer;
   Len: integer;

begin
   Len := 1 shl Order;
   { Calculate Windowing function }
   for i := 0 to Len-1 do
   begin
      pTable^[i] := Floor(CalcWindowFunc(Window,i,Len)*32767+0.5);
   end;
end;

{------------------------------------------------------------------------------}
procedure GenWindowTableFloat(pTable: PFloatArray; Window, Order: integer);
var
   i: integer;
   Len: integer;

begin
   Len := 1 shl Order;
   { Calculate Windowing function }
   for i := 0 to Len-1 do
   begin
      pTable^[i] := CalcWindowFunc(Window,i,Len);
   end;
end;

{------------------------------------------------------------------------------}
procedure CalcWindowInt(Samps: PIntArray; Window, Order: integer);
var
   i: integer;
   Len: integer;

begin
   Len := 1 shl Order;
   for i := 0 to Len-1 do
   begin
      Samps^[i] := Trunc(Samps^[i]*CalcWindowFunc(Window,i,Len));
   end;
end;

{------------------------------------------------------------------------------}
procedure CalcWindowFloat(Samps: PFloatArray; Window, Order: integer);
var
   i: integer;
   Len: integer;

begin
   Len := 1 shl Order;
   for i := 0 to Len-1 do
   begin
      Samps^[i] := Samps^[i]*CalcWindowFunc(Window,i,Len);
   end;
end;

{------------------------------------------------------------------------------}
procedure GenBitRevTable(pTable: PIntArray; Order: integer);
var
   i, temp, mask: integer;
   Len: integer;

begin
   Len := 1 shl Order;

   for i := 0 to Len-1 do
   begin
      temp := 0;
      mask := Len div 2;
      while mask > 0 do
      begin
         temp := temp shr 1;
         if (i and mask > 0) then temp := temp + Len div 2;
         mask := mask shr 1;
      end;
      pTable^[i] := temp;
   end;
end;

{$IFDEF WIN32}
{------------------------------------------------------------------------------}
function InitCplxFFT(iOrder: integer): PFFTCplx;
begin
   Result := nil;
   if (iOrder > 0) and (iOrder <= 31) then
   begin
      Result := GlobalAllocMem(SizeOf(TFFTCplx));
      if (Result <> nil) then
      with Result^ do
      begin
         Order       := iOrder;
         FFTLen      := 1 shl Order;
         Scale       := 1/FFTLen;

         BitRevTable := GlobalAllocMem(FFTlen*sizeOf(Integer));
         GenBitRevTable(BitRevTable,Order);

         SinTable    := GlobalAllocMem((FFTLen div 2)*sizeOf(TfCplx));
         GenSinTable1(SinTable, Order)
      end;
   end;
end;

{------------------------------------------------------------------------------}
procedure DoneCplxFFT(var pfft: PFFTCplx);
begin
   if (pfft <> nil) then
   begin
      GlobalFreeMem(Pointer(pfft^.BitRevTable));
      GlobalFreeMem(Pointer(pfft^.SinTable));
      GlobalFreeMem(Pointer(pfft));
   end;
end;

{------------------------------------------------------------------------------}
procedure DoCplxFFTa(pfft: PFFTCplx; re, im: PFLoatArray; Sign: integer);
begin
   if (pfft <> nil) and (re <> nil) and (im <> nil) then
   with pfft^ do
   begin
      DoCplxFFT1(re,im,sinTable,FFTLen,Sign);

      fvecBitRev1(re,BitRevTable,Order);
      fvecBitRev1(im,BitRevTable,Order);

      if (Sign < 0) then
      begin
	 fvecMul1(re,Scale,FFTLen);
	 fvecMul1(im,Scale,FFTLen);
      end;
   end;
end;

{------------------------------------------------------------------------------}
procedure DoCplxFFTb(pfft: PFFTCplx; samps: PfCplxArray; Sign: integer);
var
   S: integer;
begin
   if (pfft <> nil) and (samps <> nil) then
   with pfft^ do
   begin
      if Sign = -1 then
         S := -1
      else
         S := 1;

      DoCplxFFT2(samps,sinTable,FFTLen,S);

      fvecBitRev2(samps,BitRevTable,Order);

      if (Sign < 0) then
      begin
	 fvecMul1(Pointer(samps),Scale,2*FFTLen);
      end;
   end;
end;

{==============================================================================}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -