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

📄 mmfftflt.pas

📁 一套及时通讯的原码
💻 PAS
📖 第 1 页 / 共 2 页
字号:
{========================================================================}
{=                (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: 20.01.1998 - 18:00:00 $                                      =}
{========================================================================}
unit MMFFTFlt;

{$I COMPILER.INC}

interface

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

{========================================================================}
const
     { constants for the DataType fields }
     DT_8BIT   = $00;  { x0 b }
     DT_16BIT  = $01;  { x1 b }
     DT_MONO   = $00;  { 0x b }
     DT_STEREO = $02;  { 1x b }

     { constants for channels }
     CH_BOTH   = $00;
     CH_LEFT   = $01;
     CH_RIGHT  = $02;

function GetDataType(pwfx: PWaveFormatEx): integer;

{========================================================================}
const
    {$IFDEF CBUILDER3} {$EXTERNALSYM DESM} {$ENDIF}
    DESM           = 8;

    {$IFDEF CBUILDER3} {$EXTERNALSYM MAX_FFTLEN} {$ENDIF}
    MAX_FFTLEN     = 1024;         { Define the maximum FFT buffer length.}
    {$IFDEF CBUILDER3} {$EXTERNALSYM MAX_CHANNELS} {$ENDIF}
    MAX_CHANNELS   = 2;

type
    PFFTCplxArray  = ^TFFTCplxArray;
    TFFTCplxArray  = array[0..MAX_FFTLEN+1] of TfCplx;

    TFFTLongArray  = array[0..MAX_FFTLEN+1] of Longint;
    TFFTFloatArray = array[0..MAX_FFTLEN+1] of Float;

    {-- TFilterParams ---------------------------------------------------------}
    PFilterParams  = ^TFilterParams;
    TFilterParams  = packed record
       Out_Buf     : TFFTLongArray;
       old_r       : TFFTFloatArray;
    end;

    {-- TFFTFilter ------------------------------------------------------------}
    PFFTFilter      = ^TFFTFilter;
    TFFTFilter      = packed record
       DataType     : integer;            { DT_8BIT,DT_16BIT,DT_MONO,DT_STEREO  }
       SampleRate   : Longint;            { SampleRate for the samples          }
       Channels     : integer;            { number of Channels                  }

       FFTLen       : integer;
       FFTLen_2     : integer;            { actual FFTlength                    }
       Order        : integer;

       pfft         : PFFTCplx;           { instance for FFT calculation        }

       BufIn        : PChar;
       BufIn_Bytes  : Longint;

       BufOut       : PChar;
       BufOut_Bytes : Longint;

       MaxBufferSize: Longint;

       WindowFunc   : Longint;

       Params       : array[0..MAX_CHANNELS-1] of TFilterParams;

       {-- var for FFT ------------}
       ampl         : TFFTFloatArray;
       fh           : TFFTCplxArray;
       fx           : TFFTCplxArray;

       DataSection  : TRtlCriticalSection;
    end;

function  InitFFTFilter(pwfx: PWaveFormatEx; FFTLength, MaxBufSize: integer): PFFTFilter;
procedure DoneFFTFilter(var pflt: PFFTFilter);
procedure SetFFTFilterWindow(pflt: PFFTFilter; Window: integer);
procedure SetFFTFilterBand(pflt: PFFTFilter; f1, f2, Gain: Float);
procedure ResetFFTFilter(pflt: PFFTFilter);
function  DoFFTFilter(pflt: PFFTFilter; Channel: TMMChannel; pIn: PChar; Len: Cardinal): Boolean;

implementation

uses
    MMAlloc;

var
   Allocator: TMMAllocator;

{==============================================================================}
function GetDataType(pwfx: PWaveFormatEx): Integer;
begin
   Result := -1;
   if (pwfx <> Nil) and (pwfx^.wFormatTag = WAVE_FORMAT_PCM) then
   begin
      Result := 0;
      if (pwfx^.wBitsPerSample = 16) then Result := Result or DT_16BIT;
      if (pwfx^.nChannels = 2) then Result := Result or DT_STEREO;
   end;
end;

{==============================================================================}
{ -- FFT Filter --                                                             }
{==============================================================================}
function InitFFTFilter(pwfx: PWaveFormatEx; FFTLength,MaxBufSize: integer): PFFTFilter;
begin
   Result := Allocator.AllocBufferEx(GHND,SizeOf(TFFTFilter));
   if (Result <> nil) then
   with Result^ do
   begin
      DataType   := GetDataType(pwfx);
      SampleRate := pwfx^.nSamplesPerSec;
      Channels   := pwfx^.nChannels;
      FFTLength  := Min(FFTLength, MAX_FFTLEN);
      FFTLen     := 1;
      { Convert FFTLen to a power of 2 }
      Order := 0;
      while FFTLength > 1 do
      begin
         FFTLength := FFTLength shr 1;
         inc(Order);
      end;
      if (Order > 0) then FFTLen := FFTLen shl Order;
      FFTLen_2 := FFTlen div 2;

      WindowFunc := 1;

      pfft   := InitCplxFFT(Order);

      MaxBufferSize := MaxBufSize;

      BufIn  := Allocator.AllocBufferEx(GHND,2*MaxBufSize*sizeOf(Byte));
      BufOut := Allocator.AllocBufferEx(GHND,2*MaxBufSize*sizeOf(Byte));

      FillChar(DataSection, SizeOf(DataSection), 0);
      InitializeCriticalSection(DataSection);

      ResetFFTFilter(Result);
      SetFFTFilterBand(Result,0,SampleRate div 2,0);
   end;
end;

{==============================================================================}
procedure DoneFFTFilter(var pflt: PFFTFilter);
begin
   if (pflt <> nil) then
   begin
      DeleteCriticalSection(pflt^.DataSection);
      DoneCplxFFT(pflt^.pfft);
      Allocator.FreeBuffer(Pointer(pflt.BufIn));
      Allocator.FreeBuffer(Pointer(pflt.BufOut));
      Allocator.FreeBuffer(Pointer(pflt));
   end;
end;

{==============================================================================}
procedure re_im_Init(pflt: PFFTFilter; amp: PFloatArray);
var
   i: integer;
   ampl_1: TFFTFloatArray;

begin
   with pflt^ do
   begin
      for i := 0 to FFTLen_2 do
      begin
         ampl_1[i] := amp[i];
         ampl_1[FFTLen_2+1+i] := 0
      end;

      ampl_1[0] := ampl_1[0] * 0.5;
      ampl_1[FFTLen_2] := ampl_1[FFTLen_2] * 0.5;

      for i := 0 to FFTLen_2 do
      begin
         fx[i].re := ampl_1[i]*cos(2*M_PI*i/4.0);
         fx[i].im := ampl_1[i]*sin(2*M_PI*i/4.0);
         fx[FFTLen_2+1+i].re := 0;
         fx[FFTLen_2+1+i].im := 0;
      end;

      DoCplxFFTb(pfft,@fx,1);

      {-- OTOBRASENIE 1 -------------------------------------------------}
      for i := 0 to FFTLen-1 do
      begin
         ampl_1[i] := fx[i].re*CalcWindowFunc(WindowFunc, i, FFTLen_2);

         fx[i].re := 0;
         fx[i].im := 0;
      end;

      for i := 0 to FFTlen_2 do fx[i].re := ampl_1[i];

      doCplxFFTb(pfft,@fx,-2);
   end;
end;

{==== INIT IMP-REACTION =======================================================}
procedure InitImp(pflt: PFFTFilter; dx,dy: integer; Gain: Float);
var
   i: integer;

begin
   with pflt^ do
   begin
      EnterCriticalSection(DataSection);
      try
         for i := dx to dy do
         begin
            ampl[i] := pow(10.0,(Gain+6)/20.0);
         end;

         re_im_Init(pflt,@ampl);

         for i := 0 to FFTLen-1 do
         begin
            {-- No Normalization ---}
            fh[i].re := fx[i].re;
            fh[i].im := fx[i].im;
         end;

      finally
         LeaveCriticalSection(DataSection);
      end;
   end;
end;

{== SetFFTFilter ==============================================================}
procedure SetFFTFilterWindow(pflt: PFFTFilter; Window: integer);
var
   i: integer;

begin
   with pflt^ do
   begin
      EnterCriticalSection(DataSection);
      try
         WindowFunc := Window;

         re_im_Init(pflt,@ampl);

         for i := 0 to FFTLen-1 do
         begin
            {-- No Normalization ---}
            fh[i].re := fx[i].re;
            fh[i].im := fx[i].im;
         end;

      finally
         LeaveCriticalSection(DataSection);
      end;
   end;
end;

{== SetFFTFilter ==============================================================}
procedure SetFFTFilterBand(pflt: PFFTFilter; f1,f2,Gain: Float);
var
   dx,dy: integer;
   f,fshag: FLoat;

begin
   with pflt^ do
   begin
      if f1 >= SampleRate div 2 then f1 := SampleRate div 2-1;
      if f2 > SampleRate div 2 then f2 := SampleRate div 2;

      if f1 > f2 then
      begin
         f := f1;
         f1 := f2;
         f2 := f;
      end;
      if (f2 = f1) then f2 := f2+1;

      fshag:= SampleRate/FFTLen;

      dx := Trunc(f1/fshag);
      dy := Trunc(f2/fshag);
      InitImp(pflt,dx,dy,Gain);
   end;
end;

{== ResetFFTFilter ============================================================}
procedure ResetFFTFilter(pflt: PFFTFilter);
var
   i: integer;
begin
   with pflt^ do
   begin
      BufIn_Bytes := 0;
      BufOut_Bytes:= 0;

      for i := 0 to Channels-1 do
      with Params[i] do
      begin
         FillChar(Out_Buf, sizeOf(Out_Buf),0);
         FillChar(Old_r, sizeOf(Old_r),0);
      end;
   end;
end;

{== FFT Filter ================================================================}
procedure FFT_Filter(pflt: PFFTFilter; pIn, pOut: PLongArray; channel: integer);
var
   i: integer;

begin

⌨️ 快捷键说明

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